Configuration
APX uses two configuration layers — global (machine-local, never committed) and project-local (committed to the repo, no secrets). Commands at both layers use dotted-key syntax and are JSON-aware.
Global config — ~/.apx/config.json
Section titled “Global config — ~/.apx/config.json”The global config file is created on first run. It holds engine credentials, daemon settings, the super-agent model, voice, memory, and Telegram options.
Top-level structure
Section titled “Top-level structure”{ "port": 7430, "host": "127.0.0.1", "log_level": "info", "user": { "language": "en", "locale": "", "timezone": "" }, "super_agent": { ... }, "engines": { ... }, "memory": { ... }, "voice": { ... }, "telegram": { ... }, "projects": []}Engines
Section titled “Engines”API keys and base URLs for every supported LLM provider:
{ "engines": { "anthropic": { "api_key": "sk-ant-..." }, "openai": { "api_key": "sk-...", "base_url": "https://api.openai.com/v1" }, "groq": { "api_key": "...", "base_url": "https://api.groq.com/openai/v1" }, "cerebras": { "api_key": "...", "base_url": "https://api.cerebras.ai/v1" }, "openrouter": { "api_key": "...", "base_url": "https://openrouter.ai/api/v1" }, "gemini": { "api_key": "..." }, "ollama": { "base_url": "http://localhost:11434" } }}Ollama model residency
Section titled “Ollama model residency”APX sends keep_alive: -1 with every Ollama chat request. Once APX loads a model, Ollama keeps it in memory, so later turns avoid a cold model load. Stop it explicitly with ollama stop <model> or restart Ollama to free that memory.
This applies only to models APX calls. A host without enough available RAM or VRAM can still make Ollama unload an idle model to load another one.
Per-engine egress proxy
Section titled “Per-engine egress proxy”Any engine accepts a proxy, and only that engine’s traffic goes through it:
{ "engines": { "zen": { "proxy": "http://127.0.0.1:8888" } }}Everything else — Telegram, the other providers, the vault, the update check —
keeps using the normal route. This is deliberately narrower than HTTPS_PROXY
or Node’s --use-env-proxy, which are process-wide.
Because the tunnel lives behind the proxy’s address rather than in this
machine’s routing table, it does not fight Tailscale the way a VPN client does.
A ready-made container is in examples/egress-proxy/.
A proxy that is configured but unreachable fails the call rather than falling back to the direct route: a silent fallback would send the traffic exactly where the proxy was set up to avoid.
Super-agent
Section titled “Super-agent”{ "super_agent": { "enabled": false, "name": "apx", "model": "anthropic:claude-sonnet-4-5", "permission_mode": "automatico", "allowed_tools": [], "model_fallback": { "enabled": true, "models": [ "openrouter:meta-llama/llama-3.3-70b-instruct", "groq:llama-3.3-70b-versatile" ], "health_timeout_ms": 800 } }}permission_mode controls which tools the super-agent can run without asking:
| Mode | Behavior |
|---|---|
total | All tools allowed, no confirmation |
automatico | APX decides automatically based on safety heuristics |
permiso | Only tools listed in allowed_tools; everything else asks |
The identity file — ~/.apx/identity.json
Section titled “The identity file — ~/.apx/identity.json”This file sets the assistant’s user-facing name and personality:
{ "name": "APX", "persona": ""}Change name to give your assistant a different display name across all surfaces (Telegram,
Desktop, Web). The technical config key super_agent.name is separate — identity.json is
what end users see.
Project config — ~/.apx/projects/<apx_id>/config.json
Section titled “Project config — ~/.apx/projects/<apx_id>/config.json”Project-level overrides take priority over the global config, for that project only. The file
lives in the project’s runtime storage, not in its repo: it used to be .apc/config.json,
which is committed, so a mistyped scope could stage an api key for the next push. Keys are safe
here. Projects configured before the move are migrated the first time the daemon reads them —
the old file is moved, not copied.
.apc/ keeps the portable half — project.json, agents, skills, organization — and the daemon
refuses to write anything credential-shaped into it.
{ "super_agent": { "model": "groq:llama-3.3-70b-versatile", "permission_mode": "total" }, "telegram": { "route_to_agent": "reviewer" }}Config commands
Section titled “Config commands”View config
Section titled “View config”apx config reaches both layers. It edits the project layer by default and the global
layer with --global (or --scope global) — so the flag decides which file you are touching.
apx config show --global # ~/.apx/config.json, secrets redactedapx config show --global | jq .super_agent # JSON on stdout, header on stderrapx config show # this project's own values + the effective mergeapx config show --effective # just the merged effective configapx config show --only-overrides # just the project overrides
apx project config show my-app # same, for a project you are not standing inapx project config show my-app --key super_agent.model$ apx config show --global { "port": 7430, "host": "127.0.0.1", "log_level": "info", "super_agent": { "enabled": true, "model": "anthropic:claude-sonnet-4-5", "permission_mode": "automatico" }, "engines": { "anthropic": { "api_key": "sk-ant-••••a91f" }, "openai": { "api_key": "sk-••••7c2d" }, "ollama": { "base_url": "http://localhost:11434" } }, "telegram": { "enabled": true, "channels": [ { "name": "default" } ] } }
Set and unset values
Section titled “Set and unset values”Values are JSON-aware — booleans, numbers, and arrays are parsed correctly:
Global settings — credentials, the daemon, voice, and the super-agent defaults — need
--global. The write goes through the daemon, which reloads the new value immediately:
apx config set --global super_agent.enabled trueapx config set --global super_agent.model "anthropic:claude-sonnet-4-5"apx config set --global engines.openai.api_key "sk-..."apx config unset --global super_agent.model # remove key, fall back to defaultProject overrides are the default, so they need no flag. Inside the project:
apx config set super_agent.model groq:llama-3.3-70b-versatileapx config set telegram.route_to_agent reviewerapx config unset super_agent.modelFrom anywhere, naming the project:
apx project config set my-app super_agent.model groq:llama-3.3-70b-versatileapx project config set my-app telegram.route_to_agent reviewerapx project config unset my-app super_agent.modelapx project config edit my-app # open in $EDITORModel commands
Section titled “Model commands”apx model manages the super-agent’s model fallback router — the ordered list of providers APX
tries in sequence when the primary model is unavailable:
apx model status # probe all providers, show active modelapx model order ollama openrouter groq # set fallback orderapx model key groq sk-xxxx # save an API keyapx model set openrouter meta-llama/llama-3.3-70b-instruct # pin a model for one providerapx model test # which model would be picked right now?apx model enable # enable the fallback routerapx model disable # disable (primary only, no fallback)$ apx model status Model router primary: anthropic:claude-sonnet-4-5 fallback: on order: anthropic → openrouter → groq → ollama active: anthropic:claude-sonnet-4-5 ✓ anthropic claude-sonnet-4-5 up key:config ✓ openrouter meta-llama/llama-3.3-70b up key:config ✗ groq llama-3.3-70b-versatile down (no key) ✓ ollama llama3.2:3b up key:config Keys → ~/.apx/config.json engines.{groq,openrouter}.api_key Or env: GROQ_API_KEY, OPENROUTER_API_KEY
Permission commands
Section titled “Permission commands”apx permission is a shorthand for reading and writing super_agent.permission_mode:
apx permission show # print current modeapx permission set total # allow all toolsapx permission set automatico # APX decidesapx permission set permiso # only allowed_tools- Projects — per-project config and where it lives.
- Installation — where
~/.apx/is first created.