FabricFabric
ReferenceConfig

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.enc

Nothing 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

TypeUsed for
claude_oauthClaude OAuth token (Claude Max).
anthropic_api_keyDirect Anthropic API key.

Per-LLM-connection (keyed by connection slug)

TypeUsed for
llm_api_keyAPI keys for OpenAI, Google, OpenRouter, Vercel AI Gateway, Ollama (optional), etc.
llm_oauthOAuth access + refresh tokens for ChatGPT Plus / Codex, GitHub Copilot, Google AI Studio, Microsoft Copilot.
llm_iamAWS Bedrock credentials: { accessKeyId, secretAccessKey, region }.
llm_service_accountGCP Vertex service-account JSON.

Per-source (keyed by workspace + source slug)

TypeUsed for
source_bearerBearer tokens for MCP and API sources.
source_oauthOAuth tokens + refresh tokens + registered clientId.
source_apikeyHeader / query / basic API keys.
source_basicBasic-auth { username, password } pairs (stored as JSON).

Per-workspace

TypeUsed for
workspace_oauthWorkspace-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:

OSSource
macOSIOPlatformUUID from ioreg. Tied to the logic board; survives OS reinstalls.
WindowsMachineGuid 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.enc to 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 --commit rotates it.

Setup vs runtime

When you add a credential (paste a key, complete OAuth, etc.):

  1. The value is serialised to JSON.
  2. The JSON is encrypted with the machine-bound key.
  3. credentials.enc is rewritten atomically.

When you use a credential (start a session, call a source):

  1. The file is decrypted in memory.
  2. The specific credential is looked up by ID.
  3. 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:

ProviderRotates refreshToken on every refresh?
MicrosoftYes.
GoogleNo — same refresh token is reused.
SlackNo.
Claude (Anthropic OAuth)No.
Generic OAuthDepends 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.enc

On 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_KEY in the environment for a fabric-cli run invocation, Fabric Agents uses it in memory only.
  • Session content — messages, tool calls, attachments all live in session.jsonl per session. They're not encrypted, but they're also not credentials.
  • Server bearer tokensFABRIC_SERVER_TOKEN for the headless server is never stored in credentials.enc; it's an environment variable, managed by you.

On this page