gitnexushub 0.4.5 → 0.7.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/api.d.ts +90 -1
- package/dist/api.js +34 -0
- package/dist/cli-helpers.js +2 -0
- package/dist/connect-command.js +6 -2
- package/dist/context.js +41 -2
- package/dist/editors/detect.js +5 -0
- package/dist/editors/kiro.d.ts +15 -0
- package/dist/editors/kiro.js +118 -0
- package/dist/editors/types.d.ts +1 -1
- package/dist/hooks-installer.d.ts +33 -1
- package/dist/hooks-installer.js +125 -18
- package/dist/index.js +29 -2
- package/dist/install-ci-command.d.ts +176 -0
- package/dist/install-ci-command.js +680 -0
- package/dist/wiki/claude.d.ts +11 -5
- package/dist/wiki/claude.js +8 -3
- package/dist/wiki/compose-overview.d.ts +29 -0
- package/dist/wiki/compose-overview.js +48 -0
- package/dist/wiki/concurrency.d.ts +20 -0
- package/dist/wiki/concurrency.js +91 -0
- package/dist/wiki/helpers.d.ts +102 -0
- package/dist/wiki/helpers.js +308 -0
- package/dist/wiki/incremental.d.ts +72 -0
- package/dist/wiki/incremental.js +214 -0
- package/dist/wiki/index.js +37 -0
- package/dist/wiki/session.d.ts +10 -0
- package/dist/wiki/session.js +89 -9
- package/dist/wiki/upload-command.d.ts +12 -0
- package/dist/wiki/upload-command.js +384 -53
- package/hooks/gitnexus-enterprise-hook.cjs +245 -13
- package/package.json +1 -1
- package/skills/gitnexus-debugging.md +89 -89
- package/skills/gitnexus-exploring.md +78 -78
- package/skills/gitnexus-impact-analysis.md +99 -99
- package/skills/gitnexus-pr-review.md +161 -161
package/dist/index.js
CHANGED
|
@@ -18,6 +18,7 @@ import { removeProjectContext } from './context.js';
|
|
|
18
18
|
import { runSync } from './sync-command.js';
|
|
19
19
|
import { ok, info, warn, fail, resolveAuth, DEFAULT_HUB_URL, EDITORS } from './cli-helpers.js';
|
|
20
20
|
import { runConnect } from './connect-command.js';
|
|
21
|
+
import { runInstallCi } from './install-ci-command.js';
|
|
21
22
|
import { registerWikiCommand } from './wiki/index.js';
|
|
22
23
|
const BANNER = [
|
|
23
24
|
' ██████╗ ██╗████████╗███╗ ██╗███████╗██╗ ██╗██╗ ██╗███████╗',
|
|
@@ -56,7 +57,7 @@ program
|
|
|
56
57
|
.command('connect', { isDefault: true })
|
|
57
58
|
.description('Register Hub MCP, install skills, and write project files')
|
|
58
59
|
.argument('[token]', 'gnx_ API token (optional if already saved)')
|
|
59
|
-
.option('--editor <name>', 'Editor to configure: claude-code | cursor | windsurf | opencode')
|
|
60
|
+
.option('--editor <name>', 'Editor to configure: claude-code | cursor | windsurf | opencode | kiro')
|
|
60
61
|
.option('--hub <url>', `Hub URL (default: saved config or ${DEFAULT_HUB_URL})`)
|
|
61
62
|
.option('--skip-project', 'Only configure MCP, skip project files')
|
|
62
63
|
.action(connectAction);
|
|
@@ -64,7 +65,7 @@ program
|
|
|
64
65
|
program
|
|
65
66
|
.command('disconnect')
|
|
66
67
|
.description('Remove GitNexus MCP config, skills, and project files')
|
|
67
|
-
.option('--editor <name>', 'Editor to unconfigure: claude-code | cursor | windsurf | opencode')
|
|
68
|
+
.option('--editor <name>', 'Editor to unconfigure: claude-code | cursor | windsurf | opencode | kiro')
|
|
68
69
|
.action(async (opts) => {
|
|
69
70
|
try {
|
|
70
71
|
printBanner();
|
|
@@ -111,6 +112,32 @@ program
|
|
|
111
112
|
process.exit(1);
|
|
112
113
|
}
|
|
113
114
|
});
|
|
115
|
+
// ─── install-ci command ───────────────────────────────────────────
|
|
116
|
+
//
|
|
117
|
+
// Opens a PR on the user's GitHub repo that adds the GitNexus PR
|
|
118
|
+
// review workflow. Mints a long-lived CI token via the Hub, sets it
|
|
119
|
+
// (and CLAUDE_CODE_OAUTH_TOKEN, when a local Claude Code login is
|
|
120
|
+
// detected) as repo Actions secrets, and base64-PUTs the rendered
|
|
121
|
+
// workflow YAML through the user's `gh` CLI. v2 ships a single
|
|
122
|
+
// workflow file; Claude is the primary review mechanism, no opt-out.
|
|
123
|
+
program
|
|
124
|
+
.command('install-ci')
|
|
125
|
+
.description('Open a PR adding the GitNexus PR review workflow + set Actions secrets')
|
|
126
|
+
.option('--hub <url>', `Hub URL (default: saved config or ${DEFAULT_HUB_URL})`)
|
|
127
|
+
.option('--claude-token <token>', 'Claude OAuth token from `claude setup-token` (leaks to argv — prefer the CLAUDE_CODE_OAUTH_TOKEN env var)')
|
|
128
|
+
.option('--claude-token-file <path>', 'Path to a file containing the Claude OAuth token (alternative to --claude-token / env var)')
|
|
129
|
+
.action(async (opts) => {
|
|
130
|
+
try {
|
|
131
|
+
printBanner();
|
|
132
|
+
await runInstallCi(opts);
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
console.error('');
|
|
136
|
+
fail(err.message);
|
|
137
|
+
console.error('');
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
114
141
|
// ─── wiki commands ────────────────────────────────────────────────
|
|
115
142
|
registerWikiCommand(program);
|
|
116
143
|
program.parse();
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `gnx install-ci` (v2) — opens a PR on the user's GitHub repo that
|
|
3
|
+
* adds the single Claude-led GitNexus CI workflow, using the user's
|
|
4
|
+
* local `gh` CLI rather than a Hub-side OAuth-write grant.
|
|
5
|
+
*
|
|
6
|
+
* v1 shipped three workflow files (gitnexus.yml + claude.yml +
|
|
7
|
+
* claude-code-review.yml) and a `--no-claude` opt-out. v2 collapses
|
|
8
|
+
* to one file and makes Claude mandatory: the workflow's only review
|
|
9
|
+
* mechanism is the `anthropics/claude-code-action@v1` step, primed
|
|
10
|
+
* with a pre-computed Context Pack from `Akon-Labs/gitnexus-check@v2`.
|
|
11
|
+
*
|
|
12
|
+
* Pivot rationale (unchanged from v1): we don't want the Hub to keep
|
|
13
|
+
* a write-capable GitHub token per user. Doing the GitHub write from
|
|
14
|
+
* the user's machine via `gh` keeps the Hub free of `workflow` /
|
|
15
|
+
* `repo` OAuth scopes.
|
|
16
|
+
*
|
|
17
|
+
* Flow:
|
|
18
|
+
* 1. Detect git repo + GitHub remote.
|
|
19
|
+
* 2. Resolve fullName → repoId via `GET /api/repos`.
|
|
20
|
+
* 3. POST install-ci-bundle (mints CI token, renders workflow YAML).
|
|
21
|
+
* 4. `gh` preflight (installed, authed, has `repo` scope).
|
|
22
|
+
* 5. Push branch + PUT workflow file + open PR.
|
|
23
|
+
* 6. Set GITNEXUS_TOKEN + CLAUDE_CODE_OAUTH_TOKEN secrets via stdin.
|
|
24
|
+
*
|
|
25
|
+
* The exported `runInstallCi` is the commander entry point; the
|
|
26
|
+
* GitHub-write helpers (`pushWorkflowAndOpenPr`, `setRepoSecret`)
|
|
27
|
+
* accept an injected `runGh` for unit-testability.
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* Adapter for `gh` invocations. Real impl shells out via execFileSync;
|
|
31
|
+
* tests replace it with a recording fake. The Promise return shape
|
|
32
|
+
* mirrors what we actually need from `gh` — stdout, stderr, exit code.
|
|
33
|
+
*
|
|
34
|
+
* `input`, when set, is piped to stdin. We use this for `gh secret
|
|
35
|
+
* set NAME --repo OWNER/REPO`, which reads the secret value from stdin
|
|
36
|
+
* when no `--body` / `--body-file` flag is set. That keeps the secret
|
|
37
|
+
* out of argv (`ps` leak) and out of any shell history.
|
|
38
|
+
*/
|
|
39
|
+
export type GhRunner = (args: string[], opts?: {
|
|
40
|
+
input?: string;
|
|
41
|
+
}) => Promise<{
|
|
42
|
+
stdout: string;
|
|
43
|
+
stderr: string;
|
|
44
|
+
code: number;
|
|
45
|
+
}>;
|
|
46
|
+
interface InstallCiOpts {
|
|
47
|
+
hub?: string;
|
|
48
|
+
/**
|
|
49
|
+
* Raw Claude Code OAuth token (output of `claude setup-token`). Lowest
|
|
50
|
+
* priority — leaks to argv / `ps` / shell history. Prefer the env var
|
|
51
|
+
* `CLAUDE_CODE_OAUTH_TOKEN` for routine use; this flag is the escape
|
|
52
|
+
* hatch for one-off / scripted runs.
|
|
53
|
+
*/
|
|
54
|
+
claudeToken?: string;
|
|
55
|
+
/**
|
|
56
|
+
* Path to a file whose contents are the Claude OAuth token. Mid
|
|
57
|
+
* priority — keeps the token off argv. Useful for ops that pre-stage
|
|
58
|
+
* the token in a file rather than the environment.
|
|
59
|
+
*/
|
|
60
|
+
claudeTokenFile?: string;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Entry point for `gnx install-ci`. Imported by index.ts so commander
|
|
64
|
+
* has a stable handle.
|
|
65
|
+
*
|
|
66
|
+
* Output is structured as 6 numbered steps with a final boxed summary.
|
|
67
|
+
* The styling matches the v1 install-ci output that the user explicitly
|
|
68
|
+
* called out as "polished" — we keep the visual contract.
|
|
69
|
+
*/
|
|
70
|
+
export declare function runInstallCi(opts: InstallCiOpts): Promise<void>;
|
|
71
|
+
/**
|
|
72
|
+
* Returns the missing scope name (e.g. "repo") if the active gh auth
|
|
73
|
+
* session lacks one we need, else null. We check `repo` only — that
|
|
74
|
+
* scope covers everything install-ci does:
|
|
75
|
+
* - push branches & file content (Contents API)
|
|
76
|
+
* - open PRs (Pulls API)
|
|
77
|
+
* - read+write Actions secrets (`repo` is sufficient for repo-level
|
|
78
|
+
* secrets; only org-level secrets need `admin:org`)
|
|
79
|
+
*
|
|
80
|
+
* Falls back to "no missing scope" if we can't parse `gh auth status`
|
|
81
|
+
* — better to let the real call surface the real error than block on
|
|
82
|
+
* a parser misfire across gh versions.
|
|
83
|
+
*/
|
|
84
|
+
export declare function ghMissingScope(): string | null;
|
|
85
|
+
/**
|
|
86
|
+
* Read the user's Claude Code OAuth token from local credentials so
|
|
87
|
+
* we can auto-set CLAUDE_CODE_OAUTH_TOKEN as a GitHub Actions secret
|
|
88
|
+
* — the same source Claude Code's own `/install-github-app` reads.
|
|
89
|
+
*
|
|
90
|
+
* Lookup order (descending preference — first hit wins):
|
|
91
|
+
*
|
|
92
|
+
* 1. `opts.claudeToken` from `--claude-token=<value>` (lowest priority,
|
|
93
|
+
* flagged for completeness — leaks to argv / `ps` / shell history).
|
|
94
|
+
* 2. `opts.claudeTokenFile` from `--claude-token-file=<path>` — reads
|
|
95
|
+
* the file's trimmed contents. Keeps the token off argv.
|
|
96
|
+
* 3. `process.env.CLAUDE_CODE_OAUTH_TOKEN` — the documented happy path.
|
|
97
|
+
* User runs `claude setup-token` once, exports the result via shell
|
|
98
|
+
* rc, then `gnx install-ci` picks it up automatically on every run.
|
|
99
|
+
*
|
|
100
|
+
* Why we no longer auto-detect from `~/.claude/.credentials.json`: that
|
|
101
|
+
* file's `claudeAiOauth.accessToken` is the user's *interactive session*
|
|
102
|
+
* token (~1h expiry, refreshed in-band). It is NOT a valid CI OAuth
|
|
103
|
+
* token — those are minted explicitly by `claude setup-token` and have
|
|
104
|
+
* the longer-lived headless scope set the GHA expects. Live testing on
|
|
105
|
+
* deer-flow PR #11 confirmed: shipping the session token to the GHA
|
|
106
|
+
* causes "Could not resolve auth credentials" inside the bundled
|
|
107
|
+
* Anthropic SDK. Better to fail loud with a clear instruction than to
|
|
108
|
+
* silently set the wrong token.
|
|
109
|
+
*
|
|
110
|
+
* Returns the trimmed token if any source yields one; null otherwise.
|
|
111
|
+
* The caller prints a clear "run `claude setup-token` first" instruction
|
|
112
|
+
* on null and exits non-zero rather than shipping a half-installed CI.
|
|
113
|
+
*/
|
|
114
|
+
export declare function readClaudeOAuthToken(opts: {
|
|
115
|
+
claudeToken?: string;
|
|
116
|
+
claudeTokenFile?: string;
|
|
117
|
+
}): string | null;
|
|
118
|
+
/**
|
|
119
|
+
* Default `gh` runner — shells out via execFileSync. Captures stdout
|
|
120
|
+
* + stderr separately so callers can inspect each. When `input` is set,
|
|
121
|
+
* pipes it to stdin (used for `gh secret set` so secret material never
|
|
122
|
+
* lands in argv or process listings). Translates non-zero exit into a
|
|
123
|
+
* thrown Error whose message is the stderr text, matching the contract
|
|
124
|
+
* tests expect.
|
|
125
|
+
*/
|
|
126
|
+
export declare const defaultGhRunner: GhRunner;
|
|
127
|
+
/**
|
|
128
|
+
* Set a repository-level Actions secret without ever putting the value
|
|
129
|
+
* in argv. `gh secret set NAME --repo OWNER/REPO` reads the secret
|
|
130
|
+
* value from stdin when neither `--body` nor `--body-file` is set —
|
|
131
|
+
* documented behavior across all supported gh versions.
|
|
132
|
+
*
|
|
133
|
+
* (We deliberately avoid `--body-file -`. That flag was added later
|
|
134
|
+
* than our minimum supported gh version; older installs reject it as
|
|
135
|
+
* "unknown flag" and crash the install-ci flow even though the
|
|
136
|
+
* underlying API supports stdin natively.)
|
|
137
|
+
*/
|
|
138
|
+
export declare function setRepoSecret(runGh: GhRunner, fullName: string, name: string, value: string): Promise<void>;
|
|
139
|
+
export interface PushResult {
|
|
140
|
+
prUrl: string;
|
|
141
|
+
/**
|
|
142
|
+
* True when we found the workflow file already present on the branch
|
|
143
|
+
* with byte-identical content AND a PR already exists. We still
|
|
144
|
+
* surface the PR URL so the user can check on it; the summary box
|
|
145
|
+
* formats this case as "already installed" rather than "completed".
|
|
146
|
+
*/
|
|
147
|
+
alreadyInstalled: boolean;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Push the workflow file to `branchName` and open a PR.
|
|
151
|
+
*
|
|
152
|
+
* Idempotency:
|
|
153
|
+
* - If `branchName` already exists we keep using it (gh's create-branch
|
|
154
|
+
* fails with "Reference already exists" — caught and ignored).
|
|
155
|
+
* - If the workflow file is already present with byte-identical
|
|
156
|
+
* content AND a matching PR is already open from this head, we
|
|
157
|
+
* mark `alreadyInstalled = true` and skip the PUT + create-PR
|
|
158
|
+
* calls. The branch name embeds a timestamp so practical retries
|
|
159
|
+
* never collide, but tests inject a fixed branch name to drive
|
|
160
|
+
* this code path.
|
|
161
|
+
* - If the file exists with different content, we PUT with the
|
|
162
|
+
* existing sha so it's an update.
|
|
163
|
+
* - If a PR creation returns 422 (duplicate), we fall back to the
|
|
164
|
+
* `pulls?head=...&state=all` lookup and surface that URL.
|
|
165
|
+
*
|
|
166
|
+
* `runGh` is injected so tests can drive the full idempotency matrix
|
|
167
|
+
* without spawning a real `gh`.
|
|
168
|
+
*/
|
|
169
|
+
export declare function pushWorkflowAndOpenPr(args: {
|
|
170
|
+
owner: string;
|
|
171
|
+
repo: string;
|
|
172
|
+
branchName: string;
|
|
173
|
+
workflowYaml: string;
|
|
174
|
+
runGh: GhRunner;
|
|
175
|
+
}): Promise<PushResult>;
|
|
176
|
+
export {};
|