Skip to main content

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

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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

jigsawwm-3.1.0.tar.gz (94.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

jigsawwm-3.1.0-py3-none-any.whl (105.3 kB view details)

Uploaded Python 3

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

Hashes for jigsawwm-3.1.0.tar.gz
Algorithm Hash digest
SHA256 dc589c11fc219e65ad5aa72979f939dfd041edf4cd1581825e8ab140d4f0f055
MD5 c397bc1be99c4c32e56d7672386175ff
BLAKE2b-256 6a43e0e2506e4c464f010692b15b9859b6f1fdb7fe35a07f311f0bcf87e0c290

See more details on using hashes here.

Provenance

The following attestation bundles were made for jigsawwm-3.1.0.tar.gz:

Publisher: pypi.yaml on klesh/JigsawWM

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for jigsawwm-3.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9b66e0339c1ba9b1ab8b891d33b838b510fa72a0af7a9007dcb91a85d14a90ee
MD5 9e7ec7b7da0ccb044fff1f8312476854
BLAKE2b-256 0ef622eb0af5255cb8fffe3ee530e1b1d4c1dd729cdb2efae67a54c5edd1b612

See more details on using hashes here.

Provenance

The following attestation bundles were made for jigsawwm-3.1.0-py3-none-any.whl:

Publisher: pypi.yaml on klesh/JigsawWM

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page