taskwm - Task-Centric Workspaces for bspwm
A task-based workflow manager for bspwm that lets you organize your work into tasks, each with its own set of windows.
Features
- Task Picker (Super+1): A dedicated desktop for managing tasks
- Active Workspace (Super+2): Your current task's windows
- Window Swapping: Seamlessly switch between tasks, windows follow automatically
- Polybar Integration: Shows current task with done/switch controls
- CLI Interface: Short commands for scripting and quick actions
Dependencies
Required:
- Python 3.x
- pywebview (
pip install pywebview) - WebKitGTK (for pywebview on Linux)
- bspwm / bspc
- xdotool (for window ID detection)
- polybar (for status bar integration)
- Inter font (for picker UI typography)
Optional:
- xprop (for WM_CLASS inspection)
Installing on Arch Linux
sudo pacman -S python webkit2gtk-4.1 bspwm xdotool polybar inter-font pip install pywebview
Installation
- Clone the repository:
git clone https://github.com/magik6k/taskwm ~/src/taskwm- Create symlinks in your PATH:
mkdir -p ~/.local/bin ln -sf ~/src/taskwm/taskwm/bin/tw ~/.local/bin/tw
- Ensure
~/.local/binis in your PATH (add to~/.bashrcor~/.zshrc):
export PATH="$HOME/.local/bin:$PATH"
Configuration
sxhkdrc
Add these keybindings to your ~/.config/sxhkd/sxhkdrc:
# Task workspaces super + 1 bspc desktop -f tasks super + 2 bspc desktop -f active # Legacy numeric desktops super + {0,3,4,5,6,7,8,9} bspc desktop -f {0,3,4,5,6,7,8,9} # Move window to desktop super + shift + {0,1,2,3,4,5,6,7,8,9} bspc node -d {0,tasks,active,3,4,5,6,7,8,9} # Quick done - close current task super + shift + d tw d -f
bspwmrc
Add to your ~/.config/bspwm/bspwmrc:
# Start taskwm daemon (after sxhkd) tw daemon & # Rule for taskwm picker bspc rule -a taskwm-picker desktop=tasks state=tiled
Polybar
Add these modules to your polybar config:
[module/taskwm] type = custom/script interval = 1 exec = tw status -l 40 click-left = bspc desktop -f tasks format-foreground = #7cafc2 [module/taskwm-done] type = custom/menu expand-right = true label-open = " Done " label-open-foreground = #e8e8e8 label-open-background = #333333 label-close = " Cancel " label-separator = " " menu-0-0 = "Confirm" menu-0-0-foreground = #ff6666 menu-0-0-exec = tw d -f
Then add to your bar:
modules-center = taskwm-done taskwmUsage
CLI Commands
tw a "title" # Add a new task, prints ID tw l # List tasks (ID<tab>title) tw l -a # List all tasks including done tw s <id> # Select task (swap windows into active) tw d # Mark current task done (prompts if windows exist) tw d -f # Force done (closes windows) tw r <id> # Remove task tw r <id> -f # Force remove (closes windows) tw cur # Print current task ID tw title # Print current task title tw status # Print current task title (for polybar) tw daemon # Run the background daemon
Workflow
-
Start the daemon (automatic if in bspwmrc):
-
Create a task:
- Press Super+1 to go to the Tasks desktop
- Type a task name and press Enter or click +
- Or from CLI:
tw a "Fix bug #123"
-
Select a task:
- Click [Select] in the picker, or
- Click the task name in polybar to go to picker, or
- From CLI:
tw s 1
-
Work on your task:
- Press Super+2 to go to Active desktop
- Open windows, they stay with your task
- Switch tasks anytime - windows move automatically
-
Complete a task:
- Click "Done" in polybar, then "Confirm", or
- Click [Close] in the picker, or
- From CLI:
tw d
Keyboard Shortcuts (in Picker)
| Key | Action |
|---|---|
| Up/Down | Navigate task list |
| Enter | Select highlighted task (or add if typing) |
| Delete / Ctrl+D | Close highlighted task |
| Ctrl+N | Focus input field |
| Escape | Clear input / deselect |
File Locations
- State:
~/.local/state/taskwm/state.json - Config:
~/.config/taskwm/config.json - PID files:
~/.local/state/taskwm/*.pid
Configuration Options
{
"monitor": "DP-0",
"theme": {
"font": "monospace 10",
"bg": "#111111",
"fg": "#e6e6e6",
"accent": "#66aaff",
"button_bg": "#222222",
"entry_bg": "#1a1a1a",
"select_bg": "#333333",
"border": "#333333"
},
"behavior": {
"close_policy": "delete",
"move_stray_on_tasks_to": "active"
}
}Troubleshooting
Check if daemon is running
ps aux | grep 'tw daemon' cat ~/.local/state/taskwm/daemon.pid
Restart the daemon
pkill -f 'taskwm' tw daemon &
View state
cat ~/.local/state/taskwm/state.json | python -m json.tool
Reset state
rm ~/.local/state/taskwm/state.json pkill -f 'taskwm' tw daemon &
Architecture
taskwm/
├── taskwm/
│ ├── __init__.py # Package init
│ ├── __main__.py # Module entry point
│ ├── cli.py # CLI commands (tw)
│ ├── state.py # State management (JSON)
│ ├── config.py # Configuration handling
│ ├── bspwm.py # bspwm interaction (bspc wrapper)
│ ├── daemon.py # Background daemon
│ └── ui_picker.py # Task picker UI (Tkinter)
└── bin/
└── tw # CLI wrapper script
Maintanance
I'm generally very busy so I don't intend to actively work on fixing issues unless they are actively annoying for me personally. I've built this tool basically vibe-coding all the way. If there is someone who wants to maintain and grow this project please let me know so we can transfer the repo to a better home.
License
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
See LICENSE for full text.
