From 321df726bc50f39a0bf8ddb2a80faa34c58d3c69 Mon Sep 17 00:00:00 2001 From: rajkumarsakthivel Date: Thu, 11 Jun 2026 14:17:26 +0100 Subject: [PATCH 1/2] fix: detect Codex via VS Code extension and show skipped agents in init Auto-detection missed Codex when users installed it via the VS Code extension but hadn't run the CLI yet (so ~/.codex didn't exist). Now also checks ~/.vscode/extensions/openai.* as a secondary signal. Added feedback line in `cce init --agent auto` showing which agents weren't detected so users know to use --agent to force setup. Closes #98 --- src/context_engine/cli.py | 8 ++++++++ src/context_engine/editors.py | 21 ++++++++++++++++++++- tests/test_editors_codex.py | 16 ++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/context_engine/cli.py b/src/context_engine/cli.py index 1e3e3ef..06c86b5 100644 --- a/src/context_engine/cli.py +++ b/src/context_engine/cli.py @@ -922,6 +922,14 @@ def init(ctx: click.Context, agent: str) -> None: section = _editor_section(editor, project_dir) click.echo(_dim(f" ~/{editor['config_path']} → [{section}]")) + # In auto mode, show which agents weren't detected so the user knows + # they can use --agent to force configuration. + if agent == "auto": + skipped = set(EDITORS.keys()) - editor_targets + if skipped: + names = ", ".join(sorted(EDITORS[k]["name"] for k in skipped)) + click.echo(_dim(f" Not detected: {names}. Use --agent to configure manually.")) + # Write instruction files for the selected editors. In `auto` mode, also # pick up instruction files whose marker exists even if the editor itself # wasn't detected (e.g. an `AGENTS.md` checked in without a `~/.codex/`). diff --git a/src/context_engine/editors.py b/src/context_engine/editors.py index 4811688..43cf415 100644 --- a/src/context_engine/editors.py +++ b/src/context_engine/editors.py @@ -235,7 +235,12 @@ def _toml_quote(s: str) -> str: def detect_editors(project_dir: Path) -> list[str]: """Return list of editor keys detected for this project. Markers are - looked up under each editor's scope root (project dir or home dir).""" + looked up under each editor's scope root (project dir or home dir). + + For Codex, also checks for the VS Code extension directory + (``~/.vscode/extensions/openai.*``) since the extension doesn't + create ``~/.codex`` until the CLI is run separately. + """ found = [] for key, editor in EDITORS.items(): root = _scope_root(editor, project_dir) @@ -243,9 +248,23 @@ def detect_editors(project_dir: Path) -> list[str]: if (root / marker).exists(): found.append(key) break + else: + # Secondary detection for Codex: VS Code extension installed + if key == "codex" and _has_vscode_codex_extension(): + found.append(key) return found +def _has_vscode_codex_extension() -> bool: + """Check if any OpenAI VS Code extension is installed by looking for + extension directories matching ``openai.*`` under ``~/.vscode/extensions``. + No subprocess needed, works cross-platform.""" + ext_dir = Path.home() / ".vscode" / "extensions" + if not ext_dir.is_dir(): + return False + return any(ext_dir.glob("openai.*")) + + def _codex_toml_block(command: str, project_dir: str, *, section: str) -> str: """Generate one TOML mcp_servers block. Section is the full dotted key rendered from the editor's section_template (e.g. `mcp_servers.cce-myapp-a3f2`). diff --git a/tests/test_editors_codex.py b/tests/test_editors_codex.py index d38785f..adbcbb5 100644 --- a/tests/test_editors_codex.py +++ b/tests/test_editors_codex.py @@ -130,6 +130,22 @@ def test_no_codex_detection_when_home_codex_absent(fake_home, project_dir): assert "codex" not in detect_editors(project_dir) +def test_detect_codex_via_vscode_extension(fake_home, project_dir): + """Codex VS Code extension installed but ~/.codex doesn't exist yet. + Detection should still fire via the extension directory.""" + ext_dir = fake_home / ".vscode" / "extensions" / "openai.openai-chatgpt-adhoc-1.0.0" + ext_dir.mkdir(parents=True) + # ~/.codex does NOT exist + assert not (fake_home / ".codex").exists() + detected = detect_editors(project_dir) + assert "codex" in detected + + +def test_no_codex_detection_without_any_signal(fake_home, project_dir): + """Neither ~/.codex nor VS Code extension present — no detection.""" + assert "codex" not in detect_editors(project_dir) + + # ── Configure: writes to ~/.codex/config.toml ──────────────────────────────── def test_configure_writes_to_user_global_codex_config(fake_home, project_dir): From a64aabc7b269002663b165f470d06a2f5a0beef6 Mon Sep 17 00:00:00 2001 From: rajkumarsakthivel Date: Mon, 15 Jun 2026 18:58:21 +0100 Subject: [PATCH 2/2] fix: address Copilot review on init feedback and codex detection - Auto-mode "Not detected" hint now only lists agents that can be forced via --agent (claude/codex/copilot), not all EDITORS keys - Rename _has_vscode_codex_extension to _has_vscode_openai_extension to match what the function actually checks (any openai.* extension) --- src/context_engine/cli.py | 9 +++++++-- src/context_engine/editors.py | 10 +++++----- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/context_engine/cli.py b/src/context_engine/cli.py index 06c86b5..d4bbefa 100644 --- a/src/context_engine/cli.py +++ b/src/context_engine/cli.py @@ -925,9 +925,14 @@ def init(ctx: click.Context, agent: str) -> None: # In auto mode, show which agents weren't detected so the user knows # they can use --agent to force configuration. if agent == "auto": - skipped = set(EDITORS.keys()) - editor_targets + # Only mention agents that can be forced via --agent + configurable_keys = set() + for _agent_name, editor_keys in _INIT_AGENT_TO_EDITORS.items(): + configurable_keys.update(editor_keys) + skipped = configurable_keys - editor_targets if skipped: - names = ", ".join(sorted(EDITORS[k]["name"] for k in skipped)) + agent_names = [a for a, keys in _INIT_AGENT_TO_EDITORS.items() if keys & skipped] + names = ", ".join(sorted(agent_names)) click.echo(_dim(f" Not detected: {names}. Use --agent to configure manually.")) # Write instruction files for the selected editors. In `auto` mode, also diff --git a/src/context_engine/editors.py b/src/context_engine/editors.py index 43cf415..8ab5e49 100644 --- a/src/context_engine/editors.py +++ b/src/context_engine/editors.py @@ -250,15 +250,15 @@ def detect_editors(project_dir: Path) -> list[str]: break else: # Secondary detection for Codex: VS Code extension installed - if key == "codex" and _has_vscode_codex_extension(): + if key == "codex" and _has_vscode_openai_extension(): found.append(key) return found -def _has_vscode_codex_extension() -> bool: - """Check if any OpenAI VS Code extension is installed by looking for - extension directories matching ``openai.*`` under ``~/.vscode/extensions``. - No subprocess needed, works cross-platform.""" +def _has_vscode_openai_extension() -> bool: + """Check if any OpenAI VS Code extension is installed (as a proxy for Codex) + by looking for extension directories matching ``openai.*`` under + ``~/.vscode/extensions``. No subprocess needed, works cross-platform.""" ext_dir = Path.home() / ".vscode" / "extensions" if not ext_dir.is_dir(): return False