Selvedge

Rastreamento de alterações para bases de código da era da IA — captura o porquê por trás de cada mudança à medida que o agente a realiza.

Documentação

selvedge

selvedge.sh  ·  PyPI  ·  GitHub

Tests PyPI License: MIT

Memória de longo prazo para codebases codificados por IA — incluindo o que já foi tentado e rejeitado.

A atribuição de linhas diz quem escreveu algo. O Selvedge diz ao seu agente o que não escrever em seguida: as abordagens que este codebase já tentou, reverteu e por quê. É um git blame para agentes de IA, para o porquê em vez de qual modelo tocou em qual linha — capturado ao vivo, pelo agente, à medida que a mudança acontece, para que nada a jusante precise adivinhar.

O Selvedge é um servidor MCP local. Agentes de codificação de IA (Claude Code, Codex, Copilot, Cursor, Gemini CLI e Windsurf) o chamam enquanto trabalham para registrar eventos de mudança estruturados com raciocínio. Seus dados permanecem em um arquivo SQLite em .selvedge/ ao lado de seu código.

Local-first por padrão, servidor de equipe por escolha, zero-LLM sempre.


Há seis meses, seu agente de IA adicionou uma coluna chamada user_tier_v2. Você não sabe por quê. git blame aponta para um commit de claude-code com uma mensagem gerada que diz "Atualizar esquema." A sessão que fez a mudança já se foi — e também o prompt que a produziu.

Com o Selvedge, você executa isto em vez disso:

$ selvedge blame user_tier_v2

  user_tier_v2
  Changed     2025-10-14 09:31:02
  Agent       claude-code
  Commit      3e7a991
  Reasoning   User asked to add a grandfathering flag for legacy free-tier
              users during the pricing migration. Stores the original tier
              so we can backfill discounts without touching billing history.

Esse raciocínio foi capturado pelo agente no momento — escrito no Selvedge a partir do mesmo contexto que produziu a mudança. Não inferido do diff posteriormente por um segundo LLM. Não é uma mensagem de commit digitada à mão.



Para quem é o Selvedge

O Selvedge tem dois públicos. Mesma ferramenta, mesmo pip install, mesmo arquivo SQLite em .selvedge/. Diferente escala de dor.

Equipes que gerenciam codebases de longo prazo, codificados por IA. Quando o projeto é grande o suficiente para que você (ou outra pessoa) o toque novamente em seis meses, doze meses, três anos — mas a maior parte foi escrita por um agente cujo contexto evaporou no dia em que cada PR foi enviado. git blame diz o que mudou. O Selvedge diz por quê — mesmo depois que a sessão do agente, o modelo de prompt, o desenvolvedor que pediu e a versão do modelo já se foram há muito tempo. Este é o caso de uso original: codebases de produção, decisões de esquema, migrações, mudanças de dependência que precisam de uma trilha de auditoria que sobreviva à rotatividade.

Desenvolvedores solo usando Claude Code em projetos do dia a dia. Projetos paralelos, builds de fim de semana, a pequena ferramenta interna que você continua ajustando. Você não precisa de governança empresarial — você só precisa lembrar por que você (ou seu agente) fez o que fez ontem, semana passada, no último sprint. Execute selvedge init uma vez. Adicione quatro linhas ao seu CLAUDE.md. A partir daí, selvedge blame é memória muscular — uma forma de falar com seu eu do passado quando seu eu do passado era um LLM.

Se você já voltou ao seu próprio projeto construído por IA e pensou "para que isso era mesmo?", o Selvedge é a peça que faltava.


O problema

Código escrito por humanos vaza intenção em todos os lugares — mensagens de commit, descrições de PR, comentários inline, o tópico do Slack que o precedeu. Código escrito por IA não. O agente tem clareza perfeita sobre por que tomou cada decisão, mas esse contexto vive no prompt e evapora quando a conversa termina.

Seis meses depois, sua equipe está depurando uma decisão de esquema sem trilha. git blame diz o que mudou e quando. Não pode dizer por quê.

