Skip to content

Identity bundles

An Identity bundle is a named credential set that AgentMux assigns to an agent instance at launch. The bundle decouples what an agent does (configured by the Memory bundle and the agent’s provider) from who it acts as (configured by Identity). The same Memory + provider can run as different identities — work, personal, demo — without restart.

An Identity is a logical grouping of per-provider credentials:

Provider classCredential typeExamples
githubPersonal access tokenrepo scopes, gh CLI auth
awsProfile name (referenced from ~/.aws/)dev, qa, prod
anthropicAPI keyClaude API access (fallback to OAuth)
customFree-form key/valueAny provider-specific token

The set of providers in a bundle is open-ended — AccountProvider is "github" | "aws" | "anthropic" | "custom" today, with custom covering anything that doesn’t fit a named slot.

Identity bundles now carry OAuth credentials as first-class members, not just API keys. Each bundle’s Claude / Codex / Copilot OAuth login lives in its own auth-config directory, so two bundles for the same provider can hold genuinely distinct OAuth sessions (work account vs personal, etc.). The bundle stores a pointer to the directory plus a status field (valid / expired / needs_reauth / unknown) that surfaces in the bundle manager so credential health is visible without launching an agent.

The OAuth invariant: a successful OAuth flow always lands bound to a bundle. If you start an OAuth flow without one selected, the system creates a new bundle on the spot rather than letting the credential live “ambient” — that ambient path used to silently let two named identities share ~/.claude, with no actual isolation.

Migration is automatic: any pre-bundles OAuth login becomes a synthesized Default identity bundle pointing at the existing ~/.claude (or equivalent), no token movement required. The Default bundle behaves like any other — you can rename it, delete it, or swap an agent to a different bundle without losing the credential.

For the spec, see SPEC_OAUTH_IDENTITY_BUNDLES_2026_05_22.md in the main repo.

Identity is not a widget-bar entry. Two paths reach it:

Per-agent (the original surface):

  1. Open an Agent pane (pinned in the widget bar).
  2. Click the cog (⚙) in the pane header.
  3. Switch to the Identity tab.

App-wide manager (hamburger menu):

  1. Click the hamburger (≡) at the top of the tab bar.
  2. Choose Identity & Memory.
  3. The bundle manager modal opens — browse and edit any bundle without first opening a specific agent.

The hamburger-menu path opens a singleton modal shared across the app: if it’s already open in another window, clicking the entry focuses that window instead of opening a duplicate. The per-agent cog path stays scoped to the current pane.

The view registration (view: "identity") and IdentityPaneViewModel exist for pane.open RPC and right-click menu paths, but the primary paths are the two above.

The Launch Agent modal exposes a single Identity dropdown. The default selection is the singleton blank Identity (“no creds — use ambient environment”). Selecting a real Identity at launch:

  1. Resolves the bundle’s accounts.
  2. Computes the per-provider env vars (GH_TOKEN, AWS_PROFILE, …) the agent’s CLI needs.
  3. Spawns the agent process with those env vars set.
  4. Records the identity_id foreign key on the db_agent_instances row.

You can swap Identity on a running agent by reopening the Identity tab and picking a different bundle — the spawn-time env injection re-applies on next turn.

If the selected provider requires OAuth (or an API key) and isn’t authenticated yet, the modal’s Pre-Launch Auth panel appears inline and gates the Launch button. In the current release the OAuth result is session-scoped; persistent bundle storage that ties an OAuth login to a reusable Identity is Phase C and not yet shipped.

Identity bundles live in two SQLite tables in the sidecar’s objects.db:

TableOwns
db_identity_bundlesBundle metadata: id, name, description, is_blank flag
db_identity_bindingsPer-provider binding: (identity_id, provider) → account_id

The actual credential records live in db_identity_accounts (the individual-credentials table). db_identity_bindings is a junction between Identity bundles and that table.

These tables are part of objects.db’s flat schema (run_object_schema). See SPEC_CONSOLIDATE_FORGE_IDENTITY_INTO_AGENT_2026_04_13.md for the canonical model.

  • Not a credential vault. AgentMux doesn’t encrypt or audit credential access at the OS level today. The bundle is a grouping convenience — the credentials still live wherever the provider’s CLI puts them.
  • Not the same as a session. Identity is durable; the agent instance owns a foreign key to it. Sessions come and go; Identity survives.
  • Not a top-level pane. No widget-bar entry. See Pane types for the full pane catalog.