@seojin08/skill-finder 0.3.2 → 0.3.3
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
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
새 버전의 항목은 `npm run package`가 내려받기 페이지의 meta.json에 서명과 함께 넣고, 앱의 "새 버전" 표시를 누르면 보입니다. 한 줄이 한 항목입니다.
|
|
4
4
|
|
|
5
|
+
## 0.3.3 (2026-11-03)
|
|
6
|
+
|
|
7
|
+
- 스킬 설치에 쓰는 skills CLI를 1.7.6으로 올렸습니다. 저장소 안의 바로가기(symlink)를 통해 스킬 폴더 밖의 파일이 함께 복사될 수 있던 보안 문제가 막혔습니다.
|
|
8
|
+
- 이제 Node.js 22.20 이상이 필요합니다. 더 낮은 버전이면 실행할 때 업데이트 안내가 나옵니다.
|
|
9
|
+
|
|
5
10
|
## 0.3.2 (2026-11-02)
|
|
6
11
|
|
|
7
12
|
- 영어·일본어 화면에서 숫자·이름·명령이 끼는 문장이 그 언어의 어순으로 자연스럽게 나옵니다.
|
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ Claude Code 스킬을 한곳에서 찾아 점수·위험 신호와 함께 보고
|
|
|
23
23
|
|
|
24
24
|
### macOS·Linux·Windows (npx)
|
|
25
25
|
|
|
26
|
-
Node.js 22.
|
|
26
|
+
Node.js 22.20 이상이 있으면 설치 없이 실행합니다. 데이터는 사용자 폴더(macOS `~/Library/Application Support/Skill Finder`, Linux `~/.local/share/skill-finder`, Windows `%LOCALAPPDATA%\SkillFinder\npx-data`)에 남습니다.
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
29
|
npx @seojin08/skill-finder
|
|
@@ -45,7 +45,7 @@ npx @seojin08/skill-finder stop # 백그라운드로 켠 앱 끄
|
|
|
45
45
|
|
|
46
46
|
### 소스에서
|
|
47
47
|
|
|
48
|
-
필요한 것: Node.js 22.
|
|
48
|
+
필요한 것: Node.js 22.20 이상(24 권장), git, Claude Code(`claude` 명령).
|
|
49
49
|
|
|
50
50
|
```bash
|
|
51
51
|
npm install
|
package/bin/skill-finder.mjs
CHANGED
|
@@ -34,7 +34,7 @@ const T = {
|
|
|
34
34
|
|
|
35
35
|
공통: --json(기계가 읽는 출력), --port N, --no-open, --lang ko|en|ja
|
|
36
36
|
설치·삭제는 앱 화면의 확인 창에서만 합니다.`,
|
|
37
|
-
node: (v) => `Node.js ${v}는 너무 오래됐습니다. 22.
|
|
37
|
+
node: (v) => `Node.js ${v}는 너무 오래됐습니다. 22.20 이상이 필요합니다: https://nodejs.org`,
|
|
38
38
|
noWeb: '웹 화면이 빌드되지 않았습니다. 먼저 npm run build를 실행하세요.',
|
|
39
39
|
starting: (p) => `Skill Finder를 켜는 중입니다 (127.0.0.1:${p})…`,
|
|
40
40
|
background: (p) => `Skill Finder를 백그라운드로 켰습니다 (127.0.0.1:${p}). 끄려면: skill-finder stop`,
|
|
@@ -70,7 +70,7 @@ Usage:
|
|
|
70
70
|
|
|
71
71
|
Common: --json (machine-readable), --port N, --no-open, --lang ko|en|ja
|
|
72
72
|
Installing and removing happen only in the app's confirm dialog.`,
|
|
73
|
-
node: (v) => `Node.js ${v} is too old. 22.
|
|
73
|
+
node: (v) => `Node.js ${v} is too old. 22.20 or later is needed: https://nodejs.org`,
|
|
74
74
|
noWeb: 'The web app is not built. Run npm run build first.',
|
|
75
75
|
starting: (p) => `Starting Skill Finder (127.0.0.1:${p})…`,
|
|
76
76
|
background: (p) => `Started Skill Finder in the background (127.0.0.1:${p}). To stop it: skill-finder stop`,
|
|
@@ -106,7 +106,7 @@ Installing and removing happen only in the app's confirm dialog.`,
|
|
|
106
106
|
|
|
107
107
|
共通: --json(機械向け出力), --port N, --no-open, --lang ko|en|ja
|
|
108
108
|
インストールと削除はアプリの確認画面でのみ行います。`,
|
|
109
|
-
node: (v) => `Node.js ${v} は古すぎます。22.
|
|
109
|
+
node: (v) => `Node.js ${v} は古すぎます。22.20 以上が必要です: https://nodejs.org`,
|
|
110
110
|
noWeb: 'Web 画面がビルドされていません。先に npm run build を実行してください。',
|
|
111
111
|
starting: (p) => `Skill Finder を起動しています (127.0.0.1:${p})…`,
|
|
112
112
|
background: (p) => `Skill Finder をバックグラウンドで起動しました (127.0.0.1:${p})。止めるには: skill-finder stop`,
|
|
@@ -204,7 +204,7 @@ function readPid() {
|
|
|
204
204
|
/** Starts the server: in this terminal (`start`), or detached for the read commands. Resolves its port. */
|
|
205
205
|
async function startServer(background) {
|
|
206
206
|
const [major, minor] = process.versions.node.split('.').map(Number);
|
|
207
|
-
if (major < 22 || (major === 22 && minor <
|
|
207
|
+
if (major < 22 || (major === 22 && minor < 20)) throw new Error(t.node(process.versions.node));
|
|
208
208
|
if (!existsSync(join(ROOT, 'web', 'dist', 'index.html'))) throw new Error(t.noWeb);
|
|
209
209
|
let port = Number(portArg) || Number(process.env.PORT) || DEFAULT_PORT;
|
|
210
210
|
if (!(await portFree(port))) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seojin08/skill-finder",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "Find Claude Code skills across marketplaces, skills.sh and GitHub, see their risk signals, and install them after checking what comes along. Local web app and read-only CLI.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
"skill-finder": "bin/skill-finder.mjs"
|
|
9
9
|
},
|
|
10
10
|
"engines": {
|
|
11
|
-
"node": ">=22.
|
|
11
|
+
"node": ">=22.20"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"express": "5.3.0",
|
|
15
|
-
"skills": "1.7.
|
|
15
|
+
"skills": "1.7.6",
|
|
16
16
|
"yaml": "2.9.1",
|
|
17
17
|
"zod": "4.6.7"
|
|
18
18
|
},
|
package/server/src/config.js
CHANGED
|
@@ -7,19 +7,31 @@ export const SERVER_DIR = join(ROOT_DIR, 'server');
|
|
|
7
7
|
export const WEB_DIST_DIR = join(ROOT_DIR, 'web', 'dist');
|
|
8
8
|
/** The release launcher keeps the token outside the app folder (UI debate D-6); from the environment only. */
|
|
9
9
|
export const ENV_PATH = process.env.SKILL_FINDER_ENV_PATH ? resolve(process.env.SKILL_FINDER_ENV_PATH) : join(ROOT_DIR, '.env');
|
|
10
|
-
export const SKILLS_CLI_VERSION = '1.7.4';
|
|
11
10
|
/** The bundled skills CLI: under the app, or wherever npm put it when installed as a package (npx hoists it). */
|
|
12
|
-
|
|
13
|
-
const local = join(ROOT_DIR, 'node_modules', 'skills'
|
|
11
|
+
const SKILLS_DIR = (() => {
|
|
12
|
+
const local = join(ROOT_DIR, 'node_modules', 'skills');
|
|
14
13
|
if (existsSync(local))
|
|
15
14
|
return local;
|
|
16
15
|
try {
|
|
17
|
-
return
|
|
16
|
+
return dirname(createRequire(import.meta.url).resolve('skills/package.json'));
|
|
18
17
|
}
|
|
19
18
|
catch {
|
|
20
19
|
return local;
|
|
21
20
|
}
|
|
22
21
|
})();
|
|
22
|
+
export const SKILLS_CLI_PATH = join(SKILLS_DIR, 'bin', 'cli.mjs');
|
|
23
|
+
/**
|
|
24
|
+
* The version the app runs, read from the bundled package so the commands it shows for running by hand name the same
|
|
25
|
+
* one (it was written here by hand and could fall behind the package, review 2026-11-03).
|
|
26
|
+
*/
|
|
27
|
+
export const SKILLS_CLI_VERSION = (() => {
|
|
28
|
+
try {
|
|
29
|
+
return String(JSON.parse(readFileSync(join(SKILLS_DIR, 'package.json'), 'utf8')).version);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return 'latest'; // no bundled CLI: installing fails anyway, and the shown command still runs
|
|
33
|
+
}
|
|
34
|
+
})();
|
|
23
35
|
/** Vite dev server port (web/vite.config.ts); allowed as a Host/Origin in --dev mode only. */
|
|
24
36
|
export const DEV_VITE_PORT = 5174;
|
|
25
37
|
function parseEnvFile(text) {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { basename, joinPath, skillMdPath } from "./tree.js";
|
|
2
|
-
// Mirrors skills CLI 1.7.
|
|
2
|
+
// Mirrors skills CLI 1.7.6 src/skills.ts (discoverSkills) so that what we list is what `skills add --skill` can install.
|
|
3
|
+
// Unchanged since 1.7.4 except two things not mirrored: extra search dirs a repo can list in skills.sh.json (`paths`),
|
|
4
|
+
// and skipping a skill whose name or description is empty once control characters are removed.
|
|
3
5
|
export const SKIP_DIRS = ['node_modules', '.git', 'dist', 'build', '__pycache__'];
|
|
4
6
|
export const AGENT_PROJECT_SKILL_DIRS = [
|
|
5
7
|
'.agents/skills',
|
|
@@ -56,7 +56,7 @@ function readLock(file) {
|
|
|
56
56
|
}
|
|
57
57
|
return byFolder;
|
|
58
58
|
}
|
|
59
|
-
/** The folder the skills CLI installs a skill into (its `sanitizeName`, skills@1.7.4). */
|
|
59
|
+
/** The folder the skills CLI installs a skill into (its `sanitizeName`, the same in skills@1.7.4 and 1.7.6). */
|
|
60
60
|
export function skillFolderName(name) {
|
|
61
61
|
return name.toLowerCase().replace(/[^a-z0-9._]+/g, '-').replace(/^[.\-]+|[.\-]+$/g, '').slice(0, 255) || 'unnamed-skill';
|
|
62
62
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
import { RISK_ORDER, RISK_RULES_VERSION } from "../analyze/risk.js";
|
|
3
|
+
import { SKILLS_CLI_VERSION } from "../config.js";
|
|
3
4
|
import { basename } from "../discovery/tree.js";
|
|
4
5
|
import { normalizeSkillName, PluginUnavailableError, skillId } from "../indexer.js";
|
|
5
6
|
import { installSummary } from "../install/summary.js";
|
|
@@ -132,7 +133,8 @@ export async function runSearch(deps, query, filters, emit) {
|
|
|
132
133
|
const sources = new Set(filters.sources?.length ? filters.sources : ['marketplace', 'skillssh', 'github']);
|
|
133
134
|
const maxRisk = filters.maxRisk ?? 'medium';
|
|
134
135
|
// `r` is the result-item shape; bump it when items gain fields so cached searches are rebuilt.
|
|
135
|
-
|
|
136
|
+
// c: cached results carry install commands naming the skills CLI version (`npx skills@x.y.z …`)
|
|
137
|
+
const key = cacheKey(query, filters, { w: settings.weights, t: !!ctx.config.githubToken, s: minStars, r: RESULTS_VERSION, k: RISK_RULES_VERSION, c: SKILLS_CLI_VERSION });
|
|
136
138
|
// The English query for a Korean one goes out first, cached search or not: it comes from the query alone,
|
|
137
139
|
// and the button helps most exactly when there is little else to show.
|
|
138
140
|
const suggestion = koreanSuggestion(query);
|