From c59537d0baa9c62b2237b38cfc9c3c0b6229655e Mon Sep 17 00:00:00 2001 From: yujeong-jeon Date: Wed, 13 May 2026 15:48:45 +0900 Subject: [PATCH 1/4] =?UTF-8?q?=E2=9C=A8=20feat:=20use-naverpaydev-lib=20?= =?UTF-8?q?=ED=94=8C=EB=9F=AC=EA=B7=B8=EC=9D=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @naverpay/* 패키지의 llms.txt를 node_modules에서 읽어 올바른 API 사용을 돕는 스킬. llms.txt 누락 시 .d.ts fallback 지원. --- .../.claude-plugin/plugin.json | 24 +++ plugins/use-naverpaydev-lib/README.md | 41 +++++ .../skills/use-naverpaydev-lib.md | 162 ++++++++++++++++++ 3 files changed, 227 insertions(+) create mode 100644 plugins/use-naverpaydev-lib/.claude-plugin/plugin.json create mode 100644 plugins/use-naverpaydev-lib/README.md create mode 100644 plugins/use-naverpaydev-lib/skills/use-naverpaydev-lib.md diff --git a/plugins/use-naverpaydev-lib/.claude-plugin/plugin.json b/plugins/use-naverpaydev-lib/.claude-plugin/plugin.json new file mode 100644 index 0000000..fd1f3df --- /dev/null +++ b/plugins/use-naverpaydev-lib/.claude-plugin/plugin.json @@ -0,0 +1,24 @@ +{ + "name": "naverpay-use-naverpaydev-lib", + "version": "0.1.0", + "description": "node_modules에서 @naverpay/* 및 @pie/* 패키지의 llms.txt를 읽어 올바른 API 사용법을 컨텍스트에 주입합니다", + "author": { + "name": "NaverPayDev" + }, + "repository": "https://github.com/NaverPayDev/naverpay-plugins", + "keywords": [ + "naverpay", + "claude-plugin", + "claude", + "plugin", + "llms.txt", + "hidash", + "pie" + ], + "skills": [ + { + "name": "use-naverpaydev-lib", + "path": "./skills/use-naverpaydev-lib.md" + } + ] +} diff --git a/plugins/use-naverpaydev-lib/README.md b/plugins/use-naverpaydev-lib/README.md new file mode 100644 index 0000000..fd02465 --- /dev/null +++ b/plugins/use-naverpaydev-lib/README.md @@ -0,0 +1,41 @@ +# use-naverpaydev-lib Plugin + +`@naverpay/*` 및 `@pie/*` 패키지의 `llms.txt`를 **node_modules에서 직접 읽어** 정확한 API 사용법을 컨텍스트에 주입하는 스킬입니다. + +## 설치 + +```bash +/plugin install naverpay-use-naverpaydev-lib@naverpay-plugins +``` + +## 사용법 + +``` +/use-naverpaydev-lib +``` + +스킬 실행 후 Claude는 설치된 `@naverpay/*`, `@pie/*` 패키지의 `llms.txt`를 읽고, 이후 해당 패키지 코드 작성 시 llms.txt에 명시된 API 명세를 기반으로 정확한 함수명과 시그니처를 사용합니다. + +## 지원 패키지 매니저 + +| 패키지 매니저 | node_modules 구조 | symlink 처리 | +| ------------- | ----------------- | ------------ | +| npm | 표준 hoisted | 불필요 | +| bun | 표준 hoisted | 불필요 | +| yarn (hoisted)| 표준 hoisted | 불필요 | +| pnpm | symlink → `.pnpm/`| `find -L` 사용 | +| yarn PnP | `.yarn/unplugged/`| `find -L` 사용 | + +## 동작 방식 + +1. 현재 프로젝트의 패키지 매니저 자동 감지 (락 파일 기반) +2. `node_modules/@naverpay/*` 및 `node_modules/@pie/*`에서 `llms.txt` 탐색 +3. 발견된 모든 `llms.txt` 내용을 읽어 Claude 컨텍스트에 주입 +4. 이후 해당 패키지 관련 코드 작성 시 주입된 API 명세 자동 참조 + +## llms.txt가 포함된 패키지 + +- [`@naverpay/hidash`](https://github.com/NaverPayDev/hidash) — hidash 유틸 라이브러리 +- `@pie/*` — NaverPay 컴포넌트/유틸 패키지 모음 + +llms.txt가 없는 패키지는 조용히 건너뜁니다. diff --git a/plugins/use-naverpaydev-lib/skills/use-naverpaydev-lib.md b/plugins/use-naverpaydev-lib/skills/use-naverpaydev-lib.md new file mode 100644 index 0000000..f1a387c --- /dev/null +++ b/plugins/use-naverpaydev-lib/skills/use-naverpaydev-lib.md @@ -0,0 +1,162 @@ +--- +description: node_modules에서 @naverpay/* 패키지의 API 문서를 읽어 올바른 사용법을 컨텍스트에 주입합니다. llms.txt가 있으면 우선 사용하고, 없으면 .d.ts 타입 정의로 폴백합니다. +allowed-tools: Bash(find:*), Bash(cat:*), Bash(ls:*), Bash(node:*), Read +--- + +# NaverPayDev 라이브러리 사용 가이드 로더 + +설치된 `@naverpay/*` 패키지의 API 문서를 컨텍스트에 주입합니다. + +- **1순위**: `llms.txt` — 패키지 관리자가 작성한 간결한 가이드 +- **폴백**: `.d.ts` 타입 정의 — llms.txt가 없거나 누락된 경우 빌드 산출물에서 직접 추론 + +## 실행 절차 + +### 1. 패키지 매니저 및 node_modules 위치 탐지 + +```bash +# 패키지 매니저 감지 +if [ -f "pnpm-lock.yaml" ]; then + echo "pm=pnpm" +elif [ -f "bun.lockb" ] || [ -f "bun.lock" ]; then + echo "pm=bun" +elif [ -f "yarn.lock" ]; then + if [ -f ".yarnrc.yml" ] && grep -q "nodeLinker: pnp" ".yarnrc.yml" 2>/dev/null; then + echo "pm=yarn-pnp" + else + echo "pm=yarn" + fi +else + echo "pm=npm" +fi + +# node_modules 위치 탐색 (현재 디렉토리에서 상위로) +dir=$(pwd) +nm_path="" +while [ "$dir" != "/" ]; do + if [ -d "$dir/node_modules" ]; then + nm_path="$dir/node_modules" + break + fi + dir=$(dirname "$dir") +done +echo "node_modules=$nm_path" +``` + +### 2. @naverpay/* 패키지 목록 수집 + +```bash +NM="<위에서 탐지한 node_modules 경로>" + +# pnpm: 심볼릭 링크를 추적해야 하므로 -L 필수 +# npm / bun / yarn hoisted: -L 없어도 동작하지만 함께 써도 무방 +find -L "$NM/@naverpay" -maxdepth 1 -mindepth 1 -type d 2>/dev/null +``` + +yarn PnP인 경우: + +```bash +find -L ".yarn/unplugged" -maxdepth 4 -path "*/@naverpay/*/package.json" 2>/dev/null \ + | sed 's|/package.json||' +``` + +### 3. 각 패키지별 API 문서 로드 (llms.txt → .d.ts 폴백) + +수집된 패키지 경로마다 아래 순서로 시도합니다. + +#### 3-1. llms.txt 시도 + +```bash +PKG_PATH="<패키지 경로>" # 예: /path/to/node_modules/@naverpay/hidash + +if [ -f "$PKG_PATH/llms.txt" ]; then + cat "$PKG_PATH/llms.txt" +fi +``` + +llms.txt가 있으면 내용을 그대로 컨텍스트에 주입하고 해당 패키지는 완료. + +#### 3-2. llms.txt 없을 때: .d.ts 폴백 + +```bash +# package.json의 exports 맵에서 공개 타입 파일 목록 추출 +node -e " +const fs = require('fs'); +const pkg = JSON.parse(fs.readFileSync('$PKG_PATH/package.json', 'utf8')); +const exp = pkg.exports || {}; +const seen = new Set(); // 중복 방지 (같은 함수의 .d.ts / .d.mts) +const typeFiles = []; + +// exports 맵 순회: .d.ts 우선, 없으면 .d.mts +for (const [key, val] of Object.entries(exp)) { + if (!key.startsWith('.')) continue; + const candidates = typeof val === 'object' ? [ + val.types, + val.require?.types, + val.import?.types, + ] : [val]; + for (const t of candidates) { + if (!t) continue; + const rel = t.replace(/^\.\//, ''); + const base = rel.replace(/\.d\.m?ts$/, ''); // 함수명 기준 중복 제거 + if (!seen.has(base) && (rel.endsWith('.d.ts') || rel.endsWith('.d.mts'))) { + seen.add(base); + typeFiles.push(rel); + } + } +} + +// exports 맵 없으면 루트 types/typings 필드 사용 +if (typeFiles.length === 0) { + const root = pkg.types || pkg.typings; + if (root) typeFiles.push(root.replace(/^\.\//, '')); +} + +// 그마저도 없으면 index.d.ts 시도 +if (typeFiles.length === 0) typeFiles.push('index.d.ts'); + +console.log(typeFiles.join('\n')); +" +``` + +출력된 파일 목록을 읽어 컨텍스트에 주입: + +```bash +# 위에서 나온 파일들을 순서대로 읽기 (존재하는 것만) +# 파일 수가 많은 패키지(함수별 subpath 구조)도 각 파일이 수 줄이므로 전체 읽기 +for rel_path in <추출된 파일 목록>; do + abs="$PKG_PATH/$rel_path" + [ -f "$abs" ] && echo "// $rel_path" && cat "$abs" +done +``` + +### 4. 결과 출력 + +각 패키지 처리 후 요약: + +``` +✅ NaverPayDev 라이브러리 API 문서 로드 완료 + +로드된 패키지: +- @naverpay/hidash → llms.txt (가이드 문서) +- @naverpay/utils → .d.ts 타입 정의 (llms.txt 없음 — 폴백) + +위 패키지 사용 시 로드된 API 명세에 따라 정확한 함수명·시그니처를 사용합니다. +``` + +`@naverpay/*` 패키지가 아예 없는 경우: + +```txt +ℹ️ node_modules에서 @naverpay/* 패키지를 찾지 못했습니다. +의존성이 설치되어 있는지 확인하세요. +``` + +## 규칙 + +- `@naverpay/*` 스코프만 탐색 (다른 스코프 하드코딩 금지) +- node_modules에서 직접 읽는다 (GitHub fetch 금지) — 설치된 버전과 정확히 일치해야 함 +- pnpm 환경에서 Glob 도구는 symlink를 추적하지 못하므로 반드시 Bash `find -L`을 사용 +- llms.txt가 있으면 무조건 우선 사용. .d.ts는 llms.txt가 없는 패키지에만 적용 +- .d.ts 폴백 시 exports 맵에 없는 내부 파일(`internal/`, `_*`)은 읽지 않음 +- 읽어온 API 명세는 현재 대화 컨텍스트에 유지하며, 해당 패키지 코드 작성 시 반드시 참조 +- llms.txt 또는 .d.ts 내용을 그대로 신뢰하며 추측으로 API를 변형하지 않음 From 09c668bf00755a5dfd5abb2c6b842f3fa5d162d9 Mon Sep 17 00:00:00 2001 From: yujeong-jeon Date: Wed, 13 May 2026 15:48:48 +0900 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=94=A7=20ci:=20=ED=94=8C=EB=9F=AC?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20=EA=B5=AC=EC=A1=B0=20=EA=B2=80=EC=A6=9D=20?= =?UTF-8?q?=EC=9B=8C=ED=81=AC=ED=94=8C=EB=A1=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR에서 plugin.json 스키마, 필수 파일 존재 여부, skill/agent/command 참조 유효성을 자동 검사 --- .github/workflows/validate-plugin.yml | 91 +++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 .github/workflows/validate-plugin.yml diff --git a/.github/workflows/validate-plugin.yml b/.github/workflows/validate-plugin.yml new file mode 100644 index 0000000..c460a02 --- /dev/null +++ b/.github/workflows/validate-plugin.yml @@ -0,0 +1,91 @@ +name: Plugin Validator + +on: + pull_request: + types: [opened, synchronize, reopened] + paths: + - 'plugins/**' + +jobs: + validate: + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Validate plugin structure with Claude + uses: anthropics/claude-code-action@v1 + with: + anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + direct_prompt: | + 이 PR에서 `plugins/` 디렉토리 아래 변경된 플러그인의 구조와 문서를 검사하고 결과를 PR 코멘트로 남겨줘. + + ## 검사 방법 + + 1. 변경된 플러그인 디렉토리 파악 + ```bash + git diff --name-only origin/${{ github.base_ref }}...HEAD -- plugins/ + ``` + 경로에서 `plugins//` 수준의 고유 플러그인 목록을 추출해. + + 2. 각 플러그인에 대해 아래 항목을 순서대로 검사해. + + ## 검사 항목 + + ### 필수 파일 존재 여부 + - [ ] `.claude-plugin/plugin.json` 존재 + - [ ] `README.md` 존재 + - [ ] `plugin.json`에 선언된 skill/agent/command 파일이 실제로 존재 + + ### plugin.json 스키마 + `.claude-plugin/plugin.json`을 읽어 아래 필드가 모두 있는지 확인: + - `name` (문자열, 필수) + - `description` (문자열, 필수) + - `author.name` (필수) + - `repository` (필수, `https://github.com/NaverPayDev/naverpay-plugins` 포함) + - `skills` / `agents` / `commands` 중 하나 이상 선언 + + ### 스킬/에이전트/커맨드 파일 frontmatter + 선언된 각 파일(`.md`)을 읽어: + - `description` 필드 존재 + - `allowed-tools` 또는 `tools` 필드 존재 (선택이지만 누락 시 주의 표시) + - YAML frontmatter가 `---`로 올바르게 열리고 닫히는지 + + ### README 품질 (참고용, 실패 처리 안 함) + - 설치 방법 (`/plugin install`) 언급 여부 + - 사용법 예시 포함 여부 + + ## 코멘트 형식 + + 검사 결과를 아래 형식으로 PR에 코멘트를 달아줘. 반드시 한국어로 작성. + + ```markdown + ## 🔍 플러그인 구조 검사 결과 + + ### `` + + | 항목 | 결과 | 비고 | + |------|------|------| + | `.claude-plugin/plugin.json` | ✅ / ❌ | | + | `README.md` | ✅ / ❌ | | + | 선언된 파일 존재 | ✅ / ❌ | | + | plugin.json 필수 필드 | ✅ / ❌ | 누락 필드 목록 | + | frontmatter 유효성 | ✅ / ❌ | | + + + **수정 필요:** + - ... + + + **모든 검사 통과** — 플러그인 구조가 올바릅니다. + ``` + + `plugins/` 외 파일만 변경된 경우(예: `examples/`, 루트 파일)에는 코멘트 없이 조용히 종료해. + claude_args: | + --allowedTools "Bash(git diff:*),Bash(git log:*),Bash(cat:*),Bash(ls:*),Read,Glob,Grep" + --max-turns 5 From 09c53345a01234b3b5c087f57da954d467babca5 Mon Sep 17 00:00:00 2001 From: yujeong-jeon Date: Wed, 13 May 2026 15:51:13 +0900 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=94=A7=20fix:=20direct=5Fprompt=20?= =?UTF-8?q?=E2=86=92=20prompt=20(claude-code-action=20v1=20=ED=98=B8?= =?UTF-8?q?=ED=99=98)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/validate-plugin.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/validate-plugin.yml b/.github/workflows/validate-plugin.yml index c460a02..e800293 100644 --- a/.github/workflows/validate-plugin.yml +++ b/.github/workflows/validate-plugin.yml @@ -22,7 +22,7 @@ jobs: uses: anthropics/claude-code-action@v1 with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} - direct_prompt: | + prompt: | 이 PR에서 `plugins/` 디렉토리 아래 변경된 플러그인의 구조와 문서를 검사하고 결과를 PR 코멘트로 남겨줘. ## 검사 방법 From 2988930070eea8c57b823aa0b1b2455375d40068 Mon Sep 17 00:00:00 2001 From: yujeong-jeon Date: Wed, 13 May 2026 15:52:28 +0900 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=94=A7=20fix:=20id-token=20write=20?= =?UTF-8?q?=EA=B6=8C=ED=95=9C=20=EC=B6=94=EA=B0=80=20(OIDC=20=EC=9D=B8?= =?UTF-8?q?=EC=A6=9D)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/validate-plugin.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/validate-plugin.yml b/.github/workflows/validate-plugin.yml index e800293..50d0442 100644 --- a/.github/workflows/validate-plugin.yml +++ b/.github/workflows/validate-plugin.yml @@ -12,6 +12,7 @@ jobs: permissions: contents: read pull-requests: write + id-token: write steps: - name: Checkout repository uses: actions/checkout@v4