Configuration

Plexi reads config.toml from the active channel profile. Alpha uses ~/.plexi-alpha/config.toml, beta uses ~/.plexi-beta/config.toml, main uses ~/.plexi/config.toml, and PR builds use ~/.plexi-pr-<N>/config.toml.

Changes take effect on the next launch unless a command says otherwise.

Channel discipline

Alpha config stays default. just install refreshes ~/.plexi-alpha/config.toml from the built-in template, and PR builds seed from alpha. Do not use alpha for personal overrides you expect to keep.

Beta config is the staging ground. ~/.plexi-beta/config.toml is not reset by alpha installs, so it is the right place to test migrations, advanced settings, and personal config before promoting a release.

PR builds are isolated. A PR build reads ~/.plexi-pr-<N>/config.toml; use the plexi-pr-<N> binary when checking a PR-specific config behavior.

Commands

plexi config edit
plexi config check
plexi config reset

config edit opens the active channel config. config check validates known keys and TOML syntax. config reset backs up the current file to config.toml.bak, then writes the built-in default template.

Reference

Top-level (config.toml)

FieldTypeDefaultDescription
config_versioninteger
font_sizefloat
pane_gapfloat4.0Inter-pane gap width in pixels. Default: 4.0. Clamped to [0.0, 20.0].
pane_title_font_sizefloat11.0Pane title bar font size. Default: 11.0. Clamped to [6.0, 32.0].
osc_pane_titlebooltrueApply OSC 0/1/2 title sequences from terminal processes as pane names. Defaults to true; set false to keep terminal pane names manual-only.
theme_presetstring
confirm_quitbooltrueSet to false to quit immediately on Cmd+Q without triple-press confirmation (default: true).
confirm_closebooltrueSet to false to close panes immediately on Cmd+W without a confirmation dialog (default: true).
confirm_context_closebooltrueSet to false to close contexts immediately on Cmd+Shift+W without a confirmation dialog (default: true).
focus_history_depthinteger

Theme ([theme])

Pick a preset and optionally override individual colors. Individual color fields override preset values when both are set.

Available presets: catppuccin-mocha, catppuccin-latte, dracula, tokyo-night, tokyo-day, gruvbox-dark, gruvbox-light, nord, solarized-dark, solarized-light, matrix, bios, plexi-night, plexi-day.

FieldTypeDefaultDescription
presetstringTheme preset name. Applied first; individual color fields override the preset.
bg_darkeststring
bg_sidebarstring
bg_toolbarstring
terminal_bgstring
bg_hoverstring
bg_sidebar_hoverstring
bg_activestring
text_primarystring
text_dimstring
text_sectionstring
accentstring
borderstring
foregroundstring
backgroundstring
blackstring
redstring
greenstring
yellowstring
bluestring
magentastring
cyanstring
whitestring
bright_blackstring
bright_redstring
bright_greenstring
bright_yellowstring
bright_bluestring
bright_magentastring
bright_cyanstring
bright_whitestring
bright_foregroundstring
pip_workingstring
pip_idlestring
pip_blockedstring
pip_dimfloat

Effects ([effects])

FieldTypeDefaultDescription
crtbool
ghostbool
ghost_opacityfloat0.75Opacity for unfocused panes when ghost is enabled. Range 0.0–1.0; default 0.75. Setting this implies ghost = true unless ghost = false is explicit.

Log ([log])

level accepts error, warn, info, or debug. Applies live on config save — no restart required.

FieldTypeDefaultDescription
levelstring
retention_daysinteger

Notifications ([notifications])

interrupt_threshold maps to named priority levels: 0 = LOW, 50 = NORMAL, 100 = HIGH, 200 = CRITICAL. Notifications below the threshold queue silently; at or above it, arrival opens the modal.

FieldTypeDefaultDescription
enabledbooltrueMaster switch. If false, incoming notifications are silently dropped — apps still send them, but the modal never appears and the queue stays empty. Defaults to true.
focus_modeboolfalseFocus mode. When true, NO notification auto-surfaces regardless of priority. Everything queues silently; the user reviews via Cmd+Shift+A. Defaults to false.
interrupt_thresholdinteger100Minimum priority that may auto-open the modal. Notifications below this value queue silently (badge ticks, Cmd+Shift+A reveals them). At or above it, arrival auto-opens the modal. Defaults to 100 (PRIORITY_HIGH) — NORMAL and LOW are passive; HIGH and CRITICAL interrupt. Set to 0 to auto-open everything; set to 201 to match focus_mode = true.

AI ([ai])

API keys are NOT stored in config.toml. Export OPENROUTER_API_KEY in your shell profile (~/.zshrc, ~/.zprofile, etc.), or store it in the Plexi secret store:

