Andares

Andares deixam um time inteiro trabalhar em paralelo no mesmo projeto sem um pisar no outro. Cada andar é um canvas próprio, com o seu próprio checkout do repositório, em uma branch só dele. Assim você e seus agentes podem construir várias funcionalidades ao mesmo tempo, revisar o pull request de alguém ou testar uma ideia arriscada enquanto o Térreo continua exatamente como você deixou. Os andares funcionam onde o seu código estiver: na sua máquina ou em um workspace de SSH, Docker ou runtime personalizado.

Por que Andares?

Quando você está imerso em uma tarefa e precisa mudar de contexto, talvez para corrigir um bug em outra branch, revisar um PR ou experimentar uma abordagem diferente, normalmente teria que fazer stash do seu trabalho, trocar de branch e lembrar onde parou depois. Com agentes é pior: dois deles editando a mesma pasta tropeçam nas mudanças um do outro.

Um andar acaba com esse atrito. Ele tem seus próprios terminais, sua própria branch e sua própria working tree, e quando o trabalho fica pronto você o pousa de volta no Térreo, com um merge local ou abrindo um pull request.

Funciona onde o seu código vive

Os andares acompanham o seu código. Em um workspace de SSH, Docker ou runtime personalizado (runtimes personalizados no Mac), o andar é criado nessa máquina, ao lado do seu projeto, e clonado com copy-on-write quando o disco dela suporta. Todo o resto funciona igual: hooks, status, pouso e pull requests. Em um pull request, a branch é enviada a partir da máquina do workspace, e o CLI do host roda no seu computador com o seu próprio login (ou na máquina do workspace, se você preferir). Veja Ambientes.

Como um andar guarda o seu código

Por padrão, um andar é uma worktree do git do seu projeto: um segundo checkout do mesmo repositório, em uma branch só dele. Ele compartilha o histórico do projeto, então a branch aparece na sua IDE, no GitHub e em todo lugar na mesma hora.

Copy-on-write

Quando o disco suporta, o Maestri não faz o checkout do andar arquivo por arquivo. Ele clona os arquivos do Térreo para o andar com copy-on-write e depois deixa o git reescrever só os arquivos que a branch do andar tem diferentes. Isso traz duas grandes vantagens:

  • É instantâneo e quase não ocupa espaço. Um arquivo clonado compartilha o armazenamento com o original até que um dos dois mude, então um andar de um projeto grande custa quase nada em disco.
  • O andar já nasce pronto para rodar. Dependências como node_modules, configurações locais como arquivos .env e até as suas alterações sem commit vêm junto, então um servidor de desenvolvimento ou uma bateria de testes funciona no andar novo sem reinstalar nada.

Caches e saídas de build (.next, dist, build, target, DerivedData e afins) ficam de fora, para que cada andar compile do zero e servidores de desenvolvimento em paralelo nunca corrompam o cache um do outro. Você pode adicionar suas próprias pastas em Pastas excluídas ao criar um andar. Pastas de submódulos começam vazias, como um checkout novo as deixa; rode git submodule update --init no andar quando precisar delas.

O copy-on-write funciona nestes sistemas de arquivos:

Onde o projeto estáCopy-on-write
MacAPFS, o padrão nos Macs modernos
Linux, ou um workspace de SSH, Docker ou runtime personalizadobtrfs, XFS e bcachefs (tudo que o cp --reflink=always consegue clonar), ou APFS quando a máquina remota é um Mac
WindowsNão disponível. O andar é um checkout comum

Em qualquer outro disco o andar continua sendo uma worktree, só que um checkout comum, apenas com os arquivos que o git rastreia. Use um hook de setup para instalar as dependências nesses andares.

Cópia independente

Ao criar um andar, você pode escolher Cópia independente em vez de Worktree do git. O Maestri então clona o projeto inteiro, .git incluído, em um repositório só dele, exatamente como está agora. Por ser separada, uma cópia independente pode fazer checkout da mesma branch em que o Térreo está, o que uma worktree não pode. Quando você a pousa, os commits dela são trazidos de volta para o seu projeto.

Cópias independentes precisam de copy-on-write e de um projeto com repositório próprio (uma pasta .git de verdade, não uma worktree). Elas aparecem no Mac em APFS e no Linux em um disco com copy-on-write, para projetos na sua própria máquina. Andares em workspaces de SSH, Docker e runtime personalizado são sempre worktrees, clonadas com copy-on-write no disco dessa máquina do mesmo jeito.

