<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="brand/nerviz-banner-dark.png">
<img alt="Nerviz — an agent harness for Spring Boot" src="https://raw.githubusercontent.com/nerviz-ai/nerviz/HEAD/brand/nerviz-banner-light.png" width="100%">
</picture>
</p>
CI
Release
License: Apache 2.0
PRs Welcome
Java 21+
Built with Claude Code
Spring Boot
GitHub stars
GitHub issues
Last commit
Claude Code에서 작동하는 Spring Boot용 에이전트 하네스입니다. 이 도구는 데이터로 선언된 아키텍처로부터 프로젝트를 생성하며, 코드가 작성되기 전에 모든 기능을 승인된 명세(spec)로 설계하고, 해당 아키텍처가 금지하는 내용은 쓰기 시점에 차단합니다. 생성된 프로젝트에는 전체 하네스가 포함되어 있으며 나중에 이를 업데이트할 수 있습니다.
문서화: docs/en/ (영어) · docs/pt-br/
(포르투갈어). 유사 프로젝트와의 비교 및 출처는 다음 문서를 참고하세요:
docs/en/09-differentiators.md.
/init-project 실행을 통해 생성된 결과물은 공개되어 있습니다: nerviz-ai/bank-app입니다. 이 프로젝트는 clean-architecture-single-module 유형이며, 녹색 빌드(green build)를 달성했습니다. 해당 실행에는 20분이 소요되었으며, 이 수치는 세션 기록에서 추출되어 GENESIS.md에 기록되었습니다.
생성된 프로젝트를 그대로 열어보면: compose Postgres를 대상으로 시작하며, mvn clean verify가 테스트(tests), Spotless, Checkstyle, JaCoCo와 함께 성공적으로 통과합니다.
다음으로, 생성된 프로젝트 내의 첫 번째 기능인 /new-feature를 살펴보겠습니다. 이 명령어는 한 줄 요청을 받아 디자인 변경이 필요한 질문(누가 호출할 수 있는지, 중복 여부, 연령 규칙, 데이터 보존 등)만을 묻고, 각 레이어별로 하나의 스킬이 해당 사양(spec)의 부분을 작성합니다. 코드가 단 한 줄 존재하기 전에 이 사양은 승인되고, 동결되며, 커밋되고 푸시됩니다. 전체 과정은 10분이 소요되었으며, 그중 약 2분은 답변을 기다리는 시간이었습니다.
이 프로세스를 통해 생성된 모든 내용은 공개적입니다:
승인된 사양,
부분별 작성 내용(partials),
그리고 실행 과정의 감사 보고서입니다.
이것은 /new-feature의 두 가지 흐름 중 첫 번째 흐름입니다. 두 번째 흐름인 /new-feature-implement UC-001-create-customer는 /clear 명령어 이후에 실행되며, 승인된 사양을 정리된 세션에서 실행 에이전트(executor agent)에게 전달합니다.
한눈에 보기 (At a glance)
- 데이터로서의 아키텍처 9가지, 그리고 사용자가 추가할 수 있는 아키텍처. 청사진은 YAML 파일입니다. 하나를 추가해도 프롬프트는 변경되지 않습니다.
- 코드보다 사양(Spec) 우선. 하나의 유스 케이스가 실행될 때마다, 각 레이어별 오너 스킬이 단계적으로 설계하고, 사용자가 승인하며, 동결합니다.
- 쓰기 시점 차단 (Blocked at write time). 금지된 import, 스킬 영역 밖의 쓰기 작업, 승인된 사양에 대한 수정, 또는 강제 푸시(force push)는 후크(hook)에 의해 거부됩니다. 모델에게 규칙을 기억하라고 요청하지 않습니다.
- Spring Initializr에서 가져온 버전. 절대 모델의 메모리에서 가져오지 않습니다.
- 모든 실행 과정 측정. 각 스킬과 에이전트는 소요 시간, 토큰(tokens), 질문 횟수, 수정된 파일 목록을 포함한 보고서를 남깁니다.
- 자체 완결형 프로젝트 (Self-contained projects). 생성된 프로젝트는 전체 하네스와 자체 CI(Continuous Integration)를 가지고 있으며,
/arch-adopt가 나중에 이를 업데이트합니다.
이것이 무엇이고, 무엇이 아닌지 (What this is, and what it is not)
2026년의 실질적인 정의는 *에이전트 = 모델 + 하네스(harness)*입니다. Claude Code가 모델과 도구 루프(tool loop)를 제공합니다. 이 저장소는 Spring Boot 작업을 위한 나머지 하네스를 두 부분으로 나누어 제공합니다:
- 가이드(Guides): 에이전트가 행동하기 전에 모델을 유도합니다. 여기에는 규범(
rules/), 절차 및 예시(skills/), 아키텍처 청사진, 그리고 구축 중인 기능의 사용 사례 명세서가 포함됩니다.
- 센서(Sensors): 모델이 무엇을 했는지 결정론적으로 확인합니다. 스킬 영역 외부에서의 쓰기를 거부하거나 금지된 임포트를 막는 훅(hook), 증분 빌드, ArchUnit, compose 건강 게이트(health gate), 그리고 하네스 자체를 검증하는 CI(Continuous Integration)가 이에 해당합니다.
이것은 코딩 어시스턴트가 아닙니다: 모델이나 에디터를 가져오지 않습니다. LangGraph나 Spring AI와 같은 에이전트 프레임워크도 아닙니다: 이들은 에이전트를 구축하지만, 이 저장소는 에이전트를 제약합니다. 또한 프로젝트 템플릿도 아닙니다: 실행 시간에 Spring Initializr를 통해 생성되며, 그 역할은 생성이 끝난 후에도 모든 기능에 걸쳐 계속됩니다.
문제점
개발자는 30줄짜리 CLAUDE.md로 Java 프로젝트를 시작합니다. 6개월 후에는 400줄이 되고, 모델은 그 절반을 무시하며, 동일한 규칙이 더 이상 일치하지 않는 세 개의 스킬에 존재하게 됩니다. AI는 이 프로젝트에서 무엇이 진실인지 저렴하고 신뢰성 있게 알려주는 것이 아무것도 없고, 잘못되었을 때 이를 막아주는 것도 없기 때문에 아키텍처를 '잊어버립니다'.
새로운 프로젝트 역시 제로(zero)부터 시작합니다. 동일한 규칙들이 다시 작성되고, 이전 프로젝트에서 배운 것은 아무것도 살아남지 못합니다.
접근 방식
AI 파일을 프로덕션 코드처럼 취급합니다: 명시적인 아키텍처, 단방향 의존성, 규칙당 하나의 소유 파일(owning file), 그리고 모델의 기억이 아닌 프로그램에 의한 강제 적용입니다. 구체적으로는 다음과 같습니다:
- 아키텍처는 데이터입니다. 아홉 가지 청사진(
hexagonal, hexagonal-single-module, clean-architecture-multi-module, clean-architecture-single-module, layered, onion, onion-single-module, vertical-slice, modular-monolith)와 사용자가 직접 만든 청사진이 각각 YAML 파일로 존재합니다. 하나의 forbidden_imports 선언은 모듈의 CLAUDE.md, 쓰기를 차단하는 후크, 그리고 POM 그래프에 정보를 제공합니다. 새로운 아키텍처는 프롬프트를 건드리지 않으며, CI가 이를 확인합니다.
- 버전은 절대로 메모리에서 작성되지 않습니다. 기본 프로젝트는 실행 시점(run time)에
start.spring.io로부터 가져옵니다. Spring 또는 Java 버전이 사실(fact)로 나타나면 CI가 실패합니다.
- 실행당 하나의 유스케이스(use case)가 존재하며, 이는 빌드되기 전에 설계됩니다.
/new-feature는 요청을 레이어별 소유자 스킬(owner skill) 하나를 통해 전달하고 UC-NNN-spec.md를 통합합니다. 승인된 후에야 제한된 실행기 에이전트(restricted executor agent)가 src/ 아래에 코드를 작성합니다.
- 영역(Territory)은 약속되는 것이 아니라 강제됩니다. 모든 스킬과 에이전트는
schemas/extensions.json에 클래스를 가지고 있습니다. 이 클래스는 해당 요소가 작성할 수 있는 경로를 명시하며, guard 후크는 파일 도구와 셸 명령어 모두를 통해 그 외의 모든 것을 거부합니다. 승인된 spec 폴더는 고정(frozen)됩니다.
- 컨텍스트는 저렴하게 유지됩니다. 루트의
CLAUDE.md는 200줄 미만으로 유지됩니다. Norms는 해당 영역 내 파일이 건드려질 때에만 paths를 통해 로드됩니다.
- 모든 실행은 측정됩니다. 생성된 프로젝트에서 각 스킬 또는 에이전트 호출(invocation)은 토큰 및 조각별 모델 정보, 호출 체인(call chain), 건드려진 파일, 그리고 실패 내역을 포함하는 보고서를 남깁니다.
시작하기 (Getting started)
요구 사항: JDK 21+, git, curl. 그 외에는 아무것도 필요하지 않습니다: Python 없음, Node 없음, 셸 스크립트 없음, PATH에 mvn 없음 (래퍼는 Initializr의 starter.tgz 내부에 포함됩니다).
새 프로젝트 (New project)
프로젝트는 이 저장소의 사본(copy)으로부터 생성되는 것이며, 빈 디렉터리에 .claude/를 복사하는 방식이 아닙니다. /init-project와 청사진 카탈로그(blueprint catalog)는 해당 사본에 유지되며, 프로젝트는 export 모드를 통해 개발에 필요한 내용만 받게 됩니다. 이 사본은 클론(clone)이며, 아래 또는 플러그인이 가져오는 트리 구조를 가집니다:
claude plugin marketplace add nerviz-ai/marketplace
claude plugin install nerviz@nerviz
cd ~/dev && claude
그런 다음 /nerviz:new-project를 사용하면 최신 릴리스(release)를 ~/dev/nerviz-<태그>에 가져오고, 어떤 태그와 커밋을 가져왔는지 기록하며, /init-project를 위해 해당 위치에서 세션을 열도록 출력합니다. 이 생성 과정은 클론이 실행하는 것과 동일합니다. 대신 클론을 사용하려면:
cd ~/dev
git clone --depth 1 https://github.com/nerviz-ai/nerviz
...
해당 세션 내부에서는 다음과 같이 실행합니다:
/arch-doctor # 이 장치에서 강제가 활성화되었는지 확인
/init-project --blueprint hexagonal --build maven --name my-api
Claude Code는 시작된 디렉터리 외부에 작성하기 전에 사용자에게 묻습니다. 한 번의 생성을 승인하려면, /init-project를 실행하기 전에 mkdir ../my-api를 실행하고 /add-dir ../my-api를 실행하세요. 빈 디렉터리도 허용됩니다.
프로젝트는 클론 옆, 즉 ../<이름> (위 예시에서는 ~/dev/my-api)에 탄생합니다. 마지막으로, git-publish는 두 번 묻습니다. 첫 번째는 git init을 실행하여 첫 커밋을 만들 때이고, 두 번째는 GitHub 저장소(repository)를 생성하고 푸시할 때입니다. 하나의 클론으로는 원하는 만큼 많은 프로젝트를 생성할 수 있으며, 그 사이에는 /clear를 사용합니다.
그런 다음 생성된 프로젝트 내부에서 새로운 세션을 열어 개발을 시작합니다:
/new-feature <첫 번째 사용 사례가 수행해야 할 작업>
이 순서로 하는 이유:
- 생성된 프로젝트는 자체적인
.claude/를 가집니다. export 모드는 규칙(rules), 개발 스킬(development skills), 실행 에이전트(executor agents), 훅(hook), 그리고 활성 청사진(active blueprint)을 작성합니다. 이는 init-project, project-bootstrap, 및 청사진 카탈로그를 제외하므로, 프로젝트가 라이브 코드 위에 스스로 재생성될 수 없습니다. 또한 이 저장소에는 쓰지 않도록 거부합니다.
.claude/settings.json은 세션 시작 시 한 번 읽힙니다. 클론에서 열린 세션은 프로젝트의 훅이 아닌 이 저장소의 훅을 사용하여 실행됩니다. 여기서 개발한다는 것은 프로젝트의 어떤 훅도 작동하지 않으며, 모든 것이 작동하는 것처럼 보인다는 것을 의미합니다.
- 첫 번째
git-publish 게이트를 수락하세요. tests 훅은 git diff HEAD를 사용합니다. 커밋이 없는 저장소에서는 HEAD가 존재하지 않아 훅이 단 하나의 테스트도 실행하지 않고 종료됩니다.
프로젝트 자체의 CLAUDE.md는 해결된 버전과 실제 모듈 목록을 포함하여 부트스트랩(bootstrap) 중에 생성됩니다. 이 저장소 루트에 있는 CLAUDE.md는 메타 리포지토리(meta-repository)를 설명하며 이동하지 않습니다. 전체 생성 순서는 docs/en/02-init-project.md에 있습니다.
기존 프로젝트 (Existing project)
해당 프로젝트의 세션 내부에서 /arch-adopt를 사용하면, 여기서 생성된 적이 없는 프로젝트에 이 .claude/를 설치하거나, 뒤처진 버전을 더 최신 버전으로 가져올 수 있습니다. 이는 오염된 작업 트리(dirty worktree)는 거부하고 결정론적(deterministic)인 export 모드를 통해 작성합니다. 또한 .claude/.arch-provenance.json을 기록하여, 다음 업데이트 시 수동으로 편집한 모든 파일에 이름을 지정한 후 덮어씁니다. 업데이트 시에는 프로젝트가 아직 보지 못한 컨벤션 변경 사항에 대한 migrations 노트를 출력하지만, 절대 실행하지는 않습니다. docs/en/10-arch-adopt.md를 참조하세요.
Spring Boot 기준선 아래의 프로젝트 (Project below the Spring Boot floor)
이 .claude/의 기준선보다 낮은 Spring Boot 라인의 프로젝트는 export에 의해, 그리고 /arch-adopt에 의해서도 거부됩니다. 올라가는 방법은 /platform-upgrade입니다. 프로젝트 내부에서 실행하세요:
- 변경하는 것: Spring Boot 버전, Initializr가 나열하는 BOM들(Spring Cloud 트레인), 이름이 변경된 starter와 Testcontainers 아티팩트, 이제 필요한 starter의 타입(
@EnableCaching), 이름이 변경된 타입(테스트 슬라이스(test slices), @MockBean, 그리고 @SpyBean), 이름이 변경된 설정 속성, 그리고 새로운 플러그인이 거부하는 Gradle wrapper.
- 방법:
ArchHook.jar upgrade-recipe가 데이터와 속성 변경을 통해 Spring 자체 JAR의 게시를 작성하며, 이는 프로젝트 자체의 Maven 또는 Gradle wrapper를 통해 Apache 라이선스가 부여된 OpenRewrite 코어에 의해 실행됩니다. 이름 변경만으로는 커버할 수 없는 것은 빌드가 성공(green)할 때까지 컴파일 오류 하나하나를 안내하며 통과하는 과정입니다. 테스트는 버전 업데이트 전후에 실행되며, ArchHook.jar test-diff는 업그레이드가 기존에 깨져 있던 것 중 무엇을 추가로 망가뜨렸는지 알려줍니다.
- 절대 하지 않는 것: 커밋(commit)하거나,
.claude/를 쓰거나, 실패하는 테스트를 삭제, 건너뛰기 또는 완화하지 않습니다. 더티 워크트리(dirty worktree)는 거부하며, /arch-adopt를 출력하면서 종료됩니다.