@n-seiji/nuthatch 0.1.0 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/README.ja.md +163 -0
  2. package/README.md +95 -9
  3. package/dist/cli.js +3471 -43161
  4. package/package.json +1 -5
package/README.ja.md ADDED
@@ -0,0 +1,163 @@
1
+ [English](README.md)
2
+
3
+ <p align="center">
4
+ <img src="docs/assets/logo.png" alt="nuthatch — hop between git worktrees" width="560">
5
+ </p>
6
+
7
+ <p align="center"><em>ナットハッチが木々を渡るように、git worktree 間を hop する。</em></p>
8
+
9
+ `nuthatch` は zero-setup な git worktree manager。単一コマンド **`hop`** が、
10
+ 任意の branch の worktree へジャンプする — 存在しなければその場で作成する。
11
+ 人間 (対話的 picker) と AI coding agent (非対話、`--json`) の両方に対応。
12
+
13
+ ## なぜ
14
+
15
+ - **Zero setup** — 状態ファイルなし、init コマンドなし。
16
+ `git worktree list --porcelain` が唯一の正本。任意のリポジトリで即動く。
17
+ - **Convention over config** — worktree は常に
18
+ `<root の親>/_worktree/<repo>/<branch>` に置かれるため、一覧やパスの推測が
19
+ 速く予測可能。
20
+ - **AI native** — 全コマンドが非対話で完結し、`--json` はどこでも使え、path
21
+ は stdout・ログは stderr に出て、エラーは次の一手を教えてくれる。
22
+
23
+ ## 使い方
24
+
25
+ ```sh
26
+ hop # worktree/branch を対話的に選んで cd
27
+ hop feat/foo # feat/foo の worktree へ cd — 未作成ならその場で作成
28
+ hop root # root clone へ cd
29
+ hop - # 直前の worktree へ戻る
30
+
31
+ hop ls [--json] # worktree 一覧 (dirty, ahead/behind, kind)
32
+ hop rm <branch> # worktree を削除 (branch は残す) — managed/external 問わず、dirty には --force が必要
33
+ hop clean # ゴミ worktree を自動判定して削除 (managed のみ)
34
+ hop root <branch> # root clone を一時的に切替 (動作確認用) —
35
+ # 対象 branch が他所で checkout 済みなら、clean かつ unlocked な holder を swap する
36
+ hop root - # root clone を元に戻す (root の branch のみ; swap で detach した holder はそのまま)
37
+
38
+ hop -- <branch> # 予約コマンドと被る branch 名をエスケープ
39
+ # (`hop` 自体と同名の branch (例: `hop -- hop`) にも必要)
40
+ hop --help # usage を表示 (-h / hop help でも同じ)
41
+ ```
42
+
43
+ 同じ branch が複数の worktree で checkout されている場合、branch だけを指定する
44
+ `hop rm` は削除対象を推測せず拒否する。対話的 picker は選択した path を、lock 内の
45
+ 最終安全確認まで保持する。
46
+
47
+ ### 対話的 picker
48
+
49
+ picker は候補を section に分けて表示する — 既存の worktree (root が先頭) と
50
+ 未作成の branch — ステータスマーカー・整列した列・短縮パス付きで:
51
+
52
+ ```
53
+ WORKTREES
54
+ ❯ ● main root ~/ghq/.../nuthatch
55
+ ○ feat/picker managed …/_worktree/feat__picker
56
+ ● codex/fix-x ext …/.claude/worktrees/x
57
+
58
+ BRANCHES — Enter creates a worktree
59
+ + feat/idea local
60
+ + origin/hotfix remote
61
+
62
+ (●=dirty ○=clean +=not created)
63
+ ```
64
+
65
+ candidate が 0 件になった section は (header ごと) 丸ごと消える —
66
+ 検索クエリで絞り込んだ結果 0 件になった場合も同様。
67
+
68
+ 各 section 内の順序は insertion 順ではなく固定: WORKTREES は root が先頭、
69
+ 次に managed、その次に external (各グループ内は branch 名昇順、detached
70
+ HEAD の worktree はグループ内最後); BRANCHES は remote より local が先
71
+ (各グループ内は branch 名昇順)。これは検索フィルタ中も保たれる —
72
+ 絞り込んでも残った項目の並びは変わらない。BRANCHES の行は dim 表示になり、
73
+ ○/●/+ マーカーに加えて「既に worktree」か「まだ未作成」かが一目でわかる。
74
+
75
+ picker は terminal の alternate screen buffer (fzf や vim と同じ仕組み) で
76
+ 動くため、scrollback 履歴に残らない — 実行のたびに画面を上書きし、
77
+ どう終了しても (選択、Esc/Ctrl-C、割り込み) shell の画面をきれいに復元する。
78
+
79
+ ### 対話的 picker のキー
80
+
81
+ action panel は候補一覧の隣に列として表示される (overlay ではない) ので、
82
+ action を選ぶ間も一覧が見え続ける。60 列未満の terminal では横に並べられ
83
+ ないため、一覧の下にスタックする形にフォールバックする。
84
+
85
+ | キー | 動作 |
86
+ |---|---|
87
+ | `Enter` | 選択中の候補へ cd |
88
+ | `Tab`, `→`, `Ctrl+L`, `Ctrl+F` | 選択中の候補の action panel を開く (ここで cd / 削除 / root 切替) |
89
+ | `Ctrl+X` | 選択中の worktree を削除 (`external` は先に y/N を確認) |
90
+ | `Ctrl+R` | root clone を選択中の branch へ切替 (`external` は先に y/N を確認) |
91
+ | `↑`/`↓`, `Ctrl+P`/`Ctrl+N`, `Ctrl+K`/`Ctrl+J` | 選択を移動 (矢印・emacs・vim キーがすべて併用可) |
92
+ | `Esc` | 静かにキャンセル — exit 0、stdout は空のまま (shell wrapper は cd しない) |
93
+ | `Ctrl+C` | 割り込みとしてキャンセル — exit 130、実際の SIGINT と同じ |
94
+
95
+ action panel 内: 同じ上下移動キー (左右は閉じる操作に予約されており、
96
+ 移動としては使われない)、`Enter` でハイライト中の action を実行、
97
+ `c`/`d`/`r` で cd/delete/switch-root を直接実行、`Esc`、`Tab`、`←`、
98
+ `Ctrl+H` で一覧に戻る (`←`/`Ctrl+H` は開く操作の `→`/`Ctrl+L`/`Ctrl+F` と
99
+ 対になっている; `Tab` はどちらの状態からでもトグルする — Ghostty のように
100
+ Cmd+K のようなキーの組み合わせを Tab に remap する terminal で便利)。
101
+ `delete` はすでに作成済みの worktree (`managed` / `external`) すべてに
102
+ 表示される (`external` の削除は panel からでも Ctrl+X からでも必ず y/N
103
+ を確認する); `switch root here` は root worktree 自身には表示されず、
104
+ `external` worktree に対しては HEAD を detach する可能性があるため
105
+ 同じく先に y/N を確認する。削除すると候補一覧が再読み込みされ、picker を
106
+ 抜けずに削除を続けられる; cd と switch-root は終了して結果の path を
107
+ 出力する (hop の stdout 契約どおり)。
108
+
109
+ Shell 統合 (自動 `cd`):
110
+
111
+ ```sh
112
+ # ~/.zshrc
113
+ eval "$(hop init zsh)"
114
+ ```
115
+
116
+ ## Install
117
+
118
+ > まだリリースされていない — バージョンは publish も tag もされていない。
119
+ > 最初の `v*` tag が出た後は、以下の選択肢が記載どおりに動く。
120
+
121
+ 推奨: GitHub Release のバイナリ (bun 製、mise なら
122
+ `mise use github:n-seiji/nuthatch`)。npm 版は Node で動くため git 呼び出しが遅い
123
+ (hop ls ~400ms vs ~60ms) — CI や頻繁な呼び出しにはバイナリを使う。
124
+
125
+ ```sh
126
+ # ビルド済みバイナリ (macOS arm64/x64, Linux x64) — Node.js 不要、最速:
127
+ curl -fsSL https://raw.githubusercontent.com/n-seiji/nuthatch/main/install.sh | sh
128
+ mise use github:n-seiji/nuthatch # mise、GitHub Release のバイナリ経由
129
+
130
+ # npm (低速: Node 経由で git を呼ぶ — バイナリの hop ls ~60ms に対し ~400ms)
131
+ npm i -g @n-seiji/nuthatch # または: bunx @n-seiji/nuthatch
132
+ mise use -g npm:@n-seiji/nuthatch # mise、npm 経由
133
+ ```
134
+
135
+ install script は `hop` を `~/.local/bin` に置き (`HOP_INSTALL_DIR` で
136
+ 上書き可)、常に最新の GitHub Release を取得する; 特定バージョンに固定する
137
+ には `HOP_VERSION=vX.Y.Z` を使う。Linux arm64 はビルド済みバイナリが
138
+ まだないため、npm install を使う。
139
+
140
+ ## Agent skill (Claude Code / Codex plugin)
141
+
142
+ このリポジトリは plugin marketplace も兼ねており、
143
+ [`using-hop`](skills/using-hop/SKILL.md) skill を配布する —
144
+ coding agent に `hop` を非対話・安全に扱う方法を教える skill。
145
+
146
+ ```sh
147
+ # Claude Code
148
+ /plugin marketplace add n-seiji/nuthatch
149
+ /plugin install hop@nuthatch
150
+
151
+ # Codex
152
+ codex plugin marketplace add n-seiji/nuthatch
153
+ codex plugin install hop
154
+ ```
155
+
156
+ ## Docs
157
+
158
+ - [docs/design.md](docs/design.md) — 設計書 (全文)
159
+ - [AGENTS.md](AGENTS.md) — このリポジトリで作業する coding agent 向けガイド
160
+
161
+ ## License
162
+
163
+ GPL-3.0 — [LICENSE](LICENSE) 参照。
package/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ [日本語](README.ja.md)
2
+
1
3
  <p align="center">
