@hunyed15/codecgc 0.1.0 → 0.1.2
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/INSTALLATION.md +28 -5
- package/README.md +21 -10
- package/package.json +3 -1
- package/scripts/install_codecgc.py +90 -0
- package/scripts/postinstall_codecgc.js +75 -0
package/INSTALLATION.md
CHANGED
|
@@ -34,16 +34,39 @@ npm --version # 应显示 9.x.x 或更高
|
|
|
34
34
|
|
|
35
35
|
## 安装 CodeCGC
|
|
36
36
|
|
|
37
|
-
### 方式 1
|
|
37
|
+
### 方式 1:从 npm 全局安装(推荐)
|
|
38
38
|
|
|
39
39
|
```bash
|
|
40
|
-
#
|
|
41
|
-
|
|
40
|
+
# 使用 npm 官方源安装
|
|
41
|
+
npm install -g @hunyed15/codecgc --registry=https://registry.npmjs.org/
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
安装完成后,CodeCGC 会尝试自动执行一次用户级 Claude 集成,相当于:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
cgc-install --mode user
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
这会写入:
|
|
51
|
+
|
|
52
|
+
- `~/.claude/mcp.json`
|
|
53
|
+
- `~/.claude/hooks/route-edit.ps1`
|
|
54
|
+
- `~/.claude/commands/cgc.md`
|
|
55
|
+
- `~/.claude/commands/cgc-install.md`
|
|
56
|
+
- `~/.claude/commands/cgc-status.md`
|
|
57
|
+
- `~/.claude/commands/cgc-doctor.md`
|
|
42
58
|
|
|
43
|
-
|
|
44
|
-
|
|
59
|
+
写入完成后,可以在 Claude 中直接输入:
|
|
60
|
+
|
|
61
|
+
```text
|
|
62
|
+
/cgc
|
|
63
|
+
/cgc-install
|
|
64
|
+
/cgc-status
|
|
65
|
+
/cgc-doctor
|
|
45
66
|
```
|
|
46
67
|
|
|
68
|
+
如果安装阶段因为 Python 未就绪而跳过了这一步,可以在装好 Python 后手动补执行该命令。
|
|
69
|
+
|
|
47
70
|
安装后,以下命令将全局可用:
|
|
48
71
|
- `cgc`
|
|
49
72
|
- `cgc-install`
|
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# CodeCGC Release v0.1.
|
|
1
|
+
# CodeCGC Release v0.1.2
|
|
2
2
|
|
|
3
3
|
## 📦 发布内容
|
|
4
4
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
## 📋 版本信息
|
|
8
8
|
|
|
9
|
-
- **版本号**: 0.1.
|
|
9
|
+
- **版本号**: 0.1.2
|
|
10
10
|
- **发布日期**: 2026-05-04
|
|
11
11
|
- **Python 要求**: >= 3.10
|
|
12
12
|
- **Node.js 要求**: >= 20.0.0
|
|
@@ -36,20 +36,31 @@
|
|
|
36
36
|
### 1. 安装
|
|
37
37
|
|
|
38
38
|
```bash
|
|
39
|
-
#
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
# 安装 CodeCGC
|
|
43
|
-
npm install -g .
|
|
39
|
+
# 从 npm 安装 CodeCGC
|
|
40
|
+
npm install -g @hunyed15/codecgc --registry=https://registry.npmjs.org/
|
|
44
41
|
|
|
45
42
|
# 安装 Python 依赖
|
|
46
43
|
pip install pyyaml
|
|
47
44
|
|
|
48
|
-
#
|
|
49
|
-
|
|
50
|
-
cd geminimcp && pip install -e . && cd ..
|
|
45
|
+
# 如自动集成未生效,可手动补执行
|
|
46
|
+
cgc-install --mode user
|
|
51
47
|
```
|
|
52
48
|
|
|
49
|
+
全局安装完成后,CodeCGC 会尝试自动写入 Claude 用户级集成到 `~/.claude`,包括:
|
|
50
|
+
|
|
51
|
+
- `~/.claude/mcp.json`
|
|
52
|
+
- `~/.claude/hooks/route-edit.ps1`
|
|
53
|
+
- `~/.claude/commands/cgc*.md` 自定义 slash commands
|
|
54
|
+
|
|
55
|
+
安装完成后,可以在 Claude 中直接使用:
|
|
56
|
+
|
|
57
|
+
- `/cgc`
|
|
58
|
+
- `/cgc-install`
|
|
59
|
+
- `/cgc-status`
|
|
60
|
+
- `/cgc-doctor`
|
|
61
|
+
|
|
62
|
+
如果安装时 Python 尚未就绪,自动集成会跳过,此时可在安装 Python 后手动执行 `cgc-install --mode user`。
|
|
63
|
+
|
|
53
64
|
### 2. 初始化项目
|
|
54
65
|
|
|
55
66
|
```bash
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hunyed15/codecgc",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Claude-hosted multi-model workflow product shell for CodeCGC.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"cgc-route": "bin/cgc-route.js"
|
|
24
24
|
},
|
|
25
25
|
"scripts": {
|
|
26
|
+
"postinstall": "node scripts/postinstall_codecgc.js",
|
|
26
27
|
"cgc:help": "node bin/cgc.js --help",
|
|
27
28
|
"cgc:status": "node bin/cgc-status.js --format summary",
|
|
28
29
|
"cgc:doctor": "node bin/cgc-doctor.js --format summary",
|
|
@@ -39,6 +40,7 @@
|
|
|
39
40
|
"files": [
|
|
40
41
|
"bin/",
|
|
41
42
|
"scripts/*.py",
|
|
43
|
+
"scripts/postinstall_codecgc.js",
|
|
42
44
|
"scripts/README-codecgc-cli.md",
|
|
43
45
|
".claude/hooks/route-edit.ps1",
|
|
44
46
|
"codecgc/cgc/",
|
|
@@ -64,6 +64,7 @@ def get_user_claude_paths(override_root: str = "") -> dict[str, Path]:
|
|
|
64
64
|
"mcp": root / "mcp.json",
|
|
65
65
|
"hooks_dir": root / "hooks",
|
|
66
66
|
"hook_script": root / "hooks" / "route-edit.ps1",
|
|
67
|
+
"commands_dir": root / "commands",
|
|
67
68
|
}
|
|
68
69
|
|
|
69
70
|
|
|
@@ -78,6 +79,7 @@ def get_workspace_paths(override_workspace: str = "") -> dict[str, Path]:
|
|
|
78
79
|
"settings": claude_dir / "settings.json",
|
|
79
80
|
"mcp": root / ".mcp.json",
|
|
80
81
|
"hook_script": hooks_dir / "route-edit.ps1",
|
|
82
|
+
"commands_dir": claude_dir / "commands",
|
|
81
83
|
"routing_file": root / "model-routing.yaml",
|
|
82
84
|
}
|
|
83
85
|
|
|
@@ -110,6 +112,79 @@ def build_hook_payload(command_text: str) -> dict[str, Any]:
|
|
|
110
112
|
}
|
|
111
113
|
|
|
112
114
|
|
|
115
|
+
def _normalize_command_path_for_markdown(path: Path) -> str:
|
|
116
|
+
return str(path).replace("\\", "\\\\")
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def build_custom_command_templates(bin_dir: Path) -> dict[str, str]:
|
|
120
|
+
cgc_js = _normalize_command_path_for_markdown(bin_dir / "cgc.js")
|
|
121
|
+
install_js = _normalize_command_path_for_markdown(bin_dir / "cgc-install.js")
|
|
122
|
+
status_js = _normalize_command_path_for_markdown(bin_dir / "cgc-status.js")
|
|
123
|
+
doctor_js = _normalize_command_path_for_markdown(bin_dir / "cgc-doctor.js")
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
"cgc.md": f"""---
|
|
127
|
+
description: Run CodeCGC in the current project
|
|
128
|
+
argument-hint: "[request or flags]"
|
|
129
|
+
---
|
|
130
|
+
Use the Bash tool to run CodeCGC in the current project directory.
|
|
131
|
+
|
|
132
|
+
- If the user supplied arguments, run:
|
|
133
|
+
`node "{cgc_js}" $ARGUMENTS`
|
|
134
|
+
- If the user did not supply arguments, run:
|
|
135
|
+
`node "{cgc_js}" --help`
|
|
136
|
+
- Show the command you ran and summarize the result briefly.
|
|
137
|
+
""",
|
|
138
|
+
"cgc-install.md": f"""---
|
|
139
|
+
description: Install or sync CodeCGC integration for the current project or user Claude profile
|
|
140
|
+
argument-hint: "[flags]"
|
|
141
|
+
---
|
|
142
|
+
Use the Bash tool to run the CodeCGC install command.
|
|
143
|
+
|
|
144
|
+
- If the user supplied arguments, run:
|
|
145
|
+
`node "{install_js}" $ARGUMENTS`
|
|
146
|
+
- If the user did not supply arguments, run:
|
|
147
|
+
`node "{install_js}"`
|
|
148
|
+
- Show the command you ran and summarize the result briefly.
|
|
149
|
+
""",
|
|
150
|
+
"cgc-status.md": f"""---
|
|
151
|
+
description: Check CodeCGC integration status
|
|
152
|
+
argument-hint: "[flags]"
|
|
153
|
+
---
|
|
154
|
+
Use the Bash tool to run the CodeCGC status command.
|
|
155
|
+
|
|
156
|
+
- If the user supplied arguments, run:
|
|
157
|
+
`node "{status_js}" $ARGUMENTS`
|
|
158
|
+
- If the user did not supply arguments, run:
|
|
159
|
+
`node "{status_js}"`
|
|
160
|
+
- Show the command you ran and summarize the result briefly.
|
|
161
|
+
""",
|
|
162
|
+
"cgc-doctor.md": f"""---
|
|
163
|
+
description: Run CodeCGC doctor checks
|
|
164
|
+
argument-hint: "[flags]"
|
|
165
|
+
---
|
|
166
|
+
Use the Bash tool to run the CodeCGC doctor command.
|
|
167
|
+
|
|
168
|
+
- If the user supplied arguments, run:
|
|
169
|
+
`node "{doctor_js}" $ARGUMENTS`
|
|
170
|
+
- If the user did not supply arguments, run:
|
|
171
|
+
`node "{doctor_js}"`
|
|
172
|
+
- Show the command you ran and summarize the result briefly.
|
|
173
|
+
""",
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def write_custom_command_files(target_dir: Path, bin_dir: Path) -> list[str]:
|
|
178
|
+
target_dir.mkdir(parents=True, exist_ok=True)
|
|
179
|
+
templates = build_custom_command_templates(bin_dir)
|
|
180
|
+
written: list[str] = []
|
|
181
|
+
for filename, content in templates.items():
|
|
182
|
+
path = target_dir / filename
|
|
183
|
+
path.write_text(content, encoding="utf-8")
|
|
184
|
+
written.append(str(path))
|
|
185
|
+
return written
|
|
186
|
+
|
|
187
|
+
|
|
113
188
|
def merge_hook_settings(current: dict[str, Any], command_text: str) -> tuple[dict[str, Any], bool]:
|
|
114
189
|
hooks = current.get("hooks")
|
|
115
190
|
expected_hooks = build_hook_payload(command_text)
|
|
@@ -240,6 +315,7 @@ def install_local_runtime(override_workspace: str = "") -> dict[str, Any]:
|
|
|
240
315
|
|
|
241
316
|
if PROJECT_HOOK_PATH.resolve() != workspace_paths["hook_script"].resolve():
|
|
242
317
|
shutil.copyfile(PROJECT_HOOK_PATH, workspace_paths["hook_script"])
|
|
318
|
+
written_commands = write_custom_command_files(workspace_paths["commands_dir"], WORKSPACE / "bin")
|
|
243
319
|
|
|
244
320
|
summary = build_mode_summary_payload(
|
|
245
321
|
scope="项目级 Claude 与 MCP 集成面",
|
|
@@ -255,10 +331,13 @@ def install_local_runtime(override_workspace: str = "") -> dict[str, Any]:
|
|
|
255
331
|
"routing_file": str(routing_path),
|
|
256
332
|
"claude_settings": str(workspace_paths["settings"]),
|
|
257
333
|
"hook_script": str(workspace_paths["hook_script"]),
|
|
334
|
+
"commands_dir": str(workspace_paths["commands_dir"]),
|
|
335
|
+
"command_files": written_commands,
|
|
258
336
|
"notes": [
|
|
259
337
|
"Repository-local MCP config was synced from the executor registry.",
|
|
260
338
|
"Project-local model-routing.yaml was synchronized and preserves custom path blocks.",
|
|
261
339
|
"Claude pre-edit guardrail hook was synchronized into the target workspace.",
|
|
340
|
+
"Project-local Claude slash commands were synchronized into .claude/commands.",
|
|
262
341
|
"This mode prepares project-level integration surfaces for the selected workspace.",
|
|
263
342
|
],
|
|
264
343
|
"summary": summary,
|
|
@@ -290,11 +369,13 @@ def preview_user_install(override_root: str = "") -> dict[str, Any]:
|
|
|
290
369
|
"settings_json": str(user_paths["settings"]),
|
|
291
370
|
"mcp_json": str(user_paths["mcp"]),
|
|
292
371
|
"hook_script": str(user_paths["hook_script"]),
|
|
372
|
+
"commands_dir": str(user_paths["commands_dir"]),
|
|
293
373
|
},
|
|
294
374
|
"would_write": {
|
|
295
375
|
"settings_changed": settings_changed or not user_paths["settings"].exists(),
|
|
296
376
|
"mcp_changed": True,
|
|
297
377
|
"hook_changed": True,
|
|
378
|
+
"commands_changed": True,
|
|
298
379
|
},
|
|
299
380
|
"preview": {
|
|
300
381
|
"settings": sanitize_for_preview(merged_settings),
|
|
@@ -313,12 +394,14 @@ def install_user_runtime(override_root: str = "") -> dict[str, Any]:
|
|
|
313
394
|
user_paths = get_user_claude_paths(override_root)
|
|
314
395
|
user_paths["root"].mkdir(parents=True, exist_ok=True)
|
|
315
396
|
user_paths["hooks_dir"].mkdir(parents=True, exist_ok=True)
|
|
397
|
+
user_paths["commands_dir"].mkdir(parents=True, exist_ok=True)
|
|
316
398
|
|
|
317
399
|
settings = load_json_file(user_paths["settings"])
|
|
318
400
|
merged_settings, settings_changed = merge_hook_settings(settings, build_user_hook_command(user_paths))
|
|
319
401
|
write_json_file(user_paths["settings"], merged_settings)
|
|
320
402
|
write_json_file(user_paths["mcp"], build_mcp_config())
|
|
321
403
|
shutil.copyfile(PROJECT_HOOK_PATH, user_paths["hook_script"])
|
|
404
|
+
written_commands = write_custom_command_files(user_paths["commands_dir"], WORKSPACE / "bin")
|
|
322
405
|
summary = build_mode_summary_payload(
|
|
323
406
|
scope="用户级 Claude 集成面",
|
|
324
407
|
human_summary="用户级 Claude 集成文件已写入。",
|
|
@@ -334,15 +417,19 @@ def install_user_runtime(override_root: str = "") -> dict[str, Any]:
|
|
|
334
417
|
"settings_json": str(user_paths["settings"]),
|
|
335
418
|
"mcp_json": str(user_paths["mcp"]),
|
|
336
419
|
"hook_script": str(user_paths["hook_script"]),
|
|
420
|
+
"commands_dir": str(user_paths["commands_dir"]),
|
|
337
421
|
},
|
|
338
422
|
"changes": {
|
|
339
423
|
"settings_changed": settings_changed or not user_paths["settings"].exists(),
|
|
340
424
|
"mcp_changed": True,
|
|
341
425
|
"hook_changed": True,
|
|
426
|
+
"commands_changed": True,
|
|
342
427
|
},
|
|
428
|
+
"command_files": written_commands,
|
|
343
429
|
"notes": [
|
|
344
430
|
"User-level Claude integration files were written to the selected root.",
|
|
345
431
|
"The user-level hook script was copied from the project hook source.",
|
|
432
|
+
"User-level Claude slash commands were written to ~/.claude/commands.",
|
|
346
433
|
"This mode is explicit and should be used only when a broader Claude integration surface is intended.",
|
|
347
434
|
],
|
|
348
435
|
"summary": summary,
|
|
@@ -373,6 +460,7 @@ def build_install_mode_summary(result: dict[str, Any]) -> str:
|
|
|
373
460
|
f"- Routing 文件: {result.get('routing_file', '')}",
|
|
374
461
|
f"- Claude 设置: {result.get('claude_settings', '')}",
|
|
375
462
|
f"- Hook 脚本: {result.get('hook_script', '')}",
|
|
463
|
+
f"- Slash Commands: {result.get('commands_dir', '')}",
|
|
376
464
|
"- 说明: 可选外部能力如 MemOS 不由 cgc-install 自动写入;如需启用,请在 Claude 中单独配置官方 MCP。",
|
|
377
465
|
]
|
|
378
466
|
next_actions = [
|
|
@@ -391,6 +479,7 @@ def build_install_mode_summary(result: dict[str, Any]) -> str:
|
|
|
391
479
|
f"- 预演 Settings: {planned.get('settings_json', '')}",
|
|
392
480
|
f"- 预演 MCP: {planned.get('mcp_json', '')}",
|
|
393
481
|
f"- 预演 Hook: {planned.get('hook_script', '')}",
|
|
482
|
+
f"- 预演 Slash Commands: {planned.get('commands_dir', '')}",
|
|
394
483
|
"- 说明: 该预演只覆盖 CodeCGC 必需执行器;MemOS 等可选外部能力仍建议在 Claude 中独立配置。",
|
|
395
484
|
]
|
|
396
485
|
next_actions = []
|
|
@@ -410,6 +499,7 @@ def build_install_mode_summary(result: dict[str, Any]) -> str:
|
|
|
410
499
|
f"- Settings: {written.get('settings_json', '')}",
|
|
411
500
|
f"- MCP: {written.get('mcp_json', '')}",
|
|
412
501
|
f"- Hook 脚本: {written.get('hook_script', '')}",
|
|
502
|
+
f"- Slash Commands: {written.get('commands_dir', '')}",
|
|
413
503
|
"- 说明: 该安装只写入 CodeCGC 必需执行器;MemOS 等可选外部能力仍需在 Claude 中单独配置。",
|
|
414
504
|
]
|
|
415
505
|
next_actions = [
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { spawnSync } = require("node:child_process");
|
|
4
|
+
const path = require("node:path");
|
|
5
|
+
|
|
6
|
+
function shouldRunUserInstall() {
|
|
7
|
+
const globalFlag = String(process.env.npm_config_global || "").toLowerCase();
|
|
8
|
+
const localPrefix = String(process.env.npm_config_local_prefix || "");
|
|
9
|
+
const prefix = String(process.env.npm_config_prefix || "");
|
|
10
|
+
|
|
11
|
+
if (globalFlag === "true") {
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
if (prefix && localPrefix && prefix !== localPrefix) {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function findPython() {
|
|
21
|
+
const override = String(process.env.CODECGC_PYTHON_COMMAND || "").trim();
|
|
22
|
+
const candidates = override
|
|
23
|
+
? [override]
|
|
24
|
+
: (process.platform === "win32" ? ["python", "py"] : ["python3", "python"]);
|
|
25
|
+
|
|
26
|
+
for (const command of candidates) {
|
|
27
|
+
const probe = spawnSync(command, ["--version"], {
|
|
28
|
+
encoding: "utf8",
|
|
29
|
+
shell: false,
|
|
30
|
+
});
|
|
31
|
+
if (probe.status === 0) {
|
|
32
|
+
return command;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return "";
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function main() {
|
|
39
|
+
if (!shouldRunUserInstall()) {
|
|
40
|
+
return 0;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const python = findPython();
|
|
44
|
+
if (!python) {
|
|
45
|
+
console.warn("[codecgc] Skipped automatic Claude integration: Python was not found.");
|
|
46
|
+
console.warn("[codecgc] Run `cgc-install --mode user` after installing Python.");
|
|
47
|
+
return 0;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const repoRoot = path.resolve(__dirname, "..");
|
|
51
|
+
const installScript = path.join(repoRoot, "scripts", "install_codecgc.py");
|
|
52
|
+
const result = spawnSync(
|
|
53
|
+
python,
|
|
54
|
+
[installScript, "--mode", "user", "--format", "summary"],
|
|
55
|
+
{
|
|
56
|
+
cwd: repoRoot,
|
|
57
|
+
stdio: "inherit",
|
|
58
|
+
shell: false,
|
|
59
|
+
env: {
|
|
60
|
+
...process.env,
|
|
61
|
+
PYTHONIOENCODING: process.env.PYTHONIOENCODING || "utf-8",
|
|
62
|
+
PYTHONUTF8: process.env.PYTHONUTF8 || "1",
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
if (result.status !== 0) {
|
|
68
|
+
console.warn("[codecgc] Automatic Claude integration did not complete during npm install.");
|
|
69
|
+
console.warn("[codecgc] You can retry manually with `cgc-install --mode user`.");
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return 0;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
process.exit(main());
|