Skip to content

Stores: Planeje em Seu Próprio Repo ​

Beta. Stores, referências, contexto de trabalho e worksets são novos. Nomes de comandos, flags, formatos de arquivo e saída JSON podem ainda mudar de forma entre versões. Cada passo a passo abaixo foi executado contra a build atual, mas releia este guia após atualizar.

O problema que isso resolve ​

O OpenSpec normalmente vive dentro de um repositório de código: uma pasta openspec/ ao lado do seu código, contendo especificações e mudanças para aquele repositório.

Isso deixa de se encaixar no momento em que seu planejamento é maior do que um único repositório:

  • Seu trabalho abrange vários repositórios — um recurso toca o servidor de API, a aplicação web e uma biblioteca compartilhada. Em qual pasta openspec/ o plano deve ficar?
  • Sua equipe planeja antes de o código existir, ou planeja coisas que nunca se tornam código neste repositório.
  • Os requisitos são de propriedade de uma equipe e consumidos por outras. A versão do wiki diverge, e seu agente de codificação não consegue lê-la de qualquer forma.

Uma store é a resposta: um repositório independente cujo único trabalho é o planejamento. Ele tem a mesma forma openspec/ que você já conhece — especificações e mudanças — além de um pequeno arquivo de identidade. Você o registra na sua máquina uma vez, pelo nome, e então todos os comandos normais do OpenSpec podem funcionar nele de qualquer lugar.

A estrutura ​

            team-plans  (uma loja: planejamento em seu próprio repositório)
            ├── .openspec-store/store.yaml     identity: "I am team-plans"
            └── openspec/
                ├── specs/      o que é verdadeiro
                └── changes/    o que está em movimento
                      ▲
                      │ registrado em cada máquina por nome;
                      │ compartilhado ao fazer push/clonar como qualquer repositório
        ┌─────────────┼─────────────┐
        │             │             │
    web-app       api-server     mobile-app
   (repositório de código)   (repositório de código)    (repositório de código)

Duas regras mantêm isso simples:

  1. Uma loja é apenas um repositório git. Você faz commit, push, pull e revisão sozinho. O OpenSpec nunca clona, sincroniza ou faz push de nada por conta própria.
  2. Declaracoes, não maquinaria. Os repositórios podem declarar como se relacionam com as lojas (mostrado abaixo). As declarações alteram o que o OpenSpec pode lhe dizer — nunca onde seus comandos atuam.

Cinco minutos para sua primeira loja ​

Dois comandos levam você do zero a uma mudança funcional e escopada pela loja:

bash
openspec store setup team-plans --path ~/openspec/team-plans
Store ready: team-plans
Location: /Users/you/openspec/team-plans
OpenSpec root: ready
Registry: registered

Next: run normal OpenSpec commands against this store, for example:
  openspec new change <change-id> --store team-plans
Share this store by committing and pushing it like any Git repo.
bash
openspec new change add-login --store team-plans
Using OpenSpec root: team-plans (/Users/you/openspec/team-plans)
Created change 'add-login' at /Users/you/openspec/team-plans/openspec/changes/add-login/
Schema: spec-driven
Next: openspec status --change add-login --store team-plans

Esse é todo o modelo. A partir daqui, o ciclo de vida é exatamente o que você conhece — status, instructions, validate, archive — com --store team-plans em cada comando, e cada dica impressa carrega a flag para você. A linha Using OpenSpec root: sempre informa onde um comando está atuando.

História: uma equipe, um repositório de planejamento ​

Uma equipe mantém seus specs e mudanças em team-plans em vez de espalhá-los pelos repositórios de código.

Dia um (quem quer que configure):

bash
openspec store setup team-plans --path ~/openspec/team-plans \
  --remote git@github.com:acme/team-plans.git
git -C ~/openspec/team-plans push -u origin main

Passar --remote grava a URL de clone dentro do arquivo de identidade da própria loja (.openspec-store/store.yaml), no commit inicial. Todo clone futuro nasce sabendo de onde veio, então verificações de saúde e mensagens de erro podem imprimir uma correção completa e colável para colegas que ainda não a têm.

Cada colega (uma vez por máquina):

bash
git clone git@github.com:acme/team-plans.git ~/openspec/team-plans
openspec store register ~/openspec/team-plans

A partir daí, todos trabalham no mesmo repositório de planejamento por nome:

bash
openspec status --store team-plans --change add-login
openspec show add-login --store team-plans

Compartilhar trabalho é git, por propósito. Uma mudança que você cria existe apenas em sua cópia local até que você faça commit e push dela — igual ao código. Planos recebem ramificações, pull requests e revisão gratuitamente, porque uma loja é um repositório comum.

Conectando os repositórios de código da equipe. Um repositório de código cujo planejamento é totalmente externalizado precisa de exatamente uma linha, em openspec/config.yaml:

yaml
# web-app/openspec/config.yaml
store: team-plans

Agora, qualquer comando OpenSpec executado dentro de web-app atua sobre team-plans sem nenhuma flag:

bash
cd ~/src/web-app
openspec status --change add-login
Using OpenSpec root: team-plans (/Users/you/openspec/team-plans)
...

O ponteiro é um fallback, nunca uma substituição: uma --store explícita sempre vence, e se o repositório crescer pastas de planejamento próprias, essas vencem (com um aviso para remover o ponteiro obsoleto).

Um padrão para cada repositório na sua máquina. Se você trabalha em vários repositórios de código que planejam todos para a mesma loja, defina uma vez, globalmente, em vez de adicionar a linha store: em cada repositório:

bash
openspec config set defaultStore team-plans

Agora, qualquer comando executado fora de uma raiz de planejamento — e sem --store nem ponteiro de projeto — resolve para team-plans. Ele fica no final da lista de precedência, então --store, uma raiz local e um ponteiro store: do projeto ainda vencem. O banner da raiz e o bloco JSON root relatam source: "global_default" com o id da loja, para que você possa distinguir sempre um padrão em toda a máquina de um ponteiro próprio do repositório. Limpe-o com openspec config unset defaultStore. Se o id não estiver registrado, os comandos erroam e informam que você deve registrá-lo ou limpar o padrão obsoleto.

Exemplo: um recurso, dois repositórios de componentes ​

Suponha que add-checkout-promo afete tanto checkout-api quanto checkout-web. A equipe deseja um contrato de produto compartilhado, enquanto cada repositório de código ainda precisa de suas próprias tarefas de implementação, ramificação e revisão.

Use duas camadas:

  1. Mantenha o comportamento compartilhado em team-plans.
  2. Mantenha planos de implementação em cada repositório de componente e referencie a loja como contexto upstream somente leitura.

Primeiro, planeje o contrato compartilhado na loja:

bash
openspec new change add-checkout-promo --store team-plans
openspec status --change add-checkout-promo --store team-plans

A proposta e os specs devem descrever o comportamento na fronteira entre os componentes — por exemplo, os campos de promoção retornados pelo serviço e como o frontend lida com um checkout inelegível. Revise esta mudança no repositório da loja como qualquer outro branch e pull request.

Que contexto o planejamento vê? ​

Selecionar uma loja altera a raiz do OpenSpec; ela não descobre ou lê todos os repositórios de código que usam essa loja. Instruções da loja veem os artefatos e o contexto configurado na loja. Elas veem o código dos componentes apenas quando essas pastas também estão disponíveis para o agente ou editor e o agente as lê.

Um workset é uma maneira conveniente de abrir a loja de planejamento e ambos os repositórios de código juntos:

bash
openspec workset create checkout-promo \
  --member ~/openspec/team-plans \
  --member ~/src/checkout-api \
  --member ~/src/checkout-web \
  --tool code
openspec workset open checkout-promo

Isso torna as pastas visíveis em um único workspace do IDE. Isso não copia o contexto de origem para a loja, seleciona repositórios afetados ou concede permissão ao agente para editá-los. Coloque fatos duradouros entre componentes nos specs compartilhados; não confie que o planejador lembre-se da fonte que ele aconteceu de inspecionar.

Como a implementação começa em cada repositório? ​

Quando não há --store explícito nem raiz openspec/ mais próxima aplicável, um ponteiro store: team-plans direciona comandos para essa loja. Isso não divide uma lista de tarefas de uma loja pelo diretório do qual apply foi invocado. O OpenSpec atualmente não roteia tarefas para repositórios.

Quando cada componente precisa de um ciclo de apply/review com escopo independente, forneça a ele uma raiz OpenSpec local e referencie a loja central em vez de apontar para ela:

yaml
# checkout-api/openspec/config.yaml (e igualmente em checkout-web)
schema: spec-driven
references:
  - team-plans

Após o contrato compartilhado ser aprovado e disponível nos specs principais da loja, crie uma pequena mudança local para a parte do componente:

bash
cd ~/src/checkout-api
openspec new change implement-checkout-promo-api

cd ~/src/checkout-web
openspec new change implement-checkout-promo-ui

O índice de referência nas instruções de cada repositório fornece o resumo do spec da loja e o comando de busca exato (openspec show ... --store team-plans). Cada proposta local cita esse contrato compartilhado, e suas tarefas descrevem apenas trabalho nesse componente. Então execute /opsx:apply em cada repositório separadamente; a resolução da raiz mantém os artefatos e as edições de implementação limitadas a esse repositório. As alterações do serviço e do frontend agora podem ser testadas, revisadas, mescladas e arquivadas independentemente.

Se a implementação precisar começar enquanto a mudança da loja compartilhada ainda estiver ativa, busque-a explicitamente com openspec show add-checkout-promo --store team-plans; os índices de referência listam specs canônicos da loja, não mudanças ativas da loja. Mantenha o branch da loja e os branches dos componentes vinculados em suas descrições de pull-request para que os revisores possam ver qual versão do contrato cada implementação segue.

História: requisitos que cruzam linhas de equipe ​

Uma equipe de plataforma possui os requisitos. Equipes de produto constroem contra eles, em seus próprios repositórios, com seus próprios designs. Uma referência descreve esse relacionamento sem mover o trabalho de ninguém.

   platform-reqs (loja)                 api-server (repositório de código)
   owned by the platform team            owned by a product team
   ┌──────────────────────────┐          ┌──────────────────────────┐
   │ openspec/specs/          │ ◀────────│ openspec/config.yaml     │
   │   payments/spec.md       │ reads    │   references:            │
   │   auth/spec.md           │          │     - platform-reqs      │
   │                          │          │ openspec/specs/          │
   │ openspec/changes/        │          │   (their own designs)    │
   │   platform work          │          │ openspec/changes/        │
   │                          │          │   (their own work)       │
   │                          │          └──────────────────────────┘
   └──────────────────────────┘

A equipe de produto declara o que ela utiliza no openspec/config.yaml de seu repositório:

yaml
references:
  - platform-reqs

Referências são contexto somente leitura. O repositório mantém sua própria raiz openspec/; o trabalho permanece lá. O que muda: openspec instructions nesse repositório agora inclui um índice dos specs da loja referenciada — cada um com um resumo de uma linha e o comando de busca exato (openspec show <spec-id> --type spec --store platform-reqs). Um agente trabalhando em api-server pode encontrar os requisitos de pagamento upstream, citá-los e escrever seu design de baixo nível na raiz própria do repositório — sem que ninguém precise colar contexto manualmente.

Uma referência pode carregar sua fonte de clone, para que colegas que ainda não têm a loja recebam uma correção completa em vez de um beco sem saída:

yaml
references:
  - { id: platform-reqs, remote: "git@github.com:acme/platform-reqs.git" }

Quando você quiser o plano e o código abertos juntos, crie um workset. Isso é pessoal e explícito: cada pessoa escolhe as pastas com as quais realmente trabalha em sua máquina. Nada sobre esses caminhos de cópia local é comitado no repositório de planejamento compartilhado.

bash
openspec workset create platform \
  --member ~/openspec/platform-reqs \
  --member ~/src/api-server \
  --member ~/src/web-app

Duas perguntas que você sempre pode fazer ​

"Minha configuração está saudável?" — openspec doctor verifica a raiz atual e suas lojas referenciadas, somente leitura, com uma correção colável por achado:

Doctor

Root
  Location: /Users/you/src/api-server
  OpenSpec root: ok

References
  - platform-reqs: ok (/Users/you/openspec/platform-reqs)
  - design-system: Referenced store 'design-system' is not registered on this machine.
    Fix: git clone -- git@github.com:acme/design-system.git '/Users/you/openspec/design-system' && openspec store register '/Users/you/openspec/design-system' --id design-system

"Com o que estou trabalhando?" — openspec context monta o conjunto de trabalho a partir das declarações do OpenSpec: a raiz e as lojas que ela referencia.

Working context for api-server (/Users/you/src/api-server)

OpenSpec root
  api-server  /Users/you/src/api-server

Referenced stores
  platform-reqs  /Users/you/openspec/platform-reqs
    Fetch: openspec show <spec-id> --type spec --store platform-reqs

Ambos suportam --json para agentes. openspec context --code-workspace <path> adicionalmente escreve um arquivo de workspace do VS Code contendo o conjunto inteiro — a única gravação que este comando realiza.

Worksets: reabra as pastas que você trabalha em conjunto ​

Separado de tudo o acima: a maioria das pessoas abre as mesmas poucas pastas juntamente a cada sessão — o repositório de planejamento mais dois ou três repositórios de código. Um workset é uma visualização pessoal e nomeada exatamente disso, reaberta com um único comando na sua ferramenta de escolha.

  workset "platform"                 openspec workset open platform
  ├── team-plans   ~/openspec/team-plans         │
  ├── api-server   ~/src/api-server              ▼
  └── web-app      ~/src/web-app       os três abertos na sua ferramenta
