Skip to content

Tutorial

For the tutorial, we will use wpm to set up a keyboard-focused desktop environment on a brand new virtual machine which uses kanata to enable QMK-style keyboard layers, whkd to enable programmable hotkeys, komorebi to enable tiling window management, and komorebi-bar as a status bar.

One you have completed the tutorial, you should have a good idea of how wpm can be used to model and enforce constraints in use cases from customized desktops to complex local development environments and more.

Create a new Virtual Machine

  • Open Hyper-V Manager
  • Select "Quick Create"
  • Select "Windows 11 dev environment"
  • Select "Create Virtual Machine"

Install scoop

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Invoke-RestMethod -Uri https://get.scoop.sh | Invoke-Expression

Install wpm

Install scoop and then install wpm

scoop install git # need this to be able to add the extras bucket

scoop bucket add extras
scoop install wpm

Generate example units

Generate some example unit files in ~/.config/wpm

wpmctl examplegen $(wpm units)

You can ls the directory to make sure they have been generated

PS C:\Users\User> ls $(wpmctl units)


    Directory: C:\Users\User\.config\wpm


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----          4/6/2025   3:02 PM            503 desktop.json
-a----          4/6/2025   3:02 PM            883 kanata.json
-a----          4/6/2025   3:02 PM           1032 komokana.json
-a----          4/6/2025   3:02 PM           1026 komorebi-bar.json
-a----          4/6/2025   3:02 PM           1417 komorebi.json
-a----          4/6/2025   3:02 PM            971 mousemaster.json
-a----          4/6/2025   3:02 PM            835 whkd.json

Start wpmd

Run wpmd in terminal to start the process manager - this will automatically download all required packages and configuration files before starting to listen for commands

PS C:\Users\User> wpmd
2025-04-06T22:07:42.124299Z  INFO wpm::process_manager: desktop: registered unit
2025-04-06T22:07:42.126354Z  INFO wpm::unit: kanata: adding resource C:\Users\User\AppData\Local\wpm\store\gist.githubusercontent.com_LGUG2Z_bbafc51ddde2bd1462151cfcc3f7f489_raw_28e24c4a493166fa866ae24ebc4ed8df7f164bd1\minimal.clj to store
2025-04-06T22:07:42.207182Z  INFO wpm::unit: installing scoop manifest https://raw.githubusercontent.com/ScoopInstaller/Extras/8a6d8ff0f3963611ae61fd9f45ff36e3c321c8b5/bucket/kanata.json
Installing 'kanata' (1.8.1) [64bit] from 'https://raw.githubusercontent.com/ScoopInstaller/Extras/8a6d8ff0f3963611ae61fd9f45ff36e3c321c8b5/bucket/kanata.json'
Loading kanata.exe from cache
Checking hash of kanata.exe ... ok.
Linking ~\scoop\apps\kanata\current => ~\scoop\apps\kanata\1.8.1
Creating shim for 'kanata'.
'kanata' (1.8.1) was installed successfully!
Notes
-----
Configuration Guide: https://github.com/jtroo/kanata/blob/main/docs/config.adoc

2025-04-06T22:07:44.513651Z  INFO wpm::process_manager: kanata: registered unit
2025-04-06T22:07:44.515218Z  INFO wpm::unit: komokana: adding resource C:\Users\User\AppData\Local\wpm\store\raw.githubusercontent.com_LGUG2Z_komokana_refs_tags_v0.1.5\komokana.example.yaml to store
2025-04-06T22:07:44.592705Z  INFO wpm::unit: installing scoop manifest https://raw.githubusercontent.com/ScoopInstaller/Extras/e633292b4e1101273caac59ffcb4a7ce7ee7a2e8/bucket/komokana.json
Installing 'komokana' (0.1.5) [64bit] from 'https://raw.githubusercontent.com/ScoopInstaller/Extras/e633292b4e1101273caac59ffcb4a7ce7ee7a2e8/bucket/komokana.json'
Loading komokana-0.1.5-x86_64-pc-windows-msvc.zip from cache
Checking hash of komokana-0.1.5-x86_64-pc-windows-msvc.zip ... ok.
Extracting komokana-0.1.5-x86_64-pc-windows-msvc.zip ... done.
Linking ~\scoop\apps\komokana\current => ~\scoop\apps\komokana\0.1.5
Creating shim for 'komokana'.
'komokana' (0.1.5) was installed successfully!
'komokana' suggests installing 'extras/komorebi'.