2
4
  <img src="docs/assets/logo.png" alt="nuthatch — hop between git worktrees" width="560">
3
5
  </p>
@@ -29,11 +31,88 @@ hop root # cd into the root clone
29
31
  hop - # cd back to the previous worktree
30
32
 
31
33
  hop ls [--json] # list worktrees (dirty, ahead/behind, kind)
32
- hop rm <branch> # remove a worktree (branch is kept)
33
- hop clean # auto-detect and remove garbage worktrees
34
- hop root <branch> # temporarily switch the root clone (for verification)
35
- hop root - # switch the root clone back
34
+ hop rm <branch> # remove a worktree (branch is kept) — managed or external, dirty needs --force
35
+ hop clean # auto-detect and remove garbage worktrees (managed only)
36
+ hop root <branch> # temporarily switch the root clone (for verification) —
37
+ # swaps out a clean, unlocked holder if the branch is checked out elsewhere
38
+ hop root - # switch the root clone back (only root's branch; a swapped-out holder stays detached)
39
+
40
+ hop -- <branch> # escape a branch name that collides with a reserved command
41
+ # (also required for a branch named the same as your `hop` binary/alias, e.g. `hop -- hop`)
42
+ hop --help # print usage (also -h / hop help)
43
+ ```
44
+
45
+ If Git reports the same branch checked out in multiple worktrees, the
46
+ branch-only `hop rm` command refuses rather than guessing which path to
47
+ remove. The interactive picker keeps the selected path through the final
48
+ lock-protected safety check.
49
+
50
+ ### Interactive picker
51
+
52
+ The picker groups candidates into sections — existing worktrees (root first)
53
+ and not-yet-created branches — with a status marker, aligned columns, and
54
+ shortened paths:
55
+
36
56
  ```