plexi secret set openrouter-api-key --global
FieldTypeDefaultDescription
backendstringBackend selection: "openrouter" (default) or "ollama".
per_app_daily_usdfloat$1.00Per-app daily spend cap in USD. Default $1.00.
global_daily_usdfloat$10.00Global daily spend cap across all apps in USD. Default $10.00.

OpenRouter ([ai.openrouter])

FieldTypeDefaultDescription
api_key_envstringOPENROUTER_API_KEYEnvironment variable name for the API key. Default: OPENROUTER_API_KEY.
model_lowstringLow-tier model. e.g. “qwen/qwen3.6-flash”
model_mediumstringMedium-tier model. e.g. “xiaomi/mimo-v2.5-pro”
model_highstringHigh-tier model. e.g. “anthropic/claude-fable-5”

Ollama ([ai.ollama])

FieldTypeDefaultDescription
hoststringhttp://localhost:11434Ollama host URL. Default: http://localhost:11434.
model_lowstringLow-tier model. e.g. “llama3.2:3b”
model_mediumstringMedium-tier model. e.g. “llama3.3:70b”
model_highstringHigh-tier model. e.g. “qwq:32b”

Agents ([agents])

Command templates for dispatching coding agents. {cmd} is replaced with the prompt or slash command at dispatch time.

FieldTypeDefaultDescription
lowstringclaude haiku with —dangerously-skip-permissionsFast/cheap tasks. Default: claude haiku with —dangerously-skip-permissions.
mediumstringclaude sonnet with —dangerously-skip-permissionsStandard work. Default: claude sonnet with —dangerously-skip-permissions.
highstringclaude with —dangerously-skip-permissionsComplex/autonomous tasks. Default: claude with —dangerously-skip-permissions.

Keybindings ([keybindings])

Override only the shortcuts you want to change. Unknown or conflicting overrides log a warning at startup and keep the default binding.

Modifier keys: cmd (alias: command), shift, ctrl (alias: control), alt (aliases: opt, option).

Key names: az, 09, enter, escape, tab, space, backspace, delete, up, down, left, right, open_bracket, close_bracket, backslash, slash, comma, period, equals, minus.

Each value is a string like "cmd+p" or "cmd+shift+w".

ActionDescription
quitquit
close_paneclose pane
toggle_command_palettetoggle command palette
split_horizontalsplit horizontal
split_verticalsplit vertical
split_rightsplit right
split_downsplit down
swap_pane_leftswap pane left
swap_pane_downswap pane down
swap_pane_upswap pane up
swap_pane_rightswap pane right
send_pane_leftsend pane left
send_pane_downsend pane down
send_pane_upsend pane up
send_pane_rightsend pane right
navigate_leftnavigate left
navigate_downnavigate down
navigate_upnavigate up
navigate_rightnavigate right
new_tabnew tab
next_tabnext tab
prev_tabprev tab
next_contextnext context
prev_contextprev context
move_context_upmove context up
move_context_downmove context down
nav_backnav back
focus_history_forwardfocus history forward
toggle_sidebartoggle sidebar
toggle_zoomtoggle zoom
toggle_shortcutstoggle shortcuts
rename_contextrename context
rename_panerename pane
new_contextnew context
new_page_rightnew page right
toggle_minimaptoggle minimap
scroll_upscroll up
scroll_downscroll down
increase_font_sizeincrease font size
decrease_font_sizedecrease font size
open_file_browseropen file browser
open_quick_noteopen quick note
open_configopen config
reload_configreload config
open_secrets_manageropen secrets manager
open_assistantopen assistant
force_reload_appforce reload app
toggle_notification_modaltoggle notification modal
open_scratchpadopen scratchpad
push_to_subcontextpush to subcontext
new_child_contextnew child context
set_context_root_from_cwdset context root from cwd
hide_panehide pane
park_contextpark context
open_notes_pickeropen notes picker
close_contextclose context

CLI ([cli])

FieldTypeDefaultDescription
tipsbooltruePrint contextual tips after CLI commands. Default: true. Set to false to suppress.

File handlers ([file_handlers])

Choose which app opens each file type from the File Explorer. Keys are bare lowercase extensions (e.g. md, not .md). Values are handler specs:

ValueBehavior
app:<id>Open in a Plexi app by its registry id (e.g. app:text-editor)
osHand to the OS default opener (open / xdg-open)
cmd:<command>Reserved; falls back to os until wired

A handler here overrides an app’s own file_types association. Unmapped extensions fall through to manifest associations, then builtin media players, then the OS default.

Marketplace ([marketplace])

All fields are optional. Omitting the section uses the official plexiapp.com registry and CDN. Override only to point at a private registry or to test publishing flows.

