git-wisp
v0.0.3
Published
Agent- and human-friendly Git multitasking, powered by worktrees
Downloads
9
Maintainers
Readme
Install
$ npm i -g git-wisp # aliased to wispHow wisp works
There have been many attempts to nail a DX for parallel work in the agentic coding era. Most are thin wrappers over git worktree. Instead, this tool introduces a new paradigm: the wisp.
A wisp is a worktree in an isolated subshell that is pruned-on-close.
Here's how it works (key points in bold).
- You open a Git branch with
wisp open <branch>or create a new one withwisp new <branch>. - An ephemeral worktree is created for this branch (in
.git/wisp/worktrees) and opened in a fresh subshell. - 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
wisp close. 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.
Features
This approach has some nice properties.
- 🖥️ Tab-local checkouts — Normally a
git checkout/git switchchanges your active branch for all terminals. With wisps, you can functionality open branches in the current tab only. - 🌳 Full isolation — Each wisp is isolated on disk, so the changes you make don't interfere anything else you're doing.
- 🙅♂️ Never stash again — You can
wisp opena branch even with uncommitted changes. When you exit the subshell, things will be exactly the same as they were. ☕️ - Consistent with branch semantics — As with regular
git switch,wisp closewon'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 wisps so multiple agents can work simultaneously without conflicts.
Quickstart
This section is entirely linear and self-contained. Try running all these commands in order to get a feel for how wisp works. First, install wisp.
$ npm i -g git-wispThen clone a repo (any repo works):
$ git clone [email protected]:colinhacks/zod.git
$ cd zodAfter cloning, the main branch is checked out. Let's say we want to start work on a new feature:
$ wisp new feat-1
✓ feat-1 (from main)
Opened branch in ephemeral subshell at .git/wisp/worktrees/zod@feat-1
Type 'wisp close' to return.You're now in a wisp. Check where you are:
$ pwd
/Users/colinmcd94/Documents/repos/zod/.git/wisp/worktrees/zod@feat-1
$ git branch --show-current
feat-1Now let's make some changes. (You can also open the repo in an IDE, start an agent run, etc.)
$ touch a.txtNow let's try to close the wisp.
$ wisp close
⚠ Uncommitted changes found. Commit, stash, or reset your changes first.
Or use --force/-f to discard changes
wisp close -fWe aren't able to close because we have uncommitted changes. Let's commit them.
$ 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, wisp offers to auto-merge the changes.
$ wisp 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'CLI
wisp v0.x.y - Human- and agent-friendly Git multitasking
Usage: wisp <command> [options]
Commands:
new [branch] Create a branch and open it [--from <branch>]
open <branch> Open a branch in a wisp
close Exit current wisp
ls List orphaned worktrees
status Show current branch
rm <branch> Remove a branch's worktree
config Show or create config file
Options:
--help, -h Show help
--version, -v Show versionList orphaned worktrees
Normally the worktree will be auto-pruned when you close its associated wisp. If a worktree is left behind for some reason, you can list them with wisp ls.
$ wisp ls
┌────────┬───────────┬───────────────┐
│ branch │ status │ created │
├────────┼───────────┼───────────────┤
│ main * │ clean │ - │
│ feat-1 │ 1 changed │ 5 minutes ago │
└────────┴───────────┴───────────────┘Open a branch in a wisp
You can open any existing Git branch in a wisp.
$ wisp open feat-1
✓ feat-1 (existing worktree)
Type 'wisp close' to return.Show current branch status
$ wisp status
branch: main (root)
worktree: /path/to/zod
status: cleanRemove a worktree
Remove the worktree for a branch (the branch itself is kept):
$ wisp rm feat-1
✓ Pruned worktree for feat-1Closing a wisp
This closes the current wisp and auto-prunes the associated worktree. Your changes survive in your branch commits.
$ wisp 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 wisp; this will discard uncommitted changes.
$ wisp close --forcePrint or create a wisp.toml
To print or create a config file:
$ wisp config
✓ Config file: /path/to/repo/.git/wisp.toml
────────────────────────────────────────────────────────────
setup = "npm install"
────────────────────────────────────────────────────────────If no config exists, you'll be prompted to create one.
$ wisp config
No config file found.
Where would you like to create one?
1. .git/wisp.toml (local only, not committed)
2. wisp.toml (project root, can be committed)
Choice (1/2): 1
✓ Created /path/to/repo/.git/wisp.tomlwisp.toml
You can configure wisp with a wisp.toml file. This is useful for running setup scripts when opening a wisp (e.g., npm install).
wisp looks for config files in the following order:
| Path | Description |
|------|-------------|
| .git/wisp.toml | Local only, not committed (highest precedence) |
| wisp.toml | Project root, can be committed |
# setup script executed in subshell after initialization
setup = "npm install && cp {{ repo_path }}/.env {{ worktree_path }}/.env"The following variable substitutions are supported in setup.
| Variable | Description | Example |
|----------|-------------|---------|
| {{ branch }} | Branch name | feature/auth |
| {{ repo_path }} | Absolute path to main repo | /path/to/repo |
| {{ worktree_path }} | Absolute path to worktree | /path/to/repo/.git/wisp/worktrees/repo@feat |
