
저는 현재 백엔드 레포, 프론트엔드 레포, AWS 테라폼 레포를 Claude Code로 관리하고있습니다. 서비스가 확장되면서 레포 간 상호 의존성이 생겼고, 일관성을 유지하기 위해 내부 SDK 도입을 검토하게 됐습니다. 그러면서 자연스럽게 문제가 따라왔습니다. 에이전트가 각 레포를 열 때마다 SDK 사용법과 레포 간 연동 규약을 모릅니다. CLAUDE.md에 적어두면 되긴 한데, SDK가 업데이트되면 그 내용은 자동으로 바뀌지 않습니다. 누군가 수동으로 챙겨야 하죠.
skills-npm은 이 문제를 꽤 우아하게 해결합니다. 핵심은 단순합니다. AI 지침을 npm 패키지 안에 같이 실어서 배포하자는 것입니다.
에이전트에게 컨텍스트를 주는 방법은 크게 두 가지입니다. 직접 프롬프트에 넣거나, CLAUDE.md 같은 파일에 적어두는 것이죠. 두 번째 방식이 현실적으로 더 낫습니다. 그런데 문제가 있습니다.
CLAUDE.md에 "이 SDK는 이렇게 써라"라고 적어뒀는데, SDK가 업데이트되면 이 파일은 자동으로 바뀌지 않습니다. 누군가 수동으로 바꿔야 합니다. 근데 아무도 안 합니다. 저도 안 했습니다.본질적으로, AI에게 전달하는 컨텍스트가 코드와 분리된 채 관리되고 있다는 구조적 문제입니다.
현재 가장 많이 쓰이는 건 vercel-labs/skills 같은 Git 기반 스킬 CLI입니다. npx skills add로 Git 레포에서 스킬을 클론해서 프로젝트에 연결하는 방식이죠. 쓸 만하긴 한데 한계가 명확합니다.
skills-npm이 제안하는 컨벤션은 이겁니다. SDK 개발자가 npm publish할 때 AI 지침 파일도 같이 실어서 보낸다. 소비자는 npm install하면 자동으로 그 지침이 에이전트가 읽을 수 있는 위치로 심볼릭 링크됩니다.
SDK 버전이 2.0으로 올라가면 SKILL.md도 2.0에 맞게 업데이트됩니다. npm install만 하면 에이전트가 읽는 지침도 즉시 최신화되는 겁니다. 따로 관리할 게 없습니다.

공급자 (SDK 개발자)
skills/<스킬명>/SKILL.md 작성package.json의 files 필드에 "skills" 포함소비자 (앱 개발자)
npm i -D skills-npm 설치prepare 스크립트에 skills-npm 등록npm install 시 skills/npm-<패키지명>-<스킬명> 경로로 자동 심볼릭 링크 생성AI 에이전트 (Cursor, Claude Code, Codex 등)
skills/npm-* 경로 스캔SKILL.md를 읽어 SDK 사용법과 시스템 간 연동 로직 파악심볼릭 링크(symlink)라는 게 낯설 수 있는데, 실제 파일을 복사하는 게 아니라 node_modules 안에 있는 원본을 가리키는 포인터를 만드는 겁니다. 그래서 npm update로 패키지가 바뀌면 에이전트가 읽는 내용도 자동으로 바뀝니다.

