صياغة التميز في البرمجيات
دعنا نبني شيئاً استثنائياً معاً.
اعتمد على شركة Lasting Dynamics للحصول على جودة برمجيات لا مثيل لها.
محمد بوكريم
أغسطس 12, 2026 • 13 min read
Running two Claude Code accounts on one machine is a configuration problem, not a licensing one. Claude Code ships no command for switching identity. What it ships is an overridable configuration directory, a credential store that changes per operating system, and a documented credential hierarchy. This guide lines up the verified methods for keeping two environments apart with two Claude Code accounts, from the CLAUDE_CONFIG_DIR variable to a Docker image with a dedicated volume.
The setup is familiar to any team that works on client projects. On one side sits the personal subscription, a Pro or Max plan used for prototypes and internal repositories. On the other sits the seat the client assigned inside their own Team or Enterprise organization, the only one cleared to touch their code. That is two Claude Code accounts, two organizations, two liability perimeters, and they belong in two separate environments.
By default Claude Code keeps a single configuration per operating system user. Settings, session history, plugins, personal MCP servers, directory trust and the login session all live there together. Alternating between two Claude Code accounts with logout and login does not separate that data, it overwrites it.
Three consequences follow. Friction: every switch means another browser login, and logging out also resets first-launch state, so the next run walks you through setup again. Contamination: prompt history, permanent command approvals and MCP servers follow the user rather than the project. Governance: if the client enforced an organization pin, the wrong credential does not produce a warning, it prevents startup.
Can you use two Claude Code accounts on the same machine?
Yes. There is no native command to switch a Claude Code account, but the documentation points to the CLAUDE_CONFIG_DIR environment variable as useful for running multiple accounts side by side, and containers, a separate OS user and a virtual machine all remain available.
The most common mistake starts with a wrong assumption here. State lives in three places, and only two of them move together. The first is the ~/.claude directory: user settings, session history, plugins. The second is the ~/.claude.json file, which sits outside that directory and holds the OAuth session, user and local scope MCP servers, per-project state such as allowed tools and directory trust, plus assorted caches. The third is the credential store, and that is where the paths diverge by operating system.
إن official authentication documentation is precise about it. On macOS credentials are stored in the encrypted system Keychain. On Linux they live in ~/.claude/.credentials.json with file mode 0600. On Windows they live in %USERPROFILE%\.claude\.credentials.json and inherit the access controls of the user profile directory. Then comes a clause that covers only two of the three systems: if CLAUDE_CONFIG_DIR is set on Linux or Windows, the credentials file lives under that directory instead.
~/.claude/ settings, session history, plugins
~/.claude.json OAuth session, user MCP servers, per-project state
~/.claude/.credentials.json credentials, Linux and Windows only
system Keychain credentials, macOS
And that brings the detail that pays for the whole read: because ~/.claude.json sits outside the configuration directory, mounting a volume at ~/.claude without also setting CLAUDE_CONFIG_DIR does not keep you signed in. That is why so many attempts to isolate two Claude Code accounts inside containers break on the first rebuild.

This is the native route, and the documentation names this exact use case. إن CLAUDE_CONFIG_DIR variable overrides the configuration directory, whose default is ~/.claude. Settings, session history and plugins all land under that path, and on Linux and Windows so do credentials. The same entry describes it as useful for running multiple accounts side by side, and offers a shell alias as the example.
# ~/.zshrc or ~/.bashrc
alias claude-ld='CLAUDE_CONFIG_DIR="$HOME/.claude-ld" claude'
alias claude-client='CLAUDE_CONFIG_DIR="$HOME/.claude-client" claude'
Aliases work, but they have to be remembered. Across a mixed set of repositories it pays to bind the variable to the folder rather than to the command, so the Claude Code account follows the project instead of the memory of whoever is typing. With direnv that takes one file per repository.
# .envrc at the root of the client repository
export CLAUDE_CONFIG_DIR="$HOME/.claude-client"
The first launch against a fresh directory asks for a login, because that configuration is empty: you authenticate the second Claude Code account once and never again. From then on /status confirms which Claude Code account is active, since the Login method row shows the subscription account in use, and an API key row appears when an API key supplies the credential.
The method costs five minutes and removes the daily friction. On Linux and WSL2 it also closes the credential question outright. On macOS it does not, and the reason is worth understanding precisely.
دعنا نبني شيئاً استثنائياً معاً.
اعتمد على شركة Lasting Dynamics للحصول على جودة برمجيات لا مثيل لها.
The clause tying CLAUDE_CONFIG_DIR to credentials is written for Linux and Windows. About macOS the documentation states one thing only: credentials live in the system Keychain. It does not extend the clause to the Mac, and it does not publish the name of the Keychain entry. So the verified perimeter is this. On macOS the variable separates settings, session history, plugins and ~/.claude.json, while for credentials there is no documented separation per configuration directory.
In practice, on a Mac the native method separates the working environment without guaranteeing separation of identity. When you need the second one as well, two documented routes remain, and they are the next two sections: a container, where you are on Linux and the clause does apply, or an environment credential, which by documented precedence outranks the saved session.
Either way, read the real state of the machine before trusting a setup. Launch Claude Code against the second directory and run /status: the Login method row reports which account the session is using. Organization and email are not part of that routine view: they appear only in the row Claude Code shows for an expired login, from version 2.1.210 onward.
CLAUDE_CONFIG_DIR="$HOME/.claude-client" claude
# then, inside the session:
/status
Does CLAUDE_CONFIG_DIR isolate credentials on macOS too?
Not as far as the documentation goes: the credentials clause is limited to Linux and Windows, and on macOS credentials sit in the system Keychain. Isolating a second Claude Code account on a Mac calls for a container, an environment credential or a separate OS user.
Inside a container you are on Linux, which moves the problem onto ground where the documentation is explicit: credentials go back to being a file on disk, and they follow CLAUDE_CONFIG_DIR. Two containers with two distinct volumes are two Claude Code accounts kept apart even when the host is a Mac. The Docker image is therefore not an exotic alternative to the native method, it is its extension for when isolation has to survive scrutiny.
Anthropic publishes two artifacts. The first is a Dev Container Feature that installs Claude Code into the image you already use: one line in the features block, and the build installs Node as well when the base image does not provide it.
{
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"features": {
"ghcr.io/anthropics/devcontainer-features/claude-code:1.0": {}
}
}
The second is a complete example in the anthropics/claude-code repository, in three files: devcontainer.json for volumes, capabilities and extensions, Dockerfile for the base image and tooling, init-firewall.sh for egress. The image starts from node:20, runs as a non-root user named node, and installs git, gh, zsh, fzf, jq and delta alongside iptables and ipset. The documentation presents it as a working example to copy and adapt, not as a maintained base image.
The firewall is what makes the container defensible. The dev container documentation states that the script blocks all outbound traffic except the domains that are needed, and that this requires the NET_ADMIN و NET_RAW capabilities, added through runArgs. In the repository file the default policies are DROP and the allowlist resolved at runtime covers api.anthropic.com, registry.npmjs.org, the telemetry endpoints, the VS Code domains and the GitHub network ranges read from its metadata API. Read the script before treating it as a hard boundary: it also accepts DNS on port 53 and SSH on port 22 to any host, plus the whole subnet of the host machine, and it covers IPv4 only.
Seven lines govern the whole thing: a named volume mounted at the configuration directory, and CLAUDE_CONFIG_DIR pointed at the same path, so that .claude.json also lands inside the volume and the login survives rebuilds.
"remoteUser": "node",
"mounts": [
"source=claude-code-config-${devcontainerId},target=/home/node/.claude,type=volume"
],
"containerEnv": {
"CLAUDE_CONFIG_DIR": "/home/node/.claude"
}
إن ${devcontainerId} placeholder in the volume name is the detail that turns a configuration into a multi identity system: every repository gets its own volume, therefore its own credential, without anyone having to remember an alias. An internal repository and a client repository become two Claude Code accounts separated by construction.
بدءاً من الفكرة إلى الإطلاق، نقوم بتصميم برامج قابلة للتطوير مصممة خصيصاً لتلبية احتياجات عملك.
شارك معنا لتسريع نموك.
There is a useful side effect. Because the container runs Claude Code as a non-root user and confines command execution, the documentation treats --dangerously-skip-permissions as acceptable for unattended work. The flag is rejected when the process runs as root, so remoteUser has to point at an unprivileged account.
Two warnings are written into the documentation itself. Run with --dangerously-skip-permissions, the container does not stop a hostile repository from exfiltrating whatever is reachable inside it, including the credentials stored in the configuration directory, so keep the practice for repositories you trust. And do not mount host secrets such as ~/.ssh or cloud credential files into the container: prefer repository-scoped or short-lived tokens, and pass cloud provider credentials as environment variables through containerEnv or a secret rather than as files mounted from the host.