bash
openspec workset create platform \
  --member ~/openspec/team-plans --member ~/src/api-server \
  --tool code
openspec workset list
platform  (abre no VS Code)
  team-plans  /Users/you/openspec/team-plans
  api-server  /Users/you/src/api-server

openspec workset open platform então inicia a ferramenta salva: editores (VS Code, Cursor) abrem uma única janela com todos os membros e retornam. O primeiro membro é o principal. Substitua a ferramenta a qualquer momento com --tool <id>.

Worksets são deliberadamente não estado compartilhado. Eles vivem em sua máquina, nunca são confirmados (committed), e não fazem afirmações sobre o trabalho — eles apenas registram o que você gosta de ter aberto junto. Remover um nunca toca nas pastas dos membros. Novas ferramentas são configuração, não código: qualquer coisa iniciada via arquivo de workspace ou flags de anexo por pasta pode ser adicionada sob a chave openers na configuração global (openspec config edit).

Como os comandos decidem onde atuar ​

Cada comando normal resolve sua raiz da mesma maneira, nesta ordem:

1. --store <id>          você disse explicitamente        → esse store
2. nearest openspec/     uma raiva de planejamento real aqui     → este repo
   (subindo a partir do cwd)
3. store: pointer        config.yaml declara um store  → esse store
4. defaultStore          configuração global define uma máquina  → esse store
                         padrão
5. nenhum dos acima      stores registrados nesta máquina?         → erro com uma
                         hint de seleção
                         nenhum store registrado?         → o diretório
                                                          atual
                                                          (comportamento clássico)

A linha Using OpenSpec root: (e o bloco root na saída --json) informa qual caso você está.

Limitações conhecidas ​

  • Formato Beta. Tudo nesta página pode mudar entre versões — nomes, flags, formatos de arquivo, chaves JSON.
  • Uma cópia por store id por máquina. Registrar uma segunda cópia sob o mesmo id falha com uma dica para executar store unregister primeiro.
  • Sem sincronização, sempre — por design. OpenSpec nunca clona, puxa (pulls) ou empurra (pushes). Uma cópia desatualizada mostra especificações desatualizadas até que você faça pull; referências são indexadas em tempo real a partir do que está no disco.
  • Pastas de planejamento vazias podem estar ausentes. Um novo store pode não ter openspec/changes/, openspec/specs/, ou openspec/changes/archive/ no Git ainda. Isso é aceito durante o beta; essas pastas aparecem assim que comandos normais criam arquivos para elas.
  • Repositórios ponteiro permanecem ponteiros. Um repositório apenas de configuração cujo openspec/config.yaml declara store: <id> é tratado como planejamento externalizado, não como uma cópia de store para registrar. Remova a linha store: primeiro se quiser intencionalmente converter esse repositório em uma raiz de store local.
  • Alguns comandos permanecem onde estão. templates e as formas nominais obsoletas (openspec change show, ...) atuam apenas no diretório atual — sem --store. schemas segue a precedência canônica de seleção de raiz e aceita --store <id> mantendo sua forma de array JSON bem-sucedida inalterada.
  • Estado por máquina é por máquina. O registro de stores e worksets são configurações locais. Nada sobre o layout da sua máquina é jamais confirmado (committed) para planejamento compartilhado.
  • Dois estilos de lançamento para worksets. Uma ferramenta que não pode ser lançada com um arquivo de workspace ou flags de anexo por pasta não pode ser adicionada como um opener.
  • JSON do Agent tem uma divisão conhecida de maiúsculas/minúsculas (chaves da família store são snake_case, família workflow camelCase). Documentado no contrato do agent; unificá-lo é adiado para uma versão release.

Onde as coisas ficam ​

O quêOndeCompartilhado?
Planejamento de um store<store>/openspec/ (specs, changes)Sim — confirme (commit) e envie (push)
Identidade de um store<store>/.openspec-store/store.yamlSim — confirmado (committed) com o store
Registro de stores<data dir>/openspec/stores/registry.yamlNão — apenas esta máquina
Worksets<data dir>/openspec/worksets/Não — apenas esta máquina

<data dir> é ~/.local/share/openspec no macOS e Linux (ou $XDG_DATA_HOME/openspec quando definido), e %LOCALAPPDATA%\openspec no Windows.

Referência ​

Flags exatas e formas JSON para cada comando nesta página: Referência CLI (Stores, Doctor, Contexto de trabalho, Worksets pessoais) e o contrato do agent.