O Selvedge captura o porquê — ao vivo, pelo próprio agente, à medida que a mudança é feita. O diff é trabalho do git. O porquê é do Selvedge.


O que há de novo na v0.3.14

Consultas explícitas de sete dias funcionam como documentado.

A ferramenta MCP prior_attempts agora aceita window_minutes=10080, correspondendo ao seu padrão de sete dias. Anteriormente, enviar esse valor explicitamente falhava na validação porque a janela de tempo incorretamente compartilhava o limite de paginação de 1.000 resultados. A janela permitida é de 1–10.080 minutos; os limites de resultados permanecem limitados a 1.000. Sem novas dependências, migrações ou ferramentas MCP.


O que há de novo na v0.3.13

Mantenha o contexto da revisão com uma rejeição registrada.

  • Resumos de início de sessão mostram quando uma decisão expirou ou precisa de revisão manual, inclusive na seção de rejeição.
  • Decisões substituídas saem da lista de revisão sem ocultar decisões não relacionadas no mesmo caminho. O histórico permanece intacto; a reabertura permanece explícita.
  • Guia de feedback e correção: como relatórios se tornam decisões de produto e como reabrir uma rejeição equivocada usando supersede.

Onde o Selvedge se encaixa

Where Selvedge fits in the broader AI-coded-codebase tooling stack

Agentes de IA chamam o Selvedge enquanto trabalham. O Selvedge captura o porquê em um armazenamento durável e consultável e o emite de volta — como registros Agent Trace para leitores entre ferramentas, como metadados de observabilidade que se vinculam a stack traces do Sentry/Datadog e como artefatos de conformidade para auditorias SOC 2 e EU AI Act.

O Selvedge não substitui git (o que/quando em nível de linha), ferramentas de revisão de PR (qualidade no momento da revisão), observabilidade de agentes (rastros de chamadas LLM), ou recursos de IA de hospedagem de código de propósito geral. Ele fica entre eles — a camada de proveniência como cidadão de primeira classe à qual tudo o mais faz referência.


Como o Selvedge se compara

Há uma categoria em rápido crescimento de "git blame para agentes de IA". Aqui está onde o Selvedge se encaixa — e onde deliberadamente não se encaixa.

Caminhos rejeitadosFonte do raciocínioGranularidadeMecanismoAgrupamentoArmazenamento
SelvedgeConsultávelprior_attempts retorna tentado → revertido → reabertoCapturado ao vivo, pelo agente no mesmo contexto que produziu a mudançaEntidade — coluna de BD, tabela, variável de ambiente, dependência, rota de API, funçãoServidor MCP — o agente o chama à medida que o trabalho aconteceChangesets — slugs nomeados de feature/tarefa em muitas entidadesSQLite, zero dependências
OpenLorePurgado — rejected é um status inativo, removido do armazenamento consultável após cada sincronização de decisão (a anotação sobrevive no markdown do spec sincronizado)Derivado — análise estática tree-sitter do estado do código, mais notas de decisão limitadas por commitNó AST (18 linguagens + 12 IaC)Servidor MCP — índice único + certificados no momento do commitArestas do grafo de chamadasGrafo SQLite em .openlore/
AgentDiff (sunilmallya)NenhumInferido post-hoc por Claude Haiku a partir do diff no final da sessãoLinhaHooks de ciclo de vida do Claude Code → daemon localSessão/tarefaJSONL em disco
AgentDiff (codeprakhar25)NenhumProveniência entre agentes assinada com ed25519LinhaHooks de editor por agente + hooks git (assinatura no commit)NenhumRastros assinados em refs git
OriginNenhum — rework sinaliza código de IA revertido post-hoc, sem justificativaRecibos de prompt, capturados ao vivo por turnoLinhaHooks de ciclo de vida do agente + hook pós-commit gitNenhumNotas git + branch de sessões
Git AINenhumMetadados de atribuiçãoLinhaCheckpoint invocado pelo agente → notas git no commitNenhumNotas git
BlamePromptNenhumRecibos de prompt — prompt, custo, ferramentas; sem justificativa declaradaLinhaHooks de ciclo de vida do agente + hook pós-commitNenhumNotas git

