Skip to content

Identity & credential storage

The Identity & Accounts page covers the feature: accounts and how they’re linked to agents. This page covers the security model: where every credential and key lives at rest, how credentials reach agent processes, and what protects them.

Everything lives under one root, ~/.agentmux (%USERPROFILE%\.agentmux on Windows); dev builds use ~/.agentmux/dev/<branch>/ for their per-channel part. See Data layout for the full tree. The parts that matter for security:

PathContents
channels/<channel>/versions/<version>/data/db/objects.dbPanes and their settings, agents’ HMAC and LAN signing keys and identity tokens, held messages
channels/<channel>/versions/<version>/data/db/filestore.db, sagas.dbPane output and terminal scrollback; the operation log
channels/<channel>/versions/<version>/data/authkey.dev, ipc-port-<hash>The current launch’s auth key and host IPC token (see below)
channels/<channel>/versions/<version>/cef-cache/Chromium profile for browser panes: cookies, site storage, cache
channels/<channel>/wan-identity/wan.dbThe install’s WAN instance keypair, agents’ WAN signing keys, and WAN verification state. Shared by every version of the channel, so upgrades keep them
shared/store.dbAccounts, bundles, drone definitions, MuxBus credential metadata, per-agent MuxBus machine credentials
shared/identity-store.dbAgent-to-account links, skills, MCP servers, the work queue
shared/agents/transcripts/filestore.dbAgent conversation transcripts, continuity summaries, and AgentMux’s record of agents’ memory and of Global Memory
shared/providers/<provider>/, shared/identities/<account>/<provider>/Agent CLIs’ own login directories (see provider CLI logins)
agents/<slug>/Default agent working directories, each with an .mcp.json holding that agent’s signing keys
agents/<name>.json, shared/agents/reactive/Registries of running agents, each entry including its instance’s auth key

On channels other than stable, shared/store.db and shared/identities/ are replaced by per-channel copies (channels/<channel>/identity-store.db, channels/<channel>/identities/) unless AGENTMUX_ISOLATED_AUTH=0 is set (isolated_auth_enabled in crates/common/src/data_paths.rs).

Unix: at each launch, AgentMux makes the data root ~/.agentmux owner-only: it creates it with mode 0700, or removes group and other permissions from an existing one, keeping the owner’s bits (ensure_owner_only_dir, called from DataPaths::ensure_dirs in crates/common/src/data_paths.rs). The subdirectories and most files inside are still created with your umask, but other users can’t reach them through the closed root. This is best effort: if the mode can’t be changed (for example, the directory belongs to another user or sits on a read-only mount), AgentMux logs a warning and starts anyway. It is also skipped when the data root has been pointed at your home directory itself.

These are restricted on their own as well:

File or directoryMode
authkey.dev0600
Registry files agents/<name>.json and shared/agents/reactive/<agent>/<channel>.json0600, set at creation
.mcp.json in an agent’s working directory, and AgentMux’s manifest of the entries it wrote (.claude/.agentmux-managed-mcp-servers.json)0600, written to a temporary file and renamed into place
channels/<channel>/wan-identity/ and its wan.db0700 and 0600
The launcher’s IPC socket directory ($XDG_RUNTIME_DIR/agentmux/ or /tmp/agentmux-<uid>/)0700, and refused if owned by another user
The macOS sign-in helper script, a self-deleting temp file0700, set at creation

An agent working directory outside ~/.agentmux keeps its own permissions; of the files AgentMux writes there, only .mcp.json and its manifest are restricted. To confirm the root is closed, run ls -ld ~/.agentmux.

Windows: files inherit the access control of your profile folder, which by default admits only you, SYSTEM and administrators. authkey.dev additionally gets an owner-only access list that doesn’t inherit from its folder.

A credential attached to an identity account is stored as a SecretRef, a pointer that says where the value is (crates/srv/src/backend/storage/identities.rs). Resolution is in resolve_secret (crates/srv/src/identity/resolver/secret.rs).

