Múltiplas contas do Claude Code no VSCode

Por Gleydson Tavares em · atualizado em

Quem usa o Claude Code com uma conta de trabalho e outra pessoal na mesma máquina costuma cair na rotina de deslogar e logar de novo a cada troca de projeto. Este tutorial monta um ambiente em que cada conta tem seu próprio perfil e a janela do VSCode já abre logada na conta certa.

No fim você terá:

  • um diretório de configuração por conta, isolado pelo próprio Claude Code;
  • funções no shell que abrem o VSCode (ou o CLI) no perfil certo;
  • o histórico e as permissões dos projetos antigos distribuídos entre os perfis;
  • uma única instalação de plugins, compartilhada pelos dois perfis.

Os exemplos usam macOS e zsh, com os perfis ~/.claude-work e ~/.claude-personal. Troque os nomes pelos seus.

Onde o Claude Code guarda cada coisa

O Claude Code guarda estado em três lugares:

Onde O que guarda
~/.claude.json Config e estado. Tem oauthAccount (email e organização), projects (permissões aprovadas, trust dialog, MCP por projeto), os servidores MCP de usuário e caches.
~/.claude/ Dados. projects/ com os transcripts das sessões, plugins/, settings.json e memória.
Keychain do macOS O token OAuth, no item Claude Code-credentials.

A conta mora no Keychain. O oauthAccount do .claude.json é só o nome e o email exibidos na interface; apagar esse trecho não desloga ninguém.

Por isso não adianta trocar ~/.claude por um symlink que aponta para outro perfil, que é o que algumas extensões de “perfis” fazem. O symlink muda plugins e histórico de lugar, mas não encosta no .claude.json nem no Keychain, e a conta continua a mesma. Se ~/.claude já existe como diretório, a extensão nem consegue criar o link e falha com EEXIST: file already exists.

A variável CLAUDE_CONFIG_DIR

O Claude Code tem uma variável de ambiente nativa, CLAUDE_CONFIG_DIR, que muda a raiz de configuração inteira: no lugar de ~/.claude e ~/.claude.json, ele passa a usar $CLAUDE_CONFIG_DIR/ e $CLAUDE_CONFIG_DIR/.claude.json. Dá para ver o efeito num diretório descartável:

mkdir /tmp/cfgtest
CLAUDE_CONFIG_DIR=/tmp/cfgtest claude mcp list
# No MCP servers configured
ls -a /tmp/cfgtest
# .claude.json  (criado agora)

O Keychain acompanha: o nome do item de credencial é derivado do diretório de configuração. Depois de logar em dois perfis, aparecem itens assim:

Claude Code-credentials            ← ~/.claude (padrão)
Claude Code-credentials-a1b2c3d4   ← perfil 1
Claude Code-credentials-e5f6a7b8   ← perfil 2

Cada diretório tem sua credencial. O próprio Claude Code isola as contas; você só precisa definir a variável certa em cada janela.

Passo 1: funções no shell

No ~/.zshrc, crie uma função por perfil para abrir o VSCode:

code-work() {
  CLAUDE_CONFIG_DIR="$HOME/.claude-work" \
    code -n --user-data-dir "$HOME/.vscode-work" "$@"
}

code-personal() {
  CLAUDE_CONFIG_DIR="$HOME/.claude-personal" \
    code -n --user-data-dir "$HOME/.vscode-personal" "$@"
}

Depois é só code-work ~/Projects/algum-projeto.

O --user-data-dir é obrigatório. O VSCode usa um único processo para todas as janelas; sem essa flag, a janela nova é aberta pelo processo que já está rodando e herda o ambiente dele, e a variável que você acabou de definir é ignorada. Com um --user-data-dir diferente, o VSCode sobe um processo separado, que enxerga a variável.

Se você também usa o CLI fora do VSCode, crie o equivalente:

claude-work()     { CLAUDE_CONFIG_DIR="$HOME/.claude-work" claude "$@"; }
claude-personal() { CLAUDE_CONFIG_DIR="$HOME/.claude-personal" claude "$@"; }

O terminal integrado de uma janela aberta com code-work já herda a variável, então lá dentro basta rodar claude.

Passo 2: primeiro login

Abra cada perfil uma vez e faça login com a conta correspondente. Os diretórios são criados sozinhos e o Keychain ganha um item por perfil.

Numa máquina nova, ou se você ainda não tem histórico que queira manter, o tutorial termina aqui, com exceção do passo 5 (plugins), que vale a pena de qualquer jeito. Os passos 3 e 4 são para quem já tem projetos acumulados num perfil único.

A janela nova parece vazia

Ao abrir com um --user-data-dir novo, o VSCode aparece como recém-instalado: sem seus ajustes e com o layout padrão. As extensões continuam instaladas. O --user-data-dir e o --extensions-dir são flags independentes, e como só a primeira mudou, as extensões ainda vêm de ~/.vscode/extensions, compartilhadas entre os perfis.

O que o --user-data-dir isola:

  • o settings.json do VSCode (o do perfil novo começa praticamente vazio);
  • keybindings e snippets;
  • layout, arquivos recentes e estado da interface;
  • globalStorage e workspaceStorage, onde as extensões guardam estado interno.

As extensões rodam, mas com o estado zerado; as que têm login próprio vão pedir de novo. As configurações do VSCode você copia uma vez:

cp ~/Library/Application\ Support/Code/User/settings.json \
   ~/.vscode-work/User/settings.json

Se preferir extensões separadas por perfil, adicione --extensions-dir às funções. O custo é instalar e atualizar extensões em dois lugares.

Passo 3: migrar o histórico

Os transcripts ficam em ~/.claude/projects/, um diretório por projeto. O nome do diretório é o caminho absoluto do projeto com /, . e _ trocados por -:

Caminho do projeto Diretório do transcript
~/Projects/acme-api -Users-voce-Projects-acme-api
~/Projects/ruby-3.4/loja -Users-voce-Projects-ruby-3-4-loja
~/Projects/app_v2/core -Users-voce-Projects-app-v2-core

O ponto de ruby-3.4 e o underscore de app_v2 também viram traço. Em shell:

slug() { echo "$1" | sed 's/[\/._]/-/g'; }

slug "/Users/voce/Projects/acme-api"
# -Users-voce-Projects-acme-api

Como exemplo, quatro projetos, dois de cada lado:

~/Projects/acme-api      → trabalho
~/Projects/acme-web      → trabalho
~/Projects/meu-blog      → pessoal
~/Projects/jogo-2d       → pessoal

Copie os diretórios para o perfil certo. Use cp em vez de mv: o ~/.claude original continua funcionando enquanto você testa.

mkdir -p ~/.claude-work/projects ~/.claude-personal/projects

cp -R ~/.claude/projects/-Users-voce-Projects-acme-api \
      ~/.claude/projects/-Users-voce-Projects-acme-web \
      ~/.claude-work/projects/

cp -R ~/.claude/projects/-Users-voce-Projects-meu-blog \
      ~/.claude/projects/-Users-voce-Projects-jogo-2d \
      ~/.claude-personal/projects/

Passo 4: migrar as permissões

O que você já aprovou em cada projeto (allowedTools, trust dialog, servidores MCP do projeto) fica na chave projects do ~/.claude.json, indexada pelo caminho do projeto:

jq '.projects | keys[]' ~/.claude.json
# "/Users/voce/Projects/acme-api"
# "/Users/voce/Projects/acme-web"
# "/Users/voce/Projects/meu-blog"
# "/Users/voce/Projects/jogo-2d"

Sem migrar essa chave, o projeto abre no perfil novo pedindo aprovação de tudo de novo. Gere um .claude.json por perfil, cada um com seus projetos. Primeiro, liste os caminhos de trabalho:

WORK=(
  "/Users/voce/Projects/acme-api"
  "/Users/voce/Projects/acme-web"
)

O perfil de trabalho recebe os projetos da lista. O --args entrega os caminhos ao jq em $ARGS.positional:

jq '.projects |= with_entries(
      select(.key as $k | $ARGS.positional | index($k)))' \
   ~/.claude.json --args "${WORK[@]}" \
   > ~/.claude-work/.claude.json

O perfil pessoal recebe o resto, com o mesmo filtro terminado em | not. Assim você não precisa listar os projetos pessoais e nenhum fica de fora:

jq '.projects |= with_entries(
      select(.key as $k | $ARGS.positional | index($k) | not))' \
   ~/.claude.json --args "${WORK[@]}" \
   > ~/.claude-personal/.claude.json

Confira as contagens:

jq '.projects | length' ~/.claude-work/.claude.json      # 2
jq '.projects | length' ~/.claude-personal/.claude.json  # 2
jq '.projects | length' ~/.claude.json                    # 4, intacto

Os dois arquivos gerados herdam também os servidores MCP de usuário do ~/.claude.json original. Daqui em diante, cada perfil tem sua lista: um servidor MCP novo precisa ser registrado nos dois, por exemplo com CLAUDE_CONFIG_DIR=~/.claude-work claude mcp add ....

Copie também o settings.json, que guarda hooks, permissões globais e statusline:

cp ~/.claude/settings.json ~/.claude-work/
cp ~/.claude/settings.json ~/.claude-personal/

Passo 5: uma instalação de plugins para os dois perfis

Cada perfil tem sua própria pasta plugins/. Com dois perfis, isso significa baixar, guardar e atualizar cada plugin duas vezes, e em pouco tempo os perfis ficam com versões diferentes do mesmo plugin. A alternativa é manter uma pasta única e fazer a plugins/ de cada perfil apontar para ela com um symlink.

O que tem na pasta de plugins

Item Conteúdo
cache/ O código de cada plugin, uma pasta por versão (cache/<marketplace>/<plugin>/<versão>).
marketplaces/ Os clones dos marketplaces de onde os plugins vêm.
installed_plugins.json Plugins instalados, com o caminho absoluto de cada versão (installPath).
known_marketplaces.json Marketplaces conhecidos, com o caminho absoluto do clone (installLocation).
data/ Estado que cada plugin grava para si.
synced/ Marketplaces sincronizados a partir da conta no claude.ai, numa pasta com o id da conta no nome.

Nada disso tem credencial. Login e token continuam no .claude.json e no Keychain de cada perfil, e a lista de plugins ativos continua no settings.json de cada perfil (enabledPlugins). Compartilhar a pasta não mistura as contas.

Por que compartilhar a pasta inteira

Compartilhar só cache/, onde fica o código, não basta. O Claude Code marca como órfãs as versões que nenhum plugin registrado no installed_plugins.json usa mais e depois apaga essas pastas. Com cache/ compartilhado e installed_plugins.json separado, a limpeza de um perfil apaga a versão que o outro ainda está usando. Com a pasta inteira compartilhada, os dois perfis leem o mesmo registro e a limpeza fica consistente.

Se você copiou plugins/ ao dividir os perfis

Copiar a pasta leva junto os caminhos absolutos. Os plugins instalados antes da divisão continuam registrados com installPath apontando para ~/.claude/plugins, e os instalados depois ficam na pasta de cada perfil. O resultado é um estado misto em que atualizar pelo perfil mexe em arquivos de outra pasta. Para ver onde cada perfil aponta:

jq -r '.plugins[][].installPath' ~/.claude-work/plugins/installed_plugins.json
jq -r '.[].installLocation' ~/.claude-work/plugins/known_marketplaces.json

Se aparecerem caminhos de mais de uma pasta, a centralização resolve.

Como centralizar

  1. Feche todas as sessões do Claude Code, nos dois perfis.

  2. Escolha a pasta central. Se o ~/.claude de antes da divisão ainda existe, use ~/.claude/plugins: é para lá que os caminhos antigos já apontam, e o claude sem variável nenhuma também passa a usar a mesma instalação. Numa instalação nova, mova a pasta de um dos perfis para um lugar neutro:

    mkdir -p ~/.claude-shared
    mv ~/.claude-work/plugins ~/.claude-shared/plugins
  3. Em cada perfil, guarde a pasta atual como backup, leve o synced/ para a pasta central e crie o link:

    CENTRAL="$HOME/.claude/plugins"   # ou ~/.claude-shared/plugins
    
    for P in ~/.claude-work ~/.claude-personal; do
      [ -d "$P/plugins" ] || continue
      mv "$P/plugins" "$P/plugins.bak"
      if [ -d "$P/plugins.bak/synced" ]; then
        mkdir -p "$CENTRAL/synced"
        cp -R "$P/plugins.bak/synced/." "$CENTRAL/synced/"
      fi
    done
    
    for P in ~/.claude-work ~/.claude-personal; do
      [ -e "$P/plugins" ] || ln -s "$CENTRAL" "$P/plugins"
    done
  4. Confira se todo caminho registrado existe:

    {
      jq -r '.plugins[][].installPath' "$CENTRAL/installed_plugins.json"
      jq -r '.[].installLocation' "$CENTRAL/known_marketplaces.json"
    } | while read -r p; do
      [ -d "$p" ] && echo "ok     $p" || echo "FALTA  $p"
    done
  5. Abra um perfil e rode /plugin. Um plugin que só existia no outro perfil não aparece na lista central: reinstale-o por ali. É mais seguro do que editar o installed_plugins.json à mão. Os plugins marcados como FALTA no passo anterior também se resolvem reinstalando.

  6. Use os dois perfis por alguns dias e, se tudo funcionar, apague os plugins.bak.

Para desfazer num perfil, remova o link e restaure o backup:

rm ~/.claude-work/plugins
mv ~/.claude-work/plugins.bak ~/.claude-work/plugins

No dia a dia

  • Instale ou atualize um plugin por qualquer perfil. O download vai para a pasta central e o symlink sobrevive à instalação.
  • No outro perfil, o plugin aparece como instalado e desativado. Ative pelo /plugin; nada é baixado de novo.
  • O installPath de um plugin novo pode vir gravado pelo caminho do link (~/.claude-work/plugins/...). Funciona nos dois perfis, porque o link aponta para a mesma pasta.
  • Depois de atualizar, reinicie as sessões abertas. Plugins que mantêm um processo em segundo plano podem continuar rodando a versão antiga, carregada em memória, mesmo depois que a pasta dela foi apagada.

O que passa a ser compartilhado

  • A pasta data/ é uma só. Um plugin que guarda informação localmente, como histórico ou memória de sessões, passa a ver os dados das duas contas. Se isso for um problema para algum plugin, deixe-o ativo em um perfil só.
  • Os dois perfis escrevem nos mesmos arquivos de registro. Evite instalar ou atualizar plugins nos dois ao mesmo tempo.

Hooks e statusline

Hooks e statusLine ficam no settings.json, que continua separado por perfil. Configure nos dois.

Quando um plugin traz o script da statusline, o caminho dele inclui a versão, e um caminho fixo quebra na primeira atualização. Resolva a versão mais nova na hora de rodar:

"statusLine": {
  "type": "command",
  "command": "bash \"$(ls -d ~/.claude/plugins/cache/<marketplace>/<plugin>/*/ | sort -V | tail -1)<caminho/do/script.sh>\""
}

O sort -V ordena por versão (2.10.0 depois de 2.9.0), o que um sort comum não faz. A statusline aparece no CLI dentro do terminal; o painel da extensão do VSCode não exibe essa barra.

Cuidados

  • Se ANTHROPIC_API_KEY estiver exportada no shell, os dois perfis autenticam pela mesma chave, porque o Claude Code dá prioridade à API key sobre o login OAuth. Só o histórico fica separado. Defina a variável apenas no comando que precisa dela.
  • Aberto pelo Dock ou pelo code puro, o VSCode sobe sem CLAUDE_CONFIG_DIR e usa o perfil padrão, ~/.claude. Para recarregar uma janela sem perder o perfil, use Developer: Reload Window, que mantém o mesmo processo.
  • Renomear um diretório de perfil gera um item novo no Keychain, e o antigo fica esquecido lá.
  • Ferramentas que editam o .claude.json costumam deixar cópias (.claude.json.bak-*) em cada perfil. Elas guardam a lista de projetos e a configuração de MCP; revise e apague de vez em quando.

Prós e contras

A favor:

  • O próprio Claude Code isola conta, histórico, permissões e MCP.
  • Não depende de extensão de terceiro.
  • Não há symlink global trocando de destino. Com duas janelas abertas, a troca de um link global faria a outra janela passar a usar o perfil errado no meio da sessão.
  • Os plugins são instalados e atualizados uma vez e ficam na mesma versão nos dois perfis.
  • É reversível: os backups e o ~/.claude original continuam disponíveis.

Contra:

  • Funciona por janela. Cada janela do VSCode usa uma conta; um workspace que mistura projetos das duas contas não se encaixa.
  • É preciso abrir o VSCode pelo terminal, com as funções do passo 1.
  • As configurações do VSCode ficam duplicadas.
  • Os dados de plugin são compartilhados entre as contas.
  • O Claude Code não prevê uma pasta de plugins compartilhada. Uma versão futura pode mudar esse comportamento; nesse caso, o backup desfaz a mudança.