wspace is a small, git-native CLI that manages a multi-repo Wazoo workspace
without Git submodules. It keeps the working rules in one place and makes them
enforceable from the terminal.
Design principles:
- Thin over custom. Prefer plain
gitporcelain/plumbing and well-known directory conventions over bespoke state files. The workspace layout is encoded in a singlerepos.jsonmanifest. - Conservative mutation. Commands that write or move state (update,
worktree, env) refuse to touch dirty repositories, feature branches, missing
repos, or unmanaged checkouts.
updateonly fetches and fast-forwards clean default branches; it never resets, rebases, stashes, or rewrites history. - Machine-readable output.
check --jsonemits structured results for tools; plain output is for humans. - Exit code contract.
wspace checkexits0when the workspace is clean and1when any repository is dirty, diverged, missing, or otherwise not in sync.
wspace check— read-only baseline check. ReportsCLEAN,DIRTY,FEATURE_CLEAN,DIVERGED,UNKNOWN,MISSING, andUNMANAGEDstates.wspace init [<repo...>]— clone missing repositories from the manifest (or only a specified subset of repos). Prints a warning that fresh clones lack gitignored files and repo-specific setup.wspace update— fetch remotes and fast-forward only clean default branches.wspace worktree add <repo> <feature> [<commit-ish>]— create a git worktree underworktrees/<repo>/<feature>/, branching from the repo's default-branch baseline (origin/<default>) or an explicit<commit-ish>. Attaches an existing branch of the same name with a warning.wspace worktree list [--stale] [--json]— list worktrees across all repositories.--stalefilters to linked worktrees whose branch is fully merged into the default branch (or missing), i.e. safe removal candidates.wspace worktree remove <repo> <feature>— remove a worktree, then prune and tidy the now-emptyworktrees/<repo>/directory.wspace env sync— copy local environment files from a gitignoredsecrets/vault into checkouts and worktrees.wspace sync— alias forwspace init.wspace validate— validate the manifest without touching any repository.
All workspace commands run from the workspace root (the directory containing
repos.json). When creating worktrees for parallel feature development, always
follow this standard lifecycle:
- Check workspace status:
wspace check
- Refresh clean default branches:
wspace update
- Create a feature worktree:
(Or using
git -C repos/<repo> worktree add "$PWD/worktrees/<repo>/<feature>" -b <feature>
wspace:wspace worktree add <repo> <feature>) - Develop inside the worktree:
cd worktrees/<repo>/<feature> # make edits, run tests, commit changes
- Sync local secrets when needed:
wspace env sync --dry-run # preview changes wspace env sync # copy secrets with mode 0600 permissions
- Push and open a PR:
git push -u origin <feature> gh pr create
- Find stale worktrees after PR merge:
wspace worktree list --stale
- Clean up merged worktree:
wspace worktree remove <repo> <feature>
- Workspace Root Anchor: All repository and worktree paths in
workspace.json(orwspace.json/repos.json) resolve relative to the directory containing the manifest file, regardless of the caller's current working directory. - Why
$PWDis required withgit -C:git -C repos/<repo>changes Git's working directory torepos/<repo>before executing. If you pass a relative path likeworktrees/<repo>/<feature>, Git creates the worktree nested insiderepos/<repo>/worktrees/...instead of at the workspace root. Using"$PWD/worktrees/<repo>/<feature>"resolves$PWDfrom the workspace root before Git runs. - Default Worktree Baseline:
wspace worktree addbranches fromorigin/<default>(resolved viaorigin/HEAD), ensuring feature branches start from the remote baseline rather than a local dirty state or arbitraryHEAD.
Each Git worktree maintains an independent working directory, while modern package managers optimize dependency caching across worktrees:
pnpm: Uses a central content-addressable store (~/.local/share/pnpm/store). Runningpnpm installin a new worktree hard-links dependencies from the central store without duplicating files or re-downloading packages.- Deno: Uses the global
DENO_DIRmodule cache (~/.cache/denoor%LOCALAPPDATA%\deno), sharing cached dependencies across all worktrees zero-copy. - npm / yarn: Running
npm installoryarn installinside a worktree installs dependencies for that worktree, fetching packages from the shared user HTTP cache.
PATH_BLOCKEDorINVALIDduringinit: An existing directory or file occupies the expected repository path but is not a valid Git repository.wspace initfails closed without touching or overwriting the path. Remove or relocate the blocking path manually.SKIP_FEATURE/FEATURE_CLEAN: Indicates thatrepos/<repo>is checked out on a feature branch instead of the default branch.wspace updateskips updating feature branches to protect user work.- Symlink rejection in
env sync: For security,wspace env syncwill refuse to overwrite any destination path that is a symbolic link. - Dirty linked worktrees:
wspace checkinspects both primary checkouts and linked feature worktrees. If any linked worktree has uncommitted changes,wspace checkreturns a non-zero exit code (1).
Install from JSR as the wspace binary:
deno install -g --name wspace jsr:@wazoo/workspaceOr build a local binary:
deno task buildRequires a Deno runtime (v2+). The wspace binary has no runtime dependencies.
deno task ciRuns deno fmt --check, deno lint, deno check, and deno test (includes
integration tests against real local git repositories).