Agent- and human-friendly Git multitasking, powered by worktrees
npm install workshell
workshellHuman- and agent-friendly Git multitasking. Powered by worktrees.
by @colinhacks
``bashwk
$ npm i -g workshell # aliases to
$ wk --help
wk v0.0.6 - Open branches in ephemeral subshells
Usage: wk ...
`
worksThere have been many attempts to nail a DX for parallel work in the agentic coding era. Most are thin wrappers over git worktree. Instead wk introduces a new paradigm: the workshell.
A _workshell_ is an ephemeral worktree whose lifecycle is bound to a subshell.
Here's how it works (key points in bold).
- You open a Git branch with wk open or create a new one with wk new .~/.workshell/worktrees
- An ephemeral worktree is created for this branch (in ) and opened in a fresh subshell.wk close
- You are now in an fresh checkout of your repo that is isolated on disk. Make changes with your agent/editor of choice and commit them.
- You close the subshell with . The associated worktree is auto-pruned.
- Your changes still exist on the associated branch, as Git commits/branches are shared among all worktrees. The worktree is destroyedβbut your commits aren't.
This approach has some nice properties.
- π₯οΈ Tab-local workspaces β Normally a git checkout/git switch changes your active branch for all terminals. With workshells, you can functionality open branches in the current tab only.wk open
- π³ Full isolation β Each workshell is isolated on disk, so the changes you make don't interfere anything else you're doing.
- π
ββοΈ Never stash again β You can a branch even with uncommitted changes. When you exit the subshell, things will be exactly the same as they were. βοΈgit switch
- πͺΎ Consistent with branch semantics β As with regular , wk close won't let you close the subshell if you have unstaged/uncommitted changes. This is a feature, not a bug! Regular worktrees make it easy to lose your work in a forgotten corner of your file system.
- π€ Agent-ready β Spin up parallel workshells so multiple agents can work simultaneously without conflicts.
This section is entirely linear and self-contained. Try running all these commands in order to get a feel for how wk works. First, install wk.
`bash`
$ npm i -g workshell
This installs the workshell CLI. For convenience, it's also aliased to wk. We'll use wk throughout the quickstart.
`sh
$ wk status
branch: main (root)
worktree: /Users/colinmcd94/Documents/projects/pf
status: clean
`
Clone a repo (any repo works):
`bash`
$ git clone git@github.com:colinhacks/zod.git
$ cd zod
After cloning, the main branch is checked out. Let's say we want to start work on a new feature:
`bash
$ wk new feat-1
β feat-1 (from main)
Opened branch in ephemeral subshell
Type 'wk close' to return.
`
You're now in a workshell. Check where you are:
`bash
$ pwd
~/.workshell/worktrees/{repo-id}/zod@feat-1
$ git branch --show-current
feat-1
`
Now let's make some changes. (You can also open the repo in an IDE, start an agent run, etc.)
`bash`
$ touch a.txt
Now let's try to close the workshell.
`bash`
$ wk close
β Uncommitted changes found. Commit, stash, or reset your changes first.
Or use --force/-f to discard changes
wk close -f
We aren't able to close because we have uncommitted changes. Let's commit them.
`bash`
$ git add -A && git commit -am "Add a.txt"
Now we can try closing again. Since our changes can be fast-forwarded from the base branch, wk offers to auto-merge the changes.
`bash
$ wk close
β Back in main
Pruned worktree. Your changes are still in the 'feat-1' branch.
To merge your changes:
git merge feat-1
Auto-merge? (y/n/never) y
β Merged 'feat-1' into 'main'
`
`sh
wk v0.x.y - Human- and agent-friendly Git multitasking
Usage: wk
Commands:
new [branch] Create a branch and open it [--from
open
close Exit current workshell
ls List orphaned worktrees
status Show current branch
rm
config Show or create config file
Options:
--help, -h Show help
--version, -v Show version
`
Normally the worktree will be auto-pruned when you close its associated workshell. If a worktree is left behind for some reason, you can list them with wk ls.
`sh`
$ wk ls
ββββββββββ¬ββββββββββββ¬ββββββββββββββββ
β branch β status β created β
ββββββββββΌββββββββββββΌββββββββββββββββ€
β main * β clean β - β
β feat-1 β 1 changed β 5 minutes ago β
ββββββββββ΄ββββββββββββ΄ββββββββββββββββ
You can open any existing Git branch in a workshell.
`sh
$ wk open feat-1
β feat-1 (existing worktree)
Type 'wk close' to return.
`
`sh`
$ wk status
branch: main (root)
worktree: /path/to/zod
status: clean
Remove the worktree for a branch (the branch itself is kept):
`sh
$ wk rm feat-1
β Pruned worktree for feat-1
`
This closes the current workshell and auto-prunes the associated worktree. Your changes survive in your branch commits.
`sh
$ wk close
β Back in main
Pruned worktree. Your changes are still in the 'feat-1' branch.
To merge your changes:
git merge feat-1
Auto-merge? (y/n/never) y
β Merged 'feat-1' into 'main'
`
If the branch hasn't been pushed to a remote, you'll be prompted to auto-merge:
- y β merge into base branchn
- β skip (branch is kept, merge manually later)never
- β permanently disable auto-merge prompt
That command will fail if you have unstaged/uncommited changes. Use the --force/-f flag to force close the workshell; this will discard uncommitted changes.
`sh`
$ wk close --force
To print or create a config file:
`sh
$ wk config
β Config file: /path/to/repo/.git/workshell.toml
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
setup = "npm install"
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
`
If no config exists, you'll be prompted to create one.
`sh
$ wk config
No config file found.
Where would you like to create one?
1. .git/workshell.toml (local only, not committed)
2. workshell.toml (project root, can be committed)
Choice (1/2): 1
β Created /path/to/repo/.git/workshell.toml
`
You can configure wk with a workshell.toml file. This is useful for running setup scripts when opening a workshell (e.g., npm install).
wk looks for config files in the following order:
| Path | Description |
|------|-------------|
| .git/workshell.toml | Local only, not committed (highest precedence) |workshell.toml
| | Project root, can be committed |
Currently only one setting is supported: setup.
`toml{{ branch }}setup script executed in subshell after initialization
the following variable substitutions are supported
β The name of the opened branch, e.g. feature/auth {{ repo_path }}
β The absolute path to main repo, e.g. /path/to/repo{{ worktree_path }}
β The absolute path to worktree, e.g. ~/.workshell/worktrees/.../repo@feat``
setup = "npm install && cp {{ repo_path }}/.env {{ worktree_path }}/.env"