Coding agents
Point your coding agent at caft. Claude Code and Codex go through a local router.
| Setting | Value |
|---|---|
| API format | OpenAI Chat Completions |
| Base URL | https://api.caft.dev/v1 |
| API key | Your caft API key |
| Model ID | glm-5.3-flash |
Use the base URL, not the full /chat/completions URL, unless a section says otherwise. Each example reads the key from CAFT_API_KEY. Setting names can differ between client versions.
OpenCode
Merge this into ~/.config/opencode/opencode.json, run opencode models caft to check that caft/glm-5.3-flash is listed, then start OpenCode.
{
"$schema": "https://opencode.ai/config.json",
"model": "caft/glm-5.3-flash",
"small_model": "caft/glm-5.3-flash",
"provider": {
"caft": {
"npm": "@ai-sdk/openai-compatible",
"name": "caft",
"options": {
"baseURL": "https://api.caft.dev/v1",
"apiKey": "{env:CAFT_API_KEY}"
},
"models": {
"glm-5.3-flash": {
"name": "GLM 5.3 Flash"
}
}
}
}
}The caft/ prefix picks the provider inside OpenCode; caft receives glm-5.3-flash.
OMP
OMP (Oh My Pi) is separate from pi. Merge this into ~/.omp/agent/models.yml, then run omp --model caft/glm-5.3-flash.
providers:
caft:
baseUrl: https://api.caft.dev/v1
api: openai-completions
apiKey: CAFT_API_KEY
authHeader: true
models:
- id: glm-5.3-flash
name: GLM 5.3 Flash (caft)apiKey names the environment variable; authHeader: true sends it as a bearer token.
Kilo
- Open Settings → Providers → Custom provider.
- Provider ID
caft, display namecaft, Provider API OpenAI Compatible (not OpenAI Responses). - Enter the base URL and your key, add the model, save, and select it.
0, Kilo turns off automatic context compaction.Cline
In Cline's settings choose OpenAI Compatible, enter the base URL, your key, and model glm-5.3-flash, then save.
pi
Add this provider to ~/.pi/agent/models.json, start pi, and pick GLM 5.3 Flash (caft) in /model. The $ tells pi to read the environment variable.
{
"providers": {
"caft": {
"baseUrl": "https://api.caft.dev/v1",
"api": "openai-completions",
"apiKey": "$CAFT_API_KEY",
"models": [
{
"id": "glm-5.3-flash",
"name": "GLM 5.3 Flash (caft)"
}
]
}
}
}Hermes
- Outside a chat, run
hermes model. (/modelinside a chat only switches between providers you already added.) - Choose Custom endpoint (self-hosted / VLLM / etc.).
- Enter the base URL, your key, and model
glm-5.3-flash. API compatibility: Chat Completions or Auto-detect. - If asked for a context length, use the value on the Models page. Start a new session.
OpenClaw
Merge this into ~/.openclaw/openclaw.json and start a new session. If OpenClaw runs as a background service, give that service CAFT_API_KEY too.
{
"agents": {
"defaults": {
"model": {
"primary": "caft/glm-5.3-flash"
}
}
},
"models": {
"mode": "merge",
"providers": {
"caft": {
"baseUrl": "https://api.caft.dev/v1",
"apiKey": "${CAFT_API_KEY}",
"api": "openai-completions",
"models": [
{
"id": "glm-5.3-flash",
"name": "GLM 5.3 Flash (caft)"
}
]
}
}
}
}Aider
export OPENAI_API_BASE=https://api.caft.dev/v1 export OPENAI_API_KEY="$CAFT_API_KEY" aider --model openai/glm-5.3-flash --no-show-model-warnings
Keep the openai/ prefix; it selects Aider's OpenAI-compatible client. Ignore the model names Aider suggests.
Goose
Save this as ~/.config/goose/custom_providers/caft.json. Goose needs the full /chat/completions URL.
{
"name": "caft",
"engine": "openai",
"display_name": "caft",
"api_key_env": "CAFT_API_KEY",
"base_url": "https://api.caft.dev/v1/chat/completions",
"models": [
{
"name": "glm-5.3-flash"
}
],
"requires_auth": true,
"supports_streaming": true
}export GOOSE_PROVIDER=caft export GOOSE_MODEL=glm-5.3-flash goose run --with-builtin developer -t "Say hello."
The developer extension gives Goose its file and shell tools.
Crush
Add this to ~/.config/crush/crushrc, then select caft/glm-5.3-flash. Use --type openai-compat; openai is reserved for OpenAI itself.
provider add caft --type openai-compat \ --name "caft" \ --base-url "https://api.caft.dev/v1" \ --api-key "$CAFT_API_KEY" model add caft/glm-5.3-flash --name "GLM 5.3 Flash"
Qwen Code
export OPENAI_API_KEY="$CAFT_API_KEY" export OPENAI_BASE_URL=https://api.caft.dev/v1 export OPENAI_MODEL=glm-5.3-flash qwen --auth-type openai
Use --auth-type openai (Chat Completions), not openai-responses.
Continue
Works in the editor extension and the cn CLI. Put the key in ~/.continue/.env (the extension does not read shell variables), then merge the model into ~/.continue/config.yaml.
CAFT_API_KEY=YOUR_CAFT_API_KEY
name: caft
version: 1.0.0
schema: v1
models:
- name: GLM 5.3 Flash (caft)
provider: openai
model: glm-5.3-flash
apiBase: https://api.caft.dev/v1
apiKey: ${{ secrets.CAFT_API_KEY }}
roles:
- chat
- edit
- apply
capabilities:
- tool_useZCode
Add caft as a custom provider; the built-in Z.ai provider connects to Z.ai.
- Settings → Model settings → Add provider → Create custom provider.
- Base URL as above, API format Chat completions, your key.
- Add model
glm-5.3-flashwith Smart configuration on. - In Advanced settings, clear Image, Video and PDF, and replace the Reasoning parameter mapping with:
{
"reasoning_effort": reasoningLevel == "disabled" ? "none" : reasoningLevel == "enabled" ? "high" : reasoningLevel
}The default mapping adds thinking, enable_thinking and reasoning fields that can be rejected with HTTP 400. This one sends only reasoning_effort.
Claude Code
Claude Code speaks Anthropic Messages. Claude Code Router (CCR) translates it to Chat Completions on your machine.
~/.claude/settings.json and ~/.codex/config.toml. Back them up first and restore them after you stop CCR.npm install -g @musistudio/claude-code-router(Node.js 22+).- Save this as
~/.claude-code-router/config.json. CCR reads it only on first start.
{
"HOST": "127.0.0.1",
"PORT": 3456,
"APIKEY": "your-local-ccr-key",
"Providers": [
{
"name": "caft",
"api_base_url": "https://api.caft.dev/v1/chat/completions",
"api_key": "$CAFT_API_KEY",
"models": [
"glm-5.3-flash"
]
}
]
}ccr start export ANTHROPIC_BASE_URL=http://127.0.0.1:3456 export ANTHROPIC_AUTH_TOKEN=your-local-ccr-key export ANTHROPIC_MODEL=caft/glm-5.3-flash export ANTHROPIC_DEFAULT_HAIKU_MODEL=caft/glm-5.3-flash export ANTHROPIC_DEFAULT_SONNET_MODEL=caft/glm-5.3-flash export ANTHROPIC_DEFAULT_OPUS_MODEL=caft/glm-5.3-flash claude
APIKEY is a local secret between Claude Code and CCR, not your caft key. Without the model variables, Claude Code asks for Claude model names and CCR returns 400.
Codex
Codex speaks the Responses API. A local LiteLLM proxy translates it to Chat Completions.
- Set
CAFT_API_KEY, andLITELLM_MASTER_KEYto a separate secret starting withsk-. - Save as
config.yamland runlitellm --config config.yaml --host 127.0.0.1 --port 4000.
model_list:
- model_name: caft-flash
litellm_params:
model: openai/glm-5.3-flash
api_base: https://api.caft.dev/v1
api_key: os.environ/CAFT_API_KEY
use_chat_completions_api: true
additional_drop_params: ["web_search_options"]
general_settings:
master_key: os.environ/LITELLM_MASTER_KEY- Merge into
~/.codex/config.toml, setLITELLM_API_KEYto the master key, and start Codex.
model = "caft-flash" model_provider = "caft-litellm" [model_providers.caft-litellm] name = "caft via LiteLLM" base_url = "http://127.0.0.1:4000/v1" env_key = "LITELLM_API_KEY" wire_api = "responses"
use_chat_completions_api makes LiteLLM call Chat Completions. The drop rule removes web_search_options, which Codex's web search adds; or set web_search = "disabled". A "model metadata not found" warning is harmless. CCR also serves /v1/responses if you already run it.
Check the connection
Send a short message, then ask the agent to read a small file in a test folder. A text reply alone doesn't prove tool calls work. If either fails, see Troubleshooting.