57
+ WORKTREES
58
+ ❯ ● main root ~/ghq/.../nuthatch
59
+ ○ feat/picker managed …/_worktree/feat__picker
60
+ ● codex/fix-x ext …/.claude/worktrees/x
61
+
62
+ BRANCHES — Enter creates a worktree
63
+ + feat/idea local
64
+ + origin/hotfix remote
65
+
66
+ (●=dirty ○=clean +=not created)
67
+ ```
68
+
69
+ A section (header included) disappears entirely when it has no candidates —
70
+ including when a search query filters it down to zero.
71
+
72
+ Ordering within each section is fixed, not insertion order: WORKTREES puts
73
+ root first, then managed worktrees, then external ones (branch name
74
+ ascending within each group, detached-HEAD worktrees last within theirs);
75
+ BRANCHES puts local branches before remote ones (branch name ascending
76
+ within each group). This holds under search filtering too — narrowing the
77
+ list never reshuffles what's left. BRANCHES rows render dim so "already a
78
+ worktree" vs. "not created yet" reads at a glance, on top of the ○/●/+
79
+ markers.
80
+
81
+ The picker runs in the terminal's alternate screen buffer (the same
82
+ mechanism fzf and vim use), so it never gets pushed into your scrollback
83
+ history — each run paints over itself and cleanly restores your shell's
84
+ screen on exit, however it exits (selection, Esc/Ctrl-C, or an interrupt).
85
+
86
+ ### Interactive picker keys
87
+
88
+ The action panel renders as a column beside the candidate list (not an
89
+ overlay), so the list stays visible while you pick an action. On terminals
90
+ narrower than 60 columns it falls back to stacking below the list instead,
91
+ since the two can't fit side by side.
92
+
93
+ | Key | Action |
94
+ |---|---|
95
+ | `Enter` | cd into the selected candidate |
96
+ | `Tab`, `→`, `Ctrl+L`, `Ctrl+F` | Open the action panel for the selected candidate (cd / delete / switch root here) |
97
+ | `Ctrl+X` | Delete the selected worktree (asks y/N first for an `external` worktree) |
98
+ | `Ctrl+R` | Switch the root clone to the selected branch (asks y/N first for an `external` worktree) |
99
+ | `↑`/`↓`, `Ctrl+P`/`Ctrl+N`, `Ctrl+K`/`Ctrl+J` | Move the selection (arrow, emacs, and vim keys all work side by side) |
100
+ | `Esc` | Cancel quietly — exit 0, stdout stays empty (the shell wrapper just doesn't cd) |
101
+ | `Ctrl+C` | Cancel like an interrupt — exit 130, same as a real SIGINT |
102
+
103
+ Inside the action panel: the same up/down movement keys (left/right are
104
+ reserved for closing, so they never double as movement), `Enter` to run the
105
+ highlighted action, `c`/`d`/`r` to run cd/delete/switch-root directly, and
106
+ `Esc`, `Tab`, `←`, or `Ctrl+H` to close it back to the list (`←`/`Ctrl+H`
107
+ mirror the `→`/`Ctrl+L`/`Ctrl+F` that open it; `Tab` toggles either way —
108
+ handy on terminals like Ghostty that remap a chord such as Cmd+K to Tab). `delete`
109
+ appears for any already-created worktree (`managed` or `external` — deleting
110
+ an `external` one always asks y/N, whether from the panel or Ctrl+X); `switch
111
+ root here` doesn't appear on the root worktree itself, and also asks y/N
112
+ first for an `external` worktree, since it can detach that worktree's HEAD.
113
+ Deleting reloads the
114
+ candidate list so you can keep deleting without leaving the picker; cd and
115
+ switch-root exit and print the resulting path, per hop's stdout contract.
37
116
 
38
117
  Shell integration (auto-`cd`):
39
118
 
@@ -47,12 +126,19 @@ eval "$(hop init zsh)"
47
126
  > Not released yet — no version has been published or tagged. Once the first
48
127
  > `v*` tag ships, the options below will work as described.
49
128
 
50
- ```sh
51
- npm i -g @n-seiji/nuthatch # or: bunx @n-seiji/nuthatch
52
- mise use -g npm:@n-seiji/nuthatch # mise
129
+ Recommended: the GitHub Release binary (built with bun; via mise,
130
+ `mise use github:n-seiji/nuthatch`). The npm version runs on Node, so its git
131
+ calls are slower (hop ls ~400ms vs ~60ms) — prefer the binary for CI or
132
+ frequent invocations.
53
133
 
54
- # Prebuilt binary (macOS arm64/x64, Linux x64) — no Node.js required:
134
+ ```sh
135
+ # Prebuilt binary (macOS arm64/x64, Linux x64) — no Node.js required, fastest:
55
136
  curl -fsSL https://raw.githubusercontent.com/n-seiji/nuthatch/main/install.sh | sh
137
+ mise use github:n-seiji/nuthatch # mise, via the GitHub Release binary
138
+
139
+ # npm (slower: shells out to git via Node — hop ls ~400ms vs ~60ms for the binary)
140
+ npm i -g @n-seiji/nuthatch # or: bunx @n-seiji/nuthatch
141
+ mise use -g npm:@n-seiji/nuthatch # mise, via npm
56
142
  ```
57
143
 
58
144
  The install script places `hop` in `~/.local/bin` (override with
@@ -78,7 +164,7 @@ codex plugin install hop
78
164
 
79
165
  ## Docs
80
166
 
81
- - [docs/design.md](docs/design.md) — full design document (Japanese)
167
+ - [docs/design.md](docs/design.md) — full design document
82
168
  - [AGENTS.md](AGENTS.md) — guide for coding agents working on this repo
83
169
 
84
170
  ## License