evocode is a local protocol bridge for Codex-style coding workflows. The codebase focuses on translating between OpenAI Responses-style requests, OpenAI Chat Completions, and Anthropic Messages.
This repository is under active development. Do not treat planned features as available until they are listed under "Current Scope".
- Local HTTP bridge on
http://127.0.0.1:17761. - OpenAI Chat Completions endpoint:
POST /v1/chat/completions. - Anthropic Messages endpoint:
POST /v1/messages. - OpenAI Responses-style endpoints:
POST /responsesandPOST /v1/responses. - Core request/response translation between Chat Completions, Anthropic Messages, and Responses.
- SSE translation for Chat Completions, Anthropic Messages, and Responses, including split-frame buffering, reasoning, usage, error, and function-call events.
- Basic tool/function calling translation for OpenAI
tool_callsand Anthropictool_use. and MCP support. - OpenAI
response_formatmapping forjson_objectandjson_schema, including schema normalization and tuple-schema conversion for provider compatibility. - Simple upstream provider selection through
providerand[providers.<name>].
Default config path:
~/.evocode/config.json
OpenAI Chat Completions upstream example:
{
"provider": "openai_chat",
"providers": {
"openai_chat": {
"wire_api": "chat_completions",
"base_url": "https://api.openai.com/v1",
"models": [{"name": "gpt-4.1", "context_window": 256000}],
"api_key": "Bearer YOUR_API_KEY",
"api_key_header": "Authorization"
}
}
}Anthropic-compatible upstream example:
{
"provider": "minimax",
"providers": {
"minimax": {
"wire_api": "anthropic",
"base_url": "https://api.minimaxi.com/anthropic",
"models": [{"name": "MiniMax-M2.7", "context_window": 256000, "auto_compact_token_limit": 220000}],
"api_key": "YOUR_API_KEY",
"api_key_header": "X-Api-Key"
}
}
}The legacy misspelled path ~/.evocde/config.json is also accepted if it
already exists.
cargo run --release -p evocode-cli -- serve # start bridge only
cargo run --release -p evocode-cli -- config # print config helpThis project is the core protocol translation engine. It does not manage any
specific agent's configuration (such as Codex CLI or Claude Code). Agent-specific
setup logic (e.g. writing to ~/.codex/config.toml) is handled by the
evocode-tauri desktop application.
- evocode-proto — HTTP server and protocol translation between Anthropic Messages, OpenAI Chat Completions, and OpenAI Responses.
- evocode-config — Configuration load/save for
~/.evocode/config.json. - evocode-cli — CLI entry point with
serveandconfigcommands.
evocode implements multiple safeguards to prevent the agent session from terminating prematurely — a common failure mode when bridging non-Responses protocols to Codex CLI.
When the bridge converts an upstream response to Responses format, it sets
end_turn: false if any of the following conditions are met:
- Pending tool calls — the response contains
tool_use/tool_callsblocks that Codex must execute before the model can continue. - Truncated output — the upstream stopped due to
max_tokensrather than completing naturally. - Reasoning-only response — the model produced only
thinking/redacted_thinkingblocks with no visible text or tool calls, indicating it needs another chance to produce actionable output.
Without these conditions, end_turn is omitted (equivalent to true),
allowing normal task completion.
Some upstream models emit extended reasoning (thinking) without any visible
text or tool calls. Codex interprets an empty output_text as a completed turn
and emits task_complete. To prevent this:
- When a response contains only reasoning items, the bridge mirrors the
reasoning content into a synthetic
messageitem so Codex has visible text to render. - The original
reasoningitem is preserved — this is not a rewrite. - The
end_turnis forced tofalse, giving the model another opportunity to produce concrete output.
The most advanced safeguard: a lightweight session tracker that analyzes conversation structure across turns.
Heuristic: if the incoming request contains tool result items that appear
after the last assistant message (meaning tools were just executed and the
model hasn't yet responded to their output), and the model's response then
completes with no text output and no new tool calls, the bridge overrides
end_turn to false to keep the turn alive. If the model already produced
visible text, it has consumed the tool results — no override occurs.
This catches cases where the upstream model receives tool output but prematurely declares the task done instead of calling the next tool.
Why it doesn't loop: the check only triggers when tool results are structurally positioned after the last assistant message in the conversation history. Once the model has produced any response — even a simple "done" — that response becomes the new last assistant message, and the tool results are now before it, preventing re-triggering on the next iteration.
To verify these safeguards are working, search the bridge logs for:
completion validation: overriding end_turn=false— session-aware validation fired, preventing premature termination.task_complete/end_turnrelated diagnostic messages in theevocode_proto::translatelog target.
Requirements:
- Rust 1.85 or newer, because this workspace uses Rust edition 2024.
cargo install --git https://github.com/evolutions-code/evocode --locked evocode-cli