codelean
v1.0.6
Published
Accurate, cost-efficient Codex-like coding agent with local preprocessing and multi-provider model routing
Maintainers
Readme
codelean
codelean is an accurate, cost-efficient Codex-like coding agent with local preprocessing and multi-provider model routing. It helps remote strong models "see less, see right, and rework less" through local model preprocessing.
Core Strategy
Accuracy first, cost second
- Prioritize code accuracy, test pass rate, and tool call success rate.
- Prefer Rust for performance-sensitive local paths, including parsing, scanning, indexing, compression, batching, bridge calls, and TUI/CLI hot paths.
- Use local models to preprocess, compress, and filter context before sending to remote strong models.
- Reduce remote model input tokens and call rounds without sacrificing one-shot success rate.
Architecture
User Request
↓
Local Preprocessing
├─ Task classification
├─ File selection
├─ Context compression
├─ Prompt optimization
├─ Safety filtering
↓
Remote Strong Model (based on refined context)
↓
Local Verification (test/lint/diff)Local models handle: task routing, file indexing, context compression, prompt optimization, failure summarization, caching.
Remote strong models handle: complex reasoning, critical decisions, final code generation.
Current Scope
- Provide Codex-compatible preprocessing, provider, tool-loop, sanitizer, sandbox policy, hooks, history, skills, and MCP/plugin metadata APIs as standalone TypeScript package APIs, with a Rust
codelean-codex-corebridge for performance-sensitive task routing classification, AGENTS loading, command metadata analysis, repo file summarization, context snippet extraction, safety scans, context compression metadata analysis, plugin manifest loading, hook/plugin/skill parsing, skill discovery, and hook command output decisions. - Keep TypeScript at orchestration, provider/API boundaries, compatibility adapters, and test fixtures unless a performance-sensitive path explicitly needs a Rust implementation.
- Optimize for accuracy first, then cost, with speed and safety maintained.
- Keep Codex-like file/shell/approval/diff/test capabilities as the product direction.
- Provide native OS-level sandbox isolation on macOS and Linux; keep interactive approval UI, real remote MCP/OAuth smoke, real-credential plugin marketplace smoke, cross-host sandbox/TUI validation, and full terminal TUI rendering as independent codelean roadmap items. Local plugin add/remove, local marketplace/cache inspection, Codex remote plugin/skill discovery/publish/fetch/install/uninstall helpers, MCP get/preflight/login-readiness checks, stdio/HTTP/SSE MCP lifecycle sessions, sandbox long-running command sessions, and history session inspection are available in the lightweight CLI or runtime APIs.
- Provide a unified
ModelProviderboundary for model calls, streaming, tool-call events, usage, and errors. - Support
anthropicandgeminidirectly, plus OpenAI-compatible providers includingopenai,qwen, andmimo. - Add local preprocessing layer:
LocalRouter,ContextBuilder,ContextCompressor,SafetyFilter. - Provide deterministic history summary memory, safe notification command adapters, MCP stdio process lifecycle, and read-only skill reference/asset discovery.
- Export
createCodeleanRustCodexCoreBridge/invokeCodeleanRustCodexCoreBridgefromcodelean/codexfor host-managed stdin/stdout access to the Rust parser bridge; AGENTS/hooks/plugins/skills/sandbox/permissions/preprocessing also expose optional Rust-backed adapter paths (new LocalRouter(..., { rustBridge }),new CodexPreprocessor({ rustBridge }),loadCodexAgentsInstructions({ config: { rustBridge } }),analyzeCodeleanCommand(...),bridge.analyzeCommand(...),bridge.classifyRoutingPrompt(...),bridge.extractContextSnippets(...),bridge.analyzeContextCompression(...),new ContextBuilder(8000, { rustBridge }),new ContextCompressor().compressEnhanced(context, { rustBridge }),listCodexHookEventMetadataWithRustBridge,parseCodexHookConfigsWithRustBridge,parseCodexHookCommandOutputWithRustBridge,parseCodexHookCommandOutputsWithRustBridge,parseCodeleanMcpServerDefinitionsWithRustBridge,parseCodeleanPluginManifestWithRustBridge,parseCodeleanPluginManifestsWithRustBridge, andloadCodeleanSkills({ config: { rustBridge } })).
Install
npm install -g codeleanOr build from source:
git clone [email protected]:zhoujianlin/codelean.git
cd codelean
npm install
npm run buildUsage
For the full documentation index, see docs/README.md.
Codex-Style Config Compatibility
Codelean reads Codex-style configuration fields from Codelean's own ~/.codelean/config.toml and optional ~/.codelean/<profile>.config.toml; it does not read ~/.codex directly. model_provider accepts Codelean built-ins or custom Codex model-provider ids. Custom [model_providers.<id>] entries with base_url are mapped onto Codelean's OpenAI-compatible transport, and provider API keys can come from env_key/api_key_env or from a Codex-style ~/.codelean/auth.json containing OPENAI_API_KEY.
model_provider = "openai"
model = "ppio/pa/gpt-5.5"
reasoning = "high"
verbosity = "low"
service_tier = "flex"
model_context_window = 200000
model_reasoning_summary = "auto"
hide_agent_reasoning = false
show_raw_agent_reasoning = false
disable_response_storage = false
preferred_auth_method = "apikey"
approval_policy = "on-request"
approvals_reviewer = "security-team"
sandbox_mode = "workspace-write"
notify = ["terminal-notifier", "-message", "Codelean done"]
[model_providers.openai]
base_url = "https://api.ppinfra.com/v3/openai"
env_key = "PPIO_API_KEY"
[model_routing]
mode = "auto"
fallback = "remote"
probe_on_startup = false
remote_complexity_threshold = "medium"
timeout_ms = 2500
[sandbox_workspace_write]
writable_roots = ["../shared", "/tmp/codelean-cache"]
network_access = false
[tools]
web_search = true
include_plan_tool = false
[features]
responses_api = true
[tui]
hide_agent_reasoning = true
[projects."/path/to/repo"]
trust_level = "trusted"
approval_policy = "on-request"
[permissions]
filesystem = "workspace-write"
network = false
[default_permissions]
shell = "ask"
[history]
persistence = "save-all"
[memories]
enabled = true
[skills]
include = ["repo-map", "testing"]
[hooks]
enabled = true
[mcp_servers.docs]
command = "docs-mcp"
args = ["--stdio"]
env.DOCS_TOKEN = "token-from-config"
[mcp_servers.web]
url = "https://mcp.example.test/http"
transport = "http"Supported built-in provider IDs are openai, anthropic, gemini, qwen, mimo, and ollama; the built-in local default is Ollama with qwen2.5-coder:1.5b. Custom Codex provider ids such as mify, ppio, or lmstudio are supported only when a matching [model_providers.<id>] section provides an OpenAI-compatible base_url. The default [model_routing] strategy is auto: use a user-configured local endpoint first, otherwise use the built-in Ollama local endpoint, but route medium, complex, and critical prompt tasks to the configured remote provider by default for accuracy; set remote_complexity_threshold = "off" to keep ready local models for all task complexities. Provider API-key fields accept both env_key and api_key_env, and auth.json follows Codex's API-key login shape. The reasoning, model_reasoning_effort, verbosity, model_verbosity, service_tier, max_output_tokens, and model_max_output_tokens values are parsed and forwarded on OpenAI-compatible/Responses requests as model metadata when configured. The model_context_window, model_reasoning_summary, hide_agent_reasoning, show_raw_agent_reasoning, disable_response_storage, and preferred_auth_method fields are retained as Codex-compatible model/UX metadata, exposed in debug models, and can be overridden with repeatable -c key=value flags. Codex-style [tools], [features], [tui], [projects."<path>"], [permissions], [default_permissions], [history], [memories], [skills], and [hooks] simple scalar values are retained as safe metadata, can be overridden with dotted -c section.key=value flags, and are surfaced in diagnostics; [tui].notifications, [tui].notification_method, and [tui].notification_condition are applied by the Rust TUI notification bridge, while other retained metadata does not auto-enable external web search, GUI behavior, trust changes, permission profile changes, or hook/skill execution. approvals_reviewer is parsed and surfaced in status/permissions as host-managed reviewer metadata. notify = ["command", "arg"] is parsed as safe host notification command metadata, surfaced in features list, and dispatched by the CLI/TUI notification bridge for approval, user-input, and run lifecycle events when configured. sandbox_workspace_write.writable_roots and sandbox_workspace_write.network_access are parsed, shown in codelean permissions, and applied to codelean-owned CLI/TUI sandbox policy checks. Codex-style [mcp_servers.<name>] sections are merged with CODELEAN_HOME/mcp-servers.json, CODELEAN_MCP_SERVERS, and plugin-declared MCP servers.
MiMo
MiMo is OpenAI-compatible. The default MiMo base URL is https://api.xiaomimimo.com/v1, and the default model is mimo-v2.5-pro.
export MIMO_API_KEY="sk-..."
codelean --provider mimo --prompt "Explain this repo"Top-level Codex-compatible helpers include codelean exec/codelean e for non-interactive prompts, codelean review for a local change summary, codelean status, codelean usage, codelean permissions, codelean route <prompt>, codelean models status, codelean diff, and codelean init for local session/config diagnostics and repository utilities, codelean login, codelean logout, codelean doctor, codelean features list, codelean debug models [--bundled], codelean debug app-server ..., codelean debug prompt-input [-i <image>] <prompt>, codelean debug trace-reduce <dir>, codelean debug clear-memories, and codelean update for lightweight auth/health/feature/model/update diagnostics, codelean mcp-server, codelean app-server, codelean remote-control, codelean apply/codelean a, codelean cloud/codelean cloud-tasks, codelean responses-api-proxy, codelean stdio-to-uds, and codelean exec-server for safe local compatibility explanations instead of launching cloud, daemon, or internal socket services, codelean execpolicy check [--rules <path>] [--pretty] -- <command> as a Codex-compatible local sandbox preflight JSON view, codelean resume --last, codelean resume <session-id>, codelean fork <session-id>, codelean archive <session-id>, codelean unarchive <session-id>, and codelean delete <session-id> for local CODELEAN_HOME/history.jsonl session inspection/copy/removal, codelean mcp list|verbose|add <name> --url <url>|add <name> -- <cmd>|remove <id>|get <id>|preflight <id>|login <id>|logout <id> for local MCP config and readiness checks, codelean plugin list|verbose|marketplace add <path>|marketplace list|marketplace list --remote|marketplace upgrade [id]|marketplace remove <id>|add <path>|publish <path>|fetch <remote-plugin-id>|remove <id>, codelean skills list|verbose|publish <skill-name>|fetch <remote-plugin-id> <skill-name>, codelean app [target] for Codex Desktop handoff tracking, and codelean apps for local registry/workspace inspection, codelean completion bash|zsh|fish for shell completions, and codelean sandbox explain|run -- <command> for local sandbox policy checks or execution. Remote plugin/skill discovery, publish, and fetch use Codex-compatible resource endpoints (/ps/plugins/list?collection=vertical for the OpenAI curated remote collection, /ps/plugins/installed, /ps/plugins/workspace/shared, /public/plugins/workspace, /ps/plugins/<id>, and /ps/plugins/<id>/skills/<name>), accept --url, --api-key, and --account-id, and keep local materialized resources under .codelean/CODELEAN_HOME. Codex also exposes the curated plugin export backup at https://chatgpt.com/backend-api/plugins/export/curated, which Codelean records as codexCuratedPluginExportURL for diagnostics and future cache/bootstrap flows.
Running codelean with no prompt in an interactive terminal starts a Codex-like REPL. The startup banner uses a compact Codex-aligned layout showing model, provider, workdir, approval policy, sandbox mode, and routing mode; the Rust fullscreen TUI keeps startup help/footer hints hidden and avoids extra blank lines for a tighter first screen. On startup the TUI can check the npm latest version, show an update prompt when a newer codelean is available, and let you update now, skip, or skip until the next version; set CODELEAN_CHECK_FOR_UPDATE_ON_STARTUP=false to disable this check. Codex-style startup shortcuts include repeatable -c, --config for supported invocation overrides such as provider, model_provider, model, approval_policy, approvals_reviewer, sandbox_mode, file_opener, project_doc_fallback_filenames, sandbox_workspace_write.writable_roots, sandbox_workspace_write.network_access, model_reasoning_effort, model_verbosity, service_tier, base_url, api_key, max_output_tokens, model_max_output_tokens, and provider dot paths like model_providers.<id>.base_url plus model_providers.<id>.env_key/api_key_env, -m, --model, -C, --cd, -s, --sandbox, -a, --ask-for-approval, -p, --profile, -V, --version, help, and --dangerously-bypass-approvals-and-sandbox for explicit local bypass display. Comma-separated values are accepted for shortcut list overrides such as project_doc_fallback_filenames and sandbox_workspace_write.writable_roots. Type /, /?, /commands, or /help to list supported slash commands; the list mirrors Codex built-in slash command names while local-only helpers such as /provider, /approval, /sandbox, /workdir, /version, and /route <prompt> remain available. Implemented local commands include /status, /status json, /model, /usage, /permissions, /skills, /skills verbose, /mcp, /mcp verbose, /plugins, /plugin, /plugins verbose, /theme, /keymap, /ide, /experimental, /memories, /hooks, /agent, /subagents, /multi-agents, /side, /btw, /app, /import, /resume, /fork, /personality, /plan, /goal, /rename, /pets, /pet, /copy, /mention, /setup-default-sandbox, /sandbox-add-read-dir, /approve, /test-approval, /rollout, /logout, /feedback, /debug-config, /diff, /init, /compact, /new, /archive, /delete, /clear, /raw, /vim, /title, /statusline, /ps, /stop, /clean, /exit, and /quit; /status reports grouped session/model/workspace/policy/usage/UI information for humans, /status json preserves the machine-readable status snapshot, /usage reports local session turns, model, provider, elapsed time, history path, and provider token usage when streaming responses include usage metadata, /theme and /keymap track current-session UI preferences, /ide, /experimental, /memories, /hooks, /agent, /subagents, /multi-agents, /side, and /btw track local environment/thread state, /app, /import, /resume, /fork, and /personality track local handoff/session navigation preferences, /plan, /goal, /rename, /pets, /copy, /mention, /compact, /statusline, and /new track or reset local conversation/status state, while prompt turns are persisted to CODELEAN_HISTORY_PATH or CODELEAN_HOME/history.jsonl, /archive and /delete record local session-close requests before exiting without mutating persisted chat stores, /setup-default-sandbox, /sandbox-add-read-dir, /approve, and /test-approval track local sandbox/approval state, /review summarizes local change scope, /apps summarizes local app/plugin/MCP availability, /debug-m-drop and /debug-m-update record Codex memory-maintenance debug requests without mutating local state, /rollout prints the local Codelean rollout path, /logout and /feedback provide local account/log guidance, /skills reads workspace .codelean/skills/<skill-name>/SKILL.md, /mcp reads CODELEAN_MCP_SERVERS JSON plus plugin MCP servers, and /plugins//plugin read CODELEAN_PLUGIN_CACHE or CODELEAN_HOME/plugins.json. Codex commands that need the full TUI/cloud runtime are recognized and reported as not executed by the lightweight CLI instead of failing as unknown.
You can also set defaults:
export CODELEAN_PROVIDER="mimo"
export CODELEAN_MODEL="mimo-v2.5-pro"
export MIMO_API_KEY="sk-..."
codelean --prompt "Write a TypeScript function"For Token Plan usage, override the base URL:
export MIMO_BASE_URL="https://token-plan-cn.xiaomimimo.com/v1"Local Model Setup (Recommended)
For cost optimization, install Ollama and download the default Qwen2.5-Coder model:
# Install Ollama
curl -fsSL https://ollama.com/install.sh | sh
# Download the built-in default model
ollama pull qwen2.5-coder:1.5b
# Optional: download a larger model if you override CODELEAN_LOCAL_COMPLEX_MODEL
ollama pull qwen2.5-coder:7b
# Ollama will auto-start
ollama serveWhy Qwen2.5-Coder?
- Code-specialized: optimized for code understanding, generation, and completion
- Multi-language: supports 80+ programming languages
- Large context: 32K (1.5B) to 128K (7B/14B)
- Fast: <100ms first token on M1/M2 Mac for 1.5B model
- Accurate: high performance on HumanEval, MBPP benchmarks
- Chinese-friendly: better understanding of Chinese comments and variable names
Model Comparison
| Model | Size | Memory | Speed | Use Case | Context | |-------|------|--------|-------|----------|---------| | qwen2.5-coder:1.5b | 1.5B | ~1GB | Very Fast | Task classification, file selection, repo indexing | 32K | | qwen2.5-coder:7b | 7B | ~4GB | Fast | Context compression, prompt optimization, log summarization | 128K | | llama3.2:3b | 3B | ~2GB | Fast | General reasoning, natural language understanding | 128K |
Configuration
Default single-model setup:
export CODELEAN_LOCAL_FAST_MODEL=qwen2.5-coder:1.5b
export CODELEAN_LOCAL_COMPLEX_MODEL=qwen2.5-coder:1.5bOptional dual-model setup:
export CODELEAN_LOCAL_FAST_MODEL=qwen2.5-coder:1.5b
export CODELEAN_LOCAL_COMPLEX_MODEL=qwen2.5-coder:7bLocal Model CLI
Use the CLI helpers to check and prepare the configured local models:
codelean local-model status
codelean models status
codelean local-model install-script
codelean local-model install-ollama --dry-run
codelean local-model install-ollama
codelean local-model pull --dry-run
codelean local-model pullstatusprints JSON describing Ollama or OpenAI-compatible local service availability and configured model status.models statusprints the configured routing strategy, local/remote endpoints, local readiness, and final selection decision.- In
automode, the default remote cutoff ismedium, so onlysimpleprompts stay local when the local model is ready; configureremote_complexity_thresholdasoff,medium,complex, orcritical. install-scriptprints an install/pull script for Ollama, or environment setup for OpenAI-compatible local services.install-ollamasafely auto-installs Ollama only when a supported local installer is detected, currently macOS with Homebrew; otherwise it prints manual steps and exits non-zero.pulldownloads the configured fast and complex models for Ollama;--dry-runprints the pull plan.- Override CLI defaults with
--local-model-provider,--local-model-base-url,--ollama-command,--ollama-base-url,--fast-model, and--complex-model. - Programmatic helpers are exported from
codelean/local-models.
Routing Behavior
model_routing.mode = "auto"probes the configured local endpoint and uses it for prompts below the remote cutoff. The defaultremote_complexity_threshold = "medium"keeps onlysimpleprompts local;medium,complex, andcriticalprompts route to the configured remote provider for accuracy.- If the local endpoint is unavailable,
fallback = "remote"sends the prompt to the remote provider. Usefallback = "none"to fail closed orremote_complexity_threshold = "off"to keep every ready local-model prompt local. - CLI
--providerand--modelare explicit one-invocation endpoint overrides. Codex-style-c model_provider=...and-c model=...configure the remote endpoint for that invocation, but do not disableautorouting by themselves. - In the interactive REPL,
/remote <prompt>forces only that prompt through the remote route, does not write configuration, and immediately restores the default routing behavior for later prompts. - Ollama and loopback OpenAI-compatible local models use a conservative request shape: incompatible
verbosityandservice_tiermetadata is filtered, reasoning effort is normalized no higher thanhigh, and tools are omitted for known local model families that do not support tool calls.
Dual-model collaboration
Accuracy-first dual-model collaboration is opt-in. When enabled for a non-simple task, the configured primary model generates an answer, an independent reviewer performs a read-only review, and the primary model revises the answer when needed. The reviewer never receives tool definitions and never executes tools. The workflow is serial, preserves the same session context, stores control-plane checkpoints under the same session, and resumes from the latest completed (phase, round) without replaying completed provider/tool work. Normal conversation history stores only the user prompt, tool events, and final assistant answer; reviewer instructions and drafts are not replayed as conversation messages.
max_revision_rounds = 1 performs generate → review 1 → optional revise 1 → final review 2 → finalize. Setting it to 2 adds review/revise round 2 and a final review round 3. A reviewer revise decision after the configured limit is a failure, never an implicit approval. The primary endpoint must have a distinct configured opposite endpoint: a remote primary requires a local reviewer, and a local primary requires a remote reviewer. Provider, model, and normalized base URL identity must differ; credentials are never written to checkpoints.
Enable it in ~/.codelean/config.toml:
[collaboration]
enabled = true
accuracy_first = true
review_critical_only = true
max_revision_rounds = 1Equivalent environment variables are CODELEAN_COLLABORATION_ENABLED, CODELEAN_COLLABORATION_ACCURACY_FIRST, CODELEAN_COLLABORATION_REVIEW_CRITICAL_ONLY, and CODELEAN_COLLABORATION_MAX_REVISION_ROUNDS. max_revision_rounds accepts 1 or 2. Collaboration increases latency and model/token cost because reviewer calls and each revision are included in aggregate usage; leave it disabled for simple or latency-sensitive prompts. The interactive /remote <prompt> route keeps the current sessionId and history context, while collaboration remains disabled unless the collaboration setting is explicitly enabled.
Every collaboration run has a durable runId. A failed interactive run prints an exact recovery command:
/collab status [runId]
/collab resume <runId>--prompt and exec use a durable random session when collaboration is enabled. Successful non-interactive runs print only the final answer; failures print the sanitized reason and resume command on stderr. The TUI bridge accepts collaboration-status and collaboration-resume requests and forwards bounded collaboration metadata through prompt and stream responses. The Rust fullscreen TUI exposes Conversation, Collaboration, Tools, History, Approval, and Logs panes while keeping conversation history and the composer visible. Tools shows bounded safe tool lifecycle state, History shows bounded current-session prompt previews, Approval is a read-only lifecycle view while the popup remains the only decision surface, and Logs shows bounded safe lifecycle summaries. With an empty composer, use Tab / Shift+Tab to cycle panes and PageUp / PageDown to scroll each operational pane independently; pane navigation and scrolling make no additional bridge or provider calls.
Useful routing checks:
codelean models status
codelean local-model status
ollama list
curl http://127.0.0.1:11434/v1/modelsFor LM Studio, vLLM, llama.cpp server, or another OpenAI-compatible local endpoint:
export CODELEAN_LOCAL_MODEL_PROVIDER=openai_compatible
export CODELEAN_LOCAL_MODEL_BASE_URL=http://127.0.0.1:1234/v1
codelean local-model status --fast-model local-fast --complex-model local-complexLocal preprocessing is used for:
- Task classification and routing
- File relevance ranking
- Deterministic context compression with optional local-model enhancement
- Failure log summarization, with opt-in Rust scanning for large logs
- Repo indexing and caching
- History summary extraction, with opt-in Rust scanning from async memory-store APIs
- Optional local-model security verification
They do not replace remote strong models for critical code generation.
Optional local-model context compression keeps the deterministic result as the fallback and can use either Ollama (/api/generate) or an OpenAI-compatible local service (/chat/completions).
Compression also applies deterministic budget allocation across summaries, snippets, and metadata before the final hard token cap, and can use deterministic multi-stage summaries so tight prompts keep useful file context instead of dropping everything at once.
# Optional: enable model-backed context compression
export CODELEAN_LOCAL_COMPRESSION_MODEL_ENABLED=true
export CODELEAN_LOCAL_COMPRESSION_MODEL_PROVIDER=openai_compatible
export CODELEAN_LOCAL_COMPRESSION_MODEL_ENDPOINT=http://127.0.0.1:1234/v1
export CODELEAN_LOCAL_COMPRESSION_MODEL=local-complexTo validate the OpenAI-compatible local-model enhancement path without installing Ollama or starting LM Studio/vLLM, run the repository mock smoke. It starts an in-process /v1/models and /v1/chat/completions server, then verifies local-model readiness, context compression enhancement, and safety review:
npm run build
npm run codex:local-model-mock-smokeLocal Security Redaction
All outbound chat and stream requests pass through SafetyFilter before reaching a remote provider. The filter uses deterministic rules first, blocks sensitive files as whole-file placeholders, and can optionally ask a local model to classify ambiguous values as real secrets or safe examples. Async context filtering can opt into the Rust safety.scan bridge for deterministic rule scanning; masking policy, local-model review, and synchronous safety APIs remain TypeScript fallback boundaries.
# Optional: enable local model review for ambiguous findings
export CODELEAN_SECURITY_LOCAL_MODEL_ENABLED=true
export CODELEAN_SECURITY_LOCAL_MODEL_ENDPOINT=http://127.0.0.1:11434
export CODELEAN_SECURITY_LOCAL_MODEL=qwen2.5-coder:1.5b
export CODELEAN_SECURITY_LOCAL_MODEL_PROVIDER=ollama
# Or use an OpenAI-compatible local service:
export CODELEAN_SECURITY_LOCAL_MODEL_PROVIDER=openai_compatible
export CODELEAN_SECURITY_LOCAL_MODEL_ENDPOINT=http://127.0.0.1:1234/v1
# Optional privacy controls
export CODELEAN_SECURITY_MASK_EMAILS=false
export CODELEAN_SECURITY_MASK_IPS=false
export CODELEAN_SECURITY_ALLOW_REMOTE_WITH_SECRETS=trueSet CODELEAN_SECURITY_ALLOW_REMOTE_WITH_SECRETS=false to fail closed whenever a request still contains detected secrets before redaction. The local security model receives only a small snippet around the suspicious value, not the full repository context.
Codex-Compatible Runtime
Codelean exposes Codex-compatible building blocks for preprocessing, Responses-compatible calls, tool-call loops, response-item sanitization, sandbox policy checks, hooks, history, memory, optional cost tracking, skills, and MCP/plugin metadata lifecycle. The package preserves Codex-style tool metadata, approvals, sandbox fields, hook matcher/config metadata, skill/system messages, and MCP/plugin schema shape while remaining independent from legacy source-only integrations.
CodexPreprocessor loads scoped project instructions by default: AGENTS.override.md wins over AGENTS.md in the same directory, discovery climbs to the nearest .git root, and matching files are injected as sanitized prompt constraints in broad-to-narrow order. Use agents: false to disable loading, agents: { enabled: true, fallbackFilenames: ['CODELEAN.md'] }, or config.toml project_doc_fallback_filenames = ["CODELEAN.md"] to include explicit fallback project docs through the same scoped lookup, including the optional Rust bridge path. This is a lightweight read-only loader; hosts can still inject their own fully resolved rule set through messages or constraints.
Set skills: true to load sanitized SKILL.md instructions from workspace .codelean/skills; pass explicit skill roots with loadCodeleanSkills or the preprocessor skills config when a host wants stricter selection. The optional Rust bridge can discover SKILL.md candidates and parse skill frontmatter, while TypeScript keeps SafetyFilter masking, reference/asset/script handling, and fallback. codelean skills script <name> -- <args> resolves declared skill scripts into a host approval plan without executing them, preserving Codex-style sandbox and approval boundaries; codelean skills script <name> --execute-approved -- <args> and runtime hosts that already collected explicit approval can use executeCodeleanSkillScriptWithApproval to run the resolved script through CodeleanSandbox. TUI hosts can pass the host approval plan through createCodeleanTuiSkillScriptApproval to render skill name, script path, sandbox mode, command, arguments, cwd, and reason in the approval pane; createCodeleanTuiFileOpenApproval similarly turns file opener requests into structured host approval prompts without directly launching GUI apps, and config.toml file_opener = "cursor" or CLI -c file_opener=cursor is preserved for host/TUI selection.
import { CodeleanCodexRuntime, CostController, ResponsesModelProvider } from 'codelean/codex'
const provider = new ResponsesModelProvider({
baseURL: 'https://api.openai.com/v1',
apiKey: process.env.OPENAI_API_KEY,
defaultModel: 'gpt-4.1'
})
const runtime = new CodeleanCodexRuntime({
provider,
workingDir: process.cwd(),
costController: new CostController()
})
const result = await runtime.run({
prompt: 'Fix the bug in src/app.ts',
files: ['src/app.ts'],
model: 'gpt-4.1'
})
console.log(result.responseText)For Responses-compatible continuation, pass previousResponseId, responseId, or a prior result.continuation into the next runtime.run call. Results include responseId and continuation when the provider returns a Responses API id.
When a Responses-compatible gateway rejects an otherwise valid previous_response_id because the id is unavailable or the gateway does not support it, Codelean retries that turn once with the complete sanitized message history.
CodeleanCodexRuntime includes a runtime permission evaluator for command allowlists, deny patterns, workspace-root checks, and approval-required decisions. It also uses CodeleanSandbox for codelean-owned read-only/workspace-write/danger-full-access policy checks, writable roots, restricted-network preflight, bounded process execution, incremental sessions, stdin handoff, and explainable preflight results; CLI/TUI helpers seed that policy from sandbox_workspace_write.
Native OS Sandbox
The CLI automatically selects native isolation for sandbox execution. macOS requires the trusted system executable /usr/bin/sandbox-exec (Seatbelt); Linux requires bubblewrap at /usr/bin/bwrap or /bin/bwrap. If CODELEAN_SANDBOX_EXECUTOR_COMMAND is configured, that external executor takes precedence over native selection. Check the effective mode, network policy, selected isolation strategy, backend availability, and fail-closed diagnostic with:
codelean sandbox status --json
codelean sandbox run --json -- 'printf sandbox-ok'Native filesystem and network semantics are:
read-onlykeeps the host filesystem readable but denies persistent host writes.workspace-writemakes only the normalized workspace and configuredsandbox_workspace_write.writable_rootswritable; real-path normalization prevents symlink escapes outside those roots.danger-full-accessleaves host filesystem writes unrestricted while preserving the explicitly configured network policy. The CLI--dangerously-bypass-approvals-and-sandboxshortcut additionally enables network access.network = "restricted"denies network access with Seatbelt on macOS. On Linux it creates a network namespace and hides the host/runwith a private tmpfs;network = "enabled"retains host network access.
Unsupported platforms and missing native executables fail closed before launching the command and report the reason through codelean sandbox status --json. Native isolation can allocate a real PTY through the packaged Rust codelean-pty-host helper; missing or untrusted helper paths fail closed rather than falling back to a plain pipe. External isolation remains higher priority when CODELEAN_SANDBOX_EXECUTOR_COMMAND is configured.
Native PTY and interactive approvals
codelean sandbox run --tty -- <command> requests a real OS PTY. Add --tty-rows <1..4096> and --tty-cols <1..4096> together to set the initial terminal size; yielded sessions keep the PTY open for write_stdin, incremental reads, and resize. The Rust helper owns PTY allocation, merges PTY output into the bounded result stream, validates control frames and dimensions, and terminates the process tree on timeout, close, or protocol failure. It does not provide direct user takeover of the child terminal: interactive access remains a host/TUI policy decision.
The CLI automatically selects the packaged helper only after native sandbox capability is available. Set CODELEAN_PTY_HOST_BINARY to an absolute executable path to override helper discovery; codelean sandbox status --json reports the selected native backend and PTY helper separately, so a usable sandbox with an unavailable PTY is diagnosable before execution.
Runtime approval events preserve the bounded execution context needed by a host UI: working directory, TTY and dimensions, session/background/yield settings, approval policy, sandbox permissions, justification, and a display/key pair for an explicit canonical prefix rule. Environment variables and stdin contents are deliberately not included. The Rust fullscreen TUI offers Allow once, Always allow this rule for this session, and Deny when both rule fields exist; it stores only the exact key for the lifetime of that TUI process. Remembered rules can skip a repeated approval popup, but they never override runtime hard denials or sandbox blocks.
Library consumers must configure the helper explicitly for native PTY execution; the library default remains fail-closed isolation: "disabled":
import { CodeleanSandbox, createCodeleanNativePtyHost } from 'codelean/codex'
const nativePtyHost = createCodeleanNativePtyHost({
executable: '/absolute/path/to/codelean-pty-host'
})
const sandbox = new CodeleanSandbox({
isolation: 'native',
mode: 'workspace-write',
workspaceRoot: process.cwd(),
network: 'restricted',
nativePtyHost,
ttyRows: 24,
ttyCols: 80
})import { CodeleanCodexRuntime, ResponsesModelProvider } from 'codelean/codex'
const runtime = new CodeleanCodexRuntime({
provider,
workingDir: process.cwd(),
sandbox: { mode: 'workspace-write', network: 'restricted' },
execCommandGuard: {
allowedCommands: [/^git\b/u, /^npm\s+test\b/u],
requireApproval: [/^npm\s+test\b/u]
},
approvalHandler: request => {
// Host UI/policy decides whether a require_approval decision may proceed.
return { status: 'pending', reason: `Approval required for ${request.command}` }
}
})Runtime integrations can also pass hooks to observe/block lifecycle events, parse Codex-style hook command config with parseCodexHookConfigWithRustBridge, batch parse multiple hook configs with parseCodexHookConfigsWithRustBridge, normalize command hook stdout decisions with parseCodexHookCommandOutputWithRustBridge, batch normalize command hook stdout decisions with parseCodexHookCommandOutputsWithRustBridge, generate approval-only hook command plans with createCodexCommandHookApprovalPlans, use history to persist/replay messages and tool events via CodeleanHistoryStore, set compactHistory.historyEventThreshold to trigger pre_compact / post_compact hooks when runtime history reaches a local threshold, use CodeleanSandbox.startSession for policy-checked long-running commands with incremental read, stdin-after-start write, wait, and close, use memory plus memoryReplay to inject relevant CodeleanMemoryStore repo/session notes before model calls, and use costController to record provider usage/cost/latency when responses include token usage. MCP/plugin hosts can use CodeleanMcpPluginRegistry to parse and validate .codex-plugin/plugin.json, expose plugin hookPaths, skillsPath, mcpServersPath, and appsPath, load safe in-plugin hook config files with loadCodeleanPluginHookConfigs, load safe plugin-declared skill roots with loadCodeleanPluginSkills, safely load plugin-declared app definition files with loadCodeleanPluginAppDefinitions, safely load plugin-declared external MCP definition files, and normalize MCP server definitions, use parseCodeleanMcpServerDefinitionsWithRustBridge for Rust-backed MCP definition normalization with TypeScript fallback, use lifecycle preflight to verify OAuth metadata or a usable tokenProvider, and opt into stdio, HTTP JSON-RPC POST, or SSE GET + message POST MCP sessions when credentials and host policy are ready.
For tools that already produce Codex ResponseItem JSON, use the JSON sanitizer before provider serialization:
codelean sanitize-response-items < response-items.json > sanitized-response-items.jsonTo verify the runtime without a production model endpoint, Codelean includes a local mock Responses provider:
codelean mock-responses-provider --port 18080 --log /tmp/codelean-codex-mock.logWhen running from this repository, the full local smoke test is:
npm run build
npm run codex:runtime-smoke
npm run codex:local-model-mock-smoke
npm run codex:real-runtime-mock-smokeThe smoke tests start local mock providers, run CodeleanCodexRuntime, verify exec_command can write loop files, and check that mock provider logs contain redacted secrets but no raw sk-... values. codex:real-runtime-mock-smoke exercises the same codex:real-runtime-smoke script against a local Responses-compatible mock endpoint, so the real-provider tool-loop path is covered without external credentials.
Useful smoke-test options:
# Timeout in milliseconds; default is 120000
CODELEAN_RUNTIME_SMOKE_TIMEOUT_MS=180000 npm run codex:runtime-smoke
# Keep the temporary workdir and mock provider log for inspection
CODELEAN_RUNTIME_SMOKE_KEEP_TEMP=1 npm run codex:runtime-smokeWhen you have a real Responses-compatible endpoint, run the production-provider smoke. After npm run build, both commands use the active .codelean/config.toml and auth.json when CODELEAN_REAL_* overrides are absent; the configured provider must use wire_api = "responses". An explicit CODELEAN_REAL_PROVIDER_BASE_URL never reuses credentials from the configured endpoint, so set CODELEAN_REAL_PROVIDER_API_KEY_ENV explicitly when the override requires authentication.
# Active .codelean Responses provider and auth
npm run codex:real-runtime-ready
npm run codex:real-runtime-smoke
# Check environment readiness without network access first
CODELEAN_REAL_PROVIDER_BASE_URL=http://127.0.0.1:1234/v1 \
CODELEAN_REAL_PROVIDER_MODEL=local-model \
npm run codex:real-runtime-ready
# Local OpenAI-compatible service
CODELEAN_REAL_PROVIDER_BASE_URL=http://127.0.0.1:1234/v1 \
CODELEAN_REAL_PROVIDER_MODEL=local-model \
npm run codex:real-runtime-smoke
# API-backed provider
OPENAI_API_KEY=... \
CODELEAN_REAL_PROVIDER_BASE_URL=https://api.openai.com/v1 \
CODELEAN_REAL_PROVIDER_API_KEY_ENV=OPENAI_API_KEY \
CODELEAN_REAL_PROVIDER_MODEL=gpt-4.1 \
npm run codex:real-runtime-smokeCODELEAN_REAL_MODEL and CODELEAN_REAL_PROVIDER_ENV_KEY remain supported as backward-compatible aliases.
Anthropic
export ANTHROPIC_API_KEY="sk-ant-..."
codelean --provider anthropic --model claude-sonnet-4-5 --prompt "Explain this repo"OpenAI-compatible providers
export OPENAI_API_KEY="sk-..."
codelean --provider openai --model gpt-4o --prompt "Explain this repo"
export QWEN_API_KEY="sk-..."
codelean --provider qwen --model qwen-plus --prompt "Explain this repo"Routing Modes
Routing modes are available through both the preprocessing API and a lightweight CLI route preview. Full approval/sandbox decisions remain the responsibility of the host runtime that executes tools.
codelean --routing-mode economy --route-only --prompt "Explain this helper"Supported modes: high_accuracy, balanced, economy, and critical.
import { CodexPreprocessor } from 'codelean/codex'
import { RoutingMode } from 'codelean/preprocessing'
const preprocessor = new CodexPreprocessor({
routingMode: RoutingMode.Balanced
})Environment Variables
| Variable | Description |
|----------|-------------|
| CODELEAN_PROVIDER | Default provider: anthropic, openai, gemini, qwen, or mimo |
| CODELEAN_MODEL | Default model for the selected provider |
| CODELEAN_API_KEY | Generic API key override for the selected provider |
| CODELEAN_BASE_URL | Generic base URL override for OpenAI-compatible providers |
| ANTHROPIC_API_KEY | Anthropic API key |
| OPENAI_API_KEY | OpenAI API key |
| GEMINI_API_KEY | Gemini API key |
| GEMINI_BASE_URL | Gemini base URL, default https://generativelanguage.googleapis.com/v1beta |
| QWEN_API_KEY | Qwen API key |
| MIMO_API_KEY | MiMo API key |
| MIMO_BASE_URL | MiMo base URL, default https://api.xiaomimimo.com/v1 |
| CODELEAN_MAX_OUTPUT_TOKENS | Max output tokens, default 4096 |
| OLLAMA_COMMAND | Ollama command for local-model helpers, default ollama |
| OLLAMA_BASE_URL / OLLAMA_HOST | Ollama base URL for local preprocessing, default http://127.0.0.1:11434 |
| CODELEAN_LOCAL_MODEL_PROVIDER | Local model helper provider: ollama or openai_compatible, default ollama |
| CODELEAN_LOCAL_MODEL_BASE_URL | OpenAI-compatible local endpoint base URL override |
| CODELEAN_LOCAL_FAST_MODEL | Local fast model, default qwen2.5-coder:1.5b |
| CODELEAN_LOCAL_COMPLEX_MODEL | Local complex model, default qwen2.5-coder:1.5b |
| CODELEAN_LOCAL_MODEL_TIMEOUT_MS | Local-model status/list timeout, default 2500 |
| CODELEAN_MODEL_ROUTING_MODE | Model routing strategy: auto, local, or remote; default auto |
| CODELEAN_MODEL_ROUTING_FALLBACK | Auto fallback target: remote, local, or none; default remote |
| CODELEAN_MODEL_ROUTING_PROBE_ON_STARTUP | Probe local model readiness during startup/status checks, default false |
| CODELEAN_MODEL_ROUTING_REMOTE_COMPLEXITY_THRESHOLD | Auto mode remote cutoff: off, medium, complex, or critical; default medium |
| CODELEAN_MODEL_ROUTING_TIMEOUT_MS | Local readiness probe timeout, default 2500 |
For local model setup, use the recommended Qwen2.5-Coder Ollama commands in the earlier local model section.
Code Structure
src/
cli/index.ts # CLI entry
index.ts # Public package entry
client.ts # CodeleanClient
config.ts # Multi-provider config
providers/
index.ts # Provider exports
anthropic-provider.ts # Anthropic Messages API adapter
openai-compatible-provider.ts # OpenAI-compatible adapter base
mimo-provider.ts # MiMo adapter
provider-factory.ts # Provider selection
preprocessing/
index.ts # Preprocessing exports
types.ts # Preprocessing types
local-router.ts # Task classification and routing
repo-indexer.ts # Repo summary and file indexing
context-builder.ts # Relevant file selection
context-compressor.ts # Deterministic context compression
prompt-optimizer.ts # Prompt rewriting for remote model
safety-filter.ts # Secret detection and masking, with opt-in Rust rule scanning
failure-summarizer.ts # Test failure log compression, with opt-in Rust scanning
cost-controller.ts # Token/cost tracking and suggestions
codex/
index.ts # Codex adapter exports
preprocessor.ts # Codex request preparation
responses-provider.ts # Responses API model provider
runtime.ts # Codex-compatible tool loop
response-item-sanitizer.ts # ResponseItem JSON sanitizer bridge
mock-responses-provider.ts # Local mock Responses provider
types.ts # Shared request/response/event typesKey Metrics
- Accuracy: test pass rate, patch quality, tool call success rate.
- Cost: avg tokens per call, total cost, preprocessing savings percentage.
- Speed: time to first token, total latency, preprocessing overhead.
- Safety: secret leaks, dangerous command blocks, data policy violations.
Roadmap
Completed
- Multi-provider adapters: OpenAI-compatible, Anthropic, Gemini, MiMo, and provider factory.
- Provider adapter regression coverage: OpenAI-compatible, Gemini, MiMo, and Anthropic request/response/stream tool-call mappings.
- Local preprocessing: safety filtering, context building, deterministic context compression, routing, repo indexing, prompt optimization, cost tracking, and failure summarization.
- Codex-compatible runtime:
CodeleanCodexRuntime,ResponsesModelProvider, ResponseItem sanitizer, optionalCostControllerusage recording, mock Responses provider, CLI commands, runtime smoke test, and mock local-model enhancement smoke. - Native OS sandbox: automatic CLI selection, explicit library opt-in, macOS Seatbelt and Linux bubblewrap backends, read-only/workspace-write/network enforcement, bounded process trees, and fail-closed capability diagnostics.
- Native PTY host and approval UI: the CLI uses the trusted Rust
codelean-pty-hosthelper when available, library callers opt in withcreateCodeleanNativePtyHost, real PTY sessions support bounded I/O and resize, and the Rust fullscreen TUI renders approval metadata with exact session-scoped prefix-rule memory. - Packaging: subpath exports for
codelean/preprocessing,codelean/providers, andcodelean/codex;prepackcleansdist, rebuilds, minifies publishable JavaScript, strips source maps, andnpm pack --dry-runpasses. Runtime dependencies are kept separate from dev/test tooling. This raises reverse-engineering cost but is not cryptographic protection for npm-distributed code.
Publish Checklist
Run these checks before publishing from a clean checkout:
npm ci
npm run verify:loop
npm publish --dry-run --registry <registry> --access <public|restricted>Notes:
npm run verify:loopretries the full local verification chain up to three times and exits on the first fully passing attempt; the finalnpm pack --dry-runtriggersprepack, andCODELEAN_VERIFY_ATTEMPTS/CODELEAN_VERIFY_RETRY_DELAY_MStune retries.prepackrewrites ignoreddist/into publish-protected output.- Confirm registry access, 2FA/provenance, package name ownership, and
dist-tagoutside the repository. - The package publishes only public docs from
package.jsonfiles; keep internal planning/status docs out of the packlist. - For public npm, verify whether the internal repository, issue tracker, homepage, and remaining public docs are intended to be visible.
Deferred
- Real-provider runtime smoke: run
npm run codex:real-runtime-readyfirst, thennpm run codex:real-runtime-smokewhen a real Responses-compatible endpoint and credentials are available. - Advanced optimization: strategy tuning, dual-model diff review, and local model fine-tuning after real-provider smoke data is available.
- External environment parity: run real MCP/plugin marketplace and cross-host sandbox/TUI end-to-end smokes when external servers, credentials, representative macOS/Linux hosts, and an interactive terminal environment are available.
To keep running the remaining deferred tasks until completion, use:
npm run remaining:loopThe loop persists progress to .codelean/remaining-tasks.json, waits between attempts with CODELEAN_REMAINING_TASKS_INTERVAL_MS, and exits only when all tasks complete. Set CODELEAN_REMAINING_TASKS_MAX_ITERATIONS for bounded runs; leave it unset for a continuous loop. It runs real-provider readiness/smoke first, then optional commands from CODELEAN_STRATEGY_TUNING_COMMAND, CODELEAN_DUAL_REVIEW_COMMAND, CODELEAN_FINE_TUNE_COMMAND, CODELEAN_EXTERNAL_MCP_PLUGIN_COMMAND, and CODELEAN_EXTERNAL_OS_SANDBOX_TUI_COMMAND. For local-only completion without external credentials, set CODELEAN_REMAINING_TASKS_LOCAL_FALLBACK=1; this rebuilds the package, runs the mock real-provider runtime smoke through codex:real-runtime-smoke, and records the external tuning/review/fine-tuning/MCP/plugin/sandbox/TUI tasks as explicitly accepted local fallbacks.
Loop command environment variables accept either simple whitespace-separated commands without shell operators or a JSON array such as ["npm","run","review"]. Use the JSON array form for arguments containing shell metacharacters; shell operators like &&, |, redirection, and command substitution are rejected by default.
To execute Codex parity gap tasks until all locally verifiable work is complete, use:
npm run codex-gap:loopThis writes .codelean/codex-gap-loop.json, verifies the built-in Codex P0 runtime tools (exec_command, write_stdin, apply_patch, update_plan, request_user_input, and view_image), runs TypeScript validation, then runs npm run verify:loop. Successful completion requires every slice to finish; bounded runs can stop earlier when CODELEAN_CODEX_GAP_MAX_ITERATIONS is reached. Set CODELEAN_CODEX_GAP_INTERVAL_MS for sleep timing. External Codex environment validation defaults to local, credential-free smokes: npm run codex:real-runtime-mock-smoke, npm run codex:interactive-hello-smoke, tests/codex/mcp-lifecycle.test.ts, tests/codex/remote-resources.test.ts, and tests/codex/sandbox.test.ts plus tests/codex/tui.test.ts. The interactive hello smoke starts a local mock provider, runs global codelean, enters 你好, verifies a normal assistant reply, then exits with /exit. Override defaults with CODELEAN_CODEX_GAP_REAL_PROVIDER_SMOKE_COMMAND, CODELEAN_CODEX_GAP_MCP_OAUTH_SMOKE_COMMAND, CODELEAN_CODEX_GAP_PLUGIN_MARKETPLACE_SMOKE_COMMAND, and CODELEAN_CODEX_GAP_OS_SANDBOX_TUI_SMOKE_COMMAND when real provider/MCP/plugin marketplace/sandbox environments are available; set CODELEAN_CODEX_GAP_LOCAL_FALLBACK=1 only to explicitly accept a failed or unavailable local/default smoke as local-only completion.
Provider HTTP error bodies are redacted and truncated before surfacing in thrown errors, so API keys, bearer tokens, Gemini keys, and synthetic sk-... values do not leak through diagnostics.
To combine completeness scanning, full verification, and remaining task execution in one loop, run:
npm run completeness:loopThis writes .codelean/completeness-loop.json, scans docs for unmapped incomplete items, runs npm run verify:loop, then executes one remaining:loop iteration. It repeats until verification passes, all mapped remaining tasks complete, and no unmapped incomplete items remain. Use CODELEAN_COMPLETENESS_MAX_ITERATIONS for bounded runs, CODELEAN_COMPLETENESS_INTERVAL_MS for the sleep interval, CODELEAN_COMPLETENESS_STRICT=1 to fail immediately on unmapped findings, CODELEAN_COMPLETENESS_LOCAL_FALLBACK=1 to propagate local-only completion into remaining:loop, and CODELEAN_COMPLETENESS_EXTRA_COMMAND for an additional project-specific completion check.
Success Criteria
- Provider adapters expose a unified chat / stream / tool-call interface.
- Local preprocessing can redact secrets, select relevant files, route tasks, optimize prompts, and summarize failures before remote calls.
- Codelean Codex-compatible mock runtime smoke can execute a tool loop without leaking raw synthetic secrets.
- Real-provider code modification loop is explicitly deferred until endpoint and credentials are available.
- Usage, errors, timeouts, costs, and latency can be tracked uniformly.
Contributing
Pull requests welcome. For major changes, please open an issue first.
License
MIT. See LICENSE.
