Skip to content

Configuration keys ​

Every key of ~/.noeta/config.toml, every provider table key, the settings-file keys noeta reads, how plugin settings combine, and every environment variable noeta reads. Where each comes from and which wins is explained in Configuration.

config.toml ​

~/.noeta/config.toml ($NOETA_HOME/config.toml) is read by every noeta command (noeta/cli/config.py). A flag or an environment variable wins over the top-level keys.

Top-level keys ​

KeyTypeDefaultMeaningOverridden by
modelstringnone (required somewhere)the model new tasks run, an id or an alias--model, NOETA_MODEL
providerstringanthropicthe default provider: a family (anthropic, openai_compat, openai_responses, or a provider package's) or the name of a [providers.<name>] table--provider, NOETA_PROVIDER
base_urlstringthe family'sthe default provider's base URL: the host for anthropic, …/v1 for openai_compat, the whole …/v1/responses URL for openai_responses--base-url, NOETA_BASE_URL
api_keystringnonethe default provider's key: a literal, {env:NAME} or {keyring:service/user}; without one, anthropic reads ANTHROPIC_API_KEY and openai_compat reads OPENAI_API_KEY; openai_responses reads no variable and needs oneNOETA_API_KEY
extra_headerstable of stringsnoneheaders sent with every request of the default provider; values may be {env:…} / {keyring:…} references—
storestringsqlite:///~/.noeta/tasks.dbsqlite:///path or postgres://…--store, NOETA_STORE
effortstringthe model'slow, medium, high, xhigh or max, for the tasks the terminal UI, -p, acp, serve and worker create (the noeta command)--effort, NOETA_EFFORT
models_filepathnonea JSON file describing more models (below)NOETA_MODELS_FILE
list_modelsbooltrueread the default provider's /models listing for models the catalog does not know—
prompt_cache_ttl"5m" or "1h"the API's (5m)anthropic only: the one-hour prompt cache, billed higher per write—
promptstablenoneprompt overrides for every task this front end starts, by prompt name ("system/main.append" = "…")--system-prompt, --append-system-prompt

Tables: [providers.<name>], [plugins.<name>], [agents.<name>], [channels.<name>] (below). Another top-level key is ignored with a warning on stderr naming it (…/config.toml: unknown top-level keys ['modle']; ignored), so a typo shows; it is not an error, so a key an older or newer noeta reads does not stop this one. An unknown key inside a table is an error.

[providers.<name>] ​

More providers besides the default one. Each model id goes to the provider whose table names it, else to the first provider whose /models listing has it (the default first), else to the default. A task records the route its model took, so every worker sends it to the same provider (Providers and model routing).

KeyRequiredMeaning
familyyesanthropic, openai_compat, openai_responses, or a provider package's
base_urlnoas the top-level base_url, for this family
api_keynoa literal, {env:NAME} or {keyring:service/user}; without one, anthropic and openai_compat fall back to their usual environment variable
headersnoa table of headers; values may be secret references
modelsnomodel ids this provider serves, as strings or rows {id, context_window, max_output_tokens}; a row with both limits teaches the catalog a model it does not know
list_modelsno (default true)read this provider's /models for more models and their windows (kept a day in ~/.noeta/cache/models)
prompt_cache_ttlnoanthropic only: "1h" or "5m"

Any other key is an error. The name default is taken (it names the top-level provider). One model named for two providers is an error. provider = "<table name>" at the top level makes a table the default instead.

Models file ​

models_file / NOETA_MODELS_FILE names a JSON file of models the shipped catalog does not know, so they run at their real limits:

json
{"models": [
  {"id": "my-gateway/model-x", "context_window": 1000000, "max_output_tokens": 65536,
   "supports_vision": false, "family": "anthropic", "provider": "deepseek"}
]}

id, context_window and max_output_tokens are needed for a row to count; supports_vision, family (the wire family) and efforts (marks a reasoning model) are optional; provider routes the model to a configured provider by name. A bare list of rows works too.

A model's limits come from noeta's catalog first, then a models file or table rows, then its provider's listing, else 128,000 tokens of window and 16,384 of output with a warning.

[plugins.<name>] ​

A plugin's arguments, by its registry name, for every agent that runs it:

toml
[plugins.shell]
background = true
[plugins.compaction]
compaction_model = "claude-haiku-5-5"
[plugins.web]
enabled = false                  # off for every agent
[plugins.my_plugin]              # a third-party plugin's arguments
endpoint = "https://…"
token = "{env:MY_PLUGIN_TOKEN}"

Each built-in plugin's arguments are in Built-in plugins.

[agents.<name>] ​

Takes one key, add_plugins: plugins appended to that agent after its file's own, as names or {name = {arguments}} tables. [agents."*"] adds to every agent. A plugin the agent already has is not added twice.

toml
[agents.main]
add_plugins = ["my_plugin", { hooks = {} }]
[agents."*"]
add_plugins = ["audit_log"]

[channels.<name>] ​

A channel's arguments: a long-running listener for an outside conversation (a chat app, a webhook), run by noeta worker and noeta serve. enabled = false leaves one out.

toml
[channels.chat_bridge]
token = "{env:CHAT_TOKEN}"

[policy] (managed only) ​

Read only from the machine's directory (/etc/noeta/config.toml, /Library/Application Support/Noeta/config.toml, C:\Program Files\Noeta\config.toml):

KeyMeaning
allowed_pluginswhen set, only these plugins load among those noeta does not ship
blocked_pluginsthese never load, built-in or not

Plugin settings ​

A plugin setting is what a host says about one plugin, by name: its arguments (a table, where enabled = false switches it off), a ready Extension instance (in Python), or on/off. The same shape is used at every level (noeta/agents/agent_files.py):

  1. the arguments the noeta command derives from your places (the memory home, the settings files for hooks and MCP, the skills folders, permission rules);
  2. the settings Claude Code plugin folders bring;
  3. config.toml [plugins.<name>];
  4. what the front end itself passes (-p's --mcp-config, --allowedTools …).

Later levels lay over earlier ones key by key; an instance or an on/off replaces. An agent file's own arguments for a plugin (plugins: [{shell: {background: true}}]) are laid over the host's. The built-in agents keep memory, mcp and repetition_guard off until a setting names them; the noeta command sets the first two.

Secrets in arguments are written as references ({env:NAME}, {keyring:service/user}), resolved only when the plugin is made; config files and task logs hold only the reference.

A task records the plugins it runs with (name, source, version or file hash, a hash of the arguments). A worker that lacks one never runs the task without it (The plugin system).

Settings files ​

The JSON settings files (~/.noeta/settings.json, .noeta/settings.json, .noeta/settings.local.json, --settings, the managed managed-settings.json) use Claude Code's format. The keys noeta acts on (noeta/cli/settings_files.py and the plugins that read the files):

KeyRead byMeaning
envthe noeta commandenvironment variables set in noeta's process before anything else is read
modelthe noeta commandthe model, when no flag, variable or config.toml names one
agentfront endsthe agent new tasks start with
outputStyle—read; output styles are not applied
languageenvironmentthe language the model answers in
attribution.commit, attribution.prenvironmentthe trailer lines for commits and pull requests ("": none); includeCoAuthoredBy: false empties both
permissions.allow, .deny, .askpermissionsrule lists, Claude Code's Tool(spec) strings; they add up across files
permissions.defaultModepermissionsthe starting permission mode
permissions.additionalDirectoriespermissions, fs, skillsmore directories the tools may use
permissions.disableBypassPermissionsModepermissions"disable": no bypassPermissions
useAutoModeDuringPlanplan_modefalse in any file: plan mode does not use the auto mode classifier
sandboxthe local exec envClaude Code's sandbox object: enabled, failIfUnavailable, filesystem, network, excludedCommands, … (Where commands run)
hookshooksClaude Code's hooks (Permissions and hooks)
mcpServersmcpMCP servers (user and local scope)
enabledMcpjsonServers, disabledMcpjsonServers, enableAllProjectMcpServersmcpconsent for a project's .noeta/mcp.json servers (MCP servers)
skillListingBudgetFraction, skillListingMaxDescCharsskillsthe skill listing's budget and per-skill description cap
pluginConfigsClaude Code pluginsuserConfig values written by noeta plugin add / configure

Environment variables ​

Variables noeta reads (grepped across noeta/ and tui/):

VariableRead byMeaning
NOETA_HOMEeverythingnoeta's home (default ~/.noeta); ~/.agents/skills stays under the home directory
NOETA_MODELnoetathe model
NOETA_PROVIDERnoetathe default provider family or table name
NOETA_BASE_URLnoetathe default provider's base URL
NOETA_API_KEYnoetathe default provider's key (never passed to commands noeta starts)
ANTHROPIC_API_KEYanthropic providerits key when none is configured
OPENAI_API_KEYopenai_compat providerits key when none is configured
NOETA_STOREnoetathe store URL (never passed to commands)
NOETA_EFFORTnoetathe effort
NOETA_MODELS_FILEnoetaa models file
NOETA_SERVER_TOKENserve, --server, acp --serverthe server's bearer token; a client sends it (never passed to commands)
NOETA_AUTO_COMPACT_WINDOWcompactioncap the window auto-compaction derives its threshold from (Claude Code's CLAUDE_CODE_AUTO_COMPACT_WINDOW)
NOETA_AUTOCOMPACT_PCT_OVERRIDEcompactioncompact at this percentage of the effective window when that is lower (Claude Code's CLAUDE_AUTOCOMPACT_PCT_OVERRIDE)
NOETA_SLASH_COMMAND_TOOL_CHAR_BUDGETskillsthe skill listing's budget in characters (Claude Code's SLASH_COMMAND_TOOL_CHAR_BUDGET)
NOETA_MCP_TIMEOUTmcpmilliseconds for every MCP request but a tool call (default 30 s)
NOETA_MCP_TOOL_TIMEOUTmcpmilliseconds for one MCP tool call when the server sets none (default: in effect no limit)
NOETA_MAX_MCP_OUTPUT_TOKENSmcpan MCP result's size before it is saved to a file instead (default 25,000)
NOETA_MAX_MCP_DESCRIPTION_LENGTHmcpthe cap on MCP tool descriptions and server instructions (default 4,096 characters, 16,384 for a deferred tool once loaded; the variable sets both)
NOETA_TERMINAL_MCP_TOOLSmcpcomma-separated full MCP tool names whose result ends the turn
NOETA_MCP_OAUTH_CALLBACK_PORTmcpthe OAuth redirect port
NOETA_MCP_CLIENT_SECRETnoeta mcp add / add-json with --client-secretthe OAuth client secret, instead of typing it (never passed to commands)
NOETA_WEB_SEARCH_API_KEYwebthe Tavily key that turns on WebSearch (never passed to commands)
TZterminal UI, -p, acpthe person's time zone, sent with each new task as its timezone (else the zone /etc/localtime or /etc/timezone names)
VISUAL, EDITORterminal UIthe editor /memory and /config edit open

Variables noeta sets for what it starts:

VariableSet forValue
NOETA_PROJECT_DIR, CLAUDE_PROJECT_DIRhook commandsthe task's working directory
NOETA_MCP_SERVER_NAME, NOETA_MCP_SERVER_URLan MCP server's headersHelperthe server's name and URL
CLAUDE_PLUGIN_OPTION_<KEY>a Claude Code plugin's hooksits userConfig values

In skill and command bodies, ${NOETA_SKILL_DIR} / ${CLAUDE_SKILL_DIR}, ${NOETA_PROJECT_DIR} / ${CLAUDE_PROJECT_DIR}, ${NOETA_EFFORT} / ${CLAUDE_EFFORT} and ${CLAUDE_SESSION_ID} (the root task's id) are substituted. In a Claude Code plugin's files, ${CLAUDE_PLUGIN_ROOT}, ${CLAUDE_PLUGIN_DATA} (~/.noeta/plugin-data/<name>) and ${user_config.KEY} are too.

Every variable a {env:NAME} reference in noeta's config names is withheld from commands, hooks and MCP servers too, as are PGPASSWORD, PGPASSFILE, PGSERVICE and PGSERVICEFILE when the store is on Postgres (noeta/toolkit/local_env.py). Everything else is inherited, as in Claude Code.

The desktop app reads NOETA_DESKTOP_NOETA (the noeta binary), NOETA_DESKTOP_WEB (the web app's files) and NOETA_DESKTOP_USER_DATA; see Web, desktop and editors.