leerness 1.9.181 β†’ 1.9.182

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,100 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.9.182 β€” 2026-05-21
4
+
5
+ **🌐 곡식 쑰직 μŠ€ν‚¬ catalog μžλ™ 탐색 β€” vercel-labs/agent-skills + anthropics/skills 직접 톡합 (μ‚¬μš©μž λͺ…μ‹œ).**
6
+
7
+ 자율 λͺ¨λ“œ 112 λΌμš΄λ“œ. μ‚¬μš©μž λͺ…μ‹œ: *"곡식 쑰직의 μŠ€ν‚¬ λͺ¨μŒμ„ νƒμƒ‰ν•΄μ„œ λ‹€μš΄λ‘œλ“œ λ°›μ•„μ„œ μŠ€ν‚¬μ„ μ‚¬μš©ν•˜λŠ”μ§€ 확인 (vercel-labs/agent-skills, anthropics/skills) + μ§€κΈˆ μ„€κ³„ν•˜λŠ” λ°©ν–₯이 μ˜¬λ°”λ₯Έμ§€ νŒλ‹¨λ„ λ„ˆκ°€ ν•΄μ€˜"*.
8
+
9
+ ### 핡심 μΆ”κ°€
10
+
11
+ #### 1. `SKILL_CATALOG_PRESETS` β€” λ‚΄μž₯ 곡식 catalog
12
+ ```js
13
+ const SKILL_CATALOG_PRESETS = {
14
+ 'vercel': { owner: 'vercel-labs', repo: 'agent-skills', branch: 'main', path: 'skills' },
15
+ 'anthropic': { owner: 'anthropics', repo: 'skills', branch: 'main', path: 'skills' }
16
+ };
17
+ ```
18
+
19
+ #### 2. `_fetchGitHubSkills(owner, repo, branch, dirPath)` β€” GitHub Contents API 직접 호좜
20
+ - rate limit: 60 req/hr (LEERNESS_GITHUB_TOKEN μ‹œ 5000 req/hr)
21
+ - 응닡을 ν‘œμ€€ entry ν˜•μ‹μœΌλ‘œ λ³€ν™˜ (name, url, description, source, homepage)
22
+ - raw.githubusercontent.com URL μžλ™ ꡬ성
23
+
24
+ #### 3. `leerness skill discover` ν™•μž₯
25
+ ```bash
26
+ $ leerness skill discover --preset anthropic
27
+ # leerness skill discover (1.9.182 β€” GitHub presets)
28
+ targets: anthropics/skills#main:skills
29
+ fetching anthropics/skills...
30
+ βœ“ anthropics/skills: 17개 skill 발견
31
+ 전체 17건 (전체 ν‘œμ‹œ β€” λ§€μΉ­ μ—†μŒ)
32
+
33
+ | name | source | url |
34
+ |---|---|---|
35
+ | algorithmic-art | github:anthropics/skills | https://raw.githubusercontent.com/anthropics/skills/main/skills/algorithmic-art/SKILL.md |
36
+ | mcp-builder | github:anthropics/skills | https://raw.githubusercontent.com/anthropics/skills/main/skills/mcp-builder/SKILL.md |
37
+ | ...
38
+ ```
39
+
40
+ μ‹ κ·œ μ˜΅μ…˜:
41
+ - `--preset <name>` β€” λ‚΄μž₯ catalog (vercel, anthropic)
42
+ - `--all-presets` β€” λͺ¨λ“  preset λ™μ‹œ 탐색
43
+ - `--github owner/repo[#branch][:path]` β€” 직접 GitHub repo μ§€μ •
44
+
45
+ #### 4. `leerness skill auto-install` β€” μ‹ κ·œ λͺ…λ Ή (μ‚¬μš©μž λͺ…μ‹œ 핡심)
46
+ ```bash
47
+ $ leerness skill auto-install --query "mcp"
48
+ # leerness skill auto-install (1.9.182)
49
+ presets: vercel, anthropic
50
+ query: mcp
51
+ mode: 🟑 dry-run (LEERNESS_SKILL_AUTO_INSTALL=1 λ˜λŠ” --yes ν•„μš”)
52
+ fetching anthropics/skills...
53
+ βœ“ anthropics/skills: 17개 skill
54
+ 맀칭 1/17건 (query: mcp)
55
+ | mcp-builder | github:anthropics/skills | https://raw.githubusercontent.com/anthropics/skills/main/skills/mcp-builder/SKILL.md |
56
+
57
+ πŸ’‘ μžλ™ install ν™œμ„±ν™”: .env 에 LEERNESS_SKILL_AUTO_INSTALL=1 λ˜λŠ” leerness skill auto-install --yes
58
+ ```
59
+
60
+ - handoff μ»¨ν…μŠ€νŠΈμ—μ„œ μžλ™ query μΆ”μΆœ (μ§„ν–‰ task ν‚€μ›Œλ“œ)
61
+ - LEERNESS_SKILL_AUTO_INSTALL=1 μ‹œ μ‹€μ œ λ‹€μš΄λ‘œλ“œ (λ³΄μ•ˆ opt-in)
62
+ - λ―Έμ„€μ • μ‹œ dry-run (μΆ”μ²œλ§Œ)
63
+
64
+ #### 5. .env.example 보강
65
+ ```
66
+ LEERNESS_SKILL_AUTO_INSTALL=0
67
+ LEERNESS_SKILL_AUTO_PRESETS=vercel,anthropic
68
+ ```
69
+
70
+ ### μ‹€ 검증 (live GitHub API)
71
+ - **anthropics/skills 17개 skill μžλ™ 발견**:
72
+ algorithmic-art, brand-guidelines, canvas-design, claude-api, doc-coauthoring, **docx**, frontend-design, internal-comms, **mcp-builder**, **pdf**, **pptx**, skill-creator, slack-gif-creator, theme-factory, web-artifacts-builder, **webapp-testing**, **xlsx**
73
+ - **mcp-builder μ‹€ λ‹€μš΄λ‘œλ“œ + μ„€μΉ˜ 성곡**:
74
+ `leerness-stress/.harness/skills/mcp-builder/SKILL.md` λ‹€μš΄λ‘œλ“œ 검증
75
+ description: "Guide for creating high-quality MCP (Model Context Protocol) servers..."
76
+
77
+ ### λ°©ν–₯μ„± 평가 λ³΄κ³ μ„œ (μ‚¬μš©μž λͺ…μ‹œ)
78
+ μ‚¬μš©μž μš”μ²­: *"μ§€κΈˆ μ„€κ³„ν•˜λŠ” λ°©ν–₯이 μ˜¬λ°”λ₯Έ λ°©ν–₯인지 νŒλ‹¨λ„ λ„ˆκ°€ ν•΄μ€˜"*. λ³΄κ³ μ„œ: `_reports/direction-1.9.182.md` (λΉ„κ³΅κ°œ).
79
+
80
+ **κ²°λ‘ **:
81
+ | 평가 ν•­λͺ© | 점수 |
82
+ |---|---|
83
+ | μžμœ¨μ„± (auto loop Β· review Β· install) | 8.5/10 |
84
+ | μ„±μž₯μ„± (learn Β· suggest Β· skill catalog) | 8/10 |
85
+ | μ•ˆμ „μ„± (sandbox Β· permissions Β· env opt-in) | 9/10 |
86
+ | λ²”μš©μ„± (multi-provider Β· MCP Β· bridges) | 8/10 |
87
+ | 검증 κ°€λŠ₯μ„± (verify-claim Β· stress Β· e2e) | 9.5/10 |
88
+
89
+ **μ’…ν•©**: 86/100. **μ˜¬λ°”λ₯Έ λ°©ν–₯**. 약점은 *μŠ€ν‚¬ 적용 ν›„ 회고 λΆ€μž¬ + μ™ΈλΆ€ μŠ€ν‚¬ μ‹ λ’°μ„± 검증* β€” 1.9.183~190 λ§ˆμΌμŠ€ν†€.
90
+
91
+ ### Verified
92
+ - stress-v127: **16/16** (preset 4 + .env λΌμš°νŒ… 2 + μ‹€ GitHub fetch 3 + VERSION+λˆ„μ  νšŒκ·€ 7)
93
+ - e2e 217/217 baseline μœ μ§€
94
+ - VERSION = 1.9.182 Β· autonomous-rounds = 112 Β· main μžλ™ push 43 λΌμš΄λ“œ 연속
95
+
96
+ ---
97
+
3
98
  ## 1.9.181 β€” 2026-05-21