Por que "caminhos rejeitados" importam — o que não é copiável. A falha cara não é esquecer por que uma coluna existe. É um agente reimplementando confiantemente algo que a equipe já matou por um bom motivo, seis meses depois que todos que sabiam disso saíram da janela de contexto. Nenhuma das ferramentas de atribuição de linha acima expõe caminhos rejeitados, e não é uma lacuna de recurso que elas possam fechar em uma versão — um armazenamento orientado a linhas não tem noção de uma entidade que persistiu em um ciclo de tentar → reverter → tentar novamente. Veja docs/demos/prior-attempts.md.

Por que o determinismo importa. O raciocínio do Selvedge é a intenção do próprio agente, escrita a partir da mesma janela de contexto que produziu a mudança. Não há modelo em nenhum lugar no caminho de armazenamento ou recuperação, então a mesma consulta retorna a mesma resposta hoje e em dois anos, entre versões de modelo. Ferramentas que inferem raciocínio post-hoc estão executando um segundo LLM que nunca viu o prompt original: o que produzem é paráfrase, e reexecutá-lo pode produzir categorias diferentes para a mesma mudança. Como um comentarista do Hacker News disse sobre uma abordagem concorrente, "grep não encontrará seu commit porque você rejeitou 'oauth-library'… a menos que haja aplicação determinística" (0x457).

O determinismo sozinho não é mais um separador — o OpenLore também é nativamente determinístico, e diz isso. O composto que separa é testemunho somente de acréscimo: raciocínio que o próprio agente escreveu, mantido em um armazenamento onde uma rejeição é um registro de primeira classe em vez de um status inativo a ser varrido.

Por que "nível de entidade" importa. A maioria das ferramentas atribui linhas. O Selvedge atribui coisas que você realmente procura: users.email, env/STRIPE_SECRET_KEY, api/v1/checkout, deps/stripe. A primeira pergunta após git blame geralmente é "qual é o histórico desta coluna", não "qual é o histórico das linhas 40–48 de users.py".

Por que "capturado ao vivo" importa. Não é um diferencial por si só — toda ferramenta aqui reivindica algum sabor disso — mas é o mecanismo que torna o raciocínio confiável. Escrever no momento da mudança, a partir do contexto que a produziu, é a razão pela qual não há um segundo modelo no caminho para alucinar uma explicação. Um campo reasoning vazio é em si um sinal honesto: o agente não tinha um.

Comparação atual em 2026-08-05; OpenLore na v2.1.8 / 265★, verificada contra sua fonte. Correções são bem-vindas como issue.

Por que "changesets" importam. Um rollout de cobrança do Stripe toca a tabela users, duas novas variáveis de ambiente, três novas rotas de API, uma dependência e quatro funções em todo o codebase. Marque cada evento com changeset:add-stripe-billing e você poderá puxar todo o escopo de volta depois — mesmo que o PR original tenha sido dividido em oito menores ao longo de um mês.

Selvedge ↔ Agent Trace. Agent Trace é um formato de fio aberto de atribuição de código de IA publicado pela Cursor (RFC, jan. 2026). Seu lar original no GitHub ficou 404 em agosto de 2026 e o impulso multi-vendor por trás dele diminuiu, mas o spec e o schema ainda resolvem em agent-trace.dev, congelados na v0.1.0. Desde a v0.3.9, selvedge export --format agent-trace emite registros Agent Trace v0.1.0 e selvedge import --format agent-trace os lê de volta — um formato de intercâmbio portátil e documentado para atribuição de IA por arquivo/linha, com raciocínio e proveniência em nível de entidade carregados nos metadados dev.selvedge de cada registro. O mapeamento está em docs/agent-trace-interop.md; o Selvedge fornece o schema e não tem dependência de runtime no projeto upstream.


Início rápido

Claude Code — instale o plugin (recomendado)

Dois comandos, dentro do Claude Code. Sem pip install prévio — o plugin inicializa o servidor por conta própria via uvx (ou pipx):

