oh-my-agent 1.0.2 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of oh-my-agent might be problematic. Click here for more details.

Files changed (28) hide show
  1. package/README.md +48 -57
  2. package/dist/application/DiagnoseProjectUseCase.d.ts +6 -3
  3. package/dist/application/DiagnoseProjectUseCase.d.ts.map +1 -1
  4. package/dist/application/DiagnoseProjectUseCase.js +23 -9
  5. package/dist/application/DiagnoseProjectUseCase.js.map +1 -1
  6. package/dist/application/SetupSkillsUseCase.d.ts +4 -1
  7. package/dist/application/SetupSkillsUseCase.d.ts.map +1 -1
  8. package/dist/application/SetupSkillsUseCase.js +37 -41
  9. package/dist/application/SetupSkillsUseCase.js.map +1 -1
  10. package/dist/index.js +24 -21
  11. package/dist/index.js.map +1 -1
  12. package/dist/infrastructure/skills/SkillsScorer.d.ts +17 -0
  13. package/dist/infrastructure/skills/SkillsScorer.d.ts.map +1 -0
  14. package/dist/infrastructure/skills/SkillsScorer.js +63 -0
  15. package/dist/infrastructure/skills/SkillsScorer.js.map +1 -0
  16. package/dist/infrastructure/skills/SkillsShClient.d.ts +24 -0
  17. package/dist/infrastructure/skills/SkillsShClient.d.ts.map +1 -0
  18. package/dist/infrastructure/skills/SkillsShClient.js +65 -0
  19. package/dist/infrastructure/skills/SkillsShClient.js.map +1 -0
  20. package/dist/infrastructure/skills/StackKeywords.d.ts +13 -0
  21. package/dist/infrastructure/skills/StackKeywords.d.ts.map +1 -0
  22. package/dist/infrastructure/skills/StackKeywords.js +43 -0
  23. package/dist/infrastructure/skills/StackKeywords.js.map +1 -0
  24. package/package.json +1 -1
  25. package/dist/infrastructure/skills/SkillsRegistry.d.ts +0 -15
  26. package/dist/infrastructure/skills/SkillsRegistry.d.ts.map +0 -1
  27. package/dist/infrastructure/skills/SkillsRegistry.js +0 -102
  28. package/dist/infrastructure/skills/SkillsRegistry.js.map +0 -1
package/README.md CHANGED
@@ -1,18 +1,19 @@
1
1
  # oh-my-agent
2
2
 
3
- > AI 스킬을 자동으로 진단·배포·관리하는 MCP 서버
3
+ > AI 스킬을 자동으로 진단·설치·관리하는 MCP 서버
4
4
 
