mimo2codex Proxy Skill
Skill by ara.so — Codex Skills collection.
Overview
mimo2codex is a local proxy server that translates between OpenAI Codex's Responses API (wire_api = "responses") and upstream LLM providers using Chat Completions API. It enables the latest Codex CLI and desktop app to work with:
- Xiaomi MiMo (V2.5 Pro, V2 Flash, V2 Omni)
- DeepSeek (V4 Pro, V4 Flash, Reasoner)
- Generic OpenAI-compatible providers (Qwen, GLM, Kimi, Ollama, vLLM, LM Studio)
Key features:
- Per-request model routing (send
mimo-v2.5-pro→ MiMo,deepseek-v4-pro→ DeepSeek) - Automatic MiMo
reasoning_contentround-trip handling (v0.2.3+) - Built-in admin webui at
http://127.0.0.1:8788/admin/ - Tool calling, web search, vision (model-dependent)
- sqlite persistence for logs and token stats
Installation
npm (recommended)
npm install -g mimo2codex
curl one-liner
# macOS/Linux
curl -fsSL https://raw.githubusercontent.com/7as0nch/mimo2codex/main/scripts/install.sh | bash
# Windows PowerShell
irm https://raw.githubusercontent.com/7as0nch/mimo2codex/main/scripts/install.ps1 | iex
Git clone (for development)
git clone https://github.com/7as0nch/mimo2codex
cd mimo2codex
npm install
npm run build
npm link # registers `mimo2codex` globally
Requirements: Node.js ≥ 18
Quick Start
1. Get API Keys
- MiMo: platform.xiaomimimo.com → Console → API Keys (
sk-ortp-prefix) - DeepSeek: api-docs.deepseek.com → API Keys (
sk-prefix)
2. Configure Environment Variables
Built-in loader (v0.2.8+, recommended):
# Initialize .env file in ~/.mimo2codex/
mimo2codex init
# Edit ~/.mimo2codex/.env and add your keys:
# MIMO_API_KEY=sk-your-mimo-key
# DS_API_KEY=sk-your-deepseek-key
# Start (auto-loads .env)
mimo2codex
Manual environment variables:
# MiMo only
export MIMO_API_KEY=sk-your-mimo-key
mimo2codex
# DeepSeek only
export DS_API_KEY=sk-your-deepseek-key
mimo2codex --model ds
# Both providers (per-request routing)
export MIMO_API_KEY=sk-your-mimo-key
export DS_API_KEY=sk-your-deepseek-key
mimo2codex
3. Configure Codex
The startup banner prints the required snippets. Copy them to:
macOS/Linux:
~/.codex/auth.json~/.codex/config.toml
Windows:
%USERPROFILE%\.codex\auth.json%USERPROFILE%\.codex\config.toml
Example auth.json:
{
"base_url": "http://127.0.0.1:8788",
"api_key": "fake_api_key"
}
Example config.toml:
wire_api = "responses"
model = "mimo-v2.5-pro"
4. Start Codex
codex
CLI Commands
Core Commands
# Start proxy (MiMo default)
mimo2codex
# Start with DeepSeek as default
mimo2codex --model ds
# Custom port
mimo2codex --port 9000
# Custom data directory
mimo2codex --data-dir /path/to/data
# Disable reasoning display (still round-trips for MiMo)
mimo2codex --no-reasoning
# Disable .env auto-loading
mimo2codex --no-load-env
Utility Commands
# Initialize .env file
mimo2codex init
# Print cc-switch snippets
mimo2codex print-cc-switch
# Show version
mimo2codex --version
# Show help
mimo2codex --help
Configuration
Environment Variables
| Variable | Provider | Required |
|---|---|---|
MIMO_API_KEY |
MiMo | For MiMo models |
DS_API_KEY or DEEPSEEK_API_KEY |
DeepSeek | For DeepSeek models |
QWEN_API_KEY |
Qwen | For Qwen models |
GLM_API_KEY |
GLM | For GLM models |
KIMI_API_KEY |
Kimi | For Kimi models |
OPENAI_API_KEY |
OpenAI | For OpenAI models |
CODEX_HOME |
- | Custom Codex config directory |
CLI Flags
| Flag | Default | Description |
|---|---|---|
--port |
8788 |
Proxy server port |
--host |
127.0.0.1 |
Proxy server host |
--model |
mimo |
Default provider (mimo or ds) |
--data-dir |
~/.mimo2codex |
Data/logs directory |
--no-reasoning |
false |
Hide reasoning from terminal |
--no-load-env |
false |
Disable .env auto-loading |
--log-level |
info |
Log level (debug/info/warn/error) |
Model Routing
Built-in Model IDs
MiMo:
mimo-v2.5-pro(default)mimo-v2-flashmimo-v2.5(vision)mimo-v2-omni(vision)
DeepSeek:
deepseek-v4-pro(default)deepseek-v4-flashdeepseek-chatdeepseek-reasoner
Routing Logic
- Explicit match: If client sends
mimo-v2.5-pro, routes to MiMo (if key configured) - Fallback: If client sends unknown model (e.g.
gpt-4o), routes to--modelprovider's default - Provider disabled: If client sends
qwen3-maxbut noQWEN_API_KEY, falls back to--modelprovider
Example routing with both keys configured:
export MIMO_API_KEY=sk-mimo-key
export DS_API_KEY=sk-deepseek-key
mimo2codex # default fallback: mimo
# In Codex config.toml:
# model = "deepseek-v4-pro" → Routes to DeepSeek
# model = "mimo-v2.5-pro" → Routes to MiMo
# model = "gpt-4o" → Falls back to mimo-v2.5-pro
Admin Web UI
Access at http://127.0.0.1:8788/admin/ (port matches --port)
Features
- Dashboard: Token usage charts, cache hit rates, request stats
- Models: View all available models, test with ⚡Probe button
- Providers: View/edit provider configs from
providers.json - Logs: Browse chat logs with filtering
- Settings: Configure Codex paths, manage aliases
- Codex Enable: One-click write of
auth.jsonandconfig.toml(replaces cc-switch)
Codex Enable (v0.2.6+)
- Open
http://127.0.0.1:8788/admin/ - Click "Codex Enable" tab
- Select model and click "Apply"
- Automatically backs up existing configs (first OpenAI backup preserved permanently)
Runtime override mode: Switch models without restarting Codex (experimental)
Adding Custom Providers
Edit ~/.mimo2codex/providers.json (created after first run):
{
"providers": [
{
"name": "qwen",
"baseUrl": "https://dashscope.aliyuncs.com/compatible-mode/v1",
"apiKeyEnvVar": "QWEN_API_KEY",
"defaultModel": "qwen3-max",
"models": ["qwen3-max", "qwen-turbo"],
"aliases": {
"qwen3": "qwen3-max"
},
"supportsWebSearch": true
}
]
}
Provider schema:
| Field | Type | Description |
|---|---|---|
name |
string | Unique provider identifier |
baseUrl |
string | OpenAI-compatible base URL |
apiKeyEnvVar |
string | Environment variable name |
defaultModel |
string | Model ID for fallback |
models |
string[] | Supported model IDs |
aliases |
object | Model alias mappings |
supportsWebSearch |
boolean | Enable web search tool |
Example: Ollama
{
"name": "ollama",
"baseUrl": "http://localhost:11434/v1",
"apiKeyEnvVar": "OLLAMA_API_KEY",
"defaultModel": "llama3.2",
"models": ["llama3.2", "qwen2.5-coder"],
"aliases": {
"llama": "llama3.2"
},
"supportsWebSearch": false
}
export OLLAMA_API_KEY=ollama # Any non-empty value
mimo2codex
In Codex config.toml:
model = "llama3.2"
Tool Calling
Supported Tools
- Function tools: Custom JSON schemas
- local_shell: Execute shell commands
- MCP tools: Via
namespaceparameter - web_search: MiMo native (auto-enabled for MiMo, skipped for DeepSeek)
Web Search
MiMo: Translates Codex's web_search tool to MiMo's native builtin. Requires plugin activation in MiMo console.
DeepSeek: Web search not supported — tool calls are stripped.
Example Tool Call
// Codex sends:
{
"model": "mimo-v2.5-pro",
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"parameters": {
"type": "object",
"properties": {
"location": { "type": "string" }
}
}
}
}
]
}
// mimo2codex translates to MiMo Chat Completions:
{
"model": "mimo-v2.5-pro",
"tools": [
{
"type": "function",
"function": { ... }
}
]
}
Vision Support
Supported models:
mimo-v2.5(MiMo)mimo-v2-omni(MiMo)
Non-vision models (mimo-v2.5-pro, mimo-v2-flash, DeepSeek models): Images are auto-stripped with placeholder text.
Example Vision Request
In Codex config.toml:
model = "mimo-v2.5"
codex
> Describe this image: /path/to/image.jpg
mimo2codex forwards the image URL/base64 to MiMo's vision model.
MiMo reasoning_content Round-Trip
Problem: MiMo requires every assistant message with tool_calls to echo back its reasoning_content on the next turn. Without this, MiMo returns 400 errors or hallucinates.
Solution: mimo2codex ≥ 0.2.3 automatically stores and re-inserts reasoning_content on subsequent turns.
Example
// Turn 1: MiMo returns
{
"role": "assistant",
"content": "",
"tool_calls": [...],
"reasoning_content": "I need to search the web"
}
// Turn 2: mimo2codex auto-injects reasoning_content
{
"role": "assistant",
"content": "",
"tool_calls": [...],
"reasoning_content": "I need to search the web" // ← auto-added
}
Flag: --no-reasoning hides reasoning from terminal but preserves round-trip.
Common Patterns
Multi-Provider Setup
# .env file (~/.mimo2codex/.env)
MIMO_API_KEY=sk-mimo-key
DS_API_KEY=sk-deepseek-key
QWEN_API_KEY=sk-qwen-key
# Start proxy
mimo2codex
# Codex config.toml - switch models dynamically:
# model = "mimo-v2.5-pro"
# model = "deepseek-v4-pro"
# model = "qwen3-max"
Testing Model Connections
Use the admin UI's ⚡Probe button:
- Open
http://127.0.0.1:8788/admin/ - Go to "Codex Enable" or "Models" tab
- Click ⚡Probe next to any model
- Validates key, baseUrl, and model ID end-to-end
Token Usage Tracking
# Start proxy
mimo2codex
# View stats at http://127.0.0.1:8788/admin/
# - Dashboard: Charts with cache hit overlay
# - Green bars: Cache hits
# - Gray ghosts: Prompt token totals
# - Window-wide hit rate summary
Custom Codex Directory
# Via environment variable
export CODEX_HOME=/custom/path
mimo2codex
# Via admin UI settings
# Navigate to Settings → Codex Path
Troubleshooting
400 Errors with MiMo (Tool Calls)
Symptom: MiMo returns 400 or agent rambles instead of calling tools.
Cause: Missing reasoning_content round-trip.
Fix: Upgrade to mimo2codex ≥ 0.2.3
npm update -g mimo2codex
Provider Not Routing
Check:
- API key is set:
echo $MIMO_API_KEY - Provider is enabled in startup banner
- Model ID matches provider's catalog (case-sensitive)
# Debug with log level
mimo2codex --log-level debug
Port Already in Use
# Change port
mimo2codex --port 9000
# Update auth.json:
# "base_url": "http://127.0.0.1:9000"
Web Search Not Working
MiMo: Activate the web search plugin in MiMo Console → Plugins.
DeepSeek: Not supported (tool calls are stripped).
Image Generation (/hatch)
Codex's /hatch command calls OpenAI's image_gen client-side — mimo2codex cannot intercept this. Workaround: Use mimoskill/ (see project README).
.env Not Loading
# Verify file location
ls ~/.mimo2codex/.env
# Check file syntax (no spaces around =)
cat ~/.mimo2codex/.env
# Disable auto-loading if needed
mimo2codex --no-load-env
Windows PowerShell Execution Policy
If irm | iex fails:
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned
Integration with cc-switch
Generate cc-switch snippets:
mimo2codex print-cc-switch
Output example:
[mimo-v2.5-pro]
model = "mimo-v2.5-pro"
wire_api = "responses"
base_url = "http://127.0.0.1:8788"
api_key = "fake_api_key"
Copy to cc-switch config and use cc mimo-v2.5-pro to switch.
Data Persistence
Default location: ~/.mimo2codex/data.db (sqlite)
Stored data:
- Chat logs (request/response pairs)
- Token usage stats
- Cache hit metrics
- Model mappings
Custom location:
mimo2codex --data-dir /custom/path
TypeScript API (for embedding)
import { startServer } from 'mimo2codex';
const server = await startServer({
port: 8788,
host: '127.0.0.1',
dataDir: '~/.mimo2codex',
logLevel: 'info',
noReasoning: false,
loadEnv: true
});
// Server running at http://127.0.0.1:8788