Runtime Configuration
Anda stores runtime state in ~/.anda by default. The main configuration file is ~/.anda/config.yaml, created automatically on first launch. Optional MCP server configuration lives in ~/.anda/mcp.json.
Model Providers
The active provider must include family, model, and api_base. api_key can be written in the config file or left empty and supplied through an environment variable.
model:
active: "deepseek-v4-pro"
providers:
- family: anthropic
model: "deepseek-v4-pro"
api_base: "https://api.deepseek.com/anthropic"
api_key: "YOUR_API_KEY"
labels: ["pro", "brain"]
disabled: false
Supported model API key environment variables include:
OPENAI_API_KEY
ANTHROPIC_API_KEY
GEMINI_API_KEY
GOOGLE_API_KEY
DEEPSEEK_API_KEY
MINIMAX_API_KEY
MIMO_API_KEY
MOONSHOT_API_KEY
KIMI_API_KEY
BIGMODEL_API_KEY
GLM_API_KEY
Common Top-Level Settings
| Setting | Purpose |
|---|---|
addr | Local gateway address, default 127.0.0.1:8042. |
sandbox | When true, shell execution goes through ~/.anda/sandbox. |
https_proxy | Proxy used for model and channel requests. |
model | Model providers for the agent and memory brain. |
transcription | Provider for voice input and audio attachment transcription. |
tts | Provider for voice playback. |
channels | Telegram, WeChat, Discord, Lark/Feishu, and other channel configuration. |
Speech providers
Enable transcription.enabled for speech input and tts.enabled for speech output, and configure the selected default_provider section in each. See the configuration example.
transcription.initial_promptsupplies vocabulary hints to Groq and OpenAI Whisper. StepFun uses its owntranscription.stepfun.prompt.- Google STT accepts WAV/FLAC through its synchronous API. The Chrome extension converts unsupported recording formats to WAV. Requests must fit within 10 MB including Base64/JSON, and audio must be at most 60 seconds. Anda rejects oversized requests and known WAV/FLAC header durations above this limit; files without a known duration are still subject to Google's limit. Longer audio requires another provider or a shorter recording.
local_whisper.max_audio_bytescontrols the self-hosted endpoint's upload limit independently of the cloud limit.tts.max_text_lengthis a character limit (default 4096); provider limits also apply. Google TTS permits up to 5000 UTF-8 bytes and StepFun permits up to 1000 characters per call. Voice conversations already split replies into shorter segments.tts.default_formatselects StepFun output (mp3,opus,wav, orflac). Edge, OpenAI, and Google output MP3. Unknown formats are rejected; rawpcmis rejected because no client can play it, so usewavinstead. Artifact extensions always match the produced audio.- If the
tts.default_providerortranscription.default_providersection is missing or invalid, startup fails with that provider's error. Other invalid provider sections are skipped with a warning. - Edge requires
edge-ttson PATH (pip install edge-tts). Settts.edge.binary_pathtoedge-tts; theedge-playbackwrapper is not supported. Cancelling or timing out synthesis terminates the subprocess. - StepFun ASR requires a final
transcript.text.doneevent. A stream that ends with only partial text returns an error.
The unused transcription.max_duration_secs, transcription.transcribe_non_ptt_audio, and transcription.groq.language_code settings have been removed from the configuration form and example. Old configuration files still load; these keys are ignored. Use transcription.groq.language for a Groq language hint.
MCP Servers
Anda Bot can connect to MCP servers through stdio child processes or HTTP
endpoints. Put a portable MCP configuration in ~/.anda/mcp.json, then run
anda mcp reload (or restart the daemon). The file accepts both mcpServers and servers as the root key so
you can paste configs from other MCP-compatible tools with minimal changes.
{
"mcpServers": {
"filesystem": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "$ANDA_WORKSPACE"]
},
"remote": {
"type": "http",
"url": "https://mcp.example.com/mcp",
"headers": {
"Authorization": "Bearer ${secret:MCP_REMOTE_TOKEN}"
}
}
}
}
Remote MCP tools appear as Anda tools named like
mcp_<server_id>_<remote_tool>. Config strings support $VAR and ${VAR}
environment expansion, with ${VAR:-default} for a variable that may be unset,
and ${secret:NAME} for a secret (see Secrets). ANDA_HOME and
ANDA_WORKSPACE are built in. For stdio
servers, command is spawned directly without a shell; when cwd is omitted,
the first Anda workspace is used. If type is omitted, Anda infers stdio from
command or http from url.
Each entry is loaded on its own, and MCP never stops the daemon from starting:
an entry that cannot be used (an environment variable it names is unset, an
unsupported type such as the deprecated sse, an id used twice) is skipped
with a warning in the daemon log, and the other servers still load. Servers
connect in the background once the daemon is up, so a slow endpoint or a first
npx -y download does not delay it. Stdio servers get the same extended PATH
as the shell tool, so npx, uvx and Homebrew commands are found even when the
daemon runs as a login service. Such a service does not see variables exported
in your shell profile, so a ${VAR} reference needs the variable in the
daemon's own environment.
Optional per-server fields tune how Anda talks to the endpoint and runs the server:
| Field | Purpose |
|---|---|
startup | When Anda discovers the server's tools. background (default) connects after the daemon is up; eager waits for discovery before the daemon reports ready. Either way an unreachable server is skipped, never fatal. |
lifecycle | How the protocol revision is negotiated. auto (default) probes the stateless server/discover lifecycle and falls back to the legacy initialize handshake. Use discover to require the newer one, or initialize to pin a server that mishandles unknown methods. |
tasks | Opts into the tasks extension, so a long-running tool can hand back a task Anda polls to completion instead of holding its response open. Takes {"max_wait_secs": <seconds>}, default 300. Omit it and the server must answer every call inline. |
timeouts | Deadlines in seconds, each between 1 and 86400: setup_secs to connect (default 90), list_secs to list the tools (30), request_secs for one request (180), call_secs for a whole tool call (600) and elicitation_secs for you to answer a server's request for input (300). |
concurrency | Which of the server's tools may run at the same time: serial (default), read_only_parallel for tools the server marks read-only, or parallel. |
limits | {"output_text_bytes": <bytes>}: the text the agent gets from one result, between 256 and 1048576 (default 32768). |
inherit_env | Local servers only. true (default) gives the process the daemon's whole environment; false gives it only the platform's essentials (PATH, HOME, TMPDIR and the like) and its own env, so no other secret in the daemon's environment reaches it. |
events | {"webhook_ingress": true} makes this server (dMsg) receive webhooks for event automations whose events only a webhook delivers. One server can be the ingress. |
resources | Whether the agent and the apps may list and read the server's resources. On unless false. |
elicitation | Whether the server may ask you for input while one of its tools runs. On unless false. |
{
"mcpServers": {
"legacy": {
"type": "http",
"url": "https://legacy.example.com/mcp",
"lifecycle": "initialize"
},
"long-running": {
"type": "http",
"url": "https://batch.example.com/mcp",
"tasks": { "max_wait_secs": 900 },
"timeouts": { "call_secs": 1200 }
}
}
}
The agent can also add a server at runtime with add_mcp_server. Set
persist: false for the current daemon only, or persist: true to save the
server into ~/.anda/mcp.json for future restarts. Its server fields mirror one
mcp.json entry: type, command, args, env, cwd, url, headers,
enabled, include, and exclude, plus the tool-only id and persist
fields. The settings in the table above are yours to set, in mcp.json, on the
MCP page or with anda mcp options, not through the tool. manage_mcp_server lets the
agent list the servers with their status and last error and reconnect one;
enabling, disabling, removing or signing out of a server asks for your approval
first.
For OAuth endpoints, connect_mcp_server runs the browser authorization and
stores the tokens in the local credential store. Calling it again on a connected
server only verifies the connection; pass reauthorize: true to sign out and
consent again, which is what granting a different set of scopes requires.
Managing servers with anda mcp
anda mcp list # status, tools and last error of each server
anda mcp get github # one server and its tools
anda mcp add context7 -- npx -y @upstash/context7-mcp
anda mcp add docs --url https://docs.example.com/mcp --header 'Authorization: Bearer ${DOCS_TOKEN}'
anda mcp add-json notes '{"type":"http","url":"https://notes.example.com/mcp"}'
anda mcp login linear --url https://mcp.linear.app/mcp # OAuth sign-in; --no-browser prints the URL
anda mcp tool github delete_repository --hide # keep one tool from the agent
anda mcp secret set DOCS_TOKEN # also: secret list, secret unset
anda mcp disable context7 # also: enable, remove, reconnect, logout, reload
anda mcp options github --call-timeout 900 # advanced settings; `default` clears one
anda mcp import --dry-run # servers set up in other apps
anda mcp import github notes=work-notes --from cursor # import them; no names imports every new one
anda mcp events github # the events a server reports
anda mcp triggers # event automations; also: add, get, update, pause, resume, delete
With the daemon running, every command goes through it, so a change applies at
once: a server whose connection settings changed restarts, and one whose change
the connection does not use (a field Anda does not read, say) keeps running.
Failed servers are retried in the background, backing off from 30 seconds to 30
minutes, and the reason is kept for list. Without the daemon, add,
add-json, remove, enable, disable, tool, approval, external-users,
secret, options, import and logout edit the files directly and take effect when the daemon starts. list also shows entries that
were skipped and why, and --json prints any result as JSON.
Edits keep the fields Anda does not read, your ${VAR} references, and the root
the file uses. remove also deletes the server's stored sign-in unless you pass
--keep-credentials. Anda does not watch mcp.json: after editing it by hand,
run anda mcp reload. Where each server came from, its last error, the tool
definitions and instructions you reviewed and how often its tools were called
are kept in ~/.anda/mcp_state.json.
The MCP page
Anda Desktop (MCP in the sidebar) and the extension dashboard (#mcp) manage the
same servers. The page lists each server with its status, and shows its last
error, usage and instructions; its tools, with the approval policy of each, the
server's hints, and what changed since you reviewed it; sign-in; the secrets it
uses; and its entry, with secrets hidden. Add takes a URL with headers, a
command with environment variables, or configuration pasted from another app.
It shows the full command line before anything runs, tests the connection, and
by default stores header values, tokens and keys as secrets, leaving only
${secret:...} references in mcp.json. A server that asks for OAuth opens its
sign-in page in your browser. The Add menu also imports servers from other apps
and browses the MCP Registry (both below), and the Configuration tab edits the
advanced settings.
In Anda Desktop, a link of the form
anda://mcp/install?name=<id>&config=<base64url JSON> opens the Add dialog with
that configuration and a warning to check what it runs. Nothing is saved until
you add it, and a link cannot change an existing server.
Importing from other apps
anda mcp import and Import from other apps on the MCP page read the MCP
settings of Claude Desktop, Claude Code (~/.claude.json), Cursor, VS Code (and
GitHub Copilot's CLI, ~/.copilot/mcp-config.json), Windsurf and Codex
(~/.codex/config.toml), and the project files (.mcp.json,
.cursor/mcp.json, .vscode/mcp.json) of the projects Claude Code knows and of
the current directory (for the CLI) or the daemon's workspace. These files are
only read, never changed.
anda mcp import --dry-run # what each server would become
anda mcp import # every server new to Anda
anda mcp import github notes=work-notes # the ones named; NAME=ID renames
anda mcp import --from cursor --keep-plaintext
Each server is shown with what importing it does: new, renamed when its name is
taken by another server, already in Anda, the same server as one listed
earlier, or one that cannot be imported (an SSE server, say) and why. On the way
in, an entry is translated into Anda's form: VS Code's ${env:NAME},
${userHome} and ${workspaceFolder} are filled in, and Windsurf's
serverUrl, Copilot's tool lists and Codex's tables are read. Header values,
tokens and keys move to secrets unless you pass --keep-plaintext. A VS Code
${input:...} and an environment variable the daemon does not have become
secrets to set: the CLI and the page ask for them, and a server whose secret is
not set yet waits for it. Imported local servers get "inherit_env": false.
What does not carry over, such as an envFile or a list of auto-approved tools,
is listed with the server.
The MCP Registry
Browse the MCP Registry on the MCP page searches the official
MCP Registry. The daemon makes the
request, with its own proxy settings. A server published with a remote endpoint
installs as that endpoint by default, since it runs nothing on your computer;
you can choose one of its npm, PyPI, OCI (Docker) or NuGet packages instead,
which runs as a local command with "inherit_env": false. The install form asks
for the URL variables, headers, environment variables and arguments the server
declares; a value marked secret goes to the secret store. You can test the
server before installing it. The Registry shows only that a server was
published, not that it is safe: its tools still ask before they run until you
allow them.
Secrets
${secret:NAME} in a header, environment value, argument or URL expands to a
secret stored in ~/.anda/mcp_secrets.json, which only your user can read, so
mcp.json holds no tokens and can be shared or backed up as it is. Names use
letters, digits and _, and one secret can serve several servers.
anda mcp secret set GITHUB_PAT # reads the value without echo
gh auth token | anda mcp secret set GITHUB_PAT
anda mcp secret list # names, whether set, and the servers using each
anda mcp secret unset GITHUB_PAT
Values are never shown again, by the CLI, the MCP page or the API: set a new one
to change it. A server whose secret is not set is skipped, with a diagnostic
naming the secret, and starts once you set it; a new value restarts the servers
that use it. Removing a server also deletes the secrets only it used, unless you
pass --keep-credentials.
Approving MCP tool calls
Every call the agent makes to an MCP tool passes an approval check, as shell
commands do. The server's approval policy decides it, for all of its tools or
for one:
| Policy | When the agent asks first |
|---|---|
auto (default) | Unless the session runs with full access. Tools the server marks read-only run without asking while their definition is unchanged. |
ask | Always, even with full access. |
allow | Never, while the tool's definition is unchanged. |
"github": {
"type": "http",
"url": "https://api.githubcopilot.com/mcp/",
"approval": { "default": "allow", "tools": { "merge_pull_request": "ask" } }
}
anda mcp approval github allow # every tool of the server
anda mcp approval github ask --tool merge_pull_request # one tool
anda mcp approval github inherit --tool merge_pull_request # back to the server's policy
The policy is read only when a tool is called, so changing it never reconnects
the server. Scheduled jobs and goals run with full access, so auto tools run
there too. Where nobody can answer an approval, such as an IM chat or a
scheduled job that meets an ask tool, the call is not made and the agent is
told how you can allow it.
An approval card for an MCP tool also offers Always allow (the a key in the
terminal UI): it approves the call and sets that tool to allow.
Anda keeps each tool's definition as the server first served it. When a server
later changes a tool's description or schema, or adds a tool, that tool loses
what its old definition was granted: it is asked about, even under allow,
until you approve one call of it or accept it with anda mcp review github
(all tools) or anda mcp review github <tool>. anda mcp diff github <tool>
shows what changed, and anda mcp get github marks the tools that need review.
The instructions a server gives the model are kept the same way: when they
change, anda mcp get says so and the MCP page shows both versions, until
anda mcp review github accepts them.
Requests from external IM users can call a server's tools only when the server
allows them ("allow_external_users": true, or anda mcp external-users github on), and never a tool that would need approval: an external user cannot
approve on your behalf.
Skills written for other agents can name MCP tools as mcp__<server>__<tool>,
and Anda resolves those names to the same tools. A wildcard such as
mcp__github__* is not resolved: list each tool.
Event automations
Servers that support the MCP Events extension report events, such as a new
issue or a new comment. An automation runs the agent on your instructions when
one arrives. Create one on a server's Events tab on the MCP page, with
anda mcp triggers add, or by asking the agent, whose create_event_trigger
asks for your approval first:
anda mcp events github # event types, how each is delivered, its arguments
anda mcp triggers add github issue.opened --args '{"repo":"owner/name"}' \
--instructions "Label each new issue and summarize it" --batch-window 60
anda mcp triggers get 3 # its state, latest runs and events
anda mcp triggers update 3 --instructions "Label it and assign it" # what you leave out stays
anda mcp triggers pause 3 # also: resume, delete
- Where results go. An automation created on the MCP page or with the CLI replies in a conversation of yours, which later runs continue; one the agent created replies where it was asked, in that conversation or IM chat.
- Batching and limits. Events that arrive within the batch window (30
seconds by default, up to an hour) are handled in one run of up to 20 events.
An automation pauses itself when it would run more often than its hourly
limit (
max_runs_per_hour, 12 by default), which also stops a feedback loop such as replying to an issue and receiving that comment as a new event, and after five failed runs in a row. Resume it when ready. - Trust. Event data comes from the server and is untrusted: runs show it to
the model as data, not instructions, and do not record it as yours. These runs
do not get the full access scheduled jobs have: they can call read-only tools
and tools set to
allow, and anything that needs approval (a write tool underauto, a risky shell command) is refused. - Changes and notices. Change an automation on the Events tab or with
anda mcp triggers update; changing its event, arguments or delivery subscribes again from now. The dialog also names the server's tools the automation would be refused. When an automation pauses itself, its server needs sign-in, or the server ends it, Anda tells you in a short message where its replies go. - Memory. What a run carries is attributed to the server and event
(
mcp:<server>/<event>) as an external source, as an external IM sender's words are, so Formation never records it as yours. - Delivery. Anda keeps a push stream open, or polls, as the event type allows, and keeps the position it reached, so events that arrived while the daemon was stopped are replayed when the server supports it; an event already seen is not run twice. When the server says events were lost, the automation shows it. An automation whose server is disabled, removed or failing waits, one whose server needs sign-in says so, and both resume when the server is back.
- Webhooks through dMsg. Some servers deliver events only by webhook, and
Anda listens on no public port. Mark dMsg's entry with
"events": {"webhook_ingress": true}: for each such automation Anda creates an endpoint there, subscribes the server to it and renews the subscription before it expires, and dMsg relays the deliveries it verified. Without an ingress the automation waits in theneeds_ingressstate.
{
"mcpServers": {
"dmsg": { "command": "dmsg", "args": ["mcp"], "events": { "webhook_ingress": true } }
}
}
Automations, the events they received and their runs are kept in the daemon's database; an endpoint's signing secret is kept in the MCP secret store.
Resources and requests for input
Servers can offer resources: files, records and other context by URI. The agent
lists and reads them with mcp_resources (list, with no server for every
connected one; templates for URI templates to fill in; and read); short text
comes back inline, and long or binary contents as attachments. In Anda Desktop
and the extension, the message box's + menu has MCP resource, which lists the
connected servers' resources and attaches the one you pick to your message. A
read changes nothing, so it follows the server's approval policy as a reviewed
read-only tool does: it runs without asking unless the server is set to ask
or the session asks before everything, and external IM users reach only servers
that allow them. What a server returns is untrusted, like a tool's result.
A server can also ask you for input while one of its tools runs (MCP
elicitation). Anda shows the request above the message box of the conversation
the call runs for: a form becomes one card per field, which checks your answer
(a number in range, an email address, one of the options), and a request to
open a page becomes a card with the link, which opens when you choose Open the
page. Decline tells the server you won't answer; writing in chat instead, or
letting the server's deadline pass (timeouts.elicitation_secs, 300 seconds by
default), cancels the request. Where nobody can answer, such as an automation, a
scheduled job or an IM chat, the request is cancelled at once. The answer goes
to the server, so never enter passwords, keys or payment details in such a card.
Both are on by default. Set "resources": false or "elicitation": false on
an entry, or run anda mcp options <id> --resources off (or
--elicitation off), to turn one off.
Authorizing an MCP server over SSH
The authorization server redirects the browser to
http://127.0.0.1:<gateway port>/mcp/oauth/callback, which the daemon serves
itself. That address is loopback from the browser's point of view, which is
what authorization servers require of a native app — so when Anda runs on a
remote machine, the redirect needs the gateway port forwarded:
ssh -N -L 8042:127.0.0.1:8042 user@your-server
This is the same tunnel used to reach the side panel, so it is usually already
open. -N runs it without a remote shell; add -f to background it.
With no desktop session to open a browser in, connect_mcp_server does not
block. It returns status: "authorization_required" together with an
authorization_url; open that URL in your own browser, approve access, and the
redirect completes the connection through the tunnel. Ask Anda to connect again
to confirm the server is up.
If no port can be forwarded at all, approve access anyway and copy the full URL
from the browser's address bar — it holds the code and state — then have
Anda call connect_mcp_server with that string as redirect_url.
Local Directory Structure
~/.anda/
config.yaml
mcp.json
mcp_secrets.json
mcp_state.json
anda-daemon.pid
channels/
credentials/ # local encrypted trusted-user credential store
db/
keys/ # explicit file keys or Secret Service fallback keys
logs/
bundled-skills/
sandbox/
skills/
skills-manifest.json
skill-backups/
skill-trash/
workspace/
| Directory | Contents |
|---|---|
credentials/ | Local encrypted credential store. Trusted-user private keys are stored here as encrypted COSE Keys. |
db/ | Local memory, conversations, channel state, cron state, object state, and related data. |
keys/ | Explicitly exported or Linux Secret Service fallback signing-key files. Daemon and owner identity private keys are stored in the OS secure credential store by default when it is available. |
logs/ | Daemon and CLI logs. |
channels/ | Channel runtime state. |
bundled-skills/ | Release-managed skills installed by Anda updates. |
sandbox/ | Shell isolation directory when sandboxing is enabled. |
skills/ | Personal runtime skills created, cloned, or edited by the user. |
skills-manifest.json | Skills you disabled in the Dashboard. A file that cannot be parsed is reported and left as is, not reset. |
skill-backups/ | Timestamped copies of a Personal skill's SKILL.md, taken before each update. |
skill-trash/ | Deleted Personal skills moved aside before removal. |
workspace/ | Default workspace for file and shell tools. |
Privacy Boundary
Anda local state, memory graph, conversations, channel state, cron state, logs, and workspace data are stored on your machine by default. Daemon and owner identity private keys are stored in the OS secure credential store by default, while trusted-user private keys are stored in the local encrypted credential store under ~/.anda/credentials/. Explicit file keys and Linux Secret Service fallback keys may exist under ~/.anda/keys/.
On Linux, if no Secret Service provider is available or unlocked, Anda can read existing daemon/owner key files at ~/.anda/keys/anda_bot.key and ~/.anda/keys/user.key, and prints/logs a warning. Both files must be present: an unavailable keyring never causes replacement identities to be generated. For an existing installation, unlock the provider or restore the original keys. Trusted-user private keys remain encrypted with a key derived from the original daemon identity.
For a new installation without an OS keyring, explicitly run anda user init-file-keys before anda start. This creates missing private key files without overwriting existing files, and refuses initialization if local database/credential data or accessible keyring identities already exist. Do not use it to recover an existing installation. Imported COSE keys must identify the Ed25519 curve; an algorithm, when present, must be EdDSA, and a private key’s public component must match its secret. Raw 32-byte Base64 keys remain supported.
To use Secret Service, start and unlock a provider in a user D-Bus session, for example gnome-keyring-daemon --start --components=secrets, make sure DBUS_SESSION_BUS_ADDRESS is set for Anda, then restart it. KDE users can unlock KWallet instead. Existing file identities are migrated together to one keyring bundle; the source files are removed only after the bundle is saved successfully.
However, model providers may still receive prompts, tool-result summaries, and memory formation or recall requests. Choose trusted providers, private endpoints, or proxy policies according to your privacy needs.
Use anda --home /path/to/.anda when you need isolated data for different identities, projects, or tests.
Brain runtime
Set brain.runtime_config to a trusted JSON/YAML file relative to the configuration directory; BRAIN_RUNTIME_CONFIG overrides it. Restart to install bindings before Space loading. The browser Brain inbox and TUI /brain inbox, /brain status, /brain formation <id> use the authenticated caller. Reading is not execution permission; retry an answer with the same event key and text. Recall receipts prove delivery only, and Formation acceptance is not completion. The learning feature is independent of mib; semantic, utility, trust and automatic learning require explicit native configuration and authority. Current IM transports are not automatic action adapters. MIB persistent memory does not claim normal/ungated learning or complete costs.
brain:
runtime_config: null
You can also connect an eligible ChatGPT Plus / Pro plan without an API key:
anda auth login chatgpt
anda auth accounts
anda auth models <profile-id>
anda auth use <profile-id> <model-slug>
anda auth logout <profile-id>
In Anda Desktop, open Settings → Agent configuration → Models. In the extension, open Models on the configuration page or the model section in side-panel settings. Click Continue with ChatGPT, complete browser authorization, then choose Use selected model. Press Ctrl+G in the TUI to sign in. CLI/TUI sign-in selects the first available model; pass --model <slug> to the CLI to choose another. Without a configured model, the daemon serves only authenticated setup controls; Brain, channels and cron start after model selection. All three clients share account and refresh state under the same ANDA_HOME. Credentials are encrypted in chatgpt/accounts.cose, never stored in config.yaml or browser storage.
Changing a ChatGPT plan model waits until running tasks and subagents are idle. ChatGPT plan providers are owner-only: while they are enabled, other users and external IM requests are rejected. Audio, video and transcription require separate providers. A usage limit never silently switches billing to an API key; use ChatGPT usage settings. Existing .codex/auth.json configurations remain compatible, but new connections should use this dedicated sign-in flow.
For a headless or SSH host, run anda auth login chatgpt --no-browser --port 1455 and forward 127.0.0.1:1455 from the browser's machine to the daemon host. To move a session, run anda auth export <profile-id> --output /absolute/path/session.json (disconnects the source), transfer the owner-only file securely over SSH, and run anda auth import /absolute/path/session.json on the destination. Import removes the transfer file and preserves the destination host ID. Activate a model with anda auth use <profile-id> <model-slug>. Never refresh the same session on both hosts.