Skip to content

Multi-subscription support: install to non-default CLAUDE_CONFIG_DIR and propagate it to local member spawns #268

@kumaakh

Description

@kumaakh

Background

Claude Code supports fully sandboxed multi-subscription setups via the CLAUDE_CONFIG_DIR environment variable — each client project gets its own config dir, its own OAuth token, its own MCP registrations, and its own billing bucket. This is a well-understood pattern (see reference conversation: https://claude.ai/share/35ebedb6-2e32-44a2-84dc-6c1bc68c45c1).

A common real-world setup: a consultant or agency runs separate Claude subscriptions per client, each mapped to a different CLAUDE_CONFIG_DIR. When apra-fleet is used as the PM/orchestrator inside one of these profiles, two gaps surface.


Gap 1 — Installer only targets the default Claude installation

The installer registers the MCP server and writes settings into the default ~/.claude/ directory. Users running from a non-default profile (e.g. CLAUDE_CONFIG_DIR=~/.claude-clientA) get no registration there, so fleet is invisible to that Claude instance.

Request: Accept a target profile directory at install time — via a flag (--claude-dir <path>) or by honouring the ambient CLAUDE_CONFIG_DIR — and write all registrations (MCP server, hooks, settings) into that directory instead of the system default.


Gap 2 — Local member spawns (claude -p) may fall back to the wrong profile

claude -p inherits CLAUDE_CONFIG_DIR from its parent process if the var is set, but if it is not explicitly injected at spawn time, child processes can silently fall back to $HOME/.claude/ — a different subscription and a different billing bucket.

Per the reference conversation, Pattern 1 (explicit env injection at spawn) is the most defensive approach:

child_process.spawn('claude', ['-p', task], {
  env: { ...process.env, CLAUDE_CONFIG_DIR: profile.configDir }
})

Request: When the orchestrator dispatches a local member, explicitly pass CLAUDE_CONFIG_DIR into the spawned process's environment, sourced from the orchestrator's own runtime profile. This ensures tokens, MCP credentials, and session history all stay within the originating subscription — no cross-billing.


Combined effect

A user running fleet from a sandboxed profile should be able to:

  1. Install fleet into that profile's config dir with one command
  2. Dispatch local doer/reviewer members that bill exclusively against that subscription

Neither should require manual env-var wiring or knowledge of internals.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions