Skip to main content
Back to posts
Writing

Claude Code at Work: Solving the Enterprise Authentication Problem

How I built claude-switch to seamlessly switch Claude Code between personal and enterprise accounts, syncing plugins, MCP servers, and npm registries

I spend most of my day inside Claude Code. It has become my pair programmer, documentation writer, and thinking partner. But like many developers working at large companies, I hit a friction point early on: I have a personal Claude subscription that I use for side projects, and my employer provides enterprise access through an internal AI gateway. Switching between them was painful.

This post explains the architecture of Claude Code's configuration system, and how I built a workflow to switch between accounts seamlessly. If you use Claude Code at work and at home, this might save you hours of frustration.


The Problem: Two Worlds, One Tool

Claude Code stores its configuration in a hidden .claude directory in your home folder. This single directory holds everything: your authentication tokens, settings, plugins, conversation history, and more. The assumption baked into this design is that you are one person with one account.

But enterprise users live in two worlds:

  • Personal: Direct Anthropic API access via OAuth, using your Claude Pro/Max subscription
  • Work: Access through corporate gateways (Portkey, AWS Bedrock, internal proxies) with SSO authentication

When I wanted to switch from personal coding on a weekend to work on Monday, I had to manually juggle configuration files, clear cached tokens, and pray nothing broke. There had to be a better way.


Understanding Claude Code's Architecture

Before explaining the solution, let me walk you through how Claude Code actually stores its state. This is useful for anyone trying to debug authentication issues or customize their setup.

~/.claude/
    |
    |-- .credentials.json      # OAuth tokens for personal account
    |-- settings.json          # User preferences and API helpers
    |-- gateway-helper-config.json  # Enterprise gateway configuration
    |
    |-- /tokens/               # Enterprise SSO tokens (encrypted)
    |   |-- jwt-*.enc          # JWT tokens for each SSO provider
    |
    |-- /plugins/              # Installed plugins
    |   |-- config.json        # Plugin registry
    |   |-- /repos/            # Plugin source code
    |
    |-- /projects/             # Per-project state and memory
    |-- /logs/                 # Gateway and session logs
    |-- /todos/                # Task lists from sessions
    |-- history.jsonl          # Command history

The Key Files

.credentials.json - This is where personal OAuth tokens live. When you authenticate with claude login, the access token, refresh token, expiration time, and subscription type get stored here:

{
  "claudeAiOauth": {
    "accessToken": "sk-ant-oat01-...",
    "refreshToken": "sk-ant-ort01-...",
    "expiresAt": 1762386054209,
    "scopes": ["user:inference", "user:profile"],
    "subscriptionType": "max"
  }
}

settings.json - This controls Claude Code's behavior. The critical field for enterprise users is apiKeyHelper, which points to a script that provides authentication tokens dynamically:

{
  "apiKeyHelper": "node \"path/to/jwt-token-helper.js\"",
  "statusLine": {
    "type": "command",
    "command": "..."
  }
}

/tokens/jwt-*.enc - Enterprise SSO tokens are stored encrypted. On macOS they go into Keychain, on Windows into Credential Manager, and on Linux/WSL they use AES-256-GCM encrypted files. This is important: your enterprise credentials never sit in plain text.


The Solution: claude-switch

The solution to the dual-account problem is claude-switch - a shell script I wrote that handles the complete context switch between personal and corporate profiles. It does more than just swap authentication; it manages the entire development environment.

Here is what claude-switch handles:

  1. Claude authentication - Swaps settings.json and gateway-helper-config.json between profiles
  2. Plugin and MCP server sync - Keeps your extensions consistent across both profiles
  3. NPM registry - Switches between corporate Artifactory and public npmjs.org
  4. Token management - Backs up and restores encrypted SSO tokens for each profile

The Profile Structure

claude-switch stores profile configurations in a dedicated directory:

~/.claude/profiles/
    |-- personal-settings.json      # Personal Claude settings
    |-- corporate-settings.json     # Corporate Claude settings
    |-- corporate-gateway-config.json   # Gateway configuration
    |-- tokens-personal/            # Backed up personal tokens
    |-- tokens-corporate/           # Backed up corporate tokens
    |-- npmrc-backup-personal       # Personal npm config
    |-- npmrc-backup-corporate      # Corporate npm config

Automatic Plugin Sync

One of the most useful features is automatic plugin and MCP server synchronization. When you install a new plugin or configure an MCP server in one profile, claude-switch merges it into both profiles on the next switch.

The sync uses a simple Python script embedded in the shell script:

# Merge enabledPlugins (union of both)
personal_plugins = personal.get('enabledPlugins', {})
corporate_plugins = corporate.get('enabledPlugins', {})
merged_plugins = {**personal_plugins, **corporate_plugins}

# Merge mcpServers (union of both)
personal_mcp = personal.get('mcpServers', {})
corporate_mcp = corporate.get('mcpServers', {})
merged_mcp = {**personal_mcp, **corporate_mcp}

This means I never have to manually configure the same plugin twice. Install it once, switch profiles, and it is already there.

NPM Registry Switching

This was the feature I did not expect to need but now cannot live without. Many enterprises use private npm registries (Artifactory, Nexus, etc.) for internal packages and security scanning. When I switch to corporate mode, claude-switch also switches my npm registry:

# Corporate mode
npm config set registry "https://artifacts.example.com/artifactory/api/npm/npm-all/"

# Personal mode
npm config delete registry  # Falls back to public npmjs.org

