Code Support Agent¶
Delegate coding work to Claude Code and Codex — the two coding CLIs —
from inside a LazyBridge agent, then let them collaborate.
lazytools.connectors.code_support gives each CLI two integration modes and a
collaboration pipeline that combines them.
| Agent | CLI mode | MCP mode | Guide |
|---|---|---|---|
| Claude Code | claude_code |
claude_code_mcp |
Claude Code |
| Codex | codex |
codex_mcp |
Codex |
| Collaboration | — | — | Collaboration (build_cli_collaboration) |
Status & install
Status: alpha. The CLI-mode tools (claude_code, codex,
build_cli_collaboration) are stdlib-only (subprocess, json, shutil):
claude_code_mcp / codex_mcp) additionally
need the mcp extra:
The package is lazytoolkit (PyPI); the import root is lazytools. The two
CLIs are not Python packages — install them separately and make sure
claude / codex are on PATH:
- Claude Code — https://docs.anthropic.com/claude-code
- Codex — https://github.com/openai/codex
Two modes, one idea¶
Both agents run as subprocesses — not Python libraries, not HTTP APIs. What differs is the relationship between your agent and the CLI:
CLI mode (claude_code, codex) |
MCP mode (claude_code_mcp, codex_mcp) |
|
|---|---|---|
| Relationship | the CLI is the agent | the CLI exposes a tool surface; your agent orchestrates it |
| One call | a whole delegated task → result string | one MCP tool invocation |
| Built on | subprocess.run (stdlib) |
the MCP connector — needs [mcp] |
| Use when | you want to delegate a task | you want the CLI's primitives inside your own loop |
Pick CLI mode to hand off "do this task and tell me the result". Pick MCP mode
when you want your own agent to drive the CLI's individual tools (Claude's
Read/Edit/Bash, or Codex's codex/codex-reply) step by step.
At a glance¶
from lazybridge import Agent, LLMEngine
from lazytools.connectors.code_support import claude_code_mcp
# allow= is REQUIRED (deny-by-default). Patterns match the namespaced name.
reader = claude_code_mcp(allow=["claude_code.Read", "claude_code.Glob"])
agent = Agent(engine=LLMEngine("claude-opus-4-8"), tools=[reader])
Startup check¶
from lazytools.connectors.code_support import check_clis_available
check_clis_available() # {"claude": True, "codex": False}
shutil.which for both CLIs — call it at startup to fail fast on a missing CLI
instead of discovering it at the first tool call.
Timeouts — set tool_timeout=None¶
LLMEngine's tool_timeout wraps each tool call in asyncio.wait_for. But the
CLI-mode functions run subprocess.run(...) in a thread pool, and cancelling
the coroutine does not interrupt that thread — the subprocess keeps running
(orphaned) until its own timeout fires. So let the subprocess own the
deadline:
If you do want an engine-level ceiling, set tool_timeout strictly greater
than the per-call timeout (e.g. tool_timeout=320 with timeout=300).
Security & safety¶
- Read is the default. CLI-mode tools default to
mode="read"(Claude:Read,Bash,Grep,Glob; Codex:-s read-only). Opt into writes explicitly. - MCP mode is deny-by-default.
claude_code_mcp/codex_mcprequire anallow=/deny=filter, exactly likeMCP.stdio— and Claude Code's MCP server has no per-call confirmation of its own, so the allow-list is your primary control. - Secrets stay with the CLIs. Auth is owned by each CLI's own login
(
~/.claude/.credentials.json/ANTHROPIC_API_KEYfor Claude,codex loginfor Codex), inherited via the environment; the connector never reads, rewrites, or echoes tokens. - Errors are returned, not raised (CLI mode). Missing CLI, non-zero exit, and
timeouts come back as
"[claude_code] …"/"[codex] …"strings so the model can recover instead of crashing the run.
See also¶
- Claude Code — CLI + MCP modes, full reference.
- Codex — CLI + MCP modes, full reference.
- Collaboration — the two agents working together.
- Tools overview — every connector at a glance.
- MCP — the connector the MCP mode is built on.
- Safety — gating dangerous tools.