Skip to main content

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"),
    )
)

Tray


🤖 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

  1. Press Win + R → type shell:startup → hit Enter
  2. Add a shortcut to your .pyw script in the folder

📚 Documentation

👉 Read the Docs

Debugging

Inspecting active window information

  1. Define a hotkey to trigger the Window Inspection. You can refer to the example here: Window Inspection Example.
  2. Switch the problematic window and hit the hotkey.
  3. Open the log file located at C:\Users\<YourUsername>\AppData\Local\jigsawwm\jigsawwm.log and scroll to the bottom.
  4. Locate the relevant lines.

Metadata

Release files for jigsawwm 3.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for jigsawwm 3.1.0
File Size Uploaded
jigsawwm-3.1.0.tar.gz 94.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for jigsawwm 3.1.0
File Interpreter ABI Platform
jigsawwm-3.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 200.1 kB

Release files / jigsawwm-3.1.0.tar.gz

Download URL jigsawwm-3.1.0.tar.gz
Size 94.8 kB
Tags Source
SHA-256 checksum
How to use checksums
dc589c11fc219e65ad5aa72979f939dfd041edf4cd1581825e8ab140d4f0f055
BLAKE2b-256 checksum
How to use checksums
6a43e0e2506e4c464f010692b15b9859b6f1fdb7fe35a07f311f0bcf87e0c290
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 27, 2025.

Transparency log

Release files / jigsawwm-3.1.0-py3-none-any.whl

Download URL jigsawwm-3.1.0-py3-none-any.whl
Size 105.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9b66e0339c1ba9b1ab8b891d33b838b510fa72a0af7a9007dcb91a85d14a90ee
BLAKE2b-256 checksum
How to use checksums
0ef622eb0af5255cb8fffe3ee530e1b1d4c1dd729cdb2efae67a54c5edd1b612
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 27, 2025.

Transparency log

Release history Release notifications | RSS feed

This release

3.1.0 This release

2 release files

3.0.1

2 release files

3.0.0

2 release files

2.2.0

2 release files

2.1.1

2 release files

2.1.0

2 release files

2.0.1

2 release files

2.0.0

2 release files

1.2.1

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page