4
99
 
5
100
  **πŸšͺ REPL μ§„μž… 흐름 정리 β€” μ‚¬μš©μž λͺ…μ‹œ 4μ’… + 직접 ꡬ동 μ‹€ 호좜 검증.**
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > **AI μ½”λ”© μ—μ΄μ „νŠΈμ˜ κ±°μ§“ μ™„λ£ŒΒ·μ€‘λ³΅Β·λ§κ°Β·μΆ©λŒμ„ λ§‰μ•„μ£ΌλŠ” κ²€μˆ˜Β·κΈ°μ–΅Β·ν˜‘μ—… CLI ν•˜λ„€μŠ€.**
4
4
 
5
- [![npm](https://img.shields.io/badge/npm-leerness-blue)](https://www.npmjs.com/package/leerness) [![version](https://img.shields.io/badge/version-1.9.181-green)]() [![tests](https://img.shields.io/badge/e2e-217%2F217-success)]() [![stress](https://img.shields.io/badge/stress--v126-18%2F18-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-54-brightgreen)]() [![rounds](https://img.shields.io/badge/autonomous--rounds-111-blueviolet)]() [![main-push](https://img.shields.io/badge/release--main--push-42_rounds-success)]() [![repl-flow](https://img.shields.io/badge/REPL_μ§„μž…-provider_μžλ™μ„ νƒ-success)]() [![repl-tested](https://img.shields.io/badge/μ‹€ν˜ΈμΆœ-claude_검증-success)]() [![npm-auto](https://img.shields.io/badge/npm_auto--publish-NPM__TOKEN_톡합-success)]() [![capability](https://img.shields.io/badge/6_capability-72%25_production--ready-brightgreen)]() [![sandbox](https://img.shields.io/badge/runCommandSafe-cwd_jail%2Benv_scrub-success)]() [![license](https://img.shields.io/badge/license-MIT-lightgrey)]()
5
+ [![npm](https://img.shields.io/badge/npm-leerness-blue)](https://www.npmjs.com/package/leerness) [![version](https://img.shields.io/badge/version-1.9.182-green)]() [![tests](https://img.shields.io/badge/e2e-217%2F217-success)]() [![stress](https://img.shields.io/badge/stress--v127-16%2F16-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-54-brightgreen)]() [![rounds](https://img.shields.io/badge/autonomous--rounds-112-blueviolet)]() [![main-push](https://img.shields.io/badge/release--main--push-43_rounds-success)]() [![skill-presets](https://img.shields.io/badge/skill_catalog-vercel%2Banthropic_톡합-success)]() [![skill-auto](https://img.shields.io/badge/skill_auto--install-handoff_톡합_(opt--in)-success)]() [![direction](https://img.shields.io/badge/λ°©ν–₯μ„±_평가-86%2F100_(μ˜¬λ°”λ₯Έ_λ°©ν–₯)-brightgreen)]() [![npm-auto](https://img.shields.io/badge/npm_auto--publish-NPM__TOKEN_톡합-success)]() [![sandbox](https://img.shields.io/badge/runCommandSafe-cwd_jail%2Benv_scrub-success)]() [![license](https://img.shields.io/badge/license-MIT-lightgrey)]()
6
6
 
7
7
  ```
8
8
  ╔══════════════════════════════════════════════════════════════╗
@@ -12,9 +12,9 @@
12
12
  β•‘ β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•”β•β•β• β–ˆβ–ˆβ•”β•β•β• β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β• β•šβ•β•β•β•β–ˆβ–ˆβ•‘ β•‘
13
13
  β•‘ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘ β•‘
14
14
  β•‘ β•šβ•β•β•β•β•β•β•β•šβ•β•β•β•β•β•β•β•šβ•β•β•β•β•β•β•β•šβ•β• β•šβ•β•β•šβ•β• β•šβ•β•β•β•β•šβ•β•β•β•β•β•β•β•šβ•β•β•β•β•β•β• β•‘
15
- β•‘ v1.9.181 AI Agent Reliability Harness + Sandbox β•‘
15
+ β•‘ v1.9.182 AI Agent Reliability Harness + Sandbox β•‘
16
16
  β•‘ verify Β· remember Β· orchestrate Β· audit Β· sandbox Β· drift β•‘
17
- β•‘ πŸšͺ REPL μ§„μž… 흐름 정리 (provider μžλ™ 선택 Β· μ‹€ν˜ΈμΆœ 검증) β•‘
17
+ β•‘ 🌐 곡식 catalog μžλ™ 탐색 (vercel/anthropic) Β· μžκ°€ μ„±μž₯ν˜• β•‘
18
18
  β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
19
19
  ```
20
20
 
package/bin/harness.js CHANGED
@@ -7,7 +7,7 @@ const cp = require('child_process');
7
7
  const os = require('os'); // 1.9.178: _publishToNpm μ—μ„œ os.tmpdir() μ‚¬μš© (μ „μ—­ import)
8
8
  const readline = require('readline');
9
9
 
10
- const VERSION = '1.9.181';
10
+ const VERSION = '1.9.182';
11
11
  const MARK = '<!-- leerness:managed -->';
12
12
  const README_START = '<!-- leerness:project-readme:start -->';
13
13
  const README_END = '<!-- leerness:project-readme:end -->';
@@ -872,7 +872,11 @@ async function install(root, opts = {}) {
872
872
  '# μ˜ˆμ‹œ URL: https://agentskills.io/llms.txt',
873
873
  'LEERNESS_SKILL_DISCOVER_URL=',
874
874
  '# (선택) μ‚¬μš©μž μš”μ²­ 뢄석 μ‹œ μžλ™ λ§€μΉ­ μŠ€ν‚¬ μΆ”μ²œ. 1=ν™œμ„±, 0/λ―Έμ„€μ •=λΉ„ν™œμ„±.',
875
- 'LEERNESS_SKILL_AUTO_DISCOVER=0'
875
+ 'LEERNESS_SKILL_AUTO_DISCOVER=0',
876
+ '# 1.9.182 β€” handoff μ‹œ 곡식 catalog (vercel-labs, anthropics) μžλ™ 탐색 + λ§€μΉ­ μ‹œ μžλ™ install. 1=ν™œμ„± (opt-in λ³΄μ•ˆ).',
877
+ 'LEERNESS_SKILL_AUTO_INSTALL=0',
878
+ '# 1.9.182 β€” handoff μžλ™ 탐색 λŒ€μƒ preset (콀마 ꡬ뢄). 예: vercel,anthropic',
879
+ 'LEERNESS_SKILL_AUTO_PRESETS=vercel,anthropic'
876
880
  ];
877
881
  mergeLinesFile(path.join(root, '.env.example'), envLines);
878
882
  // 1.9.153: .env 직접 생성/λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ (μ‚¬μš©μž λͺ…μ‹œ μš”μ²­). λ³΄μ•ˆ = 빈 κ°’λ§Œ β€” μ‚¬μš©μžκ°€ 직접 토큰 채움.
@@ -1322,15 +1326,135 @@ function _parseSkillCatalog(body, sourceUrl) {
1322
1326
  return entries;
1323
1327
  }
1324
1328
 
1325
- // skill discover β€” agentskills.io λ˜λŠ” μ‚¬μš©μž μ§€μ • URL의 μΉ΄νƒˆλ‘œκ·Έ μΈλ±μŠ€μ—μ„œ λ§€μΉ­ μΆ”μ²œ
1329
+ // 1.9.182: 곡식 쑰직 μŠ€ν‚¬ catalog presets β€” μ‚¬μš©μž λͺ…μ‹œ (vercel-labs, anthropics 같은 1st-party μžλ™ 탐색).
1330
+ // 각 entry: GitHub repo의 skills/ 디렉토리에 SKILL.md 듀이 μžˆλŠ” ν‘œμ€€ ꡬ쑰.
1331
+ // sync: leerness skill discover --preset <name> Β· --all-presets Β· --github <owner/repo>[#branch]
1332
+ const SKILL_CATALOG_PRESETS = {
1333
+ 'vercel': { owner: 'vercel-labs', repo: 'agent-skills', branch: 'main', path: 'skills',
1334
+ homepage: 'https://github.com/vercel-labs/agent-skills' },
1335
+ 'anthropic': { owner: 'anthropics', repo: 'skills', branch: 'main', path: 'skills',
1336
+ homepage: 'https://github.com/anthropics/skills' }
1337
+ };
1338
+
1339
+ // 1.9.182: GitHub repo 의 skills/ 디렉토리 μžλ™ 탐색.
1340
+ // GitHub Contents API (no auth 60req/hr, .env GITHUB_TOKEN μ‹œ 5000req/hr) μ‚¬μš©.
1341
+ // 응닡을 ν‘œμ€€ entry ν˜•μ‹μœΌλ‘œ λ³€ν™˜: { name, url, description, format: 'github', source }
1342
+ async function _fetchGitHubSkills(owner, repo, branch, dirPath) {
1343
+ branch = branch || 'main'; dirPath = dirPath || 'skills';
1344
+ const apiUrl = `https://api.github.com/repos/${owner}/${repo}/contents/${dirPath}?ref=${branch}`;
1345
+ const token = process.env.LEERNESS_GITHUB_TOKEN || process.env.GITHUB_TOKEN || '';
1346
+ const headers = token ? { Authorization: `Bearer ${token}` } : {};
1347
+ // _httpFetch κ°€ headersλ₯Ό μ§€μ›ν•˜μ§€ μ•ŠμœΌλ©΄ raw https μ‚¬μš©
1348
+ let body, status;
1349
+ try {
1350
+ const https = require('https');
1351
+ const u = new URL(apiUrl);
1352
+ body = await new Promise((resolve, reject) => {
1353
+ const req = https.get({
1354
+ hostname: u.hostname, path: u.pathname + u.search,
1355
+ headers: { 'User-Agent': `leerness/${VERSION}`, ...headers }
1356
+ }, res => {
1357
+ status = res.statusCode;
1358
+ const chunks = [];
1359
+ res.on('data', c => chunks.push(c));
1360
+ res.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
1361
+ });
1362
+ req.on('error', reject);
1363
+ req.setTimeout(10000, () => { req.destroy(new Error('timeout')); });
1364
+ });
1365
+ } catch (e) { return { ok: false, error: e.message, skills: [] }; }
1366
+ if (status !== 200) return { ok: false, error: `HTTP ${status}`, skills: [] };
1367
+ let items; try { items = JSON.parse(body); } catch { return { ok: false, error: 'invalid JSON', skills: [] }; }
1368
+ if (!Array.isArray(items)) return { ok: false, error: 'not array', skills: [] };
1369
+ const skills = items
1370
+ .filter(i => i && i.type === 'dir')
1371
+ .map(i => ({
1372
+ name: i.name,
1373
+ url: `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/${i.path}/SKILL.md`,
1374
+ description: '',
1375
+ format: 'github',
1376
+ source: `github:${owner}/${repo}`,
1377
+ homepage: i.html_url
1378
+ }));
1379
+ return { ok: true, skills };
1380
+ }
1381
+
1382
+ // skill discover β€” agentskills.io / GitHub repo / 곡식 preset μΉ΄νƒˆλ‘œκ·Έ μΈλ±μŠ€μ—μ„œ λ§€μΉ­ μΆ”μ²œ
1326
1383
  async function skillDiscoverCmd(root) {
1327
- const url = arg('--source', null) || process.env.LEERNESS_SKILL_DISCOVER_URL || null;
1384
+ // 1.9.182: --preset / --all-presets / --github μΆ”κ°€ (μ‚¬μš©μž λͺ…μ‹œ β€” vercel-labs/agent-skills, anthropics/skills λ“±)
1385
+ const preset = arg('--preset', null);
1386
+ const allPresets = has('--all-presets');
1387
+ const github = arg('--github', null); // 예: vercel-labs/agent-skills λ˜λŠ” owner/repo#branch:path
1328
1388
  const query = arg('--query', null);
1389
+
1390
+ // preset / --all-presets / --github 처리 β€” 단일 source URLκ³Ό λ³„κ°œ 흐름
1391
+ if (preset || allPresets || github) {
1392
+ const targets = [];
1393
+ if (allPresets) for (const k of Object.keys(SKILL_CATALOG_PRESETS)) targets.push({ key: k, ...SKILL_CATALOG_PRESETS[k] });
1394
+ else if (preset) {
1395
+ const p = SKILL_CATALOG_PRESETS[preset];
1396
+ if (!p) { fail(`μ•Œ 수 μ—†λŠ” preset: ${preset} (μ‚¬μš© κ°€λŠ₯: ${Object.keys(SKILL_CATALOG_PRESETS).join(', ')})`); return process.exit(1); }
1397
+ targets.push({ key: preset, ...p });
1398
+ }
1399
+ if (github) {
1400
+ // owner/repo λ˜λŠ” owner/repo#branch λ˜λŠ” owner/repo#branch:path
1401
+ const m = github.match(/^([^/]+)\/([^#:]+)(?:#([^:]+))?(?::(.+))?$/);
1402
+ if (!m) { fail(`--github ν˜•μ‹ 였λ₯˜ (예: vercel-labs/agent-skills λ˜λŠ” owner/repo#main:skills)`); return process.exit(1); }
1403
+ targets.push({ key: 'custom', owner: m[1], repo: m[2], branch: m[3] || 'main', path: m[4] || 'skills', homepage: `https://github.com/${m[1]}/${m[2]}` });
1404
+ }
1405
+ log(`# leerness skill discover (1.9.182 β€” GitHub presets)`);
1406
+ if (query) log(`query: ${query}`);
1407
+ log(`targets: ${targets.map(t => `${t.owner}/${t.repo}#${t.branch}:${t.path}`).join(', ')}`);
1408
+ log('');
1409
+ const allEntries = [];
1410
+ for (const t of targets) {
1411
+ log(` fetching ${t.owner}/${t.repo}...`);
1412
+ const r = await _fetchGitHubSkills(t.owner, t.repo, t.branch, t.path);
1413
+ if (!r.ok) {
1414
+ log(` ⚠ ${t.owner}/${t.repo}: ${r.error}`);
1415
+ continue;
1416
+ }
1417
+ log(` βœ“ ${t.owner}/${t.repo}: ${r.skills.length}개 skill 발견`);
1418
+ for (const s of r.skills) allEntries.push(s);
1419
+ }
1420
+ log('');
1421
+ if (has('--json')) { log(JSON.stringify({ presets: targets.map(t => t.key), query, entries: allEntries }, null, 2)); return; }
1422
+ if (!allEntries.length) {
1423
+ log(' (μŠ€ν‚¬ 0건 β€” preset/path/branch 확인 λ˜λŠ” rate limit κ°€λŠ₯)');
1424
+ return;
1425
+ }
1426
+ let matched = allEntries;
1427
+ if (query) {
1428
+ const q = query.toLowerCase();
1429
+ matched = allEntries.filter(e => e.name.toLowerCase().includes(q) || (e.description || '').toLowerCase().includes(q));
1430
+ log(`맀칭 ${matched.length}/${allEntries.length}건 (query: ${query})`);
1431
+ } else {
1432
+ log(`전체 ${allEntries.length}건 (전체 ν‘œμ‹œ β€” λ§€μΉ­ μ—†μŒ)`);
1433
+ }
1434
+ log('');
1435
+ log('| name | source | url |');
1436
+ log('|---|---|---|');
1437
+ for (const e of matched.slice(0, 40)) {
1438
+ log(`| ${e.name} | ${e.source} | ${e.url} |`);
1439
+ }
1440
+ log('');
1441
+ log(`πŸ’‘ μ„€μΉ˜: leerness skill install <url> Β· μžλ™ install (env opt-in): LEERNESS_SKILL_AUTO_INSTALL=1`);
1442
+ return;
1443
+ }
1444
+
1445
+ // κΈ°μ‘΄ 단일 URL 흐름 (1.9.42)
1446
+ const url = arg('--source', null) || process.env.LEERNESS_SKILL_DISCOVER_URL || null;
1329
1447
  if (!url) {
1330
1448
  fail([
1331
1449
  'LEERNESS_SKILL_DISCOVER_URL ν™˜κ²½λ³€μˆ˜ λ˜λŠ” --source URL ν•„μš”.',
1450
+ '',
1451
+ 'λ˜λŠ” (1.9.182 μ‹ κ·œ) β€” 곡식 쑰직 catalog presets:',
1452
+ ' leerness skill discover --preset vercel # vercel-labs/agent-skills',
1453
+ ' leerness skill discover --preset anthropic # anthropics/skills',
1454
+ ' leerness skill discover --all-presets # λͺ¨λ“  preset λ™μ‹œ 탐색',
1455
+ ' leerness skill discover --github owner/repo # 직접 GitHub repo μ§€μ •',
1456
+ '',
1332
1457
  '예: leerness skill discover --source https://agentskills.io/llms.txt',
1333
- 'λ˜λŠ” .env에 LEERNESS_SKILL_DISCOVER_URL=...',
1334
1458
  '',
1335
1459
  '(μ •μ±…: leernessλŠ” μ‚¬μš©μž λ™μ˜ 없이 μ™ΈλΆ€ URL을 fetchν•˜μ§€ μ•ŠμŒ β€” 1.9.42 opt-in)'
1336
1460
  ].join('\n'));
@@ -1372,6 +1496,78 @@ async function skillDiscoverCmd(root) {
1372
1496
  log(`πŸ’‘ μ„€μΉ˜: leerness skill install <url>`);
1373
1497
  }
1374
1498
 
1499
+ // 1.9.182: skill auto-install β€” 곡식 organization catalog μžλ™ 탐색 β†’ skill match β†’ μžλ™ install.
1500
+ // μ‚¬μš©μž λͺ…μ‹œ: "μŠ€ν‚¬μ„ μ‚¬μš©ν•˜κ±°λ‚˜ μ μš©ν•΄λ‘λ©΄ 쒋을 뢀뢄듀을 μ•Œμ•„μ„œ μ›Ήμ—μ„œ 곡식 쑰직의 μŠ€ν‚¬ λͺ¨μŒμ„ νƒμƒ‰ν•΄μ„œ λ‹€μš΄λ‘œλ“œ λ°›μ•„μ„œ μ‚¬μš©"
1501
+ // μ •μ±…: LEERNESS_SKILL_AUTO_INSTALL=1 일 λ•Œλ§Œ μ‹€μ œ install (λ³΄μ•ˆ opt-in). λ―Έμ„€μ • μ‹œ dry-run (μΆ”μ²œλ§Œ).
1502
+ async function skillAutoInstallCmd(root) {
1503
+ root = absRoot(root);
1504
+ const presets = (process.env.LEERNESS_SKILL_AUTO_PRESETS || arg('--presets', 'vercel,anthropic') || '').split(',').map(s => s.trim()).filter(Boolean);
1505
+ const autoInstall = process.env.LEERNESS_SKILL_AUTO_INSTALL === '1' || has('--yes');
1506
+ const query = arg('--query', null) || _autoInstallQueryFromHandoff(root);
1507
+ const maxInstall = Number(arg('--max', '3'));
1508
+ log(`# leerness skill auto-install (1.9.182)`);
1509
+ log(`presets: ${presets.join(', ') || '(none)'}`);
1510
+ log(`query: ${query || '(auto β€” handoff μ»¨ν…μŠ€νŠΈ)'}`);
1511
+ log(`mode: ${autoInstall ? '🟒 μžλ™ install' : '🟑 dry-run (LEERNESS_SKILL_AUTO_INSTALL=1 λ˜λŠ” --yes ν•„μš”)'}`);
1512
+ log('');
1513
+ const allEntries = [];
1514
+ for (const key of presets) {
1515
+ const p = SKILL_CATALOG_PRESETS[key];
1516
+ if (!p) { log(` ⚠ μ•Œ 수 μ—†λŠ” preset: ${key}`); continue; }
1517
+ log(` fetching ${p.owner}/${p.repo}...`);
1518
+ const r = await _fetchGitHubSkills(p.owner, p.repo, p.branch, p.path);
1519
+ if (!r.ok) { log(` ⚠ ${p.owner}/${p.repo}: ${r.error}`); continue; }
1520
+ log(` βœ“ ${p.owner}/${p.repo}: ${r.skills.length}개 skill`);
1521
+ for (const s of r.skills) allEntries.push(s);
1522
+ }
1523
+ log('');
1524
+ // query λ§€μΉ­ (substring) β€” query μ—†μœΌλ©΄ λͺ¨λ“  ν•­λͺ©
1525
+ let matched = allEntries;
1526
+ if (query) {
1527
+ const q = String(query).toLowerCase();
1528
+ matched = allEntries.filter(e => e.name.toLowerCase().includes(q) || (e.description || '').toLowerCase().includes(q));
1529
+ log(`맀칭 ${matched.length}/${allEntries.length}건 (query: ${query})`);
1530
+ } else {
1531
+ log(`전체 ${allEntries.length}건 (λͺ¨λ“  ν•­λͺ©)`);
1532
+ }
1533
+ if (!matched.length) { log(' (λ§€μΉ­ 0건 β€” query λ³€κ²½ λ˜λŠ” --presets μΆ”κ°€)'); return; }
1534
+ log('');
1535
+ log('| name | source | url |');
1536
+ log('|---|---|---|');
1537
+ for (const e of matched.slice(0, maxInstall)) {
1538
+ log(`| ${e.name} | ${e.source} | ${e.url} |`);
1539
+ }
1540
+ log('');
1541
+ if (!autoInstall) {
1542
+ log(`πŸ’‘ μžλ™ install ν™œμ„±ν™”: .env 에 LEERNESS_SKILL_AUTO_INSTALL=1 λ˜λŠ” \`leerness skill auto-install --yes\``);
1543
+ log(` ν˜„μž¬ ${Math.min(maxInstall, matched.length)}건이 install λŒ€μƒ (μ‹€μ œ λ‹€μš΄λ‘œλ“œ X β€” dry-run)`);
1544
+ return;
1545
+ }
1546
+ log(`πŸ“₯ μžλ™ install μ‹œμž‘ β€” μ΅œλŒ€ ${maxInstall}건`);
1547
+ let installed = 0, failed = 0;
1548
+ for (const e of matched.slice(0, maxInstall)) {
1549
+ try {
1550
+ await skillInstallCmd(root, e.url);
1551
+ installed++;
1552
+ } catch (err) {
1553
+ log(` ⚠ ${e.name} install μ‹€νŒ¨: ${err.message}`);
1554
+ failed++;
1555
+ }
1556
+ }
1557
+ log('');
1558
+ log(`βœ“ auto-install μ™„λ£Œ: ${installed}건 μ„€μΉ˜ / ${failed}건 μ‹€νŒ¨ / ${matched.length - installed - failed}건 skip`);
1559
+ }
1560
+
1561
+ // 1.9.182: handoff μ»¨ν…μŠ€νŠΈ (ν˜„μž¬ in-progress task) μ—μ„œ μžλ™ query μΆ”μΆœ
1562
+ function _autoInstallQueryFromHandoff(root) {
1563
+ try {
1564
+ const rows = readProgressRows(root);
1565
+ const active = rows.find(r => r.status === '[μ§„ν–‰]' || r.status === '[in-progress]' || r.status === 'in_progress');
1566
+ if (active) return (active.request || '').split(/\s+/).slice(0, 3).join(' ');
1567
+ } catch {}
1568
+ return null;
1569
+ }
1570
+
1375
1571
  // skill export <id> β€” κΈ°μ‘΄ 자체 skill을 agentskills.io ν‘œμ€€ SKILL.md둜 export
1376
1572
  function skillExportCmd(root, id) {
1377
1573
  if (!id) { fail('μ‚¬μš©λ²•: leerness skill export <id>'); return process.exit(1); }
@@ -13540,6 +13736,8 @@ async function main() {
13540
13736
  if (cmd === 'benchmark') return benchmarkCmd(absRoot(args[1] || arg('--path', process.cwd())));
13541
13737
  if (cmd === 'skill' && args[1] === 'publish') return skillPublishCmd(absRoot(arg('--path', process.cwd())));
13542
13738
  if (cmd === 'skill' && args[1] === 'suggest') return skillSuggestCmd(absRoot(arg('--path', process.cwd())));
13739
+ // 1.9.182: leerness skill auto-install β€” 곡식 catalog μžλ™ 탐색 + skill match λ§€μΉ­ μ‹œ μžλ™ install (μ‚¬μš©μž λͺ…μ‹œ)
13740
+ if (cmd === 'skill' && args[1] === 'auto-install') return await skillAutoInstallCmd(absRoot(arg('--path', process.cwd())));
13543
13741
  if (cmd === 'mcp' && args[1] === 'serve') return mcpServeCmd(absRoot(arg('--path', process.cwd())));
13544
13742
  if (cmd === 'gate') return gate(args[1] || process.cwd());
13545
13743
  if (cmd === 'verify-code') return verifyCodeCmd(args[1] || process.cwd());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "leerness",
3
- "version": "1.9.181",
3
+ "version": "1.9.182",
4
4
  "description": "Leerness: λΉ„νŒŒκ΄΄ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜, μžλ™ 버전 κ°μ§€Β·μ—…λ°μ΄νŠΈ, κ³„νš/μ§„ν–‰/ν•Έλ“œμ˜€ν”„ μžλ™ν™”, κ²ŒμœΌλ¦„Β·μ‹œν¬λ¦ΏΒ·μΈμ½”λ”© μžλ™ κ°€λ“œ, Claude Code μŠ¬λž˜μ‹œ 톡합을 κ°–μΆ˜ ν•œκ΅­μ–΄ μš°μ„  AI 개발 ν•˜λ„€μŠ€.",
5
5
  "keywords": [
6
6
  "leerness",