Git worktreeを宣言的に管理するCLI「gion」を作りました
TL;DR
Git worktree を並行運用して増えがちな「作業場所の増殖・迷子・削除不安」を、workspaceとPlanでまとめて扱うCLIが gion です。
-
gion.yaml→gion apply:Planで差分を見てから、worktreeの作成・更新・削除を反映する - workspace単位で複数repoのworktreeを束ね、タスク用の疑似モノレポ環境を素早く用意できる
-
giongoで workspace/worktree を検索して即移動し、「どこで作業してたっけ?」を減らす - 片付けは2系統:
gcは安全に自動回収、rmは dirty/unpushed/diverged を見ながら手動で消せる
はじめに
AIエージェントで並行開発を回すようになって、Git worktree に辿り着きました。
ただ、並行が増えるほど worktree も増えて、「どこに作ろう?」「移動がめんどい...」「これ削除していいんだっけ?」が増えてきました。
そこで、作る・移動・片付けをいい感じにまとめたくて gion を作りました。
gion は Git worktree を「タスク(workspace)単位」で扱う小さな CLI です。
gion.yaml をエディタまたはコマンドラインで理想状態に修正し、gion apply で差分(Plan)を確認しつつ作業場所を揃えます。
このGIFは、YAML直編集で入った作成・削除・更新を gion apply(内部で Plan 表示→確認→Apply)で反映する例です。

概要
コア機能は“作る/移動/片付け”の3つです。
- 作る:
gion.yamlを手動編集、またはgion manifest addで更新 →gion apply(Plan→確認→Apply) - 移動:
giongoで検索して移動(状態は変えない) - 片付け:
gion.yamlを手動編集、またはgion manifest gc/gion manifest rmで更新 →gion apply(Plan→確認→Apply)
仕組み(gion.yaml と manifestサブコマンドの関係)
gion の中心は gion.yaml です。ここに「こうなっていてほしい(望ましい状態)」を書きます。
gion manifest は、その gion.yaml を更新するための入口です(直接編集してもOKです)。
流れはシンプルで、gion.yaml を更新したら gion apply で反映します(Plan→確認→Apply)。
gion manifest ... は gion.yaml を更新するための入口で、デフォルトではそのまま apply まで進みます(更新だけにしたい場合は --no-apply)。
用語だけ補足すると、Git worktree はブランチ(や特定コミット)をチェックアウトした作業用ディレクトリです。一方、ここで言う workspace は「タスク単位の箱」で、その中に1つ以上のworktree(必要なら複数リポジトリのworktree)を束ねて扱います。
イメージとしては、だいたい次のようなディレクトリ構造になります。
GION_ROOT/
├─ gion.yaml # 望ましい状態(inventory)
├─ bare/ # 共有のbare repoストア
└─ workspaces/ # タスク単位のworkspace
├─ PROJ-123/ # workspace_id(タスク)
│ ├─ backend/ # worktree(repo: backend)
│ ├─ frontend/
│ └─ docs/
└─ PROJ-456/
└─ backend/
作る(ApplyでPlanを確認して、まとめて作る)
workspaceを「作る」操作は、gion manifest add コマンドか、gion.yaml の直接編集で行います。
作成は gion.yaml を更新して gion apply するだけで、更新方法が gion manifest add(対話式)か直編集かの違いです。
4つの作成mode
入口は repo / issue / review / preset の4つです。
始め方に合わせて入口を選べるだけで、行き着く先は同じで、最終的には gion.yaml に「こうしたい」を積んでいきます。

issue / review(まとめて積んで、一括で作る)
Issue(やPR)を複数選んで gion.yaml に積み、gion apply を実行して Plan で差分を確認してから反映します。

※ --issue / --review を使う場合は gh CLI が必要です(GitHub前提)。
repo(workspaceを一つ作る)
とにかく最短で1つ作るなら repo が一番シンプルです。リポジトリとworkspace IDを指定して追加し、gion apply の Plan で作成内容を確認してから反映します。

preset(複数repoをworkspaceに束ねる)
workspaceは「タスク単位の箱」なので、backend + frontend + docs みたいに複数repoを束ねたくなります。presetを作っておけば、次からはそれらをまとめて一つのworkspaceを作成できます。


YAML直編集
gion.yaml は直接編集も可能です。
たとえば ブランチ名を直したいとき、複数workspaceを同時に削除・作成したいとき、既存の定義を更新しつつ整理したいとき、などです。
直編集のあとに gion apply を実行すると、まず削除・作成・更新がまとめて Plan に出るので「何が起きるか」を落ち着いて確認できます。納得できたらそのまま Apply で反映できます。

移動する(workspace/worktreeを検索して移動する)
worktreeが増えてくると、「あの作業どこでやってたっけ?」を思い出す時間が増えてきます。
移動は giongo を使います(brew/miseで入れると gion と一緒に入ってきます)。
これは状態を一切変えず、目的地を選ぶところまでを担当します。
giongo は workspace と worktree をまとめて一覧し、検索で絞って選べます。
workspace を選べばその workspace ディレクトリへ、worktree を選べばそのリポジトリの作業ディレクトリへ移動できます。

削除する(gcで安全に回収して、rmは止まりながら消す)
worktreeが増えてくると、「これってもう消していいんだっけ?」と立ち止まることがあると思います。
gionはこの片付けを、gion manifest gc と gion manifest rm の2つに分けて扱います。
gion manifest gc(自動・保守的に回収)
gion manifest gc は「高い確度で安全に消せるものだけ」をまとめて候補にします。
たとえば、デフォルトブランチにマージ済みのものは回収できる一方で、判断が難しい(未コミット/未push/状態が読めない等)ものは基本的に対象外です。作っただけでコミットが無いworkspaceも、うっかり消さないように外します。

gion manifest rm(手動・ガードレール付きで消す)
一方 gion manifest rm は「人間が消したいもの」を選ぶための入口です。選択はインタラクティブにできて、最後に確認してから進めます。
選択画面では workspace に軽いタグが付きます([dirty] / [unpushed] / [diverged] / [unknown])。
-
dirty:未コミット変更がある(未追跡ファイルやコンフリクト含む) -
unpushed:upstream より手元が ahead(未pushのコミットがある) -
diverged:ahead かつ behind(手元と upstream が分岐している) -
unknown:upstream が無い / detached HEAD などで判定できない
たとえば dirty の場合、Plan 側で risk: dirty (...) や変更ファイルが見えるので、削除前にサッと確認できます(具体的な見え方はGIF参照)。

YAML直編集
削除も gion.yaml を直接編集して行えます。
直編集の場合も gion apply の Plan で “消えるもの” が明示され、最後に確認プロンプトが出るので、うっかり消しすぎる事故を減らせます(不安ならそこで n で止めればOKです)。
おわりに
インストール手順(Homebrew / mise 対応)と使い方はGitHubのREADMEにまとめています。よければ覗いて、手元で一度触ってみてください!
Discussion