dwm(1) — dan's workspace manager

NAME

dwm — a TUI workspace manager for jj and git

DESCRIPTION

Suddenly everyone is building multi-agentic workflows on top of git worktrees, and there are a lot of apps to manage them. Most of them do too much, and they don't support jj workspaces. Here is mine, which aims to do as little as possible while remaining useful.

dwm (pronounced "doom") creates, lists, and deletes workspaces stored under <repo>/.dwm/worktrees/<name>/, with a shell wrapper that auto-cds into the selected workspace. It works with both jj and git repositories.

The first time you create a workspace in a repo, dwm adds .dwm/ to your ignore rules — .git/info/exclude for git repos, .gitignore for jj-only repos — so workspace directories never end up tracked.

It provides an interactive TUI picker for browsing and switching between workspaces, with filtering, sorting, and inline deletion. It will also show a live-updating summary of Claude Code sessions that are running in each workspace.

My workflow looks like this: dwm new to create and move to the new worktree, and then claude to open my coding assistant of choice. Once my changes are done, I run dwm delete to clear up the worktree. If I'm switching between long-lived tasks, I use dwm list to see my open workspaces.

dwm TUI showing workspace list with preview pane

INSTALL

Shell installer (macOS and Linux):

curl --proto '=https' --tlsv1.2 -LsSf
    https://github.com/drivasperez/dwm/releases/download/v1.0.1/dwm-installer.sh | sh

Homebrew:

brew install drivasperez/tap/dwm

Cargo:

cargo install dwm

Pre-built binaries are available on the latest GitHub release.

SHELL SETUP

`dwm` needs to add a small snippet to your shell config in order to be able to switch directories for you. Run dwm setup interactively and it will offer to add the wrapper to your shell config and set up agent hooks automatically:

dwm setup

Or add it manually:

Bash / Zsh — add to .bashrc or .zshrc:

eval "$(dwm shell-setup)"

Fish — add to ~/.config/fish/config.fish:

dwm shell-setup --fish | source

This wraps the dwm binary so that selecting a workspace automatically cds into it.

SETUP HOOKS

After dwm new creates a workspace, it can run a setup script (e.g. npm install, copy .env, …) so the workspace is immediately usable. Configure it via .dwm.toml at the repo root:

[scripts]
setup = "npm install && cp ../main/.env .env"
# `run` and `archive` are reserved for future lifecycle hooks; parsed but not invoked yet

If .dwm.toml is absent but a Conductor conductor.json exists at the repo root, dwm reads scripts.setup from it as a drop-in fallback. Conductor-specific fields like runScriptMode and enterpriseDataPrivacy are accepted and ignored, so an existing conductor.json works without edits.

The script runs as sh -c "<command>" with the new workspace as its working directory. Stdout and stderr from the script are forwarded to dwm's stderr (dwm's stdout is reserved for the path the shell wrapper cds into). A non-zero exit prints a warning but doesn't unwind — the workspace is still created and you're still cdd into it.

The script sees these environment variables:

DWM_WORKSPACE_PATH
Absolute path of the new workspace
DWM_WORKSPACE_NAME
Workspace name
DWM_REPO_ROOT
Absolute path of the original repo root
DWM_VCS
jj or git
DWM_FROM_WORKSPACE
The --from <name> value, if provided
CONDUCTOR_ROOT_PATH
Alias of DWM_REPO_ROOT, for Conductor compat
CONDUCTOR_WORKSPACE_PATH
Alias of DWM_WORKSPACE_PATH
CONDUCTOR_WORKSPACE_NAME
Alias of DWM_WORKSPACE_NAME

AGENT STATUS TRACKING

dwm can show the status of Claude Code agents running in your workspaces. The TUI's "Agent" column displays per-workspace counts like 2 waiting, 1 working.

To set it up, run:

dwm setup

This installs Claude Code hooks that report agent status to dwm.

USAGE

dwm new [name]
Create a workspace (name auto-generated if omitted)
dwm new --at <rev>
Create a workspace starting from a specific revision
dwm new --from <ws>
Fork from an existing workspace's current change
dwm list
Interactive TUI picker to switch workspaces
dwm list --all
Multi-repo dashboard across all repos
dwm status
Non-interactive workspace summary
dwm switch <name>
Switch to a workspace by name
dwm rename <old> <new>
Rename a workspace
dwm delete [name]
Delete a workspace (current one if name omitted)
dwm setup
Interactive shell and agent setup
dwm version
Print the current version (also available as dwm --version)
┌──────────────────────────┐
│░░░░░░░░░░░░░░░░░░░░░░░░░░│
│░░░░░░░░░░░░░░░░░░░░░░░░░░│
│░░░░░░░░░░░░Hello░░robot░░│
│░░░░░░░░░░░░░░░░░░░░░░░░░░│
│░░░░░░░░░░░░░░░┌┐░░┌┐░░░░░│
│░░┌┐░░░░░░░░░░░└┘░░└┘░░░░░│
│░░││░░░░░░░░░░░░░░░░░░░░░░│
│░░└┘░░░░░░░░░░░░░░░░░░░░░░│
│░░░░░░░░░░░░░░░░░░░░░░░░░░│
│░░░░░░░░░░░░░░░░░░░░░░░░░░│
│░░░░░░░░░┌─────────────┐░░│
│░░░░░░░░░│▚▚▚▚▚▚▚▚▚▚▚▚▚│░░│
│░░░░░░░░░└─────────────┘░░│
│░░░░░░░░░░░░░░░░░░░░░░░░░░│
│░░░░░░░░░░░░░░░░░░░░░░░░░░│
└──────────────────────────┘
      

dwm 1.0.1 — source — releases