CLI em Python para recuperar o histórico de chats do Cursor depois de renomear ou mover a pasta de um projeto.
Quando o caminho do workspace muda, o Cursor trata o projeto como novo e os chats somem da UI. Esta ferramenta relinka os metadados do workspace antigo para o novo — sem mover, renomear ou apagar pastas do projeto.
- Relinka todos os chats do workspace (
composerHeaders, JSON legado e glass) - Reescreve paths absolutos dentro dos chats (
composerData+bubbleId) — chips@file,fsPath, URIs — no padrão do cursor-helper - Dry-run por padrão — nada é gravado sem
--execute - Backup automático com
--revert - Modo
--repairquando a pasta antiga já não existe - Alternativa
--junction(Windows) sem alterar o SQLite --scan-orphans— lista (e opcionalmente arquiva) metadados sem pasta local- Paths via flags,
.envou prompt interativo
| OS | Windows |
| Python | 3.10+ |
| Cursor | Abra o caminho novo ao menos uma vez (File → Open Folder) |
| Admin | Só necessário para --junction |
Feche o Cursor antes de aplicar alterações (ou use --quit-cursor).
git clone https://github.com/toledomg/cursor-chat-migrate.git
cd cursor-chat-migrate
python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txt# 1. Simula (dry-run)
python migrate-cursor-chats.py --from "F:\Projetos\antigo" --to "F:\Projetos\novo"
# 2. Aplica
python migrate-cursor-chats.py --execute --from "F:\Projetos\antigo" --to "F:\Projetos\novo"Sem --from / --to, o script usa o .env ou pergunta no terminal.
Abra o projeto no caminho novo e confira os chats. Só então apague a pasta antiga, se quiser — o script não a remove.
Relinka metadados em AppData / ~/.cursor. Não mexe nas pastas do projeto.
python migrate-cursor-chats.py # dry-run
python migrate-cursor-chats.py --execute # aplica
python migrate-cursor-chats.py --quit-cursor --execute # fecha o Cursor e aplicaUse quando a pasta antiga já foi renomeada ou apagada:
python migrate-cursor-chats.py --repair --from "F:\caminho\antigo" --to "F:\caminho\novo"
python migrate-cursor-chats.py --repair --execute --from "..." --to "..."Restaura um backup criado pelo script:
python migrate-cursor-chats.py --revert # lista / pergunta
python migrate-cursor-chats.py --revert 20260802-120000 # por timestamp
python migrate-cursor-chats.py --revert --executeApaga pastas em %APPDATA%\Cursor\User\backups\cursor-chat-migration-* (só as criadas por este script). Exclusão permanente — não dá para --revert depois.
# Só lista (dry-run)
python migrate-cursor-chats.py --clean-backups
# Apaga todos
python migrate-cursor-chats.py --clean-backups --execute
# Mantém os 2 mais recentes, apaga o resto
python migrate-cursor-chats.py --clean-backups --keep 2 --execute
# Apaga um backup específico
python migrate-cursor-chats.py --clean-backups 20260802-120000 --executeCria um junction Windows (caminho antigo → pasta nova) sem alterar o SQLite. Requer terminal como Administrador.
python migrate-cursor-chats.py --junction
python migrate-cursor-chats.py --junction --execute| Metadados | Junction | |
|---|---|---|
| Altera SQLite | Sim | Não |
| Move pastas do projeto | Não | Não |
| Requer Admin | Não | Sim |
| Abrir projeto por | Caminho novo | Caminho antigo |
Lista metadados do Cursor cuja pasta (ou .code-workspace) não existe mais no disco — lixo acumulado após delete/move de projetos.
# Só relatório (dry-run)
python migrate-cursor-chats.py --scan-orphans
# Arquiva órfãos em backups/ (libera espaço; desfaz com --revert)
python migrate-cursor-chats.py --scan-orphans --execute
python migrate-cursor-chats.py --scan-orphans --quit-cursor --executeO que é varrido:
| Local | Critério de órfão |
|---|---|
%APPDATA%\Cursor\User\workspaceStorage\* |
workspace.json aponta para path inexistente (ou JSON inválido) |
%USERPROFILE%\.cursor\projects\* |
slug com path conhecido via workspace.json e pasta local ausente |
- Dry-run imprime nome do projeto, path original, pasta de storage e tamanho
- Com
--execute, os itens são movidos parabackups/(nãormdireto) — recuperáveis via--revert - Slugs opacos (ex.: só dígitos) entram como “não resolvidos” e não são removidos automaticamente
- Drives desmontados / pastas de rede offline também aparecem como órfãos — confira o relatório antes de
--execute
Prioridade: --from / --to → variáveis no .env → prompt interativo.
cp .env.example .envOLD_PROJECT_PATH=F:\Projetos\meu-projeto-antigo
NEW_PROJECT_PATH=F:\Projetos\meu-projeto-novo| Variável | Descrição |
|---|---|
OLD_PROJECT_PATH |
Caminho absoluto antes da renomeação |
NEW_PROJECT_PATH |
Caminho absoluto depois da renomeação |
CURSOR_USER_DATA |
Pasta User do Cursor (opcional) |
CURSOR_HOME_PROJECTS |
Pasta ~/.cursor/projects (opcional) |
O .env está no .gitignore e não deve ser commitado.
migrate-cursor-chats.py [-h] [--from CAMINHO] [--to CAMINHO]
[--execute] [--repair] [--scan-orphans]
[--clean-backups [BACKUP]] [--keep N]
[--revert [BACKUP]] [--junction]
[--quit-cursor] [--force] [--patch-disk-kv]
| Flag | Descrição |
|---|---|
| (sem flags) | Dry-run da migração — simula sem gravar |
--from, -f |
Caminho antigo |
--to, -t |
Caminho novo |
--execute |
Aplica alterações |
--repair |
Relinka quando a pasta antiga já sumiu |
--scan-orphans |
Lista órfãos; com --execute, arquiva em backups/ |
--clean-backups [BACKUP] |
Lista/apaga backups do script; com --execute, confirma e remove |
--keep N |
Com --clean-backups, mantém os N mais recentes |
--revert [BACKUP] |
Restaura backup (lista se omitir o nome) |
--junction |
Junction Windows em vez da migração SQLite |
--quit-cursor |
Encerra o Cursor antes de gravar |
--force |
Segue com Cursor aberto (risco de desfazer) |
--patch-disk-kv |
Varredura lenta em cursorDiskKV (off por padrão) |
--revert, --junction, --scan-orphans e --clean-backups são mutuamente exclusivos.
Com --execute, a migração de metadados:
- Cria backup +
manifest.jsonem%APPDATA%\Cursor\User\backups\cursor-chat-migration-YYYYMMDD-HHMMSS\ - Copia dados do workspace antigo → novo e atualiza
workspace.json - Relinka
composerHeadersemstate.vscdb, atualiza JSON legado / glass e faz patch leve naItemTable - Atualiza referências do Open Recent em
storage.json - Mescla
agent-transcriptsem~/.cursor/projects/<slug>/
Não altera arquivos dentro de OLD_PROJECT_PATH nem NEW_PROJECT_PATH.
| Item | Caminho típico |
|---|---|
| Workspace storage | %APPDATA%\Cursor\User\workspaceStorage\ |
| Banco global | %APPDATA%\Cursor\User\globalStorage\state.vscdb |
| Open Recent | %APPDATA%\Cursor\User\globalStorage\storage.json |
| Agent transcripts | %USERPROFILE%\.cursor\projects\<slug>\agent-transcripts\ |
Workspace ID antigo não encontrado
O AppData ainda precisa ter workspace.json apontando para o path antigo. Se a pasta já sumiu do disco, use --repair. Se o registro em AppData também foi apagado, restaure um backup ou use --junction.
Workspace ID novo não encontrado
Abra o projeto em NEW_PROJECT_PATH no Cursor uma vez e rode de novo.
Cursor.exe está em execução
Feche o Cursor, use --quit-cursor, ou (com risco) --force.
Chats não aparecem após --execute
python migrate-cursor-chats.py --repair --execute --from "..." --to "..."Se precisar, restaure com --revert.
state.vscdb muito grande / demora
Por padrão não se varre cursorDiskKV. Use --patch-disk-kv só se algum chat ainda faltar após o fluxo normal (pode levar horas com bancos > 1 GB).
Erro ao criar junction
Terminal como Administrador; OLD_PROJECT_PATH não deve existir no disco.
- Sempre rode o dry-run antes de
--execute. - Backup automático com
manifest.jsoné criado antes de gravar. - Projeto testado em Windows. Não afiliado ao Cursor / Anysphere.