test-skill-installer
Skill1 starsChanged 3 months agoMITView on GitHub
대상 프로젝트를 분석해 그 프로젝트 전용 테스트 작성 스킬(test-writer)을 설치하는 메타 스킬. "테스트 스킬 설치/생성", "이 프로젝트에 테스트 스킬 깔아줘", "테스트 자동화 세팅", "test-skill-installer", "테스트 강제 hook", "코드 작업 후 테스트 강제" 요청 시 사용. 언어/프레임워크/빌드툴/테스트 러너/기존 컨벤션을 감지해 .claude/skills/test-writer/SKILL.md를 생성하고, 코드 편집 후 테스트를 강제하는 Stop hook과 CLAUDE.md 가이드를 주입한다. MSA처럼 레포마다 스택이 다른 환경에서 프로젝트별 맞춤 테스트 스킬을 1회 명령으로 깐다.
In this repository13 other files it gives its agents.
- 01-architecture-checkSkill
- 02-guidelinesSkill
- 03-spec-requirementSkill
- 04-planningSkill
- 05-plan-reviewSkill
- 06-codingSkill
- applyhomeSkill
- code-recallSkill
- harness-evolveSkill
- harness-installerSkill
- obsidianSkill
- pre-commit-reviewSkill
- session-evalSkill
The file
We split this skill into the rules it gives an agent
1 rule. About 0 are common, 0 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 149
Stop hook은 stop_hook_active가 true면 재차단하지 않는다 → 사용자가 의도적으로 스킵할 수 있는 탈출구가 있다(무한루프 방지).
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
test-skill-installer — 프로젝트별 테스트 스킬 인스톨러
현재 작업 디렉토리(대상 프로젝트)를 분석해 그 프로젝트에 맞는 test-writer 스킬을
설치한다. 결과물:
.claude/skills/test-writer/SKILL.md— 감지된 스택/컨벤션이 박힌 맞춤 테스트 작성 스킬.claude/hooks/test-guard/— 코드 편집 후 테스트를 강제하는 Stop hook (+ PostToolUse 추적).claude/settings.json— 위 hook 등록 (기존 설정과 머지).claude/.test-guard.conf— "테스트 실행으로 인정할" 명령 정규식CLAUDE.md— "코드 작업 후 test-writer 실행" 가이드 블록 주입
번들 자산은
${CLAUDE_PLUGIN_ROOT}/assets/아래에 있다:test-writer-template.md,hooks/track-edits.sh,hooks/test-guard.sh,hooks/hooks.json. 대상 프로젝트 경로는 항상 현재 작업 디렉토리($PWD) 기준으로 쓴다.
절차
0) 사전 확인
- 현재 디렉토리가 대상 프로젝트 루트인지 확인한다(보통 git 루트). 아니면 사용자에게 확인.
- 이미
.claude/skills/test-writer/SKILL.md가 있으면 재설치/갱신 모드임을 알리고, 기존 내용을 덮기 전에 무엇이 바뀌는지 요약해 사용자 동의를 받는다.
1) 프로젝트 분석 (가장 중요)
다음을 현재 작업 디렉토리의 실제 파일을 읽어 판별한다. 추측 금지. 외부 지식베이스·팀 표준·다른 레포가 아니라 이 프로젝트의 코드 자체만 근거로 삼는다.
- 언어 / 빌드툴: 매니페스트로 식별.
package.json(JS/TS, npm/yarn/pnpm),pyproject.toml/setup.py/requirements.txt(Python),go.mod(Go),mix.exs(Elixir),build.gradle(.kts)/pom.xml(JVM, Kotlin/Java),Gemfile(Ruby),Cargo.toml(Rust),composer.json(PHP),*.csproj(.NET) 등.
- 테스트 프레임워크 / 러너: 의존성과 설정에서.
- 예: jest/vitest/mocha, pytest/unittest,
go test, ExUnit(mix test), JUnit/Spock/Kotest, RSpec, cargo test, PHPUnit, xUnit 등.
- 예: jest/vitest/mocha, pytest/unittest,
- 테스트 디렉토리 / 네이밍: 기존 테스트를
Glob으로 찾아 위치와 파일명 규칙을 파악.- 예:
tests/,test/,__tests__/,src/**/*.test.ts,*_test.go,test/**/*_test.exs.
- 예:
- 실행 명령: 매니페스트의 scripts/tasks에서 실제 명령을 뽑는다.
- 전체 실행, 단일 파일 실행, 커버리지 명령.
- 기존 컨벤션: 테스트가 있으면 대표 테스트 파일 1~2개를 직접 읽어 import 방식, 픽스처/팩토리, 모킹 도구, 어서션 스타일, 셋업/티어다운 패턴을 기록한다. 테스트가 거의 없으면 소스 코드 자체의 스타일(네이밍, 모듈 구조, 에러 처리 관례)을 읽어 그에 맞는 테스트 스타일을 정한다. 어느 쪽이든 근거는 이 디렉토리의 코드다.
- 비즈니스 로직 지도: 엔트리포인트와 핵심 도메인 모듈/디렉토리를 파악해, test-writer가 "어디부터 커버할지" 알 수 있게 요약을 만든다.
분석 결과를 사용자에게 짧게 표로 보고하고 진행한다.
2) test-writer 스킬 생성
${CLAUDE_PLUGIN_ROOT}/assets/test-writer-template.md를 읽는다.{{...}}플레이스홀더를 1)의 결과로 모두 치환한다. 빈 값을 남기지 말 것 (해당 없으면 "N/A — 이 프로젝트엔 없음"처럼 명시).{{PROJECT_NAME}}{{LANGUAGE}}{{TEST_FRAMEWORK}}{{BUILD_TOOL}}{{TEST_DIR}}{{TEST_NAMING}}{{RUN_ONE_COMMAND}}{{RUN_ALL_COMMAND}}{{COVERAGE_COMMAND}}{{CONVENTION_NOTES}}{{INTEGRATION_NOTES}}{{E2E_NOTES}}{{EXTRA_SECTIONS}}: 프로젝트 특이사항(모노레포 패키지별 러너, 통합 테스트용 docker-compose, 테스트 DB 준비 절차 등)을 필요한 만큼 섹션으로 추가. 없으면 빈 문자열.
- 결과를
.claude/skills/test-writer/SKILL.md로 쓴다(Write). - e2e가 무의미한 프로젝트(순수 라이브러리 등)면 e2e 섹션을 단위/통합 중심으로 축소하고 그 사유를 한 줄 남긴다.
3) 테스트 명령 설정 파일
.claude/.test-guard.conf를 쓴다. 1)에서 뽑은 전체 테스트 명령을 정규식으로:test_command_regex=<예: (mix test|pytest|npm (run )?test)>- hook은 이 정규식에 매칭되는 Bash 명령을 "테스트 실행"으로 인정해 부채를 해제한다. 러너 명령의 핵심 토큰을 넣되 과하게 넓히지 말 것.
4) hook 설치 (테스트 강제)
mkdir -p .claude/hooks/test-guard${CLAUDE_PLUGIN_ROOT}/assets/hooks/track-edits.sh와test-guard.sh를.claude/hooks/test-guard/로 복사하고chmod +x..claude/settings.json의hooks에 아래를 머지한다(기존 hook 보존).${CLAUDE_PLUGIN_ROOT}/assets/hooks/hooks.json의hooks객체가 머지할 내용이다.- settings.json이 없으면
{ "hooks": { ... } }로 생성. - 있으면
jq로 이벤트 키별 배열 concat + 중복 제거 병합:SNIP="${CLAUDE_PLUGIN_ROOT}/assets/hooks/hooks.json" mkdir -p .claude if [ -f .claude/settings.json ]; then trap 'rm -f .claude/settings.json.tmp' EXIT jq -s ' def dedup: reduce .[] as $x ([]; if any(.[]; . == $x) then . else . + [$x] end); (.[0]) as $cur | (.[1].hooks) as $new | $cur * { hooks: ( reduce ($new | to_entries[]) as $e (($cur.hooks // {}); .[$e.key] = (((.[$e.key] // []) + $e.value) | dedup)) ) } ' .claude/settings.json "$SNIP" > .claude/settings.json.tmp \ && mv .claude/settings.json.tmp .claude/settings.json else jq '{hooks:.hooks}' "$SNIP" > .claude/settings.json fi*(최상위 키 보존) + 각 이벤트 키(PostToolUse/Stop/…)의 배열을 덮어쓰지 않고 concat한다 → 이미 등록돼 있던 다른 PostToolUse hook이 보존된다.dedup은 완전히 동일한 matcher-group 객체를 제거하므로 재설치해도 멱등이다 (= "이미 test-guard hook이 등록돼 있으면 중복 추가 안 함"이 구현으로 보장됨).- jq가 compile/실행 실패하면
&& mv가 안 돌아 기존 settings.json은 그대로 두고,trap이 빈.tmp를 정리한다.
- 머지 후
jq -e '.hooks.Stop and .hooks.PostToolUse' .claude/settings.json로 유효성과 hook 등록을 실제로 확인해 사용자에게 보고(0이면 등록 성공).
- settings.json이 없으면
- 항상 작업 디렉토리의
.claude/settings.json에 넣는다. 위치를 사용자에게 묻지 않는다.
5) CLAUDE.md 가이드 주입
- 프로젝트 루트
CLAUDE.md를 읽는다(없으면 생성). - 아래 마커 블록을 추가한다. 이미 마커가 있으면 그 안만 갱신(중복 추가 금지):
<!-- test-skill-installer:begin --> ## 테스트 규칙 (test-writer) - 코드를 추가/수정한 뒤에는 **반드시 `test-writer` 스킬**로 변경분의 테스트를 작성/보강하고, 테스트 러너(`{{RUN_ALL_COMMAND}}`)를 돌려 통과를 확인한 뒤 작업을 마친다. - 기존 테스트 컨벤션을 따르고, 테스트가 없는 부분만 채운다. - 코드 편집 후 테스트 없이 종료하려 하면 Stop hook이 막고 리마인드한다. 테스트가 정말 불필요한 변경이면 그 사유를 한 줄 남기고 종료한다. <!-- test-skill-installer:end -->{{RUN_ALL_COMMAND}}는 1)의 실제 명령으로 치환.
6) 글로벌(~/.claude) 동기화 — 사용자가 원할 때만
- 사용자가 "내 글로벌에도", "로컬에서도 쓰게" 라고 한 경우에만 수행.
test-writer스킬은 프로젝트 맞춤이라 글로벌 복사는 보통 부적절하다. 대신 인스톨러 자체를 글로벌에서 쓸 수 있게 하는 것이 맞다: marketplace를 통해test-skill-installer플러그인을 사용자 레벨로 설치하면 어느 프로젝트에서든/test-skill-installer:install을 쓸 수 있다.- hook(
track-edits.sh/test-guard.sh)을 모든 프로젝트에 전역 적용하고 싶다면,~/.claude/settings.json에 같은 hook을 등록하되 command 경로를 고정 위치 (예:~/.claude/hooks/test-guard/)로 복사해 쓴다. 단 전역 강제는 부작용이 크니 사용자에게 위험(모든 세션에서 동작)을 고지하고 동의를 받는다.
7) 검증 & 보고
- 생성/수정한 파일 목록, hook 등록 상태, CLAUDE.md 주입 결과를 요약.
- 즉시 검증: 더미 흐름으로 hook이 등록됐는지
jq출력으로 확인하고, 사용자에게 "다음 코드 편집부터 강제가 동작한다"고 안내한다. - 마지막에
test-writer스킬을 한 번 시범 실행할지 물어본다(선택).
설계 노트 (강제 메커니즘)
- CLAUDE.md 문구 = soft 가이드, Stop hook = hard 강제. 둘을 함께 깐다.
- Stop hook은
stop_hook_active가 true면 재차단하지 않는다 → 사용자가 의도적으로 스킵할 수 있는 탈출구가 있다(무한루프 방지). 진짜 권한 경계가 아니라 "기본값"이다. - 부채 판정은 소스 코드 확장자 편집 기준이며 테스트/문서/설정 편집은 제외한다.
- 의존성: hook은
jq를 쓰면 정확하고, 없으면sed폴백으로 동작한다(권장:jq설치).
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