FieldTypeDefaultDescription
registry_urlstringofficial `plexiappOverride the catalog index URL. Default: official plexiapp.com index.
cdn_urlstringofficial `plexiappOverride the package CDN base. Default: official plexiapp.com CDN.
submit_urlstringPublisher submission endpoint. Unset = publishing prepared locally but not uploaded (fails closed with a clear message).
payment_backendstringPayment backend selector. Unset / "none" = stub (paid installs fail closed). A real provider (e.g. "stripe") slots into crate::app::marketplace::payment_provider() keyed on this value.
account_backendstringAccount/auth backend selector. Unset / "none" = stub (login/signup fail closed). A real provider slots into crate::app::account::account_provider() keyed on this value.
account_emailstringDefault email pre-filled by plexi account login. Unset = prompt.

Default config.toml

This is the built-in template Plexi writes when it creates or resets the active channel config.

# Plexi Configuration — full reference: https://plexiapp.com/docs/config | docs/CONFIG.md
# Edit: plexi config edit  |  Check: plexi config check  |  Reset: plexi config reset

config_version = 1

font_size = 14.0
# pane_gap = 4                 # inter-pane gap in pixels (0-20)
# pane_title_font_size = 12    # pane title bar font size (6-32)

confirm_quit  = true
confirm_close = false
confirm_context_close = true

# focus_history_depth = 100
osc_pane_title = true

[theme]
preset = "catppuccin-mocha"
# Presets: catppuccin-mocha, catppuccin-latte, dracula, tokyo-night, tokyo-day, gruvbox-dark, gruvbox-light, nord, solarized-dark, solarized-light, matrix, bios, plexi-night, plexi-day
# Uncomment to override individual colors:
# accent       = "#89b4fa"
# bg_darkest   = "#11111b"
# terminal_bg  = "#292a44"
# text_primary = "#cdd6f4"
# foreground   = "#e8e6ed"

[effects]
crt           = false
ghost         = true
ghost_opacity = 0.75

[notifications]
# enabled = true
# focus_mode = false
# interrupt_threshold = 100    # 0=LOW 50=NORMAL 100=HIGH 200=CRITICAL

[ai]
backend = "openrouter"         # "openrouter" (cloud) or "ollama" (local)

[ai.openrouter]
api_key_env  = "OPENROUTER_API_KEY"
model_low    = "qwen/qwen3.6-flash"
model_medium = "xiaomi/mimo-v2.5-pro"
model_high   = "anthropic/claude-fable-5"

# [ai.ollama]
# host         = "http://localhost:11434"
# model_low    = "llama3.2:3b"
# model_medium = "llama3.3:70b"
# model_high   = "qwq:32b"

# [log]
# level = "info"               # error | warn | info | debug — applies live on save, no restart
# retention_days = 30

# [keybindings]
# toggle_command_palette = "cmd+p"
# open_config            = "cmd+comma"
# close_context          = "cmd+shift+w"

[agents]
low    = "claude --model claude-haiku-4-5 --dangerously-skip-permissions '{cmd}'"
medium = "claude --model claude-sonnet-4-6 --dangerously-skip-permissions '{cmd}'"
high   = "claude --dangerously-skip-permissions '{cmd}'"

[cli]
tips = true

# [file_handlers]
# Choose which app opens each file type from the File Explorer (Enter / double-
# click). Keys are bare, lowercase extensions; values are `kind:value` specs:
#   "app:<id>"      open in a Plexi app by its registry id (e.g. text-editor)
#   "os"            hand to the OS default opener (open / xdg-open)
#   "cmd:<command>" reserved for a future release; falls back to "os" for now
# A handler here overrides an app's own file_types association. Unmapped types
# fall through to manifest associations, then builtin media players, then the OS.
# md   = "app:text-editor"
# txt  = "app:text-editor"
# json = "app:text-editor"
# py   = "os"

[marketplace]
# Hosted app catalog + CDN. Defaults point at the official plexiapp.com registry,
# so leave these unset to use it. Override only to point at a private registry.
# registry_url    = "https://plexiapp.com/registry/v1/index.json"
# cdn_url         = "https://plexiapp.com/registry/v1/packages"
# Publisher submission endpoint. Unset = `plexi app publish` prepares the package
# locally but does not upload it.
# submit_url      = "https://plexiapp.com/registry/v1/submit"
# Paid-app payment backend. Unset / "none" = paid installs fail closed (no charge
# possible). A real provider is wired in a future release.
# payment_backend = "none"
# Account/auth backend. Unset / "none" = login/signup fail closed. Accounts are
# only ever needed to publish or buy paid apps — free apps install without one.
# account_backend = "none"
# Default email pre-filled by `plexi account login`.
# account_email   = "[email protected]"