This prevents the common problem of accidentally publishing to the wrong registry or failing to install packages because you are pointing at the wrong source.


The Switch Flow

My workflow is now a single command:

Switching to Corporate

$ claude-switch corporate

Switching to CORPORATE Profile
----------------------------------------

[1/4] Backing up current configuration...
  Backed up personal tokens

[2/4] Syncing plugins and MCP servers...
  Synced enabledPlugins across profiles
  Synced mcpServers across profiles

[3/4] Switching Claude authentication...
  Loaded corporate settings
  Configured corporate gateway

[4/4] Switching NPM registry...
  NPM registry: Corporate Artifactory

----------------------------------------
CORPORATE Profile Active
----------------------------------------

Claude Code:
  Gateway: https://live.ai.example.com
  Auth: Corporate SSO (gateway-helper)
  Billing: Corporate account

NPM:
  Registry: Corporate Artifactory

Next: Run claude to start

Switching to Personal

$ claude-switch personal

Switching to PERSONAL Profile
----------------------------------------

[1/4] Backing up current configuration...
  Backed up corporate tokens

[2/4] Syncing plugins and MCP servers...
  Synced enabledPlugins across profiles
  Synced mcpServers across profiles

[3/4] Switching Claude authentication...
  Loaded personal settings
  Removed corporate gateway config

[4/4] Switching NPM registry...
  NPM registry: Public npmjs.org

----------------------------------------
PERSONAL Profile Active
----------------------------------------

Claude Code:
  Auth: Direct Anthropic authentication
  Billing: Your personal Claude subscription

NPM:
  Registry: Public npmjs.org

Checking Current Status

Running claude-switch without arguments shows the current state:

$ claude-switch

Current Profile Status
----------------------------------------

Claude Profile: CORPORATE
  Gateway: portkey
  URL: https://live.ai.example.com
  Auth: Corporate SSO

NPM Registry: CORPORATE
  Registry: Corporate Artifactory

----------------------------------------

Usage: claude-switch [corporate|personal]

  corporate  Switch to corporate gateway + Artifactory
  personal   Switch to personal Anthropic account + public npm

The beauty is that both profiles can coexist. The script does not touch .credentials.json when switching, and personal Claude does not touch gateway-helper-config.json. They are completely isolated.


Token Storage Security

A common concern with SSO workflows is: where do my credentials actually live?

The gateway helper uses platform-native secure storage:

PlatformStorage Method
macOSKeychain Access
WindowsWindows Credential Manager
Linux/WSLEncrypted files (~/.claude/tokens/)

For Linux and WSL, tokens are encrypted with AES-256-GCM using a user-specific derived key. No external dependencies like libsecret are required. This was a deliberate design choice: we wanted it to work on minimal server environments and corporate-locked machines.


Troubleshooting Common Issues

After using this setup for months, here are the issues I have hit and how to fix them:

"Authentication failed" after it was working

SSO tokens expire. Usually the gateway helper auto-refreshes, but if something goes wrong:

# Clear cached tokens (Linux/WSL)
rm -rf ~/.claude/tokens/

# Switch back to corporate to re-authenticate
claude-switch corporate

Claude Code works but uses the wrong account

Check which profile is active:

claude-switch

This shows exactly which profile is loaded and which npm registry is configured.

Plugins missing after switching

If plugins are not syncing, ensure Python3 is installed. The sync script requires it:

# Check if Python3 is available
python3 --version

# If not installed on Ubuntu/Debian
sudo apt install python3

NPM installing from wrong registry

After switching profiles, verify your npm registry:

npm config get registry

If it shows the wrong registry, run claude-switch again to reset it.


Why This Matters

The broader point here is about developer experience in the age of AI tooling. As AI coding assistants become essential infrastructure, the friction of authentication and configuration will determine adoption.

Enterprise security teams rightfully want control over how AI tools access corporate resources. But if the developer experience is too painful, people will find workarounds - personal accounts on corporate machines, copy-pasting code into web interfaces, or just avoiding AI tools altogether.

claude-switch shows there is a middle path: keep enterprise security intact while making the developer experience seamless. Authentication tokens are managed automatically, plugins stay in sync, and even the npm registry follows along. Switching contexts is a single command that takes two seconds.


Conclusion

If you are using Claude Code at an enterprise and struggling with authentication, here is my advice:

  1. Understand the file structure - Know where Claude Code stores state so you can debug issues
  2. Build a profile switcher - Do not manually swap config files; automate it with a script like claude-switch
  3. Sync your extensions - Plugins and MCP servers should follow you across profiles automatically
  4. Do not forget npm - If your enterprise uses a private registry, include that in your switching logic

The goal is to make the AI tool disappear into your workflow. You should not be thinking about authentication or configuration; you should be thinking about the code you are writing. A few hours spent setting up proper infrastructure pays dividends every single day.


Get the Code

The full claude-switch script is open source and available on GitHub:

github.com/darshshah981/claude-profile-manager

Quick install:

curl -o ~/.local/bin/claude-switch https://raw.githubusercontent.com/darshshah981/claude-profile-manager/main/claude-switch
chmod +x ~/.local/bin/claude-switch
claude-switch init

The script is configurable - edit ~/.claude/profiles/config.sh to customize profile names, gateway URLs, npm registries, and which features to enable. The patterns here are portable across different AI coding assistants; it is really about wrapping any CLI tool with proper enterprise profile management.

More soon.