vde-worktree 0.0.1 → 0.0.2

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.
package/README.ja.md ADDED
@@ -0,0 +1,343 @@
1
+ # vde-worktree
2
+
3
+ `vde-worktree` は、人間とコーディングエージェントの両方を想定した、安全な Git worktree 管理 CLI です。
4
+
5
+ 利用できるコマンド名:
6
+ - `vde-worktree`
7
+ - `vw`(エイリアス)
8
+
9
+ 英語版ドキュメント: `README.md`
10
+
11
+ ## このツールで解決すること
12
+
13
+ - worktree をリポジトリ配下 `.worktree/` に統一配置
14
+ - `switch` を冪等にして、同じ指示を繰り返しても破綻しにくくする
15
+ - `del` / `gone` の破壊操作に安全ガードを入れる
16
+ - Agent 向けに安定した JSON 出力を提供
17
+ - hooks ベースで運用を拡張しやすくする
18
+
19
+ ## 動作要件
20
+
21
+ - Node.js 22+
22
+ - pnpm 10+
23
+ - `fzf`(`cd` に必須)
24
+ - `gh`(PR merged 判定に任意)
25
+
26
+ ## インストール / ビルド
27
+
28
+ ```bash
29
+ pnpm install
30
+ pnpm run build
31
+ ```
32
+
33
+ 開発時の検証:
34
+
35
+ ```bash
36
+ pnpm run ci
37
+ ```
38
+
39
+ ## クイックスタート
40
+
41
+ ```bash
42
+ vw init
43
+ vw switch feature/foo
44
+ cd "$(vw cd)"
45
+ ```
46
+
47
+ ## 管理ディレクトリ
48
+
49
+ `vw init` 実行後に次を管理します:
50
+
51
+ - `.worktree/`(worktree 実体)
52
+ - `.vde/worktree/hooks/`
53
+ - `.vde/worktree/logs/`
54
+ - `.vde/worktree/locks/`
55
+ - `.vde/worktree/state/`
56
+
57
+ また `.git/info/exclude` に管理対象エントリを冪等で追記します。
58
+
59
+ ## 全体ルール
60
+
61
+ - 多くの書き込み系コマンドは `init` 実行済みが前提
62
+ - 書き込み時は内部の repo lock で排他制御
63
+ - `--json` 指定時、stdout は単一 JSON オブジェクトのみ
64
+ - ログや警告は stderr に出力
65
+ - 非TTYで unsafe 操作を行う場合は `--allow-unsafe` が必要
66
+
67
+ ## グローバルオプション
68
+
69
+ - `--json`: 機械可読の単一 JSON 出力
70
+ - `--verbose`: 詳細ログ
71
+ - `--no-hooks`: 今回のみ hook 無効化(`--allow-unsafe` 必須)
72
+ - `--allow-unsafe`: unsafe 操作の明示同意
73
+ - `--hook-timeout-ms <ms>`: hook timeout 上書き
74
+ - `--lock-timeout-ms <ms>`: repo lock timeout 上書き
75
+
76
+ ## コマンド詳細
77
+
78
+ ### `init`
79
+
80
+ ```bash
81
+ vw init
82
+ ```
83
+
84
+ 機能:
85
+ - `.worktree/` と `.vde/worktree/*` を作成
86
+ - `.git/info/exclude` に管理エントリ追加
87
+ - デフォルト hook テンプレートを作成
88
+
89
+ ### `list`
90
+
91
+ ```bash
92
+ vw list
93
+ vw list --json
94
+ ```
95
+
96
+ 機能:
97
+ - Git の porcelain 情報から worktree 一覧を取得
98
+ - branch/path/dirty/lock/merged/upstream を表示
99
+
100
+ ### `status`
101
+
102
+ ```bash
103
+ vw status
104
+ vw status feature/foo
105
+ vw status --json
106
+ ```
107
+
108
+ 機能:
109
+ - 対象 worktree 1件の状態を表示
110
+ - branch 指定なしなら現在 `cwd` から該当 worktree を解決
111
+
112
+ ### `path`
113
+
114
+ ```bash
115
+ vw path feature/foo
116
+ vw path feature/foo --json
117
+ ```
118
+
119
+ 機能:
120
+ - 指定 branch の絶対 worktree path を返す
121
+
122
+ ### `new`
123
+
124
+ ```bash
125
+ vw new
126
+ vw new feature/foo
127
+ ```
128
+
129
+ 機能:
130
+ - 新しい branch + worktree を `.worktree/` に作成
131
+ - branch 省略時は `wip-xxxxxx` を自動生成
132
+
133
+ ### `switch`
134
+
135
+ ```bash
136
+ vw switch feature/foo
137
+ ```
138
+
139
+ 機能:
140
+ - 指定 branch の worktree があれば再利用、なければ作成
141
+ - 冪等な branch 入口コマンド
142
+
143
+ ### `mv`
144
+
145
+ ```bash
146
+ vw mv feature/new-name
147
+ ```
148
+
149
+ 機能:
150
+ - 現在の非primary worktree の branch 名と path をリネーム
151
+ - detached HEAD では実行不可
152
+
153
+ ### `del`
154
+
155
+ ```bash
156
+ vw del
157
+ vw del feature/foo
158
+ vw del feature/foo --force-unmerged --allow-unpushed --allow-unsafe
159
+ ```
160
+
161
+ 機能:
162
+ - worktree と branch を安全に削除
163
+ - デフォルトで dirty / locked / unmerged(unknown含む) / unpushed(unknown含む) を拒否
164
+
165
+ 主な解除フラグ:
166
+ - `--force-dirty`
167
+ - `--allow-unpushed`
168
+ - `--force-unmerged`
169
+ - `--force-locked`
170
+ - `--force`(上記を一括有効)
171
+
172
+ ### `gone`
173
+
174
+ ```bash
175
+ vw gone
176
+ vw gone --apply
177
+ vw gone --json
178
+ ```
179
+
180
+ 機能:
181
+ - 一括クリーンアップ候補の抽出/削除
182
+ - デフォルトは dry-run
183
+ - `--apply` で削除実行
184
+
185
+ ### `get`
186
+
187
+ ```bash
188
+ vw get origin/feature/foo
189
+ ```
190
+
191
+ 機能:
192
+ - remote branch を fetch
193
+ - ローカル追跡 branch がなければ作成
194
+ - worktree を作成/再利用
195
+
196
+ ### `extract`
197
+
198
+ ```bash
199
+ vw extract --current
200
+ vw extract --current --stash
201
+ ```
202
+
203
+ 機能:
204
+ - primary worktree の現在 branch を `.worktree/` 側へ切り出し
205
+ - primary を base branch に戻す
206
+ - dirty 状態で切り出す場合は `--stash` を使用
207
+
208
+ 現状の制約:
209
+ - 実装は primary worktree の抽出フローが中心
210
+
211
+ ### `use`
212
+
213
+ ```bash
214
+ vw use feature/foo
215
+ vw use feature/foo --allow-agent --allow-unsafe
216
+ ```
217
+
218
+ 機能:
219
+ - primary worktree を指定 branch に checkout
220
+ - primary context を固定したい用途向け
221
+
222
+ 安全条件:
223
+ - primary が dirty なら拒否
224
+ - 非TTYでは `--allow-agent` と `--allow-unsafe` の両方が必要
225
+
226
+ ### `exec`
227
+
228
+ ```bash
229
+ vw exec feature/foo -- pnpm test
230
+ vw exec feature/foo --json -- pnpm test
231
+ ```
232
+
233
+ 機能:
234
+ - 指定 branch の worktree を `cwd` にしてコマンド実行
235
+ - shell 展開は使わず引数配列で実行
236
+
237
+ 終了コード:
238
+ - 子プロセス成功: `0`
239
+ - 子プロセス失敗: `21`(JSON では `CHILD_PROCESS_FAILED`)
240
+
241
+ ### `invoke`
242
+
243
+ ```bash
244
+ vw invoke post-switch
245
+ vw invoke pre-new -- --arg1 --arg2
246
+ ```
247
+
248
+ 機能:
249
+ - `pre-*` / `post-*` hook を手動実行
250
+ - hook デバッグ用
251
+
252
+ ### `copy`
253
+
254
+ ```bash
255
+ vw copy .envrc .claude/settings.local.json
256
+ ```
257
+
258
+ 機能:
259
+ - repo 相対パスのファイル/ディレクトリを target worktree にコピー
260
+ - 主に hook 内で `WT_WORKTREE_PATH` と合わせて使う想定
261
+
262
+ ### `link`
263
+
264
+ ```bash
265
+ vw link .envrc
266
+ vw link .envrc --no-fallback
267
+ ```
268
+
269
+ 機能:
270
+ - target worktree 側に symlink を作成
271
+ - Windows では `--no-fallback` がない場合、copy にフォールバック可
272
+
273
+ ### `lock` / `unlock`
274
+
275
+ ```bash
276
+ vw lock feature/foo --owner codex --reason "agent in progress"
277
+ vw unlock feature/foo --owner codex
278
+ vw unlock feature/foo --force
279
+ ```
280
+
281
+ 機能:
282
+ - `lock`: `.vde/worktree/locks/` に lock 情報を保存
283
+ - `unlock`: lock を解除(owner 不一致時は `--force` 必須)
284
+
285
+ ### `cd`
286
+
287
+ ```bash
288
+ cd "$(vw cd)"
289
+ ```
290
+
291
+ 機能:
292
+ - `fzf` で worktree を対話選択
293
+ - 選択した絶対 path を stdout に出力
294
+
295
+ ## merged 判定(ローカル + PR)
296
+
297
+ 各 worktree で次を評価します:
298
+
299
+ - `merged.byAncestry`: ローカル履歴判定(`git merge-base --is-ancestor`)
300
+ - `merged.byPR`: GitHub PR merged 判定(`gh`)
301
+ - `merged.overall`: 最終判定
302
+
303
+ `overall` ポリシー:
304
+
305
+ - `byPR === true` -> `overall = true`
306
+ - `byPR === false` -> `overall = false`
307
+ - `byPR === null` -> `byAncestry` にフォールバック
308
+
309
+ `byPR` が `null` になる例:
310
+ - `gh` 未導入
311
+ - `gh auth` 未設定
312
+ - API 失敗
313
+ - `git config vde-worktree.enableGh false`
314
+
315
+ ## JSON 契約
316
+
317
+ `--json` 指定時、stdout は常に単一 JSON オブジェクトです。
318
+
319
+ 共通成功フィールド:
320
+ - `schemaVersion`
321
+ - `command`
322
+ - `status`
323
+ - `repoRoot`
324
+
325
+ エラー時:
326
+ - `status: "error"`
327
+ - `code`
328
+ - `message`
329
+ - `details`
330
+
331
+ ## 設定キー(git config)
332
+
333
+ - `vde-worktree.baseBranch`
334
+ - `vde-worktree.baseRemote`
335
+ - `vde-worktree.enableGh`
336
+ - `vde-worktree.hooksEnabled`
337
+ - `vde-worktree.hookTimeoutMs`
338
+ - `vde-worktree.lockTimeoutMs`
339
+ - `vde-worktree.staleLockTTLSeconds`
340
+
341
+ ## 現在のスコープ
342
+
343
+ - Ink ベースの `tui` は未実装
package/README.md CHANGED
@@ -1,45 +1,341 @@
1
1
  # vde-worktree
2
2
 
3
- ## ⚠️ IMPORTANT NOTICE ⚠️
3
+ `vde-worktree` is a safe Git worktree manager designed for both humans and coding agents.
4
4
 
5
- **This package is created solely for the purpose of setting up OIDC (OpenID Connect) trusted publishing with npm.**
5
+ It installs two command names:
6
+ - `vde-worktree`
7
+ - `vw` (alias)
6
8
 
7
- This is **NOT** a functional package and contains **NO** code or functionality beyond the OIDC setup configuration.
9
+ Japanese documentation: [README.ja.md](./README.ja.md)
8
10
 
9
- ## Purpose
11
+ ## Goals
10
12
 
11
- This package exists to:
12
- 1. Configure OIDC trusted publishing for the package name `vde-worktree`
13
- 2. Enable secure, token-less publishing from CI/CD workflows
14
- 3. Establish provenance for packages published under this name
13
+ - Keep all worktrees in one repo-local location: `.worktree/`
14
+ - Provide idempotent branch-to-worktree operations
15
+ - Prevent accidental destructive actions by default
16
+ - Expose stable JSON output for automation
17
+ - Support hook-driven customization
15
18
 
16
- ## What is OIDC Trusted Publishing?
19
+ ## Requirements
17
20
 
18
- OIDC trusted publishing allows package maintainers to publish packages directly from their CI/CD workflows without needing to manage npm access tokens. Instead, it uses OpenID Connect to establish trust between the CI/CD provider (like GitHub Actions) and npm.
21
+ - Node.js 22+
22
+ - pnpm 10+
23
+ - `fzf` (required for `cd`)
24
+ - `gh` (optional, for PR-based merge status)
19
25
 
20
- ## Setup Instructions
26
+ ## Install / Build
21
27
 
22
- To properly configure OIDC trusted publishing for this package:
28
+ ```bash
29
+ pnpm install
30
+ pnpm run build
31
+ ```
23
32
 
24
- 1. Go to [npmjs.com](https://www.npmjs.com/) and navigate to your package settings
25
- 2. Configure the trusted publisher (e.g., GitHub Actions)
26
- 3. Specify the repository and workflow that should be allowed to publish
27
- 4. Use the configured workflow to publish your actual package
33
+ Validate locally:
28
34
 
29
- ## DO NOT USE THIS PACKAGE
35
+ ```bash
36
+ pnpm run ci
37
+ ```
30
38
 
31
- This package is a placeholder for OIDC configuration only. It:
32
- - Contains no executable code
33
- - Provides no functionality
34
- - Should not be installed as a dependency
35
- - Exists only for administrative purposes
39
+ ## Quick Start
36
40
 
37
- ## More Information
41
+ ```bash
42
+ vw init
43
+ vw switch feature/foo
44
+ cd "$(vw cd)"
45
+ ```
38
46
 
39
- For more details about npm's trusted publishing feature, see:
40
- - [npm Trusted Publishing Documentation](https://docs.npmjs.com/generating-provenance-statements)
41
- - [GitHub Actions OIDC Documentation](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect)
47
+ ## Managed Directories
42
48
 
43
- ---
49
+ After `vw init`, the tool manages:
44
50
 
45
- **Maintained for OIDC setup purposes only**
51
+ - `.worktree/` (worktree roots)
52
+ - `.vde/worktree/hooks/`
53
+ - `.vde/worktree/logs/`
54
+ - `.vde/worktree/locks/`
55
+ - `.vde/worktree/state/`
56
+
57
+ `init` updates `.git/info/exclude` idempotently.
58
+
59
+ ## Global Behavior
60
+
61
+ - Most write commands require prior `init`.
62
+ - Write commands are protected by an internal repository lock.
63
+ - `--json` prints exactly one JSON object to stdout.
64
+ - Logs and warnings are written to stderr.
65
+ - Non-TTY unsafe overrides require `--allow-unsafe`.
66
+
67
+ ## Global Options
68
+
69
+ - `--json`: machine-readable single-object output
70
+ - `--verbose`: verbose logging
71
+ - `--no-hooks`: disable hooks for this run (requires `--allow-unsafe`)
72
+ - `--allow-unsafe`: explicit unsafe override
73
+ - `--hook-timeout-ms <ms>`: hook timeout override
74
+ - `--lock-timeout-ms <ms>`: repository lock timeout override
75
+
76
+ ## Command Guide
77
+
78
+ ### `init`
79
+
80
+ ```bash
81
+ vw init
82
+ ```
83
+
84
+ What it does:
85
+ - Creates `.worktree/` and `.vde/worktree/*`
86
+ - Appends managed entries to `.git/info/exclude`
87
+ - Creates default hook templates
88
+
89
+ ### `list`
90
+
91
+ ```bash
92
+ vw list
93
+ vw list --json
94
+ ```
95
+
96
+ What it does:
97
+ - Lists all worktrees from Git porcelain output
98
+ - Includes metadata such as branch, path, dirty, lock, merged, and upstream status
99
+
100
+ ### `status`
101
+
102
+ ```bash
103
+ vw status
104
+ vw status feature/foo
105
+ vw status --json
106
+ ```
107
+
108
+ What it does:
109
+ - Shows one worktree state
110
+ - Without branch argument, resolves current worktree from current `cwd`
111
+
112
+ ### `path`
113
+
114
+ ```bash
115
+ vw path feature/foo
116
+ vw path feature/foo --json
117
+ ```
118
+
119
+ What it does:
120
+ - Resolves and returns the absolute worktree path for the target branch
121
+
122
+ ### `new`
123
+
124
+ ```bash
125
+ vw new
126
+ vw new feature/foo
127
+ ```
128
+
129
+ What it does:
130
+ - Creates a new branch + worktree under `.worktree/`
131
+ - Without argument, generates `wip-xxxxxx`
132
+
133
+ ### `switch`
134
+
135
+ ```bash
136
+ vw switch feature/foo
137
+ ```
138
+
139
+ What it does:
140
+ - Idempotent branch entrypoint
141
+ - Reuses existing worktree if present, otherwise creates one
142
+
143
+ ### `mv`
144
+
145
+ ```bash
146
+ vw mv feature/new-name
147
+ ```
148
+
149
+ What it does:
150
+ - Renames current non-primary worktree branch and moves its directory
151
+ - Requires branch checkout (not detached HEAD)
152
+
153
+ ### `del`
154
+
155
+ ```bash
156
+ vw del
157
+ vw del feature/foo
158
+ vw del feature/foo --force-unmerged --allow-unpushed --allow-unsafe
159
+ ```
160
+
161
+ What it does:
162
+ - Removes worktree and branch safely
163
+ - By default, rejects dirty, locked, unmerged/unknown, or unpushed/unknown states
164
+
165
+ Useful force flags:
166
+ - `--force-dirty`
167
+ - `--allow-unpushed`
168
+ - `--force-unmerged`
169
+ - `--force-locked`
170
+ - `--force` (enables all force flags)
171
+
172
+ ### `gone`
173
+
174
+ ```bash
175
+ vw gone
176
+ vw gone --apply
177
+ vw gone --json
178
+ ```
179
+
180
+ What it does:
181
+ - Bulk cleanup candidate finder/remover
182
+ - Default mode is dry-run
183
+ - `--apply` actually deletes eligible branches/worktrees
184
+
185
+ ### `get`
186
+
187
+ ```bash
188
+ vw get origin/feature/foo
189
+ ```
190
+
191
+ What it does:
192
+ - Fetches remote branch
193
+ - Creates tracking local branch when missing
194
+ - Creates/reuses local worktree
195
+
196
+ ### `extract`
197
+
198
+ ```bash
199
+ vw extract --current
200
+ vw extract --current --stash
201
+ ```
202
+
203
+ What it does:
204
+ - Extracts current primary worktree branch into `.worktree/`
205
+ - Switches primary worktree back to base branch
206
+ - `--stash` allows extraction when primary is dirty
207
+
208
+ Current limitation:
209
+ - Implementation currently supports primary worktree extraction flow.
210
+
211
+ ### `use`
212
+
213
+ ```bash
214
+ vw use feature/foo
215
+ vw use feature/foo --allow-agent --allow-unsafe
216
+ ```
217
+
218
+ What it does:
219
+ - Checks out the target branch in the primary worktree
220
+ - Intended for human workflows where primary context must be fixed
221
+
222
+ Safety:
223
+ - Rejects dirty primary worktree
224
+ - In non-TTY mode, requires `--allow-agent` and `--allow-unsafe`
225
+
226
+ ### `exec`
227
+
228
+ ```bash
229
+ vw exec feature/foo -- pnpm test
230
+ vw exec feature/foo --json -- pnpm test
231
+ ```
232
+
233
+ What it does:
234
+ - Executes command inside the target branch worktree path
235
+ - Does not use shell expansion
236
+
237
+ Exit behavior:
238
+ - Child success => `0`
239
+ - Child failure => `21` (`CHILD_PROCESS_FAILED` in JSON mode)
240
+
241
+ ### `invoke`
242
+
243
+ ```bash
244
+ vw invoke post-switch
245
+ vw invoke pre-new -- --arg1 --arg2
246
+ ```
247
+
248
+ What it does:
249
+ - Manually invokes `pre-*` / `post-*` hook scripts
250
+ - Useful for debugging hook behavior
251
+
252
+ ### `copy`
253
+
254
+ ```bash
255
+ vw copy .envrc .claude/settings.local.json
256
+ ```
257
+
258
+ What it does:
259
+ - Copies repo-relative files/dirs from repo root into target worktree
260
+ - Primarily intended for hook usage with `WT_WORKTREE_PATH`
261
+
262
+ ### `link`
263
+
264
+ ```bash
265
+ vw link .envrc
266
+ vw link .envrc --no-fallback
267
+ ```
268
+
269
+ What it does:
270
+ - Creates symlink in target worktree pointing to repo-root file
271
+ - On Windows, can fallback to copy unless `--no-fallback`
272
+
273
+ ### `lock` / `unlock`
274
+
275
+ ```bash
276
+ vw lock feature/foo --owner codex --reason "agent in progress"
277
+ vw unlock feature/foo --owner codex
278
+ vw unlock feature/foo --force
279
+ ```
280
+
281
+ What they do:
282
+ - `lock` writes lock metadata under `.vde/worktree/locks/`
283
+ - `unlock` clears lock, enforcing owner match unless `--force`
284
+
285
+ ### `cd`
286
+
287
+ ```bash
288
+ cd "$(vw cd)"
289
+ ```
290
+
291
+ What it does:
292
+ - Interactive worktree picker via `fzf`
293
+ - Prints selected absolute path to stdout
294
+
295
+ ## Merge Status (Local + PR)
296
+
297
+ Each worktree reports:
298
+
299
+ - `merged.byAncestry`: local ancestry check (`git merge-base --is-ancestor <branch> <baseBranch>`)
300
+ - `merged.byPR`: PR-based merged check via GitHub CLI
301
+ - `merged.overall`: final decision
302
+
303
+ Overall policy:
304
+
305
+ - `byPR === true` => `overall = true`
306
+ - `byPR === false` => `overall = false`
307
+ - `byPR === null` => fallback to `byAncestry`
308
+
309
+ `byPR` becomes `null` when PR lookup is unavailable (for example: `gh` missing, auth missing, API error, or `vde-worktree.enableGh=false`).
310
+
311
+ ## JSON Contract
312
+
313
+ With `--json`, stdout always emits exactly one JSON object.
314
+
315
+ Common success fields:
316
+ - `schemaVersion`
317
+ - `command`
318
+ - `status`
319
+ - `repoRoot`
320
+
321
+ Error shape:
322
+ - `status: "error"`
323
+ - `code`
324
+ - `message`
325
+ - `details`
326
+
327
+ ## Configuration Keys
328
+
329
+ Configured via `git config`:
330
+
331
+ - `vde-worktree.baseBranch`
332
+ - `vde-worktree.baseRemote`
333
+ - `vde-worktree.enableGh`
334
+ - `vde-worktree.hooksEnabled`
335
+ - `vde-worktree.hookTimeoutMs`
336
+ - `vde-worktree.lockTimeoutMs`
337
+ - `vde-worktree.staleLockTTLSeconds`
338
+
339
+ ## Current Scope
340
+
341
+ - Ink-based `tui` is not implemented yet.