@solaqua/gji 0.13.0 → 0.15.0

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 (45) hide show
  1. package/dist/application/worktree/go-resolution.js +5 -3
  2. package/dist/application/worktree/sources.d.ts +13 -4
  3. package/dist/application/worktree/sources.js +34 -13
  4. package/dist/cli/commands/clean.d.ts +4 -2
  5. package/dist/cli/commands/clean.js +338 -65
  6. package/dist/cli/commands/go.d.ts +2 -1
  7. package/dist/cli/commands/go.js +17 -13
  8. package/dist/cli/commands/hub.js +4 -1
  9. package/dist/cli/commands/warp.js +6 -4
  10. package/dist/cli/program.js +5 -0
  11. package/dist/domain/shared/concurrency.d.ts +1 -1
  12. package/dist/domain/shared/concurrency.js +6 -1
  13. package/dist/domain/worktree/path-filter.d.ts +13 -0
  14. package/dist/domain/worktree/path-filter.js +72 -0
  15. package/dist/domain/worktree/policy.d.ts +1 -0
  16. package/dist/domain/worktree/policy.js +1 -1
  17. package/dist/gji-bundle.mjs +746 -368
  18. package/dist/infrastructure/git/refs.js +3 -11
  19. package/dist/presentation/shell/completion.js +7 -2
  20. package/dist/presentation/worktree/picker.d.ts +9 -6
  21. package/dist/presentation/worktree/picker.js +19 -2
  22. package/man/man1/gji-back.1 +1 -1
  23. package/man/man1/gji-clean.1 +4 -1
  24. package/man/man1/gji-completion.1 +1 -1
  25. package/man/man1/gji-config.1 +1 -1
  26. package/man/man1/gji-doctor.1 +1 -1
  27. package/man/man1/gji-done.1 +1 -1
  28. package/man/man1/gji-go.1 +1 -1
  29. package/man/man1/gji-history.1 +1 -1
  30. package/man/man1/gji-init.1 +1 -1
  31. package/man/man1/gji-ls.1 +1 -1
  32. package/man/man1/gji-new.1 +1 -1
  33. package/man/man1/gji-open.1 +1 -1
  34. package/man/man1/gji-pr.1 +1 -1
  35. package/man/man1/gji-remove.1 +1 -1
  36. package/man/man1/gji-root.1 +1 -1
  37. package/man/man1/gji-run-hook.1 +1 -1
  38. package/man/man1/gji-status.1 +1 -1
  39. package/man/man1/gji-sync-files.1 +1 -1
  40. package/man/man1/gji-sync.1 +1 -1
  41. package/man/man1/gji-task.1 +1 -1
  42. package/man/man1/gji-undo.1 +1 -1
  43. package/man/man1/gji-warp.1 +1 -1
  44. package/man/man1/gji.1 +1 -1
  45. package/package.json +1 -1
@@ -64,17 +64,9 @@ async function resolveCachedRemoteDefaultBranch(cwd, remote) {
64
64
  return ref.startsWith(prefix) ? ref.slice(prefix.length) : undefined;
65
65
  }
66
66
  catch {
67
- try {
68
- const refs = await runGit(cwd, [
69
- "for-each-ref",
70
- "--format=%(refname:strip=3)",
71
- `refs/remotes/${remote}`,
72
- ]);
73
- return refs.split("\n").find((ref) => ref !== "HEAD");
74
- }
75
- catch {
76
- return undefined;
77
- }
67
+ // A remote branch list does not identify which branch is the default.
68
+ // Refuse to guess when the symbolic remote HEAD is unavailable.
69
+ return undefined;
78
70
  }
79
71
  }
80
72
  export async function readBranchLastCommitTimestamp(cwd, branch) {
@@ -221,7 +221,11 @@ _gji_completion() {
221
221
  COMPREPLY=( $(compgen -W "--compact --json --help" -- "$cur") )
222
222
  ;;
223
223
  clean)
224
- COMPREPLY=( $(compgen -W "-f --force --stale --dry-run --json --help" -- "$cur") )
224
+ if [ "\${COMP_WORDS[COMP_CWORD-1]}" = "--path" ]; then
225
+ COMPREPLY=( $(compgen -d -- "$cur") )
226
+ else
227
+ COMPREPLY=( $(compgen -W "-f --force --stale --path --dry-run --json --help" -- "$cur") )
228
+ fi
225
229
  ;;
226
230
  remove|rm)
227
231
  COMPREPLY=( $(compgen -W "$(__gji_worktree_branches) -f --force --dry-run --json --help" -- "$cur") )
@@ -454,6 +458,7 @@ complete -c gji -n '__fish_seen_subcommand_from ls' -l json -d 'print active wor
454
458
 
455
459
  complete -c gji -n '__fish_seen_subcommand_from clean' -s f -l force -d 'bypass prompts, force-remove dirty worktrees, and force-delete unmerged branches'
456
460
  complete -c gji -n '__fish_seen_subcommand_from clean' -l stale -d 'only target clean worktrees whose upstream is gone and branch is merged into the default branch'
461
+ complete -c gji -n '__fish_seen_subcommand_from clean' -l path -r -F -d 'only target worktrees under a directory or matching a path glob (repeatable)'
457
462
  complete -c gji -n '__fish_seen_subcommand_from clean' -l dry-run -d 'show what would be deleted without removing anything'
458
463
  complete -c gji -n '__fish_seen_subcommand_from clean' -l json -d 'emit JSON on success or error instead of human-readable output'
459
464
 
@@ -612,7 +617,7 @@ case "\${words[2]}" in
612
617
  _arguments '--compact[show only branch and path columns]' '--json[print active worktrees as JSON]'
613
618
  ;;
614
619
  clean)
615
- _arguments '(-f --force)'{-f,--force}'[bypass prompts, force-remove dirty worktrees, and force-delete unmerged branches]' '--stale[only target clean worktrees whose upstream is gone and branch is merged into the default branch]' '--dry-run[show what would be deleted without removing anything]' '--json[emit JSON on success or error instead of human-readable output]'
620
+ _arguments '(-f --force)'{-f,--force}'[bypass prompts, force-remove dirty worktrees, and force-delete unmerged branches]' '--stale[only target clean worktrees whose upstream is gone and branch is merged into the default branch]' '*--path[only target worktrees under a directory or matching a path glob]:pattern:_files' '--dry-run[show what would be deleted without removing anything]' '--json[emit JSON on success or error instead of human-readable output]'
616
621
  ;;
617
622
  remove|rm)
618
623
  _arguments '(-f --force)'{-f,--force}'[bypass prompts, force-remove a dirty worktree, and force-delete an unmerged branch]' '--dry-run[show what would be deleted without removing anything]' '--json[emit JSON on success or error instead of human-readable output]' '2:branch:->worktrees'
@@ -30,17 +30,20 @@ export interface WorktreePickerIO {
30
30
  }
31
31
  export interface WorktreePromptScope {
32
32
  label: string;
33
- toggle: () => Promise<WorktreePromptScopeResult>;
33
+ toggle: (signal?: AbortSignal) => Promise<WorktreePromptScopeResult>;
34
34
  toggleLabel: string;
35
35
  }
36
36
  export interface WorktreePromptScopeResult {
37
- entries: WorktreePromptEntry[];
38
37
  label: string;
38
+ metadata?: WorktreeMetadataMode;
39
+ sources: WorktreeSource[];
39
40
  toggleLabel: string;
40
41
  }
41
- export declare function buildWorktreePromptEntries(sources: WorktreeSource[], dependencies?: BuildWorktreePromptEntriesDependencies): Promise<WorktreePromptEntry[]>;
42
- export declare function promptForSingleWorktree(message: string, worktrees: WorktreePromptEntry[], io?: WorktreePickerIO & {
42
+ export interface WorktreePickerOptions extends WorktreePickerIO {
43
+ catalog?: WorktreeCatalogDependencies;
43
44
  scope?: WorktreePromptScope;
44
- }): Promise<string | null>;
45
- export declare function promptForMultipleWorktrees(message: string, worktrees: WorktreePromptEntry[], io?: WorktreePickerIO): Promise<string[] | null>;
45
+ }
46
+ export declare function buildWorktreePromptEntries(sources: WorktreeSource[], dependencies?: BuildWorktreePromptEntriesDependencies): Promise<WorktreePromptEntry[]>;
47
+ export declare function promptForSingleWorktree(message: string, worktrees: WorktreePromptEntry[], io?: WorktreePickerOptions): Promise<string | null>;
48
+ export declare function promptForMultipleWorktrees(message: string, worktrees: WorktreePromptEntry[], io?: WorktreePickerOptions): Promise<string[] | null>;
46
49
  export declare function formatWorktreeBranchLabel(branch: string | null, pullRequests?: PullRequestInfo[]): string;
@@ -33,6 +33,7 @@ export async function promptForSingleWorktree(message, worktrees, io = {}) {
33
33
  message,
34
34
  multiple: false,
35
35
  output: io.output,
36
+ catalog: io.catalog,
36
37
  scope: io.scope,
37
38
  });
38
39
  return typeof choice === "string" ? choice : null;
@@ -44,6 +45,8 @@ export async function promptForMultipleWorktrees(message, worktrees, io = {}) {
44
45
  message,
45
46
  multiple: true,
46
47
  output: io.output,
48
+ catalog: io.catalog,
49
+ scope: io.scope,
47
50
  });
48
51
  return Array.isArray(choice) ? choice : null;
49
52
  }
@@ -121,6 +124,7 @@ class SearchablePrompt {
121
124
  scope;
122
125
  scopeTogglePending = false;
123
126
  promptClosed = false;
127
+ cancellation = new AbortController();
124
128
  prompt;
125
129
  constructor(options, input, output) {
126
130
  this.options = options;
@@ -189,10 +193,15 @@ class SearchablePrompt {
189
193
  this.scopeTogglePending = true;
190
194
  renderPrompt(prompt);
191
195
  try {
192
- const nextScope = await currentScope.toggle();
196
+ const nextScope = await currentScope.toggle(this.cancellation.signal);
193
197
  if (this.promptClosed)
194
198
  return;
195
- this.entries = nextScope.entries.map(buildSearchableWorktreeEntry);
199
+ const nextEntries = await buildWorktreePromptEntries(nextScope.sources, {
200
+ catalog: this.options.catalog,
201
+ metadata: nextScope.metadata,
202
+ });
203
+ this.entries = nextEntries.map(buildSearchableWorktreeEntry);
204
+ this.pruneHiddenSelections();
196
205
  this.scope = {
197
206
  label: nextScope.label,
198
207
  toggle: currentScope.toggle,
@@ -228,6 +237,7 @@ class SearchablePrompt {
228
237
  }
229
238
  cancel(prompt) {
230
239
  this.promptClosed = true;
240
+ this.cancellation.abort();
231
241
  prompt.state = "cancel";
232
242
  renderPrompt(prompt);
233
243
  closePrompt(prompt);
@@ -321,6 +331,13 @@ class SearchablePrompt {
321
331
  }
322
332
  this.selected.add(entry.value);
323
333
  }
334
+ pruneHiddenSelections() {
335
+ const visibleValues = new Set(this.entries.filter(isSelectableEntry).map((entry) => entry.value));
336
+ for (const value of this.selected) {
337
+ if (!visibleValues.has(value))
338
+ this.selected.delete(value);
339
+ }
340
+ }
324
341
  render(state, error) {
325
342
  const entries = this.visibleEntries();
326
343
  const visibleEntries = windowPromptEntries(entries, this.cursor, this.maxItems());
@@ -1,4 +1,4 @@
1
- .TH GJI\-BACK 1 "August 2026" "gji 0.13.0" "User Commands"
1
+ .TH GJI\-BACK 1 "October 2026" "gji 0.15.0" "User Commands"
2
2
  .SH NAME
3
3
  gji\-back \- navigate to the previously visited worktree, optionally N steps back
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-CLEAN 1 "August 2026" "gji 0.13.0" "User Commands"
1
+ .TH GJI\-CLEAN 1 "October 2026" "gji 0.15.0" "User Commands"
2
2
  .SH NAME
3
3
  gji\-clean \- interactively prune linked worktrees
4
4
  .SH SYNOPSIS
@@ -13,6 +13,9 @@ bypass prompts, force\-remove dirty worktrees, and force\-delete unmerged branch
13
13
  .B \-\-stale
14
14
  only target clean worktrees whose upstream is gone and branch is merged into the default branch
15
15
  .TP
16
+ .B \-\-path <pattern>
17
+ only target worktrees under a directory or matching a path glob (repeatable)
18
+ .TP
16
19
  .B \-\-dry\-run
17
20
  show what would be deleted without removing anything
18
21
  .TP
@@ -1,4 +1,4 @@
1
- .TH GJI\-COMPLETION 1 "August 2026" "gji 0.13.0" "User Commands"
1
+ .TH GJI\-COMPLETION 1 "October 2026" "gji 0.15.0" "User Commands"
2
2
  .SH NAME
3
3
  gji\-completion \- print shell completion definitions
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-CONFIG 1 "August 2026" "gji 0.13.0" "User Commands"
1
+ .TH GJI\-CONFIG 1 "October 2026" "gji 0.15.0" "User Commands"
2
2
  .SH NAME
3
3
  gji\-config \- manage global config defaults
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-DOCTOR 1 "August 2026" "gji 0.13.0" "User Commands"
1
+ .TH GJI\-DOCTOR 1 "October 2026" "gji 0.15.0" "User Commands"
2
2
  .SH NAME
3
3
  gji\-doctor \- check gji installation and configuration health
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-DONE 1 "August 2026" "gji 0.13.0" "User Commands"
1
+ .TH GJI\-DONE 1 "October 2026" "gji 0.15.0" "User Commands"
2
2
  .SH NAME
3
3
  gji\-done \- finish the current linked worktree and return safely
4
4
  .SH SYNOPSIS
package/man/man1/gji-go.1 CHANGED
@@ -1,4 +1,4 @@
1
- .TH GJI\-GO 1 "August 2026" "gji 0.13.0" "User Commands"
1
+ .TH GJI\-GO 1 "October 2026" "gji 0.15.0" "User Commands"
2
2
  .SH NAME
3
3
  gji\-go \- resolve and jump to a worktree path
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-HISTORY 1 "August 2026" "gji 0.13.0" "User Commands"
1
+ .TH GJI\-HISTORY 1 "October 2026" "gji 0.15.0" "User Commands"
2
2
  .SH NAME
3
3
  gji\-history \- show navigation history
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-INIT 1 "August 2026" "gji 0.13.0" "User Commands"
1
+ .TH GJI\-INIT 1 "October 2026" "gji 0.15.0" "User Commands"
2
2
  .SH NAME
3
3
  gji\-init \- set up shell integration interactively or print a shell wrapper
4
4
  .SH SYNOPSIS
package/man/man1/gji-ls.1 CHANGED
@@ -1,4 +1,4 @@
1
- .TH GJI\-LS 1 "August 2026" "gji 0.13.0" "User Commands"
1
+ .TH GJI\-LS 1 "October 2026" "gji 0.15.0" "User Commands"
2
2
  .SH NAME
3
3
  gji\-ls \- list active worktrees
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-NEW 1 "August 2026" "gji 0.13.0" "User Commands"
1
+ .TH GJI\-NEW 1 "October 2026" "gji 0.15.0" "User Commands"
2
2
  .SH NAME
3
3
  gji\-new \- create a branch with an optional linked worktree
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-OPEN 1 "August 2026" "gji 0.13.0" "User Commands"
1
+ .TH GJI\-OPEN 1 "October 2026" "gji 0.15.0" "User Commands"
2
2
  .SH NAME
3
3
  gji\-open \- open the worktree in an editor
4
4
  .SH SYNOPSIS
package/man/man1/gji-pr.1 CHANGED
@@ -1,4 +1,4 @@
1
- .TH GJI\-PR 1 "August 2026" "gji 0.13.0" "User Commands"
1
+ .TH GJI\-PR 1 "October 2026" "gji 0.15.0" "User Commands"
2
2
  .SH NAME
3
3
  gji\-pr \- fetch a pull request by number, #number, or URL into a linked worktree
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-REMOVE 1 "August 2026" "gji 0.13.0" "User Commands"
1
+ .TH GJI\-REMOVE 1 "October 2026" "gji 0.15.0" "User Commands"
2
2
  .SH NAME
3
3
  gji\-remove \- deprecated: use gji done for one worktree or gji clean for bulk cleanup
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-ROOT 1 "August 2026" "gji 0.13.0" "User Commands"
1
+ .TH GJI\-ROOT 1 "October 2026" "gji 0.15.0" "User Commands"
2
2
  .SH NAME
3
3
  gji\-root \- print the main repository root path
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-RUN\-HOOK 1 "August 2026" "gji 0.13.0" "User Commands"
1
+ .TH GJI\-RUN\-HOOK 1 "October 2026" "gji 0.15.0" "User Commands"
2
2
  .SH NAME
3
3
  gji\-run\-hook \- run a named hook (after\-create, after\-enter, before\-remove) in the current worktree
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-STATUS 1 "August 2026" "gji 0.13.0" "User Commands"
1
+ .TH GJI\-STATUS 1 "October 2026" "gji 0.15.0" "User Commands"
2
2
  .SH NAME
3
3
  gji\-status \- summarize repository and worktree health
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-SYNC\-FILES 1 "August 2026" "gji 0.13.0" "User Commands"
1
+ .TH GJI\-SYNC\-FILES 1 "October 2026" "gji 0.15.0" "User Commands"
2
2
  .SH NAME
3
3
  gji\-sync\-files \- manage local files copied into new worktrees
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-SYNC 1 "August 2026" "gji 0.13.0" "User Commands"
1
+ .TH GJI\-SYNC 1 "October 2026" "gji 0.15.0" "User Commands"
2
2
  .SH NAME
3
3
  gji\-sync \- fetch and update one or all worktrees
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-TASK 1 "August 2026" "gji 0.13.0" "User Commands"
1
+ .TH GJI\-TASK 1 "October 2026" "gji 0.15.0" "User Commands"
2
2
  .SH NAME
3
3
  gji\-task \- show or update the current worktree task
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-UNDO 1 "August 2026" "gji 0.13.0" "User Commands"
1
+ .TH GJI\-UNDO 1 "October 2026" "gji 0.15.0" "User Commands"
2
2
  .SH NAME
3
3
  gji\-undo \- restore the most recent destructive worktree operation
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-WARP 1 "August 2026" "gji 0.13.0" "User Commands"
1
+ .TH GJI\-WARP 1 "October 2026" "gji 0.15.0" "User Commands"
2
2
  .SH NAME
3
3
  gji\-warp \- deprecated: use gji go (press Tab for all known repos)
4
4
  .SH SYNOPSIS
package/man/man1/gji.1 CHANGED
@@ -1,4 +1,4 @@
1
- .TH GJI 1 "August 2026" "gji 0.13.0" "User Commands"
1
+ .TH GJI 1 "October 2026" "gji 0.15.0" "User Commands"
2
2
  .SH NAME
3
3
  gji \- Context switching without the mess.
4
4
  .SH SYNOPSIS
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solaqua/gji",
3
- "version": "0.13.0",
3
+ "version": "0.15.0",
4
4
  "description": "Git worktree CLI for fast context switching.",
5
5
  "license": "MIT",
6
6
  "author": "sjquant",