diff --git a/bin/cli.mjs b/bin/cli.mjs new file mode 100755 index 0000000..fb655df --- /dev/null +++ b/bin/cli.mjs @@ -0,0 +1,148 @@ +#!/usr/bin/env node + +import fs from "fs"; +import path from "path"; +import os from "os"; + +const PREBUILT = path.join( + path.dirname(new URL(import.meta.url).pathname), + "..", + "prebuilt" +); +const SKILLS_DIR = path.join(os.homedir(), ".claude", "skills"); + +// --- helpers --- + +function cpR(src, dest) { + fs.mkdirSync(dest, { recursive: true }); + for (const entry of fs.readdirSync(src, { withFileTypes: true })) { + const s = path.join(src, entry.name); + const d = path.join(dest, entry.name); + if (entry.isDirectory()) cpR(s, d); + else fs.copyFileSync(s, d); + } +} + +function parseFrontmatter(filepath) { + const text = fs.readFileSync(filepath, "utf8"); + const m = text.match(/^---\n([\s\S]*?)\n---/); + if (!m) return {}; + const fm = {}; + for (const line of m[1].split("\n")) { + const idx = line.indexOf(":"); + if (idx > 0 && !line.startsWith(" ") && !line.startsWith("-")) { + fm[line.slice(0, idx).trim()] = line.slice(idx + 1).trim(); + } + } + return fm; +} + +function availableMasters() { + if (!fs.existsSync(PREBUILT)) return []; + return fs + .readdirSync(PREBUILT, { withFileTypes: true }) + .filter((d) => d.isDirectory() && d.name !== "compare") + .map((d) => { + const skillMd = path.join(PREBUILT, d.name, "SKILL.md"); + const fm = fs.existsSync(skillMd) ? parseFrontmatter(skillMd) : {}; + return { name: d.name, description: fm.description || "" }; + }); +} + +// --- commands --- + +function cmdList() { + const masters = availableMasters(); + if (!masters.length) { + console.log("No prebuilt masters found."); + return; + } + console.log(`\nAvailable masters (${masters.length}):\n`); + const nameW = Math.max(...masters.map((m) => m.name.length), 4); + for (const m of masters) { + const desc = m.description.length > 80 ? m.description.slice(0, 77) + "..." : m.description; + console.log(` ${m.name.padEnd(nameW)} ${desc}`); + } + console.log(); +} + +function cmdInstall(names) { + fs.mkdirSync(SKILLS_DIR, { recursive: true }); + for (const name of names) { + const src = path.join(PREBUILT, name); + if (!fs.existsSync(src)) { + console.log(` ✗ ${name} — not found in prebuilt/`); + continue; + } + const dest = path.join(SKILLS_DIR, `master-${name}`); + cpR(src, dest); + console.log(` ✓ ${name} → ${dest}`); + } +} + +function cmdUninstall(names) { + for (const name of names) { + const dest = path.join(SKILLS_DIR, `master-${name}`); + if (!fs.existsSync(dest)) { + console.log(` ✗ ${name} — not installed`); + continue; + } + fs.rmSync(dest, { recursive: true, force: true }); + console.log(` ✓ ${name} removed`); + } +} + +function showHelp() { + console.log(` +master-skill — Chinese Buddhist Master AI Skills installer + +Usage: + master-skill install Install masters to ~/.claude/skills/ + master-skill install --all Install all available masters + master-skill list List available masters + master-skill uninstall Remove installed masters + master-skill --help Show this help + +Examples: + npx master-skill install zhiyi fazang + npx master-skill install --all + npx master-skill list + npx master-skill uninstall zhiyi +`); +} + +// --- main --- + +const args = process.argv.slice(2); +const cmd = args[0]; + +if (!cmd || cmd === "--help" || cmd === "-h") { + showHelp(); +} else if (cmd === "list") { + cmdList(); +} else if (cmd === "install") { + const rest = args.slice(1); + if (rest.includes("--all")) { + const all = availableMasters().map((m) => m.name); + if (!all.length) { + console.log("No masters available."); + } else { + console.log(`Installing all ${all.length} masters...\n`); + cmdInstall(all); + } + } else if (rest.length === 0) { + console.log("Usage: master-skill install | --all"); + } else { + cmdInstall(rest); + } +} else if (cmd === "uninstall") { + const rest = args.slice(1); + if (rest.length === 0) { + console.log("Usage: master-skill uninstall "); + } else { + cmdUninstall(rest); + } +} else { + console.log(`Unknown command: ${cmd}\nRun master-skill --help for usage.`); + process.exit(1); +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..4405946 --- /dev/null +++ b/package.json @@ -0,0 +1,12 @@ +{ + "name": "master-skill", + "version": "0.3.0", + "description": "Chinese Buddhist Master AI Skills — RAG-grounded, source-cited, fidelity-tested", + "bin": { + "master-skill": "./bin/cli.mjs" + }, + "keywords": ["claude-skills", "agent-skills", "buddhism", "ai-persona", "rag", "digital-humanities"], + "license": "MIT", + "repository": {"type": "git", "url": "https://github.com/xr843/Master-skill"}, + "files": ["bin/", "prebuilt/", "scripts/"] +} diff --git a/prebuilt/fazang/teaching.md b/prebuilt/fazang/references/teaching.md similarity index 100% rename from prebuilt/fazang/teaching.md rename to prebuilt/fazang/references/teaching.md diff --git a/prebuilt/fazang/voice.md b/prebuilt/fazang/references/voice.md similarity index 100% rename from prebuilt/fazang/voice.md rename to prebuilt/fazang/references/voice.md diff --git a/prebuilt/huineng/teaching.md b/prebuilt/huineng/references/teaching.md similarity index 100% rename from prebuilt/huineng/teaching.md rename to prebuilt/huineng/references/teaching.md diff --git a/prebuilt/huineng/voice.md b/prebuilt/huineng/references/voice.md similarity index 100% rename from prebuilt/huineng/voice.md rename to prebuilt/huineng/references/voice.md diff --git a/prebuilt/kumarajiva/teaching.md b/prebuilt/kumarajiva/references/teaching.md similarity index 100% rename from prebuilt/kumarajiva/teaching.md rename to prebuilt/kumarajiva/references/teaching.md diff --git a/prebuilt/kumarajiva/voice.md b/prebuilt/kumarajiva/references/voice.md similarity index 100% rename from prebuilt/kumarajiva/voice.md rename to prebuilt/kumarajiva/references/voice.md diff --git a/prebuilt/ouyi/teaching.md b/prebuilt/ouyi/references/teaching.md similarity index 100% rename from prebuilt/ouyi/teaching.md rename to prebuilt/ouyi/references/teaching.md diff --git a/prebuilt/ouyi/voice.md b/prebuilt/ouyi/references/voice.md similarity index 100% rename from prebuilt/ouyi/voice.md rename to prebuilt/ouyi/references/voice.md diff --git a/prebuilt/xuanzang/teaching.md b/prebuilt/xuanzang/references/teaching.md similarity index 100% rename from prebuilt/xuanzang/teaching.md rename to prebuilt/xuanzang/references/teaching.md diff --git a/prebuilt/xuanzang/voice.md b/prebuilt/xuanzang/references/voice.md similarity index 100% rename from prebuilt/xuanzang/voice.md rename to prebuilt/xuanzang/references/voice.md diff --git a/prebuilt/xuyun/teaching.md b/prebuilt/xuyun/references/teaching.md similarity index 100% rename from prebuilt/xuyun/teaching.md rename to prebuilt/xuyun/references/teaching.md diff --git a/prebuilt/xuyun/voice.md b/prebuilt/xuyun/references/voice.md similarity index 100% rename from prebuilt/xuyun/voice.md rename to prebuilt/xuyun/references/voice.md diff --git a/prebuilt/yinguang/teaching.md b/prebuilt/yinguang/references/teaching.md similarity index 100% rename from prebuilt/yinguang/teaching.md rename to prebuilt/yinguang/references/teaching.md diff --git a/prebuilt/yinguang/voice.md b/prebuilt/yinguang/references/voice.md similarity index 100% rename from prebuilt/yinguang/voice.md rename to prebuilt/yinguang/references/voice.md