@solaqua/gji 0.4.1 → 0.5.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/dist/back.d.ts +13 -0
- package/dist/back.js +74 -0
- package/dist/cli.js +43 -0
- package/dist/gji-bundle.mjs +653 -484
- package/dist/go.js +2 -0
- 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/init.js +7 -0
- package/dist/new.js +3 -0
- package/dist/pr.js +3 -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 +1 -1
- 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.1 +9 -1
- package/package.json +1 -1
package/dist/go.js
CHANGED
|
@@ -4,6 +4,7 @@ import { loadEffectiveConfig } from './config.js';
|
|
|
4
4
|
import { readWorktreeHealth } from './git.js';
|
|
5
5
|
import { isHeadless } from './headless.js';
|
|
6
6
|
import { extractHooks, runHook } from './hooks.js';
|
|
7
|
+
import { appendHistory } from './history.js';
|
|
7
8
|
import { detectRepository, listWorktrees, sortByCurrentFirst } from './repo.js';
|
|
8
9
|
import { writeShellOutput } from './shell-handoff.js';
|
|
9
10
|
const GO_OUTPUT_FILE_ENV = 'GJI_GO_OUTPUT_FILE';
|
|
@@ -36,6 +37,7 @@ export function createGoCommand(dependencies = {}) {
|
|
|
36
37
|
const config = await loadEffectiveConfig(repository.repoRoot, undefined, options.stderr);
|
|
37
38
|
const hooks = extractHooks(config);
|
|
38
39
|
await runHook(hooks.afterEnter, resolvedPath, { branch: chosenWorktree?.branch ?? undefined, path: resolvedPath, repo: basename(repository.repoRoot) }, options.stderr);
|
|
40
|
+
appendHistory(resolvedPath, chosenWorktree?.branch ?? null).catch(() => undefined);
|
|
39
41
|
await writeShellOutput(GO_OUTPUT_FILE_ENV, resolvedPath, options.stdout);
|
|
40
42
|
return 0;
|
|
41
43
|
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { loadHistory } from './history.js';
|
|
2
|
+
import { formatHistoryList } from './back.js';
|
|
3
|
+
export async function runHistoryCommand(options) {
|
|
4
|
+
const history = await loadHistory(options.home);
|
|
5
|
+
if (options.json) {
|
|
6
|
+
options.stdout(`${JSON.stringify(history, null, 2)}\n`);
|
|
7
|
+
return 0;
|
|
8
|
+
}
|
|
9
|
+
if (history.length === 0) {
|
|
10
|
+
options.stdout('No navigation history.\n');
|
|
11
|
+
return 0;
|
|
12
|
+
}
|
|
13
|
+
options.stdout(formatHistoryList(history, options.cwd));
|
|
14
|
+
return 0;
|
|
15
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const HISTORY_FILE_NAME = "history.json";
|
|
2
|
+
export interface HistoryEntry {
|
|
3
|
+
branch: string | null;
|
|
4
|
+
path: string;
|
|
5
|
+
timestamp: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function HISTORY_FILE_PATH(home?: string): string;
|
|
8
|
+
export declare function loadHistory(home?: string): Promise<HistoryEntry[]>;
|
|
9
|
+
export declare function appendHistory(path: string, branch: string | null, home?: string): Promise<void>;
|
package/dist/history.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { dirname, join, resolve } from 'node:path';
|
|
4
|
+
import { GLOBAL_CONFIG_DIRECTORY } from './config.js';
|
|
5
|
+
export const HISTORY_FILE_NAME = 'history.json';
|
|
6
|
+
const MAX_HISTORY_ENTRIES = 50;
|
|
7
|
+
export function HISTORY_FILE_PATH(home = homedir()) {
|
|
8
|
+
const configDir = process.env.GJI_CONFIG_DIR;
|
|
9
|
+
if (configDir) {
|
|
10
|
+
return join(resolve(configDir), HISTORY_FILE_NAME);
|
|
11
|
+
}
|
|
12
|
+
return join(home, GLOBAL_CONFIG_DIRECTORY, HISTORY_FILE_NAME);
|
|
13
|
+
}
|
|
14
|
+
export async function loadHistory(home = homedir()) {
|
|
15
|
+
const path = HISTORY_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(isHistoryEntry);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export async function appendHistory(path, branch, home = homedir()) {
|
|
28
|
+
const historyPath = HISTORY_FILE_PATH(home);
|
|
29
|
+
const existing = await loadHistory(home);
|
|
30
|
+
// Skip if the most recent entry is the same path (no-op navigation)
|
|
31
|
+
if (existing.length > 0 && existing[0].path === path) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const entry = { branch, path, timestamp: Date.now() };
|
|
35
|
+
const next = [entry, ...existing].slice(0, MAX_HISTORY_ENTRIES);
|
|
36
|
+
await mkdir(dirname(historyPath), { recursive: true });
|
|
37
|
+
await writeFile(historyPath, `${JSON.stringify(next, null, 2)}\n`, 'utf8');
|
|
38
|
+
}
|
|
39
|
+
function isHistoryEntry(value) {
|
|
40
|
+
return (typeof value === 'object' &&
|
|
41
|
+
value !== null &&
|
|
42
|
+
'path' in value &&
|
|
43
|
+
typeof value.path === 'string' &&
|
|
44
|
+
'timestamp' in value &&
|
|
45
|
+
typeof value.timestamp === 'number');
|
|
46
|
+
}
|
package/dist/init.js
CHANGED
|
@@ -21,6 +21,13 @@ const SHELL_WRAPPED_COMMANDS = [
|
|
|
21
21
|
names: ['pr'],
|
|
22
22
|
tempPrefix: 'gji-pr',
|
|
23
23
|
},
|
|
24
|
+
{
|
|
25
|
+
bypassOption: '--print',
|
|
26
|
+
commandName: 'back',
|
|
27
|
+
envVar: 'GJI_BACK_OUTPUT_FILE',
|
|
28
|
+
names: ['back'],
|
|
29
|
+
tempPrefix: 'gji-back',
|
|
30
|
+
},
|
|
24
31
|
{
|
|
25
32
|
bypassOption: '--print',
|
|
26
33
|
commandName: 'go',
|
package/dist/new.js
CHANGED
|
@@ -6,6 +6,7 @@ import { isCancel, text } from '@clack/prompts';
|
|
|
6
6
|
import { loadEffectiveConfig, resolveConfigString } from './config.js';
|
|
7
7
|
import { syncFiles } from './file-sync.js';
|
|
8
8
|
import { extractHooks, runHook } from './hooks.js';
|
|
9
|
+
import { appendHistory } from './history.js';
|
|
9
10
|
import { isHeadless } from './headless.js';
|
|
10
11
|
import { maybeRunInstallPrompt } from './install-prompt.js';
|
|
11
12
|
import { pathExists, promptForPathConflict } from './conflict.js';
|
|
@@ -105,6 +106,7 @@ export function createNewCommand(dependencies = {}) {
|
|
|
105
106
|
else {
|
|
106
107
|
const choice = await prompt(worktreePath);
|
|
107
108
|
if (choice === 'reuse') {
|
|
109
|
+
appendHistory(worktreePath, worktreeName).catch(() => undefined);
|
|
108
110
|
await writeOutput(worktreePath, options.stdout);
|
|
109
111
|
return 0;
|
|
110
112
|
}
|
|
@@ -147,6 +149,7 @@ export function createNewCommand(dependencies = {}) {
|
|
|
147
149
|
options.stdout(`${JSON.stringify({ branch: worktreeName, path: worktreePath }, null, 2)}\n`);
|
|
148
150
|
}
|
|
149
151
|
else {
|
|
152
|
+
await appendHistory(worktreePath, worktreeName);
|
|
150
153
|
await writeOutput(worktreePath, options.stdout);
|
|
151
154
|
}
|
|
152
155
|
return 0;
|
package/dist/pr.js
CHANGED
|
@@ -6,6 +6,7 @@ import { loadEffectiveConfig, resolveConfigString } from './config.js';
|
|
|
6
6
|
import { syncFiles } from './file-sync.js';
|
|
7
7
|
import { pathExists, promptForPathConflict } from './conflict.js';
|
|
8
8
|
import { extractHooks, runHook } from './hooks.js';
|
|
9
|
+
import { appendHistory } from './history.js';
|
|
9
10
|
import { isHeadless } from './headless.js';
|
|
10
11
|
import { maybeRunInstallPrompt } from './install-prompt.js';
|
|
11
12
|
import { detectRepository, resolveWorktreePath } from './repo.js';
|
|
@@ -58,6 +59,7 @@ export function createPrCommand(dependencies = {}) {
|
|
|
58
59
|
}
|
|
59
60
|
const choice = await prompt(worktreePath);
|
|
60
61
|
if (choice === 'reuse') {
|
|
62
|
+
appendHistory(worktreePath, branchName).catch(() => undefined);
|
|
61
63
|
await writeOutput(worktreePath, options.stdout);
|
|
62
64
|
return 0;
|
|
63
65
|
}
|
|
@@ -112,6 +114,7 @@ export function createPrCommand(dependencies = {}) {
|
|
|
112
114
|
options.stdout(`${JSON.stringify({ branch: branchName, path: worktreePath }, null, 2)}\n`);
|
|
113
115
|
}
|
|
114
116
|
else {
|
|
117
|
+
await appendHistory(worktreePath, branchName);
|
|
115
118
|
await writeOutput(worktreePath, options.stdout);
|
|
116
119
|
}
|
|
117
120
|
return 0;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
.TH GJI\-BACK 1 "May 2026" "gji 0.5.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.5.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
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
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.5.0" "User Commands"
|
|
2
2
|
.SH NAME
|
|
3
3
|
gji \- Context switching without the mess.
|
|
4
4
|
.SH SYNOPSIS
|
|
@@ -23,6 +23,12 @@ 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
|
|
26
32
|
.B go [options] [branch]
|
|
27
33
|
print or select a worktree path
|
|
28
34
|
.TP
|
|
@@ -60,6 +66,8 @@ output the version number
|
|
|
60
66
|
.BR gji\-init (1),
|
|
61
67
|
.BR gji\-completion (1),
|
|
62
68
|
.BR gji\-pr (1),
|
|
69
|
+
.BR gji\-back (1),
|
|
70
|
+
.BR gji\-history (1),
|
|
63
71
|
.BR gji\-go (1),
|
|
64
72
|
.BR gji\-root (1),
|
|
65
73
|
.BR gji\-status (1),
|