@solaqua/gji 0.3.0 → 0.4.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.
- package/README.md +124 -11
- package/dist/clean.d.ts +1 -0
- package/dist/clean.js +103 -13
- package/dist/cli.js +62 -4
- package/dist/completion.d.ts +6 -0
- package/dist/completion.js +11 -0
- package/dist/config.js +1 -0
- package/dist/git.d.ts +3 -0
- package/dist/git.js +38 -0
- package/dist/gji +5 -0
- package/dist/gji-bundle.mjs +16536 -0
- package/dist/index.js +25 -1
- package/dist/init.d.ts +12 -2
- package/dist/init.js +100 -37
- package/dist/ls.d.ts +3 -0
- package/dist/ls.js +46 -2
- package/dist/pr.js +43 -1
- package/dist/shell-completion.d.ts +1 -0
- package/dist/shell-completion.js +284 -0
- package/dist/shell.d.ts +2 -0
- package/dist/shell.js +21 -0
- package/dist/sync.js +2 -13
- package/dist/worktree-info.d.ts +33 -0
- package/dist/worktree-info.js +105 -0
- package/man/man1/gji-clean.1 +22 -0
- package/man/man1/gji-completion.1 +9 -0
- package/man/man1/gji-config.1 +19 -0
- package/man/man1/gji-go.1 +13 -0
- package/man/man1/gji-init.1 +13 -0
- package/man/man1/gji-ls.1 +16 -0
- package/man/man1/gji-new.1 +22 -0
- package/man/man1/gji-pr.1 +16 -0
- package/man/man1/gji-remove.1 +19 -0
- package/man/man1/gji-root.1 +13 -0
- package/man/man1/gji-status.1 +13 -0
- package/man/man1/gji-sync.1 +16 -0
- package/man/man1/gji-trigger-hook.1 +9 -0
- package/man/man1/gji.1 +71 -0
- package/package.json +17 -3
package/dist/shell.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export function resolveSupportedShell(requestedShell, detectedShell) {
|
|
2
|
+
const requested = normalizeShell(requestedShell);
|
|
3
|
+
if (requested) {
|
|
4
|
+
return requested;
|
|
5
|
+
}
|
|
6
|
+
return normalizeShell(detectedShell);
|
|
7
|
+
}
|
|
8
|
+
function normalizeShell(value) {
|
|
9
|
+
if (!value) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
const candidate = value.split('/').at(-1)?.toLowerCase();
|
|
13
|
+
switch (candidate) {
|
|
14
|
+
case 'bash':
|
|
15
|
+
case 'fish':
|
|
16
|
+
case 'zsh':
|
|
17
|
+
return candidate;
|
|
18
|
+
default:
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
}
|
package/dist/sync.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { loadEffectiveConfig } from './config.js';
|
|
2
|
-
import { isDirtyWorktree, runGit } from './git.js';
|
|
2
|
+
import { isDirtyWorktree, resolveRemoteDefaultBranch, runGit } from './git.js';
|
|
3
3
|
import { comparePaths } from './paths.js';
|
|
4
4
|
import { detectRepository, listWorktrees } from './repo.js';
|
|
5
5
|
export async function runSyncCommand(options) {
|
|
@@ -10,7 +10,7 @@ export async function runSyncCommand(options) {
|
|
|
10
10
|
let defaultBranch;
|
|
11
11
|
try {
|
|
12
12
|
defaultBranch = resolveConfiguredString(config.syncDefaultBranch)
|
|
13
|
-
?? await
|
|
13
|
+
?? await resolveRemoteDefaultBranch(repository.repoRoot, remote);
|
|
14
14
|
}
|
|
15
15
|
catch {
|
|
16
16
|
emitError(options, `Unable to reach remote '${remote}'`);
|
|
@@ -89,17 +89,6 @@ function selectTargetWorktrees(worktrees, currentRoot, all) {
|
|
|
89
89
|
}
|
|
90
90
|
return [currentWorktree];
|
|
91
91
|
}
|
|
92
|
-
async function resolveDefaultBranch(repoRoot, remote) {
|
|
93
|
-
const stdout = await runGit(repoRoot, ['ls-remote', '--symref', remote, 'HEAD']);
|
|
94
|
-
const refLine = stdout
|
|
95
|
-
.split('\n')
|
|
96
|
-
.find((line) => line.startsWith('ref: refs/heads/'));
|
|
97
|
-
if (!refLine) {
|
|
98
|
-
return null;
|
|
99
|
-
}
|
|
100
|
-
const match = /^ref: refs\/heads\/(.+)\tHEAD$/.exec(refLine);
|
|
101
|
-
return match?.[1] ?? null;
|
|
102
|
-
}
|
|
103
92
|
function resolveConfiguredString(value) {
|
|
104
93
|
return typeof value === 'string' && value.length > 0 ? value : null;
|
|
105
94
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type WorktreeHealth } from './git.js';
|
|
2
|
+
import type { WorktreeEntry } from './repo.js';
|
|
3
|
+
export interface WorktreeInfo extends WorktreeEntry {
|
|
4
|
+
lastCommitTimestamp: number | null;
|
|
5
|
+
status: WorktreeHealth['status'] | 'unknown';
|
|
6
|
+
upstream: UpstreamState;
|
|
7
|
+
}
|
|
8
|
+
export interface SerializedWorktreeInfo {
|
|
9
|
+
branch: string | null;
|
|
10
|
+
lastCommitTimestamp: number | null;
|
|
11
|
+
path: string;
|
|
12
|
+
status: WorktreeInfo['status'];
|
|
13
|
+
upstream: UpstreamState;
|
|
14
|
+
}
|
|
15
|
+
export type UpstreamState = {
|
|
16
|
+
kind: 'detached';
|
|
17
|
+
} | {
|
|
18
|
+
kind: 'no-upstream';
|
|
19
|
+
} | {
|
|
20
|
+
kind: 'stale';
|
|
21
|
+
} | {
|
|
22
|
+
kind: 'tracked';
|
|
23
|
+
ahead: number;
|
|
24
|
+
behind: number;
|
|
25
|
+
} | {
|
|
26
|
+
kind: 'unknown';
|
|
27
|
+
};
|
|
28
|
+
export declare function readWorktreeInfos(worktrees: WorktreeEntry[]): Promise<WorktreeInfo[]>;
|
|
29
|
+
export declare function serializeWorktreeInfo(info: WorktreeInfo): SerializedWorktreeInfo;
|
|
30
|
+
export declare function formatWorktreeHint(info: WorktreeInfo): string;
|
|
31
|
+
export declare function formatUpstreamState(upstream: UpstreamState): string;
|
|
32
|
+
export declare function formatLastCommit(timestampSeconds: number | null): string;
|
|
33
|
+
export declare function formatRelativeAge(timestampSeconds: number): string;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { readBranchLastCommitTimestamp, readWorktreeHealth } from './git.js';
|
|
2
|
+
export async function readWorktreeInfos(worktrees) {
|
|
3
|
+
return Promise.all(worktrees.map((worktree) => readWorktreeInfo(worktree)));
|
|
4
|
+
}
|
|
5
|
+
async function readWorktreeInfo(worktree) {
|
|
6
|
+
const [healthResult, lastCommitResult] = await Promise.allSettled([
|
|
7
|
+
readWorktreeHealth(worktree.path),
|
|
8
|
+
worktree.branch === null ? null : readBranchLastCommitTimestamp(worktree.path, worktree.branch),
|
|
9
|
+
]);
|
|
10
|
+
const health = healthResult.status === 'fulfilled' ? healthResult.value : null;
|
|
11
|
+
const lastCommitTimestamp = lastCommitResult.status === 'fulfilled'
|
|
12
|
+
? lastCommitResult.value
|
|
13
|
+
: null;
|
|
14
|
+
return {
|
|
15
|
+
...worktree,
|
|
16
|
+
lastCommitTimestamp,
|
|
17
|
+
status: health?.status ?? 'unknown',
|
|
18
|
+
upstream: buildUpstreamState(worktree.branch, health),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function buildUpstreamState(branch, health) {
|
|
22
|
+
if (branch === null) {
|
|
23
|
+
return { kind: 'detached' };
|
|
24
|
+
}
|
|
25
|
+
if (health === null) {
|
|
26
|
+
return { kind: 'unknown' };
|
|
27
|
+
}
|
|
28
|
+
if (!health.hasUpstream) {
|
|
29
|
+
return { kind: 'no-upstream' };
|
|
30
|
+
}
|
|
31
|
+
if (health.upstreamGone) {
|
|
32
|
+
return { kind: 'stale' };
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
ahead: health.ahead,
|
|
36
|
+
behind: health.behind,
|
|
37
|
+
kind: 'tracked',
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export function serializeWorktreeInfo(info) {
|
|
41
|
+
return {
|
|
42
|
+
branch: info.branch,
|
|
43
|
+
lastCommitTimestamp: info.lastCommitTimestamp,
|
|
44
|
+
path: info.path,
|
|
45
|
+
status: info.status,
|
|
46
|
+
upstream: info.upstream,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
export function formatWorktreeHint(info) {
|
|
50
|
+
const details = [
|
|
51
|
+
`status: ${info.status}`,
|
|
52
|
+
`upstream: ${formatUpstreamState(info.upstream)}`,
|
|
53
|
+
];
|
|
54
|
+
if (info.lastCommitTimestamp !== null) {
|
|
55
|
+
details.push(`last: ${formatRelativeAge(info.lastCommitTimestamp)}`);
|
|
56
|
+
}
|
|
57
|
+
return `${info.path} (${details.join(', ')})`;
|
|
58
|
+
}
|
|
59
|
+
export function formatUpstreamState(upstream) {
|
|
60
|
+
if (upstream.kind === 'detached') {
|
|
61
|
+
return 'n/a';
|
|
62
|
+
}
|
|
63
|
+
if (upstream.kind === 'no-upstream') {
|
|
64
|
+
return 'no-upstream';
|
|
65
|
+
}
|
|
66
|
+
if (upstream.kind === 'stale') {
|
|
67
|
+
return 'gone';
|
|
68
|
+
}
|
|
69
|
+
if (upstream.kind === 'unknown') {
|
|
70
|
+
return 'unknown';
|
|
71
|
+
}
|
|
72
|
+
return formatAheadBehind(upstream.ahead, upstream.behind);
|
|
73
|
+
}
|
|
74
|
+
function formatAheadBehind(ahead, behind) {
|
|
75
|
+
if (ahead === 0 && behind === 0) {
|
|
76
|
+
return 'up to date';
|
|
77
|
+
}
|
|
78
|
+
if (ahead === 0) {
|
|
79
|
+
return `behind ${behind}`;
|
|
80
|
+
}
|
|
81
|
+
if (behind === 0) {
|
|
82
|
+
return `ahead ${ahead}`;
|
|
83
|
+
}
|
|
84
|
+
return `ahead ${ahead}, behind ${behind}`;
|
|
85
|
+
}
|
|
86
|
+
export function formatLastCommit(timestampSeconds) {
|
|
87
|
+
return timestampSeconds === null ? 'n/a' : formatRelativeAge(timestampSeconds);
|
|
88
|
+
}
|
|
89
|
+
export function formatRelativeAge(timestampSeconds) {
|
|
90
|
+
const ageSeconds = Math.max(0, Math.floor(Date.now() / 1000) - timestampSeconds);
|
|
91
|
+
const units = [
|
|
92
|
+
{ label: 'y', seconds: 365 * 24 * 60 * 60 },
|
|
93
|
+
{ label: 'mo', seconds: 30 * 24 * 60 * 60 },
|
|
94
|
+
{ label: 'd', seconds: 24 * 60 * 60 },
|
|
95
|
+
{ label: 'h', seconds: 60 * 60 },
|
|
96
|
+
{ label: 'm', seconds: 60 },
|
|
97
|
+
];
|
|
98
|
+
for (const unit of units) {
|
|
99
|
+
const value = Math.floor(ageSeconds / unit.seconds);
|
|
100
|
+
if (value > 0) {
|
|
101
|
+
return `${value}${unit.label} ago`;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return 'just now';
|
|
105
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
.TH GJI\-CLEAN 1 "May 2026" "gji 0.4.1" "User Commands"
|
|
2
|
+
.SH NAME
|
|
3
|
+
gji\-clean \- interactively prune linked worktrees
|
|
4
|
+
.SH SYNOPSIS
|
|
5
|
+
.B gji clean [\fIoptions\fR] [options]
|
|
6
|
+
.SH DESCRIPTION
|
|
7
|
+
interactively prune linked worktrees
|
|
8
|
+
.SH OPTIONS
|
|
9
|
+
.TP
|
|
10
|
+
.B \-f, \-\-force
|
|
11
|
+
bypass prompts, force\-remove dirty worktrees, and force\-delete unmerged branches
|
|
12
|
+
.TP
|
|
13
|
+
.B \-\-stale
|
|
14
|
+
only target clean worktrees whose upstream is gone and branch is merged into the default branch
|
|
15
|
+
.TP
|
|
16
|
+
.B \-\-dry\-run
|
|
17
|
+
show what would be deleted without removing anything
|
|
18
|
+
.TP
|
|
19
|
+
.B \-\-json
|
|
20
|
+
emit JSON on success or error instead of human\-readable output
|
|
21
|
+
.SH "SEE ALSO"
|
|
22
|
+
.BR gji (1)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
.TH GJI\-COMPLETION 1 "May 2026" "gji 0.4.1" "User Commands"
|
|
2
|
+
.SH NAME
|
|
3
|
+
gji\-completion \- print shell completion definitions
|
|
4
|
+
.SH SYNOPSIS
|
|
5
|
+
.B gji completion [options] [shell]
|
|
6
|
+
.SH DESCRIPTION
|
|
7
|
+
print shell completion definitions
|
|
8
|
+
.SH "SEE ALSO"
|
|
9
|
+
.BR gji (1)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
.TH GJI\-CONFIG 1 "May 2026" "gji 0.4.1" "User Commands"
|
|
2
|
+
.SH NAME
|
|
3
|
+
gji\-config \- manage global config defaults
|
|
4
|
+
.SH SYNOPSIS
|
|
5
|
+
.B gji config [options] [command]
|
|
6
|
+
.SH DESCRIPTION
|
|
7
|
+
manage global config defaults
|
|
8
|
+
.SH SUBCOMMANDS
|
|
9
|
+
.TP
|
|
10
|
+
.B get
|
|
11
|
+
print the global config or a single key
|
|
12
|
+
.TP
|
|
13
|
+
.B set
|
|
14
|
+
set a global config value
|
|
15
|
+
.TP
|
|
16
|
+
.B unset
|
|
17
|
+
remove a global config value
|
|
18
|
+
.SH "SEE ALSO"
|
|
19
|
+
.BR gji (1)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
.TH GJI\-GO 1 "May 2026" "gji 0.4.1" "User Commands"
|
|
2
|
+
.SH NAME
|
|
3
|
+
gji\-go \- print or select a worktree path
|
|
4
|
+
.SH SYNOPSIS
|
|
5
|
+
.B gji go [\fIoptions\fR] [options] [branch]
|
|
6
|
+
.SH DESCRIPTION
|
|
7
|
+
print or select a worktree path
|
|
8
|
+
.SH OPTIONS
|
|
9
|
+
.TP
|
|
10
|
+
.B \-\-print
|
|
11
|
+
print the resolved worktree path explicitly
|
|
12
|
+
.SH "SEE ALSO"
|
|
13
|
+
.BR gji (1)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
.TH GJI\-INIT 1 "May 2026" "gji 0.4.1" "User Commands"
|
|
2
|
+
.SH NAME
|
|
3
|
+
gji\-init \- print or install shell integration
|
|
4
|
+
.SH SYNOPSIS
|
|
5
|
+
.B gji init [\fIoptions\fR] [options] [shell]
|
|
6
|
+
.SH DESCRIPTION
|
|
7
|
+
print or install shell integration
|
|
8
|
+
.SH OPTIONS
|
|
9
|
+
.TP
|
|
10
|
+
.B \-\-write
|
|
11
|
+
write the integration to the shell config file
|
|
12
|
+
.SH "SEE ALSO"
|
|
13
|
+
.BR gji (1)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
.TH GJI\-LS 1 "May 2026" "gji 0.4.1" "User Commands"
|
|
2
|
+
.SH NAME
|
|
3
|
+
gji\-ls \- list active worktrees
|
|
4
|
+
.SH SYNOPSIS
|
|
5
|
+
.B gji ls [\fIoptions\fR] [options]
|
|
6
|
+
.SH DESCRIPTION
|
|
7
|
+
list active worktrees
|
|
8
|
+
.SH OPTIONS
|
|
9
|
+
.TP
|
|
10
|
+
.B \-\-compact
|
|
11
|
+
show only branch and path columns
|
|
12
|
+
.TP
|
|
13
|
+
.B \-\-json
|
|
14
|
+
print active worktrees as JSON
|
|
15
|
+
.SH "SEE ALSO"
|
|
16
|
+
.BR gji (1)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
.TH GJI\-NEW 1 "May 2026" "gji 0.4.1" "User Commands"
|
|
2
|
+
.SH NAME
|
|
3
|
+
gji\-new \- create a new branch or detached linked worktree
|
|
4
|
+
.SH SYNOPSIS
|
|
5
|
+
.B gji new [\fIoptions\fR] [options] [branch]
|
|
6
|
+
.SH DESCRIPTION
|
|
7
|
+
create a new branch or detached linked worktree
|
|
8
|
+
.SH OPTIONS
|
|
9
|
+
.TP
|
|
10
|
+
.B \-f, \-\-force
|
|
11
|
+
remove and recreate the worktree if the target path already exists
|
|
12
|
+
.TP
|
|
13
|
+
.B \-\-detached
|
|
14
|
+
create a detached worktree without a branch
|
|
15
|
+
.TP
|
|
16
|
+
.B \-\-dry\-run
|
|
17
|
+
show what would be created without executing any git commands or writing files
|
|
18
|
+
.TP
|
|
19
|
+
.B \-\-json
|
|
20
|
+
emit JSON on success or error instead of human\-readable output
|
|
21
|
+
.SH "SEE ALSO"
|
|
22
|
+
.BR gji (1)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
.TH GJI\-PR 1 "May 2026" "gji 0.4.1" "User Commands"
|
|
2
|
+
.SH NAME
|
|
3
|
+
gji\-pr \- fetch a pull request by number, #number, or URL into a linked worktree
|
|
4
|
+
.SH SYNOPSIS
|
|
5
|
+
.B gji pr [\fIoptions\fR] [options] <ref>
|
|
6
|
+
.SH DESCRIPTION
|
|
7
|
+
fetch a pull request by number, #number, or URL into a linked worktree
|
|
8
|
+
.SH OPTIONS
|
|
9
|
+
.TP
|
|
10
|
+
.B \-\-dry\-run
|
|
11
|
+
show what would be created without executing any git commands or writing files
|
|
12
|
+
.TP
|
|
13
|
+
.B \-\-json
|
|
14
|
+
emit JSON on success or error instead of human\-readable output
|
|
15
|
+
.SH "SEE ALSO"
|
|
16
|
+
.BR gji (1)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
.TH GJI\-REMOVE 1 "May 2026" "gji 0.4.1" "User Commands"
|
|
2
|
+
.SH NAME
|
|
3
|
+
gji\-remove \- remove a linked worktree and delete its branch when present
|
|
4
|
+
.SH SYNOPSIS
|
|
5
|
+
.B gji remove [\fIoptions\fR] [options] [branch]
|
|
6
|
+
.SH DESCRIPTION
|
|
7
|
+
remove a linked worktree and delete its branch when present
|
|
8
|
+
.SH OPTIONS
|
|
9
|
+
.TP
|
|
10
|
+
.B \-f, \-\-force
|
|
11
|
+
bypass prompts, force\-remove a dirty worktree, and force\-delete an unmerged branch
|
|
12
|
+
.TP
|
|
13
|
+
.B \-\-dry\-run
|
|
14
|
+
show what would be deleted without removing anything
|
|
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)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
.TH GJI\-ROOT 1 "May 2026" "gji 0.4.1" "User Commands"
|
|
2
|
+
.SH NAME
|
|
3
|
+
gji\-root \- print the main repository root path
|
|
4
|
+
.SH SYNOPSIS
|
|
5
|
+
.B gji root [\fIoptions\fR] [options]
|
|
6
|
+
.SH DESCRIPTION
|
|
7
|
+
print the main repository root path
|
|
8
|
+
.SH OPTIONS
|
|
9
|
+
.TP
|
|
10
|
+
.B \-\-print
|
|
11
|
+
print the resolved repository root path explicitly
|
|
12
|
+
.SH "SEE ALSO"
|
|
13
|
+
.BR gji (1)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
.TH GJI\-STATUS 1 "May 2026" "gji 0.4.1" "User Commands"
|
|
2
|
+
.SH NAME
|
|
3
|
+
gji\-status \- summarize repository and worktree health
|
|
4
|
+
.SH SYNOPSIS
|
|
5
|
+
.B gji status [\fIoptions\fR] [options]
|
|
6
|
+
.SH DESCRIPTION
|
|
7
|
+
summarize repository and worktree health
|
|
8
|
+
.SH OPTIONS
|
|
9
|
+
.TP
|
|
10
|
+
.B \-\-json
|
|
11
|
+
print repository and worktree health as JSON
|
|
12
|
+
.SH "SEE ALSO"
|
|
13
|
+
.BR gji (1)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
.TH GJI\-SYNC 1 "May 2026" "gji 0.4.1" "User Commands"
|
|
2
|
+
.SH NAME
|
|
3
|
+
gji\-sync \- fetch and update one or all worktrees
|
|
4
|
+
.SH SYNOPSIS
|
|
5
|
+
.B gji sync [\fIoptions\fR] [options]
|
|
6
|
+
.SH DESCRIPTION
|
|
7
|
+
fetch and update one or all worktrees
|
|
8
|
+
.SH OPTIONS
|
|
9
|
+
.TP
|
|
10
|
+
.B \-\-all
|
|
11
|
+
sync every worktree in the repository
|
|
12
|
+
.TP
|
|
13
|
+
.B \-\-json
|
|
14
|
+
emit JSON on success or error instead of human\-readable output
|
|
15
|
+
.SH "SEE ALSO"
|
|
16
|
+
.BR gji (1)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
.TH GJI\-TRIGGER\-HOOK 1 "May 2026" "gji 0.4.1" "User Commands"
|
|
2
|
+
.SH NAME
|
|
3
|
+
gji\-trigger\-hook \- run a named hook (afterCreate, afterEnter, beforeRemove) in the current worktree
|
|
4
|
+
.SH SYNOPSIS
|
|
5
|
+
.B gji trigger\-hook [options] <hook>
|
|
6
|
+
.SH DESCRIPTION
|
|
7
|
+
run a named hook (afterCreate, afterEnter, beforeRemove) in the current worktree
|
|
8
|
+
.SH "SEE ALSO"
|
|
9
|
+
.BR gji (1)
|
package/man/man1/gji.1
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
.TH GJI 1 "May 2026" "gji 0.4.1" "User Commands"
|
|
2
|
+
.SH NAME
|
|
3
|
+
gji \- Context switching without the mess.
|
|
4
|
+
.SH SYNOPSIS
|
|
5
|
+
.B gji
|
|
6
|
+
[\fIoptions\fR] <\fIcommand\fR> [\fIargs\fR]
|
|
7
|
+
.SH DESCRIPTION
|
|
8
|
+
Context switching without the mess.
|
|
9
|
+
.PP
|
|
10
|
+
Each branch lives in its own worktree with its own node_modules and terminal,
|
|
11
|
+
eliminating the need for \fBgit stash\fR when switching contexts.
|
|
12
|
+
.SH COMMANDS
|
|
13
|
+
.TP
|
|
14
|
+
.B new [options] [branch]
|
|
15
|
+
create a new branch or detached linked worktree
|
|
16
|
+
.TP
|
|
17
|
+
.B init [options] [shell]
|
|
18
|
+
print or install shell integration
|
|
19
|
+
.TP
|
|
20
|
+
.B completion [options] [shell]
|
|
21
|
+
print shell completion definitions
|
|
22
|
+
.TP
|
|
23
|
+
.B pr [options] <ref>
|
|
24
|
+
fetch a pull request by number, #number, or URL into a linked worktree
|
|
25
|
+
.TP
|
|
26
|
+
.B go [options] [branch]
|
|
27
|
+
print or select a worktree path
|
|
28
|
+
.TP
|
|
29
|
+
.B root [options]
|
|
30
|
+
print the main repository root path
|
|
31
|
+
.TP
|
|
32
|
+
.B status [options]
|
|
33
|
+
summarize repository and worktree health
|
|
34
|
+
.TP
|
|
35
|
+
.B sync [options]
|
|
36
|
+
fetch and update one or all worktrees
|
|
37
|
+
.TP
|
|
38
|
+
.B ls [options]
|
|
39
|
+
list active worktrees
|
|
40
|
+
.TP
|
|
41
|
+
.B clean [options]
|
|
42
|
+
interactively prune linked worktrees
|
|
43
|
+
.TP
|
|
44
|
+
.B remove [options] [branch]
|
|
45
|
+
remove a linked worktree and delete its branch when present
|
|
46
|
+
.br
|
|
47
|
+
Alias: \fBrm\fR
|
|
48
|
+
.TP
|
|
49
|
+
.B trigger\-hook [options] <hook>
|
|
50
|
+
run a named hook (afterCreate, afterEnter, beforeRemove) in the current worktree
|
|
51
|
+
.TP
|
|
52
|
+
.B config [options] [command]
|
|
53
|
+
manage global config defaults
|
|
54
|
+
.SH OPTIONS
|
|
55
|
+
.TP
|
|
56
|
+
.B \-V, \-\-version
|
|
57
|
+
output the version number
|
|
58
|
+
.SH "SEE ALSO"
|
|
59
|
+
.BR gji\-new (1),
|
|
60
|
+
.BR gji\-init (1),
|
|
61
|
+
.BR gji\-completion (1),
|
|
62
|
+
.BR gji\-pr (1),
|
|
63
|
+
.BR gji\-go (1),
|
|
64
|
+
.BR gji\-root (1),
|
|
65
|
+
.BR gji\-status (1),
|
|
66
|
+
.BR gji\-sync (1),
|
|
67
|
+
.BR gji\-ls (1),
|
|
68
|
+
.BR gji\-clean (1),
|
|
69
|
+
.BR gji\-remove (1),
|
|
70
|
+
.BR gji\-trigger\-hook (1),
|
|
71
|
+
.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.4.1",
|
|
4
4
|
"description": "Git worktree CLI for fast context switching.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "sjquant",
|
|
@@ -24,9 +24,13 @@
|
|
|
24
24
|
],
|
|
25
25
|
"files": [
|
|
26
26
|
"dist",
|
|
27
|
+
"man",
|
|
27
28
|
"README.md",
|
|
28
29
|
"LICENSE"
|
|
29
30
|
],
|
|
31
|
+
"man": [
|
|
32
|
+
"man/man1/gji.1"
|
|
33
|
+
],
|
|
30
34
|
"publishConfig": {
|
|
31
35
|
"access": "public"
|
|
32
36
|
},
|
|
@@ -38,18 +42,28 @@
|
|
|
38
42
|
},
|
|
39
43
|
"scripts": {
|
|
40
44
|
"build": "node scripts/clean-dist.mjs && tsc -p tsconfig.build.json",
|
|
41
|
-
"
|
|
45
|
+
"generate:readme-demos": "node scripts/generate-readme-demos.mjs",
|
|
46
|
+
"bundle": "node scripts/bundle.mjs",
|
|
47
|
+
"generate-man": "node scripts/generate-man.mjs",
|
|
48
|
+
"docs:build": "pnpm --dir website build",
|
|
49
|
+
"docs:start": "pnpm --dir website start",
|
|
50
|
+
"prepublishOnly": "pnpm test && pnpm build && pnpm generate-man",
|
|
42
51
|
"test": "vitest run --passWithNoTests",
|
|
43
52
|
"test:watch": "vitest"
|
|
44
53
|
},
|
|
45
54
|
"dependencies": {
|
|
46
55
|
"@clack/core": "0.5.0",
|
|
47
56
|
"@clack/prompts": "^0.11.0",
|
|
48
|
-
"commander": "^14.0.1"
|
|
57
|
+
"commander": "^14.0.1",
|
|
58
|
+
"update-notifier": "^7.3.1"
|
|
49
59
|
},
|
|
50
60
|
"devDependencies": {
|
|
51
61
|
"@types/node": "^24.6.0",
|
|
62
|
+
"esbuild": "^0.27.0",
|
|
52
63
|
"typescript": "^5.9.3",
|
|
53
64
|
"vitest": "^3.2.4"
|
|
65
|
+
},
|
|
66
|
+
"pnpm": {
|
|
67
|
+
"onlyBuiltDependencies": ["esbuild"]
|
|
54
68
|
}
|
|
55
69
|
}
|