@n-seiji/nuthatch 0.1.2 → 0.1.4

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 +174 -0
  2. package/README.md +45 -15
  3. package/dist/cli.js +3465 -43705
  4. package/package.json +2 -6
package/README.ja.md ADDED
@@ -0,0 +1,174 @@
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
+ ## トラブルシューティング
141
+
142
+ `hop: git executable not found. Looked in: …` は git のバイナリを見つけられ
143
+ なかったという意味。hop は `PATH` の絶対パスエントリを順に探し、その後
144
+ `/opt/homebrew/bin`, `/usr/local/bin`, `/usr/bin`, `/bin` を見る。git が
145
+ それ以外の場所にある場合は、直接指定する:
146
+
147
+ ```sh
148
+ export HOP_GIT=/path/to/git
149
+ ```
150
+
151
+ ## Agent skill (Claude Code / Codex plugin)
152
+
153
+ このリポジトリは plugin marketplace も兼ねており、
154
+ [`using-hop`](skills/using-hop/SKILL.md) skill を配布する —
155
+ coding agent に `hop` を非対話・安全に扱う方法を教える skill。
156
+
157
+ ```sh
158
+ # Claude Code
159
+ /plugin marketplace add n-seiji/nuthatch
160
+ /plugin install hop@nuthatch
161
+
162
+ # Codex
163
+ codex plugin marketplace add n-seiji/nuthatch
164
+ codex plugin install hop
165
+ ```
166
+
167
+ ## Docs
168
+
169
+ - [docs/design.md](docs/design.md) — 設計書 (全文)
170
+ - [AGENTS.md](AGENTS.md) — このリポジトリで作業する coding agent 向けガイド
171
+
172
+ ## License
173
+
174
+ 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,15 +31,22 @@ 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)
36
39
 
37
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`)
38
42
  hop --help # print usage (also -h / hop help)
39
43
  ```
40
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
+
41
50
  ### Interactive picker
42
51
 
43
52
  The picker groups candidates into sections — existing worktrees (root first)
@@ -50,11 +59,11 @@ shortened paths:
50
59
  ○ feat/picker managed …/_worktree/feat__picker
51
60
  ● codex/fix-x ext …/.claude/worktrees/x
52
61
 
53
- BRANCHES — Enter で worktree 作成
62
+ BRANCHES — Enter creates a worktree
54
63
  + feat/idea local
55
64
  + origin/hotfix remote
56
65
 
57
- (●=dirty ○=clean +=未作成)
66
+ (●=dirty ○=clean +=not created)
58
67
  ```
59
68
 
60
69
  A section (header included) disappears entirely when it has no candidates —
@@ -85,8 +94,8 @@ since the two can't fit side by side.
85
94
  |---|---|
86
95
  | `Enter` | cd into the selected candidate |
87
96
  | `Tab`, `→`, `Ctrl+L`, `Ctrl+F` | Open the action panel for the selected candidate (cd / delete / switch root here) |
88
- | `Ctrl+X` | Delete the selected worktree (asks y/N first) |
89
- | `Ctrl+R` | Switch the root clone to the selected branch, immediately |
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) |
90
99
  | `↑`/`↓`, `Ctrl+P`/`Ctrl+N`, `Ctrl+K`/`Ctrl+J` | Move the selection (arrow, emacs, and vim keys all work side by side) |
91
100
  | `Esc` | Cancel quietly — exit 0, stdout stays empty (the shell wrapper just doesn't cd) |
92
101
  | `Ctrl+C` | Cancel like an interrupt — exit 130, same as a real SIGINT |
@@ -97,8 +106,11 @@ highlighted action, `c`/`d`/`r` to run cd/delete/switch-root directly, and
97
106
  `Esc`, `Tab`, `←`, or `Ctrl+H` to close it back to the list (`←`/`Ctrl+H`
98
107
  mirror the `→`/`Ctrl+L`/`Ctrl+F` that open it; `Tab` toggles either way —
99
108
  handy on terminals like Ghostty that remap a chord such as Cmd+K to Tab). `delete`
100
- only appears for a worktree nuthatch manages (`managed`); `switch root
101
- here` doesn't appear on the root worktree itself. Deleting reloads the
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
102
114
  candidate list so you can keep deleting without leaving the picker; cd and
103
115
  switch-root exit and print the resulting path, per hop's stdout contract.
104
116
 
@@ -114,12 +126,19 @@ eval "$(hop init zsh)"
114
126
  > Not released yet — no version has been published or tagged. Once the first
115
127
  > `v*` tag ships, the options below will work as described.
116
128
 
117
- ```sh
118
- npm i -g @n-seiji/nuthatch # or: bunx @n-seiji/nuthatch
119
- 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.
120
133
 
121
- # 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:
122
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
123
142
  ```
124
143
 
125
144
  The install script places `hop` in `~/.local/bin` (override with
@@ -127,6 +146,17 @@ The install script places `hop` in `~/.local/bin` (override with
127
146
  specific version with `HOP_VERSION=vX.Y.Z`. Linux arm64 has no prebuilt
128
147
  binary yet — use the npm install instead.
129
148
 
149
+ ## Troubleshooting
150
+
151
+ `hop: git executable not found. Looked in: …` means hop could not find a git
152
+ binary. hop searches every absolute entry in `PATH`, then `/opt/homebrew/bin`,
153
+ `/usr/local/bin`, `/usr/bin` and `/bin`. If your git lives somewhere else,
154
+ point hop straight at it:
155
+
156
+ ```sh
157
+ export HOP_GIT=/path/to/git
158
+ ```
159
+
130
160
  ## Agent skill (Claude Code / Codex plugin)
131
161
 
132
162
  This repo doubles as a plugin marketplace that ships the
@@ -145,7 +175,7 @@ codex plugin install hop
145
175
 
146
176
  ## Docs
147
177
 
148
- - [docs/design.md](docs/design.md) — full design document (Japanese)
178
+ - [docs/design.md](docs/design.md) — full design document
149
179
  - [AGENTS.md](AGENTS.md) — guide for coding agents working on this repo
150
180
 
151
181
  ## License