Skip to content

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 ​

toml
# ~/.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 = false

Every 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:

text
~/.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 rollback

The 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 ​

toml
[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:

toml
[ui]
font_size = 16

Tune transcript density ​

Hide or group the model's thinking blocks and tool-call cards by default:

toml
[ui]
thinking_visibility = "collapse"      # show | collapse | hide
tool_calls_visibility = "group-turn"  # show | group-turn | group-run | group-block | hide

Both 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 ​

toml
[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.

toml
[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 = 900

subagent_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) ​

toml
[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 = 0

A retired worker respawns lazily from its persisted session on the next message. 0 disables retirement entirely (clamped 0-1440).

Quieter completion notifications ​

toml
[ui]
notify_on_completion = true
notify_min_duration_seconds = 30   # only ping for turns 30s or longer

Set 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 ​

toml
[shell]
default_command = "/bin/zsh"
default_args = ["-l"]
inherit_env = false   # do not leak Aethon's PATH/locale into shell tabs

With 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 ​

toml
[agent]
thinking_level = "medium"   # off | minimal | low | medium | high | xhigh | max | ultra
codex_fast_mode = false     # Codex models: trade reasoning depth for speed

thinking_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.

toml
[devshell]
enabled = "auto"   # auto | always | never
mode = "auto"      # auto | direnv | nix | nix-shell
cache_ttl_hours = 720
refresh_on_lockfile_change = true
  • enabled = "never" disables wrapping globally.
  • enabled = "always" forces detection and fails loud if a marker resolves but the resolver errors.
  • mode pins a single resolver kind; auto follows precedence (direnv, then flake, then shell.nix).

To pin or disable per project, drop a devshell.toml in the repo:

toml
# <project-root>/.aethon/devshell.toml
[devshell]
enabled = "never"   # never wrap this repo
# mode = "nix"      # or pin the flake resolver if enabled

Only 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 ​

toml
[updates]
channel = "nightly"   # stable | nightly
disable_auto_check = false

stable 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 ​

toml
[server]
enabled = false

This 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 ​

toml
[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 = true

soft_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 ​

toml
[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 reply

mod 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.

toml
[mcp]
enabled = true                        # host-level MCP support
project_configs = "require-approval"  # auto-load | require-approval | never

enabled 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:

toml
[startup]
auto_approve = false   # true = run workspace startup commands without confirming

Leave 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 through apply_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.