Config Reference
Exhaustive reference for the @brimveyn/aimux-config surface.
This is the exhaustive reference for the public configuration surface used by
aimux.
Entry Points
Package name:
@brimveyn/aimux-configPrimary exports:
defineConfigactionsthemes,THEMES,THEME_IDSGroupBuilder,KeymapBuilder,ModeBindingBuildergetDefaultKeymapConfigresolveConfig- public types for config, state, and tooling
Additional export:
@brimveyn/aimux-config/backendsTop-level Config Object
defineConfig({
theme?: {
initialMode?: 'light' | 'dark'
paletteOverrides?: Partial<AimuxPalette>
}
keymaps?: (k: KeymapBuilderApi) => KeymapBuilderApi
backends?: Record<string, BackendConfig>
sidebar?: SidebarConfig
sessionBar?: SessionBarConfig
gitPane?: GitPaneConfig
hooks?: HooksConfig
snippets?: SnippetDef[]
snippetTriggerChar?: string
autoCommit?: Partial<AutoCommitConfig>
multiRepo?: Partial<MultiRepoConfig>
statusBar?: StatusBarConfig
worktreeTemplates?: WorktreeTemplate[]
})Support Matrix
| Field | Status | Notes |
|---|---|---|
keymaps | Supported | Fully resolved and registered by the app |
sessionBar | Supported | Startup overrides; if set, these values reapply on every launch and beat aimux.json |
gitPane | Supported | Startup overrides for pane state; app-managed runtime state still persists separately |
theme | Supported | theme.initialMode is a startup override; persisted aimux.json.themeId still wins |
backends | Typed surface only | Resolved by the config package, but current runtime wiring is deferred |
sidebar | Typed surface only | Type exists, but current runtime sidebar state comes from app-managed state and snapshots |
hooks | Typed surface only | Type exists; runtime use is not currently wired |
snippets | Supported | Config-pinned snippets are merged into the runtime catalog at boot; read-only in the picker. See ../guide/snippets.md |
snippetTriggerChar | Supported | Single-character prefix for inline snippet triggers (default :). See ../guide/snippets.md |
autoCommit | Supported | AI-written commit messages. Disabled by default; see ../guide/git-mode.md#auto-commit |
multiRepo | Supported | Aggregates nested sub-repos into one git panel. Enabled by default; see ../guide/git-mode.md#multi-repo-workspaces |
statusBar | Supported | Hosts the aiUsage sub-block (AI usage indicator) and the separator glyph style for the bottom status bar |
worktreeTemplates | Supported | Multi-tab / multi-pane layouts spawned at worktree creation. See ../guide/worktrees.md#templates |
defineConfig
defineConfig(config) is the authoring helper for user config files.
Use it in:
~/.config/aimux/<profile>/aimux.config.ts~/.config/aimux/<profile>/aimux.config.js
It is a typed pass-through helper, not a runtime loader by itself.
keymaps
Status: Supported
Type:
keymaps?: (k: KeymapBuilderApi) => KeymapBuilderApiUse this field to customize keybindings.
Builder methods:
leader(key)timeout(ms)mode(id | ids[], configure)
Mode builder methods:
map(keys, action, description?)unmap(keys)group(prefix, name, configure)passthrough()
Important runtime facts:
- shipped default leader is
<C-w> - shipped default timeout is
300 - repeated
.mode()calls merge - same-key user bindings override earlier ones
unmap()removes defaults by exact key string- array mode definitions apply to every listed mode
See ../guide/keymaps.md for notation and merge semantics.
sessionBar
Status: Supported
Type:
sessionBar?: {
initialVisible?: boolean
}Runtime behavior:
- consumed during app initialization
- used as a higher-priority source than
aimux.json.sessionBarVisible - reapplied on every launch while this config entry remains set
Example:
export default defineConfig({
sessionBar: {
initialVisible: true,
},
})gitPane
Status: Supported
Type (discriminated union on mode):
type GitPaneConfig =
| {
initialMode?: 'embedded'
initialPosition?: 'top' | 'bottom'
initialVisible?: boolean
initialRatio?: number // 0..1, clamped to [0.2, 0.8]
initialDiffModeRatio?: number // 0..1, clamped to [0.2, 0.8]
initialFileListMode?: 'tree' | 'flat'
initialTreeCompaction?: boolean
path?: GitPanePathConfig
diffCount?: GitPaneDiffCountConfig
prefetchRadius?: number
}
| {
initialMode: 'pane'
initialPosition?: 'left' | 'right'
initialVisible?: boolean
initialRatio?: number
initialDiffModeRatio?: number
initialFileListMode?: 'tree' | 'flat'
initialTreeCompaction?: boolean
path?: GitPanePathConfig
diffCount?: GitPaneDiffCountConfig
prefetchRadius?: number
}
type GitPanePathConfig = { enabled: false } | { enabled: true; pathFn?: (path: string) => string }
type GitPaneDiffCountConfig = { enabled: boolean }Runtime behavior:
mode: 'embedded'renders the git file list inside the sidebar, above orinitialMode: 'embedded'renders the git file list inside the sidebar, above or below the tab list depending oninitialPosition.initialMode: 'pane'renders the git file list as a standalone pane next to the sidebar (left) or on the far right of the main area (right).initialPositionallowed values are constrained perinitialModeat the type level.initialRatiocontrols startup size: inembeddedmode it's the vertical split ratio against the tab list; inpanemode it maps to a column count in[20, 80].initialDiffModeRatiocontrols the file-list width while you are in full-screen git diff mode.initialFileListModecontrols whether the git file list renders as a folder tree or as a flat list.initialTreeCompactioncontrols whether tree mode collapses unary directory chains at startup.path.enabled: falsehides the directory part of each file path, showing only the basename. Whenenabled: true, an optionalpathFnrewrites the path before rendering (e.g. stripping a prefix).diffCount.enabled: falsehides the+added / −removedcolumn.prefetchRadiusis a regular config knob, not a persisted pane-state field.- The
initial*fields are startup overrides. Current runtime pane state is still persisted inaimux.json, but typed config values take precedence on every launch when present.
Example:
export default defineConfig({
gitPane: {
initialMode: 'pane',
initialPosition: 'right',
initialDiffModeRatio: 0.3,
initialFileListMode: 'tree',
initialRatio: 0.35,
initialTreeCompaction: true,
path: {
enabled: true,
pathFn: (p) => p.replace(/^src\//, ''),
},
diffCount: { enabled: false },
},
})Legacy migration: config files written before gitPane existed stored
gitPanelVisible / gitPanelRatio at the root of aimux.json. Those keys
are read once on load and converted to { mode: 'embedded', position: 'bottom', ratio, visible }, then persisted under gitPane on the next save.
theme
Type:
theme?: {
initialMode?: 'light' | 'dark'
paletteOverrides?: Partial<AimuxPalette>
}theme.initialMode picks the built-in light or dark family when there is no
persisted aimux.json.themeId.
theme.paletteOverrides customizes the active palette at startup and applies to
the resolved runtime theme regardless of whether the base theme came from
persisted state or from initialMode.
import { defineConfig } from '@brimveyn/aimux-config'
export default defineConfig({
theme: {
initialMode: 'dark',
paletteOverrides: {
primary: '#7dd3fc',
warning: '#fbbf24',
},
},
})See ../guide/themes.md for runtime picker behavior and
palette override guidance.
Precedence at startup: persisted aimux.json.themeId (if still known) →
theme.initialMode → built-in dark fallback. paletteOverrides applies on top
of the chosen base theme.
backends
Status: Typed surface only
Type:
backends?: Record<string, BackendConfig>BackendConfig:
interface BackendConfig {
command: string
args?: string[]
}Notes:
- the config package resolves this field
- helper functions such as
claudeBackend()andcodexBackend()are exported - the helper module explicitly documents runtime wiring as deferred
Do not present this as a fully working runtime backend override surface today.
sidebar
Status: Typed surface only
Type:
interface SidebarConfig {
widgets?: string[]
width?: number
}Current runtime behavior is driven by app state and persisted workspace data, not by this top-level typed config field.
hooks
Status: Typed surface only
Type:
interface HooksConfig {
onSessionCreate?: (session: { name: string; projectPath?: string }) => void | Promise<void>
}This is currently a typed API surface, not a documented runtime feature.
snippets
Status: Supported
Type:
interface SnippetDef {
name: string
trigger?: string
text: string
vars?: Record<string, SnippetVar>
}
interface SnippetShellVar {
sh: string
timeout?: number // ms, default 5000
trim?: boolean // default true
}
type SnippetVar = SnippetShellVarRuntime behavior:
- snippets are loaded from
aimux-snippets.json(user-edited, JSON catalog) - snippets declared in
aimux.config.tsare merged into the runtime catalog with id prefixconfig:and treated as read-only in the picker varsare only honored onconfig:snippets — anyvarsfield on a user-catalog snippet is stripped on load (security: only the typed config may declare shell execution)- a snippet whose
triggermatches an inline-typed sequence expands thetextwith{{name}}variable substitution and$|cursor placement
See ../guide/snippets.md for the full reference.
snippetTriggerChar
Status: Supported
Type:
/** Single-character prefix that opens an inline trigger. Default: `:`. */
snippetTriggerChar?: stringA non-single-character value falls back to : at resolution time. See
../guide/snippets.md.
autoCommit
Status: Supported
Type:
autoCommit?: {
enabled?: boolean // default: false
timeoutMs?: number // default: 60_000
models?: Partial<Record<string, string>> // per-provider model override
}Controls the AI-assisted commit message flow surfaced in the commit modal
(c in git mode). When enabled: false (the default), the [ Auto-commit ]
button is hidden, Ctrl+A surfaces a status message pointing here, and no
background request is ever made. When enabled: true:
- A background driver watches the working tree and pre-generates a commit message (Claude Haiku by default) whenever the tree stays stable for ~2 s.
- The
[ Auto-commit ]button andCtrl+Ainside the modal consume the cached suggestion if ready, or show a loading overlay until it arrives. - Manual staging is respected: with files already staged, the generated
message (and the actual commit) only cover the staged set; with nothing
staged,
git add -Ais run before committing.
Supported providers: claude, codex, opencode. The active tab's
assistant determines which CLI is invoked.
Example:
export default defineConfig({
autoCommit: {
enabled: true,
models: {
claude: 'claude-haiku-4-5',
codex: 'gpt-5-mini',
},
timeoutMs: 60_000,
},
})See ../guide/git-mode.md#auto-commit
for the full user-facing walkthrough.
multiRepo
Status: Supported
Type:
multiRepo?: {
enabled?: boolean // default: true
maxDepth?: number // default: 1 (direct children only)
}When a session's projectPath contains nested git repositories, aimux scans
for them once per session and merges their status into a single aggregated
git panel. In flat list mode each file is tagged with a short disambiguating
prefix (1, 2, or more letters — extended only where names collide) so you can
tell at a glance which sub-repo a file belongs to; in tree mode the regular
path hierarchy is preserved. Within each section (staged / unstaged /
untracked), files are grouped by repo before being sorted by path.
enabled: true(default) turns discovery on.maxDepth: 1scans the direct children ofprojectPath. Set2to also descend one level further for deeply nested layouts.- Discovery results are cached per
(projectPath, maxDepth)— the scan runs once per session. - Sub-repo commands (stage / unstage / discard / diff) are routed to each file's originating repository automatically.
- If
projectPathis itself a git repo, its files appear first (no prefix) and sub-repo files follow.
Example:
export default defineConfig({
multiRepo: {
enabled: true,
maxDepth: 1,
},
})Set enabled: false to fall back to single-repo behaviour (no discovery, no
prefix).
statusBar
Status: Supported
Type:
interface StatusBarConfig {
aiUsage?: AIUsageToolConfig
separator?: 'arrow' | 'round' | 'slant' | 'flame' | 'none' // default 'arrow'
}
interface AIUsageToolConfig {
enabled?: boolean // default false
tools?: Array<'claude' | 'codex'> // default ['claude', 'codex']
pollSeconds?: number // default 60; clamped to a minimum of 5
claudePlan?: 'auto' | 'pro' | 'max5' | 'max20' // default 'auto'; reserved
codexWeeklyLimit?: number // reserved
}Runtime behavior:
- when
aiUsage.enabled !== truethe indicator is hidden and no polling happens - the indicator lives on the right side of the status bar and supports click to open a details popover
- Claude data comes from
api.anthropic.com/api/oauth/usageusing the OAuth token stored in the macOS Keychain (Claude Code-credentials) - Codex data comes from
chatgpt.com/backend-api/wham/usageusing the OAuth token stored in~/.codex/auth.json - all colors are pulled from the active theme palette; no hardcoded colors
separator
Powerline-style glyph rendered between the status bar sections (mode badge,
session/path tile, AI usage tile, version tile). All non-none options require
a nerd-font / powerline-capable font.
| Value | Right glyph | Left glyph | Codepoints |
|---|---|---|---|
arrow | U+E0B0 / U+E0B2 | ||
round | U+E0B4 / U+E0B6 | ||
slant | U+E0BC / U+E0BA | ||
flame | U+E0C0 / U+E0C2 | ||
none | — | — | (no glyph; sections snap via background colour only) |
Resolved once at app startup and persisted for the session.
See ../guide/ai-usage-indicator.md for the
full AI usage guide, field reference, and platform requirements.
Example:
export default defineConfig({
statusBar: {
separator: 'round',
aiUsage: {
enabled: true,
pollSeconds: 60,
tools: ['claude', 'codex'],
},
},
})worktreeTemplates
A list of reusable layouts spawned when the user creates a new worktree. Each template appears in a picker at the end of the new-worktree flow; the chosen template's tabs and panes are created, sized, and (optionally) prefilled with an initial command.
See ../guide/worktrees.md#templates for the full walkthrough, including
the picker UX, the "Worktree from template…" shortcut entry, and validation
rules.
worktreeTemplates: [
{
id: 'lint-watch',
name: 'Claude + lint watch',
description: 'Claude on the left, bun lint --watch on the right',
tabs: [
{
panes: [
{ id: 'main', assistant: 'claude' },
{
id: 'lint',
assistant: 'terminal',
splitFrom: 'main',
direction: 'horizontal',
ratio: 0.35,
send: 'bun lint --watch',
},
],
},
],
},
]Types:
interface WorktreeTemplate {
id: string
name: string
description?: string
tabs: WorktreeTemplateTab[]
}
interface WorktreeTemplateTab {
panes: WorktreeTemplatePane[]
}
interface WorktreeTemplatePane {
id: string
assistant: string
splitFrom?: string
direction?: 'horizontal' | 'vertical'
ratio?: number
send?: string
}worktreeTemplates can also be set in aimux.json under the same key
(JSON form, same schema). The TS config wins when both are present.
Actions
actions exports the built-in action catalog used by keymaps.
Common groups:
- tabs:
nextTab,prevTab,newTab,renameTab,closeTab,restartTab - workspaces:
sessionPicker,switchSessionByIndex(n)and workspace modal actions - snippets:
snippetPicker, snippet filter and editor actions - themes:
themePicker,previewTheme,confirmTheme,restoreTheme - panes:
splitVertical,splitHorizontal,focusPane,resizePane,closePane - UI:
toggleSidebar,resizeSidebar,toggleSessionBar,toggleGitPane,resizeGitPane(delta),setGitPaneMode(mode),setGitPanePosition(position) - modes:
enterInsert,leaveTerminalInput,closeModal,helpModal - git:
enterGitMode,exitGitMode, stage/unstage/delete, commit, push
You can also provide your own ActionFn for dynamic runtime behavior.
Themes API
Exports:
themes.define(name, baseThemeId, overrides)— palette shortcut. Patch VSCode color keys on top ofbaseThemeId. Returns aNamedThemeDefinition.themes.full(theme)— pass-through for a rawNamedTheme(shiki theme JSON withname,displayName,type,colors,settings, …).themes.extend(baseThemeId, overrides)— unnamed variant ofdefine(lower-level).AIMUX_COLOR_KEYS— the VSCode color keys aimux's UI reads.THEME_IDS— all shipped theme ids (shiki + house).THEMES— record mapping id to a fullThemeobject.
See ../guide/themes.md for the full list of shipped
themes and picker usage.
Tooling Types
The package exports many additional types such as ResolvedConfig, AppState,
ModeContext, and ResolvedKeymapConfig.
Those exports are useful for tooling and integration, but not all of them should be interpreted as stable end-user runtime promises.