~/.xynthis by default. Set XYNTHIS_HOME to relocate the whole data directory with one lever; every path below resolves through it.
Directory layout
bmc/, alongside the memory store itself, the brain also keeps
identity.ed25519 (the local signing identity for witnessed memory,
mode 0600) and witness.log (the append-only Merkle log of confirmed
facts).
The brain is the only process that writes bmc/. Everything else (the CLI, the daemon, the app, MCP clients) goes through brain.sock.
config.toml
Two sections:[models] selects what runs, [providers.<name>] defines how to reach each backend. Missing files are replaced by defaults, so a brand-new machine works without any config.
[models]
| Field | Type | Default | Meaning |
|---|---|---|---|
active | string | "echo" | Active target: "<provider>/<model>", or "<provider>" to use its default_model |
fast | string | unset | Optional cheaper target the agent uses for easy turns (post-tool summaries, short acknowledgements). Same format as active. Unset means every turn goes to active |
[providers.<name>]
| Field | Type | Default | Meaning |
|---|---|---|---|
kind | string | required | One of anthropic-messages, openai-chat, subprocess, codex-oauth, claude-oauth, xynthis-llm, echo |
base_url | string | unset | HTTP backends: for openai-chat, the root without /chat/completions; for anthropic-messages, the full /messages endpoint |
default_model | string | unset | Model id used when the target doesn’t name one |
command | string | unset | subprocess only: the CLI to spawn (e.g. "claude") |
args | string array | [] | subprocess only: fixed arguments |
model_arg | string | unset | subprocess only: flag used to pass the model name (e.g. "--model") |
lite | bool | false | Lite mode for small local models: plain chat with no tool schemas, a short system prompt, and no pre-turn memory injection. Set this for models that can’t tool-call |
launch_command | string | unset | Local providers only: shell command that starts the provider’s server when it isn’t running |
kind values map to how xynthis reaches the backend: openai-chat covers OpenAI, Ollama, llama.cpp, Groq, DeepSeek, Gemini, xAI, LM Studio, and anything else implementing the standard. subprocess pipes through an external CLI like claude or codex using that CLI’s own auth. codex-oauth and claude-oauth call the respective backends directly with tokens from an existing Codex or Claude Code login. xynthis-llm targets the local model server on http://127.0.0.1:8080/v1. echo is a deterministic network-free fallback.
Fourteen providers are pre-registered on first save: echo, anthropic, openai, ollama, xynthis-llm, llamacpp, groq, deepseek, gemini, xai, claude-code, codex, codex-oauth, claude-oauth. xynthis models list --all shows them.
API keys
Keys never live inconfig.toml. Lookup order per provider: the macOS Keychain (service com.xynthis.app, account <provider>-api-key; this is where the app’s Settings writes), then ~/.xynthis/auth.json (written by xynthis login and xynthis auth apply, mode 0600).
Environment variables
| Variable | Default | Effect |
|---|---|---|
XYNTHIS_HOME | ~/.xynthis | Relocate the entire data directory. Blank values are treated as unset |
XYNTHIS_BRAIN_SOCKET | $XYNTHIS_HOME/brain.sock | Override the brain socket path |
XYNTHIS_LLM_OVERRIDE | unset | Force an LLM target for one invocation (same as the global --llm flag); does not write config |
XYNTHIS_NO_APP | unset | 1 stops xynthis chat from launching the macOS app |
XYNTHIS_API_KEY | unset | Non-interactive key for xynthis models add |
XYNTHIS_SKILLS_DIR | ~/.xynthis/skills | Override the skill library root |
XYNTHIS_CORTEX | off | on injects the cortex bulletin into the system prompt |
XYNTHIS_CORTEX_REFRESH_SECS | 900 | Bulletin staleness threshold in seconds |
XYNTHIS_LEXICAL_FLOOR | on | 0 disables the lexical floor in memory retrieval (re-scoring stage that guarantees strong keyword matches rank) |
XYNTHIS_LLM_PORT | 8080 | Model server listen port |
XYNTHIS_LLM_BIND | 127.0.0.1 | Model server bind address. 0.0.0.0 listens on all interfaces; only do that behind a tunnel or VPN |
XYNTHIS_LLM_SMALL | unset | Set to serve the smaller backbone preset |
XYNTHIS_LLM_MODEL_ID | xynthis-local | Model id advertised on /v1/models |
XYNTHIS_LLM_TRAIN | unset | First-run seed only: if set (any value) when ~/.xynthis/llm/train_config.json does not exist, the model server creates that file with training enabled. Once the file exists, it governs and this variable is ignored; toggle training with the MCP llm_train_set tool or the app |
XYNTHIS_JSPACE | off | Set to capture workspace readouts; responses carry xynthis_jspace |
XYNTHIS_JSPACE_TOPK | 5 | Concepts captured per generated token (minimum 1) |
XYNTHIS_JSPACE_TO_BRAIN | off | Also submit each reply’s readout summary to the brain as short-lived working-memory context. Requires XYNTHIS_JSPACE; inert without it |