2025-04-06T22:07:46.792651Z  INFO wpm::process_manager: komokana: registered unit
2025-04-06T22:07:46.793421Z  INFO wpm::unit: komorebi-bar: adding resource C:\Users\User\AppData\Local\wpm\store\raw.githubusercontent.com_LGUG2Z_komorebi_refs_tags_v0.1.35_docs\komorebi.bar.example.json to store
2025-04-06T22:07:46.820347Z  INFO wpm::unit: installing scoop manifest https://raw.githubusercontent.com/ScoopInstaller/Extras/8e21dc2cd902b865d153e64a078d97d3cd0593f7/bucket/komorebi.json
Installing 'komorebi' (0.1.35) [64bit] from 'https://raw.githubusercontent.com/ScoopInstaller/Extras/8e21dc2cd902b865d153e64a078d97d3cd0593f7/bucket/komorebi.json'
Loading komorebi-0.1.35-x86_64-pc-windows-msvc.zip from cache
Checking hash of komorebi-0.1.35-x86_64-pc-windows-msvc.zip ... ok.
Extracting komorebi-0.1.35-x86_64-pc-windows-msvc.zip ... done.
Linking ~\scoop\apps\komorebi\current => ~\scoop\apps\komorebi\0.1.35
Creating shim for 'komorebi'.
Creating shim for 'komorebic'.
Creating shim for 'komorebic-no-console'.
Making C:\Users\User\scoop\shims\komorebic-no-console.exe a GUI binary.
Creating shim for 'komorebi-gui'.
Creating shim for 'komorebi-bar'.
'komorebi' (0.1.35) was installed successfully!
Notes
-----
Check out the quickstart guide on https://lgug2z.github.io/komorebi
'komorebi' suggests installing 'extras/autohotkey'.
'komorebi' suggests installing 'extras/whkd'.

2025-04-06T22:07:49.420615Z  INFO wpm::process_manager: komorebi-bar: registered unit
2025-04-06T22:07:49.421177Z  INFO wpm::unit: komorebi: adding resource C:\Users\User\AppData\Local\wpm\store\raw.githubusercontent.com_LGUG2Z_komorebi_refs_tags_v0.1.35_docs\komorebi.example.json to store
2025-04-06T22:07:49.442994Z  INFO wpm::process_manager: komorebi: registered unit
2025-04-06T22:07:49.443741Z  INFO wpm::unit: whkd: adding resource C:\Users\User\AppData\Local\wpm\store\raw.githubusercontent.com_LGUG2Z_komorebi_refs_tags_v0.1.35_docs\whkdrc.sample to store
2025-04-06T22:07:49.470394Z  INFO wpm::unit: installing scoop manifest https://raw.githubusercontent.com/ScoopInstaller/Extras/112fd691392878f8c4e9e9703dde3d1d182941e3/bucket/whkd.json
Installing 'whkd' (0.2.7) [64bit] from 'https://raw.githubusercontent.com/ScoopInstaller/Extras/112fd691392878f8c4e9e9703dde3d1d182941e3/bucket/whkd.json'
Loading whkd-0.2.7-x86_64-pc-windows-msvc.zip from cache
Checking hash of whkd-0.2.7-x86_64-pc-windows-msvc.zip ... ok.
Extracting whkd-0.2.7-x86_64-pc-windows-msvc.zip ... done.
Linking ~\scoop\apps\whkd\current => ~\scoop\apps\whkd\0.2.7
Creating shim for 'whkd'.
'whkd' (0.2.7) was installed successfully!

2025-04-06T22:07:51.580342Z  INFO wpm::process_manager: whkd: registered unit
2025-04-06T22:07:51.580712Z  INFO wpmd: listening on wpmd.sock

Start the units

The dependency graph of our example units looks like this

  • komorebi-bar depends on komorebi
  • komorebi depends on whkd and kanata

So we can run wpmctl start komorebi-bar to ensure that whkd, kanata, komorebi and komorebi-bar are all started and passing their healthchecks.

2025-04-06T22:12:26.419780Z  INFO wpmd: received socket message: Start(["komorebi-bar"])
2025-04-06T22:12:26.420163Z  INFO wpmd: successfully queued socket message
2025-04-06T22:12:26.420204Z  INFO wpm::process_manager: komorebi-bar: requires komorebi
2025-04-06T22:12:26.420689Z  INFO wpm::process_manager: komorebi: requires whkd
2025-04-06T22:12:26.421003Z  INFO wpm::unit: whkd: starting unit
2025-04-06T22:12:26.424052Z  INFO wpm::unit: whkd: running pid 11716 liveness healthcheck (1s)
2025-04-06T22:12:27.441812Z  INFO wpm::unit: whkd: passed healthcheck
2025-04-06T22:12:27.442303Z  INFO wpm::process_manager: komorebi: requires kanata
2025-04-06T22:12:27.442572Z  INFO wpm::unit: kanata: starting unit
2025-04-06T22:12:27.446427Z  INFO wpm::unit: kanata: running pid 9520 liveness healthcheck (1s)
2025-04-06T22:12:28.466568Z  INFO wpm::unit: kanata: passed healthcheck
2025-04-06T22:12:28.466976Z  INFO wpm::unit: komorebi: starting unit
2025-04-06T22:12:28.471147Z  INFO wpm::unit: komorebi: running command healthcheck - C:\Users\User\scoop\shims\komorebic.exe state (1s)
2025-04-06T22:12:29.503620Z  INFO wpm::unit: komorebi: passed healthcheck
2025-04-06T22:12:29.503983Z  INFO wpm::unit: komorebi-bar: starting unit
2025-04-06T22:12:29.507663Z  INFO wpm::unit: komorebi-bar: running pid 9860 liveness healthcheck (1s)
2025-04-06T22:12:30.529935Z  INFO wpm::unit: komorebi-bar: passed healthcheck

Shutdown

You can press ctrl-c on the terminal window running wpmd to trigger a shutdown, which will ensure that all processes started in the previous steps are shutdown cleanly with their shutdown hooks respected.

2025-04-06T22:20:02.303289Z  INFO wpm::process_manager: wpmd: shutting down process manager
2025-04-06T22:20:02.303496Z  INFO wpm::process_manager: whkd: stopping unit
2025-04-06T22:20:02.303622Z  INFO wpm::process_manager: whkd: sending kill signal to 70000
2025-04-06T22:20:02.306467Z  INFO wpm::process_manager: whkd: process 70000 successfully terminated
2025-04-06T22:20:02.306587Z  INFO wpm::process_manager: komorebi-bar: stopping unit
2025-04-06T22:20:02.306714Z  INFO wpm::process_manager: komorebi-bar: sending kill signal to 40192
2025-04-06T22:20:02.352968Z  INFO wpm::process_manager: komorebi-bar: process 40192 successfully terminated
2025-04-06T22:20:02.356650Z  INFO wpm::process_manager: komorebi: stopping unit
2025-04-06T22:20:02.356777Z  INFO wpm::process_manager: komorebi: executing shutdown command - C:\Users\User\scoop\shims\komorebic.exe stop
2025-04-06T22:20:02.453174Z  INFO wpm::unit: komorebi: executing cleanup command - C:\Users\User\scoop\shims\komorebic.exe restore-windows
2025-04-06T22:20:02.792875Z  INFO wpm::process_manager: komorebi: sending kill signal to 17448
2025-04-06T22:20:02.793018Z  INFO wpm::process_manager: komorebi: process 17448 successfully terminated
2025-04-06T22:20:02.793137Z  INFO wpm::process_manager: komorebi: executing cleanup command - C:\Users\User\scoop\shims\komorebic.exe restore-windows
2025-04-06T22:20:02.811672Z  INFO wpm::process_manager: kanata: stopping unit
2025-04-06T22:20:02.811799Z  INFO wpm::process_manager: kanata: sending kill signal to 70136
2025-04-06T22:20:02.814617Z  INFO wpm::process_manager: kanata: process 70136 successfully terminated