Credentials
How Fabric Agents stores API keys, OAuth tokens, and other secrets — encrypted file format, machine-bound key derivation, credential types, and revocation.
Fabric Agents stores every sensitive value — API keys, OAuth access and refresh tokens, Basic auth credentials — in a single encrypted file that travels with your config directory:
~/.fabric-agent/credentials.encNothing else on your machine is trusted to hold secrets. The file is never written as plaintext, and it isn't synced anywhere by default.
What's inside
Credentials are grouped by type and scope:
Global
| Type | Used for |
|---|---|
claude_oauth | Claude OAuth token (Claude Max). |
anthropic_api_key | Direct Anthropic API key. |
Per-LLM-connection (keyed by connection slug)
| Type | Used for |
|---|---|
llm_api_key | API keys for OpenAI, Google, OpenRouter, Vercel AI Gateway, Ollama (optional), etc. |
llm_oauth | OAuth access + refresh tokens for ChatGPT Plus / Codex, GitHub Copilot, Google AI Studio, Microsoft Copilot. |
llm_iam | AWS Bedrock credentials: { accessKeyId, secretAccessKey, region }. |
llm_service_account | GCP Vertex service-account JSON. |
Per-source (keyed by workspace + source slug)
| Type | Used for |
|---|---|
source_bearer | Bearer tokens for MCP and API sources. |
source_oauth | OAuth tokens + refresh tokens + registered clientId. |
source_apikey | Header / query / basic API keys. |
source_basic | Basic-auth { username, password } pairs (stored as JSON). |
Per-workspace
| Type | Used for |
|---|---|
workspace_oauth | Workspace-level MCP OAuth credentials. |
File format
credentials.enc is a binary file with a small header and an AES-256-GCM payload:
┌─ Header (64 bytes) ──────────────────────┐
│ Magic "FABRIC01\0" (8 bytes) │
│ Flags uint32 LE (4 bytes) │
│ Salt PBKDF2 salt (32 bytes) │
│ Reserved (20 bytes) │
├─ Encrypted payload ──────────────────────┤
│ IV GCM IV (12 bytes) │
│ Auth tag GCM tag (16 bytes) │
│ Ciphertext AES-256-GCM JSON (variable) │
└──────────────────────────────────────────┘The payload is a JSON object keyed by credential ID. You'll never need to read it directly — the format is stable but not part of Fabric Agents' public API.
Key derivation
The encryption key is derived from a machine identifier, not a password:
| OS | Source |
|---|---|
| macOS | IOPlatformUUID from ioreg. Tied to the logic board; survives OS reinstalls. |
| Windows | MachineGuid under HKLM\SOFTWARE\Microsoft\Cryptography. Set at OS install. |
| Linux | /etc/machine-id (or /var/lib/dbus/machine-id as a fallback). Set at OS install. |
The identifier is run through PBKDF2 (100,000 iterations, 32-byte key, random per-install salt) together with the salt from the file header. The same install on the same machine produces the same key; a different machine can't decrypt without the identifier.
If the OS can't yield an identifier for any reason, Fabric Agents falls back to username:homedir as the key material. This is weaker and we note it in the logs.
What that means in practice
- Credentials don't travel by copy. Copying
credentials.encto another machine won't work — the machine ID doesn't match. - Reinstalling the OS invalidates credentials. The machine ID usually changes, so you'll be re-prompted for everything.
- Cloning a VM disk preserves credentials. VMs share the machine ID unless you regenerate it. On Linux,
systemd-machine-id-setup --commitrotates it.
Setup vs runtime
When you add a credential (paste a key, complete OAuth, etc.):
- The value is serialised to JSON.
- The JSON is encrypted with the machine-bound key.
credentials.encis rewritten atomically.
When you use a credential (start a session, call a source):
- The file is decrypted in memory.
- The specific credential is looked up by ID.
- Decrypted values are passed to the agent or network client — they're never written to disk in plaintext.
OAuth refresh
Every OAuth credential carries accessToken, expiresAt, and (for most providers) refreshToken. Roughly five minutes before expiry, Fabric Agents refreshes in the background.
Refresh-token rotation varies by provider:
| Provider | Rotates refreshToken on every refresh? |
|---|---|
| Microsoft | Yes. |
| No — same refresh token is reused. | |
| Slack | No. |
| Claude (Anthropic OAuth) | No. |
| Generic OAuth | Depends on the provider. Fabric Agents always stores whatever the refresh endpoint returns. |
If a refresh fails (the user revoked the grant on the provider side), the credential is marked "needs auth" and the app shows a Reconnect button.
Revocation
- Delete a source — the app removes the credential entry for that source. The token itself is still valid on the provider side; revoke it there if you want to be sure.
- Re-install Fabric Agents — the install script does not touch
credentials.enc. Your credentials survive app updates. - Reset profile — the Windows installer offers a "reset profile" option that wipes both config and credentials. On macOS / Linux, do the equivalent with
rm -rf ~/.fabric-agent/. - Revoke at the provider — the real kill switch. Remove "Fabric Agents" from your Linear / GitHub / Google / Microsoft / Slack connected-apps list. The next refresh will fail and the credential goes to "needs auth".
File permissions
On macOS and Linux, credentials.enc is written inside ~/.fabric-agent/. Home-directory permissions (0700 by default on most distros) keep it readable only by you. If you've relaxed those permissions, tighten them:
chmod 700 ~/.fabric-agent
chmod 600 ~/.fabric-agent/credentials.encOn Windows, %APPDATA%\Fabric Agents\ inherits NTFS ACLs from your profile — typically not readable by other users on the same machine.
Shared-machine considerations
If another user has read access to your credentials.enc and access to the machine's identifier (same macOS, same Windows install, same Linux /etc/machine-id), they can decrypt the file. In practice on a single-user machine that's not possible; on a shared dev box it is.
For multi-user scenarios, run Fabric Agents under each user's own OS account rather than sharing one home directory. The per-user home-directory isolation plus the OS-level identifier gives you defence in depth.
What isn't stored here
- LLM provider API keys passed at runtime — if you set
LLM_API_KEYin the environment for afabric-cli runinvocation, Fabric Agents uses it in memory only. - Session content — messages, tool calls, attachments all live in
session.jsonlper session. They're not encrypted, but they're also not credentials. - Server bearer tokens —
FABRIC_SERVER_TOKENfor the headless server is never stored incredentials.enc; it's an environment variable, managed by you.
Related
- config.json — what lives outside credential storage.
- MCP authentication — credential types for MCP sources, OAuth flow.
- APIs — credential types for REST API sources.
- LLM connections — credential types per provider.
Custom endpoints
Connect Fabric Agents to Ollama, LMStudio, OpenRouter, Vercel AI Gateway, vLLM, or any OpenAI- or Anthropic-compatible endpoint via pi_compat connections.
Network proxy
Configure an HTTP/HTTPS proxy and a custom CA certificate for Fabric Agents — for corporate networks, TLS inspection middleboxes, and local proxies like mitmproxy.