저장소 컨벤션을 인식하는 코딩 에이전트 구축하기
요약
다양한 AI 코딩 에이전트(Claude Code, Cursor, Copilot 등) 간의 저장소 컨벤션 불일치 문제를 해결하기 위한 오픈 소스 CLI 도구인 klaussy-agents를 소개합니다. 하나의 SKILL.md 파일을 기반으로 각 에이전트의 고유한 형식에 맞춰 설정을 자동 생성하는 적응 계층 기술을 다룹니다.
핵심 포인트
- 에이전트별로 상이한 컨텍스트 파일(CLAUDE.md, .cursor/rules 등) 동기화 문제 해결
- 단일 SKILL.md 형식을 각 에이전트의 네이티브 프리미티브로 매핑하는 적응 계층 구현
- 멀티 에이전트 환경에서 저장소 인식 기술(repo-aware skills)의 일관성 유지
- klaussy-agents 오픈 소스 CLI를 통한 스캐폴딩 방식 제공
요약 (TL;DR)
저는 저장소의 컨벤션을 한 번 읽고 다섯 가지 코딩 에이전트(Claude Code, Gemini CLI, Cursor, Codex, GitHub Copilot)를 위한 저장소 인식 기술(repo-aware skills)을 스캐폴딩(scaffolding)하는 오픈 소스 CLI인 klaussy-agents (pip install klaussy-agents)를 구축했습니다. 흥미로운 부분은 적응 계층(adaptation layer)입니다. Claude가 작성한 하나의 SKILL.md가 서브 에이전트(sub-agent) 및 플랜 모드(plan-mode)의 용어가 각 에이전트 고유의 프리미티브(primitive)에 어떻게 매핑되는지를 포함하여, 각 에이전트의 네이티브 형식으로 다시 작성됩니다. 이것은 런타임(runtime)이 아닌 스캐폴더(scaffolder)이며, 현재 v0.3.2 버전이고, 에이전트별 번역 과정에는 실제적인 경계(seams)가 존재합니다. 저장소: github.com/steph-dove/klaussy-agents.
문제점
각 AI 코딩 에이전트는 자신만의 방식으로 저장소 컨텍스트(repo context)를 읽습니다. Claude Code는 CLAUDE.md를 읽고, Gemini CLI는 GEMINI.md를 읽으며, Codex는 AGENTS.md를, Cursor는 .cursor/rules를, 그리고 Copilot은 .github/copilot-instructions.md를 읽습니다. 게다가 각 에이전트는 재사용 가능한 "기술(skills)" 또는 "명령어(commands)"를 담은 자체 폴더를 가지고 있습니다. 따라서 한 에이전트를 위해 작성한 컨벤션과 그 안에서 조정된 모든 리뷰 또는 플랜 워크플로우(plan workflow)는 다른 에이전트로 전달되지 않습니다. 두 번째 에이전트를 동일한 저장소로 지정하면, 첫 번째 에이전트가 작성하지 않은 파일을 읽기 때문에 처음부터 다시 시작하게 됩니다.
다섯 개의 컨텍스트 파일과 기술 폴더를 수동으로 동기화할 수도 있지만, 이는 하나가 수정될 때 나머지는 수정되지 않아 금방 부패하는 번거로운 작업입니다. 실질적인 결과는, 설정을 다섯 번 다시 하지 않는 한, 당신이 여는 에이전트가 당신의 저장소에 대해 가장 적게 알고 있는 에이전트가 된다는 것입니다.
진정한 해결책을 가능하게 하는 것은 이제 다섯 가지 에이전트 모두가 동일한 공개 Agent Skills SKILL.md 형식를 읽는다는 점입니다. 하나의 폴더 형식으로 진정으로 휴대 가능합니다. 따라서 도구가 저장소의 컨벤션을 한 번 발견하면, 각 에이전트의 네이티브 레이아웃에 맞게 적응된 기술을 생성할 수 있습니다. 이 포스트는 적응(adaptation) 단계에 관한 것인데, 그 단계야말로 단순한 복사-붙여넣기를 넘어선 지점이기 때문입니다.
왜 다섯 개의 설정을 수동으로 만드는 것이 저에게 확장 가능하지 않았는가
대안이 실제로 무엇인지 명확히 하자면 다음과 같습니다. 에이전트별 설정을 수동으로 관리하는 방식은 에이전트를 하나만 사용할 때는 잘 작동합니다. CLAUDE.md 파일 하나와 몇 개의 .claude/skills/ 디렉토리를 사용하는 것은 완벽하게 좋은 설정이며, 팀 전체가 하나의 도구만 사용한다면 이런 과정이 전혀 필요하지 않습니다.
범용 스캐폴더 (Scaffolder, cookiecutter 및 유사 도구들)는 프로젝트 구조를 찍어내는 데는 훌륭하지만, 서브 에이전트 (sub-agent)가 무엇인지, 혹은 Cursor가 규칙을 적용하는 범위 (scope)와 Copilot이 적용하는 방식이 어떻게 다른지는 알지 못합니다. 여기서 발생하는 간극은 구체적으로 멀티 에이전트 (multi-agent) 환경에서의 문제입니다. 즉, 동일한 리뷰 워크플로우 (review workflow)를 다섯 가지 다른 방식으로 표현하면서, 이를 영원히 동기화된 상태로 유지해야 한다는 점입니다. 이것은 템플릿 생성 (templating)의 문제가 아니라 번역 (translation)의 문제입니다. SKILL.md 명세 (spec)는 공유된 소스 형식을 제공하며, klaussy가 수행하는 작업은 발견 (discovery), 에이전트별 적응 (adaptation), 그리고 네이티브 연결 (native wiring)입니다. 덕분에 저는 동일한 기술 (skill)의 복사본 다섯 개를 수동으로 관리할 필요가 없습니다.
솔직하게 말하자면, 명세 (spec)가 이식성 (portability)을 가능하게 만들었습니다. klaussy는 그 위에서 지루하고 오류가 발생하기 쉬운 부분을 처리합니다.
접근 방식
klaussy init은 이 모든 과정을 한 번에 수행하며, 기본적으로 다섯 개의 에이전트를 모두 설정합니다. 내부적으로는 저장소 컨벤션 (repo-conventions) 발견 단계를 한 번 실행하여, 프로젝트 전역의 CLAUDE.md와 경로 범위가 지정된 .claude/rules/*.md를 생성한 다음, 이를 각 에이전트의 네이티브 형식으로 번역합니다. 경로 범위가 지정된 규칙 (path-scoped rules)은 각 에이전트 고유의 범위 지정 메커니즘 (scoping mechanism)에 매핑됩니다. 예를 들어, applyTo: 프론트매터 (frontmatter)를 사용하는 Copilot의 .github/instructions/*.instructions.md, globs: 프론트매터를 사용하는 Cursor의 .cursor/rules/*.mdc 등이 이에 해당합니다.
'한 번의 발견 후 번역'이라는 동일한 구조가 기술 (skills)에도 적용됩니다. klaussy는 Claude Code의 구문으로 작성된 11개의 네임스페이스화된 (namespaced) 워크플로우 기술을 제공하며, 이를 각 에이전트의 전용 기술 디렉토리에 작성합니다. 기술들은 <repo>-<skill> 형태로 네임스페이스화되어 있어, 에이전트가 여러 저장소를 체크아웃(checked out)한 상태에서도 저장소 간에 충돌이 발생하지 않습니다.
pip install klaussy-agents
klaussy init # 기본 브랜치를 묻고, 다섯 개의 에이전트를 모두 스캐폴딩합니다
klaussy init --agents claude,cursor # 일부 하위 집합으로 범위를 좁힙니다
일부만 실행하고 싶다면 개별 단계(klaussy skills, settings, hooks, github 등)를 실행할 수도 있습니다. 이 포스트의 나머지 부분은 skills 단계에 집중합니다. 왜냐하면 그 단계에서 수행되는 적응 (adaptation) 과정이 제가 실제로 읽어보고 싶었던 부분이기 때문입니다.
작동 방식
하나의 작성된 기술, 다섯 개의 대상 방언
기술 (skills)은 Claude Code의 구문 (syntax)으로 작성됩니다. 이는 Claude 전용 구성 요소 몇 가지에 의존한다는 것을 의미합니다: 명령을 실행하고 그 출력을 인라인으로 포함하는 `!` 동적 셸 (dynamic-shell) 블록, subagent_type과 함께 Agent 도구를 통해 호출되는 병렬 하위 에이전트 (parallel sub-agents), 그리고 플랜 모드 (plan mode)를 위한 ExitPlanMode가 그것입니다. 이러한 토큰들은 Gemini나 Codex에게 문자 그대로 아무런 의미가 없습니다.
따라서 klaussy는 본문 (body)을 그대로 복사하지 않습니다. 대신 대상 에이전트의 용어로 동일한 의도를 포착하도록 각 본문을 다시 작성합니다. 세 가지 구체적인 재작성이 발생합니다:
-
동적 셸 블록이 명시적인 지침으로 변환됩니다.
git diff를 조용히 실행하고 결과를 인라인으로 포함하는!블록은, 다른 에이전트가 실제로 따를 수 있는 -
Claude Code:
Agent/subagent_type -
Cursor:
Task(GA) -
Codex:
spawn_agent(GA) -
Gemini CLI: subagents (기본 활성화,
experimental항목에서 토글 가능) -
GitHub Copilot:
task/read_agent(추가로 실험적 기능인context: fork포함)
따라서 순차적 실행을 하드코딩하는 대신, 적응 노트(adaptation note)는 대상 에이전트에게 Claude의 서브 에이전트(sub-agent) 용어를 자신의 상응하는 기본 요소(primitive)로 매핑하도록 지시하며, 정말로 적절한 요소가 없는 경우에만 순차적 실행으로 대체하도록 합니다. 이 노트는 Claude 전용 도구 이름을 전달하는 것이 아니라 의도("이 렌즈(lenses)들은 독립적이므로 병렬로 실행하십시오")를 전달합니다. ExitPlanMode의 경우도 마찬가지입니다. 이 노트는 Claude만 가지고 있는 특정 도구의 이름을 명시하는 대신, '계획 후 확인'이라는 의도를 설명합니다.
# 예시 — 정확한 문구는 기술(skill)마다 생성되므로, 출력된 SKILL.md에서 확인하십시오.
# 적응 노트 (기술이 서브 에이전트를 오케스트레이션할 때 추가됨):
# 이 기술은 독립적인 렌즈들을 병렬로 실행합니다. 당신의 자체적인
...
이 부분이 제가 진정으로 가르칠 만하다고 생각하는 지점입니다. 에이전트 간의 이식성(portability)은 단순히 "도구 이름을 찾아 바꾸는 것"이 아닙니다. 그것은 의도(intent)와 기본 요소(primitive)를 분리한 다음, 각 에이전트가 해당 의도를 자신이 보유한 어떤 기본 요소에든 다시 바인딩(rebind)할 수 있도록 하는 것입니다. SKILL.md 명세는 공유된 컨테이너를 제공할 뿐, 공유된 도구를 제공하는 것이 아니므로, 본문은 기능이 저하되더라도 우아하게 작동(degrade gracefully)하도록 작성되어야 합니다.
추상적이지 않은 실제 기술 사례
"생성된 기술이 실제로 무엇을 하는가"를 구체화하자면 다음과 같습니다. 리뷰 기술(review skill)은 diff 크기에 따라 분류한 다음 병렬 렌즈를 실행합니다. 표준 4가지 렌즈 외에도, 변경 사항이 AI 코드에 영향을 미치는 경우 에이전트/평가(Agentic/Evals) 렌즈를 추가하며, PR에 ADR, RFC 또는 설계 문서가 포함된 경우 아키텍처 결정/설계 문서(Architecture-Decision/Design-Doc) 렌즈를 추가합니다. 이는 정밀도에 편향되어 있습니다. 즉, 빈 리뷰(플래그를 지정할 가치가 없는 경우)도 유효한 결과입니다. 모든 발견 사항은 구체적인 트리거(trigger)를 명시해야 하며, 최종 검증 단계에서는 무언가가 보고되기 전에 거짓 양성(false positives)을 스스로 반박하여 제거합니다.
전체 워크플로우는 한 번 작성되면 다섯 가지 에이전트의 스킬 폴더(skills folders)로 모두 적응됩니다. 렌즈 팬아웃(lens fan-out)은 위에서 언급한 서브 에이전트 번역(sub-agent translation)이 정확히 필요한 부분이며, 정밀도-편향(precision-bias) 및 검증(validation) 단계는 일반적인 산문 형태이므로 변경 없이 그대로 전달됩니다.
권한 및 훅(hooks)의 동반 적용
스킬(skills) 단계가 핵심이지만, klaussy init은 에이전트별 네이티브 권한 허용 목록(permission allow-lists)도 작성합니다 (Claude settings.json allow/deny, Gemini settings.json tools.allowed, Cursor permissions.json terminalAllowlist, Codex config.toml approval/sandbox). 또한 해당 에이전트 고유의 메커니즘을 사용하여 .env, *.pem, credentials*와 같은 비밀 정보(secrets)가 각 에이전트의 손에 닿지 않도록 유지하려고 시도합니다.
또한 두 가지 에이전트 간 훅(cross-agent hooks)을 연결합니다: 커밋 전에 감지된 포맷과 린트(lint)를 실행하는 git-commit 가드(guard), 그리고 프롬프트 인젝션(prompt-injection) 마커를 찾기 위해 파일과 가져온 콘텐츠를 스캔하는 읽기 주입(read-injection) 가드입니다. 가드 스크립트는 전달받은 에이전트 훅 페이로드(hook payload)에서 명령어나 경로를 추출하고, exit 2와 함께 stderr를 출력하며 차단하는데, 이는 지원되는 모든 에이전트가 준수하는 방식입니다. 이들은 순수 표준 라이브러리(pure-stdlib)로 구성되어 있으며, 어떤 파싱 에러(parse error)가 발생하더라도 충돌하는 대신 허용(allow)으로 폴백(fallback)되도록 강화되어 있습니다. 현재 스위트(suite)는 130개의 테스트를 통과했으며, ruff 결과도 깨끗합니다.
빠른 데모
저장소를 지정하고 실행하세요:
pip install klaussy-agents
klaussy init
기본 브랜치(base branch)를 묻는 프롬프트가 나타나면, 다섯 가지 에이전트 모두를 위한 컨벤션 파일(conventions files), 스킬(skills), 권한(permissions), 훅(hooks)을 스캐폴딩(scaffolds)합니다. 일부 에이전트만 원하는 경우 이름을 지정하세요:
klaussy init --agents claude,cursor
그 후, 저장소 내에서 구성된 에이전트 중 하나를 열면 해당 에이전트가 찾는 컨벤션 파일과 자체 디렉토리에 네임스페이스화된 스킬(namespaced skills)을 이미 갖추고 있음을 의미합니다. 에이전트 자체는 여전히 사용자가 직접 설치하고 실행하는 것이며, klaussy는 에이전트들이 읽을 파일을 생성할 뿐입니다.
향후 계획 및 한계점
심층 분석(deep-dive)에서는 솔직한 버전을 보여드려야 하므로, 아직 완전히 도달하지 못한 부분은 다음과 같습니다:
- 기술(skills)은 Claude가 작성한 후 조정되는 것이지, 에이전트별로 수동 튜닝(hand-tuned)되는 것이 아닙니다. 조정 과정에서 의도(intent)를 포착하고, 서브 에이전트(sub-agent) 노트가 각 에이전트에게 자신의 프리미티브(primitive)를 사용하도록 지시하지만, 이는 번역에 가깝습니다. 각 에이전트의 특이점에 맞춰 처음부터 작성된 다섯 가지 맞춤형 기술 세트는 아닙니다. 만약 Codex에 완벽하게 관용적인(idiomatic) 기술을 원한다면, 여전히 수동으로 조정해야 할 수도 있습니다.
- 훅(Hook) 커버리지는 설계상 불균일합니다. 읽기 주입 가드(read-injection guard)는 Claude, Gemini, Cursor에만 연결되어 있습니다. Codex는 파일 읽기 전(pre-file-read) 훅 이벤트(hook event)를 노출하지 않으며, Copilot의
preToolUse는 확인되지 않은 읽기 도구 인자(read-tool args)에 대해 fail-closed 방식으로 작동하므로, 이 두 가지는 커밋 가드(commit guard)만 적용받습니다. klaussy는 가드가 어디에나 있는 것처럼 꾸미는 대신 이를 로그로 기록합니다. - 비밀 정보 제외(Secret exclusion)는 보편적으로 불가능합니다. Codex의 샌드박스(sandbox)는 쓰기(writes)와 네트워크(network)를 제어할 뿐 읽기(reads)를 제어하지 않으므로, 그곳에는 읽기 제외 기능이 없습니다. Copilot의 콘텐츠 제외(content-exclusion)는 커밋된 파일이 아니라 GitHub 설정입니다. klaussy는 아무런 효과가 없는
.ignore파일을 가짜로 만드는 대신 사실을 그대로 밝힙니다. - SKILL.md 명세(spec)가 준수된다는 점에 의존합니다. 현재 이식성(portability)은 실재하지만, 명세와 에이전트들은 아직 초기 단계입니다. 만약 에이전트가 기술을 읽는 방식을 변경한다면, klaussy는 이를 추적해야 합니다.
이 중 그 어떤 것도 에이전트들이 "동등하다"는 것을 의미하지 않습니다. 그렇지 않습니다. 조정 레이어(adaptation layer)의 핵심은 에이전트들이 서로 다르며, 기술 세트가 각 에이전트에 맞춰 유연하게 변해야 한다는 점입니다. klaussy는 스캐폴더(scaffolder)입니다. 즉, 에이전트가 읽는 파일을 생성할 뿐, 에이전트를 실행하거나 모델의 품질을 변경하지는 않습니다.
(한 가지 명확히 할 점: 별도의 유료 klaussy 데스크톱 앱이 있습니다. 다른 제품이며 동일한 개발자가 만든 것입니다. 이 포스트는 오직 오픈 소스인 klaussy-agents CLI에 대해서만 다룹니다.)
사용해 보기
저장소: github.com/steph-dove/klaussy-agents
설치: pip install klaussy-agents
{% github steph-dove/klaussy-agents %}
만약 동일한 저장소 (repo)에서 하나 이상의 코딩 에이전트 (coding agent)를 실행한다면, 당신이 선택한 에이전트에서 어떤 기술 (skill)이 번역 과정에서 깔끔하게 유지되었고 어떤 것이 어색하게 출력되었는지 알고 싶습니다. 문제가 발생한 부분에 대해 이슈 (issue)를 생성하거나 댓글을 남겨주세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기