CLI para gerenciar git worktrees por produto: várias tasks em paralelo, com config YAML reutilizável, cópia de arquivos/dependências e workspace Cursor/VS Code gerado automaticamente.
Binário: wt · MCP: wt-mcp · Python 3.11+
- Para quem é
- Como funciona
- Instalação
- Início rápido
- Fluxos de trabalho
- Comandos
- Configuração
- Estado
- MCP para agentes
- Vários produtos
- Documentação
- Desenvolvimento
Útil quando você:
- Mantém mais de um repositório por produto (ex.: API + web, backend + mobile)
- Cria uma pasta por task/ticket com worktrees git isoladas
- Quer reaproveitar arquivos locais (
.env,launch.json,node_modules, etc.) - Abre tudo num
.code-workspacecom pastas extras (docs, utilitários, specs)
Não é um wrapper genérico de git worktree para um único repo solto — o foco é o workspace de produto com N projetos.
Pasta do produto/
├── api/ ← repositório git
├── web/ ← repositório git
├── docs/ ← pasta extra no workspace
└── .worktree-manager/ ← pasta do manager
├── config.yml ← config (versionável)
├── state.yml ← estado local (não versionar)
└── worktrees/
└── TASK-123/
├── api/ ← worktree
├── web/ ← worktree
└── TASK-123.code-workspace
Dois caminhos para criar tasks:
- Em etapas —
create(pasta + workspace + estado) e depoisaddprojeto a projeto - Preset —
create --preset …encadeia create + vários adds
A branch de trabalho default é o nome da task (--branch sobrescreve; no preset, --branch proj=b por projeto).
A base de origem é por projeto (default_base no YAML, com override via --base).
Execute os comandos na pasta base do produto (pai de
.worktree-manager/) ou dentro de.worktree-manager/.
Outro produto = outra pasta = outroinit.
git clone <url-deste-repo> worktree-manager
cd worktree-manager
uv venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
uv pip install -e ".[dev]"
wt --versionAlternativa com pip:
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"Deixe o venv ativo (ou exponha wt no PATH) para usar em qualquer pasta de produto.
cd ~/projetos/meu-produtoEstrutura mínima esperada: repositórios git lado a lado (ex.: api/, web/).
wt initO assistente pergunta:
- Nome do produto
- Loop de projetos: path → nome (default: basename) → default base
Cria .worktree-manager/config.yml (worktrees em .worktree-manager/worktrees/).
Depois edite copy, workspace_folders e presets, ou use wt projects add.
name: meu-produto
root: .
worktrees_dir: worktrees
workspace_file: "{task}.code-workspace"
workspace_folders:
- path: docs
projects:
api:
path: api
default_base: main
copy:
- from: .env.local
to: .env.local
web:
path: web
default_base: main
copy:
- from: node_modules
to: node_modules
strategy: rsync
presets:
backend: [api]
frontend: [web]
fullstack: [api, web]Veja o schema completo em docs/configuracao.md e exemplos em docs/exemplos/.
Rápido (preset):
wt create TASK-123 --preset fullstack --open
# ou com branches explícitas:
wt create TASK-123 --preset fullstack --branch feature/TASK-123 --openEm etapas:
wt create TASK-123
wt add TASK-123 api
wt add TASK-123 web --base develop
wt open TASK-123wt list
wt status TASK-123
wt sync TASK-123
wt doctor
wt doctor --fix
wt prune
wt remove TASK-123 --forcewt create TASK-10 --preset backendwt create TASK-11
wt add TASK-11 api --branch feature/TASK-11
# ... trabalhar só na API ...
wt add TASK-11 web --branch feature/TASK-11wt create TASK-12 \
--preset fullstack \
--branch api=feature/TASK-12-api \
--branch web=feature/TASK-12-ui \
--base api=main \
--base web=developwt create TASK-13 --preset fullstack --dry-run
wt add TASK-13 api --dry-run
wt remove TASK-13 --force --dry-run
wt sync TASK-13 --dry-runwt remove TASK-12 web --forcewt remove TASK-12 --force --delete-branch| Comando | Descrição |
|---|---|
wt init |
Cria .worktree-manager/config.yml |
wt create <task> |
Cria task vazia (pasta + workspace + estado) |
wt create <task> --preset <nome> |
Create + adds do preset |
wt add <task> <project> [--branch <b>] [--base <b>] |
Adiciona projeto à task (branch default = task) |
wt remove <task> [project] --force |
Remove projeto da task ou a task inteira |
wt list |
Lista tasks do estado |
wt projects list |
Lista projetos do config.yml |
wt projects add <path> [--name] [--base] |
Adiciona projeto à config (nome default = basename) |
wt projects remove <nome> --force |
Remove projeto da config |
wt status <task> |
git status dos projetos da task |
wt sync <task> [project] |
Fetch + rebase/merge na base registrada |
wt open <task> |
Abre o .code-workspace (Cursor/VS Code) |
wt doctor [--fix] |
Diagnóstico; --fix tenta corrigir |
wt prune |
Limpa órfãos e ghosts |
wt help [comando] |
Ajuda detalhada |
wt --help / wt --version |
Ajuda curta e versão |
Opções úteis:
| Opção | Onde | Efeito |
|---|---|---|
--branch |
add, create --preset |
Branch de trabalho (default: nome da task) |
--branch proj=b |
create --preset |
Branch por projeto (repetível) |
--base |
add |
Base de origem (senão usa default_base) |
--base proj=branch |
create --preset |
Override de base por projeto |
--strategy |
sync |
rebase (default) ou merge |
--open |
create |
Abre o workspace ao terminar |
--delete-branch |
remove |
Apaga a branch local criada |
--dry-run |
create, add, remove, sync, doctor --fix, prune |
Mostra o plano sem alterar nada |
--force |
remove, sync |
Confirma remoção / permite dirty no sync |
Referência detalhada: docs/comandos.md.
Arquivo: .worktree-manager/config.yml.
| Campo | Obrigatório | Default | Descrição |
|---|---|---|---|
name |
sim | — | Nome do produto |
root |
não | . |
Raiz relativa ao produto (pai de .worktree-manager/) |
worktrees_dir |
não | worktrees |
Pasta das tasks (relativa a .worktree-manager/) |
workspace_file |
não | {task}.code-workspace |
Nome do workspace gerado |
workspace_folders |
não | [] |
Pastas extras no workspace |
projects.<id>.path |
sim | — | Path do repositório (relativo à raiz do produto) |
projects.<id>.default_base |
sim | — | Branch de origem padrão |
projects.<id>.copy |
não | [] |
Arquivos/pastas a copiar no add |
projects.<id>.copy[].strategy |
não | rsync |
rsync | copy | skip |
presets |
não | {} |
Nome → lista de ids de projeto |
Não existem allowed_bases nem pattern automático de branch.
Guia completo do schema, init e estado: docs/configuracao.md.
Arquivo local: .worktree-manager/state.yml.
| Config | Estado | |
|---|---|---|
| Responde | O que pode ser feito | O que já existe |
| Versionar? | Sim (config.yml é útil no time) |
Não |
| Quem escreve | init + edição humana |
Só o CLI |
Sugestão de .gitignore no produto:
.worktree-manager/state.ymlO wt doctor compara estado, pastas em disco e git worktree list (órfãos, drift de branch, worktrees fantasma, etc.).
wt doctor --fix e wt prune corrigem o que for seguro; wt sync atualiza as branches da task com a base.
O servidor wt-mcp expõe as mesmas operações da CLI via Model Context Protocol (stdio), para agentes Cursor (e outros clientes MCP) criarem/listarem/sincronizarem tasks sem parsear stdout.
Pré-requisito: pacote instalado (uv tool install --editable . ou uv pip install -e .) e wt-mcp no PATH (which wt-mcp).
- Abra Cursor Settings → MCP (ou edite o JSON de MCP).
- Inclua o servidor abaixo.
- Salve e confirme que
worktree-manageraparece como conectado (tools disponíveis no chat/agente).
Global (~/.cursor/mcp.json):
{
"mcpServers": {
"worktree-manager": {
"command": "wt-mcp",
"args": []
}
}
}Só neste repo (.cursor/mcp.json na raiz do projeto):
{
"mcpServers": {
"worktree-manager": {
"command": "wt-mcp",
"args": []
}
}
}Se wt-mcp não estiver no PATH, use o caminho absoluto do venv:
{
"mcpServers": {
"worktree-manager": {
"command": "/caminho/para/worktree-manager/.venv/bin/wt-mcp",
"args": []
}
}
}- Passe
product_root(path absoluto da pasta do produto) quando o cwd do agente não for o produto. - Respostas:
{ "ok": true, "data": … }ou{ "ok": false, "error": { "kind", "message" } }. - Ações destrutivas (
remove,prune,doctorcomfix) exigemconfirm=true(oudry_run=truepara simular).
| Tool | Equivale a |
|---|---|
resolve_product / list_tasks / list_projects |
inventário |
create_task / create_with_preset / add_project |
wt create / --preset / wt add |
remove |
wt remove … --force |
status / sync |
wt status / wt sync |
doctor / prune |
wt doctor [--fix] / wt prune |
workspace_path / open_workspace |
path do workspace / wt open |
Skill opcional (orquestra MCP ou CLI): .cursor/skills/worktree-manager/.
Detalhes e contrato de erro: docs/mcp.md.
Cada produto tem sua própria pasta .worktree-manager/:
ProdutoA/
├── api/
└── .worktree-manager/
├── config.yml
└── worktrees/
ProdutoB/
├── backend/
├── mobile/
└── .worktree-manager/
├── config.yml
└── worktrees/
cd ~/projetos/ProdutoA && wt init
cd ~/projetos/ProdutoB && wt init| Documento | Conteúdo |
|---|---|
| README.md | Porta de entrada (este arquivo) |
| docs/configuracao.md | Schema YAML, init, estado |
| docs/comandos.md | Referência detalhada dos comandos |
| docs/mcp.md | Servidor MCP (wt-mcp) para agentes |
| docs/exemplos/ | YAMLs de exemplo (genérico + casos) |
| docs/migracao-clinic.md | Caso: migrar script legado Clinic → wt |
| docs/plano-desenvolvimento.md | Histórico de fases / backlog interno |
Exemplos prontos para copiar:
# stack API + web (genérico)
mkdir -p /caminho/do/produto/worktree-manager
cp docs/exemplos/api-web.yml /caminho/do/produto/.worktree-manager/config.yml
# caso Clinic (referência)
mkdir -p /caminho/do/Clinic/worktree-manager
cp docs/exemplos/clinic.yml /caminho/do/Clinic/.worktree-manager/config.ymlSkill opcional do Cursor (orquestra MCP/wt, sem reimplementar lógica):
.cursor/skills/worktree-manager/
source .venv/bin/activate
uv pip install -e ".[dev]"
pytest
wt --help
wt-mcp # sobe o servidor MCP em stdio (usado pelo Cursor)Layout do pacote:
src/worktree_manager/
├── cli/ # comandos Typer
├── config/ # load/validate/write YAML
├── state/ # estado local
├── git/ # operações git
├── workspace/ # geração .code-workspace
├── mcp/ # servidor MCP (wt-mcp)
├── copyops.py # cópias declarativas
└── services.py # create/add/remove/sync/doctor/prune
Plano e backlog: docs/plano-desenvolvimento.md.
MIT (ver pyproject.toml).