Configuration
Aethon stores user settings in ~/.aethon/config.toml. The Settings panel (Cmd+,) writes the same file: power users can edit it directly, or click Open config.toml in Settings to reveal it in your editor.
This page is task-focused. Each section below is a copy-paste block for a common setup. The full keys-and-defaults schema lives in reference/config-reference.
File layout
# ~/.aethon/config.toml (managed by Aethon Settings).
[ui]
theme = "ember"
font_size = 14
notify_on_completion = true
notify_min_duration_seconds = 8
thinking_visibility = "hide"
tool_calls_visibility = "hide"
[agent]
model = "anthropic/claude-sonnet-4-6"
# provider_timeout_seconds = 120 # optional; omit to keep pi's default
bash_timeout_floor_seconds = 300
subagent_timeout_seconds = 300
idle_retire_minutes = 15
# thinking_level = "medium" # off|minimal|low|medium|high|xhigh|max|ultra; unset = provider default
codex_fast_mode = false
[shell]
default_share_mode = "private"
auto_restart_agent = true
default_command = "" # empty = $SHELL
default_args = []
inherit_env = true
prompt_before_close = true
[voice]
toggle_hotkey = "mod+shift+m"
# hold_hotkey defaults to "AltRight" on macOS and unset elsewhere.
speak_agent_replies = false
speak_max_chars = 600
conversation_continuous = false
[mcp]
enabled = true
project_configs = "require-approval" # auto-load | require-approval | never
[startup]
auto_approve = false
[extensions]
state_warn_kb = 64
state_hard_kb = 512
[updates]
channel = "stable"
disable_auto_check = false
[devshell]
enabled = "auto"
mode = "auto"
cache_ttl_hours = 720
refresh_on_lockfile_change = true
[server]
enabled = true
[guardrails]
# soft_prompt_anchor = "Prefer small, reviewable diffs."
hard_enforce_project_root = falseEvery section is optional, and so is every key. Unset values use the defaults shown above. Aethon never crashes on a bad TOML file: it logs a parse error and falls back to defaults, clamps out-of-range numbers, and falls back unknown enum values to safe defaults.
The .aethon directory
~/.aethon/ holds everything Aethon persists per user:
~/.aethon/
├── config.toml # this file
├── agents/ # user-scope subagent definitions (<name>.md)
├── extensions/ # installed extension packages
├── auth/ # auth-profile metadata + per-profile credentials
├── logs/ # daily-rotating Rust + bridge logs
├── state/aethon.sqlite3 # canonical app state, projects, sessions, caches
├── projects/<projectId>/ # Aethon-managed per-project data
├── state.json # debug/runtime snapshot export
├── system-prompt.md # optional full system-prompt override
├── system-prompt-append.md# optional system-prompt append
├── devshell-cache/ # resolved Nix devshell snapshots
└── updates/ # update backups for boot-probation rollbackThe hand-editable ones are config.toml, the subagent definitions under agents/ (see Agents), and the system-prompt override / append files (see Agents). The rest are managed by Aethon. Pi may also write its own session files in pi's default session directory so a conversation can be picked up from pi later, but Aethon restores its application state from SQLite.
Set a theme
[ui]
theme = "nocturne"Built-ins: ember, paper, aether, brink, daylight, mist, nocturne (plus signature, a back-compat alias for aether). An extension can register more; any registered id is valid here. An unknown id falls back to ember. You can also switch live with /theme nocturne. See Themes for registering custom themes.
font_size is the terminal and editor size in pixels, clamped to 10-24:
[ui]
font_size = 16Tune transcript density
Hide or group the model's thinking blocks and tool-call cards by default:
[ui]
thinking_visibility = "collapse" # show | collapse | hide
tool_calls_visibility = "group-turn" # show | group-turn | group-run | group-block | hideBoth default to hide when unset, so a fresh install opens with a clean transcript. Both are per-tab overridable at runtime via the composer visibility pills; these keys only set the global default for new tabs. The full grouping enum is in the config reference.
Set a default model for new tabs
[agent]
model = "anthropic/claude-sonnet-4-6"The format is provider/model-id (anthropic/claude-sonnet-4-6, openai/gpt-4o, ollama/llama3.3). This is the model new tabs open with; /model changes the active tab and persists the choice. Provider credentials come from the shell environment, not this file. See Models and providers.
Tune agent and provider timeouts
The [agent] timeout knobs give long-running work more headroom. All are in seconds and apply on the next agent spawn.
[agent]
# Only set this if a provider times out on legitimately long turns.
provider_timeout_seconds = 300 # omit entirely to keep pi's own default
# Raise the floor under model-supplied bash timeouts (default 300 = 5 min).
bash_timeout_floor_seconds = 600
# Default ceiling for inline subagents (default 300). Subagent frontmatter
# can override this per invocation.
subagent_timeout_seconds = 900subagent_timeout_seconds is the floor of a precedence chain: a subagent's frontmatter timeout wins, then AETHON_SUBAGENT_TIMEOUT_SECONDS, then this key, then the built-in 300. See Agents for the full precedence and frontmatter.
Keep agent workers warm (or reclaim memory)
[agent]
# Retire an idle per-tab worker after 30 minutes instead of the default 15.
idle_retire_minutes = 30
# Or never retire (workers stay resident; faster follow-ups, more memory):
# idle_retire_minutes = 0A retired worker respawns lazily from its persisted session on the next message. 0 disables retirement entirely (clamped 0-1440).
Quieter completion notifications
[ui]
notify_on_completion = true
notify_min_duration_seconds = 30 # only ping for turns 30s or longerSet notify_on_completion = false to silence completion alerts, or raise notify_min_duration_seconds (0-3600) so only genuinely long turns interrupt you. When a turn ends, Aethon shows an in-app toast if the window is focused but you are on a different tab, and a native OS notification if the window is unfocused. Nothing fires if the finishing tab is already active.
Hermetic shells
[shell]
default_command = "/bin/zsh"
default_args = ["-l"]
inherit_env = false # do not leak Aethon's PATH/locale into shell tabsWith inherit_env = false, new shell tabs start without Aethon's environment (the PTY still gets TERM=xterm-256color). default_command overrides the spawned program; empty or omitted falls back to $SHELL. default_args are appended after the platform default. See Shells & share modes for share-mode semantics.
Tab shortcuts (Cmd+T is focus-aware)
Cmd+T is strictly focus-aware and is not configurable: it opens an agent tab when focus is outside the bottom terminal panel, and a shell sub-tab when focus is inside it. Cmd+Shift+T always opens a shell sub-tab. See Agent tabs and Shells & share modes.
Deprecated
[shortcuts] new_tab_kind is a vestigial no-op. It is still parsed for back-compat but has no runtime effect — nothing reads it. Remove it from your config; the focus-aware routing above is the only behavior.
Set the default reasoning effort
[agent]
thinking_level = "medium" # off | minimal | low | medium | high | xhigh | max | ultra
codex_fast_mode = false # Codex models: trade reasoning depth for speedthinking_level is the default reasoning effort for new tabs; leave it unset to use each provider's own default. A tab can override it per session from the model picker's reasoning selector (see Agents). codex_fast_mode only affects Codex-family models.
GPT-6 Astra and GPT-5.6 Sol and Terra expose Light, Medium, High, Extra High, Max, and Ultra. Luna stops at Max. Ultra is an orchestration mode: Aethon sends the distinct Codex effort and proactively uses available subagents for meaningful parallel work. Older models retain their provider-defined effort sets, so existing off, minimal, and GPT-5.5 selections continue to work.
Enable or tune the Nix devshell wrap
Aethon can auto-detect a project's Nix devshell (direnv, flake, or shell.nix) and apply its environment to both interactive shell tabs and the agent's pi bash tool.
[devshell]
enabled = "auto" # auto | always | never
mode = "auto" # auto | direnv | nix | nix-shell
cache_ttl_hours = 720
refresh_on_lockfile_change = trueenabled = "never"disables wrapping globally.enabled = "always"forces detection and fails loud if a marker resolves but the resolver errors.modepins a single resolver kind;autofollows precedence (direnv, then flake, thenshell.nix).
To pin or disable per project, drop a devshell.toml in the repo:
# <project-root>/.aethon/devshell.toml
[devshell]
enabled = "never" # never wrap this repo
# mode = "nix" # or pin the flake resolver if enabledOnly enabled and mode are per-project-overridable; cache_ttl_hours and refresh_on_lockfile_change stay global.
WARNING
A malformed per-project devshell.toml is silently ignored, so a typo never blocks a shell from opening. It also means a typo is silently ineffective: confirm the override took with the ⬡ status-bar chip or AETHON_LOG=aethon::devshell=debug.
Track nightly builds
[updates]
channel = "nightly" # stable | nightly
disable_auto_check = falsestable tracks the latest release; nightly follows the nightly tag for in-development builds. Set disable_auto_check = true to stop background checks; the manual "Check for Updates" menu item still works.
Stop LAN listener and advertisement
[server]
enabled = falseThis prevents Aethon from starting its unauthenticated LAN HTTP listener and silences the mDNS advertiser (_aethon._tcp.local.) on boot. Read-only peer discovery still runs, and a manual server_start action starts and advertises the local server regardless.
WARNING
The discovery server has no authentication and no TLS today. It is scaffolding for an upcoming pairing feature, not a trusted IPC channel.
Team guardrails
[guardrails]
# Advisory: appended to the model's working context every turn. Steers, never blocks.
soft_prompt_anchor = "Prefer small, reviewable diffs. Run the test suite before claiming done."
# Enforcing: blocks write/edit/bash tool calls outside the active tab's project root.
hard_enforce_project_root = truesoft_prompt_anchor is advice the model can ignore; hard_enforce_project_root is a deterministic deny that the per-tab composer toggle can override per session. Pair them: the anchor steers the model, the enforcement flag is the backstop. Both apply on the next agent spawn.
Enable or tune voice input
[voice]
toggle_hotkey = "mod+shift+m" # mod = Cmd on macOS, Ctrl elsewhere
# hold_hotkey = "AltRight" # optional push-to-talk physical key
speak_agent_replies = false # read agent replies aloud (LFM2-Audio TTS)
speak_max_chars = 600 # cap spoken reply length, in characters
conversation_continuous = false # hands-free: auto-listen after each spoken replymod maps to Cmd on macOS and Ctrl on Linux/Windows. hold_hotkey is an optional hold-to-record key (default AltRight / Option on macOS only).
The last three keys drive the LFM2-Audio speak-aloud / hands-free conversation mode: speak_agent_replies reads replies back to you, speak_max_chars caps how much of a long reply is spoken, and conversation_continuous re-arms the mic after each reply for a hands-free loop. Auto-listen is also a runtime toggle in the conversation HUD (off by default). Push-to-talk is Cmd+Shift+M (the toggle_hotkey above); the optional hold_hotkey is a press-and-hold-to-record physical key.
WARNING
Voice requires the voice build feature. On a build without it these keys are inert and the voice commands return the error voice support not built into this binary.
MCP servers
Aethon can connect to Model Context Protocol servers and expose their tools to the agent.
[mcp]
enabled = true # host-level MCP support
project_configs = "require-approval" # auto-load | require-approval | neverenabled turns MCP support on or off at the host level. project_configs is the trust policy for repo-owned MCP files (<project>/.aethon/mcp.toml or .mcp.json):
require-approval(default) — load repo MCP files only after you approve them.auto-load— trust and load repo MCP files automatically.never— ignore repo MCP files entirely.
Use /mcp status to inspect connections, /mcp setup to add a server, and /mcp-auth [server] to run a server's auth flow. See Slash commands.
Workspace startup commands
A workspace can declare startup commands that run when it becomes active, defined per project in <project>/.aethon/startup.toml. The host gate controls whether those commands run without a prompt:
[startup]
auto_approve = false # true = run workspace startup commands without confirmingLeave auto_approve = false to be asked before a workspace's startup commands run; set it to true to trust them globally.
Per-project configuration
Only [devshell] supports a per-project override of a config.toml section, via <project-root>/.aethon/devshell.toml (see the devshell section above). Every other section is global to ~/.aethon/config.toml; there is no per-project variant for [ui], [agent], [shell], and the rest.
Separately, a repo can ship its own definitions in .aethon/: mcp.toml / .mcp.json (MCP servers, gated by [mcp] project_configs) and startup.toml (workspace startup commands, gated by [startup] auto_approve). Those are repo-owned files, not config.toml overrides.
Hot-reload
Most fields take effect on the next render. A few need a spawn or restart:
- Immediate (next render):
theme,font_size,thinking_visibility,tool_calls_visibility. - New shell tabs only:
default_share_mode,default_command,default_args,inherit_env,prompt_before_close. - Next agent spawn (env-wired): the
[agent]timeout/idle keys and the[guardrails]keys flow throughapply_user_env, so they apply when the worker next starts. - Next launch:
auto_restart_agent,[server] enabled. - Devshell refresh / next spawn:
[devshell]fields, plus the explicit "Refresh now" button in Settings.
Extension and agent-source changes request a graceful bridge reload rather than aborting an active turn. The frontend keeps tab, workspace, editor, and activity state across both Vite hot reloads and bridge reloads; if a prompt is running, the chat and footer should continue to show the tab-scoped activity until the next agent event or final answer arrives.
Where to next
- Reference: config.toml: exhaustive schema, clamp ranges, and environment-variable wiring.
- Agents: models, providers, subagent timeouts, and system-prompt overrides.
- Themes: registering custom themes.
- Extensions: extending Aethon.