API keys and tokens you add in Connectors → Accounts (a GitHub personal access token, an Anthropic or OpenAI API key, and so on) are stored in the OS secret store through the keyring crate: macOS Keychain, Windows Credential Manager, or Linux Secret Service. The entry uses service agentmux and account acct:<account id>; the database holds only this pointer and non-secret metadata (crates/srv/src/identity/secret_store.rs). The value is read at agent launch.

On Linux you need a running Secret Service (GNOME Keyring, KWallet or similar). Without one, saving the key fails with an error; AgentMux has no plaintext fallback.

AgentMux stores only the variable name and reads the value at launch from the AgentMux server’s own environment. That is the environment AgentMux itself was started with, which for an app started from the Start menu, Dock or a desktop launcher is not your shell’s. The value is never written to disk by AgentMux.

For Claude Code, Codex, Gemini, Copilot and OpenClaw logins, AgentMux stores only a directory path, and points the CLI at it with the CLI’s config-directory variable (CLAUDE_CONFIG_DIR, CODEX_HOME, GEMINI_CLI_HOME, COPILOT_HOME, OPENCLAW_HOME). The CLI writes and refreshes its own tokens there, in its own format; AgentMux does not encrypt them. The directories are:

  • shared/providers/<provider>/, the default login shared by every agent of that provider, on every channel;
  • shared/identities/<account>/<provider>/, one per account;
  • the CLI’s usual location in your home directory (for example ~/.claude), for an agent set to use the ambient login.

AgentMux reads one of these tokens itself: at each launch it uses the Claude login from shared/providers/claude/ to fetch the current model list from Anthropic. See Data sovereignty.

The value is stored as-is in the database. resolve_secret returns it only in debug builds (cfg(debug_assertions)); release builds refuse it with an error.

The variant exists, and resolving it always returns an “unsupported” error.

CredentialWhereAt rest
MuxBus Cloud sign-in (access, refresh and ID tokens)OS secret store; email and expiry in shared/store.db. On Windows the tokens are split into chunks across several Credential Manager entries, because one entry holds at most 2,560 bytes (crates/srv/src/backend/storage/muxbus.rs)OS secret store
Per-agent MuxBus machine credentials (client id, client secret, cached access token)shared/store.db, table db_agent_credentialsPlaintext
Passwords saved for HTTP Basic auth in browser panesOS secret store, one entry per identity and site (crates/srv/src/identity/browser_credential_store.rs)OS secret store
Browser-pane cookies and site storagecef-cache/Chromium is started with --password-store=basic (and, on macOS, --use-mock-keychain) so it never touches the OS keychain; by the code’s own description the cookie store then has only obfuscation-level encryption. Treat it as plaintext.
Agents’ signing keys: HMAC key, LAN and WAN Ed25519 private keysobjects.db (HMAC, LAN, and WAN keys minted before wan.db existed), wan.db (WAN), and, for the HMAC and LAN keys only, the agent’s .mcp.json in its working directoryPlaintext
The install’s WAN instance private key, which certifies its agents’ WAN keyswan.dbPlaintext
Agents’ identity tokens (AGENTMUX_AGENT_TOKEN)objects.dbPlaintext
KEY=VALUE lines in an agent definition’s environmentobjects.db, and copied into the pane’s settingsPlaintext
Instance auth key and host IPC tokenauthkey.dev (0600), ipc-port-<hash> (default permissions, inside the owner-only data root on Unix), registry files (0600)Plaintext; regenerated at every launch

At every launch, AgentMux writes the agent’s HMAC key and its LAN private key into the mcpServers.agentmux.env block of .mcp.json in the agent’s working directory, where its MCP server reads them. The WAN key stays in wan.db: AgentMux signs WAN messages itself, and removes a WAN key an older version wrote to .mcp.json (inject_jekt_signing_keys_into_mcp_json and write_mcp_json_respecting_user_servers in crates/srv/src/backend/agent_config.rs). The file is written owner-only (0600 on Unix). An existing .mcp.json is merged, not replaced: MCP server entries AgentMux didn’t write, and other top-level keys, are kept; the agentmux entry is always AgentMux’s. A file that can’t be read or isn’t a JSON object is left untouched, and the agent’s MCP servers aren’t written for that launch.

