@solaqua/gji 0.5.0 → 0.6.1

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.
@@ -1,9 +1,14 @@
1
+ import { KNOWN_GLOBAL_CONFIG_KEYS } from './config.js';
1
2
  const TOP_LEVEL_COMMANDS = [
2
3
  { name: 'new', description: 'create a new branch or detached linked worktree' },
3
4
  { name: 'init', description: 'print or install shell integration' },
4
5
  { name: 'completion', description: 'print shell completion definitions' },
5
6
  { name: 'pr', description: 'fetch a pull request into a linked worktree' },
7
+ { name: 'back', description: 'navigate to the previously visited worktree' },
8
+ { name: 'history', description: 'show navigation history' },
9
+ { name: 'open', description: 'open the worktree in an editor' },
6
10
  { name: 'go', description: 'print or select a worktree path' },
11
+ { name: 'jump', description: 'alias of go' },
7
12
  { name: 'root', description: 'print the main repository root path' },
8
13
  { name: 'status', description: 'summarize repository and worktree health' },
9
14
  { name: 'sync', description: 'fetch and update one or all worktrees' },
@@ -12,20 +17,12 @@ const TOP_LEVEL_COMMANDS = [
12
17
  { name: 'remove', description: 'remove a linked worktree and delete its branch when present' },
13
18
  { name: 'rm', description: 'alias of remove' },
14
19
  { name: 'trigger-hook', description: 'run a named hook in the current worktree' },
20
+ { name: 'warp', description: 'jump to any worktree across all known repos' },
15
21
  { name: 'config', description: 'manage global config defaults' },
16
22
  ];
17
23
  const SHELL_NAMES = ['bash', 'fish', 'zsh'];
18
24
  const HOOK_NAMES = ['afterCreate', 'afterEnter', 'beforeRemove'];
19
- const CONFIG_KEYS = [
20
- 'branchPrefix',
21
- 'syncRemote',
22
- 'syncDefaultBranch',
23
- 'syncFiles',
24
- 'skipInstallPrompt',
25
- 'installSaveTarget',
26
- 'hooks',
27
- 'repos',
28
- ];
25
+ const CONFIG_KEYS = Array.from(KNOWN_GLOBAL_CONFIG_KEYS);
29
26
  export function renderShellCompletion(shell) {
30
27
  switch (shell) {
31
28
  case 'bash':
@@ -59,7 +56,7 @@ _gji_completion() {
59
56
 
60
57
  case "$command_name" in
61
58
  new)
62
- COMPREPLY=( $(compgen -W "--detached --dry-run --json --help" -- "$cur") )
59
+ COMPREPLY=( $(compgen -W "--detached --force --open --editor --dry-run --json --help" -- "$cur") )
63
60
  ;;
64
61
  init)
65
62
  COMPREPLY=( $(compgen -W "${shells} --write --help" -- "$cur") )
@@ -70,7 +67,16 @@ _gji_completion() {
70
67
  pr)
71
68
  COMPREPLY=( $(compgen -W "--dry-run --json --help" -- "$cur") )
72
69
  ;;
73
- go)
70
+ back)
71
+ COMPREPLY=( $(compgen -W "--print --help" -- "$cur") )
72
+ ;;
73
+ history)
74
+ COMPREPLY=( $(compgen -W "--json --help" -- "$cur") )
75
+ ;;
76
+ open)
77
+ COMPREPLY=( $(compgen -W "$(__gji_worktree_branches) --editor --save --workspace --help" -- "$cur") )
78
+ ;;
79
+ go|jump)
74
80
  COMPREPLY=( $(compgen -W "$(__gji_worktree_branches) --print --help" -- "$cur") )
75
81
  ;;
76
82
  root)
@@ -94,6 +100,9 @@ _gji_completion() {
94
100
  trigger-hook)
95
101
  COMPREPLY=( $(compgen -W "${hooks} --help" -- "$cur") )
96
102
  ;;
103
+ warp)
104
+ COMPREPLY=( $(compgen -W "-n --new --print --json --help" -- "$cur") )
105
+ ;;
97
106
  config)
98
107
  if [ "$COMP_CWORD" -eq 2 ]; then
99
108
  COMPREPLY=( $(compgen -W "get set unset" -- "$cur") )
@@ -149,6 +158,9 @@ complete -c gji -f
149
158
  ${commandLines}