Criando um andar

Os seus andares aparecem em dois lugares, e os dois têm todos os recursos: a visão geral dos andares, onde o canvas se abre em 3D com uma pílula para cada andar, e a barra lateral, sob cada workspace. Use o que preferir.

  1. Clique no botão de andar no canto inferior direito do app, ao lado do minimapa.
  2. O canvas se reposiciona em um espaço 3D. Clique em Novo andar.
  3. Dê um nome (por exemplo, "Corrigir bug de login").
  4. Com Isolamento de repositório ativado, crie uma branch nova ou escolha uma existente. A branch atual do Térreo não pode ir para uma worktree, já que o git só permite uma branch em um checkout por vez. Desative para um andar que é só um canvas separado: os terminais dele trabalham na pasta do projeto, na branch do Térreo. Isso funciona em qualquer workspace.
  5. Se quiser, escolha Cópia independente em vez de Worktree do git, adicione Pastas excluídas ou ative Clonar layout do Térreo para começar o andar com as notas, terminais e blocos de texto do Térreo.
  6. Clique em Criar.

Você também pode escolher Novo andar no menu de um workspace na barra lateral ou na paleta de comandos. Para começar a partir do pull request de alguém em vez de uma branch, veja Criando um andar a partir de um pull request.

A janela fecha na hora e o andar aparece como uma pílula com barra de progresso enquanto os arquivos são preparados. Qualquer terminal que você adicionar no andar trabalha no checkout dele, então você pode rodar servidores de desenvolvimento, IDEs e builds ao mesmo tempo sem conflitos.

Informações do andar, no menu de um andar, mostra que tipo de andar ele é, onde fica a pasta dele e se os arquivos foram clonados com copy-on-write a partir do Térreo ou vieram de um checkout do git.

A partir de um Maestro

Digite @New Floor no compositor de um Maestro e descreva a tarefa. O Maestri cria o andar, coloca um agente nele e começa a trabalhar. Veja Maestro.

O compositor de um Maestro com a menção New Floor, pedindo um andar para revisar um pull request

Status e notificações

Os agentes de um andar publicam como o trabalho está enquanto avançam: Trabalhando, Bloqueado, Pronto para revisão ou Concluído, com uma linha curta e, quando sabem, o progresso. Você vê tudo de relance na pílula do andar na visão geral e na linha dele na barra lateral, e quando um andar precisa de você (um agente está bloqueado, o trabalho está pronto para revisão, um pull request tem conflitos) o Maestri avisa com uma notificação. Você pode desligar isso em Configurações → Geral → Notificar quando um andar precisar de você.

Andares listados na barra lateral sob o seu workspace, cada um com sua branch, uma linha de status do seu agente e selos de pull request
Notificações do Maestri no macOS: um andar pronto para revisão, um andar concluído e um pull request com conflitos

Os agentes publicam com o comando maestri floor status, e você mesmo pode definir um com Definir status… no menu de um andar:

maestri floor status "Ligando a página de ajustes" --state working --progress 2/5
maestri floor status "Preciso de uma decisão sobre o texto do toggle" --state blocked
maestri floor status "Pronto para pousar: CI verde, sem conflitos" --state review

O Maestri Remote também mostra cada andar com seu status e pull request, e deixa você criar andares, revisar pull requests, fazer merge e enviar correções para agentes pelo celular.

Pousando um andar

Quando o trabalho estiver pronto, clique no botão de avião ao lado do andar na visão geral dos andares, ou escolha Pousar andar no menu do andar, na visão geral ou na barra lateral.

O botão Pousar no painel do andar

A janela de pouso tem dois lados: Merge local e Pull request. Nos dois casos, o que pousa é o trabalho commitado do andar; se houver alterações sem commit, o Maestri oferece fazer o commit antes.

Merge local

A janela de pouso em Merge local, com a branch do andar, a branch destino no Térreo e a lista de arquivos alterados

Escolha a branch destino:

  • A própria branch do andar. O Maestri atualiza essa branch no seu projeto com o trabalho do andar.
  • Outra branch. O Maestri também faz o merge da branch do andar nela, e pode excluir a branch do andar depois.

