Define workspaces in YAML, then plan/apply to reconcile safely.
Worktree sprawl brings pain:
- Risky cleanup and cognitive load from too many worktrees.
- Bulk creation is powerful but tedious to set up and place.
gion makes it safe and repeatable: declare task workspaces in YAML, review diffs (including deletion risk), then create and clean them up in bulk.
You don’t have to edit YAML directly—gion manifest ... lets you add/remove workspaces interactively and updates the inventory behind the scenes.
Tip
Looking for a more ticket-centric workspace tool? kra may fit better if your day-to-day work starts from one issue or ticket, and you want each task to have its own workspace, notes, artifacts, and attached repos.
- Developers working on tasks that span multiple repositories.
- GitHub-centric, PR/issue-driven workflows (spin up local worktrees for reviews/issues and work in parallel).
- People using AI agents to create and remove many worktrees.
- Reproducible inventory:
gion.yamlis the source of truth - Bulk create: spin up many worktrees at once.
- Bulk cleanup: remove worktrees in bulk (diff + confirmation, risk surfaced for dirty/unpushed/diverged/unknown).
- Fast navigation:
giongojumps to any workspace or repo - Multi-repo tasks: group repos under a single workspace via presets
- GitHub-aware entry points: create from PRs or issues with
gh
Tip: gion manifest can be shortened to gion m or gion man.
- Plan-first: always shows a diff before applying changes.
- Deletion risk visibility: removal plans include a risk summary (e.g., dirty / unpushed / diverged / unknown).
- dirty: working tree has changes.
- unpushed: local branch is ahead of upstream.
- diverged: local and upstream have both advanced.
- unknown: status cannot be determined (e.g., git error or missing upstream).
- Confirm destructive changes: removals require an explicit confirmation;
--no-promptrefuses destructive changes. - Conservative bulk cleanup:
gion manifest gcexcludes anything uncertain and acts only when it is highly likely safe. - Clear safety boundary: gion reconciles only under
GION_ROOT/(workspaces + repo stores).
brew tap tasuku43/gion
brew install gion- Version pinning with mise (optional):
mise use -g github:tasuku43/gion@<version> - Manual install via GitHub Releases (download archive → put
gionandgiongoon your PATH) - Build from source requires Go 1.24+
- Shell integration (recommended for safe workspace removal and faster setup):
eval "$(gion shell init zsh --with-completion)"eval "$(gion shell init bash --with-completion)"
- Git
ghCLI (optional; required forgion manifest add --reviewandgion manifest add --issue— GitHub only)
gion initBy default, gion uses ~/gion as the root:
~/gion/
gion.yaml
bare/ # bare repo store (shared Git objects)
workspaces/ # task workspaces (worktrees)
gion repo get git@github.com:org/backend.gitBare repo store location:
~/gion/bare/github.com/org/backend.git
Add a workspace interactively (example output, trimmed):
gion manifest addContext
• mode: repo
• repo: git@github.com:org/backend.git
• workspace id: PROJ-123
• repo #1 (git@github.com:org/backend.git)
└─ branch: PROJ-123-sample
Info
• manifest: updated gion.yaml
Plan
• + add workspace PROJ-123
└─ backend (branch: PROJ-123-sample)
repo: github.com/org/backend
Step
• Apply changes? (default: No) (y/n)
input: y
enter confirm esc cancel
Apply
• create workspace PROJ-123
└─ backend (branch: PROJ-123-sample)
Result
• applied: add=1 update=0 remove=0
• gion.yaml rewrittenResulting worktree:
~/gion/workspaces/PROJ-123/backend
# Setup (once; shell integration + completion):
eval "$(gion shell init zsh --with-completion)"
giongogion manifest rmSelect a workspace, review the plan, then confirm to apply.
For a command overview, see docs/guides/COMMANDS.md (or run gion help).
Declare in gion.yaml, diff with gion plan, reconcile with gion apply.
Example plan (add + remove, trimmed):
Plan
• + add workspace PROJ-123
└─ backend (branch: PROJ-123)
repo: github.com/org/backend
• - remove workspace PROJ-099
└─ backend (branch: PROJ-099)
risk: dirty (unstaged=2)
sync: upstream=origin/main ahead=1 behind=0
Step
• Apply destructive changes? (default: No) (y/n)
Interactive front-end to the inventory:
gion manifest addRun with flags to skip prompts:
gion manifest add --repo git@github.com:org/backend.git PROJ-123This path is optimized for bulk creation from PRs/issues with one apply.
Interactive bulk selection (multi-select in the picker):
gion manifest addNotes:
- Requires
gh(authenticated) to fetch metadata. - The picker supports bulk selection of PRs/issues, then a single apply.
Direct URL (single workspace):
gion manifest add --review https://github.com/owner/repo/pull/123
gion manifest add --issue https://github.com/owner/repo/issues/123Create a preset:
gion manifest preset add app --repo git@github.com:org/backend.git --repo git@github.com:org/frontend.gitpresets:
app:
repos:
- git@github.com:org/backend.git
- git@github.com:org/frontend.git
- git@github.com:org/infra.gitgion manifest add --preset app PROJ-123giongo is a small companion binary that jumps into a workspace or repo using a picker.
It does not change any state.
For gion itself, prefer gion shell init as the primary shell integration entrypoint:
eval "$(gion shell init zsh --with-completion)"This enables:
- parent-shell
cdafter successful destructive workspace removal - shell completion in the same setup step
giongonavigation without a separategiongo initstep
Notes:
gion shell initis the primary shell integration path forgioncommands.gion shell initalso installs thegiongoshell wrapper.- For a permanent setup, paste the output into
~/.zshrcor~/.bashrc.
Manual removal (explicit human judgment):
gion manifest rmAutomatic cleanup (conservative):
gion manifest gcgion manifest gc removes workspace entries from gion.yaml only when they are highly likely safe to delete, then (by default) runs gion apply to reconcile.
GC safety rules (summary):
- Excludes any workspace with dirty / unpushed / diverged / unknown state.
- Considers a workspace safe only when all repos are strictly merged into their target base.
- Uses Git data from the local repo store (no PR metadata).
If the filesystem is the source of truth, rebuild the inventory:
gion importGION_ROOT is resolved in this order:
--root <path>GION_ROOTenvironment variable- default
~/gion
- Inventory file:
<GION_ROOT>/gion.yaml - Bare repo stores (shared Git objects):
<GION_ROOT>/bare/ - Workspaces (task directories containing worktrees):
<GION_ROOT>/workspaces/
GION_ROOT/ (safety boundary: gion only touches under this directory)
├─ gion.yaml # desired state (inventory)
│
├─ bare/ # shared Git object store (bare clones)
│ └─ github.com/org/
│ ├─ backend.git # bare repo store (shared)
│ ├─ frontend.git
│ └─ infra.git
│
└─ workspaces/ # task-scoped directories (each contains worktrees)
├─ PROJ-123/ # workspace_id (task)
│ ├─ backend/ # worktree checkout (repo: backend)
│ │ ├─ .git # gitdir file -> points into .../backend.git/worktrees/...
│ │ └─ ... # working directory (your changes live here)
│ ├─ frontend/
│ └─ infra/
│
└─ PROJ-456/
└─ backend/
- Workspace: a task-scoped directory under
GION_ROOT/workspaces/<WORKSPACE_ID>/that can contain multiple repos. - Worktree: a Git worktree checkout for a repo, placed under a workspace (e.g.
.../workspaces/<id>/<alias>/). - Repo store: a shared bare clone cache under
GION_ROOT/bare/(used to create and update worktrees efficiently). - Manifest: the inventory file
gion.yamland thegion manifest ...subcommands that update it.
Invariants (short):
version: 1is the current inventory schema; future changes will be versioned.- gion only reads/writes under
GION_ROOT/(safety boundary). - Workspace IDs must be valid Git branch names (used as worktree branches).
gion.yaml is plain YAML. You can edit it directly (humans or AI), then review/apply changes:
gion plan
gion applyFor the full schema, see docs/spec/core/INVENTORY.md.
Minimal example:
version: 1
workspaces:
PROJ-123:
description: "fix login flow"
mode: repo
repos:
- alias: backend
repo_key: github.com/org/backend.git
branch: PROJ-123Notes:
gion.yamlis gion-managed and rewritten; don’t rely on ordering or comments.- You can edit
gion.yamldirectly (humans or AI). For interactive changes,gion manifest ...is convenient. - If you hand-edit, run
gion planbeforegion apply. If the filesystem is the source of truth, usegion import.
See CONTRIBUTING.md.
See SECURITY.md.
See LICENSE.
- @tasuku43