/plugin marketplace add masondelan/selvedge
/plugin install selvedge@selvedge

Essa é toda a superfície voltada ao agente em um passo:

  • o servidor MCP — 8 ferramentas (log_change, prior_attempts, blame, diff, history, changeset, search, stale_decisions);
  • uma skill que diz ao agente quando chamá-las — antes de editar uma entidade rastreada, após qualquer mudança substancial;
  • o hook de aplicação PreToolUse — edições de schema/migração são bloqueadas até que prior_attempts tenha sido verificado nesta sessão, com o raciocínio anterior na mensagem de bloqueio;
  • comandos de barra/selvedge:status, /selvedge:blame <entity>, /selvedge:history, /selvedge:prior-attempts <entity>. O armazenamento (.selvedge/selvedge.db) se cria sozinho na primeira alteração registrada. Dois extras opcionais ficam no lado da CLI: o hook pós-commit que carimba cada evento com seu hash de commit (selvedge install-hook) e — se você quiser o comando selvedge no seu próprio shell PATHpip install selvedge, que o lançador então prefere em vez de uvx para uma versão fixada exata.

Plugin ou selvedge setup para Claude Code? Escolha um. Ambos conectam o servidor MCP; executar os dois registra-o duas vezes. O plugin é o caminho mais leve e aquele que se atualiza sozinho. Se você está no plugin e só quer o carimbo de hash de commit pós-commit, execute selvedge install-hook isoladamente.

Escolha seu agente de codificação

Com uv instalado:

uv tool install --upgrade selvedge
selvedge demo
cd your-project
selvedge setup --agent codex

Use codex, claude-code, cursor, copilot, gemini ou windsurf. Repita --agent para várias ferramentas, ou omita para detectar agentes instalados. Prefere pip? Use python -m pip install --upgrade selvedge em um ambiente virtual. O executável selvedge-server deve estar no PATH do seu editor; inicie o editor a partir desse ambiente ou use o caminho absoluto do executável na configuração MCP dele.

A configuração pergunta antes de alterar arquivos, faz backup do conteúdo existente, instala instruções de MCP e de agente, inicializa o projeto e oferece um hook pós-commit do Git. Para Codex, ela escreve .codex/config.toml e AGENTS.md; o Gemini CLI recebe .gemini/settings.json e GEMINI.md; o Copilot recebe .vscode/mcp.json e .github/copilot-instructions.md. Entradas TOML personalizadas do Codex exigem reconciliação manual, mesmo com --force.

Reinicie seu agente no projeto e aprove as ferramentas do Selvedge se for solicitado. O Codex deve confiar no projeto para carregar a configuração no escopo do projeto. Pergunte ao agente:

Use o Selvedge para registrar uma abordagem que consideramos e rejeitamos neste projeto. Inclua o porquê e o que mudaria nossa opinião. Depois, consulte-a com prior_attempts.

Inicie uma nova sessão e consulte a mesma entidade para verificar se a decisão é levada adiante. O acesso MCP não captura automaticamente toda decisão: as instruções instaladas orientam o agente a usá-lo. Hooks de entrega e aplicação de sessão são atualmente integrações do Claude Code.

Para bootstrap de CI ou devcontainer.json postCreateCommand:

selvedge setup --non-interactive --yes

Verifique a conexão — abra um segundo terminal no mesmo projeto:

selvedge watch

Faça qualquer alteração na sua ferramenta de IA — adicione uma coluna, renomeie uma função, adicione uma variável de ambiente. selvedge watch deve imprimir o novo evento em menos de um segundo após o agente chamar log_change. Se nada chegar, execute selvedge doctor para uma verificação de saúde de comando único que informa qual etapa está silenciosamente quebrada.

Consulte seu histórico:

selvedge status                        # recent activity + missing-commit count
selvedge diff users                    # all changes to the users table
selvedge diff users.email              # changes to a specific column
selvedge blame payments.amount         # what changed last and why
selvedge history --since 30d           # last 30 days of changes
selvedge history --since 15m           # last 15 minutes ('m' = minutes)
selvedge changeset add-stripe-billing  # all events for a feature/task
selvedge search "stripe"               # full-text search
selvedge stats                         # log_change coverage report (per-agent)
selvedge import migrations/            # backfill from migration files
selvedge export --format csv           # dump history to CSV
Instalação manual — se você preferir configurar por conta própria

Se você não quiser executar o assistente, os quatro passos manuais que ele automatiza:

1. Inicialize no seu projeto

cd your-project
selvedge init

2. Registre o servidor MCP

O Selvedge é um servidor MCP stdio padrão, então funciona com qualquer cliente MCP — Claude Code, Cursor, Windsurf, Codex CLI, Gemini CLI e outros. Veja Funciona com qualquer cliente MCP para a configuração exata por cliente. Para Claude Code:

claude mcp add selvedge -- selvedge-server

3. Diga ao seu agente para usá-lo

selvedge prompt --install CLAUDE.md

Aponte --install para o arquivo de prompt que seu cliente lê — o bloco em si é idêntico entre clientes:

ClienteArquivo de prompt
Claude CodeCLAUDE.md
Codex CLI (e outras ferramentas que reconhecem AGENTS.md)AGENTS.md
Cursor.cursor/rules/selvedge.md (ou legado .cursorrules)
Gemini CLIGEMINI.md

Isso instala o bloco canônico de instruções do agente, delimitado por sentinelas (<!-- selvedge:start --> / <!-- selvedge:end -->) para que futuras chamadas --install atualizem a região delimitada sem perturbar nada mais no arquivo. Ou canalize-o:

selvedge prompt | tee -a CLAUDE.md

Prefere copiar e colar? O mesmo bloco está a um clique no site: selvedge.sh/prompt-block — com um botão de copiar e notas sobre o que seu agente faz com ele.

4. Instale o hook pós-commit

selvedge install-hook

Esses são os mesmos quatro passos que o assistente executa.


Funciona com qualquer cliente MCP

O Selvedge é um servidor MCP stdio padrão — seu comando de lançamento é selvedge-server, colocado no seu PATH pelo pip install selvedge. Qualquer cliente com capacidade MCP pode executá-lo. Escolha o seu:

Claude Code
claude mcp add selvedge -- selvedge-server

Ou faça commit de um .mcp.json no nível do projeto para que todo o seu time o receba:

{
  "mcpServers": {
    "selvedge": { "command": "selvedge-server" }
  }
}

Documentação: https://code.claude.com/docs/en/mcp

Cursor

.cursor/mcp.json (projeto) ou ~/.cursor/mcp.json (global):

{
  "mcpServers": {
    "selvedge": { "command": "selvedge-server" }
  }
}

O esquema mais novo do Cursor também aceita um "type": "stdio" explícito; a forma somente com command também funciona (o Cursor infere stdio de command). Documentação: https://cursor.com/docs/mcp

Windsurf

~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "selvedge": { "command": "selvedge-server" }
  }
}

O Windsurf recarrega o arquivo automaticamente — sem necessidade de reiniciar. O botão Plugins → Ver configuração bruta no aplicativo abre o arquivo exato que o Cascade lê. Documentação: https://docs.windsurf.com/windsurf/cascade/mcp

Codex CLI

~/.codex/config.toml:

[mcp_servers.selvedge]
command = "selvedge-server"

Ou execute codex mcp add selvedge -- selvedge-server. Documentação: https://developers.openai.com/codex/config-reference

Gemini CLI

~/.gemini/settings.json (ou .gemini/settings.json por projeto):

{
  "mcpServers": {
    "selvedge": { "command": "selvedge-server" }
  }
}

Ou execute gemini mcp add -s user selvedge selvedge-server. Documentação: https://github.com/google-gemini/gemini-cli/blob/main/docs/tools/mcp-server.md

Qualquer outro cliente MCP

A maioria dos clientes compartilha a mesma forma JSON — aponte o seu para:

{
  "mcpServers": {
    "selvedge": { "command": "selvedge-server" }
  }
}