O lado direito lista cada arquivo alterado com o seu diff. Sincronizar traz antes para o andar as últimas mudanças da branch destino no Térreo. Por padrão o andar é removido depois de pousar, junto com seus terminais e notas; ative Manter este andar após pousar para continuar trabalhando nele.

Quando o merge teria conflitos, o Maestri diz quais arquivos e para. Resolva-os no andar (ou escolha outra branch) e pouse de novo.

Pull request

O outro lado da janela de pouso envia o trabalho do andar como um pull request. Veja Pull requests abaixo.

Pull requests

Os andares falam pull requests do começo ao fim: abra um a partir de um andar, acompanhe a revisão e o CI com agentes corrigindo o que aparecer e faça o merge sem sair do Maestri. Tudo passa pelo próprio CLI do seu host, gh para o GitHub ou glab para o GitLab, com o login que você já tem. Não há tokens para colar, e o Maestri nunca guarda nenhum.

Abrindo um pull request

A janela de pouso em Pull request, com a branch base, o título, uma descrição a partir do template do repositório e o botão Abrir pull request
  1. Clique no botão de pouso do andar (ou escolha Pousar andar no menu dele) e mude para Pull request.
  2. Escolha a branch de destino em Para.
  3. Escreva o Título e a Descrição. O Maestri já preenche para você: o assunto do commit ou o nome do andar no título, e o template de pull request do seu repositório na descrição, ou o status dos agentes e a lista de commits quando não há template. Quando o repositório tem vários templates, escolha um em Modelo.
  4. Cole ou arraste capturas de tela direto na descrição. Elas sobem junto com o pull request (GitHub, com gh 2.99 ou mais recente).
  5. Marque Abrir como rascunho se ainda não estiver pronto para revisão.
  6. Clique em Abrir pull request.

O Maestri envia a branch do andar e abre o pull request. Se o andar tiver alterações sem commit, ele oferece fazer o commit antes (Commit para abrir o pull request), já que o que ficar sem commit ficaria para trás.

A janela mostra onde ele vai abrir e com qual conta, como "Abre no GitHub como seu-login". Alterar deixa um workspace escolher outro provedor, escolher Somente o site do host ou usar Executar comandos do host em na própria máquina do workspace, para um host que só ela alcança (um GitLab atrás de uma VPN, por exemplo). Quando o host não tem provedor, o CLI dele não está instalado ou a branch vai para um fork, o Maestri envia a branch e abre a página de novo pull request do próprio host.

Pull requests que os seus agentes abrem

Você não precisa abrir pela janela. Quando um agente em um andar roda gh pr create, ou alguém abre um pelo site do host, o Maestri percebe em poucos minutos, ou assim que um agente do andar termina um turno. A partir daí ele é acompanhado exatamente como um aberto pela janela de pouso.

Acompanhando

O andar continua enquanto o pull request está em revisão, e o selo dele na visão geral e na barra lateral mostra como as coisas estão: aguardando revisão, aprovado, alterações solicitadas, checks rodando ou falhando, ou conflitos com a base. Um ponto azul marca novidades desde a última vez que você olhou, como um novo comentário, revisão ou push. Clicar no selo abre a janela de pouso no pull request.

O Maestri verifica a cada minuto o andar em que você está e a cada cinco minutos os outros, espaçando as verificações quando há muitos para nunca estourar o limite de uso do seu host. Verificar pull request no menu do andar pergunta na hora. Uma mudança que vale saber, como um check que falhou, uma revisão ou um conflito, também gera uma notificação.

Quando algo precisa de atenção, um clique entrega a tarefa a um agente nesse andar com os detalhes de que ele precisa:

  • Pedir a um agente para atender à revisão
  • Pedir a um agente para corrigir as verificações
  • Pedir a um agente para resolver os conflitos

Quando o andar tem commits que o pull request ainda não tem, a janela avisa e Push os envia.

Fazendo o merge

Clique em Merge… e escolha um método que o seu host permite: merge commit, squash ou rebase. Quando o merge acontece, o andar pousa sozinho. Rascunhos não podem receber merge até serem marcados como prontos no host.

