JigsawWM is a free and open-source project that aims to increase your productivity by offering a set of automation facilities, including the jmk module as an AHK alternative, a Tiling Window Manager to free you from managing windows manually and the Daemon to support any customization you may have in mind.
Project description
JigsawWM
JigsawWM is a free and open-source productivity toolkit for Windows that brings advanced automation and tiling window management to your desktop.
It combines:
- JMK Module — a programmable keyboard/mouse automation system inspired by QMK and an alternative to AutoHotkey.
- Tiling Window Manager — automatically arranges your windows, freeing you from tedious manual window placement.
- Daemon Framework — enables background services and daily workflow automation, all easily customizable.
🎥 Demo
https://user-images.githubusercontent.com/61080/210168366-e70dd649-f6ef-41bb-a8e5-941e392d770a.mp4
📦 Installation
Tested on:
- Windows 11 (Build 22000)
- Python 3.11.1
Also compatible with:
- Windows 10
- Python 3.8+
Install from PyPI:
pip install jigsawwm
Install from GitHub:
pip install git+https://github.com/klesh/JigsawWM.git
⚡ Quick Start
Step 1: Download and Customize
Download the example config file: example/full.pyw and adjust it to your needs.
🔧 Step 1.1 - Configure General Keybindings (JMK)
JMK is a programmable input automation engine. Here are some useful examples:
1. Tap-Hold Modifier (e.g., CapsLock as Esc on tap, Ctrl on hold):
daemon.jmk.core.register_layers([
{
Vk.CAPITAL: JmkTapHold(tap=Vk.ESCAPE, hold=Vk.LCONTROL),
},
])
💡 Tip: Tap it and hold within quick_tap_term (default: 120ms) to send multiple Esc.
2. Access Keys with Layers (e.g., press T+Z to get F1):
daemon.jmk.core.register_layers([
{ Vk.T: JmkTapHold(tap=Vk.T, hold=3) }, # Layer switch
{}, {}, {},
{ Vk.Z: JmkKey(Vk.F1) }, # Layer 3
])
3. Hotkeys (e.g., Win+Q to close window):
daemon.jmk.hotkeys.register_triggers([
("Win+q", "LAlt+F4"),
([Vk.WIN, Vk.N], minimize_active_window),
])
🪟 Step 1.2 - Configure the Window Manager
JigsawWM follows the suckless philosophy and mimics dwm, organizing windows in a strict order and layout for automatic tiling.
1. Window Navigation & Layouts
daemon.wm.hotkeys = [
([Vk.WIN, Vk.CTRL, Vk.J], daemon.wm.manager.next_window),
([Vk.WIN, Vk.CTRL, Vk.K], daemon.wm.manager.prev_window),
([Vk.WIN, Vk.SHIFT, Vk.J], daemon.wm.manager.swap_next),
([Vk.WIN, Vk.SHIFT, Vk.K], daemon.wm.manager.swap_prev),
("Win+Ctrl+/", daemon.wm.manager.set_master),
("Win+Ctrl+.", daemon.wm.manager.roll_next),
("Win+Ctrl+,", daemon.wm.manager.roll_prev),
([Vk.WIN, Vk.CONTROL, Vk.M], daemon.wm.manager.toggle_mono),
("Win+Shift+Space", daemon.wm.manager.toggle_tilable),
]
2. Workspaces (Per Monitor)
# Switch workspace
("Win+Ctrl+a", partial(daemon.wm.manager.switch_to_workspace, 0)),
("Win+Ctrl+s", partial(daemon.wm.manager.switch_to_workspace, 1)),
# Move window to workspace
("Win+Shift+a", partial(daemon.wm.manager.move_to_workspace, 0)),
("Win+Shift+s", partial(daemon.wm.manager.move_to_workspace, 1)),
3. Multi-Monitor Support
([Vk.WIN, Vk.U], daemon.wm.manager.prev_monitor),
([Vk.WIN, Vk.I], daemon.wm.manager.next_monitor),
([Vk.WIN, Vk.SHIFT, Vk.U], daemon.wm.manager.move_to_prev_monitor),
([Vk.WIN, Vk.SHIFT, Vk.I], daemon.wm.manager.move_to_next_monitor),
4. Window Rules
daemon.wm.manager.config = WmConfig(
rules=[
WmRule(exe="Flow.Launcher.exe", manageable=False),
WmRule(exe="7zFM.exe", tilable=False),
]
)
⚙️ Step 1.3 - Manage Background Services
JigsawWM can manage external processes via tray menu:
daemon.register(
ProcessService(
name="syncthing",
args=["syncthing.exe", "-no-browser", "-no-restart", "-no-upgrade"],
log_path=os.path.join(os.getenv("LOCALAPPDATA"), "syncthing.log"),
)
)
🤖 Step 1.4 - Automate Daily Routines
1. Open your daily folder in a browser once per day:
daemon.register(
DailyWebsites(
browser_name="thorium",
fav_folder="daily",
test_url="https://google.com",
proxy_url="http://localhost:7890",
)
)
2. Auto-launch apps on workdays:
daemon.register(
WorkdayAutoStart(
country_code="CN",
apps=[
r"C:\Users\Klesh\AppData\Local\Feishu\Feishu.exe",
r"C:\Program Files\Betterbird\betterbird.exe",
r"C:\Users\Klesh\AppData\Local\Programs\obsidian\Obsidian.exe",
],
)
)
🚀 Step 2: Launch and Manage
Double-click your .pyw file.
A tray icon will appear — right-click it to manage services.
🔄 Step 3: Launch at Startup
- Press
Win + R→ typeshell:startup→ hit Enter - Add a shortcut to your
.pywscript in the folder
📚 Documentation
Debugging
Inspecting active window information
- Define a hotkey to trigger the Window Inspection. You can refer to the example here: Window Inspection Example.
- Switch the problematic window and hit the hotkey.
- Open the log file located at
C:\Users\<YourUsername>\AppData\Local\jigsawwm\jigsawwm.logand scroll to the bottom. - Locate the relevant lines.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file jigsawwm-3.1.0.tar.gz.
File metadata
- Download URL: jigsawwm-3.1.0.tar.gz
- Upload date:
- Size: 94.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dc589c11fc219e65ad5aa72979f939dfd041edf4cd1581825e8ab140d4f0f055
|
|
| MD5 |
c397bc1be99c4c32e56d7672386175ff
|
|
| BLAKE2b-256 |
6a43e0e2506e4c464f010692b15b9859b6f1fdb7fe35a07f311f0bcf87e0c290
|
Provenance
The following attestation bundles were made for jigsawwm-3.1.0.tar.gz:
Publisher:
pypi.yaml on klesh/JigsawWM
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
jigsawwm-3.1.0.tar.gz -
Subject digest:
dc589c11fc219e65ad5aa72979f939dfd041edf4cd1581825e8ab140d4f0f055 - Sigstore transparency entry: 643452519
- Sigstore integration time:
-
Permalink:
klesh/JigsawWM@0989b2de0d55d11478bdbc92d615df606266880f -
Branch / Tag:
refs/tags/v3.1.0 - Owner: https://github.com/klesh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yaml@0989b2de0d55d11478bdbc92d615df606266880f -
Trigger Event:
push
-
Statement type:
File details
Details for the file jigsawwm-3.1.0-py3-none-any.whl.
File metadata
- Download URL: jigsawwm-3.1.0-py3-none-any.whl
- Upload date:
- Size: 105.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9b66e0339c1ba9b1ab8b891d33b838b510fa72a0af7a9007dcb91a85d14a90ee
|
|
| MD5 |
9e7ec7b7da0ccb044fff1f8312476854
|
|
| BLAKE2b-256 |
0ef622eb0af5255cb8fffe3ee530e1b1d4c1dd729cdb2efae67a54c5edd1b612
|
Provenance
The following attestation bundles were made for jigsawwm-3.1.0-py3-none-any.whl:
Publisher:
pypi.yaml on klesh/JigsawWM
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
jigsawwm-3.1.0-py3-none-any.whl -
Subject digest:
9b66e0339c1ba9b1ab8b891d33b838b510fa72a0af7a9007dcb91a85d14a90ee - Sigstore transparency entry: 643452543
- Sigstore integration time:
-
Permalink:
klesh/JigsawWM@0989b2de0d55d11478bdbc92d615df606266880f -
Branch / Tag:
refs/tags/v3.1.0 - Owner: https://github.com/klesh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yaml@0989b2de0d55d11478bdbc92d615df606266880f -
Trigger Event:
push
-
Statement type: