@solaqua/gji 0.12.5 → 0.13.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 (214) hide show
  1. package/README.md +12 -0
  2. package/dist/application/worktree/catalog.d.ts +31 -0
  3. package/dist/application/worktree/catalog.js +88 -0
  4. package/dist/application/worktree/context-card.d.ts +14 -0
  5. package/dist/application/worktree/context-card.js +12 -0
  6. package/dist/{go-resolver.d.ts → application/worktree/go-resolution.d.ts} +12 -4
  7. package/dist/{go-resolver.js → application/worktree/go-resolution.js} +46 -44
  8. package/dist/application/worktree/read-models.d.ts +31 -0
  9. package/dist/application/worktree/sources.d.ts +7 -0
  10. package/dist/{worktree-sources.js → application/worktree/sources.js} +12 -24
  11. package/dist/{back.d.ts → cli/commands/back.d.ts} +3 -1
  12. package/dist/{back.js → cli/commands/back.js} +8 -6
  13. package/dist/{clean.d.ts → cli/commands/clean.d.ts} +4 -2
  14. package/dist/{clean.js → cli/commands/clean.js} +32 -24
  15. package/dist/{completion.js → cli/commands/completion.js} +2 -2
  16. package/dist/{config-command.d.ts → cli/commands/config-command.d.ts} +2 -0
  17. package/dist/{config-command.js → cli/commands/config-command.js} +7 -5
  18. package/dist/{doctor.d.ts → cli/commands/doctor.d.ts} +2 -0
  19. package/dist/{doctor.js → cli/commands/doctor.js} +23 -25
  20. package/dist/{done.d.ts → cli/commands/done.d.ts} +2 -0
  21. package/dist/{done.js → cli/commands/done.js} +26 -23
  22. package/dist/{go.d.ts → cli/commands/go.d.ts} +6 -1
  23. package/dist/{go.js → cli/commands/go.js} +57 -41
  24. package/dist/{history-command.d.ts → cli/commands/history-command.d.ts} +2 -0
  25. package/dist/{history-command.js → cli/commands/history-command.js} +3 -1
  26. package/dist/{hub.d.ts → cli/commands/hub.d.ts} +7 -3
  27. package/dist/{hub.js → cli/commands/hub.js} +23 -33
  28. package/dist/{init.d.ts → cli/commands/init.d.ts} +3 -1
  29. package/dist/{init.js → cli/commands/init.js} +37 -34
  30. package/dist/{ls.d.ts → cli/commands/ls.d.ts} +4 -2
  31. package/dist/{ls.js → cli/commands/ls.js} +8 -5
  32. package/dist/{new.d.ts → cli/commands/new.d.ts} +6 -2
  33. package/dist/{new.js → cli/commands/new.js} +237 -109
  34. package/dist/{open.d.ts → cli/commands/open.d.ts} +4 -2
  35. package/dist/{open.js → cli/commands/open.js} +19 -12
  36. package/dist/{pr-open.d.ts → cli/commands/pr-open.d.ts} +4 -2
  37. package/dist/{pr-open.js → cli/commands/pr-open.js} +20 -18
  38. package/dist/{pr.d.ts → cli/commands/pr.d.ts} +5 -3
  39. package/dist/{pr.js → cli/commands/pr.js} +34 -41
  40. package/dist/{remove.d.ts → cli/commands/remove.d.ts} +4 -2
  41. package/dist/{remove.js → cli/commands/remove.js} +23 -17
  42. package/dist/{root.d.ts → cli/commands/root.d.ts} +2 -0
  43. package/dist/{root.js → cli/commands/root.js} +4 -2
  44. package/dist/{run-hook.d.ts → cli/commands/run-hook.d.ts} +2 -0
  45. package/dist/{run-hook.js → cli/commands/run-hook.js} +7 -4
  46. package/dist/{status.d.ts → cli/commands/status.d.ts} +2 -0
  47. package/dist/{status.js → cli/commands/status.js} +10 -7
  48. package/dist/{sync-files-command.d.ts → cli/commands/sync-files-command.d.ts} +2 -0
  49. package/dist/{sync-files-command.js → cli/commands/sync-files-command.js} +11 -9
  50. package/dist/{sync.d.ts → cli/commands/sync.d.ts} +2 -0
  51. package/dist/{sync.js → cli/commands/sync.js} +7 -4
  52. package/dist/{task-command.d.ts → cli/commands/task-command.d.ts} +2 -0
  53. package/dist/{task-command.js → cli/commands/task-command.js} +4 -2
  54. package/dist/{undo.d.ts → cli/commands/undo.d.ts} +8 -6
  55. package/dist/{undo.js → cli/commands/undo.js} +44 -34
  56. package/dist/{warp.d.ts → cli/commands/warp.d.ts} +5 -2
  57. package/dist/{warp.js → cli/commands/warp.js} +20 -10
  58. package/dist/cli/dependencies.d.ts +114 -0
  59. package/dist/cli/dependencies.js +118 -0
  60. package/dist/{cli.d.ts → cli/program.d.ts} +4 -2
  61. package/dist/{cli.js → cli/program.js} +108 -124
  62. package/dist/domain/repository/context.d.ts +6 -0
  63. package/dist/domain/repository/context.js +1 -0
  64. package/dist/domain/repository/registry.d.ts +5 -0
  65. package/dist/domain/repository/registry.js +1 -0
  66. package/dist/domain/shared/concurrency.d.ts +1 -0
  67. package/dist/domain/shared/concurrency.js +15 -0
  68. package/dist/domain/worktree/matching.d.ts +4 -0
  69. package/dist/domain/worktree/matching.js +79 -0
  70. package/dist/domain/worktree/policy.d.ts +2 -0
  71. package/dist/domain/worktree/policy.js +58 -0
  72. package/dist/domain/worktree/pr-reference.d.ts +1 -0
  73. package/dist/domain/worktree/pr-reference.js +9 -0
  74. package/dist/{worktree-source.d.ts → domain/worktree/source.d.ts} +1 -1
  75. package/dist/domain/worktree/source.js +1 -0
  76. package/dist/domain/worktree/types.d.ts +5 -0
  77. package/dist/domain/worktree/types.js +1 -0
  78. package/dist/gji-bundle.mjs +7035 -6212
  79. package/dist/index.js +3 -3
  80. package/dist/{dependency-bootstrap.d.ts → infrastructure/bootstrap/dependency-bootstrap.d.ts} +3 -30
  81. package/dist/{dependency-bootstrap.js → infrastructure/bootstrap/dependency-bootstrap.js} +4 -4
  82. package/dist/infrastructure/git/health.d.ts +9 -0
  83. package/dist/infrastructure/git/health.js +44 -0
  84. package/dist/infrastructure/git/refs.d.ts +6 -0
  85. package/dist/{git.js → infrastructure/git/refs.js} +1 -51
  86. package/dist/infrastructure/git/runner.d.ts +2 -0
  87. package/dist/infrastructure/git/runner.js +16 -0
  88. package/dist/{editor.d.ts → infrastructure/integrations/editor.d.ts} +2 -6
  89. package/dist/{pull-requests.d.ts → infrastructure/integrations/pull-requests.d.ts} +3 -11
  90. package/dist/{config.d.ts → infrastructure/persistence/config.d.ts} +3 -17
  91. package/dist/{config.js → infrastructure/persistence/config.js} +2 -17
  92. package/dist/{history.d.ts → infrastructure/persistence/history.d.ts} +2 -5
  93. package/dist/{task.js → infrastructure/persistence/task.js} +1 -1
  94. package/dist/infrastructure/process/command-runner.d.ts +3 -0
  95. package/dist/{hooks.d.ts → infrastructure/process/hooks.d.ts} +2 -12
  96. package/dist/infrastructure/repository/adapters.d.ts +7 -0
  97. package/dist/infrastructure/repository/adapters.js +23 -0
  98. package/dist/infrastructure/repository/context.d.ts +3 -0
  99. package/dist/infrastructure/repository/context.js +20 -0
  100. package/dist/infrastructure/repository/refs.d.ts +3 -0
  101. package/dist/infrastructure/repository/refs.js +37 -0
  102. package/dist/{repo-registry.d.ts → infrastructure/repository/registry.d.ts} +1 -5
  103. package/dist/{repo-registry.js → infrastructure/repository/registry.js} +1 -1
  104. package/dist/infrastructure/repository/worktrees.d.ts +2 -0
  105. package/dist/infrastructure/repository/worktrees.js +48 -0
  106. package/dist/{uv-validation.d.ts → infrastructure/validation/uv.d.ts} +1 -1
  107. package/dist/{uv-validation.js → infrastructure/validation/uv.js} +1 -1
  108. package/dist/infrastructure/worktree/bootstrap.d.ts +3 -0
  109. package/dist/{worktree-bootstrap.js → infrastructure/worktree/bootstrap.js} +7 -10
  110. package/dist/infrastructure/worktree/info.d.ts +6 -0
  111. package/dist/infrastructure/worktree/info.js +61 -0
  112. package/dist/{worktree-management.d.ts → infrastructure/worktree/lifecycle.d.ts} +0 -6
  113. package/dist/{worktree-management.js → infrastructure/worktree/lifecycle.js} +1 -9
  114. package/dist/ports/bootstrap.d.ts +61 -0
  115. package/dist/ports/bootstrap.js +1 -0
  116. package/dist/ports/config.d.ts +21 -0
  117. package/dist/ports/config.js +17 -0
  118. package/dist/ports/editor.d.ts +6 -0
  119. package/dist/ports/editor.js +1 -0
  120. package/dist/ports/git.d.ts +8 -0
  121. package/dist/ports/git.js +1 -0
  122. package/dist/ports/history.d.ts +5 -0
  123. package/dist/ports/history.js +1 -0
  124. package/dist/ports/hooks.d.ts +12 -0
  125. package/dist/ports/hooks.js +1 -0
  126. package/dist/{command-runner.d.ts → ports/process.d.ts} +0 -1
  127. package/dist/ports/process.js +1 -0
  128. package/dist/ports/pull-requests.d.ts +11 -0
  129. package/dist/ports/pull-requests.js +1 -0
  130. package/dist/ports/repository.d.ts +17 -0
  131. package/dist/ports/repository.js +1 -0
  132. package/dist/{bootstrap-output.d.ts → presentation/bootstrap/output.d.ts} +1 -1
  133. package/dist/presentation/bootstrap/preview.d.ts +2 -0
  134. package/dist/{bootstrap-preview.js → presentation/bootstrap/preview.js} +0 -4
  135. package/dist/{shell-completion.js → presentation/shell/completion.js} +5 -4
  136. package/dist/presentation/terminal/context-card.d.ts +2 -0
  137. package/dist/{context-card.js → presentation/terminal/context-card.js} +3 -12
  138. package/dist/presentation/worktree/format.d.ts +4 -0
  139. package/dist/presentation/worktree/format.js +41 -0
  140. package/dist/{worktree-picker.d.ts → presentation/worktree/picker.d.ts} +7 -11
  141. package/dist/{worktree-picker.js → presentation/worktree/picker.js} +11 -182
  142. package/man/man1/gji-back.1 +1 -1
  143. package/man/man1/gji-clean.1 +1 -1
  144. package/man/man1/gji-completion.1 +1 -1
  145. package/man/man1/gji-config.1 +1 -1
  146. package/man/man1/gji-doctor.1 +1 -1
  147. package/man/man1/gji-done.1 +1 -1
  148. package/man/man1/gji-go.1 +1 -1
  149. package/man/man1/gji-history.1 +1 -1
  150. package/man/man1/gji-init.1 +1 -1
  151. package/man/man1/gji-ls.1 +1 -1
  152. package/man/man1/gji-new.1 +6 -3
  153. package/man/man1/gji-open.1 +1 -1
  154. package/man/man1/gji-pr.1 +1 -1
  155. package/man/man1/gji-remove.1 +1 -1
  156. package/man/man1/gji-root.1 +1 -1
  157. package/man/man1/gji-run-hook.1 +1 -1
  158. package/man/man1/gji-status.1 +1 -1
  159. package/man/man1/gji-sync-files.1 +1 -1
  160. package/man/man1/gji-sync.1 +1 -1
  161. package/man/man1/gji-task.1 +1 -1
  162. package/man/man1/gji-undo.1 +1 -1
  163. package/man/man1/gji-warp.1 +1 -1
  164. package/man/man1/gji.1 +2 -2
  165. package/package.json +1 -1
  166. package/dist/bootstrap-preview.d.ts +0 -9
  167. package/dist/context-card.d.ts +0 -1
  168. package/dist/format-bytes.d.ts +0 -1
  169. package/dist/format-bytes.js +0 -14
  170. package/dist/git.d.ts +0 -18
  171. package/dist/repo.d.ts +0 -20
  172. package/dist/repo.js +0 -161
  173. package/dist/worktree-bootstrap.d.ts +0 -24
  174. package/dist/worktree-info.d.ts +0 -37
  175. package/dist/worktree-info.js +0 -123
  176. package/dist/worktree-sources.d.ts +0 -4
  177. /package/dist/{worktree-source.js → application/worktree/read-models.js} +0 -0
  178. /package/dist/{completion.d.ts → cli/commands/completion.d.ts} +0 -0
  179. /package/dist/{headless.d.ts → cli/runtime/headless.d.ts} +0 -0
  180. /package/dist/{headless.js → cli/runtime/headless.js} +0 -0
  181. /package/dist/{paths.d.ts → domain/shared/paths.d.ts} +0 -0
  182. /package/dist/{paths.js → domain/shared/paths.js} +0 -0
  183. /package/dist/{file-sync.d.ts → infrastructure/filesystem/file-sync.d.ts} +0 -0
  184. /package/dist/{file-sync.js → infrastructure/filesystem/file-sync.js} +0 -0
  185. /package/dist/{fs-utils.d.ts → infrastructure/filesystem/fs-utils.d.ts} +0 -0
  186. /package/dist/{fs-utils.js → infrastructure/filesystem/fs-utils.js} +0 -0
  187. /package/dist/{safe-destination.d.ts → infrastructure/filesystem/safe-destination.d.ts} +0 -0
  188. /package/dist/{safe-destination.js → infrastructure/filesystem/safe-destination.js} +0 -0
  189. /package/dist/{browser.d.ts → infrastructure/integrations/browser.d.ts} +0 -0
  190. /package/dist/{browser.js → infrastructure/integrations/browser.js} +0 -0
  191. /package/dist/{editor.js → infrastructure/integrations/editor.js} +0 -0
  192. /package/dist/{pull-requests.js → infrastructure/integrations/pull-requests.js} +0 -0
  193. /package/dist/{history.js → infrastructure/persistence/history.js} +0 -0
  194. /package/dist/{slots.d.ts → infrastructure/persistence/slots.d.ts} +0 -0
  195. /package/dist/{slots.js → infrastructure/persistence/slots.js} +0 -0
  196. /package/dist/{task.d.ts → infrastructure/persistence/task.d.ts} +0 -0
  197. /package/dist/{command-runner.js → infrastructure/process/command-runner.js} +0 -0
  198. /package/dist/{hooks.js → infrastructure/process/hooks.js} +0 -0
  199. /package/dist/{bootstrap-output.js → presentation/bootstrap/output.js} +0 -0
  200. /package/dist/{conflict.d.ts → presentation/prompts/path-conflict.d.ts} +0 -0
  201. /package/dist/{conflict.js → presentation/prompts/path-conflict.js} +0 -0
  202. /package/dist/{shell-completion.d.ts → presentation/shell/completion.d.ts} +0 -0
  203. /package/dist/{shell-handoff.d.ts → presentation/shell/handoff.d.ts} +0 -0
  204. /package/dist/{shell-handoff.js → presentation/shell/handoff.js} +0 -0
  205. /package/dist/{shell-setup.d.ts → presentation/shell/setup.d.ts} +0 -0
  206. /package/dist/{shell-setup.js → presentation/shell/setup.js} +0 -0
  207. /package/dist/{shell.d.ts → presentation/shell/shell.d.ts} +0 -0
  208. /package/dist/{shell.js → presentation/shell/shell.js} +0 -0
  209. /package/dist/{navigation-output.d.ts → presentation/terminal/navigation.d.ts} +0 -0
  210. /package/dist/{navigation-output.js → presentation/terminal/navigation.js} +0 -0
  211. /package/dist/{terminal-text.d.ts → presentation/terminal/text.d.ts} +0 -0
  212. /package/dist/{terminal-text.js → presentation/terminal/text.js} +0 -0
  213. /package/dist/{worktree-prompts.d.ts → presentation/worktree/prompts.d.ts} +0 -0
  214. /package/dist/{worktree-prompts.js → presentation/worktree/prompts.js} +0 -0
@@ -1,13 +1,8 @@
1
1
  import { env, platform, stdin, stdout } from "node:process";
2
2
  import { isCancel, Prompt } from "@clack/core";
3
3
  import { spinner } from "@clack/prompts";
4
- import { loadHistory } from "./history.js";
5
- import { createPullRequestQuery, } from "./pull-requests.js";
6
- import { readTask } from "./task.js";
7
- import { middleEllipsize, sanitizeTerminalText, startEllipsize, terminalWidth, } from "./terminal-text.js";
8
- import { readWorktreeInfos, } from "./worktree-info.js";
9
- const MAX_PULL_REQUEST_REPOSITORY_QUERY_CONCURRENCY = 4;
10
- const MAX_TASK_READ_CONCURRENCY = 8;
4
+ import { loadWorktreeCatalog, } from "../../application/worktree/catalog.js";
5
+ import { middleEllipsize, sanitizeTerminalText, startEllipsize, terminalWidth, } from "../terminal/text.js";
11
6
  export async function buildWorktreePromptEntries(sources, dependencies = {}) {
12
7
  const loading = stdin.isTTY === true && stdout.isTTY === true && stdin.isRaw !== true
13
8
  ? spinner({ indicator: "timer" })
@@ -22,91 +17,14 @@ export async function buildWorktreePromptEntries(sources, dependencies = {}) {
22
17
  }
23
18
  async function buildWorktreePromptEntriesWithoutLoading(sources, dependencies) {
24
19
  const metadataMode = dependencies.metadata ?? "full";
25
- const includeMetadata = metadataMode === "full";
26
- const pullRequestQuery = createPullRequestQuery();
27
- const queryPullRequests = dependencies.queryPullRequests ?? pullRequestQuery.listOpenPullRequests;
28
- const queryRepositoryPullRequests = includeMetadata
29
- ? (dependencies.queryRepositoryPullRequests ??
30
- (dependencies.queryPullRequests === undefined
31
- ? pullRequestQuery.listOpenPullRequestsForRepository
32
- : undefined))
33
- : undefined;
34
- const repositoryPullRequests = queryRepositoryPullRequests === undefined
35
- ? Promise.resolve(null)
36
- : readRepositoryPullRequests(sources, queryRepositoryPullRequests);
37
- const [history, infos, pullRequestsByRepository] = await Promise.all([
38
- loadHistory(),
39
- includeMetadata
40
- ? readWorktreeInfos(sources.map((source) => source.worktree))
41
- : mapWithConcurrency(sources, MAX_TASK_READ_CONCURRENCY, (source) => createUnhydratedWorktreeInfo(source.worktree)),
42
- repositoryPullRequests,
43
- ]);
44
- const pullRequests = includeMetadata
45
- ? await Promise.all(sources.map((source) => readSourcePullRequests(source, queryPullRequests, pullRequestsByRepository)))
46
- : sources.map(() => []);
47
- const historyByPath = new Map(history.map((entry) => [entry.path, entry]));
48
- const entries = sources.map((source, index) => buildWorktreePromptEntry(source, infos[index], pullRequests[index], historyByPath.get(source.worktree.path)?.timestamp ?? null, Date.now()));
20
+ const hydrated = await loadWorktreeCatalog(sources, metadataMode, dependencies.catalog ?? missingCatalogDependencies());
21
+ const entries = hydrated.map(({ info, lastUsedTimestamp, pullRequests, source }) => buildWorktreePromptEntry(source, info, pullRequests, lastUsedTimestamp, Date.now()));
49
22
  return entries
50
23
  .sort(comparePromptEntries)
51
24
  .map(({ lastActivityTimestamp: _lastActivityTimestamp, ...entry }) => entry);
52
25
  }
53
- async function createUnhydratedWorktreeInfo(worktree) {
54
- let task = null;
55
- try {
56
- task = (await readTask(worktree.path))?.task ?? null;
57
- }
58
- catch {
59
- // Task metadata is optional picker decoration.
60
- }
61
- return {
62
- ...worktree,
63
- lastCommitTimestamp: null,
64
- slot: null,
65
- status: "unknown",
66
- task,
67
- upstream: { kind: "unknown" },
68
- };
69
- }
70
- export function resolveWorktreeQuery(sources, query) {
71
- return resolveWorktreeQueryMatches(sources, query)[0] ?? null;
72
- }
73
- export function resolveWorktreeQueryMatches(sources, query) {
74
- const normalizedQuery = normalizeQuery(query);
75
- if (normalizedQuery === null)
76
- return [];
77
- const matches = findWorktreePromptSourceMatches(sources, normalizedQuery);
78
- if (isAmbiguousRepoOnlyQuery(matches, normalizedQuery))
79
- return [];
80
- const bestScore = matches[0]?.matchScore;
81
- return matches
82
- .filter((match) => match.matchScore === bestScore)
83
- .map((match) => match.source);
84
- }
85
- export function resolveExactWorktreeQueryMatches(sources, query) {
86
- const normalizedQuery = normalizeQuery(query);
87
- if (normalizedQuery === null)
88
- return [];
89
- return sources.filter((source) => scoreWorktreeMatch({
90
- ...source.worktree,
91
- repoName: source.repoName,
92
- }, normalizedQuery) === 1000);
93
- }
94
- function findWorktreePromptSourceMatches(sources, normalizedQuery) {
95
- return sources
96
- .flatMap((source) => {
97
- const matchScore = scoreWorktreeMatch({
98
- ...source.worktree,
99
- repoName: source.repoName,
100
- }, normalizedQuery);
101
- return matchScore === null ? [] : [{ matchScore, source }];
102
- })
103
- .sort(compareQueryMatches);
104
- }
105
- function isAmbiguousRepoOnlyQuery(matches, query) {
106
- if (matches[0]?.matchScore === 1000)
107
- return false;
108
- return (matches.filter((match) => match.source.repoName.toLowerCase() === query)
109
- .length > 1);
26
+ function missingCatalogDependencies() {
27
+ throw new Error("Worktree picker hydration must be supplied by the application composition root");
110
28
  }
111
29
  export async function promptForSingleWorktree(message, worktrees, io = {}) {
112
30
  const choice = await runSearchablePrompt({
@@ -129,18 +47,6 @@ export async function promptForMultipleWorktrees(message, worktrees, io = {}) {
129
47
  });
130
48
  return Array.isArray(choice) ? choice : null;
131
49
  }
132
- function compareQueryMatches(a, b) {
133
- if (a.matchScore !== b.matchScore) {
134
- return b.matchScore - a.matchScore;
135
- }
136
- if (a.source.worktree.isCurrent && !b.source.worktree.isCurrent)
137
- return -1;
138
- if (!a.source.worktree.isCurrent && b.source.worktree.isCurrent)
139
- return 1;
140
- return (a.source.repoName.localeCompare(b.source.repoName) ||
141
- (a.source.worktree.branch ?? "").localeCompare(b.source.worktree.branch ?? "") ||
142
- a.source.worktree.path.localeCompare(b.source.worktree.path));
143
- }
144
50
  function groupPromptEntries(worktrees) {
145
51
  const groups = new Map();
146
52
  for (const worktree of worktrees) {
@@ -605,7 +511,7 @@ class SearchablePrompt {
605
511
  return index === -1 ? 0 : index;
606
512
  }
607
513
  visibleEntries() {
608
- const query = normalizeQuery(this.query);
514
+ const query = normalizePromptQuery(this.query);
609
515
  if (query === null) {
610
516
  return this.entries;
611
517
  }
@@ -940,61 +846,6 @@ function buildWorktreePromptEntry(source, info, pullRequests, lastUsedTimestamp,
940
846
  task: info.task,
941
847
  };
942
848
  }
943
- async function readSourcePullRequests(source, queryPullRequests, pullRequestsByRepository) {
944
- if (source.repoRoot === undefined || source.worktree.branch === null) {
945
- return [];
946
- }
947
- if (pullRequestsByRepository !== null) {
948
- return sortSourcePullRequests(pullRequestsByRepository
949
- .get(source.repoRoot)
950
- ?.filter((pullRequest) => pullRequest.sourceBranch === source.worktree.branch));
951
- }
952
- try {
953
- const pullRequests = await queryPullRequests(source.repoRoot, source.worktree.branch);
954
- return sortSourcePullRequests(pullRequests);
955
- }
956
- catch {
957
- // PR metadata is optional selector decoration; preserve the worktree entry on lookup failures.
958
- return [];
959
- }
960
- }
961
- async function readRepositoryPullRequests(sources, queryPullRequests) {
962
- const repoRoots = [
963
- ...new Set(sources.flatMap((source) => source.repoRoot === undefined || source.worktree.branch === null
964
- ? []
965
- : [source.repoRoot])),
966
- ];
967
- const results = await mapWithConcurrency(repoRoots, MAX_PULL_REQUEST_REPOSITORY_QUERY_CONCURRENCY, async (repoRoot) => {
968
- try {
969
- return [
970
- repoRoot,
971
- sortSourcePullRequests(await queryPullRequests(repoRoot)),
972
- ];
973
- }
974
- catch {
975
- return [repoRoot, []];
976
- }
977
- });
978
- return new Map(results);
979
- }
980
- async function mapWithConcurrency(items, limit, mapper) {
981
- const results = new Array(items.length);
982
- let nextIndex = 0;
983
- async function readNext() {
984
- for (;;) {
985
- const index = nextIndex;
986
- nextIndex += 1;
987
- if (index >= items.length)
988
- return;
989
- results[index] = await mapper(items[index]);
990
- }
991
- }
992
- await Promise.all(Array.from({ length: Math.min(limit, items.length) }, () => readNext()));
993
- return results;
994
- }
995
- function sortSourcePullRequests(pullRequests) {
996
- return [...(pullRequests ?? [])].sort((a, b) => a.number - b.number);
997
- }
998
849
  export function formatWorktreeBranchLabel(branch, pullRequests = []) {
999
850
  const branchLabel = branch ?? "(detached)";
1000
851
  if (pullRequests.length === 0)
@@ -1064,20 +915,6 @@ function isYesterday(timestamp, now) {
1064
915
  date.getMonth() === yesterday.getMonth() &&
1065
916
  date.getDate() === yesterday.getDate());
1066
917
  }
1067
- function buildSearchText(repoName, worktree) {
1068
- return [
1069
- repoName,
1070
- worktree.branch ?? "detached",
1071
- worktree.path,
1072
- `${repoName}/${worktree.branch ?? "detached"}`,
1073
- ]
1074
- .join(" ")
1075
- .toLowerCase();
1076
- }
1077
- function normalizeQuery(query) {
1078
- const normalized = query?.trim().toLowerCase();
1079
- return normalized && normalized.length > 0 ? normalized : null;
1080
- }
1081
918
  function comparePromptEntries(a, b) {
1082
919
  if (a.isCurrent && !b.isCurrent)
1083
920
  return -1;
@@ -1095,18 +932,10 @@ function comparePromptEntries(a, b) {
1095
932
  (a.branch ?? "").localeCompare(b.branch ?? "") ||
1096
933
  a.path.localeCompare(b.path));
1097
934
  }
935
+ function normalizePromptQuery(query) {
936
+ const normalized = query?.trim().toLowerCase();
937
+ return normalized && normalized.length > 0 ? normalized : null;
938
+ }
1098
939
  function groupRank(group) {
1099
940
  return group === "recent" ? 0 : 1;
1100
941
  }
1101
- function scoreWorktreeMatch(entry, query) {
1102
- const branch = entry.branch ?? "detached";
1103
- const exactCandidates = [
1104
- branch,
1105
- entry.path,
1106
- `${entry.repoName}/${branch}`,
1107
- ].map((candidate) => candidate.toLowerCase());
1108
- if (exactCandidates.includes(query)) {
1109
- return 1000;
1110
- }
1111
- return buildSearchText(entry.repoName, entry).includes(query) ? 1 : null;
1112
- }
@@ -1,4 +1,4 @@
1
- .TH GJI\-BACK 1 "August 2026" "gji 0.12.5" "User Commands"
1
+ .TH GJI\-BACK 1 "August 2026" "gji 0.13.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.12.5" "User Commands"
1
+ .TH GJI\-CLEAN 1 "August 2026" "gji 0.13.0" "User Commands"
2
2
  .SH NAME
3
3
  gji\-clean \- interactively prune linked worktrees
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-COMPLETION 1 "August 2026" "gji 0.12.5" "User Commands"
1
+ .TH GJI\-COMPLETION 1 "August 2026" "gji 0.13.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.12.5" "User Commands"
1
+ .TH GJI\-CONFIG 1 "August 2026" "gji 0.13.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.12.5" "User Commands"
1
+ .TH GJI\-DOCTOR 1 "August 2026" "gji 0.13.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.12.5" "User Commands"
1
+ .TH GJI\-DONE 1 "August 2026" "gji 0.13.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.12.5" "User Commands"
1
+ .TH GJI\-GO 1 "August 2026" "gji 0.13.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.12.5" "User Commands"
1
+ .TH GJI\-HISTORY 1 "August 2026" "gji 0.13.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.12.5" "User Commands"
1
+ .TH GJI\-INIT 1 "August 2026" "gji 0.13.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.12.5" "User Commands"
1
+ .TH GJI\-LS 1 "August 2026" "gji 0.13.0" "User Commands"
2
2
  .SH NAME
3
3
  gji\-ls \- list active worktrees
4
4
  .SH SYNOPSIS
@@ -1,10 +1,10 @@
1
- .TH GJI\-NEW 1 "August 2026" "gji 0.12.5" "User Commands"
1
+ .TH GJI\-NEW 1 "August 2026" "gji 0.13.0" "User Commands"
2
2
  .SH NAME
3
- gji\-new \- create a new branch or detached linked worktree
3
+ gji\-new \- create a branch with an optional linked worktree
4
4
  .SH SYNOPSIS
5
5
  .B gji new [\fIoptions\fR] [options] [branch]
6
6
  .SH DESCRIPTION
7
- create a new branch or detached linked worktree
7
+ create a branch with an optional linked worktree
8
8
  .SH BOOTSTRAP_POLICY
9
9
  dependencyBuildCommand overrides Cargo's default cargo check. Supported lockfiles are installed automatically in new worktrees; set dependencyBootstrap to off or pass \-\-no\-install to skip setup. Sync\-file failures stop dependency installation and after\-create hooks. JSON bootstrap events include structured reasons, and failed setup reports the created worktree path.
10
10
 
@@ -13,6 +13,9 @@ Dependency bootstrap never copies dependency trees or build caches. pnpm, Yarn,
13
13
 
14
14
  .SH OPTIONS
15
15
  .TP
16
+ .B \-\-branch\-only
17
+ update the default branch and create the new branch in the current worktree
18
+ .TP
16
19
  .B \-f, \-\-force
17
20
  remove and recreate the worktree if the target path already exists
18
21
  .TP
@@ -1,4 +1,4 @@
1
- .TH GJI\-OPEN 1 "August 2026" "gji 0.12.5" "User Commands"
1
+ .TH GJI\-OPEN 1 "August 2026" "gji 0.13.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.12.5" "User Commands"
1
+ .TH GJI\-PR 1 "August 2026" "gji 0.13.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.12.5" "User Commands"
1
+ .TH GJI\-REMOVE 1 "August 2026" "gji 0.13.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.12.5" "User Commands"
1
+ .TH GJI\-ROOT 1 "August 2026" "gji 0.13.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.12.5" "User Commands"
1
+ .TH GJI\-RUN\-HOOK 1 "August 2026" "gji 0.13.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.12.5" "User Commands"
1
+ .TH GJI\-STATUS 1 "August 2026" "gji 0.13.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.12.5" "User Commands"
1
+ .TH GJI\-SYNC\-FILES 1 "August 2026" "gji 0.13.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.12.5" "User Commands"
1
+ .TH GJI\-SYNC 1 "August 2026" "gji 0.13.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.12.5" "User Commands"
1
+ .TH GJI\-TASK 1 "August 2026" "gji 0.13.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.12.5" "User Commands"
1
+ .TH GJI\-UNDO 1 "August 2026" "gji 0.13.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.12.5" "User Commands"
1
+ .TH GJI\-WARP 1 "August 2026" "gji 0.13.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.12.5" "User Commands"
1
+ .TH GJI 1 "August 2026" "gji 0.13.0" "User Commands"
2
2
  .SH NAME
3
3
  gji \- Context switching without the mess.
4
4
  .SH SYNOPSIS
@@ -12,7 +12,7 @@ eliminating the need for \fBgit stash\fR when switching contexts.
12
12
  .SH COMMANDS
13
13
  .TP
14
14
  .B new [options] [branch]
15
- create a new branch or detached linked worktree
15
+ create a branch with an optional linked worktree
16
16
  .TP
17
17
  .B done [options] [branch]
18
18
  finish the current linked worktree and return safely
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solaqua/gji",
3
- "version": "0.12.5",
3
+ "version": "0.13.0",
4
4
  "description": "Git worktree CLI for fast context switching.",
5
5
  "license": "MIT",
6
6
  "author": "sjquant",
@@ -1,9 +0,0 @@
1
- import type { DependencyBootstrapMode } from "./dependency-bootstrap.js";
2
- import { type DependencyBootstrapPreview } from "./dependency-bootstrap.js";
3
- export declare function createDependencyBootstrapPreview(mode: DependencyBootstrapMode, context: {
4
- repoRoot: string;
5
- currentRoot?: string;
6
- worktreePath: string;
7
- cargoBuildCommand?: string;
8
- }): Promise<DependencyBootstrapPreview>;
9
- export declare function formatDependencyBootstrapPreview(preview: DependencyBootstrapPreview | undefined): string;
@@ -1 +0,0 @@
1
- export declare function renderContextCard(worktreePath: string): Promise<string | null>;
@@ -1 +0,0 @@
1
- export declare function formatBytes(bytes: number | undefined): string;
@@ -1,14 +0,0 @@
1
- export function formatBytes(bytes) {
2
- if (bytes === undefined)
3
- return "size unavailable";
4
- if (bytes < 1024)
5
- return `${bytes} B`;
6
- const units = ["KB", "MB", "GB", "TB"];
7
- let value = bytes;
8
- let unit = -1;
9
- while (value >= 1024 && unit < units.length - 1) {
10
- value /= 1024;
11
- unit += 1;
12
- }
13
- return `${value.toFixed(value >= 10 ? 0 : 1)} ${units[unit]}`;
14
- }
package/dist/git.d.ts DELETED
@@ -1,18 +0,0 @@
1
- export interface WorktreeHealth {
2
- ahead: number;
3
- behind: number;
4
- hasUpstream: boolean;
5
- upstreamGone: boolean;
6
- status: "clean" | "dirty";
7
- }
8
- export interface RemoteBase {
9
- branch: string;
10
- ref: string;
11
- }
12
- export declare function runGit(cwd: string, args: string[]): Promise<string>;
13
- export declare function readWorktreeHealth(cwd: string): Promise<WorktreeHealth>;
14
- export declare function isDirtyWorktree(cwd: string): Promise<boolean>;
15
- export declare function isBranchMergedInto(cwd: string, branch: string, base?: string): Promise<boolean>;
16
- export declare function resolveRemoteDefaultBranch(cwd: string, remote: string): Promise<string | null>;
17
- export declare function resolveRemoteBase(cwd: string, remote: string, configuredBranch?: string): Promise<RemoteBase | null>;
18
- export declare function readBranchLastCommitTimestamp(cwd: string, branch: string): Promise<number | null>;
package/dist/repo.d.ts DELETED
@@ -1,20 +0,0 @@
1
- export interface RepositoryContext {
2
- currentRoot: string;
3
- gitCommonDir: string;
4
- isWorktree: boolean;
5
- repoName: string;
6
- repoRoot: string;
7
- }
8
- export interface WorktreeEntry {
9
- branch: string | null;
10
- isCurrent: boolean;
11
- path: string;
12
- }
13
- export declare function detectRepository(cwd: string): Promise<RepositoryContext>;
14
- export declare function worktreeGitDir(worktreePath: string): Promise<string>;
15
- export declare function resolveWorktreePath(repoRoot: string, branch: string, basePath?: string): string;
16
- export declare function validateBranchName(name: string): string | null;
17
- export declare function hasLocalBranch(repoRoot: string, branch: string): Promise<boolean>;
18
- export declare function hasRemoteBranch(repoRoot: string, remote: string, branch: string): Promise<boolean>;
19
- export declare function getRepositoryRemoteUrl(repoRoot: string, remote: string): Promise<string | null>;
20
- export declare function listWorktrees(cwd: string): Promise<WorktreeEntry[]>;