From 9347a1a75c38d1f0da22a396d756019efc7d2d08 Mon Sep 17 00:00:00 2001 From: gaoguobin Date: Wed, 6 May 2026 10:15:25 +0800 Subject: [PATCH 1/2] fix: use /reload-plugins instead of restart in Claude Code docs Claude Code supports hot-reloading via /reload-plugins, unlike Codex which requires a full restart. The original instructions carried over the Codex restart requirement by mistake. --- integrations/claude-code/INSTALL.md | 2 +- integrations/claude-code/UNINSTALL.md | 2 +- integrations/claude-code/UPDATE.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/integrations/claude-code/INSTALL.md b/integrations/claude-code/INSTALL.md index fd4c56f..489f8e4 100644 --- a/integrations/claude-code/INSTALL.md +++ b/integrations/claude-code/INSTALL.md @@ -71,7 +71,7 @@ python ~/.codex/codex-eide-rebuild/runtime/python/eide_rebuild.py doctor ``` Report the JSON result in the reply. -When the JSON contains `"ok": true`, tell the user to restart Claude Code so it picks up the new command and agent. +When the JSON contains `"ok": true`, tell the user to run `/reload-plugins` so Claude Code picks up the new command and agent. ## After install diff --git a/integrations/claude-code/UNINSTALL.md b/integrations/claude-code/UNINSTALL.md index dd733ec..6184ef9 100644 --- a/integrations/claude-code/UNINSTALL.md +++ b/integrations/claude-code/UNINSTALL.md @@ -38,4 +38,4 @@ If the Codex junction exists, warn the user that removing the repo will also bre ### 3. Done -Tell the user to restart Claude Code so the removed command and agent are no longer loaded. +Tell the user to run `/reload-plugins` so the removed command and agent are no longer loaded. diff --git a/integrations/claude-code/UPDATE.md b/integrations/claude-code/UPDATE.md index 3756db2..edfa6d9 100644 --- a/integrations/claude-code/UPDATE.md +++ b/integrations/claude-code/UPDATE.md @@ -37,4 +37,4 @@ python ~/.codex/codex-eide-rebuild/runtime/python/eide_rebuild.py doctor ``` Report the JSON result in the reply. -When the JSON contains `"ok": true`, tell the user to restart Claude Code so it picks up the updated templates. +When the JSON contains `"ok": true`, tell the user to run `/reload-plugins` so Claude Code picks up the updated templates. From 480b272e20343fe100c188ed0e0355032176dc74 Mon Sep 17 00:00:00 2001 From: gaoguobin Date: Wed, 6 May 2026 10:23:34 +0800 Subject: [PATCH 2/2] fix: align claude reload docs and test isolation --- README.md | 2 +- README.zh-CN.md | 2 +- runtime/python/eide_rebuild/tools.py | 8 +++----- runtime/tests/test_codex_install_docs.py | 15 +++++++++++++++ runtime/tests/test_skill_bundle_sync.py | 4 ++-- scripts/sync_skill_runtime.py | 5 +++-- skills/eide-rebuild/scripts/eide_rebuild/tools.py | 8 +++----- 7 files changed, 28 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index c9a6d7a..5ef5e93 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Fetch and follow instructions from https://raw.githubusercontent.com/gaoguobin/c Fetch and follow instructions from https://raw.githubusercontent.com/gaoguobin/codex-eide-rebuild/main/integrations/claude-code/INSTALL.md ``` -The agent follows the install doc, runs `doctor`, and reports the JSON result. Restart the agent after `doctor.ok=true`. +The agent follows the install doc, runs `doctor`, and reports the JSON result. After `doctor.ok=true`, restart Codex or run `/reload-plugins` in Claude Code. ## Update diff --git a/README.zh-CN.md b/README.zh-CN.md index 68a7121..1adc25c 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -16,7 +16,7 @@ Fetch and follow instructions from https://raw.githubusercontent.com/gaoguobin/c Fetch and follow instructions from https://raw.githubusercontent.com/gaoguobin/codex-eide-rebuild/main/integrations/claude-code/INSTALL.md ``` -Agent 会按安装文档完成安装、运行 `doctor`、回报 JSON 结果。`doctor.ok=true` 之后重启 Agent。 +Agent 会按安装文档完成安装、运行 `doctor`、回报 JSON 结果。`doctor.ok=true` 之后,Codex 需要重启,Claude Code 运行 `/reload-plugins`。 ## 升级 diff --git a/runtime/python/eide_rebuild/tools.py b/runtime/python/eide_rebuild/tools.py index bd12f12..3cbf37a 100644 --- a/runtime/python/eide_rebuild/tools.py +++ b/runtime/python/eide_rebuild/tools.py @@ -105,15 +105,13 @@ def _preferred_candidate(candidates: list[Path]) -> Path: def _extension_roots() -> list[Path]: - roots: list[Path] = [] override = os.environ.get("EIDE_REBUILD_VSCODE_EXTENSIONS_ROOT") if override: - roots.append(Path(override)) + return _iter_existing_dirs([Path(override)]) home_override = os.environ.get("EIDE_REBUILD_HOME") if home_override: - roots.append(Path(home_override) / ".vscode" / "extensions") - roots.append(Path.home() / ".vscode" / "extensions") - return _iter_existing_dirs(roots) + return _iter_existing_dirs([Path(home_override) / ".vscode" / "extensions"]) + return _iter_existing_dirs([Path.home() / ".vscode" / "extensions"]) def find_eide_extension_dir() -> str: diff --git a/runtime/tests/test_codex_install_docs.py b/runtime/tests/test_codex_install_docs.py index 4c67910..b5d81dd 100644 --- a/runtime/tests/test_codex_install_docs.py +++ b/runtime/tests/test_codex_install_docs.py @@ -77,6 +77,14 @@ def test_readmes_use_block_lifecycle_prompts(self) -> None: content = readme.read_text(encoding="utf-8") self.assertNotIn("`Fetch and follow instructions from", content) + def test_readmes_name_codex_restart_and_claude_reload(self) -> None: + english = README_EN.read_text(encoding="utf-8") + chinese = README_ZH.read_text(encoding="utf-8") + self.assertIn("restart Codex", english) + self.assertIn("`/reload-plugins` in Claude Code", english) + self.assertIn("Codex 需要重启", chinese) + self.assertIn("Claude Code 运行 `/reload-plugins`", chinese) + def test_claude_code_lifecycle_docs_use_consistent_prompt_format(self) -> None: for doc in (CC_INSTALL_DOC, CC_UPDATE_DOC, CC_UNINSTALL_DOC): with self.subTest(doc=doc.name): @@ -84,6 +92,13 @@ def test_claude_code_lifecycle_docs_use_consistent_prompt_format(self) -> None: self.assertIn("## One-paste prompt for engineers", content) self.assertIn("Paste this into Claude Code:", content) + def test_claude_code_lifecycle_docs_use_reload_plugins(self) -> None: + for doc in (CC_INSTALL_DOC, CC_UPDATE_DOC, CC_UNINSTALL_DOC): + with self.subTest(doc=doc.name): + content = doc.read_text(encoding="utf-8") + self.assertIn("/reload-plugins", content) + self.assertNotIn("restart Claude Code", content) + def test_chinese_readme_keeps_core_sections_in_sync(self) -> None: content = README_ZH.read_text(encoding="utf-8") for heading in ( diff --git a/runtime/tests/test_skill_bundle_sync.py b/runtime/tests/test_skill_bundle_sync.py index e790929..5653019 100644 --- a/runtime/tests/test_skill_bundle_sync.py +++ b/runtime/tests/test_skill_bundle_sync.py @@ -20,7 +20,7 @@ def _collect_files(root: Path) -> dict[str, bytes]: return { str(path.relative_to(root)).replace("\\", "/"): path.read_bytes() for path in sorted(root.rglob("*")) - if path.is_file() + if path.is_file() and "__pycache__" not in path.parts and path.suffix not in {".pyc", ".pyo"} } @@ -69,7 +69,7 @@ def test_sync_copy_preserves_existing_package_when_staging_fails(self) -> None: (package_target / "module.py").write_text("old package\n", encoding="utf-8") legacy_vsix.write_text("legacy\n", encoding="utf-8") - def failing_copytree(source, target): + def failing_copytree(source, target, **kwargs): raise OSError("copy failed") with ( diff --git a/scripts/sync_skill_runtime.py b/scripts/sync_skill_runtime.py index 120e9b3..b056158 100644 --- a/scripts/sync_skill_runtime.py +++ b/scripts/sync_skill_runtime.py @@ -17,6 +17,7 @@ PACKAGE_SOURCE = REPO_ROOT / "runtime" / "python" / "eide_rebuild" PACKAGE_TARGET = REPO_ROOT / "skills" / "eide-rebuild" / "scripts" / "eide_rebuild" LEGACY_VSIX_TARGET = REPO_ROOT / "skills" / "eide-rebuild" / "assets" / "eide-rebuild.cli-bridge-0.1.0.vsix" +GENERATED_PYTHON_PATTERNS = ("__pycache__", "*.pyc", "*.pyo") # --- Helpers --- @@ -35,7 +36,7 @@ def collect(root: Path) -> dict[str, bytes]: return { str(path.relative_to(root)).replace("\\", "/"): path.read_bytes() for path in sorted(root.rglob("*")) - if path.is_file() + if path.is_file() and "__pycache__" not in path.parts and path.suffix not in {".pyc", ".pyo"} } return collect(left_root) == collect(right_root) @@ -67,7 +68,7 @@ def _stage_tree_copy(source: Path, target: Path) -> Path: target.parent.mkdir(parents=True, exist_ok=True) staged = _temp_sibling(target, ".tmp") try: - shutil.copytree(source, staged) + shutil.copytree(source, staged, ignore=shutil.ignore_patterns(*GENERATED_PYTHON_PATTERNS)) return staged except Exception: if staged.exists(): diff --git a/skills/eide-rebuild/scripts/eide_rebuild/tools.py b/skills/eide-rebuild/scripts/eide_rebuild/tools.py index bd12f12..3cbf37a 100644 --- a/skills/eide-rebuild/scripts/eide_rebuild/tools.py +++ b/skills/eide-rebuild/scripts/eide_rebuild/tools.py @@ -105,15 +105,13 @@ def _preferred_candidate(candidates: list[Path]) -> Path: def _extension_roots() -> list[Path]: - roots: list[Path] = [] override = os.environ.get("EIDE_REBUILD_VSCODE_EXTENSIONS_ROOT") if override: - roots.append(Path(override)) + return _iter_existing_dirs([Path(override)]) home_override = os.environ.get("EIDE_REBUILD_HOME") if home_override: - roots.append(Path(home_override) / ".vscode" / "extensions") - roots.append(Path.home() / ".vscode" / "extensions") - return _iter_existing_dirs(roots) + return _iter_existing_dirs([Path(home_override) / ".vscode" / "extensions"]) + return _iter_existing_dirs([Path.home() / ".vscode" / "extensions"]) def find_eide_extension_dir() -> str: