Múltiplas contas do Claude Code no VSCode
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.jsondo VSCode (o do perfil novo começa praticamente vazio); - keybindings e snippets;
- layout, arquivos recentes e estado da interface;
globalStorageeworkspaceStorage, 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
-
Feche todas as sessões do Claude Code, nos dois perfis.
-
Escolha a pasta central. Se o
~/.claudede antes da divisão ainda existe, use~/.claude/plugins: é para lá que os caminhos antigos já apontam, e oclaudesem 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 -
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 -
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 -
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 oinstalled_plugins.jsonà mão. Os plugins marcados comoFALTAno passo anterior também se resolvem reinstalando. -
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
installPathde 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_KEYestiver 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
codepuro, o VSCode sobe semCLAUDE_CONFIG_DIRe 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.jsoncostumam 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
~/.claudeoriginal 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.