150
159
 
151
160
  complete -c gji -n '__fish_seen_subcommand_from new' -l detached -d 'create a detached worktree without a branch'
161
+ complete -c gji -n '__fish_seen_subcommand_from new' -l force -d 'remove and recreate the worktree if the target path already exists'
162
+ complete -c gji -n '__fish_seen_subcommand_from new' -l open -d 'open the new worktree in an editor after creation'
163
+ complete -c gji -n '__fish_seen_subcommand_from new' -l editor -r -d 'editor CLI to use with --open (code, cursor, zed, …)'
152
164
  complete -c gji -n '__fish_seen_subcommand_from new' -l dry-run -d 'show what would be created without executing any git commands or writing files'
153
165
  complete -c gji -n '__fish_seen_subcommand_from new' -l json -d 'emit JSON on success or error instead of human-readable output'
154
166
 
@@ -162,8 +174,17 @@ complete -c gji -n '__fish_seen_subcommand_from completion' -a 'zsh' -d 'shell'
162
174
  complete -c gji -n '__fish_seen_subcommand_from pr' -l dry-run -d 'show what would be created without executing any git commands or writing files'
163
175
  complete -c gji -n '__fish_seen_subcommand_from pr' -l json -d 'emit JSON on success or error instead of human-readable output'
164
176
 
165
- complete -c gji -n '__fish_seen_subcommand_from go' -l print -d 'print the resolved worktree path explicitly'
166
- complete -c gji -n '__fish_seen_subcommand_from go' -a '(__gji_worktree_branches)' -d 'worktree branch'
177
+ complete -c gji -n '__fish_seen_subcommand_from back' -l print -d 'print the resolved worktree path explicitly'
178
+
179
+ complete -c gji -n '__fish_seen_subcommand_from history' -l json -d 'print history as JSON'
180
+
181
+ complete -c gji -n '__fish_seen_subcommand_from open' -l editor -r -d 'editor CLI to use (code, cursor, zed, windsurf, subl, …)'
182
+ complete -c gji -n '__fish_seen_subcommand_from open' -l save -d 'save the chosen editor to global config'
183
+ complete -c gji -n '__fish_seen_subcommand_from open' -l workspace -d 'generate a .code-workspace file before opening (VS Code / Cursor / Windsurf)'
184
+ complete -c gji -n '__fish_seen_subcommand_from open' -a '(__gji_worktree_branches)' -d 'worktree branch'
185
+
186
+ complete -c gji -n '__fish_seen_subcommand_from go jump' -l print -d 'print the resolved worktree path explicitly'
187
+ complete -c gji -n '__fish_seen_subcommand_from go jump' -a '(__gji_worktree_branches)' -d 'worktree branch'
167
188
 
168
189
  complete -c gji -n '__fish_seen_subcommand_from root' -l print -d 'print the resolved repository root path explicitly'
169
190
 
@@ -187,6 +208,10 @@ complete -c gji -n '__fish_seen_subcommand_from remove rm' -a '(__gji_worktree_b
187
208
 
188
209
  ${hookLines}
189
210
 
211
+ complete -c gji -n '__fish_seen_subcommand_from warp' -s n -l new -d 'create a new worktree in a registered repo'
212
+ complete -c gji -n '__fish_seen_subcommand_from warp' -l print -d 'print the resolved worktree path without changing directory'
213
+ complete -c gji -n '__fish_seen_subcommand_from warp' -l json -d 'emit JSON on success or error instead of human-readable output'
214
+
190
215
  complete -c gji -n '__fish_seen_subcommand_from config; and __gji_should_complete_config_action' -a 'get set unset' -d 'config action'