Se selvedge-server não for encontrado, use seu caminho absoluto (which selvedge-server).


Como funciona

O Selvedge roda como um servidor MCP. Agentes de IA em ferramentas como Claude Code chamam as ferramentas do Selvedge enquanto trabalham — registrando eventos de mudança estruturados em um banco de dados SQLite local.

Cada evento registra:

  • O quê mudou (caminho da entidade, tipo de mudança, diff)
  • Quando (timestamp)
  • Quem (agente, ID da sessão)
  • Por quê (raciocínio — capturado do contexto do agente no momento)
  • Onde (commit git, projeto)

O diff é trabalho do git. O porquê é do Selvedge.


O Selvedge rastreia seu próprio histórico

Este repositório usa o Selvedge como teste: seu .selvedge/selvedge.db está commitado, então um clone novo já vem com o histórico de porquês do próprio Selvedge. Clone-o e pergunte por que qualquer parte do Selvedge mudou:

git clone https://github.com/masondelan/selvedge
cd selvedge
selvedge status                       # recent changes to Selvedge itself
selvedge search "telemetry"           # why the opt-in heartbeat shipped
selvedge blame selvedge/semantic.py   # why semantic search was added

Cada evento foi registrado pelos agentes que construíram o Selvedge — as mesmas chamadas log_change que este README pede que você faça no seu próprio projeto.


Convenções de caminho de entidade

users.email           DB column (table.column)
users                 DB table
src/auth.py::login    Function in a file (path::symbol)
src/auth.py           File
api/v1/users          API route
deps/stripe           Dependency
env/STRIPE_SECRET_KEY Environment variable

Consultas por prefixo funcionam em todo lugar: users retorna users, users.email, users.created_at e qualquer outra entidade sob o namespace users..


Ferramentas MCP

Quando conectado como servidor MCP, o Selvedge expõe:

FerramentaDescrição
log_changeRegistra um evento de mudança com entidade, diff e raciocínio. rename_from + change_type="rename" registra o padrão de renomeação de evento duplo; change_type="supersede" reabre uma decisão revertida (somente anexação); constraint / stale_when opcionais mantêm o princípio da decisão e sua condição de invalidação consultáveis
diffHistórico de uma entidade ou prefixo de entidade, cada linha anotada com superseded_by
blameMudança mais recente + contexto de uma entidade exata, além da decisão derivada status (ativa / revertida / reaberta)
historyHistórico filtrado em todas as entidades
changesetTodos os eventos agrupados sob um slug de recurso/tarefa nomeado
searchBusca de texto completo em todos os eventos
prior_attemptsTentativas anteriores de mudança em uma entidade + resultado inferido (tentado → revertido → reaberto) — chame antes de editar. A consulta opcional fuzzy adiciona registros semanticamente semelhantes (precisa do extra semantic; usa substring como fallback)
stale_decisionsDecisões que precisam de revisão: passaram do revisit_after e ainda estão em uso ativo (flag="revisit_due"), ou cuja condição stale_when correspondeu a uma mudança posterior (flag="review_suggested")

Referência da CLI

selvedge init [--path PATH]               Initialize in project
selvedge status                           Recent activity summary
selvedge diff ENTITY [--limit N]          Change history for entity
selvedge blame ENTITY                     Most recent change + context
selvedge history [--since SINCE]          Browse all history
              [--entity ENTITY]
              [--project PROJECT]
              [--changeset CS]
              [--summarize]
              [--limit N]
selvedge changeset [CHANGESET_ID]         Show events in a changeset
                  [--list]                or list all changesets
                  [--project NAME]
                  [--since SINCE]
selvedge search QUERY [--limit N]         Full-text search
selvedge prior-attempts ENTITY            Prior attempts + inferred outcome,
                       [--description T]   with the tried → reverted →
                       [--all]             re-opened trail + status line
                       [--window 7d]       (--all widens recall)
                       [--fuzzy TEXT]      add semantic matches (needs the
                                           semantic extra; substring fallback)
