@gonkagate/claude-code 0.1.2 → 0.2.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/CHANGELOG.md +19 -1
- package/README.md +15 -1
- package/dist/cli.d.ts +5 -3
- package/dist/cli.js +47 -15
- package/dist/cli.js.map +1 -1
- package/dist/install/local-git-ignore.d.ts +6 -0
- package/dist/install/local-git-ignore.js +42 -6
- package/dist/install/local-git-ignore.js.map +1 -1
- package/dist/install/prompts.d.ts +3 -0
- package/dist/install/prompts.js +33 -0
- package/dist/install/prompts.js.map +1 -1
- package/docs/how-it-works.md +3 -1
- package/docs/security.md +5 -1
- package/docs/troubleshooting.md +20 -4
- package/package.json +6 -2
- package/scripts/publish-alias-package.mjs +108 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
- Added `@gonkagate/claude-code-setup` as a setup-style alias for the existing Claude Code installer.
|
|
5
6
|
- Improved npm package metadata and README copy for better package-page clarity, discovery, and onboarding.
|
|
6
7
|
- Added a curated model registry and model picker to the public installer flow.
|
|
7
8
|
- Added `--model <model-key>` and `--model=<model-key>` support for curated non-secret model selection.
|
|
@@ -10,12 +11,29 @@
|
|
|
10
11
|
- Hardened local scope against symlinked `.claude` paths that could redirect secret writes outside the ignored settings path.
|
|
11
12
|
- Extended local git protection to ignore timestamped backup files for `.claude/settings.local.json`.
|
|
12
13
|
- Normalized backup permissions to owner-only mode so secret-bearing backups are not left world-readable.
|
|
13
|
-
-
|
|
14
|
+
- Hardened local scope so `.claude/settings.local.json` cannot keep tracking secrets in git before local setup proceeds.
|
|
15
|
+
- Replaced the tracked-local-settings hard stop with a recovery flow that can stop tracking the file or switch to user scope without rerunning setup.
|
|
14
16
|
- Hardened local scope against symlinked path components anywhere between the repo root and the target settings file.
|
|
15
17
|
- Pinned GitHub Actions workflows to immutable commit SHAs for release pipeline hardening.
|
|
16
18
|
- Restored automated npm publish dispatch after Release Please creates a new release tag.
|
|
17
19
|
- Made publish reruns skip versions that are already present on npm instead of failing with a duplicate-version error.
|
|
18
20
|
|
|
21
|
+
## [0.2.0](https://github.com/GonkaGate/gonkagate-claude-code/compare/v0.1.3...v0.2.0) (2026-04-13)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
### Features
|
|
25
|
+
|
|
26
|
+
* add Claude Code setup alias ([3d411f5](https://github.com/GonkaGate/gonkagate-claude-code/commit/3d411f5c0cbafd84d10cf8339e9d392bd8043a26))
|
|
27
|
+
* add Claude Code setup alias ([caa0711](https://github.com/GonkaGate/gonkagate-claude-code/commit/caa07114025b305a36d9a3e92deb8e565d185b15))
|
|
28
|
+
|
|
29
|
+
## [0.1.3](https://github.com/GonkaGate/gonkagate-claude-code/compare/v0.1.2...v0.1.3) (2026-03-31)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
### Bug Fixes
|
|
33
|
+
|
|
34
|
+
* document release-please title requirements ([5fce744](https://github.com/GonkaGate/gonkagate-claude-code/commit/5fce7441dfd0c79d6f6ab43b4fa20737df879516))
|
|
35
|
+
* document release-please title requirements ([145f9f7](https://github.com/GonkaGate/gonkagate-claude-code/commit/145f9f72da19cf31f8f73e8250047988ee1eb9bf))
|
|
36
|
+
|
|
19
37
|
## [0.1.2](https://github.com/GonkaGate/gonkagate-claude-code/compare/v0.1.1...v0.1.2) (2026-03-31)
|
|
20
38
|
|
|
21
39
|
|
package/README.md
CHANGED
|
@@ -14,6 +14,18 @@ It does not install `Claude Code` itself. It configures an existing local Claude
|
|
|
14
14
|
npx @gonkagate/claude-code
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
+
Setup-style alias for consistency with the other GonkaGate agent installers:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npx @gonkagate/claude-code-setup
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## See It In Action
|
|
24
|
+
|
|
25
|
+
From API key to a working Claude Code setup in one short walkthrough:
|
|
26
|
+
|
|
27
|
+
[](https://raw.githubusercontent.com/GonkaGate/gonkagate-claude-code/main/.github/assets/gonkagate-claude-code-demo.mp4)
|
|
28
|
+
|
|
17
29
|
Need an API key first? [Create one on GonkaGate](https://gonkagate.com/en).
|
|
18
30
|
|
|
19
31
|
You will be asked for:
|
|
@@ -22,6 +34,8 @@ You will be asked for:
|
|
|
22
34
|
- a model from the supported GonkaGate list
|
|
23
35
|
- setup scope: `user` or `local`
|
|
24
36
|
|
|
37
|
+
If you choose `local` scope and `.claude/settings.local.json` is already tracked by git, the installer offers to stop tracking that file and continue, or switch to `user` scope instead.
|
|
38
|
+
|
|
25
39
|
You need:
|
|
26
40
|
|
|
27
41
|
- local `Claude Code`
|
|
@@ -53,7 +67,7 @@ It also:
|
|
|
53
67
|
- writes settings files with owner-only permissions
|
|
54
68
|
- writes backup files with owner-only permissions
|
|
55
69
|
- adds `.claude/settings.local.json` and local backup files to `.git/info/exclude` for local setup inside a git repo
|
|
56
|
-
-
|
|
70
|
+
- offers to stop tracking `.claude/settings.local.json` before local setup writes secrets into a file that was already tracked by git
|
|
57
71
|
- refuses local setup if the target path traverses a symlinked path component, or if `.claude` / the local settings file is a symlink
|
|
58
72
|
|
|
59
73
|
## Fixed GonkaGate Setup
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { InstallScope } from "./types/settings.js";
|
|
1
|
+
import type { InstallScope, SettingsTarget } from "./types/settings.js";
|
|
2
2
|
import type { SupportedModelKey } from "./constants/models.js";
|
|
3
|
+
import type { TrackedLocalSettingsAction } from "./install/prompts.js";
|
|
3
4
|
interface CliOptions {
|
|
4
5
|
help: boolean;
|
|
5
6
|
version: boolean;
|
|
@@ -10,6 +11,7 @@ interface ProgramOutput {
|
|
|
10
11
|
writeOut?: (str: string) => void;
|
|
11
12
|
writeErr?: (str: string) => void;
|
|
12
13
|
}
|
|
13
|
-
export declare function parseCliOptions(argv: string[], output?: ProgramOutput): CliOptions;
|
|
14
|
-
export declare function
|
|
14
|
+
export declare function parseCliOptions(argv: string[], output?: ProgramOutput, commandName?: string): CliOptions;
|
|
15
|
+
export declare function resolveSettingsTarget(scope: InstallScope, cwd: string, chooseTrackedLocalSettingsAction?: (relativeTargetPath: string) => Promise<TrackedLocalSettingsAction>): Promise<SettingsTarget>;
|
|
16
|
+
export declare function run(argv?: string[], commandName?: string): Promise<void>;
|
|
15
17
|
export {};
|
package/dist/cli.js
CHANGED
|
@@ -1,27 +1,29 @@
|
|
|
1
1
|
import process from "node:process";
|
|
2
|
+
import { basename } from "node:path";
|
|
2
3
|
import { pathToFileURL } from "node:url";
|
|
3
4
|
import { Command, CommanderError, Option } from "commander";
|
|
4
5
|
import { DEFAULT_MODEL_KEY, SUPPORTED_MODELS, SUPPORTED_MODEL_KEYS, requireSupportedModel } from "./constants/models.js";
|
|
5
6
|
import { createBackup } from "./install/backup.js";
|
|
6
7
|
import { loadSettings } from "./install/load-settings.js";
|
|
7
|
-
import { ensureLocalSettingsIgnored } from "./install/local-git-ignore.js";
|
|
8
|
+
import { ensureLocalSettingsIgnored, stopTrackingLocalSettings, TrackedLocalSettingsError } from "./install/local-git-ignore.js";
|
|
8
9
|
import { mergeSettingsWithGonkaEnv } from "./install/merge-env.js";
|
|
9
|
-
import { promptForApiKey, promptForModel, promptForScope } from "./install/prompts.js";
|
|
10
|
+
import { promptForApiKey, promptForModel, promptForScope, promptForTrackedLocalSettingsAction } from "./install/prompts.js";
|
|
10
11
|
import { getSettingsTarget } from "./install/settings-paths.js";
|
|
11
12
|
import { validateApiKey } from "./install/validate-api-key.js";
|
|
12
13
|
import { writeSettings } from "./install/write-settings.js";
|
|
14
|
+
const DEFAULT_COMMAND_NAME = "gonkagate-claude-code";
|
|
13
15
|
function rejectApiKeyArgs(argv) {
|
|
14
16
|
if (argv.some((arg) => arg === "--api-key" || arg.startsWith("--api-key="))) {
|
|
15
17
|
throw new Error("Passing API keys via CLI arguments is intentionally unsupported. Run the installer interactively instead.");
|
|
16
18
|
}
|
|
17
19
|
}
|
|
18
|
-
function createProgram(output) {
|
|
20
|
+
function createProgram(output, commandName = DEFAULT_COMMAND_NAME) {
|
|
19
21
|
const supportedModelLines = SUPPORTED_MODELS.map((model) => {
|
|
20
22
|
const defaultSuffix = model.key === DEFAULT_MODEL_KEY ? " (default)" : "";
|
|
21
23
|
return ` ${model.key} ${model.displayName}${defaultSuffix}`;
|
|
22
24
|
}).join("\n");
|
|
23
25
|
const program = new Command()
|
|
24
|
-
.name(
|
|
26
|
+
.name(commandName)
|
|
25
27
|
.description("GonkaGate Claude Code installer")
|
|
26
28
|
.addOption(new Option("--model <model-key>", "Skip the model prompt with a curated supported model.").choices(SUPPORTED_MODEL_KEYS))
|
|
27
29
|
.addOption(new Option("--scope <scope>", "Skip the scope prompt. Choose user or local.").choices(["user", "local"]))
|
|
@@ -30,6 +32,7 @@ function createProgram(output) {
|
|
|
30
32
|
.addHelpText("after", `
|
|
31
33
|
Examples:
|
|
32
34
|
npx @gonkagate/claude-code
|
|
35
|
+
npx @gonkagate/claude-code-setup
|
|
33
36
|
npx @gonkagate/claude-code --model ${DEFAULT_MODEL_KEY}
|
|
34
37
|
npx @gonkagate/claude-code --scope local
|
|
35
38
|
|
|
@@ -42,10 +45,10 @@ ${supportedModelLines}
|
|
|
42
45
|
}
|
|
43
46
|
return program;
|
|
44
47
|
}
|
|
45
|
-
export function parseCliOptions(argv, output) {
|
|
48
|
+
export function parseCliOptions(argv, output, commandName = DEFAULT_COMMAND_NAME) {
|
|
46
49
|
rejectApiKeyArgs(argv);
|
|
47
|
-
const program = createProgram(output);
|
|
48
|
-
program.parse(["node",
|
|
50
|
+
const program = createProgram(output, commandName);
|
|
51
|
+
program.parse(["node", commandName, ...argv]);
|
|
49
52
|
const options = program.opts();
|
|
50
53
|
return {
|
|
51
54
|
help: false,
|
|
@@ -54,6 +57,12 @@ export function parseCliOptions(argv, output) {
|
|
|
54
57
|
modelKey: options.model
|
|
55
58
|
};
|
|
56
59
|
}
|
|
60
|
+
function getCommandNameFromArgv() {
|
|
61
|
+
const commandName = process.argv[1] === undefined
|
|
62
|
+
? DEFAULT_COMMAND_NAME
|
|
63
|
+
: basename(process.argv[1]).replace(/\.(?:js|ts)$/, "");
|
|
64
|
+
return commandName === "cli" ? DEFAULT_COMMAND_NAME : commandName;
|
|
65
|
+
}
|
|
57
66
|
function printIntro() {
|
|
58
67
|
console.log("Connect Claude Code to GonkaGate in one step.\n");
|
|
59
68
|
console.log("This installer writes Claude Code settings for GonkaGate's public gateway.");
|
|
@@ -77,23 +86,46 @@ function printSuccess(targetPath, scope, selectedModel, backupPath) {
|
|
|
77
86
|
console.log("Keep .claude/settings.local.json uncommitted.");
|
|
78
87
|
}
|
|
79
88
|
}
|
|
80
|
-
export async function
|
|
81
|
-
const
|
|
89
|
+
export async function resolveSettingsTarget(scope, cwd, chooseTrackedLocalSettingsAction = promptForTrackedLocalSettingsAction) {
|
|
90
|
+
const target = getSettingsTarget(scope, cwd);
|
|
91
|
+
if (scope !== "local") {
|
|
92
|
+
return target;
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
await ensureLocalSettingsIgnored(target.path);
|
|
96
|
+
return target;
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
if (!(error instanceof TrackedLocalSettingsError)) {
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
const action = await chooseTrackedLocalSettingsAction(error.relativeTargetPath);
|
|
103
|
+
if (action === "user") {
|
|
104
|
+
console.log("\nSwitching to user scope so the repository stays unchanged.");
|
|
105
|
+
return getSettingsTarget("user", cwd);
|
|
106
|
+
}
|
|
107
|
+
if (action === "cancel") {
|
|
108
|
+
throw new Error("Installation cancelled.");
|
|
109
|
+
}
|
|
110
|
+
await stopTrackingLocalSettings(target.path);
|
|
111
|
+
console.log(`\nStopped tracking ${error.relativeTargetPath} in git and added a local exclude.`);
|
|
112
|
+
return target;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
export async function run(argv = process.argv.slice(2), commandName = getCommandNameFromArgv()) {
|
|
116
|
+
const options = parseCliOptions(argv, undefined, commandName);
|
|
82
117
|
printIntro();
|
|
83
118
|
const apiKey = validateApiKey(await promptForApiKey());
|
|
84
119
|
const selectedModel = options.modelKey
|
|
85
120
|
? requireSupportedModel(options.modelKey)
|
|
86
121
|
: await promptForModel(SUPPORTED_MODELS, DEFAULT_MODEL_KEY);
|
|
87
|
-
const
|
|
88
|
-
const target =
|
|
89
|
-
if (scope === "local") {
|
|
90
|
-
await ensureLocalSettingsIgnored(target.path);
|
|
91
|
-
}
|
|
122
|
+
const requestedScope = options.scope ?? (await promptForScope("user"));
|
|
123
|
+
const target = await resolveSettingsTarget(requestedScope, process.cwd());
|
|
92
124
|
const loaded = await loadSettings(target.path);
|
|
93
125
|
const mergedSettings = mergeSettingsWithGonkaEnv(loaded.settings, apiKey, selectedModel);
|
|
94
126
|
const backupPath = loaded.exists ? await createBackup(target.path) : undefined;
|
|
95
127
|
await writeSettings(target.path, mergedSettings);
|
|
96
|
-
printSuccess(target.path, scope, selectedModel, backupPath);
|
|
128
|
+
printSuccess(target.path, target.scope, selectedModel, backupPath);
|
|
97
129
|
}
|
|
98
130
|
function handleCliError(error) {
|
|
99
131
|
if (error instanceof CommanderError) {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACzH,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1,7 @@
|
|
|
1
|
+
export declare class TrackedLocalSettingsError extends Error {
|
|
2
|
+
readonly relativeTargetPath: string;
|
|
3
|
+
readonly repoRoot: string;
|
|
4
|
+
constructor(relativeTargetPath: string, repoRoot: string);
|
|
5
|
+
}
|
|
1
6
|
export declare function ensureLocalSettingsIgnored(targetPath: string): Promise<void>;
|
|
7
|
+
export declare function stopTrackingLocalSettings(targetPath: string): Promise<void>;
|
|
@@ -3,20 +3,56 @@ import { access, lstat, mkdir, readFile, stat, writeFile } from "node:fs/promise
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { promisify } from "node:util";
|
|
5
5
|
const execFileAsync = promisify(execFile);
|
|
6
|
+
export class TrackedLocalSettingsError extends Error {
|
|
7
|
+
relativeTargetPath;
|
|
8
|
+
repoRoot;
|
|
9
|
+
constructor(relativeTargetPath, repoRoot) {
|
|
10
|
+
super(`Refusing local install because ${relativeTargetPath} is already tracked by git. Remove it from the index before writing secrets.`);
|
|
11
|
+
this.name = "TrackedLocalSettingsError";
|
|
12
|
+
this.relativeTargetPath = relativeTargetPath;
|
|
13
|
+
this.repoRoot = repoRoot;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
6
16
|
export async function ensureLocalSettingsIgnored(targetPath) {
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
if (!gitContext) {
|
|
17
|
+
const localSettingsContext = await getLocalSettingsGitContext(targetPath);
|
|
18
|
+
if (!localSettingsContext.gitContext || !localSettingsContext.relativeTargetPath) {
|
|
10
19
|
return;
|
|
11
20
|
}
|
|
12
|
-
const relativeTargetPath =
|
|
21
|
+
const { gitContext, relativeTargetPath } = localSettingsContext;
|
|
13
22
|
await assertTargetIsNotTracked(relativeTargetPath, gitContext.repoRoot);
|
|
23
|
+
await ensureTargetIgnored(gitContext.gitDir, relativeTargetPath);
|
|
24
|
+
}
|
|
25
|
+
export async function stopTrackingLocalSettings(targetPath) {
|
|
26
|
+
const localSettingsContext = await getLocalSettingsGitContext(targetPath);
|
|
27
|
+
if (!localSettingsContext.gitContext || !localSettingsContext.relativeTargetPath) {
|
|
28
|
+
throw new Error("Git repository is required to stop tracking local Claude Code settings.");
|
|
29
|
+
}
|
|
30
|
+
const { gitContext, relativeTargetPath } = localSettingsContext;
|
|
31
|
+
await ensureTargetIgnored(gitContext.gitDir, relativeTargetPath);
|
|
32
|
+
await execFileAsync("git", ["-C", gitContext.repoRoot, "rm", "--cached", "--quiet", "--force", "--", relativeTargetPath], {
|
|
33
|
+
encoding: "utf8"
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
async function getLocalSettingsGitContext(targetPath) {
|
|
37
|
+
const gitContext = await findGitContext(path.dirname(targetPath));
|
|
38
|
+
await assertSafeLocalSettingsTarget(targetPath, gitContext?.repoRoot);
|
|
39
|
+
if (!gitContext) {
|
|
40
|
+
return {
|
|
41
|
+
gitContext: null
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
gitContext,
|
|
46
|
+
relativeTargetPath: requireRepoRelativePath(targetPath, gitContext.repoRoot)
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
async function ensureTargetIgnored(gitDir, relativeTargetPath) {
|
|
14
50
|
const normalizedRelativePath = relativeTargetPath.split(path.sep).join("/");
|
|
15
51
|
const ignoreEntries = [
|
|
16
52
|
`/${normalizedRelativePath}`,
|
|
17
53
|
`/${normalizedRelativePath}.backup-*`
|
|
18
54
|
];
|
|
19
|
-
const excludePath = path.join(
|
|
55
|
+
const excludePath = path.join(gitDir, "info", "exclude");
|
|
20
56
|
const existingContent = await readOptionalFile(excludePath);
|
|
21
57
|
const existingEntries = new Set(existingContent
|
|
22
58
|
.split(/\r?\n/)
|
|
@@ -87,7 +123,7 @@ async function assertTargetIsNotTracked(relativeTargetPath, repoRoot) {
|
|
|
87
123
|
await execFileAsync("git", ["-C", repoRoot, "ls-files", "--error-unmatch", "--", relativeTargetPath], {
|
|
88
124
|
encoding: "utf8"
|
|
89
125
|
});
|
|
90
|
-
throw new
|
|
126
|
+
throw new TrackedLocalSettingsError(relativeTargetPath, repoRoot);
|
|
91
127
|
}
|
|
92
128
|
catch (error) {
|
|
93
129
|
if (isMissingGitBinaryError(error)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-git-ignore.js","sourceRoot":"","sources":["../../src/install/local-git-ignore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACnF,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"local-git-ignore.js","sourceRoot":"","sources":["../../src/install/local-git-ignore.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { SupportedModel, SupportedModelKey } from "../constants/models.js";
|
|
2
2
|
import type { InstallScope } from "../types/settings.js";
|
|
3
|
+
export type TrackedLocalSettingsAction = "untrack" | "user" | "cancel";
|
|
3
4
|
export declare function promptForApiKey(): Promise<string>;
|
|
4
5
|
interface SelectChoice<Value> {
|
|
5
6
|
value: Value;
|
|
@@ -20,6 +21,8 @@ interface SelectPromptConfig<Value> {
|
|
|
20
21
|
type SelectPrompt<Value> = (config: SelectPromptConfig<Value>) => Promise<Value>;
|
|
21
22
|
export declare function buildScopePromptConfig(defaultScope: InstallScope): SelectPromptConfig<InstallScope>;
|
|
22
23
|
export declare function promptForScope(defaultScope: InstallScope, selectPrompt?: SelectPrompt<InstallScope>): Promise<InstallScope>;
|
|
24
|
+
export declare function buildTrackedLocalSettingsPromptConfig(relativeTargetPath: string): SelectPromptConfig<TrackedLocalSettingsAction>;
|
|
25
|
+
export declare function promptForTrackedLocalSettingsAction(relativeTargetPath: string, selectPrompt?: SelectPrompt<TrackedLocalSettingsAction>): Promise<TrackedLocalSettingsAction>;
|
|
23
26
|
export declare function buildModelPromptConfig(models: readonly SupportedModel[], defaultModelKey: SupportedModelKey): SelectPromptConfig<SupportedModelKey>;
|
|
24
27
|
export declare function promptForModel(models: readonly SupportedModel[], defaultModelKey: SupportedModelKey, selectPrompt?: SelectPrompt<SupportedModelKey>): Promise<SupportedModel>;
|
|
25
28
|
export {};
|
package/dist/install/prompts.js
CHANGED
|
@@ -37,6 +37,39 @@ export function buildScopePromptConfig(defaultScope) {
|
|
|
37
37
|
export async function promptForScope(defaultScope, selectPrompt = select) {
|
|
38
38
|
return selectPrompt(buildScopePromptConfig(defaultScope)).catch(rethrowPromptExit);
|
|
39
39
|
}
|
|
40
|
+
export function buildTrackedLocalSettingsPromptConfig(relativeTargetPath) {
|
|
41
|
+
return {
|
|
42
|
+
message: `${relativeTargetPath} is already tracked by git. How should setup continue?`,
|
|
43
|
+
default: "untrack",
|
|
44
|
+
choices: [
|
|
45
|
+
{
|
|
46
|
+
value: "untrack",
|
|
47
|
+
name: "Stop tracking and continue",
|
|
48
|
+
short: "untrack",
|
|
49
|
+
description: `Run git rm --cached for ${relativeTargetPath}, keep the file locally, and add a local git exclude.`
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
value: "user",
|
|
53
|
+
name: "Switch to user scope",
|
|
54
|
+
short: "user",
|
|
55
|
+
description: "Write ~/.claude/settings.json instead and leave the repository alone."
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
value: "cancel",
|
|
59
|
+
name: "Cancel installation",
|
|
60
|
+
short: "cancel",
|
|
61
|
+
description: "Stop now without changing Claude Code settings."
|
|
62
|
+
}
|
|
63
|
+
],
|
|
64
|
+
loop: false,
|
|
65
|
+
theme: {
|
|
66
|
+
indexMode: "number"
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
export async function promptForTrackedLocalSettingsAction(relativeTargetPath, selectPrompt = select) {
|
|
71
|
+
return selectPrompt(buildTrackedLocalSettingsPromptConfig(relativeTargetPath)).catch(rethrowPromptExit);
|
|
72
|
+
}
|
|
40
73
|
export function buildModelPromptConfig(models, defaultModelKey) {
|
|
41
74
|
if (models.length === 0) {
|
|
42
75
|
throw new Error("No supported GonkaGate models are configured.");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/install/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/install/prompts.ts"],"names":[],"mappings":"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"}
|
package/docs/how-it-works.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
`gonkagate-claude-code` is a small Node-based installer for local `Claude Code`.
|
|
4
4
|
|
|
5
|
+
The primary package remains `@gonkagate/claude-code`. The setup-style alias package `@gonkagate/claude-code-setup` runs the same installer for consistency with the other GonkaGate agent setup packages.
|
|
6
|
+
|
|
5
7
|
## Fixed product contract
|
|
6
8
|
|
|
7
9
|
These values are intentionally fixed by the installer:
|
|
@@ -31,7 +33,7 @@ It does not touch any shell profile or other configuration file.
|
|
|
31
33
|
|
|
32
34
|
For `local` scope inside a git repository, it also adds `.claude/settings.local.json` and `.claude/settings.local.json.backup-*` to `.git/info/exclude` before writing the file.
|
|
33
35
|
|
|
34
|
-
For safety, local scope
|
|
36
|
+
For safety, local scope checks whether `.claude/settings.local.json` is already tracked by git. If it is, the installer offers to stop tracking that file and continue local setup, or switch to `user` scope instead. It also refuses any existing symlinked path component on the way to the target. That includes a symlinked `.claude` directory and a symlinked local settings file.
|
|
35
37
|
|
|
36
38
|
## Write behavior
|
|
37
39
|
|
package/docs/security.md
CHANGED
|
@@ -8,6 +8,8 @@ The recommended install flow is interactive:
|
|
|
8
8
|
npx @gonkagate/claude-code
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
The setup-style alias `npx @gonkagate/claude-code-setup` runs the same interactive installer.
|
|
12
|
+
|
|
11
13
|
The installer asks for the API key through a hidden prompt. It intentionally rejects `--api-key ...` arguments so secrets do not end up in shell history or process lists.
|
|
12
14
|
|
|
13
15
|
## Where the key is stored
|
|
@@ -21,7 +23,9 @@ This repo does not write `.env` files and does not modify shell startup files. I
|
|
|
21
23
|
|
|
22
24
|
## Local scope hygiene
|
|
23
25
|
|
|
24
|
-
If you choose `local` scope inside a git repository, the installer first
|
|
26
|
+
If you choose `local` scope inside a git repository, the installer first checks whether `.claude/settings.local.json` is already tracked by git. If it is already tracked, the installer offers to either stop tracking that file and continue local setup, or switch to `user` scope instead of writing a secret into a still-tracked file.
|
|
27
|
+
|
|
28
|
+
If you choose the stop-tracking recovery path, the installer runs `git rm --cached` for `.claude/settings.local.json`, keeps the file in your working tree, and adds local ignore rules before writing the secret-bearing settings file. That stages the file removal from version control, which is usually the right outcome for a repo-local secrets file.
|
|
25
29
|
|
|
26
30
|
For untracked local installs, the installer adds `.claude/settings.local.json` and its timestamped backup pattern to the repo's `.git/info/exclude` before writing the file so secret-bearing local settings do not immediately show up in git.
|
|
27
31
|
|
package/docs/troubleshooting.md
CHANGED
|
@@ -39,6 +39,12 @@ You can also skip the interactive model prompt with:
|
|
|
39
39
|
npx @gonkagate/claude-code --model <model-key>
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
+
The setup-style alias accepts the same options:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npx @gonkagate/claude-code-setup --model <model-key>
|
|
46
|
+
```
|
|
47
|
+
|
|
42
48
|
Only current curated keys are accepted.
|
|
43
49
|
|
|
44
50
|
## Corrupted settings file
|
|
@@ -51,13 +57,23 @@ Restore from the timestamped backup next to the settings file, or fix the JSON m
|
|
|
51
57
|
|
|
52
58
|
Rerun the installer and choose `local` scope. That writes `.claude/settings.local.json` in the current repository instead of editing your global `~/.claude/settings.json`.
|
|
53
59
|
|
|
54
|
-
##
|
|
60
|
+
## `.claude/settings.local.json` is already tracked by git
|
|
61
|
+
|
|
62
|
+
For `local` scope, the installer now detects when `.claude/settings.local.json` is already a tracked file in the repository and offers a recovery choice.
|
|
55
63
|
|
|
56
|
-
|
|
64
|
+
The recommended option is to stop tracking that file and continue. The installer will:
|
|
57
65
|
|
|
58
|
-
|
|
66
|
+
- run `git rm --cached` for `.claude/settings.local.json`
|
|
67
|
+
- keep the file in your working tree
|
|
68
|
+
- add local exclude entries so the file stays uncommitted going forward
|
|
59
69
|
|
|
60
|
-
|
|
70
|
+
If that repository intentionally versions `.claude/settings.local.json`, choose `user` scope instead.
|
|
71
|
+
|
|
72
|
+
You can still do the stop-tracking step manually if you prefer:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
git rm --cached -- .claude/settings.local.json
|
|
76
|
+
```
|
|
61
77
|
|
|
62
78
|
## Local install refused because the target path uses a symlink
|
|
63
79
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gonkagate/claude-code",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "CLI installer for using Claude Code with GonkaGate on Gonka Network.",
|
|
5
5
|
"homepage": "https://github.com/GonkaGate/gonkagate-claude-code#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
},
|
|
13
13
|
"type": "module",
|
|
14
14
|
"bin": {
|
|
15
|
+
"claude-code-setup": "bin/gonkagate-claude-code.js",
|
|
15
16
|
"gonkagate-claude-code": "bin/gonkagate-claude-code.js"
|
|
16
17
|
},
|
|
17
18
|
"files": [
|
|
@@ -27,6 +28,7 @@
|
|
|
27
28
|
"build": "tsc -p tsconfig.json",
|
|
28
29
|
"dev": "tsx src/cli.ts",
|
|
29
30
|
"prepack": "npm run build",
|
|
31
|
+
"publish:alias": "node scripts/publish-alias-package.mjs",
|
|
30
32
|
"test": "node scripts/run-tests.mjs",
|
|
31
33
|
"ci": "npm test && npm run build"
|
|
32
34
|
},
|
|
@@ -42,7 +44,9 @@
|
|
|
42
44
|
"gonka-api",
|
|
43
45
|
"gonka gateway",
|
|
44
46
|
"claude-code",
|
|
45
|
-
"claude code"
|
|
47
|
+
"claude code",
|
|
48
|
+
"claude-code-setup",
|
|
49
|
+
"setup"
|
|
46
50
|
],
|
|
47
51
|
"license": "Apache-2.0",
|
|
48
52
|
"packageManager": "npm@11.11.1",
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { constants as fsConstants } from "node:fs";
|
|
3
|
+
import { access, cp, mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { dirname, join, resolve } from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
|
|
8
|
+
const ALIAS_PACKAGE_NAME = "@gonkagate/claude-code-setup";
|
|
9
|
+
const ALIAS_BIN_NAME = "claude-code-setup";
|
|
10
|
+
const dryRun = process.argv.includes("--dry-run");
|
|
11
|
+
|
|
12
|
+
const scriptDir = dirname(fileURLToPath(import.meta.url));
|
|
13
|
+
const repoRoot = resolve(scriptDir, "..");
|
|
14
|
+
|
|
15
|
+
function run(command, args, options = {}) {
|
|
16
|
+
const result = spawnSync(command, args, {
|
|
17
|
+
cwd: repoRoot,
|
|
18
|
+
stdio: "inherit",
|
|
19
|
+
...options
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
if (result.error) {
|
|
23
|
+
throw result.error;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (result.status !== 0) {
|
|
27
|
+
process.exit(result.status ?? 1);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function isPublished(packageName, version) {
|
|
32
|
+
const result = spawnSync("npm", ["view", `${packageName}@${version}`, "version"], {
|
|
33
|
+
cwd: repoRoot,
|
|
34
|
+
encoding: "utf8",
|
|
35
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
if (result.status === 0) {
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const output = `${result.stdout}\n${result.stderr}`;
|
|
43
|
+
if (output.includes("E404") || output.includes("404 Not Found")) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
process.stdout.write(result.stdout);
|
|
48
|
+
process.stderr.write(result.stderr);
|
|
49
|
+
process.exit(result.status ?? 1);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async function assertExists(path) {
|
|
53
|
+
await access(path, fsConstants.R_OK);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const rootPackage = JSON.parse(await readFile(join(repoRoot, "package.json"), "utf8"));
|
|
57
|
+
const packageVersion = rootPackage.version;
|
|
58
|
+
|
|
59
|
+
if (!dryRun && isPublished(ALIAS_PACKAGE_NAME, packageVersion)) {
|
|
60
|
+
console.log(`${ALIAS_PACKAGE_NAME}@${packageVersion} is already published; skipping alias publish.`);
|
|
61
|
+
process.exit(0);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
for (const path of ["bin", "dist", "docs", "README.md", "CHANGELOG.md", "LICENSE"]) {
|
|
65
|
+
await assertExists(join(repoRoot, path));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const tempRoot = await mkdtemp(join(tmpdir(), "gonkagate-claude-code-setup-"));
|
|
69
|
+
const packageRoot = join(tempRoot, "package");
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
await mkdir(packageRoot, { recursive: true });
|
|
73
|
+
|
|
74
|
+
for (const path of ["bin", "dist", "docs", "README.md", "CHANGELOG.md", "LICENSE"]) {
|
|
75
|
+
await cp(join(repoRoot, path), join(packageRoot, path), { recursive: true });
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const aliasPackage = {
|
|
79
|
+
name: ALIAS_PACKAGE_NAME,
|
|
80
|
+
version: packageVersion,
|
|
81
|
+
description: "Setup-style alias for the GonkaGate Claude Code installer.",
|
|
82
|
+
homepage: rootPackage.homepage,
|
|
83
|
+
bugs: rootPackage.bugs,
|
|
84
|
+
repository: rootPackage.repository,
|
|
85
|
+
type: rootPackage.type,
|
|
86
|
+
bin: {
|
|
87
|
+
[ALIAS_BIN_NAME]: "bin/gonkagate-claude-code.js"
|
|
88
|
+
},
|
|
89
|
+
files: ["bin", "dist", "docs", "README.md", "CHANGELOG.md", "LICENSE"],
|
|
90
|
+
engines: rootPackage.engines,
|
|
91
|
+
keywords: Array.from(new Set([...rootPackage.keywords, ALIAS_BIN_NAME, "setup"])),
|
|
92
|
+
license: rootPackage.license,
|
|
93
|
+
dependencies: rootPackage.dependencies
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
await writeFile(join(packageRoot, "package.json"), `${JSON.stringify(aliasPackage, null, 2)}\n`, "utf8");
|
|
97
|
+
|
|
98
|
+
const publishArgs = ["publish", "--access", "public"];
|
|
99
|
+
if (dryRun) {
|
|
100
|
+
publishArgs.push("--dry-run");
|
|
101
|
+
} else {
|
|
102
|
+
publishArgs.push("--provenance");
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
run("npm", publishArgs, { cwd: packageRoot });
|
|
106
|
+
} finally {
|
|
107
|
+
await rm(tempRoot, { recursive: true, force: true });
|
|
108
|
+
}
|