The default working directory, ~/.agentmux/agents/<slug>/, is excluded from git by a * rule in ~/.agentmux/.gitignore. If you set an agent’s working directory to a project repository, AgentMux writes the agent’s signing keys into that project’s .mcp.json. Add .mcp.json to the project’s .gitignore and don’t commit it. Anyone holding these keys can sign messages as that agent; see Reactive event bus.

At each agent launch (inject_identity_env in crates/srv/src/identity/resolver/inject.rs):

  1. AgentMux looks up the accounts linked to the agent’s definition.
  2. For an API-key account it resolves the SecretRef and sets the provider’s variables in the process environment: GITHUB_TOKEN and GH_TOKEN for GitHub, ANTHROPIC_API_KEY, OPENAI_API_KEY, MOONSHOT_API_KEY (Kimi), AWS_ACCESS_KEY_ID. A failed resolution is logged and skipped.
  3. For an OAuth account it sets the CLI’s config-directory variable. If the account can’t be resolved, the launch is refused, unless the agent is set to use the ambient login.
  4. Credentials go into the process environment, never onto the command line. Container agents receive them through the Docker API, not docker exec -e.
  5. The log records account ids, providers and the number of variables injected, not the values.

AgentMux adds its own variables to every agent process as well: AGENTMUX_AUTH_KEY (full control of the local AgentMux server; a container agent gets a narrower per-agent token in it instead) and AGENTMUX_AGENT_TOKEN. Your MuxBus Cloud login is not passed to agents: MUXBUS_TOKEN and MUXBUS_COGNITO_DOMAIN are removed from every agent’s environment. See the trust model.

It also sets GH_CONFIG_DIR in every agent process on the host (not in container agents), and in commands run on an agent’s behalf, to a per-agent directory under AgentMux’s config directory that holds no gh login; a login made there is removed at the next spawn (crates/srv/src/backend/gh_guard.rs). A plain gh command in an agent therefore can’t act as the gh login you made on the machine. A GitHub token from the agent’s own account (GH_TOKEN) still works.

  • Keychain: update the account’s key; AgentMux rewrites the OS secret-store entry. Agents pick it up at their next launch.
  • Env: change the variable in the environment AgentMux is started from, then restart AgentMux, not just the agents: the value is read from the server’s own environment.
  • OAuthConfigDir: sign in again through the CLI, or the account’s sign-in flow in AgentMux. The CLI refreshes tokens itself.
  • Agent signing keys: the HMAC key is replaced at the agent’s next launch once it is 24 hours old. LAN and WAN keys are not rotated. All three are deleted with the agent, unless another agent still uses that name. The install’s WAN instance key is not rotated either.
  • Instance auth key, host IPC token, lan_key: new at every launch.
  • Anything running as your OS user can read the database files, the .mcp.json files, the CLI login directories, and the environment of agent processes (for example /proc/<pid>/environ on Linux). On Windows and Linux it can also read AgentMux’s OS secret-store entries; on macOS the Keychain may prompt first. The OS secret store protects against other users and offline disk access, not against your own processes.
  • A credential in an agent’s environment is available to everything that agent runs. If you give an agent a GitHub token and it runs npm install, every install script gets GH_TOKEN too.
  • The Env variant trusts AgentMux’s environment. Whatever set that variable before AgentMux started decides what gets injected.
  • Root or an administrator can read all of the above.

These follow from running agents as you. If you need stronger isolation, use OS-level separation: a separate user account, a VM, or a container agent.


Source-of-truth references:

Related: Identity & Accounts (the feature), Data sovereignty, Trust model.