Para um pull request mesclado pelo site do host, a mesma janela deixa você remover o andar com Remover andar, e o Maestri avisa antes se o andar tem trabalho que o pull request mesclado não tinha. Em todos os casos, a branch do andar continua no seu projeto. Um pull request fechado sem merge também deixa a branch, e Abrir um novo pull request começa de novo.

Criando um andar a partir de um pull request

O pull request de qualquer pessoa pode ganhar um andar só dele, para você rodar, testar e pedir a revisão de um agente sem mexer no seu próprio trabalho.

  1. Abra Novo andar e mude Começar de para Pull request.
  2. Escolha um dos pull requests abertos do repositório, os com atividade mais recente primeiro. Digite em Busque ou cole um link para filtrar, encontrar os mais antigos no host ou colar o link ou o número de um pull request.
  3. Clique em Criar. O andar recebe o nome do pull request, como "#42 Corrige redirecionamento do login", a menos que você dê outro nome.

O Maestri busca o pull request e faz o checkout em um andar novo, pronto para rodar. Pedir a um agente para revisá-lo dá a um agente do andar uma primeira revisão para fazer, relatada a você em vez de enviada. Quando terminar, Concluir revisão… remove o andar. Um pull request que já está em um andar mostra qual, já que ele só pode ter um.

Para onde vão os commits depende de onde a branch está:

  • Uma branch no seu repositório: o andar faz checkout da própria branch do pull request, e os commits que você envia do andar vão para o pull request.
  • Uma branch em um fork: o andar recebe uma cópia somente leitura dos commits, em uma branch com nome como pr-42, para nada cair no lugar errado.

Você também pode fazer isso a partir de um Maestro, digitando algo como "@New Floor para revisar o PR 32", pelo Maestri Remote no celular ou pelo terminal com maestri floor create --pull-request 42.

Hosts git e provedores

GitHub e GitLab funcionam de imediato, incluindo GitHub Enterprise e GitLab auto-hospedado depois que o host deles é adicionado a um provedor. O Maestri descobre qual provedor um projeto usa a partir de para onde o git push envia a branch do andar, seguindo a sua configuração de SSH, então um alias de Host como github-work resolve para o host real.

Configurações → Geral → Git lista cada provedor, a conta com que o CLI dele está logado e o erro exato de qualquer arquivo de provedor que não carregue. Um projeto cujo host não tem provedor continua funcionando: o Maestri envia a branch e abre a página de novo pull request do próprio host.

Adicionando o seu próprio provedor

Cada provedor é um pequeno arquivo JSON na pasta de provedores, ~/.maestri/git-hosts/providers/. Clique em Mostrar pasta de provedores nas Configurações para abri-la. O arquivo diz quais hosts ele atende e quais comandos criam, encontram, acompanham, listam e fazem merge de pull requests. O Maestri nunca chama a API de um host por conta própria: ele só roda os programas que o seu arquivo indica, como gh, glab ou curl, que guardam o próprio login.

Essa pasta também tem um guia AGENTS.md que o Maestri mantém atualizado, descrevendo o formato inteiro, com receitas para uma segunda conta do GitHub, GitHub Enterprise, GitLab auto-hospedado e hosts sem CLI. Aponte um agente para ele e peça que escreva o provedor para você.

Uma segunda conta do GitHub, por exemplo, é uma cópia do github.json com um novo id, ligada ao alias de SSH que os seus repositórios de trabalho usam e logada com essa conta:

"match": { "aliases": ["github-work"] },
"token": { "run": ["gh", "auth", "token", "--hostname", "github.com", "--user", "voce-no-trabalho"], "env": ["GH_TOKEN"] }

Algumas coisas para saber:

  • Um provedor por arquivo, chamado <id>.json, com um id igual ao nome do arquivo. Chaves desconhecidas são erros, então um erro de digitação nunca roda como outra coisa.
  • github.json e gitlab.json vêm com o Maestri. Editar um deles o marca como modificado; para uma variação, copie para um novo id. Restaurar padrão… traz de volta a versão original.
  • Um arquivo de provedor é um programa que roda com as suas permissões. Só mantenha ali arquivos que você mesmo rodaria.
  • O mesmo arquivo funciona no Maestri para macOS, Windows e Linux. Um token pode indicar um programa diferente para cada plataforma.

Hooks

