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.
Where AgentMux keeps data
Section titled “Where AgentMux keeps data”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:
| Path | Contents |
|---|---|
channels/<channel>/versions/<version>/data/db/objects.db | Panes and their settings, agents’ HMAC and LAN signing keys and identity tokens, held messages |
channels/<channel>/versions/<version>/data/db/filestore.db, sagas.db | Pane 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.db | The 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.db | Accounts, bundles, drone definitions, MuxBus credential metadata, per-agent MuxBus machine credentials |
shared/identity-store.db | Agent-to-account links, skills, MCP servers, the work queue |
shared/agents/transcripts/filestore.db | Agent 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).
File permissions
Section titled “File permissions”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 directory | Mode |
|---|---|
authkey.dev | 0600 |
Registry files agents/<name>.json and shared/agents/reactive/<agent>/<channel>.json | 0600, 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.db | 0700 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 file | 0700, 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.
Credentials, by kind
Section titled “Credentials, by kind”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).
Keychain: OS secret store
Section titled “Keychain: OS secret store”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.
Env: environment variable
Section titled “Env: environment variable”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.
OAuthConfigDir: provider CLI logins
Section titled “OAuthConfigDir: provider CLI logins”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.
PlaintextDev: debug builds only
Section titled “PlaintextDev: debug builds only”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.
SecretsManager: not implemented
Section titled “SecretsManager: not implemented”The variant exists, and resolving it always returns an “unsupported” error.
Credentials that aren’t SecretRefs
Section titled “Credentials that aren’t SecretRefs”| Credential | Where | At 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_credentials | Plaintext |
| Passwords saved for HTTP Basic auth in browser panes | OS secret store, one entry per identity and site (crates/srv/src/identity/browser_credential_store.rs) | OS secret store |
| Browser-pane cookies and site storage | cef-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 keys | objects.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 directory | Plaintext |
| The install’s WAN instance private key, which certifies its agents’ WAN keys | wan.db | Plaintext |
Agents’ identity tokens (AGENTMUX_AGENT_TOKEN) | objects.db | Plaintext |
KEY=VALUE lines in an agent definition’s environment | objects.db, and copied into the pane’s settings | Plaintext |
| Instance auth key and host IPC token | authkey.dev (0600), ipc-port-<hash> (default permissions, inside the owner-only data root on Unix), registry files (0600) | Plaintext; regenerated at every launch |
Signing keys in .mcp.json
Section titled “Signing keys in .mcp.json”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.
How credentials reach agent processes
Section titled “How credentials reach agent processes”At each agent launch (inject_identity_env in crates/srv/src/identity/resolver/inject.rs):
- AgentMux looks up the accounts linked to the agent’s definition.
- For an API-key account it resolves the
SecretRefand sets the provider’s variables in the process environment:GITHUB_TOKENandGH_TOKENfor GitHub,ANTHROPIC_API_KEY,OPENAI_API_KEY,MOONSHOT_API_KEY(Kimi),AWS_ACCESS_KEY_ID. A failed resolution is logged and skipped. - 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.
- Credentials go into the process environment, never onto the command line. Container agents receive them through the Docker API, not
docker exec -e. - 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.
Rotation
Section titled “Rotation”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.
What’s not protected
Section titled “What’s not protected”- Anything running as your OS user can read the database files, the
.mcp.jsonfiles, the CLI login directories, and the environment of agent processes (for example/proc/<pid>/environon 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 getsGH_TOKENtoo. - The
Envvariant 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:
crates/common/src/data_paths.rs— data root,ensure_dirs,ensure_owner_only_dir,wan_identity_dir,identities_dir,provider_auth_dir,isolated_auth_enabledcrates/srv/src/backend/storage/wan_identity.rs—wan.dbcrates/srv/src/backend/gh_guard.rs—GH_CONFIG_DIRin agent processescrates/srv/src/backend/storage/identities.rs—SecretRefcrates/srv/src/identity/resolver/secret.rs(resolve_secret),crates/srv/src/identity/resolver/inject.rs,crates/srv/src/identity/resolver/provider.rs— resolution and injectioncrates/srv/src/identity/secret_store.rs,crates/srv/src/identity/browser_credential_store.rs,crates/srv/src/backend/storage/muxbus.rs— OS secret store usecrates/srv/src/backend/storage/agent_credentials.rs— per-agent MuxBus machine credentialscrates/srv/src/backend/agent_config.rs(inject_jekt_signing_keys_into_mcp_json,write_mcp_json_respecting_user_servers) — signing keys in.mcp.jsoncrates/srv/src/backend/reactive/registry.rs,crates/cef/src/dev_authfile.rs,crates/launcher/src/ipc/mod.rs— the explicitly restricted filescrates/cef/src/app/mod.rs— Chromium password-store switches
Related: Identity & Accounts (the feature), Data sovereignty, Trust model.