@hunyed15/codecgc 0.1.11 → 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/README.md +53 -5
- package/bin/{cgc-install.js → cgc-init.js} +1 -1
- package/bin/codecgc.js +22 -27
- package/codecgc/cgc/SKILL.md +1 -1
- package/codecgc/cgc-arch/SKILL.md +1 -1
- package/codecgc/cgc-onboard/SKILL.md +1 -1
- package/codecgc/reference/README.md +2 -2
- package/codecgc/reference/mcp-tool-surface.md +1 -0
- package/codecgc/reference/onboarding.md +7 -7
- package/codecgc/reference/operation-guide.md +4 -4
- package/codecgc/reference/path-contract.md +1 -1
- package/codecgc/reference/policy-routing.md +2 -2
- package/codecgc/reference/project-structure.md +6 -5
- package/codecgc/reference/quickstart.md +3 -3
- package/codecgc/reference/real-workflow-loop.md +1 -1
- package/codecgc/reference/shared-conventions.md +8 -1
- package/codecgc/reference/troubleshooting.md +2 -10
- package/codecgc/roadmap/codecgc-release-maintenance/delivery-plan.md +2 -3
- package/codecgc/roadmap/codecgc-release-maintenance/overview.md +1 -1
- package/codecgc/roadmap/codecgc-release-maintenance/phases.md +1 -1
- package/codecgc/templates/project/claude/hooks/route-edit.ps1 +87 -0
- package/codecgc/templates/{claude → project/claude}/settings.local.json +1 -8
- package/codecgc/templates/project/model-routing.yaml +60 -0
- package/{codecgcmcp → mcp/codecgcmcp}/src/codecgcmcp/server.py +2 -9
- package/{geminimcp → mcp/geminimcp}/src/geminimcp/server.py +24 -8
- package/model-routing.yaml +0 -1
- package/package.json +12 -13
- package/scripts/audit_codecgc_external_capabilities.py +1 -1
- package/scripts/audit_codecgc_package_runtime.py +18 -16
- package/scripts/audit_codecgc_release_readiness.py +1 -1
- package/scripts/codecgc_runtime/executor_registry.py +2 -2
- package/scripts/codecgc_runtime/mcp_config.py +2 -2
- package/scripts/codecgc_runtime/routing_template.py +0 -1
- package/scripts/exercise_mcp_tools.py +2 -2
- package/scripts/install_codecgc.py +37 -292
- package/scripts/postinstall_codecgc.js +1 -1
- package/INSTALLATION.md +0 -211
- package/codexmcp/LICENSE +0 -21
- package/codexmcp/README.md +0 -294
- package/codexmcp/pyproject.toml +0 -37
- package/geminimcp/README.md +0 -258
- package/geminimcp/pyproject.toml +0 -15
- /package/codecgc/templates/{codex → project/codex}/codecgcrc.json +0 -0
- /package/codecgc/templates/{gemini → project/gemini/policies}/codecgc-policy.toml +0 -0
- /package/{codecgcmcp → mcp/codecgcmcp}/README.md +0 -0
- /package/{codecgcmcp → mcp/codecgcmcp}/pyproject.toml +0 -0
- /package/{codecgcmcp → mcp/codecgcmcp}/src/codecgcmcp/__init__.py +0 -0
- /package/{codecgcmcp → mcp/codecgcmcp}/src/codecgcmcp/cli.py +0 -0
- /package/{codexmcp → mcp/codexmcp}/src/codexmcp/__init__.py +0 -0
- /package/{codexmcp → mcp/codexmcp}/src/codexmcp/cli.py +0 -0
- /package/{codexmcp → mcp/codexmcp}/src/codexmcp/server.py +0 -0
- /package/{geminimcp → mcp/geminimcp}/src/geminimcp/__init__.py +0 -0
- /package/{geminimcp → mcp/geminimcp}/src/geminimcp/cli.py +0 -0
|
@@ -19,20 +19,16 @@ from sync_codecgc_mcp_config import write_mcp_config
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
WORKSPACE = PACKAGE_ROOT
|
|
22
|
-
CLAUDE_DIR = WORKSPACE / ".claude"
|
|
23
|
-
HOOKS_DIR = CLAUDE_DIR / "hooks"
|
|
24
|
-
SETTINGS_PATH = CLAUDE_DIR / "settings.json"
|
|
25
|
-
MCP_CONFIG_PATH = WORKSPACE / ".mcp.json"
|
|
26
|
-
PROJECT_HOOK_PATH = HOOKS_DIR / "route-edit.ps1"
|
|
27
22
|
PROJECT_ROUTING_PATH = WORKSPACE / "model-routing.yaml"
|
|
28
|
-
PROJECT_TEMPLATES_DIR = WORKSPACE / "codecgc" / "templates"
|
|
23
|
+
PROJECT_TEMPLATES_DIR = WORKSPACE / "codecgc" / "templates" / "project"
|
|
24
|
+
PROJECT_HOOK_PATH = PROJECT_TEMPLATES_DIR / "claude" / "hooks" / "route-edit.ps1"
|
|
29
25
|
EDIT_GUARDRAIL_MATCHER = "Edit|Write|MultiEdit|Bash|PowerShell"
|
|
30
26
|
LEGACY_EDIT_GUARDRAIL_MATCHERS = {"Edit|Write", "Edit|Write|MultiEdit"}
|
|
31
27
|
PROJECT_ONBOARDING_RELATIVE_PATH = "codecgc/START_HERE.md"
|
|
32
28
|
PROJECT_ONBOARDING_MARKER = "<!-- codecgc:onboarding:v1 -->"
|
|
33
29
|
CLAUDE_SETTINGS_TEMPLATE = PROJECT_TEMPLATES_DIR / "claude" / "settings.local.json"
|
|
34
30
|
CODEX_POLICY_TEMPLATE = PROJECT_TEMPLATES_DIR / "codex" / "codecgcrc.json"
|
|
35
|
-
GEMINI_POLICY_TEMPLATE = PROJECT_TEMPLATES_DIR / "gemini" / "codecgc-policy.toml"
|
|
31
|
+
GEMINI_POLICY_TEMPLATE = PROJECT_TEMPLATES_DIR / "gemini" / "policies" / "codecgc-policy.toml"
|
|
36
32
|
|
|
37
33
|
|
|
38
34
|
DEFAULT_HOOKS = {
|
|
@@ -74,30 +70,6 @@ PROJECT_WORKFLOW_DIRS = [
|
|
|
74
70
|
]
|
|
75
71
|
|
|
76
72
|
|
|
77
|
-
def get_user_claude_root(override_root: str = "") -> Path:
|
|
78
|
-
override = override_root.strip() or os.environ.get("CODECGC_USER_CLAUDE_DIR", "").strip()
|
|
79
|
-
if override:
|
|
80
|
-
return Path(override).expanduser().resolve()
|
|
81
|
-
|
|
82
|
-
if os.name == "nt":
|
|
83
|
-
base = Path(os.environ.get("USERPROFILE", str(Path.home())))
|
|
84
|
-
else:
|
|
85
|
-
base = Path.home()
|
|
86
|
-
return (base / ".claude").resolve()
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
def get_user_claude_paths(override_root: str = "") -> dict[str, Path]:
|
|
90
|
-
root = get_user_claude_root(override_root)
|
|
91
|
-
return {
|
|
92
|
-
"root": root,
|
|
93
|
-
"settings": root / "settings.json",
|
|
94
|
-
"mcp": root / "mcp.json",
|
|
95
|
-
"hooks_dir": root / "hooks",
|
|
96
|
-
"hook_script": root / "hooks" / "route-edit.ps1",
|
|
97
|
-
"commands_dir": root / "commands",
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
|
|
101
73
|
def get_workspace_paths(override_workspace: str = "") -> dict[str, Path]:
|
|
102
74
|
root = resolve_workspace_root(override_workspace)
|
|
103
75
|
claude_dir = root / ".claude"
|
|
@@ -158,7 +130,7 @@ def build_project_onboarding_text() -> str:
|
|
|
158
130
|
return f"""{PROJECT_ONBOARDING_MARKER}
|
|
159
131
|
# CodeCGC Start Here
|
|
160
132
|
|
|
161
|
-
This file is generated by `cgc-
|
|
133
|
+
This file is generated by `cgc-init` for this project. It is intentionally project-relative and should not contain machine-specific install paths.
|
|
162
134
|
|
|
163
135
|
## First Run
|
|
164
136
|
|
|
@@ -217,7 +189,7 @@ codecgc/reference/
|
|
|
217
189
|
|
|
218
190
|
## Recovery
|
|
219
191
|
|
|
220
|
-
- If project integration looks wrong, run `cgc-
|
|
192
|
+
- If project integration looks wrong, run `cgc-init`, then `cgc-status`.
|
|
221
193
|
- If runtime or executor startup fails, run `cgc-doctor`.
|
|
222
194
|
- If a write is blocked, inspect `model-routing.yaml`; it is the project-local policy source of truth.
|
|
223
195
|
- If an execution was rejected, use `/cgc` or `cgc` to continue the same workflow rather than starting a new one.
|
|
@@ -330,15 +302,15 @@ def build_custom_command_templates(bin_dir: Path) -> dict[str, str]:
|
|
|
330
302
|
fallback_command="cgc",
|
|
331
303
|
),
|
|
332
304
|
build_mcp_first_command_template(
|
|
333
|
-
filename="cgc-
|
|
334
|
-
description="
|
|
305
|
+
filename="cgc-init.md",
|
|
306
|
+
description="为当前项目安装/同步 CodeCGC 集成",
|
|
335
307
|
argument_hint="[参数]",
|
|
336
308
|
primary_tool="codecgc.install",
|
|
337
309
|
direct_rules=[
|
|
338
|
-
"把安装参数映射到 `codecgc.install` 的 `mode`、`workspace
|
|
310
|
+
"把安装参数映射到 `codecgc.install` 的 `mode`、`workspace` 等字段。",
|
|
339
311
|
"如果用户没有提供参数,就使用默认安装模式。",
|
|
340
312
|
],
|
|
341
|
-
fallback_command="cgc-
|
|
313
|
+
fallback_command="cgc-init",
|
|
342
314
|
),
|
|
343
315
|
build_mcp_first_command_template(
|
|
344
316
|
filename="cgc-status.md",
|
|
@@ -519,7 +491,7 @@ def build_custom_command_templates(bin_dir: Path) -> dict[str, str]:
|
|
|
519
491
|
),
|
|
520
492
|
]
|
|
521
493
|
)
|
|
522
|
-
templates["cgc-
|
|
494
|
+
templates["cgc-init.md"] = """---
|
|
523
495
|
description: Install or repair CodeCGC project-local integration
|
|
524
496
|
argument-hint: "[optional install arguments]"
|
|
525
497
|
---
|
|
@@ -529,7 +501,6 @@ Use the `codecgc.install` MCP tool as the primary path.
|
|
|
529
501
|
Default behavior:
|
|
530
502
|
|
|
531
503
|
- Run project-local install for the current workspace.
|
|
532
|
-
- Do not install user-level Claude files unless the user explicitly asks for `--mode user`.
|
|
533
504
|
- Treat `model-routing.yaml` as the single routing policy source.
|
|
534
505
|
|
|
535
506
|
Argument mapping:
|
|
@@ -538,12 +509,10 @@ Argument mapping:
|
|
|
538
509
|
- `status`: call `codecgc.install` with `mode: "status"`.
|
|
539
510
|
- `doctor`: call `codecgc.install` with `mode: "doctor"`.
|
|
540
511
|
- `--workspace <dir>`: pass the workspace through.
|
|
541
|
-
- `--mode user-dry-run`: preview user-level files only.
|
|
542
|
-
- `--mode user`: only run if the user explicitly asks to write user-level Claude integration.
|
|
543
512
|
|
|
544
513
|
Fallback:
|
|
545
514
|
|
|
546
|
-
- If the MCP tool is unavailable, run `cgc-
|
|
515
|
+
- If the MCP tool is unavailable, run `cgc-init` with the same arguments from the target project root.
|
|
547
516
|
- After install, run or suggest `cgc-start`, `cgc-status`, and `cgc-doctor`.
|
|
548
517
|
"""
|
|
549
518
|
templates["cgc-start.md"] = """---
|
|
@@ -557,7 +526,7 @@ Default behavior:
|
|
|
557
526
|
|
|
558
527
|
- Treat this as a read-only onboarding/status entry.
|
|
559
528
|
- Summarize the project-local `codecgc/START_HERE.md` guide if present.
|
|
560
|
-
- If the guide is missing, tell the user to run `/cgc-
|
|
529
|
+
- If the guide is missing, tell the user to run `/cgc-init`.
|
|
561
530
|
- Keep the answer short and in Chinese.
|
|
562
531
|
|
|
563
532
|
Argument mapping:
|
|
@@ -568,7 +537,7 @@ Argument mapping:
|
|
|
568
537
|
Fallback:
|
|
569
538
|
|
|
570
539
|
- If the MCP tool is unavailable, run `cgc-start` from the target project root.
|
|
571
|
-
- If `cgc-start` reports missing onboarding, suggest `cgc-
|
|
540
|
+
- If `cgc-start` reports missing onboarding, suggest `cgc-init`.
|
|
572
541
|
"""
|
|
573
542
|
return templates
|
|
574
543
|
|
|
@@ -752,15 +721,15 @@ def settings_have_allowed_tools(settings: dict[str, Any], allow_rules: list[str]
|
|
|
752
721
|
RUNTIME_MCP_SERVER_SPECS: dict[str, dict[str, Any]] = {
|
|
753
722
|
"codecgc": {
|
|
754
723
|
"module": "codecgcmcp.cli",
|
|
755
|
-
"pythonpath_suffixes": ["scripts", "codecgcmcp/src"],
|
|
724
|
+
"pythonpath_suffixes": ["scripts", "mcp/codecgcmcp/src"],
|
|
756
725
|
},
|
|
757
726
|
"codex": {
|
|
758
727
|
"module": "codexmcp.cli",
|
|
759
|
-
"pythonpath_suffixes": ["scripts", "codecgcmcp/src", "codexmcp/src"],
|
|
728
|
+
"pythonpath_suffixes": ["scripts", "mcp/codecgcmcp/src", "mcp/codexmcp/src"],
|
|
760
729
|
},
|
|
761
730
|
"gemini": {
|
|
762
731
|
"module": "geminimcp.cli",
|
|
763
|
-
"pythonpath_suffixes": ["scripts", "codecgcmcp/src", "geminimcp/src"],
|
|
732
|
+
"pythonpath_suffixes": ["scripts", "mcp/codecgcmcp/src", "mcp/geminimcp/src"],
|
|
764
733
|
},
|
|
765
734
|
}
|
|
766
735
|
|
|
@@ -918,7 +887,7 @@ def install_local_runtime(override_workspace: str = "") -> dict[str, Any]:
|
|
|
918
887
|
"Project-local model-routing.yaml was synchronized as the policy source of truth.",
|
|
919
888
|
"Project-local codecgc workflow directories were initialized.",
|
|
920
889
|
"Claude pre-edit guardrail hook was synchronized into the target workspace.",
|
|
921
|
-
"Claude project permissions were rendered from codecgc/templates/claude/settings.local.json.",
|
|
890
|
+
"Claude project permissions were rendered from codecgc/templates/project/claude/settings.local.json.",
|
|
922
891
|
"Project-local Codex policy contract was synchronized into .codex/codecgcrc.json.",
|
|
923
892
|
"Project-local Gemini policy was synchronized into .gemini/policies/codecgc-policy.toml.",
|
|
924
893
|
"Project-local Claude slash commands were synchronized into .claude/commands.",
|
|
@@ -929,120 +898,12 @@ def install_local_runtime(override_workspace: str = "") -> dict[str, Any]:
|
|
|
929
898
|
}
|
|
930
899
|
|
|
931
900
|
|
|
932
|
-
def build_user_hook_command(user_paths: dict[str, Path]) -> str:
|
|
933
|
-
package_root = str(WORKSPACE).replace("'", "''")
|
|
934
|
-
workspace_root = str(WORKSPACE).replace("'", "''")
|
|
935
|
-
hook_script = str(user_paths["hook_script"]).replace("'", "''")
|
|
936
|
-
return (
|
|
937
|
-
"powershell -ExecutionPolicy Bypass -Command "
|
|
938
|
-
f"\"$env:CODECGC_PACKAGE_ROOT='{package_root}'; "
|
|
939
|
-
f"$env:CODECGC_WORKSPACE_ROOT='{workspace_root}'; "
|
|
940
|
-
f"& '{hook_script}'\""
|
|
941
|
-
)
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
def preview_user_install(override_root: str = "") -> dict[str, Any]:
|
|
945
|
-
user_paths = get_user_claude_paths(override_root)
|
|
946
|
-
user_settings = load_json_file(user_paths["settings"])
|
|
947
|
-
merged_settings, settings_changed = merge_hook_settings(user_settings, build_user_hook_command(user_paths))
|
|
948
|
-
merged_settings, permissions_changed = merge_permission_settings(merged_settings, DEFAULT_ALLOWED_TOOLS)
|
|
949
|
-
mcp_config = build_mcp_config(WORKSPACE)
|
|
950
|
-
recommended_next_action = "cgc-install"
|
|
951
|
-
summary = build_mode_summary_payload(
|
|
952
|
-
scope="用户级 Claude 集成预演",
|
|
953
|
-
human_summary="已完成用户级 Claude 集成预演,未写入任何文件。",
|
|
954
|
-
recommended_next_action=recommended_next_action,
|
|
955
|
-
)
|
|
956
|
-
|
|
957
|
-
return {
|
|
958
|
-
"success": True,
|
|
959
|
-
"mode": "user-dry-run",
|
|
960
|
-
"workspace": str(WORKSPACE),
|
|
961
|
-
"user_claude_root": str(user_paths["root"]),
|
|
962
|
-
"planned_files": {
|
|
963
|
-
"settings_json": str(user_paths["settings"]),
|
|
964
|
-
"mcp_json": str(user_paths["mcp"]),
|
|
965
|
-
"hook_script": str(user_paths["hook_script"]),
|
|
966
|
-
"commands_dir": str(user_paths["commands_dir"]),
|
|
967
|
-
},
|
|
968
|
-
"would_write": {
|
|
969
|
-
"settings_changed": settings_changed or permissions_changed or not user_paths["settings"].exists(),
|
|
970
|
-
"mcp_changed": True,
|
|
971
|
-
"hook_changed": True,
|
|
972
|
-
"commands_changed": True,
|
|
973
|
-
},
|
|
974
|
-
"preview": {
|
|
975
|
-
"settings": sanitize_for_preview(merged_settings),
|
|
976
|
-
"mcp": mcp_config,
|
|
977
|
-
},
|
|
978
|
-
"notes": [
|
|
979
|
-
"This mode does not modify user-level Claude files.",
|
|
980
|
-
"Use this preview only when intentionally inspecting a user-level integration surface.",
|
|
981
|
-
"The preview includes MCP tool allow rules for codecgc, codex, and gemini servers.",
|
|
982
|
-
"Current CodeCGC product policy still defaults to project-local installation.",
|
|
983
|
-
],
|
|
984
|
-
"summary": summary,
|
|
985
|
-
}
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
def install_user_runtime(override_root: str = "") -> dict[str, Any]:
|
|
989
|
-
user_paths = get_user_claude_paths(override_root)
|
|
990
|
-
user_paths["root"].mkdir(parents=True, exist_ok=True)
|
|
991
|
-
user_paths["hooks_dir"].mkdir(parents=True, exist_ok=True)
|
|
992
|
-
user_paths["commands_dir"].mkdir(parents=True, exist_ok=True)
|
|
993
|
-
|
|
994
|
-
settings = load_json_file(user_paths["settings"])
|
|
995
|
-
merged_settings, settings_changed = merge_hook_settings(settings, build_user_hook_command(user_paths))
|
|
996
|
-
merged_settings, permissions_changed = merge_permission_settings(merged_settings, DEFAULT_ALLOWED_TOOLS)
|
|
997
|
-
write_json_file(user_paths["settings"], merged_settings)
|
|
998
|
-
write_json_file(user_paths["mcp"], build_mcp_config(WORKSPACE))
|
|
999
|
-
shutil.copyfile(PROJECT_HOOK_PATH, user_paths["hook_script"])
|
|
1000
|
-
written_commands = write_custom_command_files(user_paths["commands_dir"], WORKSPACE / "bin")
|
|
1001
|
-
summary = build_mode_summary_payload(
|
|
1002
|
-
scope="用户级 Claude 集成面",
|
|
1003
|
-
human_summary="用户级 Claude 集成文件已写入。",
|
|
1004
|
-
recommended_next_action="cgc-install --mode status",
|
|
1005
|
-
)
|
|
1006
|
-
|
|
1007
|
-
return {
|
|
1008
|
-
"success": True,
|
|
1009
|
-
"mode": "user",
|
|
1010
|
-
"workspace": str(WORKSPACE),
|
|
1011
|
-
"user_claude_root": str(user_paths["root"]),
|
|
1012
|
-
"written_files": {
|
|
1013
|
-
"settings_json": str(user_paths["settings"]),
|
|
1014
|
-
"mcp_json": str(user_paths["mcp"]),
|
|
1015
|
-
"hook_script": str(user_paths["hook_script"]),
|
|
1016
|
-
"commands_dir": str(user_paths["commands_dir"]),
|
|
1017
|
-
},
|
|
1018
|
-
"changes": {
|
|
1019
|
-
"settings_changed": settings_changed or permissions_changed or not user_paths["settings"].exists(),
|
|
1020
|
-
"mcp_changed": True,
|
|
1021
|
-
"hook_changed": True,
|
|
1022
|
-
"commands_changed": True,
|
|
1023
|
-
},
|
|
1024
|
-
"command_files": written_commands,
|
|
1025
|
-
"notes": [
|
|
1026
|
-
"User-level Claude integration files were written to the selected root.",
|
|
1027
|
-
"The user-level hook script was copied from the project hook source.",
|
|
1028
|
-
"MCP tool allow rules were merged into ~/.claude/settings.json.",
|
|
1029
|
-
"User-level Claude slash commands were written to ~/.claude/commands.",
|
|
1030
|
-
"This mode is explicit and should be used only when a broader Claude integration surface is intended.",
|
|
1031
|
-
],
|
|
1032
|
-
"summary": summary,
|
|
1033
|
-
}
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
901
|
def build_workspace_install_command(workspace_root: Path) -> str:
|
|
1037
|
-
return f"cgc-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
def build_user_preview_command(user_root: Path) -> str:
|
|
1041
|
-
return f"cgc-install --mode user-dry-run --user-root {shell_quote(str(user_root))}"
|
|
902
|
+
return f"cgc-init --mode local --workspace {shell_quote(str(workspace_root))}"
|
|
1042
903
|
|
|
1043
904
|
|
|
1044
905
|
def build_doctor_fix_command(workspace_root: Path) -> str:
|
|
1045
|
-
return f"cgc-
|
|
906
|
+
return f"cgc-init --workspace {shell_quote(str(workspace_root))}"
|
|
1046
907
|
|
|
1047
908
|
|
|
1048
909
|
def build_install_mode_summary(result: dict[str, Any]) -> str:
|
|
@@ -1061,7 +922,7 @@ def build_install_mode_summary(result: dict[str, Any]) -> str:
|
|
|
1061
922
|
f"- Hook 脚本: {result.get('hook_script', '')}",
|
|
1062
923
|
f"- Slash Commands: {result.get('commands_dir', '')}",
|
|
1063
924
|
f"- 新手入口: {result.get('onboarding_file', '')}",
|
|
1064
|
-
"- 说明: 可选外部能力如 MemOS 不由 cgc-
|
|
925
|
+
"- 说明: 可选外部能力如 MemOS 不由 cgc-init 自动写入;如需启用,请在 Claude 中单独配置官方 MCP。",
|
|
1065
926
|
]
|
|
1066
927
|
next_actions = [
|
|
1067
928
|
"cgc-start",
|
|
@@ -1070,45 +931,6 @@ def build_install_mode_summary(result: dict[str, Any]) -> str:
|
|
|
1070
931
|
]
|
|
1071
932
|
return render_summary_block("CodeCGC 安装", lines, next_actions)
|
|
1072
933
|
|
|
1073
|
-
if mode == "user-dry-run":
|
|
1074
|
-
planned = result.get("planned_files", {}) if isinstance(result.get("planned_files"), dict) else {}
|
|
1075
|
-
lines = [
|
|
1076
|
-
f"- 工作区: {result.get('workspace', '')}",
|
|
1077
|
-
f"- 用户 Claude 根目录: {result.get('user_claude_root', '')}",
|
|
1078
|
-
"- 范围: 用户级 Claude 集成预演",
|
|
1079
|
-
"- 摘要: 已完成用户级 Claude 集成预演,未写入任何文件。",
|
|
1080
|
-
f"- 预演 Settings: {planned.get('settings_json', '')}",
|
|
1081
|
-
f"- 预演 MCP: {planned.get('mcp_json', '')}",
|
|
1082
|
-
f"- 预演 Hook: {planned.get('hook_script', '')}",
|
|
1083
|
-
f"- 预演 Slash Commands: {planned.get('commands_dir', '')}",
|
|
1084
|
-
"- 说明: 该预演只覆盖 CodeCGC 必需执行器;MemOS 等可选外部能力仍建议在 Claude 中独立配置。",
|
|
1085
|
-
]
|
|
1086
|
-
next_actions = []
|
|
1087
|
-
user_root = str(result.get("user_claude_root", "")).strip()
|
|
1088
|
-
if user_root:
|
|
1089
|
-
next_actions.append("cgc-install")
|
|
1090
|
-
next_actions.append("cgc-install --mode status")
|
|
1091
|
-
return render_summary_block("CodeCGC 用户级预演", lines, next_actions)
|
|
1092
|
-
|
|
1093
|
-
if mode == "user":
|
|
1094
|
-
written = result.get("written_files", {}) if isinstance(result.get("written_files"), dict) else {}
|
|
1095
|
-
lines = [
|
|
1096
|
-
f"- 工作区: {result.get('workspace', '')}",
|
|
1097
|
-
f"- 用户 Claude 根目录: {result.get('user_claude_root', '')}",
|
|
1098
|
-
"- 范围: 用户级 Claude 集成面",
|
|
1099
|
-
"- 摘要: 用户级 Claude 集成文件已写入。",
|
|
1100
|
-
f"- Settings: {written.get('settings_json', '')}",
|
|
1101
|
-
f"- MCP: {written.get('mcp_json', '')}",
|
|
1102
|
-
f"- Hook 脚本: {written.get('hook_script', '')}",
|
|
1103
|
-
f"- Slash Commands: {written.get('commands_dir', '')}",
|
|
1104
|
-
"- 说明: 该安装只写入 CodeCGC 必需执行器;MemOS 等可选外部能力仍需在 Claude 中单独配置。",
|
|
1105
|
-
]
|
|
1106
|
-
next_actions = [
|
|
1107
|
-
"cgc-install --mode status",
|
|
1108
|
-
"cgc-doctor",
|
|
1109
|
-
]
|
|
1110
|
-
return render_summary_block("CodeCGC 用户级安装", lines, next_actions)
|
|
1111
|
-
|
|
1112
934
|
return ""
|
|
1113
935
|
|
|
1114
936
|
|
|
@@ -1202,88 +1024,22 @@ def collect_project_status(workspace_paths: dict[str, Path]) -> dict[str, Any]:
|
|
|
1202
1024
|
}
|
|
1203
1025
|
|
|
1204
1026
|
|
|
1205
|
-
def collect_user_status(user_paths: dict[str, Path]) -> dict[str, Any]:
|
|
1206
|
-
expected_mcp = build_mcp_config(WORKSPACE)
|
|
1207
|
-
expected_hook_command = build_user_hook_command(user_paths)
|
|
1208
|
-
expected_hook_text = load_text_file(PROJECT_HOOK_PATH)
|
|
1209
|
-
current_settings = load_json_file(user_paths["settings"])
|
|
1210
|
-
current_mcp = load_json_file(user_paths["mcp"])
|
|
1211
|
-
current_hook_text = load_text_file(user_paths["hook_script"])
|
|
1212
|
-
|
|
1213
|
-
hook_registered = settings_have_hook_command(current_settings, expected_hook_command)
|
|
1214
|
-
permissions_registered = settings_have_allowed_tools(current_settings, DEFAULT_ALLOWED_TOOLS)
|
|
1215
|
-
mcp_matches_exact = current_mcp == expected_mcp if user_paths["mcp"].exists() else False
|
|
1216
|
-
mcp_matches_runtime = mcp_config_matches_runtime_shape(current_mcp) if user_paths["mcp"].exists() else False
|
|
1217
|
-
mcp_matches = mcp_matches_exact or mcp_matches_runtime
|
|
1218
|
-
hook_file_matches = current_hook_text == expected_hook_text if user_paths["hook_script"].exists() else False
|
|
1219
|
-
|
|
1220
|
-
missing = []
|
|
1221
|
-
if not mcp_matches:
|
|
1222
|
-
missing.append("mcp_json")
|
|
1223
|
-
if not hook_registered:
|
|
1224
|
-
missing.append("claude_settings_hook")
|
|
1225
|
-
if not permissions_registered:
|
|
1226
|
-
missing.append("claude_settings_permissions")
|
|
1227
|
-
if not hook_file_matches:
|
|
1228
|
-
missing.append("hook_script")
|
|
1229
|
-
|
|
1230
|
-
ready = not missing
|
|
1231
|
-
return {
|
|
1232
|
-
"root": str(user_paths["root"]),
|
|
1233
|
-
"settings_json": str(user_paths["settings"]),
|
|
1234
|
-
"mcp_json": str(user_paths["mcp"]),
|
|
1235
|
-
"hook_script": str(user_paths["hook_script"]),
|
|
1236
|
-
"settings_exists": user_paths["settings"].exists(),
|
|
1237
|
-
"mcp_exists": user_paths["mcp"].exists(),
|
|
1238
|
-
"hook_exists": user_paths["hook_script"].exists(),
|
|
1239
|
-
"mcp_matches_expected": mcp_matches,
|
|
1240
|
-
"mcp_matches_expected_exact": mcp_matches_exact,
|
|
1241
|
-
"mcp_matches_runtime_shape": mcp_matches_runtime,
|
|
1242
|
-
"hook_registered": hook_registered,
|
|
1243
|
-
"permissions_registered": permissions_registered,
|
|
1244
|
-
"hook_file_matches_expected": hook_file_matches,
|
|
1245
|
-
"ready": ready,
|
|
1246
|
-
"missing_or_outdated": missing,
|
|
1247
|
-
"recommended_command": "" if ready else build_user_preview_command(user_paths["root"]),
|
|
1248
|
-
}
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
1027
|
def collect_install_status(override_workspace: str = "") -> dict[str, Any]:
|
|
1252
1028
|
workspace_paths = get_workspace_paths(override_workspace)
|
|
1253
|
-
user_paths = get_user_claude_paths()
|
|
1254
1029
|
project_status = collect_project_status(workspace_paths)
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
elif not user_status["ready"]:
|
|
1261
|
-
human_summary = "项目级集成已就绪;用户级 Claude 集成仍是可选项,当前尚未就绪。"
|
|
1030
|
+
human_summary = (
|
|
1031
|
+
"项目级 CodeCGC 集成已就绪。"
|
|
1032
|
+
if project_status["ready"]
|
|
1033
|
+
else "项目级 CodeCGC 集成尚未就绪。"
|
|
1034
|
+
)
|
|
1262
1035
|
status_summary = {
|
|
1263
1036
|
"project_ready": project_status["ready"],
|
|
1264
|
-
"user_ready": user_status["ready"],
|
|
1265
1037
|
"default_policy": "project-local-first",
|
|
1266
|
-
"recommended_next_command":
|
|
1267
|
-
"recommended_project_command": project_status["recommended_command"],
|
|
1268
|
-
"recommended_user_command": user_status["recommended_command"],
|
|
1038
|
+
"recommended_next_command": project_status["recommended_command"],
|
|
1269
1039
|
"human_summary": human_summary,
|
|
1270
|
-
"scope": "
|
|
1040
|
+
"scope": "project-local integration status",
|
|
1271
1041
|
}
|
|
1272
1042
|
|
|
1273
|
-
status_summary.update(
|
|
1274
|
-
{
|
|
1275
|
-
"default_policy": "project-local-first",
|
|
1276
|
-
"recommended_next_command": project_status["recommended_command"],
|
|
1277
|
-
"recommended_user_command": "",
|
|
1278
|
-
"human_summary": (
|
|
1279
|
-
"Project-local CodeCGC integration is ready."
|
|
1280
|
-
if project_status["ready"]
|
|
1281
|
-
else "Project-local CodeCGC integration is missing or outdated."
|
|
1282
|
-
),
|
|
1283
|
-
"scope": "project-local integration status; user-level config is optional preview only",
|
|
1284
|
-
}
|
|
1285
|
-
)
|
|
1286
|
-
|
|
1287
1043
|
return {
|
|
1288
1044
|
"success": True,
|
|
1289
1045
|
"mode": "status",
|
|
@@ -1291,7 +1047,6 @@ def collect_install_status(override_workspace: str = "") -> dict[str, Any]:
|
|
|
1291
1047
|
"summary": status_summary,
|
|
1292
1048
|
"status_summary": status_summary,
|
|
1293
1049
|
"project": project_status,
|
|
1294
|
-
"user_preview_targets": user_status,
|
|
1295
1050
|
}
|
|
1296
1051
|
|
|
1297
1052
|
|
|
@@ -1316,7 +1071,7 @@ def collect_start_status(override_workspace: str = "") -> dict[str, Any]:
|
|
|
1316
1071
|
"cgc \"你的需求\"",
|
|
1317
1072
|
]
|
|
1318
1073
|
if not onboarding_ready:
|
|
1319
|
-
quick_actions = ["/cgc-
|
|
1074
|
+
quick_actions = ["/cgc-init", build_workspace_install_command(workspace_paths["root"])]
|
|
1320
1075
|
|
|
1321
1076
|
return {
|
|
1322
1077
|
"success": True,
|
|
@@ -1388,9 +1143,9 @@ def build_pip_install_command(python_command: str, requirement: str) -> str:
|
|
|
1388
1143
|
|
|
1389
1144
|
def build_local_editable_install_command(python_command: str) -> str:
|
|
1390
1145
|
runtime_command = python_command.strip() or sys.executable
|
|
1391
|
-
codecgcmcp_path = WORKSPACE / "codecgcmcp"
|
|
1392
|
-
codexmcp_path = WORKSPACE / "codexmcp"
|
|
1393
|
-
geminimcp_path = WORKSPACE / "geminimcp"
|
|
1146
|
+
codecgcmcp_path = WORKSPACE / "mcp" / "codecgcmcp"
|
|
1147
|
+
codexmcp_path = WORKSPACE / "mcp" / "codexmcp"
|
|
1148
|
+
geminimcp_path = WORKSPACE / "mcp" / "geminimcp"
|
|
1394
1149
|
if not (codecgcmcp_path / "pyproject.toml").exists():
|
|
1395
1150
|
return ""
|
|
1396
1151
|
if not (codexmcp_path / "pyproject.toml").exists():
|
|
@@ -1642,9 +1397,9 @@ def collect_doctor_status(override_workspace: str = "") -> dict[str, Any]:
|
|
|
1642
1397
|
combined_pythonpath = os.pathsep.join(
|
|
1643
1398
|
[
|
|
1644
1399
|
str(WORKSPACE / "scripts"),
|
|
1645
|
-
str(WORKSPACE / "codecgcmcp" / "src"),
|
|
1646
|
-
str(WORKSPACE / "codexmcp" / "src"),
|
|
1647
|
-
str(WORKSPACE / "geminimcp" / "src"),
|
|
1400
|
+
str(WORKSPACE / "mcp" / "codecgcmcp" / "src"),
|
|
1401
|
+
str(WORKSPACE / "mcp" / "codexmcp" / "src"),
|
|
1402
|
+
str(WORKSPACE / "mcp" / "geminimcp" / "src"),
|
|
1648
1403
|
]
|
|
1649
1404
|
)
|
|
1650
1405
|
existing_pythonpath = runtime_env.get("PYTHONPATH", "").strip()
|
|
@@ -1712,7 +1467,7 @@ def collect_doctor_status(override_workspace: str = "") -> dict[str, Any]:
|
|
|
1712
1467
|
|
|
1713
1468
|
def build_parser() -> argparse.ArgumentParser:
|
|
1714
1469
|
parser = argparse.ArgumentParser(description="Install or inspect CodeCGC integration surfaces.")
|
|
1715
|
-
parser.add_argument("--mode", choices=["local", "
|
|
1470
|
+
parser.add_argument("--mode", choices=["local", "status", "doctor", "start"], default="local")
|
|
1716
1471
|
parser.add_argument(
|
|
1717
1472
|
"--format",
|
|
1718
1473
|
choices=["json", "summary"],
|
|
@@ -1724,7 +1479,6 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
1724
1479
|
default="",
|
|
1725
1480
|
help="Optional target workspace root for local/status modes. Defaults to the current CodeCGC repository root.",
|
|
1726
1481
|
)
|
|
1727
|
-
parser.add_argument("--user-root", default="", help="Optional explicit Claude user root for user/user-dry-run modes.")
|
|
1728
1482
|
return parser
|
|
1729
1483
|
|
|
1730
1484
|
|
|
@@ -1734,10 +1488,6 @@ def main() -> int:
|
|
|
1734
1488
|
|
|
1735
1489
|
if args.mode == "local":
|
|
1736
1490
|
result = install_local_runtime(args.workspace)
|
|
1737
|
-
elif args.mode == "user-dry-run":
|
|
1738
|
-
result = preview_user_install(args.user_root)
|
|
1739
|
-
elif args.mode == "user":
|
|
1740
|
-
result = install_user_runtime(args.user_root)
|
|
1741
1491
|
elif args.mode == "status":
|
|
1742
1492
|
result = collect_install_status(args.workspace)
|
|
1743
1493
|
elif args.mode == "doctor":
|
|
@@ -1767,22 +1517,17 @@ def main() -> int:
|
|
|
1767
1517
|
if args.mode == "status" and args.format == "summary":
|
|
1768
1518
|
summary = result.get("summary", {}) if isinstance(result.get("summary"), dict) else {}
|
|
1769
1519
|
project = result.get("project", {}) if isinstance(result.get("project"), dict) else {}
|
|
1770
|
-
user = result.get("user_preview_targets", {}) if isinstance(result.get("user_preview_targets"), dict) else {}
|
|
1771
1520
|
lines = [
|
|
1772
1521
|
f"- 工作区: {result.get('workspace', '')}",
|
|
1773
1522
|
f"- 范围: {summary.get('scope', '')}",
|
|
1774
1523
|
f"- 项目级就绪: {format_bool_zh(summary.get('project_ready'))}",
|
|
1775
|
-
f"- 用户级就绪: {format_bool_zh(summary.get('user_ready'))}",
|
|
1776
1524
|
f"- 策略: {summary.get('default_policy', '')}",
|
|
1777
1525
|
f"- 摘要: {summary.get('human_summary', '')}",
|
|
1778
1526
|
f"- 项目级缺失项: {format_list_zh(project.get('missing_or_outdated', []))}",
|
|
1779
1527
|
f"- 新手入口: {project.get('onboarding_file_path', '')}",
|
|
1780
|
-
f"- 用户级缺失项: {format_list_zh(user.get('missing_or_outdated', []))}",
|
|
1781
1528
|
]
|
|
1782
|
-
recommended_project = str(summary.get("recommended_project_command", "")).strip()
|
|
1783
|
-
recommended_user = str(summary.get("recommended_user_command", "")).strip()
|
|
1784
1529
|
recommended_next = str(summary.get("recommended_next_command", "")).strip()
|
|
1785
|
-
next_actions = [
|
|
1530
|
+
next_actions = [recommended_next] if recommended_next else []
|
|
1786
1531
|
print(render_summary_block("CodeCGC 安装状态", lines, next_actions))
|
|
1787
1532
|
return 0 if result.get("success") else 1
|
|
1788
1533
|
|
|
@@ -1816,7 +1561,7 @@ def main() -> int:
|
|
|
1816
1561
|
print(render_summary_block("CodeCGC 自检", lines, next_actions))
|
|
1817
1562
|
return 0 if result.get("success") else 1
|
|
1818
1563
|
|
|
1819
|
-
if args.format == "summary" and args.mode
|
|
1564
|
+
if args.format == "summary" and args.mode == "local":
|
|
1820
1565
|
print(build_install_mode_summary(result))
|
|
1821
1566
|
return 0 if result.get("success") else 1
|
|
1822
1567
|
|
|
@@ -18,7 +18,7 @@ function main() {
|
|
|
18
18
|
|
|
19
19
|
console.warn("[codecgc] Global CLI installed.");
|
|
20
20
|
console.warn("[codecgc] CodeCGC no longer writes Claude user-level files during npm install.");
|
|
21
|
-
console.warn("[codecgc] Run `cgc-
|
|
21
|
+
console.warn("[codecgc] Run `cgc-init` from each target project to create project-local .mcp.json, .claude/, and model-routing.yaml.");
|
|
22
22
|
return 0;
|
|
23
23
|
}
|
|
24
24
|
|