Repository navigation
Conversation
get_llm_provider() now builds a fallback chain: `codex exec --yolo`, then `claude -p --dangerously-skip-permissions`, then the configured API provider. CLIs missing from PATH are skipped. A CLI that exits non-zero, times out, or reports an error (auth, no credits) is disabled for the rest of the process so later stages don't wait on it again. Both CLIs use native JSON-schema output for the structured summary and run in a fresh temp dir so repo AGENTS.md/CLAUDE.md never reach the prompt. Configurable via LLM_CLI_PROVIDERS (order, or "none"), LLM_CLI_TIMEOUT, LLM_CODEX_MODEL and LLM_CLAUDE_MODEL. LLM_API_KEY is now optional when a CLI is available. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude now runs with --setting-sources "" and --disable-slash-commands,
so user rules, CLAUDE.md and skills no longer reach the model. Codex runs
with mcp_servers={} so the prompt can't be sent to the user's MCP servers.
Codex still loads the global ~/.codex/AGENTS.md and ~/.agents/skills, which
have no supported switch; that limitation is documented.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…broken API config - Run each CLI as a new process group and SIGKILL the group on timeout and after exit, so agent-spawned commands can't outlive the call. Capture output via temp files so a backgrounded child holding stdout can't stall a finished call until the timeout. - Always wrap CLIs in FallbackProvider, even a lone one with no API key, so an unavailable CLI is disabled after its first failure instead of retried by every structured/text stage of every summary. - When a CLI is available, log and drop an API provider that fails to initialize (missing SDK, missing base URL) instead of raising before any CLI is tried. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`--config mcp_servers={}` is merged into the loaded config, so every
configured MCP server stayed enabled for explainer runs. Codex now lists the
configured servers once (`codex mcp list --json`) and passes
`mcp_servers.<name>.enabled=false` for each, plus `--disable apps` and
`--disable plugins`. If the list can't be read, or a name can't be addressed
by codex's `-c` dotted-path parser, Codex fails closed as unavailable.
Adds a regression test that runs the real codex CLI against a synthetic
CODEX_HOME and asserts every server reports disabled (skipped without codex).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The AI explainer now tries local agent CLIs before the metered API:
codex exec --yoloclaude -p --dangerously-skip-permissions(bypass-permissions mode)LLM_PROVIDER/LLM_API_KEYconfig, used when both CLIs fail (no credits, auth, timeout) or aren't installedHow it works
utils/llm/cli_provider.pyaddsCodexCLIProviderandClaudeCLIProvider.--output-schemafor Codex,--json-schemafor Claude (which returnsstructured_output). Therisk_tagenum is enforced the same way as on the API path.--ephemeral/--no-session-persistence/--strict-mcp-config, so this repo's AGENTS.md/CLAUDE.md and MCP servers never reach the analysis.<system_instructions>block. Claude gets it via--system-prompt-file.utils/llm/fallback.pyaddsFallbackProvider, which tries providers in order.is_error) raise a newLLMUnavailableError. That provider is then disabled for the rest of the run, so a CLI with no credits doesn't add latency to every stage of every alert.model_namereports the provider that actually answered, so theAI summary using …log line is accurate.factory.pybuilds the chain.PATHare skipped.LLM_API_KEYis now optional when a CLI exists.New env vars:
LLM_CLI_PROVIDERS(defaultcodex,claude;noneturns the CLIs off),LLM_CLI_TIMEOUT(default 300s),LLM_CODEX_MODEL,LLM_CLAUDE_MODEL. When the model vars are unset, each CLI uses its own configured default.Context parity with the API
The CLIs get exactly the same per-transaction prompt and system prompts as the API path. Host-level agent config is stripped where the CLI supports it, verified live:
--setting-sources "" --disable-slash-commands --strict-mcp-config. No user rules, CLAUDE.md, skills or MCP servers reach the model.codex mcp list --jsonis disabled by name (--config mcp_servers.<name>.enabled=false), plus--disable apps --disable plugins.mcp_servers={}turned out to be a no-op merge. Listing failures and names the-cparser can't address fail closed: Codex is skipped. Verified live: a probe stdio server starts when enabled and doesn't when disabled. A regression test runs the real codex binary against a synthetic config. Codex has no supported switch for the global~/.codex/AGENTS.mdor~/.agents/skills, and both still load. Keep them empty for the user that runs monitoring..envsecrets.--tools ""disables tools entirely. It never asks for approval either way, so nothing hangs. Codex would need--sandbox read-onlyinstead of--yolo.deploy/systemd/monitoring.servicesetsPATH=<repo>/.venv/bin:/usr/local/bin:/usr/bin:/bin, which excludes~/.local/bin, and setsProtectHome=read-only. Both CLIs need write access to~/.codex/~/.claude.ReadWritePaths) plus a logged-in CLI on the host. I left that out because it loosens the unit's hardening.credits.py) still runs. Venice is the last-resort fallback, so it should stay funded.Test plan
uv run pytest -q tests: 1825 passed, 4 skipped. That includes the newtests/test_llm_cli.py(CLI argv/stdin/schema handling, error classification, fallback ordering/disabling, factory chain wiring). The existing factory tests now patchshutil.whichso they don't depend on installed CLIs.ruff check,ruff format --check,ty checkare clean.SUMMARY_SCHEMAand system prompts:CODEX_HOMEpointing at an empty dir (401), Codex is disabled after one failure and Claude answers both calls.LLM_CLI_PROVIDERS=codex, it falls through to Venice.🤖 Generated with Claude Code