selvedge supersede ENTITY                 Re-open a reverted decision —
                  --reasoning TEXT         append-only, links the prior
                  [--constraint TEXT]      reverted event (or --supersedes ID)
                  [--stale-when TEXT]
                  [--supersedes ID]
selvedge index [--model NAME]             Build/update the optional semantic
              [--json]                     embeddings index (selvedge[semantic])
selvedge stale [--entity ENTITY]          Decisions due for a revisit: past
              [--project NAME]            revisit_after + still in use, or
              [--agent NAME]              stale_when matched by a later change
              [--json]                    ("review suggested")
selvedge stats [--since SINCE]            Tool call coverage report (per-tool, per-agent)
selvedge doctor [--json]                  Health check: DB path, schema, hook, MCP wiring
selvedge install-hook [--path PATH]       Install git post-commit hook
                     [--window MIN]       (default 60 minutes)
selvedge backfill-commit --hash HASH      Backfill git_commit on recent events
                        [--window MIN]    (default 60 minutes)
selvedge import PATH                      Import migrations (SQL / Alembic) or
              [--format auto|sql|         an Agent Trace file (agent-trace)
                 alembic|agent-trace]
              [--from-git]                or walk git history for reverts:
              [--since REF|DATE]          revert-message commits + deletions
              [--project NAME]            become change_type="revert" events
              [--dry-run]                 (idempotent on commit + entity)
selvedge export [--format json|csv|       Export history (agent-trace =
                 markdown|agent-trace]      Agent Trace v0.1.0 records;
                                            markdown = reviewable digest)
              [--since SINCE]
              [--entity ENTITY]
              [--ndjson]                  agent-trace: one record per line
              [--collapse-by-session]     agent-trace: merge a session into one
              [--output FILE]
selvedge log ENTITY CHANGE_TYPE           Manually log a change
             [--diff TEXT]                CHANGE_TYPE: add, remove, modify,
             [--reasoning TEXT]           rename, retype, create, delete,
             [--agent NAME]               index_add, index_remove, migrate,
             [--commit HASH]              revert, supersede
             [--project NAME]
             [--changeset CS]
             [--revisit-after WHEN]       ISO date or offset (e.g. 90d)
             [--rename-from OLD]          OLD path when CHANGE_TYPE is 'rename'
             [--constraint TEXT]          the principle behind the decision
             [--stale-when TEXT]          what would invalidate it
             [--supersedes ID]            with CHANGE_TYPE 'supersede'
selvedge migrate-paths                    Re-canonicalize stored entity paths
                      [--apply]           (dry-run by default; --apply writes)
                      [--json]

Todos os comandos de leitura suportam --json para saída legível por máquina.

Tempo relativo em --since:

  • 15m → últimos 15 minutos (m = minutos)
  • 24h → últimas 24 horas
  • 7d → últimos 7 dias
  • 5mo → últimos 5 meses (mo ou mon = meses)
  • 1y → último ano

Entradas não analisáveis (por exemplo, --since yesterday) saem com um erro claro em vez de retornar silenciosamente resultados vazios. Timestamps ISO 8601 também são aceitos e normalizados para UTC.


Configuração

MétodoFormatoExemplo
Variável de ambienteSELVEDGE_DB=/path/to/dbSubstituição por sessão
Inicialização do projetoselvedge initCria .selvedge/selvedge.db no diretório atual
Fallback global~/.selvedge/selvedge.dbUsado se nenhum banco de dados do projeto for encontrado
Globs de observação do hook.selvedge/config.toml[hook]
watch_globs = ["**/migrations/**", "db/**/*.sql"] — substitui os globs padrão de esquema/migração do hook de aplicação
Configurações do projeto.selvedge/config.tomlVeja a lista de chaves abaixo — retenção, limites de tamanho, padrões de redação
Configurações globais~/.selvedge/config.tomlMesmas chaves; o arquivo do projeto vence onde ambos definem uma
Bypass do hookSELVEDGE_HOOK_DISABLE=1Desativa o hook de aplicação PreToolUse para o shell
Extra semânticopip install "selvedge[semantic]"Ativa selvedge index + prior-attempts --fuzzy (embeddings locais model2vec, ~30 MB; o núcleo nunca depende disso)