191
216
  ${configKeyLines}`;
192
217
  }
@@ -195,89 +220,99 @@ function renderZshCompletion() {
195
220
  const configKeys = CONFIG_KEYS.join(' ');
196
221
  const shells = SHELL_NAMES.join(' ');
197
222
  const hooks = HOOK_NAMES.join(' ');
198
- return `__gji_worktree_branches() {
223
+ return `#compdef gji
224
+
225
+ __gji_worktree_branches() {
199
226
  command gji ls --compact 2>/dev/null | awk 'NR > 1 { branch = ($1 == "*" ? $2 : $1); if (branch != "(detached)") print branch }'
200
227
  }
201
228
 
202
- _gji_completion() {
203
- local context state line
204
- local -a commands worktree_branches
205
-
206
- commands=(
207
- ${commandLines}
208
- )
229
+ local context state line
230
+ local -a commands worktree_branches
209
231
 
210
- if (( CURRENT == 2 )); then
211
- _describe 'command' commands
212
- return
213
- fi
232
+ commands=(
233
+ ${commandLines}
234
+ )
214
235
 
215
- case "\${words[2]}" in
216
- new)
217
- _arguments '--detached[create a detached worktree without a branch]' '--dry-run[show what would be created without executing any git commands or writing files]' '--json[emit JSON on success or error instead of human-readable output]' '2:branch: '
218
- ;;
219
- init)
220
- _arguments '--write[write the integration to the shell config file]' '2:shell:(${shells})'
221
- ;;
222
- completion)
223
- _arguments '2:shell:(${shells})'
224
- ;;
225
- pr)
226
- _arguments '--dry-run[show what would be created without executing any git commands or writing files]' '--json[emit JSON on success or error instead of human-readable output]' '2:ref: '
227
- ;;
228
- go)
229
- _arguments '--print[print the resolved worktree path explicitly]' '2:branch:->worktrees'
230
- ;;
231
- root)
232
- _arguments '--print[print the resolved repository root path explicitly]'
233
- ;;
234
- status)
235
- _arguments '--json[print repository and worktree health as JSON]'
236
- ;;
237
- sync)
238
- _arguments '--all[sync every worktree in the repository]' '--json[emit JSON on success or error instead of human-readable output]'
239
- ;;
240
- ls)
241
- _arguments '--compact[show only branch and path columns]' '--json[print active worktrees as JSON]'
242
- ;;
243
- clean)
244
- _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]'
245
- ;;
246
- remove|rm)
247
- _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'
248
- ;;
249
- trigger-hook)
250
- _arguments "2:hook:(${hooks})"
251
- ;;
252
- config)
253
- if (( CURRENT == 3 )); then
254
- _values 'config action' get set unset
255
- return
256
- fi
236
+ if (( CURRENT == 2 )); then
237
+ _describe 'command' commands
238
+ return
239
+ fi
257
240
 
258
- case "\${words[3]}" in
259
- get|unset)
260
- _arguments '3:key:->config_keys'
261
- ;;
262
- set)
263
- _arguments '3:key:->config_keys' '4:value: '
264
- ;;
265
- esac
266
- ;;
267
- esac
241
+ case "\${words[2]}" in
242
+ new)
243
+ _arguments '--detached[create a detached worktree without a branch]' '--force[remove and recreate the worktree if the target path already exists]' '--open[open the new worktree in an editor after creation]' '--editor[editor CLI to use with --open (code, cursor, zed, …)]:editor:' '--dry-run[show what would be created without executing any git commands or writing files]' '--json[emit JSON on success or error instead of human-readable output]' '2:branch: '
244
+ ;;
245
+ init)
246
+ _arguments '--write[write the integration to the shell config file]' '2:shell:(${shells})'
247
+ ;;
248
+ completion)
249
+ _arguments '2:shell:(${shells})'
250
+ ;;
251
+ pr)
252
+ _arguments '--dry-run[show what would be created without executing any git commands or writing files]' '--json[emit JSON on success or error instead of human-readable output]' '2:ref: '
253
+ ;;
254
+ back)
255
+ _arguments '--print[print the resolved worktree path explicitly]' '2:steps: '
256
+ ;;
257
+ history)
258
+ _arguments '--json[print history as JSON]'
259
+ ;;
260
+ open)
261
+ _arguments '--editor[editor CLI to use (code, cursor, zed, windsurf, subl, …)]:editor:' '--save[save the chosen editor to global config]' '--workspace[generate a .code-workspace file before opening (VS Code / Cursor / Windsurf)]' '2:branch:->worktrees'
262
+ ;;
263
+ go|jump)
264
+ _arguments '--print[print the resolved worktree path explicitly]' '2:branch:->worktrees'
265
+ ;;
266
+ root)
267
+ _arguments '--print[print the resolved repository root path explicitly]'
268
+ ;;
269
+ status)
270
+ _arguments '--json[print repository and worktree health as JSON]'
271
+ ;;
272
+ sync)
273
+ _arguments '--all[sync every worktree in the repository]' '--json[emit JSON on success or error instead of human-readable output]'
274
+ ;;
275
+ ls)
276
+ _arguments '--compact[show only branch and path columns]' '--json[print active worktrees as JSON]'
277
+ ;;
278
+ clean)
279
+ _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]'
280
+ ;;
281
+ remove|rm)
282
+ _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'
283
+ ;;
284
+ trigger-hook)
285
+ _arguments "2:hook:(${hooks})"
286
+ ;;
287
+ warp)
288
+ _arguments '(-n --new)'{-n,--new}'[create a new worktree in a registered repo]:branch:' '--print[print the resolved worktree path without changing directory]' '--json[emit JSON on success or error instead of human-readable output]' '2:branch: '
289
+ ;;
290
+ config)
291
+ if (( CURRENT == 3 )); then
292
+ _values 'config action' get set unset
293
+ return
294
+ fi
268
295
 
269
- case "$state" in
270
- worktrees)
271
- worktree_branches=(\${(@f)$(__gji_worktree_branches)})
272
- _describe 'worktree branch' worktree_branches
273
- ;;
274
- config_keys)
275
- _values 'config key' ${configKeys}
276
- ;;
277
- esac
278
- }
296
+ case "\${words[3]}" in
297
+ get|unset)
298
+ _arguments '3:key:->config_keys'
299
+ ;;
300
+ set)
301
+ _arguments '3:key:->config_keys' '4:value: '
302
+ ;;
303
+ esac
304
+ ;;
305
+ esac
279
306
 
280
- compdef _gji_completion gji`;
307
+ case "$state" in
308
+ worktrees)
309
+ worktree_branches=(\${(@f)$(__gji_worktree_branches)})
310
+ _describe 'worktree branch' worktree_branches
311
+ ;;
312
+ config_keys)
313
+ _values 'config key' ${configKeys}
314
+ ;;
315
+ esac`;
281
316
  }
282
317
  function escapeSingleQuotes(value) {
283
318
  return value.replace(/'/g, `'\\''`);
