diff --git a/skillhub-cli/package.json b/skillhub-cli/package.json index 7965631aa..96da3812c 100644 --- a/skillhub-cli/package.json +++ b/skillhub-cli/package.json @@ -1,6 +1,6 @@ { "name": "motovis-skillhub", - "version": "1.0.6", + "version": "1.0.7", "type": "module", "description": "SkillHub CLI - 企业级 Agent Skill 管理工具,支持命名空间", "bin": { diff --git a/skillhub-cli/src/cli.ts b/skillhub-cli/src/cli.ts index ca06afa03..4e4c736fc 100644 --- a/skillhub-cli/src/cli.ts +++ b/skillhub-cli/src/cli.ts @@ -8,6 +8,11 @@ import { dirname } from "node:path"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); +// ANSI helpers (zero-dependency) +const bold = (s: string) => `\x1b[1m${s}\x1b[0m`; +const dim = (s: string) => `\x1b[2m${s}\x1b[0m`; +const cyan = (s: string) => `\x1b[36m${s}\x1b[0m`; + function getPackageVersion(): string { try { const pkgPath = resolve(__dirname, "../package.json"); @@ -18,6 +23,108 @@ function getPackageVersion(): string { } } +interface HelpEntry { + cmd: string; + desc: string; + alias?: string; +} + +function formatSection(header: string, entries: HelpEntry[]): string { + const displayWidth = (e: HelpEntry) => e.cmd.length + (e.alias ? e.alias.length + 3 : 0); + const maxW = entries.reduce((max, e) => Math.max(max, displayWidth(e)), 0); + const col = Math.max(maxW + 4, 28); + const lines = [bold(header)]; + for (const e of entries) { + const aliasPart = e.alias ? dim(` (${e.alias})`) : ""; + const pad = " ".repeat(Math.max(col - displayWidth(e), 2)); + lines.push(` ${cyan(e.cmd)}${aliasPart}${pad}${e.desc}`); + } + return lines.join("\n"); +} + +function buildTopLevelHelp(version: string): string { + const sections: string[] = []; + + sections.push(`${bold("skillhub")} ${dim(`v${version}`)}`); + sections.push(dim("CLI for SkillHub — publish, search, and manage agent skills")); + sections.push(""); + + sections.push(formatSection("Auth", [ + { cmd: "login", desc: "Authenticate with SkillHub registry" }, + { cmd: "logout", desc: "Remove stored authentication token" }, + { cmd: "whoami", desc: "Show current authenticated user" }, + ])); + sections.push(""); + + sections.push(formatSection("Discover", [ + { cmd: "explore", desc: "Browse or search skills from the registry", alias: "find, find-skills, search" }, + { cmd: "search ", desc: dim("[Deprecated: use 'explore' instead]") }, + ])); + sections.push(""); + + sections.push(formatSection("Install & Manage", [ + { cmd: "install ", desc: "Install from registry, git, or local path", alias: "i" }, + { cmd: "download ", desc: "Download a skill package to local directory" }, + { cmd: "update [slug]", desc: "Update installed skills from their source", alias: "up" }, + { cmd: "uninstall [name]", desc: "Uninstall a skill from local agent", alias: "un" }, + { cmd: "list", desc: "List installed skills", alias: "ls" }, + { cmd: "check", desc: "Check installed skills against lock file" }, + ])); + sections.push(""); + + sections.push(formatSection("Publish", [ + { cmd: "init [name]", desc: "Create a new SKILL.md template" }, + { cmd: "publish [path]", desc: "Publish a skill to SkillHub registry" }, + { cmd: "sync [path]", desc: "Scan and publish all skills from a directory" }, + { cmd: "delete ", desc: "Delete a skill you own", alias: "del, unpublish" }, + { cmd: "archive ", desc: "Archive a skill you own" }, + { cmd: "versions ", desc: "List skill versions" }, + ])); + sections.push(""); + + sections.push(formatSection("Info & Review", [ + { cmd: "inspect ", desc: "View skill metadata without installing", alias: "info, view" }, + { cmd: "resolve ", desc: "Resolve the latest version of a skill" }, + { cmd: "rating ", desc: "View your rating for a skill" }, + { cmd: "rate ", desc: "Rate a skill (1-5)" }, + { cmd: "star ", desc: "Star a skill" }, + { cmd: "report ", desc: "Report a skill for review" }, + ])); + sections.push(""); + + sections.push(formatSection("Account", [ + { cmd: "me skills", desc: "List your published skills", alias: "me ls" }, + { cmd: "me stars", desc: "List your starred skills" }, + { cmd: "namespaces", desc: "List namespaces you have access to" }, + { cmd: "notifications", desc: "Manage notifications", alias: "notif" }, + { cmd: "reviews my", desc: "List your review submissions", alias: "reviews submissions" }, + ])); + sections.push(""); + + sections.push(formatSection("Admin", [ + { cmd: "hide ", desc: "Hide a skill (admin only)" }, + { cmd: "unhide ", desc: "Unhide a skill (admin only)" }, + { cmd: "transfer ", desc: "Transfer namespace ownership" }, + ])); + sections.push(""); + + sections.push(bold("Examples")); + sections.push(dim(" skillhub install vision2group/fork-workflow Install a skill")); + sections.push(dim(" skillhub explore Browse available skills")); + sections.push(dim(" skillhub publish Publish current directory")); + sections.push(dim(" skillhub me skills List your published skills")); + sections.push(dim(" skillhub update --global Update all global skills")); + sections.push(""); + + sections.push(bold("Global Options")); + sections.push(` ${cyan("--registry ")} Registry API base URL`); + sections.push(` ${cyan("--json")} Output results as JSON`); + sections.push(` ${cyan("--help")} Show help for a command`); + sections.push(` ${cyan("--version")} Show version number`); + + return sections.join("\n"); +} + export async function createCli(): Promise { const program = new Command(); const version = getPackageVersion(); @@ -29,6 +136,13 @@ export async function createCli(): Promise { .option("--registry ", "Registry API base URL", "http://localhost:8080") .option("--json", "Output results as JSON"); + const customHelp = buildTopLevelHelp(version); + const originalHelpInformation = program.helpInformation.bind(program); + program.helpInformation = () => { + if (program.parent) return originalHelpInformation(); + return customHelp; + }; + const [ { registerLogin }, { registerLogout },