5
- 프로젝트의 기술 스택을 분석해 적합한 AI 스킬을 추천하고, `~/oh-my-agent-library`에서 `.claude/skills/`로 심볼릭 링크를 생성해 Claude Code에서 즉시 활용할 있게 합니다.
5
+ 프로젝트의 기술 스택을 분석해 [skills.sh](https://skills.sh) 에서 최적의 스킬을 찾고 설치합니다.
6
+ 설치 수·배포자 신뢰도·보안을 종합한 점수제로 가장 적합한 스킬을 선택합니다.
6
7
 
7
- ## 설치 및 사용
8
+ ## 설치
8
9
 
9
- ### Claude Code 전역 등록
10
+ ### Claude Code 전역 등록
10
11
 
11
12
  ```bash
12
13
  claude mcp add oh-my-agent npx -y oh-my-agent
13
14
  ```
14
15
 
15
- ### 또는 프로젝트별 `.mcp.json` 설정
16
+ ### 또는 프로젝트별 `.mcp.json`
16
17
 
17
18
  ```json
18
19
  {
@@ -25,89 +26,79 @@ claude mcp add oh-my-agent npx -y oh-my-agent
25
26
  }
26
27
  ```
27
28
 
28
- ## 라이브러리 구조 준비
29
+ ## 사용법
29
30
 
30
- 스킬 파일(.md)을 아래 구조로 배치합니다:
31
+ MCP 등록 Claude Code에서 자연어로 요청합니다.
32
+
33
+ ### 스킬 자동 설치 (가장 자주 씀)
31
34
 
32
35
  ```
33
- ~/oh-my-agent-library/
34
- ├── frontend/ ← next-best-practices.md, vercel-react-best-practices.md ...
35
- ├── testing/ ← vitest-practices.md, jest-practices.md ...
36
- ├── security/ ← jwt-auth-practices.md ...
37
- ├── backend/ ← prisma-best-practices.md, express-api-patterns.md ...
38
- ├── devops/ ← docker-deployment.md ...
39
- └── manager/ ← agile-practices.md ...
36
+ 이 프로젝트에 맞는 AI 스킬 자동으로 설치해줘.
40
37
  ```
41
38
 
42
- ## 제공 도구 (MCP Tools)
39
+ 1. `package.json` 분석 기술 스택 감지
40
+ 2. skills.sh에서 각 스택별 스킬 검색
41
+ 3. 인기도·신뢰도·보안 점수화 → 최고 스킬 선택
42
+ 4. `npx skills add` 로 `.claude/skills/` 에 설치
43
+ 5. `CLAUDE.md` 자동 동기화
43
44
 
44
- ### `diagnose_project`
45
+ ---
45
46
 
46
- 프로젝트의 `package.json`을 분석해 기술 스택을 감지하고 추천 스킬 목록을 반환합니다.
47
+ ### 진단만 (설치 없이 미리보기)
47
48
 
48
49
  ```
49
- 입력: projectPath?, includeDevDeps?
50
- 출력: { detectedStack, recommendedSkills[], summary }
50
+ 프로젝트 기술 스택 분석하고 어떤 스킬 추천하는지 보여줘.
51
51
  ```
52
52
 
53
- ### `setup_skills`
53
+ ---
54
54
 
55
- 라이브러리의 스킬을 프로젝트 `.claude/skills/`에 심볼릭 링크로 배포하고 `CLAUDE.md`를 업데이트합니다.
55
+ ### 특정 스킬 지정 설치
56
56
 
57
57
  ```
58
- 입력: projectPath, skills[{domain, skillName}], updateClaudeMd?, dryRun?
59
- 출력: { results[], claudeMdUpdated, summary }
58
+ vercel-labs/next-skills@next-best-practices 스킬 설치해줘.
60
59
  ```
61
60
 
62
- ### `organize_skills`
61
+ ---
63
62
 
64
- 라이브러리 스킬 파일을 분석해 오분류된 스킬을 감지하고 자동으로 올바른 도메인으로 이동합니다.
63
+ ### 키워드로 스킬 탐색
65
64
 
66
65
  ```
67
- 입력: libraryPath?, autoFix?, targetDomain?
68
- 출력: { misplaced[], correctlyPlaced, autoFixed, summary }
66
+ prisma 관련 스킬 찾아줘.
69
67
  ```
70
68
 
71
- ### `sync_claude_md`
69
+ ---
72
70
 
73
- `.claude/skills/`를 스캔해 깨진 링크를 감지하고 `CLAUDE.md`의 스킬 섹션을 동기화합니다.
71
+ ### CLAUDE.md 재동기화
74
72
 
75
73
  ```
76
- 입력: projectPath, createIfMissing?, templateStyle?
77
- 출력: { action, installedSkills[], addedToMd[], removedFromMd[], brokenLinks[] }
74
+ .claude/skills/ 폴더 기준으로 CLAUDE.md 다시 sync해줘.
78
75
  ```
79
76
 
80
- ## CLAUDE.md 자동 관리
77
+ ## 제공 도구 (MCP Tools)
81
78
 
82
- `sync_claude_md` 실행 아래 마커 구간이 자동으로 생성·업데이트됩니다:
79
+ | 도구 | 설명 |
80
+ |------|------|
81
+ | `diagnose_project` | 기술 스택 분석 + skills.sh 검색 + 점수화된 추천 목록 반환 |
82
+ | `setup_project` | 진단 후 최고 점수 스킬 자동 설치 + CLAUDE.md 동기화 |
83
+ | `find_skills` | 키워드로 skills.sh 검색 |
84
+ | `sync_claude_md` | `.claude/skills/` 실제 파일 기준 CLAUDE.md 동기화 |
83
85
 
84
- ```markdown
85
- <!-- oh-my-agent:skills:start -->
86
- ## Active Skills
86
+ ## 점수 체계
87
87
 
88
- - **frontend/next-best-practices** Next.js 15 모범 사례
89
- - **testing/vitest-practices** — Vitest 단위 테스트
88
+ skills.sh에서 검색된 후보 스킬을 아래 기준으로 점수화합니다.
90
89
 
91
- > 섹션은 oh-my-agent가 자동 관리합니다.
92
- > 마지막 동기화: 2026-02-23T00:00:00.000Z
93
- <!-- oh-my-agent:skills:end -->
94
- ```
90
+ | 항목 | 가중치 | 기준 |
91
+ |------|--------|------|
92
+ | 인기도 | 50% | skills.sh 설치 수 |
93
+ | 배포자 신뢰도 | 35% | 공식 조직·검증 개발자 우선 (`anthropics`, `vercel-labs`, `microsoft` 등) |
94
+ | 보안 | 15% | 신뢰도 대리 지표 |
95
+
96
+ ## 감지 가능한 기술 스택
95
97
 
96
- ## 지원 기술 스택
97
-
98
- | 패키지 | 도메인 | 스킬 |
99
- |--------|--------|------|
100
- | next, nextjs | frontend | next-best-practices |
101
- | react | frontend | vercel-react-best-practices |
102
- | react-native | frontend | vercel-react-native-skills |
103
- | vitest | testing | vitest-practices |
104
- | jest | testing | jest-practices |
105
- | cypress | testing | e2e-testing |
106
- | playwright | testing | playwright-testing |
107
- | prisma | backend | prisma-best-practices |
108
- | express | backend | express-api-patterns |
109
- | jsonwebtoken, jose | security | jwt-auth-practices |
110
- | docker | devops | docker-deployment |
98
+ Next.js · React · React Native · Vue · Nuxt · Svelte · Angular
99
+ Vitest · Jest · Playwright · Cypress
100
+ Prisma · Express · Fastify · tRPC · GraphQL
101
+ Docker · Kubernetes
111
102
 
112
103
  ## 요구사항
113
104
 
@@ -1,19 +1,22 @@
1
- import { type SkillRef } from "../infrastructure/skills/SkillsRegistry.js";
1
+ import { type ScoredSkill } from "../infrastructure/skills/SkillsScorer.js";
2
+ import { META_SKILL_REFS } from "../infrastructure/skills/StackKeywords.js";
2
3
  export interface DiagnoseInput {
3
4
  projectPath?: string;
4
5
  includeDevDeps?: boolean;
5
6
  }
6
- export interface RecommendedSkill extends SkillRef {
7
+ export interface RecommendedSkill extends ScoredSkill {
7
8
  trigger: string;
8
9
  }
9
10
  export interface DiagnoseOutput {
10
11
  detectedStack: string[];
11
12
  recommendedSkills: RecommendedSkill[];
12
- metaSkills: SkillRef[];
13
+ metaSkills: typeof META_SKILL_REFS;
13
14
  summary: string;
14
15
  }
15
16
  export declare class DiagnoseProjectUseCase {
16
17
  private analyzer;
18
+ private client;
19
+ private scorer;
17
20
  execute(input: DiagnoseInput): Promise<DiagnoseOutput>;
18
21
  }
19
22
  //# sourceMappingURL=DiagnoseProjectUseCase.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DiagnoseProjectUseCase.d.ts","sourceRoot":"","sources":["../../src/application/DiagnoseProjectUseCase.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,QAAQ,EACd,MAAM,4CAA4C,CAAC;AAEpD,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAiB,SAAQ,QAAQ;IAChD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;IACtC,UAAU,EAAE,QAAQ,EAAE,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,sBAAsB;IACjC,OAAO,CAAC,QAAQ,CAAyB;IAEnC,OAAO,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC;CAiC7D"}
1
+ {"version":3,"file":"DiagnoseProjectUseCase.d.ts","sourceRoot":"","sources":["../../src/application/DiagnoseProjectUseCase.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,0CAA0C,CAAC;AAC1F,OAAO,EAAqB,eAAe,EAAE,MAAM,2CAA2C,CAAC;AAE/F,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACnD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;IACtC,UAAU,EAAE,OAAO,eAAe,CAAC;IACnC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,sBAAsB;IACjC,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,MAAM,CAAsB;IAE9B,OAAO,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC;CA6C7D"}
@@ -1,29 +1,43 @@
1
1
  import { ProjectAnalyzer } from "../domain/project/ProjectAnalyzer.js";
2
- import { STACK_TO_SKILL_REF, META_SKILLS, } from "../infrastructure/skills/SkillsRegistry.js";
2
+ import { SkillsShClient } from "../infrastructure/skills/SkillsShClient.js";
3
+ import { SkillsScorer } from "../infrastructure/skills/SkillsScorer.js";
4
+ import { STACK_TO_KEYWORDS, META_SKILL_REFS } from "../infrastructure/skills/StackKeywords.js";
3
5
  export class DiagnoseProjectUseCase {
4
6
  analyzer = new ProjectAnalyzer();
7
+ client = new SkillsShClient();
8
+ scorer = new SkillsScorer();
5
9
  async execute(input) {
6
10
  const projectPath = input.projectPath ?? process.cwd();
7
11
  const includeDevDeps = input.includeDevDeps ?? true;
8
12
  const project = await this.analyzer.analyze(projectPath, includeDevDeps);
9
- const seen = new Set();
13
+ const seenRefs = new Set();
10
14
  const recommendedSkills = [];
11
- for (const stack of project.detectedStack) {
12
- const skillRef = STACK_TO_SKILL_REF[stack];
13
- if (skillRef && !seen.has(skillRef.ref)) {
14
- seen.add(skillRef.ref);
15
- recommendedSkills.push({ ...skillRef, trigger: stack });
15
+ // 스택에 대해 병렬로 skills.sh 검색 + 점수화
16
+ const searchTasks = project.detectedStack.map(async (stack) => {
17
+ const keyword = STACK_TO_KEYWORDS[stack] ?? stack;
18
+ const candidates = await this.client.searchSkills(keyword, projectPath);
19
+ const best = this.scorer.pickBest(candidates);
20
+ if (best) {
21
+ return { ...best, trigger: stack };
22
+ }
23
+ return null;
24
+ });
25
+ const results = await Promise.all(searchTasks);
26
+ for (const result of results) {
27
+ if (result && !seenRefs.has(result.ref)) {
28
+ seenRefs.add(result.ref);
29
+ recommendedSkills.push(result);
16
30
  }
17
31
  }
18
32
  const stackStr = project.detectedStack.length > 0
19
33
  ? project.detectedStack.join(", ")
20
34
  : "감지된 스택 없음";
21
35
  const summary = `감지된 스택: ${stackStr} | ` +
22
- `추천 스킬: ${recommendedSkills.length}개 + 메타 스킬 ${META_SKILLS.length}개`;
36
+ `추천 스킬: ${recommendedSkills.length}개 + 메타 스킬 ${META_SKILL_REFS.length}개`;
23
37
  return {
24
38
  detectedStack: project.detectedStack,
25
39
  recommendedSkills,
26
- metaSkills: META_SKILLS,
40
+ metaSkills: META_SKILL_REFS,
27
41
  summary,
28
42
  };
29
43
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DiagnoseProjectUseCase.js","sourceRoot":"","sources":["../../src/application/DiagnoseProjectUseCase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AACvE,OAAO,EACL,kBAAkB,EAClB,WAAW,GAEZ,MAAM,4CAA4C,CAAC;AAkBpD,MAAM,OAAO,sBAAsB;IACzB,QAAQ,GAAG,IAAI,eAAe,EAAE,CAAC;IAEzC,KAAK,CAAC,OAAO,CAAC,KAAoB;QAChC,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QACvD,MAAM,cAAc,GAAG,KAAK,CAAC,cAAc,IAAI,IAAI,CAAC;QAEpD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;QAEzE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,MAAM,iBAAiB,GAAuB,EAAE,CAAC;QAEjD,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;YAC1C,MAAM,QAAQ,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;YAC3C,IAAI,QAAQ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBACxC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;gBACvB,iBAAiB,CAAC,IAAI,CAAC,EAAE,GAAG,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YAC1D,CAAC;QACH,CAAC;QAED,MAAM,QAAQ,GACZ,OAAO,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC;YAC9B,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC;YAClC,CAAC,CAAC,WAAW,CAAC;QAElB,MAAM,OAAO,GACX,WAAW,QAAQ,KAAK;YACxB,UAAU,iBAAiB,CAAC,MAAM,aAAa,WAAW,CAAC,MAAM,GAAG,CAAC;QAEvE,OAAO;YACL,aAAa,EAAE,OAAO,CAAC,aAAa;YACpC,iBAAiB;YACjB,UAAU,EAAE,WAAW;YACvB,OAAO;SACR,CAAC;IACJ,CAAC;CACF"}
1
+ {"version":3,"file":"DiagnoseProjectUseCase.js","sourceRoot":"","sources":["../../src/application/DiagnoseProjectUseCase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,4CAA4C,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAoB,MAAM,0CAA0C,CAAC;AAC1F,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAC;AAkB/F,MAAM,OAAO,sBAAsB;IACzB,QAAQ,GAAG,IAAI,eAAe,EAAE,CAAC;IACjC,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;IAC9B,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;IAEpC,KAAK,CAAC,OAAO,CAAC,KAAoB;QAChC,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QACvD,MAAM,cAAc,GAAG,KAAK,CAAC,cAAc,IAAI,IAAI,CAAC;QAEpD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;QAEzE,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;QACnC,MAAM,iBAAiB,GAAuB,EAAE,CAAC;QAEjD,kCAAkC;QAClC,MAAM,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YAC5D,MAAM,OAAO,GAAG,iBAAiB,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC;YAClD,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;YACxE,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;YAC9C,IAAI,IAAI,EAAE,CAAC;gBACT,OAAO,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YACrC,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAE/C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,IAAI,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;gBACxC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACzB,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;QAED,MAAM,QAAQ,GACZ,OAAO,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC;YAC9B,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC;YAClC,CAAC,CAAC,WAAW,CAAC;QAElB,MAAM,OAAO,GACX,WAAW,QAAQ,KAAK;YACxB,UAAU,iBAAiB,CAAC,MAAM,aAAa,eAAe,CAAC,MAAM,GAAG,CAAC;QAE3E,OAAO;YACL,aAAa,EAAE,OAAO,CAAC,aAAa;YACpC,iBAAiB;YACjB,UAAU,EAAE,eAAe;YAC3B,OAAO;SACR,CAAC;IACJ,CAAC;CACF"}
@@ -4,7 +4,8 @@ export interface SetupSkillsInput {
4
4
  /** 특정 스킬만 지정. 미입력 시 자동 진단 후 설치 */
5
5
  skillRefs?: string[];
6
6
  includeMetaSkills?: boolean;
7
- updateClaudeMd?: boolean;
7
+ /** CLAUDE.md 동기화 여부 (기본값: true). 실제 설치 파일 기준으로 동기화합니다. */
8
+ syncClaudeMd?: boolean;
8
9
  dryRun?: boolean;
9
10
  }
10
11
  export interface SetupSkillsOutput {
@@ -15,6 +16,8 @@ export interface SetupSkillsOutput {
15
16
  export declare class SetupSkillsUseCase {
16
17
  private runner;
17
18
  private analyzer;
19
+ private client;
20
+ private scorer;
18
21
  execute(input: SetupSkillsInput): Promise<SetupSkillsOutput>;
19
22
  }
20
23
  //# sourceMappingURL=SetupSkillsUseCase.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SetupSkillsUseCase.d.ts","sourceRoot":"","sources":["../../src/application/SetupSkillsUseCase.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6CAA6C,CAAC;AAEtF,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,kCAAkC;IAClC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,eAAe,EAAE,OAAO,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,QAAQ,CAAyB;IAEnC,OAAO,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC;CA2FnE"}
1
+ {"version":3,"file":"SetupSkillsUseCase.d.ts","sourceRoot":"","sources":["../../src/application/SetupSkillsUseCase.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6CAA6C,CAAC;AAEtF,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,kCAAkC;IAClC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,0DAA0D;IAC1D,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,eAAe,EAAE,OAAO,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,MAAM,CAAsB;IAE9B,OAAO,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAgFnE"}
@@ -1,80 +1,76 @@
1
1
  import { ProjectAnalyzer } from "../domain/project/ProjectAnalyzer.js";
2
2
  import { SkillsCliRunner } from "../infrastructure/skills/SkillsCliRunner.js";
3
- import { ClaudeMdUpdater } from "../infrastructure/fs/ClaudeMdUpdater.js";
4
- import { STACK_TO_SKILL_REF, META_SKILLS, } from "../infrastructure/skills/SkillsRegistry.js";
3
+ import { SkillsShClient } from "../infrastructure/skills/SkillsShClient.js";
4
+ import { SkillsScorer } from "../infrastructure/skills/SkillsScorer.js";
5
+ import { STACK_TO_KEYWORDS, META_SKILL_REFS } from "../infrastructure/skills/StackKeywords.js";
6
+ import { SyncClaudeMdUseCase } from "./SyncClaudeMdUseCase.js";
5
7
  export class SetupSkillsUseCase {
6
8
  runner = new SkillsCliRunner();
7
9
  analyzer = new ProjectAnalyzer();
10
+ client = new SkillsShClient();
11
+ scorer = new SkillsScorer();
8
12
  async execute(input) {
9
- const { projectPath, skillRefs, includeMetaSkills = true, updateClaudeMd = true, dryRun = false, } = input;
10
- // 설치할 스킬 레퍼런스 결정
13
+ const { projectPath, skillRefs, includeMetaSkills = true, syncClaudeMd = true, dryRun = false, } = input;
14
+ // 설치할 ref 목록 결정
11
15
  let refsToInstall = [];
12
16
  if (skillRefs && skillRefs.length > 0) {
13
17
  // 명시적으로 지정된 스킬
14
- refsToInstall = skillRefs.map((ref) => ({
15
- ref,
16
- domain: "custom",
17
- description: ref,
18
- }));
18
+ refsToInstall = skillRefs;
19
19
  }
20
20
  else {
21
- // 자동 진단으로 추천 스킬 결정
21
+ // 자동 진단: 기술 스택 감지 → skills.sh 검색 → 점수화 → 최고 선택
22
22
  const project = await this.analyzer.analyze(projectPath, true);
23
+ const searchTasks = project.detectedStack.map(async (stack) => {
24
+ const keyword = STACK_TO_KEYWORDS[stack] ?? stack;
25
+ const candidates = await this.client.searchSkills(keyword, projectPath);
26
+ const best = this.scorer.pickBest(candidates);
27
+ return best?.ref ?? null;
28
+ });
29
+ const bestRefs = await Promise.all(searchTasks);
23
30
  const seen = new Set();
24
- for (const stack of project.detectedStack) {
25
- const skillRef = STACK_TO_SKILL_REF[stack];
26
- if (skillRef && !seen.has(skillRef.ref)) {
27
- seen.add(skillRef.ref);
28
- refsToInstall.push(skillRef);
31
+ for (const ref of bestRefs) {
32
+ if (ref && !seen.has(ref)) {
33
+ seen.add(ref);
34
+ refsToInstall.push(ref);
29
35
  }
30
36
  }
31
37
  }
32
38
  // 메타 스킬 추가
33
39
  if (includeMetaSkills) {
34
- for (const meta of META_SKILLS) {
35
- if (!refsToInstall.some((r) => r.ref === meta.ref)) {
36
- refsToInstall.push(meta);
40
+ for (const meta of META_SKILL_REFS) {
41
+ if (!refsToInstall.includes(meta.ref)) {
42
+ refsToInstall.push(meta.ref);
37
43
  }
38
44
  }
39
45
  }
40
46
  if (dryRun) {
41
47
  return {
42
- results: refsToInstall.map((r) => ({
43
- ref: r.ref,
48
+ results: refsToInstall.map((ref) => ({
49
+ ref,
44
50
  success: true,
45
51
  output: "[dry-run] 실제 설치 없음",
46
52
  })),
47
53
  claudeMdUpdated: false,
48
- summary: `[dry-run] ${refsToInstall.length}개 스킬 설치 예정\n${refsToInstall.map((r) => ` - ${r.ref}`).join("\n")}`,
54
+ summary: `[dry-run] ${refsToInstall.length}개 스킬 설치 예정\n${refsToInstall.map((r) => ` - ${r}`).join("\n")}`,
49
55
  };
50
56
  }
51
57
  // 실제 설치 (npx skills add)
52
- const results = await this.runner.installMany(refsToInstall.map((r) => r.ref), projectPath);
53
- // CLAUDE.md 업데이트
58
+ const results = await this.runner.installMany(refsToInstall, projectPath);
59
+ // CLAUDE.md 동기화: 실제 설치된 파일 기준으로 sync
60
+ // (하드코딩 레지스트리 대신 실제 .claude/skills/ 파일을 읽어 동기화)
54
61
  let claudeMdUpdated = false;
55
- if (updateClaudeMd) {
56
- const successful = results
57
- .filter((r) => r.success)
58
- .map((r) => {
59
- const found = refsToInstall.find((s) => s.ref === r.ref);
60
- const parts = r.ref.split("@");
61
- const skillName = parts[1] ?? r.ref;
62
- return {
63
- domain: found?.domain ?? "unknown",
64
- skillName,
65
- description: found?.description,
66
- };
62
+ if (syncClaudeMd && results.some((r) => r.success)) {
63
+ const syncUseCase = new SyncClaudeMdUseCase();
64
+ const syncResult = await syncUseCase.execute({
65
+ projectPath,
66
+ createIfMissing: true,
67
67
  });
68
- if (successful.length > 0) {
69
- const updater = new ClaudeMdUpdater(projectPath);
70
- const updateResult = await updater.update(successful, true);
71
- claudeMdUpdated = updateResult.action !== "no_change";
72
- }
68
+ claudeMdUpdated = syncResult.action !== "no_change";
73
69
  }
74
70
  const successCount = results.filter((r) => r.success).length;
75
71
  const failCount = results.filter((r) => !r.success).length;
76
72
  const summary = `총 ${results.length}개 스킬 설치 시도 (성공: ${successCount}, 실패: ${failCount})` +
77
- (claudeMdUpdated ? " | CLAUDE.md 업데이트됨" : "");
73
+ (claudeMdUpdated ? " | CLAUDE.md 동기화됨" : "");
78
74
  return { results, claudeMdUpdated, summary };
79
75
  }
80
76
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SetupSkillsUseCase.js","sourceRoot":"","sources":["../../src/application/SetupSkillsUseCase.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SetupSkillsUseCase.js","sourceRoot":"","sources":["../../src/application/SetupSkillsUseCase.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -5,14 +5,15 @@ import { z } from "zod";
5
5
  import { DiagnoseProjectUseCase } from "./application/DiagnoseProjectUseCase.js";
6
6
  import { SetupSkillsUseCase } from "./application/SetupSkillsUseCase.js";
7
7
  import { SyncClaudeMdUseCase } from "./application/SyncClaudeMdUseCase.js";
8
- import { SkillsCliRunner } from "./infrastructure/skills/SkillsCliRunner.js";
8
+ import { SkillsShClient } from "./infrastructure/skills/SkillsShClient.js";
9
+ import { SkillsScorer } from "./infrastructure/skills/SkillsScorer.js";
9
10
  const server = new McpServer({
10
11
  name: "oh-my-agent",
11
12
  version: "1.0.0",
12
13
  });
13
14
  // ─── diagnose_project ────────────────────────────────────────────────────────
14
- server.tool("diagnose_project", `프로젝트의 package.json을 분석해 기술 스택을 감지하고 skills.sh 기반 추천 스킬 목록을 반환합니다.
15
- setup_project를 호출하기 전에 먼저 실행해 어떤 스킬이 설치될지 미리 확인할 수 있습니다.`, {
15
+ server.tool("diagnose_project", `프로젝트의 기술 스택을 감지하고 설치 가능한 추천 스킬 목록을 반환합니다.
16
+ 스킬을 실제로 설치하려면 setup_project 도구를 사용하세요.`, {
16
17
  projectPath: z
17
18
  .string()
18
19
  .optional()
@@ -29,33 +30,33 @@ setup_project를 호출하기 전에 먼저 실행해 어떤 스킬이 설치될
29
30
  };
30
31
  });
31
32
  // ─── setup_project ───────────────────────────────────────────────────────────
32
- server.tool("setup_project", `프로젝트 기술 스택을 자동으로 진단한 뒤, skills.sh에서 적합한 AI 스킬을 설치합니다.
33
- npx skills add 통해 .claude/skills/ 에 스킬 파일을 생성하고 CLAUDE.md를 업데이트합니다.
34
- find-skills, skill-creator 메타 스킬도 함께 설치됩니다.`, {
33
+ server.tool("setup_project", `프로젝트에 AI 스킬을 자동으로 설치합니다.
34
+ 기술 스택을 감지하고 skills.sh에서 최적의 스킬을 찾아 .claude/skills/ 에 설치한 CLAUDE.md를 업데이트합니다.
35
+ 스킬 설치가 필요할 도구를 직접 호출하세요. 외부 CLI를 별도로 실행하지 마세요.`, {
35
36
  projectPath: z.string().describe("세팅할 프로젝트 경로"),
36
37
  skillRefs: z
37
38
  .array(z.string())
38
39
  .optional()
39
- .describe('직접 지정할 스킬 레퍼런스 목록 (예: ["vercel-labs/next-skills@next-best-practices"]). 미입력 자동 감지.'),
40
+ .describe('설치할 스킬을 직접 지정 (예: ["vercel-labs/next-skills@next-best-practices"]). 생략하면 자동 감지.'),
40
41
  includeMetaSkills: z
41
42
  .boolean()
42
43
  .optional()
43
- .describe("find-skills, skill-creator 메타 스킬 포함 여부 (기본값: true)"),
44
- updateClaudeMd: z
44
+ .describe("메타 스킬(find-skills, skill-creator) 포함 여부 (기본값: true)"),
45
+ syncClaudeMd: z
45
46
  .boolean()
46
47
  .optional()
47
- .describe("CLAUDE.md 자동 업데이트 여부 (기본값: true)"),
48
+ .describe("설치 후 CLAUDE.md 동기화 여부 (기본값: true)"),
48
49
  dryRun: z
49
50
  .boolean()
50
51
  .optional()
51
- .describe("실제 설치 없이 설치될 스킬 목록만 미리보기 (기본값: false)"),
52
- }, async ({ projectPath, skillRefs, includeMetaSkills, updateClaudeMd, dryRun }) => {
52
+ .describe("실제 설치 없이 설치 예정 목록만 반환 (기본값: false)"),
53
+ }, async ({ projectPath, skillRefs, includeMetaSkills, syncClaudeMd, dryRun }) => {
53
54
  const useCase = new SetupSkillsUseCase();
54
55
  const result = await useCase.execute({
55
56
  projectPath,
56
57
  skillRefs,
57
58
  includeMetaSkills,
58
- updateClaudeMd,
59
+ syncClaudeMd,
59
60
  dryRun,
60
61
  });
61
62
  return {
@@ -63,30 +64,32 @@ find-skills, skill-creator 메타 스킬도 함께 설치됩니다.`, {
63
64
  };
64
65
  });
65
66
  // ─── find_skills ─────────────────────────────────────────────────────────────
66
- server.tool("find_skills", `skills.sh에서 특정 키워드로 스킬을 검색합니다.
67
- 유저가 특정 기능이나 기술에 맞는 스킬을 찾고 싶을 사용합니다.`, {
68
- query: z.string().describe("검색할 키워드 (예: 'nextjs', 'testing', 'docker')"),
67
+ server.tool("find_skills", `키워드로 skills.sh에서 스킬을 검색하고 점수화된 후보 목록을 반환합니다.
68
+ 검색 결과를 보고 설치하려면 setup_project 도구에 skillRefs를 전달하세요. CLI를 직접 실행하지 마세요.`, {
69
+ query: z.string().describe("검색 키워드 (예: 'nextjs', 'testing', 'docker')"),
69
70
  projectPath: z
70
71
  .string()
71
72
  .optional()
72
73
  .describe("실행 기준 프로젝트 경로 (기본값: 현재 디렉토리)"),
73
74
  }, async ({ query, projectPath }) => {
74
- const runner = new SkillsCliRunner();
75
+ const client = new SkillsShClient();
76
+ const scorer = new SkillsScorer();
75
77
  const cwd = projectPath ?? process.cwd();
76
78
  try {
77
- const output = await runner.find(query, cwd);
79
+ const candidates = await client.searchSkills(query, cwd);
80
+ const scored = scorer.score(candidates);
78
81
  return {
79
- content: [{ type: "text", text: output }],
82
+ content: [{ type: "text", text: JSON.stringify(scored, null, 2) }],
80
83
  };
81
84
  }
82
85
  catch (err) {
83
86
  return {
84
- content: [{ type: "text", text: `검색 실패: ${String(err)}` }],
87
+ content: [{ type: "text", text: JSON.stringify({ error: String(err) }) }],
85
88
  };
86
89
  }
87
90
  });
88
91
  // ─── sync_claude_md ───────────────────────────────────────────────────────────
89
- server.tool("sync_claude_md", `.claude/skills/ 디렉토리를 스캔해 broken 링크를 감지하고 CLAUDE.md oh-my-agent 마커 섹션을 동기화합니다.`, {
92
+ server.tool("sync_claude_md", `.claude/skills/ 실제 설치된 파일을 기준으로 CLAUDE.md 동기화합니다.`, {
90
93
  projectPath: z.string().describe("대상 프로젝트 경로"),
91
94
  createIfMissing: z
92
95
  .boolean()
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { SkillCandidate } from "./SkillsShClient.js";
2
+ export interface ScoredSkill extends SkillCandidate {
3
+ score: number;
4
+ popularityScore: number;
5
+ credibilityScore: number;
6
+ }
7
+ export declare class SkillsScorer {
8
+ /**
9
+ * 후보 스킬들을 점수화하여 내림차순으로 반환합니다.
10
+ */
11
+ score(candidates: SkillCandidate[]): ScoredSkill[];
12
+ /**
13
+ * 후보 중 최고 점수 스킬 1개를 반환합니다.
14
+ */
15
+ pickBest(candidates: SkillCandidate[]): ScoredSkill | null;
16
+ }
17
+ //# sourceMappingURL=SkillsScorer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SkillsScorer.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/skills/SkillsScorer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,MAAM,WAAW,WAAY,SAAQ,cAAc;IACjD,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAsCD,qBAAa,YAAY;IACvB;;OAEG;IACH,KAAK,CAAC,UAAU,EAAE,cAAc,EAAE,GAAG,WAAW,EAAE;IAuBlD;;OAEG;IACH,QAAQ,CAAC,UAAU,EAAE,cAAc,EAAE,GAAG,WAAW,GAAG,IAAI;CAI3D"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * 배포자(owner) 신뢰도 등급
3
+ *
4
+ * Tier 1 (1.0 ~ 0.9): 공식 조직/기업
5
+ * Tier 2 (0.8 ~ 0.65): 검증된 OSS 개발자
6
+ * Tier 3 (0.5 ~ 0.4): 일반 배포자
7
+ */
8
+ const PUBLISHER_CREDIBILITY = {
9
+ // Tier 1: Official organizations
10
+ anthropics: 1.0,
11
+ "vercel-labs": 1.0,
12
+ microsoft: 0.95,
13
+ clerk: 0.9,
14
+ callstackincubator: 0.9,
15
+ "remotion-dev": 0.88,
16
+ "browser-use": 0.82,
17
+ // Tier 2: Well-known community developers
18
+ antfu: 0.8,
19
+ wshobson: 0.65,
20
+ sickn33: 0.55,
21
+ };
22
+ const DEFAULT_CREDIBILITY = 0.4;
23
+ /**
24
+ * 점수 가중치
25
+ * - 인기도(설치 수): 50%
26
+ * - 배포자 신뢰도: 35%
27
+ * - 보안(신뢰도 대리 지표): 15%
28
+ */
29
+ const WEIGHTS = {
30
+ popularity: 0.5,
31
+ credibility: 0.35,
32
+ security: 0.15,
33
+ };
34
+ export class SkillsScorer {
35
+ /**
36
+ * 후보 스킬들을 점수화하여 내림차순으로 반환합니다.
37
+ */
38
+ score(candidates) {
39
+ if (candidates.length === 0)
40
+ return [];
41
+ const maxInstalls = Math.max(...candidates.map((c) => c.installs), 1);
42
+ return candidates
43
+ .map((candidate) => {
44
+ const popularityScore = candidate.installs / maxInstalls;
45
+ const credibilityScore = PUBLISHER_CREDIBILITY[candidate.owner] ?? DEFAULT_CREDIBILITY;
46
+ // 보안은 현재 신뢰도로 대리 평가 (공식 배포자 = 더 안전)
47
+ const securityScore = credibilityScore;
48
+ const score = popularityScore * WEIGHTS.popularity +
49
+ credibilityScore * WEIGHTS.credibility +
50
+ securityScore * WEIGHTS.security;
51
+ return { ...candidate, score, popularityScore, credibilityScore };
52
+ })
53
+ .sort((a, b) => b.score - a.score);
54
+ }
55
+ /**
56
+ * 후보 중 최고 점수 스킬 1개를 반환합니다.
57
+ */
58
+ pickBest(candidates) {
59
+ const scored = this.score(candidates);
60
+ return scored[0] ?? null;
61
+ }
62
+ }
63
+ //# sourceMappingURL=SkillsScorer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SkillsScorer.js","sourceRoot":"","sources":["../../../src/infrastructure/skills/SkillsScorer.ts"],"names":[],"mappings":"AAQA;;;;;;GAMG;AACH,MAAM,qBAAqB,GAA2B;IACpD,iCAAiC;IACjC,UAAU,EAAE,GAAG;IACf,aAAa,EAAE,GAAG;IAClB,SAAS,EAAE,IAAI;IACf,KAAK,EAAE,GAAG;IACV,kBAAkB,EAAE,GAAG;IACvB,cAAc,EAAE,IAAI;IACpB,aAAa,EAAE,IAAI;IACnB,0CAA0C;IAC1C,KAAK,EAAE,GAAG;IACV,QAAQ,EAAE,IAAI;IACd,OAAO,EAAE,IAAI;CACd,CAAC;AAEF,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEhC;;;;;GAKG;AACH,MAAM,OAAO,GAAG;IACd,UAAU,EAAE,GAAG;IACf,WAAW,EAAE,IAAI;IACjB,QAAQ,EAAE,IAAI;CACN,CAAC;AAEX,MAAM,OAAO,YAAY;IACvB;;OAEG;IACH,KAAK,CAAC,UAA4B;QAChC,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAEvC,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;QAEtE,OAAO,UAAU;aACd,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE;YACjB,MAAM,eAAe,GAAG,SAAS,CAAC,QAAQ,GAAG,WAAW,CAAC;YACzD,MAAM,gBAAgB,GACpB,qBAAqB,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,mBAAmB,CAAC;YAChE,oCAAoC;YACpC,MAAM,aAAa,GAAG,gBAAgB,CAAC;YAEvC,MAAM,KAAK,GACT,eAAe,GAAG,OAAO,CAAC,UAAU;gBACpC,gBAAgB,GAAG,OAAO,CAAC,WAAW;gBACtC,aAAa,GAAG,OAAO,CAAC,QAAQ,CAAC;YAEnC,OAAO,EAAE,GAAG,SAAS,EAAE,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,CAAC;QACpE,CAAC,CAAC;aACD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IACvC,CAAC;IAED;;OAEG;IACH,QAAQ,CAAC,UAA4B;QACnC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACtC,OAAO,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IAC3B,CAAC;CACF"}
@@ -0,0 +1,24 @@
1
+ export interface SkillCandidate {
2
+ ref: string;
3
+ owner: string;
4
+ repo: string;
5
+ skillId: string;
6
+ installs: number;
7
+ url: string;
8
+ }
9
+ /**
10
+ * npx skills find <query> 를 호출하고 결과를 파싱해 후보 스킬 목록을 반환합니다.
11
+ */
12
+ export declare class SkillsShClient {
13
+ searchSkills(query: string, cwd?: string): Promise<SkillCandidate[]>;
14
+ /**
15
+ * npx skills find 출력 파싱
16
+ * 형식:
17
+ * owner/repo@skill-name 5.1K installs
18
+ * └ https://skills.sh/owner/repo/skill-name
19
+ */
20
+ private parseOutput;
21
+ /** "5.1K" → 5100, "2M" → 2000000 */
22
+ private parseInstallCount;
23
+ }
24
+ //# sourceMappingURL=SkillsShClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SkillsShClient.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/skills/SkillsShClient.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,qBAAa,cAAc;IACnB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,SAAgB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAajF;;;;;OAKG;IACH,OAAO,CAAC,WAAW;IAoCnB,oCAAoC;IACpC,OAAO,CAAC,iBAAiB;CAQ1B"}
@@ -0,0 +1,65 @@
1
+ import { execFile } from "child_process";
2
+ import { promisify } from "util";
3
+ const execFileAsync = promisify(execFile);
4
+ /**
5
+ * npx skills find <query> 를 호출하고 결과를 파싱해 후보 스킬 목록을 반환합니다.
6
+ */
7
+ export class SkillsShClient {
8
+ async searchSkills(query, cwd = process.cwd()) {
9
+ try {
10
+ const { stdout } = await execFileAsync("npx", ["--yes", "skills", "find", query], { cwd, timeout: 30_000, env: { ...process.env } });
11
+ return this.parseOutput(stdout);
12
+ }
13
+ catch {
14
+ return [];
15
+ }
16
+ }
17
+ /**
18
+ * npx skills find 출력 파싱
19
+ * 형식:
20
+ * owner/repo@skill-name 5.1K installs
21
+ * └ https://skills.sh/owner/repo/skill-name
22
+ */
23
+ parseOutput(output) {
24
+ const candidates = [];
25
+ const lines = output.split("\n");
26
+ for (const line of lines) {
27
+ // ANSI 이스케이프 코드 제거
28
+ const clean = line.replace(/\x1b\[[0-9;]*m/g, "").trim();
29
+ // "owner/repo@skill-name 5.1K installs" 패턴 매칭
30
+ const match = clean.match(/^([\w.-]+\/[\w.-]+@[\w.-]+)\s+([\d.]+[KMB]?)\s+installs$/i);
31
+ if (!match)
32
+ continue;
33
+ const ref = match[1];
34
+ const installs = this.parseInstallCount(match[2]);
35
+ const atIdx = ref.indexOf("@");
36
+ const sourcePart = ref.slice(0, atIdx);
37
+ const skillId = ref.slice(atIdx + 1);
38
+ const slashIdx = sourcePart.indexOf("/");
39
+ const owner = sourcePart.slice(0, slashIdx);
40
+ const repo = sourcePart.slice(slashIdx + 1);
41
+ candidates.push({
42
+ ref,
43
+ owner,
44
+ repo,
45
+ skillId,
46
+ installs,
47
+ url: `https://skills.sh/${owner}/${repo}/${skillId}`,
48
+ });
49
+ }
50
+ return candidates;
51
+ }
52
+ /** "5.1K" → 5100, "2M" → 2000000 */
53
+ parseInstallCount(str) {
54
+ const num = parseFloat(str);
55
+ const suffix = str.slice(-1).toUpperCase();
56
+ if (suffix === "K")
57
+ return Math.round(num * 1_000);
58
+ if (suffix === "M")
59
+ return Math.round(num * 1_000_000);
60
+ if (suffix === "B")
61
+ return Math.round(num * 1_000_000_000);
62
+ return Math.round(num);
63
+ }
64
+ }
65
+ //# sourceMappingURL=SkillsShClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SkillsShClient.js","sourceRoot":"","sources":["../../../src/infrastructure/skills/SkillsShClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * 기술 스택 → skills.sh 검색 키워드 매핑
3
+ * 각 스택에 대해 npx skills find <keyword> 로 후보 스킬을 검색합니다.
4
+ */
5
+ export declare const STACK_TO_KEYWORDS: Record<string, string>;
6
+ /**
7
+ * 항상 설치하는 메타 스킬 (ref 형식: "owner/repo@skillId")
8
+ */
9
+ export declare const META_SKILL_REFS: Array<{
10
+ ref: string;
11
+ description: string;
12
+ }>;
13
+ //# sourceMappingURL=StackKeywords.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StackKeywords.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/skills/StackKeywords.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CA2BpD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CASvE,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * 기술 스택 → skills.sh 검색 키워드 매핑
3
+ * 각 스택에 대해 npx skills find <keyword> 로 후보 스킬을 검색합니다.
4
+ */
5
+ export const STACK_TO_KEYWORDS = {
6
+ // Frontend
7
+ next: "nextjs",
8
+ nextjs: "nextjs",
9
+ react: "react",
10
+ "react-native": "react-native",
11
+ vue: "vue",
12
+ nuxt: "nuxt",
13
+ svelte: "svelte",
14
+ angular: "angular",
15
+ // Testing
16
+ vitest: "vitest",
17
+ jest: "jest",
18
+ playwright: "playwright",
19
+ cypress: "cypress",
20
+ // Backend
21
+ prisma: "prisma",
22
+ express: "express",
23
+ fastify: "fastify",
24
+ trpc: "trpc",
25
+ graphql: "graphql",
26
+ // DevOps
27
+ docker: "docker",
28
+ kubernetes: "kubernetes",
29
+ };
30
+ /**
31
+ * 항상 설치하는 메타 스킬 (ref 형식: "owner/repo@skillId")
32
+ */
33
+ export const META_SKILL_REFS = [
34
+ {
35
+ ref: "vercel-labs/skills@find-skills",
36
+ description: "skills.sh에서 스킬 탐색 및 설치",
37
+ },
38
+ {
39
+ ref: "anthropics/skills@skill-creator",
40
+ description: "새로운 스킬 생성 가이드",
41
+ },
42
+ ];
43
+ //# sourceMappingURL=StackKeywords.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StackKeywords.js","sourceRoot":"","sources":["../../../src/infrastructure/skills/StackKeywords.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAA2B;IACvD,WAAW;IACX,IAAI,EAAE,QAAQ;IACd,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,OAAO;IACd,cAAc,EAAE,cAAc;IAC9B,GAAG,EAAE,KAAK;IACV,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,SAAS;IAElB,UAAU;IACV,MAAM,EAAE,QAAQ;IAChB,IAAI,EAAE,MAAM;IACZ,UAAU,EAAE,YAAY;IACxB,OAAO,EAAE,SAAS;IAElB,UAAU;IACV,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,SAAS;IAElB,SAAS;IACT,MAAM,EAAE,QAAQ;IAChB,UAAU,EAAE,YAAY;CACzB,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAgD;IAC1E;QACE,GAAG,EAAE,gCAAgC;QACrC,WAAW,EAAE,wBAAwB;KACtC;IACD;QACE,GAAG,EAAE,iCAAiC;QACtC,WAAW,EAAE,eAAe;KAC7B;CACF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oh-my-agent",
3
- "version": "1.0.2",
3
+ "version": "1.1.1",
4
4
  "description": "AI 스킬을 자동으로 진단·배포·관리하는 MCP 서버. 프로젝트 기술 스택을 분석해 적합한 AI 스킬을 추천·설치합니다.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,15 +0,0 @@
1
- /**
2
- * 기술 스택 키워드 → skills.sh 스킬 레퍼런스 매핑
3
- * 형식: "owner/repo@skill-name"
4
- */
5
- export interface SkillRef {
6
- ref: string;
7
- domain: string;
8
- description: string;
9
- }
10
- export declare const STACK_TO_SKILL_REF: Record<string, SkillRef>;
11
- /**
12
- * 항상 설치하는 메타 스킬 (스킬 탐색 및 생성 지원)
13
- */
14
- export declare const META_SKILLS: SkillRef[];
15
- //# sourceMappingURL=SkillsRegistry.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SkillsRegistry.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/skills/SkillsRegistry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAwFvD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW,EAAE,QAAQ,EAWjC,CAAC"}
@@ -1,102 +0,0 @@
1
- export const STACK_TO_SKILL_REF = {
2
- // Frontend
3
- next: {
4
- ref: "vercel-labs/next-skills@next-best-practices",
5
- domain: "frontend",
6
- description: "Next.js 모범 사례",
7
- },
8
- nextjs: {
9
- ref: "vercel-labs/next-skills@next-best-practices",
10
- domain: "frontend",
11
- description: "Next.js 모범 사례",
12
- },
13
- react: {
14
- ref: "vercel-labs/agent-skills@vercel-react-best-practices",
15
- domain: "frontend",
16
- description: "React 모범 사례",
17
- },
18
- "react-native": {
19
- ref: "callstackincubator/agent-skills@react-native-best-practices",
20
- domain: "frontend",
21
- description: "React Native 모범 사례",
22
- },
23
- vue: {
24
- ref: "antfu/skills@vue-testing-best-practices",
25
- domain: "frontend",
26
- description: "Vue 테스트 모범 사례",
27
- },
28
- // Testing
29
- vitest: {
30
- ref: "antfu/skills@vitest",
31
- domain: "testing",
32
- description: "Vitest 단위 테스트",
33
- },
34
- jest: {
35
- ref: "wshobson/agents@javascript-testing-patterns",
36
- domain: "testing",
37
- description: "JavaScript 테스트 패턴",
38
- },
39
- playwright: {
40
- ref: "anthropics/skills@webapp-testing",
41
- domain: "testing",
42
- description: "Playwright 웹 앱 테스팅",
43
- },
44
- cypress: {
45
- ref: "wshobson/agents@e2e-testing-patterns",
46
- domain: "testing",
47
- description: "E2E 테스트 패턴",
48
- },
49
- // Backend
50
- prisma: {
51
- ref: "sickn33/antigravity-awesome-skills@prisma-expert",
52
- domain: "backend",
53
- description: "Prisma ORM 전문가",
54
- },
55
- express: {
56
- ref: "wshobson/agents@nodejs-backend-patterns",
57
- domain: "backend",
58
- description: "Node.js 백엔드 패턴",
59
- },
60
- fastify: {
61
- ref: "wshobson/agents@nodejs-backend-patterns",
62
- domain: "backend",
63
- description: "Node.js 백엔드 패턴",
64
- },
65
- graphql: {
66
- ref: "wshobson/agents@nodejs-backend-patterns",
67
- domain: "backend",
68
- description: "Node.js 백엔드 패턴",
69
- },
70
- // DevOps
71
- docker: {
72
- ref: "sickn33/antigravity-awesome-skills@docker-expert",
73
- domain: "devops",
74
- description: "Docker 전문가",
75
- },
76
- kubernetes: {
77
- ref: "wshobson/agents@k8s-manifest-generator",
78
- domain: "devops",
79
- description: "Kubernetes 매니페스트 생성",
80
- },
81
- "github-actions": {
82
- ref: "wshobson/agents@github-actions-templates",
83
- domain: "devops",
84
- description: "GitHub Actions 템플릿",
85
- },
86
- };
87
- /**
88
- * 항상 설치하는 메타 스킬 (스킬 탐색 및 생성 지원)
89
- */
90
- export const META_SKILLS = [
91
- {
92
- ref: "vercel-labs/skills@find-skills",
93
- domain: "meta",
94
- description: "skills.sh에서 스킬 탐색 및 설치",
95
- },
96
- {
97
- ref: "anthropics/skills@skill-creator",
98
- domain: "meta",
99
- description: "새로운 스킬 생성 가이드",
100
- },
101
- ];
102
- //# sourceMappingURL=SkillsRegistry.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SkillsRegistry.js","sourceRoot":"","sources":["../../../src/infrastructure/skills/SkillsRegistry.ts"],"names":[],"mappings":"AAUA,MAAM,CAAC,MAAM,kBAAkB,GAA6B;IAC1D,WAAW;IACX,IAAI,EAAE;QACJ,GAAG,EAAE,6CAA6C;QAClD,MAAM,EAAE,UAAU;QAClB,WAAW,EAAE,eAAe;KAC7B;IACD,MAAM,EAAE;QACN,GAAG,EAAE,6CAA6C;QAClD,MAAM,EAAE,UAAU;QAClB,WAAW,EAAE,eAAe;KAC7B;IACD,KAAK,EAAE;QACL,GAAG,EAAE,sDAAsD;QAC3D,MAAM,EAAE,UAAU;QAClB,WAAW,EAAE,aAAa;KAC3B;IACD,cAAc,EAAE;QACd,GAAG,EAAE,6DAA6D;QAClE,MAAM,EAAE,UAAU;QAClB,WAAW,EAAE,oBAAoB;KAClC;IACD,GAAG,EAAE;QACH,GAAG,EAAE,yCAAyC;QAC9C,MAAM,EAAE,UAAU;QAClB,WAAW,EAAE,eAAe;KAC7B;IAED,UAAU;IACV,MAAM,EAAE;QACN,GAAG,EAAE,qBAAqB;QAC1B,MAAM,EAAE,SAAS;QACjB,WAAW,EAAE,eAAe;KAC7B;IACD,IAAI,EAAE;QACJ,GAAG,EAAE,6CAA6C;QAClD,MAAM,EAAE,SAAS;QACjB,WAAW,EAAE,mBAAmB;KACjC;IACD,UAAU,EAAE;QACV,GAAG,EAAE,kCAAkC;QACvC,MAAM,EAAE,SAAS;QACjB,WAAW,EAAE,oBAAoB;KAClC;IACD,OAAO,EAAE;QACP,GAAG,EAAE,sCAAsC;QAC3C,MAAM,EAAE,SAAS;QACjB,WAAW,EAAE,YAAY;KAC1B;IAED,UAAU;IACV,MAAM,EAAE;QACN,GAAG,EAAE,kDAAkD;QACvD,MAAM,EAAE,SAAS;QACjB,WAAW,EAAE,gBAAgB;KAC9B;IACD,OAAO,EAAE;QACP,GAAG,EAAE,yCAAyC;QAC9C,MAAM,EAAE,SAAS;QACjB,WAAW,EAAE,gBAAgB;KAC9B;IACD,OAAO,EAAE;QACP,GAAG,EAAE,yCAAyC;QAC9C,MAAM,EAAE,SAAS;QACjB,WAAW,EAAE,gBAAgB;KAC9B;IACD,OAAO,EAAE;QACP,GAAG,EAAE,yCAAyC;QAC9C,MAAM,EAAE,SAAS;QACjB,WAAW,EAAE,gBAAgB;KAC9B;IAED,SAAS;IACT,MAAM,EAAE;QACN,GAAG,EAAE,kDAAkD;QACvD,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,YAAY;KAC1B;IACD,UAAU,EAAE;QACV,GAAG,EAAE,wCAAwC;QAC7C,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,qBAAqB;KACnC;IACD,gBAAgB,EAAE;QAChB,GAAG,EAAE,0CAA0C;QAC/C,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,oBAAoB;KAClC;CACF,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAe;IACrC;QACE,GAAG,EAAE,gCAAgC;QACrC,MAAM,EAAE,MAAM;QACd,WAAW,EAAE,wBAAwB;KACtC;IACD;QACE,GAAG,EAAE,iCAAiC;QACtC,MAAM,EAAE,MAAM;QACd,WAAW,EAAE,eAAe;KAC7B;CACF,CAAC"}