package/dist/warp.d.ts ADDED
@@ -0,0 +1,20 @@
1
+ export interface WarpCommandOptions {
2
+ branch?: string;
3
+ cwd: string;
4
+ json?: boolean;
5
+ newWorktree?: boolean;
6
+ stderr: (chunk: string) => void;
7
+ stdout: (chunk: string) => void;
8
+ }
9
+ export declare function runWarpCommand(options: WarpCommandOptions): Promise<number>;
10
+ export interface WarpTarget {
11
+ branch: string | null;
12
+ path: string;
13
+ }
14
+ export declare function resolveWarpTarget(options: {
15
+ branch?: string;
16
+ commandName?: string;
17
+ cwd: string;
18
+ json?: boolean;
19
+ stderr: (chunk: string) => void;
20
+ }): Promise<WarpTarget | null>;
package/dist/warp.js ADDED
@@ -0,0 +1,196 @@
1
+ import { isCancel, select } from '@clack/prompts';
2
+ import { readWorktreeHealth } from './git.js';
3
+ import { isHeadless } from './headless.js';
4
+ import { appendHistory } from './history.js';
5
+ import { runNewCommand } from './new.js';
6
+ import { loadRegistry } from './repo-registry.js';
7
+ import { listWorktrees } from './repo.js';
8
+ import { writeShellOutput } from './shell-handoff.js';
9
+ const WARP_OUTPUT_FILE_ENV = 'GJI_WARP_OUTPUT_FILE';
10
+ export async function runWarpCommand(options) {
11
+ if (options.newWorktree) {
12
+ const registry = await loadRegistry();
13
+ if (registry.length === 0) {
14
+ options.stderr('gji warp: no repos registered yet.\n' +
15
+ 'Use any gji command in a repository to register it automatically.\n');
16
+ return 1;
17
+ }
18
+ return runWarpNew(options, registry);
19
+ }
20
+ return runWarpNavigate(options);
21
+ }
22
+ async function runWarpNavigate(options) {
23
+ if ((isHeadless() || options.json) && !options.branch) {
24
+ const message = 'branch argument is required';
25
+ if (options.json) {
26
+ options.stderr(`${JSON.stringify({ error: message }, null, 2)}\n`);
27
+ }
28
+ else {
29
+ options.stderr('gji warp: branch argument is required in non-interactive mode (GJI_NO_TUI=1)\n');
30
+ }
31
+ return 1;
32
+ }
33
+ const target = await resolveWarpTarget({ ...options, commandName: 'gji warp', json: options.json });
34
+ if (!target)
35
+ return 1;
36
+ if (options.json) {
37
+ // json callers use the output programmatically; skip history and shell handoff.
38
+ options.stdout(`${JSON.stringify({ branch: target.branch, path: target.path }, null, 2)}\n`);
39
+ return 0;
40
+ }
41
+ appendHistory(target.path, target.branch).catch(() => undefined);
42
+ await writeShellOutput(WARP_OUTPUT_FILE_ENV, target.path, options.stdout);
43
+ return 0;
44
+ }
45
+ async function runWarpNew(options, registry) {
46
+ let targetRepoRoot;
47
+ if (registry.length === 1) {
48
+ targetRepoRoot = registry[0].path;
49
+ }
50
+ else {
51
+ if (isHeadless()) {
52
+ options.stderr('gji warp: repo argument is required in non-interactive mode (GJI_NO_TUI=1)\n');
53
+ return 1;
54
+ }
55
+ const choice = await select({
56
+ message: 'Create worktree in which repo?',
57
+ options: registry.map((entry) => ({
58
+ value: entry.path,
59
+ label: entry.name,
60
+ hint: entry.path,
61
+ })),
62
+ });
63
+ if (isCancel(choice)) {
64
+ options.stderr('Aborted\n');
65
+ return 1;
66
+ }
67
+ targetRepoRoot = choice;
68
+ }
69
+ if (options.json) {
70
+ return runNewCommand({
71
+ branch: options.branch,
72
+ cwd: targetRepoRoot,
73
+ json: true,
74
+ stderr: options.stderr,
75
+ stdout: options.stdout,
76
+ });
77
+ }
78
+ // runNewCommand writes the created path to options.stdout via writeShellOutput.
79
+ // Since GJI_NEW_OUTPUT_FILE is not set in the warp shell context, it falls
80
+ // through to our captured stdout, giving us the path to hand off.
81
+ let capturedPath = '';
82
+ const captureStdout = (chunk) => {
83
+ capturedPath = chunk.trim();
84
+ };
85
+ const exitCode = await runNewCommand({
86
+ branch: options.branch,
87
+ cwd: targetRepoRoot,
88
+ stderr: options.stderr,
89
+ stdout: captureStdout,
90
+ });
91
+ if (exitCode !== 0) {
92
+ return exitCode;
93
+ }
94
+ if (!capturedPath) {
95
+ options.stderr('gji warp: could not determine new worktree path\n');
96
+ return 1;
97
+ }
98
+ await writeShellOutput(WARP_OUTPUT_FILE_ENV, capturedPath, options.stdout);
99
+ return 0;
100
+ }
101
+ function findByQuery(items, query) {
102
+ const slashIdx = query.indexOf('/');
103
+ if (slashIdx !== -1) {
104
+ const repoQuery = query.slice(0, slashIdx);
105
+ const branchQuery = query.slice(slashIdx + 1);
106
+ const match = items.find((item) => item.repoName === repoQuery && item.worktree.branch === branchQuery);
107
+ if (match)
108
+ return match;
109
+ }
110
+ return items.find((item) => item.worktree.branch === query) ?? null;
111
+ }
112
+ export async function resolveWarpTarget(options) {
113
+ const cmd = options.commandName ?? 'gji';
114
+ const emitError = (message, hint) => {
115
+ if (options.json) {
116
+ options.stderr(`${JSON.stringify({ error: message }, null, 2)}\n`);
117
+ }
118
+ else {
119
+ options.stderr(`${cmd}: ${message}\n`);
120
+ if (hint)
121
+ options.stderr(hint);
122
+ }
123
+ };
124
+ const registry = await loadRegistry();
125
+ if (registry.length === 0) {
126
+ emitError('not in a git repository and no repos registered yet.', 'Use any gji command inside a repository to register it.\n');
127
+ return null;
128
+ }
129
+ const results = await Promise.allSettled(registry.map(async (entry) => {
130
+ const worktrees = await listWorktrees(entry.path);
131
+ return { repoName: entry.name, worktrees };
132
+ }));
133
+ const allItems = [];
134
+ for (const result of results) {
135
+ if (result.status === 'rejected')
136
+ continue;
137
+ const { repoName, worktrees } = result.value;
138
+ for (const worktree of worktrees) {
139
+ allItems.push({ repoName, worktree });
140
+ }
141
+ }
142
+ if (allItems.length === 0) {
143
+ emitError('no accessible worktrees found in any registered repo.');
144
+ return null;
145
+ }
146
+ if (options.branch) {
147
+ const match = findByQuery(allItems, options.branch);
148
+ if (!match) {
149
+ emitError(`no worktree found matching: ${options.branch}`);
150
+ return null;
151
+ }
152
+ return { branch: match.worktree.branch, path: match.worktree.path };
153
+ }
154
+ const path = await promptForWarpTarget(allItems);
155
+ if (!path) {
156
+ options.stderr('Aborted\n');
157
+ return null;
158
+ }
159
+ const chosen = allItems.find((item) => item.worktree.path === path);
160
+ return { branch: chosen?.worktree.branch ?? null, path };
161
+ }
162
+ async function promptForWarpTarget(items) {
163
+ const healthResults = await Promise.allSettled(items.map((item) => readWorktreeHealth(item.worktree.path)));
164
+ const choice = await select({
165
+ message: 'Warp to a worktree',
166
+ options: items.map((item, i) => {
167
+ const health = healthResults[i].status === 'fulfilled' ? healthResults[i].value : null;
168
+ const upstream = health ? formatHint(item.worktree.branch, health) : null;
169
+ const label = `${item.repoName} › ${item.worktree.branch ?? '(detached)'}`;
170
+ const pathHint = item.worktree.isCurrent
171
+ ? `${item.worktree.path} (current)`
172
+ : item.worktree.path;
173
+ const hint = upstream ? `${upstream} · ${pathHint}` : pathHint;
174
+ return { hint, label, value: item.worktree.path };
175
+ }),
176
+ });
177
+ if (isCancel(choice)) {
178
+ return null;
179
+ }
180
+ return choice;
181
+ }
182
+ function formatHint(branch, health) {
183
+ if (branch === null)
184
+ return null;
185
+ if (!health.hasUpstream)
186
+ return 'no upstream';
187
+ if (health.upstreamGone)
188
+ return 'upstream gone';
189
+ if (health.ahead === 0 && health.behind === 0)
190
+ return 'up to date';
191
+ if (health.ahead === 0)
192
+ return `behind ${health.behind}`;
193
+ if (health.behind === 0)
194
+ return `ahead ${health.ahead}`;
195
+ return `ahead ${health.ahead}, behind ${health.behind}`;
196
+ }
@@ -1,4 +1,4 @@
1
- .TH GJI\-BACK 1 "May 2026" "gji 0.5.0" "User Commands"
1
+ .TH GJI\-BACK 1 "May 2026" "gji 0.6.1" "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 "May 2026" "gji 0.5.0" "User Commands"
1
+ .TH GJI\-CLEAN 1 "May 2026" "gji 0.6.1" "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 "May 2026" "gji 0.5.0" "User Commands"
1
+ .TH GJI\-COMPLETION 1 "May 2026" "gji 0.6.1" "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 "May 2026" "gji 0.5.0" "User Commands"
1
+ .TH GJI\-CONFIG 1 "May 2026" "gji 0.6.1" "User Commands"
2
2
  .SH NAME
3
3
  gji\-config \- manage global config defaults
4
4
  .SH SYNOPSIS
package/man/man1/gji-go.1 CHANGED
@@ -1,4 +1,4 @@
1
- .TH GJI\-GO 1 "May 2026" "gji 0.5.0" "User Commands"
1
+ .TH GJI\-GO 1 "May 2026" "gji 0.6.1" "User Commands"
2
2
  .SH NAME
3
3
  gji\-go \- print or select a worktree path
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-HISTORY 1 "May 2026" "gji 0.5.0" "User Commands"
1
+ .TH GJI\-HISTORY 1 "May 2026" "gji 0.6.1" "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 "May 2026" "gji 0.5.0" "User Commands"
1
+ .TH GJI\-INIT 1 "May 2026" "gji 0.6.1" "User Commands"
2
2
  .SH NAME
3
3
  gji\-init \- print or install shell integration
4
4
  .SH SYNOPSIS
package/man/man1/gji-ls.1 CHANGED
@@ -1,4 +1,4 @@
1
- .TH GJI\-LS 1 "May 2026" "gji 0.5.0" "User Commands"
1
+ .TH GJI\-LS 1 "May 2026" "gji 0.6.1" "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 "May 2026" "gji 0.5.0" "User Commands"
1
+ .TH GJI\-NEW 1 "May 2026" "gji 0.6.1" "User Commands"
2
2
  .SH NAME