my-sdk/
├── package.json
├── dist/
└── skills/
└── data-integrity/ ← 스킬 이름
└── SKILL.md
package.json에서 files 필드에 skills를 반드시 포함해야 합니다. 빠뜨리면 npm publish할 때 해당 디렉토리가 제외됩니다.
{
"name": "@my-org/my-sdk",
"version": "1.3.0",
"files": [
"dist",
"skills",
"index.d.ts"
]
}
npm i -D skills-npm
{
"scripts": {
"prepare": "skills-npm"
}
}
prepare 훅을 쓰는 이유는 npm install 직후 자동으로 실행되기 때문입니다. 팀원이 클론하고 npm install만 해도 세팅이 끝납니다.
.gitignore에 아래도 추가합니다. 심볼릭 링크를 커밋할 필요는 없습니다.
skills/npm-*
skills-npm.config.ts모노레포 환경이거나 특정 패키지의 스킬만 주입하고 싶을 때 씁니다.
import { defineConfig } from 'skills-npm'
export default defineConfig({
source: 'package.json',
agents: ['cursor', 'claude-code'],
gitignore: true,
include: ['@my-org/*'], // 사내 SDK 스킬만 주입, 외부 패키지 제외
})
include를 안 쓰면 node_modules 전체를 스캔합니다. 외부 패키지가 skills를 가지고 있는 경우 원치 않는 지침이 주입될 수 있으니, 조직 스코프(@my-org/*)로 필터링하는 게 안전합니다.
| 항목 | Git 기반 (npx skills add) | npm 기반 (skills-npm) |
|---|---|---|
| 버전 관리 | 툴과 별도 관리 | 툴과 함께 번들 |
| 설치 방식 | 클론 + 심볼릭 링크 | npm install + 심볼릭 링크 |
| 업데이트 | 수동 재클론 | npm update |
| 팀 공유 | 파일 커밋 또는 재클론 | 패키지 의존성으로 공유 |
| 버전 고정 | 어려움 | lockfile로 재현 가능 |
| 프라이빗 배포 | 제한적 | 프라이빗 레지스트리 활용 가능 |
두 방식은 경쟁 관계가 아닙니다. Git 기반은 npm에 올라오지 않은 커뮤니티 스킬이나 빠른 실험에 여전히 편하고, npm 기반은 팀이 직접 만든 SDK에 지침을 번들링하거나 버전 고정이 중요한 환경에 적합합니다.
몇 가지 트레이드오프가 있습니다.
추가 패키징 작업이 생깁니다. SDK 릴리즈마다 SKILL.md도 챙겨야 합니다. 코드 변경 없이 지침만 업데이트하는 경우라도 버전을 올려야 합니다. 처음엔 번거롭습니다.
토큰 관리는 여전히 필요합니다. skills-npm이 심볼릭 링크를 깔아준다고 해서 에이전트가 알아서 적절히 읽는 건 아닙니다. 로더 설정에 따라 모든 스킬이 한꺼번에 컨텍스트에 들어올 수도 있습니다. 스킬이 많아질수록 메타데이터만 먼저 노출하고 필요한 것만 로드하는 레이지 로딩 전략을 고민해야 합니다. 무지성으로 다 넣으면 토큰만 낭비됩니다.
에이전트마다 지원 방식이 다릅니다. Cursor, Claude Code, Codex 스킬 파일을 읽는 방식이 완전히 동일하지 않습니다. skills-npm.config.ts의 agents 옵션으로 타깃 에이전트를 명시하는 게 좋습니다.
지침도 코드처럼 semver로 관리하면 의도치 않은 변경을 막을 수 있습니다.
production 에이전트 워크플로라면 버전을 고정("1.3.0")하는 게 낫습니다. 범위("^1.3.0")로 쓰면 마이너 업데이트에 지침이 자동으로 바뀌는데, 에이전트가 갑자기 다른 패턴으로 코드를 짜기 시작하면 디버깅이 귀찮아집니다.
skills-npm이 해결하는 건 사실 단순합니다. "AI 지침이 코드랑 같이 버전 관리되면 좋겠다"는 것이죠. npm이 이미 그 인프라를 갖추고 있으니, 거기에 올라타는 겁니다.
아직 현장에서 이 컨벤션을 지원하는 npm 패키지 수가 많지는 않습니다. @slidev/cli, eslint-vitest-rule-tester, @vueuse/skills 등 몇 가지가 있고, 생태계는 만들어지는 중입니다. 직접 쓰는 내부 SDK가 있다면 SKILL.md 하나 추가하고 package.json에 "skills" 한 줄 넣는 것부터 시작해볼 만합니다. 앞으로 npm 패키지에 skills를 넣으며 관리를 해봐야겠습니다.