@solaqua/gji 0.4.1 → 0.6.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.
- package/README.md +37 -3
- package/dist/back.d.ts +13 -0
- package/dist/back.js +74 -0
- package/dist/cli.js +107 -1
- package/dist/config.js +1 -0
- package/dist/editor.d.ts +8 -0
- package/dist/editor.js +17 -0
- package/dist/gji-bundle.mjs +2839 -2124
- package/dist/go.js +24 -4
- package/dist/history-command.d.ts +7 -0
- package/dist/history-command.js +15 -0
- package/dist/history.d.ts +9 -0
- package/dist/history.js +46 -0
- package/dist/hooks.d.ts +5 -4
- package/dist/hooks.js +61 -9
- package/dist/init.js +32 -10
- package/dist/install-prompt.js +9 -1
- package/dist/new.d.ts +3 -0
- package/dist/new.js +36 -1
- package/dist/open.d.ts +20 -0
- package/dist/open.js +155 -0
- package/dist/pr.js +3 -0
- package/dist/repo-registry.d.ts +8 -0
- package/dist/repo-registry.js +52 -0
- package/dist/warp.d.ts +20 -0
- package/dist/warp.js +196 -0
- package/man/man1/gji-back.1 +13 -0
- package/man/man1/gji-clean.1 +1 -1
- package/man/man1/gji-completion.1 +1 -1
- package/man/man1/gji-config.1 +1 -1
- package/man/man1/gji-go.1 +1 -1
- package/man/man1/gji-history.1 +13 -0
- package/man/man1/gji-init.1 +1 -1
- package/man/man1/gji-ls.1 +1 -1
- package/man/man1/gji-new.1 +7 -1
- package/man/man1/gji-open.1 +19 -0
- package/man/man1/gji-pr.1 +1 -1
- package/man/man1/gji-remove.1 +1 -1
- package/man/man1/gji-root.1 +1 -1
- package/man/man1/gji-status.1 +1 -1
- package/man/man1/gji-sync.1 +1 -1
- package/man/man1/gji-trigger-hook.1 +1 -1
- package/man/man1/gji-warp.1 +19 -0
- package/man/man1/gji.1 +19 -1
- package/package.json +4 -2
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { basename, dirname, join, resolve } from 'node:path';
|
|
4
|
+
import { GLOBAL_CONFIG_DIRECTORY } from './config.js';
|
|
5
|
+
const REGISTRY_FILE_NAME = 'repos.json';
|
|
6
|
+
const MAX_REGISTRY_ENTRIES = 100;
|
|
7
|
+
export function REGISTRY_FILE_PATH(home = homedir()) {
|
|
8
|
+
const configDir = process.env.GJI_CONFIG_DIR;
|
|
9
|
+
if (configDir) {
|
|
10
|
+
return join(resolve(configDir), REGISTRY_FILE_NAME);
|
|
11
|
+
}
|
|
12
|
+
return join(home, GLOBAL_CONFIG_DIRECTORY, REGISTRY_FILE_NAME);
|
|
13
|
+
}
|
|
14
|
+
export async function loadRegistry(home = homedir()) {
|
|
15
|
+
const path = REGISTRY_FILE_PATH(home);
|
|
16
|
+
try {
|
|
17
|
+
const raw = await readFile(path, 'utf8');
|
|
18
|
+
const parsed = JSON.parse(raw);
|
|
19
|
+
if (!Array.isArray(parsed))
|
|
20
|
+
return [];
|
|
21
|
+
return parsed.filter(isRegistryEntry);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export async function registerRepo(repoPath, home = homedir()) {
|
|
28
|
+
const registryPath = REGISTRY_FILE_PATH(home);
|
|
29
|
+
const existing = await loadRegistry(home);
|
|
30
|
+
// Skip write if this repo is already the most-recently-used entry (common case).
|
|
31
|
+
if (existing.length > 0 && existing[0].path === repoPath)
|
|
32
|
+
return;
|
|
33
|
+
const entry = {
|
|
34
|
+
lastUsed: Date.now(),
|
|
35
|
+
name: basename(repoPath),
|
|
36
|
+
path: repoPath,
|
|
37
|
+
};
|
|
38
|
+
const filtered = existing.filter((e) => e.path !== repoPath);
|
|
39
|
+
const next = [entry, ...filtered].slice(0, MAX_REGISTRY_ENTRIES);
|
|
40
|
+
await mkdir(dirname(registryPath), { recursive: true });
|
|
41
|
+
await writeFile(registryPath, `${JSON.stringify(next, null, 2)}\n`, 'utf8');
|
|
42
|
+
}
|
|
43
|
+
function isRegistryEntry(value) {
|
|
44
|
+
return (typeof value === 'object' &&
|
|
45
|
+
value !== null &&
|
|
46
|
+
'path' in value &&
|
|
47
|
+
typeof value.path === 'string' &&
|
|
48
|
+
'name' in value &&
|
|
49
|
+
typeof value.name === 'string' &&
|
|
50
|
+
'lastUsed' in value &&
|
|
51
|
+
typeof value.lastUsed === 'number');
|
|
52
|
+
}
|
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
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
.TH GJI\-BACK 1 "May 2026" "gji 0.6.0" "User Commands"
|
|
2
|
+
.SH NAME
|
|
3
|
+
gji\-back \- navigate to the previously visited worktree, optionally N steps back
|
|
4
|
+
.SH SYNOPSIS
|
|
5
|
+
.B gji back [\fIoptions\fR] [options] [n]
|
|
6
|
+
.SH DESCRIPTION
|
|
7
|
+
navigate to the previously visited worktree, optionally N steps back
|
|
8
|
+
.SH OPTIONS
|
|
9
|
+
.TP
|
|
10
|
+
.B \-\-print
|
|
11
|
+
print the resolved worktree path explicitly
|
|
12
|
+
.SH "SEE ALSO"
|
|
13
|
+
.BR gji (1)
|
package/man/man1/gji-clean.1
CHANGED
package/man/man1/gji-config.1
CHANGED
package/man/man1/gji-go.1
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
.TH GJI\-HISTORY 1 "May 2026" "gji 0.6.0" "User Commands"
|
|
2
|
+
.SH NAME
|
|
3
|
+
gji\-history \- show navigation history
|
|
4
|
+
.SH SYNOPSIS
|
|
5
|
+
.B gji history [\fIoptions\fR] [options]
|
|
6
|
+
.SH DESCRIPTION
|
|
7
|
+
show navigation history
|
|
8
|
+
.SH OPTIONS
|
|
9
|
+
.TP
|
|
10
|
+
.B \-\-json
|
|
11
|
+
print history as JSON
|
|
12
|
+
.SH "SEE ALSO"
|
|
13
|
+
.BR gji (1)
|
package/man/man1/gji-init.1
CHANGED
package/man/man1/gji-ls.1
CHANGED
package/man/man1/gji-new.1
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
.TH GJI\-NEW 1 "May 2026" "gji 0.
|
|
1
|
+
.TH GJI\-NEW 1 "May 2026" "gji 0.6.0" "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.0" "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
package/man/man1/gji-remove.1
CHANGED
package/man/man1/gji-root.1
CHANGED
package/man/man1/gji-status.1
CHANGED
package/man/man1/gji-sync.1
CHANGED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
.TH GJI\-WARP 1 "May 2026" "gji 0.6.0" "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)
|
package/man/man1/gji.1
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
.TH GJI 1 "May 2026" "gji 0.
|
|
1
|
+
.TH GJI 1 "May 2026" "gji 0.6.0" "User Commands"
|
|
2
2
|
.SH NAME
|
|
3
3
|
gji \- Context switching without the mess.
|
|
4
4
|
.SH SYNOPSIS
|
|
@@ -23,8 +23,19 @@ print shell completion definitions
|
|
|
23
23
|
.B pr [options] <ref>
|
|
24
24
|
fetch a pull request by number, #number, or URL into a linked worktree
|
|
25
25
|
.TP
|
|
26
|
+
.B back [options] [n]
|
|
27
|
+
navigate to the previously visited worktree, optionally N steps back
|
|
28
|
+
.TP
|
|
29
|
+
.B history [options]
|
|
30
|
+
show navigation history
|
|
31
|
+
.TP
|
|
32
|
+
.B open [options] [branch]
|
|
33
|
+
open the worktree in an editor
|
|
34
|
+
.TP
|
|
26
35
|
.B go [options] [branch]
|
|
27
36
|
print or select a worktree path
|
|
37
|
+
.br
|
|
38
|
+
Alias: \fBjump\fR
|
|
28
39
|
.TP
|
|
29
40
|
.B root [options]
|
|
30
41
|
print the main repository root path
|
|
@@ -49,6 +60,9 @@ Alias: \fBrm\fR
|
|
|
49
60
|
.B trigger\-hook [options] <hook>
|
|
50
61
|
run a named hook (afterCreate, afterEnter, beforeRemove) in the current worktree
|
|
51
62
|
.TP
|
|
63
|
+
.B warp [options] [branch]
|
|
64
|
+
jump to any worktree across all known repos
|
|
65
|
+
.TP
|
|
52
66
|
.B config [options] [command]
|
|
53
67
|
manage global config defaults
|
|
54
68
|
.SH OPTIONS
|
|
@@ -60,6 +74,9 @@ output the version number
|
|
|
60
74
|
.BR gji\-init (1),
|
|
61
75
|
.BR gji\-completion (1),
|
|
62
76
|
.BR gji\-pr (1),
|
|
77
|
+
.BR gji\-back (1),
|
|
78
|
+
.BR gji\-history (1),
|
|
79
|
+
.BR gji\-open (1),
|
|
63
80
|
.BR gji\-go (1),
|
|
64
81
|
.BR gji\-root (1),
|
|
65
82
|
.BR gji\-status (1),
|
|
@@ -68,4 +85,5 @@ output the version number
|
|
|
68
85
|
.BR gji\-clean (1),
|
|
69
86
|
.BR gji\-remove (1),
|
|
70
87
|
.BR gji\-trigger\-hook (1),
|
|
88
|
+
.BR gji\-warp (1),
|
|
71
89
|
.BR gji\-config (1)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solaqua/gji",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Git worktree CLI for fast context switching.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "sjquant",
|
|
@@ -64,6 +64,8 @@
|
|
|
64
64
|
"vitest": "^3.2.4"
|
|
65
65
|
},
|
|
66
66
|
"pnpm": {
|
|
67
|
-
"onlyBuiltDependencies": [
|
|
67
|
+
"onlyBuiltDependencies": [
|
|
68
|
+
"esbuild"
|
|
69
|
+
]
|
|
68
70
|
}
|
|
69
71
|
}
|