3
3
  gji\-new \- create a new branch or detached linked worktree
4
4
  .SH SYNOPSIS
@@ -13,6 +13,12 @@ remove and recreate the worktree if the target path already exists
13
13
  .B \-\-detached
14
14
  create a detached worktree without a branch
15
15
  .TP
16
+ .B \-\-open
17
+ open the new worktree in an editor after creation
18
+ .TP
19
+ .B \-\-editor <cli>
20
+ editor CLI to use with \-\-open (code, cursor, zed, …)
21
+ .TP
16
22
  .B \-\-dry\-run
17
23
  show what would be created without executing any git commands or writing files
18
24
  .TP
@@ -0,0 +1,19 @@
1
+ .TH GJI\-OPEN 1 "May 2026" "gji 0.6.1" "User Commands"
2
+ .SH NAME
3
+ gji\-open \- open the worktree in an editor
4
+ .SH SYNOPSIS
5
+ .B gji open [\fIoptions\fR] [options] [branch]
6
+ .SH DESCRIPTION
7
+ open the worktree in an editor
8
+ .SH OPTIONS
9
+ .TP
10
+ .B \-\-editor <cli>
11
+ editor CLI to use (code, cursor, zed, windsurf, subl, …)
12
+ .TP
13
+ .B \-\-save
14
+ save the chosen editor to global config
15
+ .TP
16
+ .B \-\-workspace
17
+ generate a .code\-workspace file before opening (VS Code / Cursor / Windsurf)
18
+ .SH "SEE ALSO"
19
+ .BR gji (1)
package/man/man1/gji-pr.1 CHANGED
@@ -1,4 +1,4 @@
1
- .TH GJI\-PR 1 "May 2026" "gji 0.5.0" "User Commands"
1
+ .TH GJI\-PR 1 "May 2026" "gji 0.6.1" "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 "May 2026" "gji 0.5.0" "User Commands"
1
+ .TH GJI\-REMOVE 1 "May 2026" "gji 0.6.1" "User Commands"
2
2
  .SH NAME