The third route touches neither directories nor containers. Claude Code picks its credential along a documented hierarchy: cloud provider credentials first, then ANTHROPIC_AUTH_TOKEN, then ANTHROPIC_API_KEY, then the output of apiKeyHelper, then CLAUDE_CODE_OAUTH_TOKEN, and last the OAuth session created with /login.
The practical consequence is that an environment variable beats the subscription you logged into. Exporting a token in a shell binds that shell to one specific Claude Code account, whatever the configuration directory happens to hold. On macOS this is the most direct answer to the limitation in the previous section.
The cleanest candidate is the long lived token. The claude setup-token command opens the same browser authorization flow as /login and prints a one year OAuth token to the terminal without saving it anywhere. It requires a Pro, Max, Team or Enterprise plan and can only make model requests, so it establishes no Remote Control sessions and fetches no claude.ai connectors, while locally configured MCP servers keep working.
claude setup-token
# copy the token, then in the shell dedicated to the project:
export CLAUDE_CODE_OAUTH_TOKEN="the-generated-token"
The alternative is a Console API key, to be used knowing what it implies: when ANTHROPIC_API_KEY is set the key is used instead of your subscription even while you are logged in, always in non-interactive mode and after a single approval in interactive mode. Falling back to the subscription takes an unset. It also changes the cost model, because the key bills per token against the Console organization.
When the requirement is absolute separation, you move up a level. A dedicated operating system user is the only option that settles the macOS case without a container: Apple documents that an initial default keychain is created for each Mac user, so two users are two distinct credential stores. The price is the highest friction of the lot, because switching Claude Code accounts means switching user session, with editors, SSH keys and tooling installed twice.
A dedicated virtual machine is the strongest separation, with its own kernel, and the documentation points to it for evaluating untrusted code or when a security policy requires kernel level separation. There is also Claude Code on the web, which runs each session in an Anthropic-managed virtual machine, with a proxy enforcing a default allowlist and a second proxy holding the GitHub token outside the sandbox while issuing narrowly scoped credentials inside it. Claude Code on the web requires a Claude subscription.
One clarification so the tools do not get conflated: the built-in Bash sandbox isolates filesystem and network, not identity. It limits what a command can touch, not which Claude Code account answers. It complements everything above rather than replacing it.
نحن نصمم ونبني منتجات رقمية عالية الجودة ومميزة.
الموثوقية والأداء والابتكار في كل خطوة.
This is the case that derails improvised setups. Organizations can deploy managed settings, which no user or project scope can override, and two keys bear directly on anyone holding more than one identity: forceLoginMethod و forceLoginOrgUUID. With both set, Claude Code restricts login to the listed organization and exits at startup if the active credential belongs to a different one.
That is not a dismissible warning, it is process termination. The block also covers sessions authenticated by ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN أو apiKeyHelper, because organization membership cannot be verified for an environment credential. From version 2.1.212 every login path enforces forceLoginMethod, while the paths differ on the organization pin: claude setup-token و /install-github-app enforce only the first key.
Managed settings arrive through several channels: server-managed settings delivered at sign-in, MDM policies on macOS and Windows, or files deployed to /Library/Application Support/ClaudeCode/ on macOS, /etc/claude-code/ on Linux and WSL, and C:\Program Files\ClaudeCode\ on Windows. Check those paths before questioning your own configuration.
What happens when a client pins a specific organization?
مع
forceLoginMethodوforceLoginOrgUUIDin managed settings, Claude Code exits at startup whenever the active credential belongs to another organization, API key sessions included. In that context each Claude Code account has to live in an environment separated by construction.
The operational lesson is blunt. With client-enforced managed settings, keeping two Claude Code accounts in one configuration is not an inconvenience, it is an error condition.
Two methods carry the load, and four more exist for the cases they do not cover. The choice crosses the operating system, the isolation the contract demands, and the friction the team will absorb every morning.
| Method | Separates credentials | Friction | Where it fits |
|---|---|---|---|
| CLAUDE_CONFIG_DIR | Documented on Linux and Windows | الحد الأدنى | Daily default, internal repositories |
| Docker image or dev container | Yes, macOS hosts included | متوسط | Client work, unattended runs |
| Token in the environment | Yes, by documented precedence | منخفضة | CI, scripts, macOS companion |
| Separate OS user | Yes, distinct keychain | عالية | Tight contractual requirements |
| Virtual machine | نعم | Very high | Untrusted code, kernel separation |
| Claude Code on the web | Yes, Anthropic-managed | None | Delegating from a bare device |
Read across, the table says one thing: on Linux and WSL2 the native method settles it, on macOS a second layer is needed to keep each Claude Code account apart. Anyone on client projects with an organization pin can skip straight to the container row.
For us this is not theoretical: we work in parallel on internal products and on client repositories that carry their own organizations and their own contractual constraints. The rule we set for ourselves is that identity is not chosen by hand, it is determined by the repository you enter.
The first tier applies to everyone. Each developer keeps distinct configuration directories, one per context, wired to the project through direnv rather than an alias to remember. It costs five minutes per machine, it removes history and MCP contamination, and /status makes it obvious which Claude Code account will answer before the first request goes out.
The second tier kicks in on client projects, and there the Docker image is not negotiable. The dev container lives in the repository, versioned with the code, with a named volume per project and CLAUDE_CONFIG_DIR pointed at the mount, so the client credential exists inside that volume and nowhere else. The firewall starts in default deny and we open only the domains the project genuinely uses. The user stays non-root.
Around that sit four rules we apply without exception. Host secrets do not enter containers, so no mounted ~/.ssh and no cloud credential files. Repository tokens are narrowly scoped and short-lived. Before opening a session on client code the active identity gets checked rather than assumed. After every unattended run we review what was writable and what the session created.
The payoff is not only security, it is onboarding. A new developer clones the repository, opens the dev container, and lands in the right environment with the right Claude Code account without reading a page of instructions. Keeping two Claude Code accounts apart stops being personal discipline and becomes a property of the project, which is the only way it holds over time.
Our take, in one line
Use CLAUDE_CONFIG_DIR for everyday work, and a container with a dedicated volume when the separation between two Claude Code accounts has to survive an audit rather than just your memory.
Setting up a second Claude Code account on a project with organization or NDA constraints?
Talk to our AI engineering team →
This article was written by Mohamed Boukrim at Lasting Dynamics, an EU-based custom software development company. We design and ship agent-assisted development environments for teams that work on their own code and on client code, with the isolation and traceability constraints that brings.
Every account carries its own plan. Claude Code is included in the Pro, Max, Team and Enterprise plans, and the token produced by "claude setup-token" requires one of them. With a Console API key, billing instead runs per token against the organization the key belongs to rather than against a subscription plan.
Limits follow the plan of the account you logged in with. On Pro, Max, Team and seat-based Enterprise you can read your progress under Settings → Usage, against a five-hour session limit and weekly limits; on Enterprise the usage pool belongs to the organization; with an API key there is no cap but a per-token charge against the account the key belongs to.
Run "/status": the login method row shows the subscription account in use, and an API key row appears when an API key supplies the credential. Organization and email are not part of that routine view, they appear only in the row Claude Code shows for an expired login, from version 2.1.210 onward. Claude Code also warns at startup when a login is within three days of expiring, from version 2.1.217; versions from 2.1.203 warned five days out.
Not for separating configuration: on Windows credentials live in "%USERPROFILE%\.claude\.credentials.json" and follow CLAUDE_CONFIG_DIR, so the native method works. WSL2 matters if you want the built-in Bash sandbox, which is not supported on native Windows: there the options are WSL2 or a container.
In the anthropics/claude-code repository, folder ".devcontainer", across three files: "devcontainer.json", "Dockerfile" and "init-firewall.sh". It ships as a working example to copy and adapt rather than a maintained base image, so review the firewall allowlist, the base image and the pinned Claude Code version before relying on it.
حوّل الأفكار الجريئة إلى تطبيقات قوية.
لنصنع معاً برمجيات تُحدث تأثيراً.
محمد بوكريم
I am a Software Engineer and Backend Developer with a relentless focus on software quality and robust architecture. I don't believe in shortcuts; outstanding results are the direct product of daily commitment and hard work. Alongside my team, I leverage Agile methodologies and continuous process evaluation to push boundaries and optimize performance. I approach every challenge with a highly competitive mindset: I work tirelessly to reach the top, and once there, I keep pushing to maintain the lead.