Entre o modelo e o disco, um hook.
O Claude Code traz o modelo e as ferramentas dele. O Nerviz acrescenta cinco tipos de peça em volta. Quatro orientam o modelo. A quinta roda como processo em cada evento e pode recusar a ação.
Um caso de uso encontra o harness
O UC-005 do bank-app, do primeiro prompt ao build verde, em nove passos. O terminal mostra quais modos de hook rodaram e o que imprimiram: as recusas são o texto dos próprios hooks.
Um prompt abre o turno
Você digita /new-feature. O guard prompt fecha a fase anterior, registra o que já está no disco e abre uma fase para new-feature, classe orchestrator. O corpo da skill entra no contexto e fica até o fim do run.
Quem carrega, quem chama, quem pode dizer não
- CLAUDE.md
Índice e tabela de roteamento. A norma em si fica na rule ou na skill para a qual ele aponta.
- Entra no contexto
- Sempre, no início da sessão
- Invocado por
- Ninguém: ele carrega
- Pode bloquear
- Não
- rule
Uma norma: o que precisa ser verdade. Uma folha: nunca cita skill, agent ou comando.
- Entra no contexto
- Quando um arquivo que casa com os
pathsdela é tocado - Invocado por
- Ninguém: ela carrega
- Pode bloquear
- Não
- skill
Um procedimento. A classe fixa o modelo, as seções do corpo e onde ela pode escrever.
- Entra no contexto
- Na invocação, e fica para os turnos seguintes
- Invocado por
- Você, com
/nome, ou o modelo - Pode bloquear
- Não
- agent
Execução isolada: contexto próprio, tools restritas e modelo próprio.
- Entra no contexto
- Na delegação, num contexto limpo
- Invocado por
- Uma skill, pela Agent tool
- Pode bloquear
- Não
- hookexit 2
ArchHook.jar: Java, onze modos, sem shell. Ligado nosettings.json.- Entra no contexto
- Nunca como texto: roda como processo
- Invocado por
- O runtime, no evento
- Pode bloquear
- Sim, exit 2
Um agent só existe por um de três motivos: preservar contexto, restringir tools ou trocar de modelo. O que precisa valer sempre é hook ou regra de permissions.deny, nunca prosa em markdown.
Quantas skills e agents
Toda skill e todo agent do nerviz pertence a uma classe em extensions.json, e o schema falha em qualquer arquivo que nenhuma classe liste. As classes são o catálogo: estes números são lidos delas na release mais recente, nunca digitados à mão.
Exportados para todo projeto gerado: 27
design13orchestrator3build7observer2meta1ops4report2
Exportados para todo projeto gerado: 5
driver1executor1installer4verifier1
project-confignova2026-10-24platform-upgrade2026-10-19new-project2026-10-15mapstruct-installer2026-10-14ai-architect2026-10-13
Lido de extensions.json na release v0.44.0 do nerviz, publicada em 2026-10-27.
Três comandos, três cadeias
Cada comando abre uma cadeia própria:
/init-projectcria o projeto, uma única vez./new-featureprojeta um caso de uso e entrega uma spec, sem código./new-feature-implementconstrói o código a partir da spec aprovada.
Peças tracejadas só rodam quando se aplicam.
use-case-design00-caso-de-uso.mddomain-modeling10-dominio.mdrest-api-architect30-rest.mdsalvo quando o gatilho é só GraphQLgraphql-api-architect31-graphql.mdquando o gatilho cita um adapter GraphQLsecurity-architect32-seguranca.mdquando o acesso pede mais do que a filter chain dáhttp-client-architect28-cliente-http.mdquando uma porta chama outro sistema por HTTPai-architect29-ia.mdquando uma porta é um LLM ou um vector storesearch-architect23-busca.mdquando a linha Search index cita uma projeçãomessaging-architect25-mensageria.mdquando um evento precisa de entrega via Kafkajobs-architect35-jobs.mdem agendamento, relay de outbox, reconciliação, reindexação ou poda de históricopersistence-architect20-persistencia.mdcache-architect22-cache.mdquando o Freshness declara uma tolerânciatest-architect40-testes.md- você aprova · spec congelada
mapstruct-installerpre-flight, quando nenhum mecanismo de mappers está registrado; primeiro e sozinho se escolher MapStructcommons-logging-installerpre-flight, quando o commons está vaziojava-spring-boot-developergrupo domainjava-spring-boot-developergrupo adaptersjava-spring-boot-developergrupo tests- build verde · spec implementada
compose-service-installerquando a spec decidiu um novo serviço no compose; roda o docker-architect
- skill
- agent
- só quando se aplica
Cada classe só escreve nos próprios paths
Cada skill pertence a uma de sete classes, e cada agent a uma de quatro. A classe lista o que pode escrever no extensions.json, e o guard recusa todo o resto, deny by default. Escolha uma classe:
.claude/CLAUDE.mddocs/use-cases/BACKLOG.mduse-cases/UC-005-record-kyc-verdict/20-persistencia.mduse-cases/UC-005-record-kyc-verdict/UC-005-spec.mdlessons-learned/src/main/java/…/domain/model/Customer.javasrc/test/java/…/domain/model/CustomerTest.javapom.xmldocker-compose.yml.env.example
- pode escrever
- recusado: fora da territory
- recusado: spec congelada
- só fechamento de status e checklist
Tocou no arquivo, recebeu as normas
Toda rule declara paths. Quando um arquivo que casa é tocado, a rule entra no contexto sozinha, e ninguém precisa lembrar de citá-la. Estas são as 21 rules do bank-app, com os globs que o export escreveu para o blueprint dele. Escolha um arquivo:
architecture-ddd.mdvalue-objects.mdnaming.mdcode-quality.mderror-handling.mdlogging.mdlombok.mdpersonal-data.mdsecrets.mdapi-rest.mdapi-graphql.mdinbound-admission.mdauthorization.mdobservability.mdpersistence.mdmessaging.mdscheduling.mdhttp-client.mdai.mdcaching.mdsearch.mdtesting.mdtransport-security.mdspec-diagrams.md00-index.md
Cada evento, cada modo
O que um projeto gerado registra no .claude/settings.json. Toda entrada roda java -jar .claude/hooks/ArchHook.jar <mode>, em exec form, igual no Linux, no macOS e no Windows. Escolha um evento para ver quando ele dispara.
Os eventos, na ordem em que disparam em um turno
audit promptguard promptVocê aperta Enter. O hook roda antes de o Claude ler uma palavra.
Você digitou
Modos neste evento
audit promptAbre o registro da run quando o prompt é de uma skill auditada, para atribuir tokens e arquivos a ela.o projeto pode desligarguard promptFecha a fase anterior e abre a que o prompt nomeia, para os guards saberem qual skill está rodando.
guard callguard writeguard bashschemaaudit callaudit askO Claude está prestes a usar uma ferramenta. O hook ainda pode dizer não.
Você digitou
persistence-architect quer escrever docker-compose.ymlguard write confere o território da classe delaModos neste evento
guard callImpede que uma run de design alcance uma skill de build.pode bloquearBloqueia: Uma chamada
Skilla uma skill de classe build enquanto uma run de design está aberta.guard writeToda skill e todo agente escreve só dentro do território da sua classe, e um spec aprovado fica congelado.pode bloquearBloqueia: Uma escrita fora do território da skill ou do agente em execução, e qualquer escrita em um caso de uso aprovado, salvo o fechamento do status e o marcar de checklist.
guard bashA mesma checagem, vinda do shell: um heredoc,sed -iouteenão pode fazer o que um Write não pode.pode bloquearBloqueia: Uma escrita via shell em um lugar que a classe não pode escrever ou em um caso de uso congelado, e um force push em qualquer grafia.
schemaMantém válidos os arquivos de instrução do harness, para uma skill, um agente ou uma entrada de hook quebrada falhar na hora e não em uma run futura.pode bloquearBloqueia: Um
SKILL.md, agente, regra ou entrada de hook dosettings.jsoninválido, e um segredo no.mcp.json.audit callRegistra cada chamada de Skill, Task ou Agent como um nó da cadeia.o projeto pode desligaraudit askAnota que o Claude está esperando você, para a espera não contar como trabalho.o projeto pode desligar
context subagenttests agent-startO Claude passa o trabalho a um subagente. O hook pode carregar contexto antes do primeiro turno dele.
Você digitou
context subagent entrega o catálogo de padrõesModos neste evento
context subagentEntrega o catálogo de padrões de projeto a todo agente cuja classe o pede, antes do primeiro turno. Os outros agentes não recebem nada.tests agent-startAnota que um subagente escritor está rodando, para os testes esperarem por ele.
checkschemaformataudit fileaudit answerUma ferramenta acabou de rodar. A mudança já foi feita, e o hook olha para ela.
Você digitou
Customer.javacheck, format e a trilha olham o arquivoModos neste evento
checkSegura a arquitetura enquanto o código é escrito: a fronteira é julgada a cada edição, não no review.pode bloquearBloqueia: Um import ou nome qualificado proibido, ou uma compilação incremental que falha no módulo tocado. O arquivo já foi escrito, então o Claude é mandado corrigir.
schemaMantém válidos os arquivos de instrução do harness, para uma skill, um agente ou uma entrada de hook quebrada falhar na hora e não em uma run futura.pode bloquearBloqueia: Um
SKILL.md, agente, regra ou entrada de hook dosettings.jsoninválido, e um segredo no.mcp.json.formatRodaspotless:applyno módulo tocado, para a formatação nunca custar um turno.audit fileRegistra cada arquivo que uma run tocou.o projeto pode desligaraudit answerRegistra cada pergunta e a sua resposta, com redação, no relatório.o projeto pode desligar
audit agenttests agent-endO subagente termina e devolve o resultado.
Você digitou
Modos neste evento
audit agentFecha o relatório do subagente. Os tokens dele vêm do próprio transcript.o projeto pode desligartests agent-endLibera os testes quando o subagente escritor termina.
schemaguard sweepcompose gatetestsaudit flushO Claude acha que terminou. É o último portão antes de o turno acabar.
Você digitou
schema, guard sweep, compose gate e tests olham o que de fato mudouModos neste evento
schemaMantém válidos os arquivos de instrução do harness, para uma skill, um agente ou uma entrada de hook quebrada falhar na hora e não em uma run futura.pode bloquearBloqueia: Um
SKILL.md, agente, regra ou entrada de hook dosettings.jsoninválido, e um segredo no.mcp.json.guard sweepO reforço no fim do turno: compara o disco com o baseline do git, então pega as escritas que nenhum guard em tempo de ferramenta conseguiu ler.pode bloquearBloqueia: Qualquer mudança deste turno que a classe não pode escrever. Ele detecta; não previne.
compose gateUma stack que não sobe é pega quando o turno acaba, não depois na máquina de alguém.pode bloquearo projeto pode ajustarBloqueia: O fim do turno enquanto um serviço do compose está
exitedoudead.testsUm turno não termina com teste vermelho.pode bloquearBloqueia: O fim do turno enquanto o
verifyfalha nos módulos alterados desde oHEAD. Ele espera enquanto um subagente escritor roda.audit flushGera o relatório da run a partir do log e escreve a linha do ledger.o projeto pode desligar
audit permaudit failaudit compactaudit stopfailaudit closeSeis eventos discretos. Só escrevem na trilha de auditoria, e nenhum bloqueia.
Você digitou
git push, que fica em askModos neste evento
audit permRegistra uma permissão pedida ou negada.o projeto pode desligaraudit failRegistra uma ferramenta que falhou, como retrabalho.o projeto pode desligaraudit compactRegistra uma compactação de contexto.o projeto pode desligaraudit stopfailRegistra uma falha ao parar.o projeto pode desligaraudit closeFecha a run aberta quando a sessão termina.o projeto pode desligar
mode pode recusar com exit 2 · mode nunca bloqueia ·pode bloquear o projeto pode ajustar o projeto pode desligar
Por que cada modo existe, o que ele bloqueia e o que um projeto pode mudar: todos, em uma tabela, com o detalhe.
Abrir o catálogo de modos →Cada recusa acima roda no CI
O validate.yml roda em todo push e todo pull request. Os testes de hook executam o mesmo java -jar .claude/hooks/ArchHook.jar que os registros executam, no Ubuntu, no macOS e no Windows. Outro job verifica os invariantes do grafo de prompts, e outro exporta cada blueprint duas vezes e exige árvores idênticas.
- hooks · ubuntu-latest1m32s
- hooks · macos-latest1m37s
- hooks · windows-latest3m15s
- design invariants33s
- export is reproducible and self-contained55s
- exemplar imports resolve against the real classpath6m13s
Os seis jobs rodam em paralelo. Em cada job de hooks, o build --verify roda antes dos testes: o jar commitado precisa ser, byte a byte, o que o código-fonte compila, então os testes exercitam bytes revisados.
runs do validate.yml passaram desde 2026-09-11. 11 falharam e 4 foram cancelados. Contagem de 2026-10-13.
Os vermelhos continuam públicos no Actions. O badge acima é ao vivo; os números são um retrato.
Todos os runs →Cada step desse run, em replay
Os 58 steps nomeados do validate.yml, com os tempos que o GitHub registrou no run acima, 12× mais rápido. O job de hooks roda cada step em três runners, um ponto para cada: Ubuntu, macOS e Windows.
- Set up job · checkout · setup-java
- doctor
- committed ArchHook.jar is what the source compiles to
- the jar runs what the hooks run
- hook blocks forbidden import, from the payload and from argv
- format, check and tests hand Maven the module the edited file belongs to
- tests defers while a writer subagent of the session runs, and only then
- hook blocks a cwd-relative frontmatter injection
- schema blocks a migrations entry no project would see
- hook reports a compose image tag that disagrees with src/test
- guard keeps each skill inside its class's territory
- guard keeps each agent inside its class's territory
- guard bash refuses force pushes and holds shell writes to the phase
- guard sweep reports this turn's writes, never pre-existing dirt
- guard status prints the open phase the cockpit draws
- schema blocks a mod that would load half-way
- compose gate blocks a published service no host client can reach
- doctor gate fails on every gated line and only on those
- schema blocks a settings file that re-enables a colliding plugin
- doctor names a personal skill that shadows a project skill, and never gates
- doctor checks the agent instruction files against the blueprint, and never gates
- doctor sweeps every source file for forbidden imports, with check's own match
- export notes only real overwrites, and never guesses the stamp's commit
- context subagent hands the catalog to pattern_catalog agents only
- audit renders where the run spent, redacts tool errors, skips what class or project turns off
- audit genesis fills GENESIS from the transcripts, once
- Set up job · checkout · setup-java
- frontmatter schema (extensions.json is the single owner — invariant 10)
- decisions/ doesn't grow paths or enter 00-index.md
- no hardcoded Spring/Java version outside decisions/ (invariant 8)
- new blueprint doesn't touch prompts
- rules is a leaf of the graph
- norm contains no code boilerplate
- no new commands/
- exemplars have the .example suffix at the end
- exemplar bodies carry no comment but Javadoc
- XML exemplars are well-formed
- spec template diagrams name only what their text defines
- cache exemplars decide every library default, and only they cache
- AI exemplars decide every library default, and only they reach the library
- GraphQL exemplars decide every limit and batch every child list
- document-family exemplars name collection, alias and version, and run a replica set
- search exemplars keep the index a strict, versioned projection
- auditing exemplars keep the history whole, its actor named and its prune safe
- REST exemplars version every handler from one configuration
- admission exemplars keep one bounded limiter per caller and an inbound cap ahead of idempotency
- blueprint-declared templates exist on disk
- issue forms cited by skills exist
- compose service templates merge and parse
- each norm has a single owner
- no dependencies outside the Java ecosystem
- every norm `paths` matches some blueprint
- Set up job · checkout · setup-java
- export twice per blueprint, require identical trees
- the exported tree carries nothing that only exists here
- the exported tree passes its own schema
- re-export deletes what export.retired names
- Set up job · checkout · setup-java
- reference project from the Initializr
- build the classpath
- every exemplar import exists in a JAR
- exemplars don't use known deprecated symbols
Cada passo do player, e o teste que o prova
- passo 4
Uma skill de design não consegue escrever o
docker-compose.yml. O caso que originou tudo é um dos casos.$ java .claude/.ci/SkillTerritoryTest.java✅ compose file outside the territory — blocked (exit 2)✅ compose allowed once docker-architect joined (exit 0)✅ the implement thread itself still may not write compose (exit 2)59 casos, todos verdes
A mesma territory vale para escritas pelo shell, e toda grafia de force push é recusada.
$ java .claude/.ci/BashGuardTest.java✅ `-f` — blocked✅ executor: `sed -i -e` on a file outside its territory — blocked29 casos, todos verdes
- passo 6
Um agent é julgado pela própria classe, seja qual for a fase que quem o chamou deixou aberta.
$ java .claude/.ci/AgentTerritoryTest.java✅ the executor writes main source (exit 0)✅ archunit-installer is refused docker-compose.yml (exit 2)37 casos, todos verdes
O catálogo de design patterns só chega aos agents cuja classe o pede.
$ java .claude/.ci/SubagentContextTest.java✅ general-purpose receives nothing✅ context subagent: catalog to pattern_catalog agents only, within max_chars.
- passo 7
Um import proibido dá exit 2, pelo payload do hook e pelo
check <path>.$ java .claude/.ci/BoundaryTest.java ✓ stdin payload blocks the forbidden import ✓ check <path> blocks it with stdin left open✅ Boundary enforced: forbidden import blocked with exit 2, from the payload and from argv.
- passo 9
O sweep do
Stopsó aponta o que este turno escreveu, e nunca bloqueia duas vezes.$ java .claude/.ci/SweepTest.java✅ write outside the territory — reported, pre-existing dirt is not✅ stop_hook_active — does not block twice
O
testsespera enquanto um subagent escritor roda, e só nesse caso.$ java .claude/.ci/TestsDeferTest.java✅ tests: deferred while a writer subagent runs, Maven called otherwise.
O grafo de prompts, verificado como código
O job design invariants transforma cada regra da arquitetura do próprio harness num step que falha. Alguns deles, com o nome que têm no workflow:
frontmatter schema (extensions.json is the single owner — invariant 10)rules is a leaf of the graphnew blueprint doesn't touch promptsno hardcoded Spring/Java version outside decisions/ (invariant 8)each norm has a single ownerevery norm `paths` matches some blueprint
E em todo projeto gerado
O projeto leva o próprio CI. O job architectural boundaries roda o doctor gate, que falha quando o jar, os hooks, o schema ou as boundaries estão quebrados, ou quando algum arquivo-fonte tem um import proibido.
- architectural boundaries
java .claude/hooks/ArchHook.java doctor gate10s - build and tests3m37s