3
3
  gji\-remove \- remove a linked worktree and delete its branch when present
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-ROOT 1 "May 2026" "gji 0.5.0" "User Commands"
1
+ .TH GJI\-ROOT 1 "May 2026" "gji 0.6.1" "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\-STATUS 1 "May 2026" "gji 0.5.0" "User Commands"
1
+ .TH GJI\-STATUS 1 "May 2026" "gji 0.6.1" "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 1 "May 2026" "gji 0.5.0" "User Commands"
1
+ .TH GJI\-SYNC 1 "May 2026" "gji 0.6.1" "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\-TRIGGER\-HOOK 1 "May 2026" "gji 0.5.0" "User Commands"
1
+ .TH GJI\-TRIGGER\-HOOK 1 "May 2026" "gji 0.6.1" "User Commands"
2
2
  .SH NAME
3
3
  gji\-trigger\-hook \- run a named hook (afterCreate, afterEnter, beforeRemove) in the current worktree
4
4
  .SH SYNOPSIS
@@ -0,0 +1,19 @@
1
+ .TH GJI\-WARP 1 "May 2026" "gji 0.6.1" "User Commands"
2
+ .SH NAME
3
+ gji\-warp \- jump to any worktree across all known repos
4
+ .SH SYNOPSIS
5
+ .B gji warp [\fIoptions\fR] [options] [branch]
6
+ .SH DESCRIPTION
7
+ jump to any worktree across all known repos
8
+ .SH OPTIONS
9
+ .TP
10
+ .B \-n, \-\-new [branch]
11
+ create a new worktree in a registered repo
12
+ .TP
13
+ .B \-\-print
14
+ print the resolved worktree path without changing directory
15
+ .TP
16
+ .B \-\-json
17
+ emit JSON on success or error instead of human\-readable output
18
+ .SH "SEE ALSO"
19
+ .BR gji (1)