Skip to main content

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​

SettingPurpose
addrLocal gateway address, default 127.0.0.1:8042.
sandboxWhen true, shell execution goes through ~/.anda/sandbox.
https_proxyProxy used for model and channel requests.
modelModel providers for the agent and memory brain.
transcriptionProvider for voice input and audio attachment transcription.
ttsProvider for voice playback.
channelsTelegram, 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_prompt supplies vocabulary hints to Groq and OpenAI Whisper. StepFun uses its own transcription.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_bytes controls the self-hosted endpoint's upload limit independently of the cloud limit.
  • tts.max_text_length is 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_format selects StepFun output (mp3, opus, wav, or flac). Edge, OpenAI, and Google output MP3. Unknown formats are rejected; raw pcm is rejected because no client can play it, so use wav instead. Artifact extensions always match the produced audio.
  • If the tts.default_provider or transcription.default_provider section is missing or invalid, startup fails with that provider's error. Other invalid provider sections are skipped with a warning.
  • Edge requires edge-tts on PATH (pip install edge-tts). Set tts.edge.binary_path to edge-tts; the edge-playback wrapper is not supported. Cancelling or timing out synthesis terminates the subprocess.
  • StepFun ASR requires a final transcript.text.done event. 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:

FieldPurpose
startupWhen 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.
lifecycleHow 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.
tasksOpts 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.
timeoutsDeadlines 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).
concurrencyWhich 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_envLocal 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.
resourcesWhether the agent and the apps may list and read the server's resources. On unless false.
elicitationWhether 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:

PolicyWhen 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.
askAlways, even with full access.
allowNever, 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 under auto, 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 the needs_ingress state.
{
"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/
DirectoryContents
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.jsonSkills 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.

tip

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.