.selvedge/config.toml

Toda chave é opcional; um arquivo ausente significa os padrões abaixo. A precedência é flag da CLI → variável de ambiente → .selvedge/config.toml do projeto → ~/.selvedge/config.toml global → padrão. SELVEDGE_DB é a única exceção: ela sempre vence na resolução do banco de dados, porque o arquivo de configuração é encontrado por resolver esse caminho. selvedge doctor imprime o valor efetivo e a etapa que o produziu para cada configuração.

retention_days_events     = 0       # 0 = never delete events (the default)
retention_days_tool_calls = 90      # local telemetry retention
backup_keep_last          = 7
diff_bytes                = 65536   # truncate oversized diffs at log time
reasoning_bytes           = 32768   # truncate oversized reasoning
db_size_warn_mb           = 500     # doctor warns above this
stale_days                = 0       # 0 = off
digest_max_bytes          = 4096    # cap on the session-start digest
redaction_patterns        = []      # extra secret shapes to warn about

[hook]
watch_globs = ["**/migrations/**", "db/**/*.sql"]

Toda chave também tem uma substituição por ambiente (SELVEDGE_DIFF_BYTES, SELVEDGE_RETENTION_DAYS_EVENTS, …).


Revisando a intenção capturada em um pull request

.selvedge/selvedge.db é um arquivo SQLite, então o raciocínio dentro dele não aparece em um diff. Exporte um resumo em Markdown ao lado dele e faça commit de ambos:

selvedge export --format markdown -o .selvedge/DECISIONS.md
git add .selvedge/

O resumo é agrupado por entidade com decisões revertidas primeiro, e é determinístico — regenerar sem novos eventos produz um diff de zero linhas, então ele permanece revisável em vez de virar ruído que todos aprendem a ignorar. Âncoras de cabeçalho derivam do caminho da entidade, então links para ele continuam funcionando conforme ele cresce. Regere-o no mesmo commit do código, ou a partir de um hook pré-commit.


Verificação de cobertura

Quer saber com que frequência seu agente realmente chama log_change? Duas maneiras de verificar:

# Quick summary in the terminal
selvedge stats

# Cross-reference against git commits
python scripts/coverage_check.py --since 30d

O script de cobertura compara seu log do git com os eventos do Selvedge e mostra quais commits têm eventos de mudança associados. Cobertura baixa geralmente significa que o prompt do sistema precisa ser reforçado — veja docs/fallbacks.md para orientação.

Em CI (GitHub Action)

A mesma verificação é distribuída como a Action composta Selvedge Coverage Check, então você pode acompanhar a cobertura do agente a cada push — e opcionalmente falhar o build quando ela cair:

# .github/workflows/selvedge-coverage.yml
name: Selvedge coverage
on: [push, pull_request]
jobs:
  coverage:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0            # full history so commits can be matched
      - uses: masondelan/selvedge@v0.3.14   # pin to a release tag (or @main for latest)
        with:
          since: 30d
          fail-under: "0.5"         # optional: fail below 50% coverage; omit to report only

Ele grava um resumo de cobertura no resumo do job e expõe coverage-ratio, covered e total como saídas da etapa. A ação faz referência cruzada do seu histórico do git com o log de eventos do Selvedge, então o runner precisa do .selvedge/selvedge.db do projeto (faça commit dele, ou restaure-o antes desta etapa) e do histórico completo do git (fetch-depth: 0). Entradas: since, window, limit, fail-under, selvedge-version, python-version, working-directory, db-path.


Contribuindo

Leia o processo de feedback e revisão para relatar problemas, avaliar solicitações de recursos e acompanhar discussões.

git clone https://github.com/masondelan/selvedge
cd selvedge
pip install -e ".[dev]"
pytest

Consulte CLAUDE.md para detalhes da arquitetura e o roteiro das fases.


Licença

MIT — veja LICENSE.