Hooks permitem automatizar comandos que rodam em momentos-chave do ciclo de vida de um andar: quando ele é criado, quando você quer executar tarefas e quando ele é excluído.

Para configurar hooks, clique com o botão direito no botão de andar no canvas e selecione Configurar hooks….

Clique com o botão direito no botão de andar para acessar Configurar hooks

Tipos de hooks

Existem três tipos de hooks:

  • Setup: roda quando um andar é criado. Use para instalar dependências, vincular serviços ou preparar o ambiente. Ative Auto-run para executar os comandos de setup automaticamente quando o andar é criado.
  • Run: roda quando você clica no botão play. Use para iniciar servidores de desenvolvimento, rodar testes ou qualquer tarefa sob demanda.
  • Teardown: roda quando um andar é excluído. Use para limpar recursos, desvincular serviços ou remover arquivos temporários.

Cada hook suporta múltiplos comandos. Clique em + Add command para adicionar mais.

Variáveis de ambiente

O Maestri fornece variáveis de ambiente que você pode usar nos seus comandos de hook:

  • $MAESTRI_FLOOR_NAME: o nome do andar
  • $MAESTRI_BRANCH_NAME: o nome da branch git
  • $MAESTRI_FLOOR_PATH: o diretório de trabalho do andar
  • $MAESTRI_ROOT_PATH: a raiz original do projeto
  • $MAESTRI_PROJECT_NAME: o nome do workspace
Painel de configuração de hooks mostrando hooks de setup, run e teardown com variáveis de ambiente

Acesso rápido

Uma vez configurados, seus hooks ficam sempre acessíveis pelo ícone de raio (⚡) ao lado do botão de andar no canvas. A partir dele você pode ver todos os seus hooks agrupados por tipo e executá-los individualmente ou todos de uma vez com Run All.

Popover de hooks mostrando comandos de setup e teardown com botões de execução

Renomeando um andar

Clique com o botão direito em um andar na visão geral dos andares ou na barra lateral e escolha Renomear. Isso é útil quando o escopo do seu trabalho muda ou você quer um nome mais descritivo.

Excluindo um andar

Escolha Excluir andar no menu de um andar. O que vai junto depende do tipo de andar:

  • Worktree do git: a pasta é removida junto com qualquer alteração sem commit. Os commits da branch continuam no seu projeto, a menos que você também marque Remover a branch também.
  • Cópia independente: a pasta é removida com o repositório próprio dela, então alterações sem commit e commits que você ainda não pousou vão junto.

O comando floor

Agentes no Modo Maestro podem gerenciar andares pelo terminal:

maestri floor create "Nome" [--branch B] [--existing-branch] [--copy] [--copy-ground]
maestri floor create --pull-request 42
maestri floor list
maestri floor land "Nome" [--into BRANCH] [--delete-branch] [--keep-floor]
maestri floor delete "Nome" [--keep-branch]
maestri floor status "Texto" [--state working|blocked|review|done] [--progress 2/5]

Pousar e excluir rodam a partir de um terminal no Térreo, nunca de dentro do próprio andar. floor status funciona em qualquer terminal e publica para o andar em que aquele terminal está.

Requisitos

  • Um repositório git. Sem um, o andar é um canvas separado cujos terminais trabalham na pasta do projeto, na branch do Térreo.
  • Copy-on-write, para andares instantâneos. APFS no Mac, ou btrfs, XFS ou bcachefs no Linux. Em outros discos os andares são checkouts comuns.
  • O CLI do seu host, para pull requests. gh para o GitHub ou glab para o GitLab, instalado e logado. Sem ele, os pull requests abrem pelo site do host.

Como funciona

Os andares ficam em uma pasta .maestri/floors ao lado do seu projeto, na máquina em que o projeto estiver. A pasta é limpa quando o último andar sai.

Uma worktree é registrada no git sem checkout, os arquivos do Térreo são clonados para ela com copy-on-write (.git à parte) e o índice do git é então reconstruído por cima, reescrevendo só os arquivos que a branch tem diferentes. Pousar uma worktree não precisa de transferência, já que a branch do andar já está no seu projeto. Um merge em outra branch roda no checkout que tem essa branch, e é recusado em vez de sobrescrever alterações sem commit ali. Uma cópia independente é um clone completo com copy-on-write, e pousá-la traz antes os commits dela de volta para o seu projeto.