I wanted to run Claude Code under two different accounts (let’s call them .claude-personal + .claude-work) on the same Windows machine, simultaneously.

On paper, this should be easy: there’s guidance floating around that suggests setting the CLAUDE_CONFIG_DIR environment variable so each instance uses a different “home” or “config” directory.

However, in reality, Claude Code doesn’t only store state under ~\.claude\. It also keeps global state right in ~\.claude.json. This means that when both instances share the same real home directory, they will inevitably step on each other.

Rather than wrestle with extensions and ad-hoc env vars or other weird copying solutions, I made each instance run with a fully separate home directory, to avoid conflict plus a couple of symbolic links to avoid duplicating binaries and tool state.

Here’s what I did (obviously with Claude’s help).

What was conflicting?

Claude Code maintains a mix of:

  • Project settings: .claude\settings.json / .claude\settings.local.json inside a repo
  • Global settings: Mostly stored inside ~\.claude\ including files and folders such as .credentials.json, file-history, plugins, tasks, etc.

Why mostly? Because it also stores config inside ~\.claude.json. When you try to run two accounts against the same ~ (home) directory, even when you specify different config directories, this file becomes the shared point of failure.

Diagram of two Windows home folders ("Personal" and "Work") each with their own `.claude.json`, showing a red conflict icon when they point to the same file, and a green check when separated; clean infographic style.

Step 1: Use the native installation for Claude

I followed the instructions from here to do a native PowerShell install of Claude.

Maybe you can make it work in other ways as well, but this seemed simplest and should hopefully ensure automatic updates keep working.

Step 2: Stop relying on the IDE extension

This was the first pragmatic decision.

The IDE extensions felt janky for this specific setup, and I couldn’t get them to consistently respect the environment overrides anyway.

So I disabled the extension entirely and ran Claude Code from a terminal inside the IDE. I haven’t yet missed the lack of IDE integration…

Step 3: Create a dedicated “home” per account

I’m using PowerShell as my primary shell, so I added a helper function to my PowerShell profile.

Where is the PowerShell profile?

For PowerShell 7+ on Windows, the common path is:

  • $HOME\Documents\PowerShell\Microsoft.PowerShell_profile.ps1

You can also just print your actual profile path:

$PROFILE

The idea

Create two folders like:

  • C:\Users\<you>\.claude-split\.claude-personal\
  • C:\Users\<you>\.claude-split\.claude-work\

Then, when starting Claude Code, set environment variables so the process believes that folder is home.

The variable that seems to matter on Windows is $USERPROFILE.

Fixed folders.

The path variable

Claude will also expect to find claude.exe at ~\.local\bin\claude.exe. I had hoped to do something funky with symbolic links to the original install to avoid multiple copies of claude.exe. In practice, I could not make it work, because the symlink seemed to keep getting overwritten by the actual executable. If you manage to do it, please let me know 😀.

Example: PowerShell launcher functions

In order to automate this, add something like this to your PowerShell profile:

function Invoke-ClaudeWithProfile {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$ProfileName,

        [Parameter(ValueFromRemainingArguments = $true)]
        $ClaudeArgs
    )

    # Build the base directory, fake home directory,
    # and profile-specific bin directory Claude will use.
    $baseDir = Join-Path $env:USERPROFILE ".claude-split"
    $targetPath = Join-Path $baseDir $ProfileName
    $profileBin = Join-Path $targetPath ".local\bin"

    # Create the fake home directory and the fake claude directory
    New-Item -ItemType Directory -Path $profileBin -Force | Out-Null

    # Store the current user home and path variables
    $oldUserProfile = $env:USERPROFILE
    $oldPath = $env:PATH

    try {
		
        # Set the USERPROFILE variable to our fake directory
        $env:USERPROFILE = $targetPath
        # Add the fake Claude directory to the PATH variable
        $env:PATH = "$profileBin;$env:PATH"
        Write-Host "--- Claude Instance: [$ProfileName] ($targetPath) ---" -ForegroundColor Cyan

        # Run claude (with these variables set) and whatever arguments were passed
        & claude @ClaudeArgs
    }
    finally {
		
        # Return the USERPROFILE and PATH variables back to their
        # previous values when claude exits
        $env:USERPROFILE = $oldUserProfile
        $env:PATH = $oldPath
        Write-Host "--- Profile Restored ---" -ForegroundColor Gray
    }
}

Some subtleties about what is happening here

When you run this function for the first time (assuming we are running it for .claude-personal), this is what happens:

  1. We add our fake home directory to PATH.

  2. PowerShell looks for claude.exe at C:\Users\<you>\.claude-split\.claude-personal\.local\bin\claude.exe, but it won’t find it because it doesn’t exist yet.

  3. PowerShell then looks for claude.exe at C:\Users\<you>\.local\bin\claude.exe, which the original Claude install put on the system path. It should find it and run it.

  4. Since the fake home directory is set, Claude itself expects claude.exe at C:\Users\<you>\.claude-split\.claude-personal\.local\bin\claude.exe, doesn’t find it, and downloads a fresh copy to that location.

On subsequent uses of this function, it immediately uses claude.exe at C:\Users\<you>\.claude-split\.claude-personal\.local\bin\claude.exe.

Aside from duplicating .exe files, one downside is that C:\Users\<you>\.local\bin\claude.exe may not get updated if you always launch Claude through profile functions. In practice, that should not be a major issue in this setup.

Step 4: Calling this function

You would then create shortcut functions for each separate Claude instance you want to run.

So for example, I might have:

function claude-work {
    Invoke-ClaudeWithProfile -ProfileName ".claude-work" @args
}

function claude-personal {
    Invoke-ClaudeWithProfile -ProfileName ".claude-personal" @args
}

This forces each instance to have its own:

  • ~\.claude.json
  • ~\.claude\...

…beneath the fake home folder we defined, which should prevent cross-account corruption.

Once you “fake” a different home directory, some tools start looking for binaries and configs in places you didn’t expect.

To avoid maintaining duplicate copies (and to keep tools happy), I created some symlinks. In the end, the only one I kept was for the glab-cli config directory, as the others either didn’t work out or were not necessary. You may need to do something similar for other CLI tools you use.

As I noted above, I tried doing this for claude.exe, but it didn’t work out, so I have to live with some duplication there.

Important: On many Windows setups, creating symlinks requires an elevated PowerShell session (Run as Administrator). Some machines allow Developer Mode symlinks without elevation, but assume you’ll need admin unless you know otherwise.

I had to do this for GitLab CLI (glab).

On Windows, glab stores its config under:

  • %LOCALAPPDATA%\glab-cli\ (including config.yml)

(At least in my installation.)

With our fake home directories, we may want each Claude profile to see the same glab state.

Run in elevated PowerShell:

$realGlabDir = Join-Path $env:LOCALAPPDATA "glab-cli"
$homeGlabDir = "C:\Users\<you>\.claude-split\.claude-work\AppData\Local\glab-cli"

New-Item -ItemType Directory -Force -Path (Split-Path $homeGlabDir) | Out-Null
New-Item -ItemType SymbolicLink -Path $homeGlabDir -Target $realGlabDir

GitHub CLI note

Interestingly, I didn’t have to add extra symlinks for GitHub tooling in my setup. It just worked with Claude having the fake home directory…

Current status

So far, I haven’t found any unwanted side effects.

There may be additional state Claude Code relies on that could get confused in edge cases, but for now, this approach has been stable: two accounts, one Windows PC, no cross-contamination.

Let me know how you get on and if you find any bugs!

Originally posted: