claude-skills-cli 0.0.20 → 0.0.21

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.
Files changed (81) hide show
  1. package/dist/add-hook.cmd-B6iZtoPi.js +193 -0
  2. package/dist/add-hook.cmd-B6iZtoPi.js.map +1 -0
  3. package/dist/doctor.cmd-CkNw6ine.js +119 -0
  4. package/dist/doctor.cmd-CkNw6ine.js.map +1 -0
  5. package/dist/frontmatter-validator-DO686mla.js +226 -0
  6. package/dist/frontmatter-validator-DO686mla.js.map +1 -0
  7. package/dist/fs-CuGv3Ob2.js +23 -0
  8. package/dist/fs-CuGv3Ob2.js.map +1 -0
  9. package/dist/index.js +24 -22
  10. package/dist/index.js.map +1 -1
  11. package/dist/init.cmd-BoeuCgQP.js +108 -0
  12. package/dist/init.cmd-BoeuCgQP.js.map +1 -0
  13. package/dist/install.cmd-CH7yZ92g.js +79 -0
  14. package/dist/install.cmd-CH7yZ92g.js.map +1 -0
  15. package/dist/output-Dz8fk6Gu.js +102 -0
  16. package/dist/output-Dz8fk6Gu.js.map +1 -0
  17. package/dist/package.cmd-CwGRHdEq.js +107 -0
  18. package/dist/package.cmd-CwGRHdEq.js.map +1 -0
  19. package/dist/stats.cmd-D1ujNiDO.js +121 -0
  20. package/dist/stats.cmd-D1ujNiDO.js.map +1 -0
  21. package/dist/{core/templates.js → templates-BQTgkXfH.js} +16 -13
  22. package/dist/templates-BQTgkXfH.js.map +1 -0
  23. package/dist/validate.cmd-CDUJDKGs.js +96 -0
  24. package/dist/validate.cmd-CDUJDKGs.js.map +1 -0
  25. package/dist/validator-DV5zeeel.js +721 -0
  26. package/dist/validator-DV5zeeel.js.map +1 -0
  27. package/package.json +34 -35
  28. package/dist/commands/add-hook.cmd.js +0 -35
  29. package/dist/commands/add-hook.cmd.js.map +0 -1
  30. package/dist/commands/add-hook.js +0 -216
  31. package/dist/commands/add-hook.js.map +0 -1
  32. package/dist/commands/doctor.cmd.js +0 -19
  33. package/dist/commands/doctor.cmd.js.map +0 -1
  34. package/dist/commands/doctor.js +0 -128
  35. package/dist/commands/doctor.js.map +0 -1
  36. package/dist/commands/init.cmd.js +0 -37
  37. package/dist/commands/init.cmd.js.map +0 -1
  38. package/dist/commands/init.js +0 -86
  39. package/dist/commands/init.js.map +0 -1
  40. package/dist/commands/install.cmd.js +0 -23
  41. package/dist/commands/install.cmd.js.map +0 -1
  42. package/dist/commands/install.js +0 -64
  43. package/dist/commands/install.js.map +0 -1
  44. package/dist/commands/package.cmd.js +0 -28
  45. package/dist/commands/package.cmd.js.map +0 -1
  46. package/dist/commands/package.js +0 -134
  47. package/dist/commands/package.js.map +0 -1
  48. package/dist/commands/stats.cmd.js +0 -19
  49. package/dist/commands/stats.cmd.js.map +0 -1
  50. package/dist/commands/stats.js +0 -154
  51. package/dist/commands/stats.js.map +0 -1
  52. package/dist/commands/validate.cmd.js +0 -39
  53. package/dist/commands/validate.cmd.js.map +0 -1
  54. package/dist/commands/validate.js +0 -77
  55. package/dist/commands/validate.js.map +0 -1
  56. package/dist/core/templates.js.map +0 -1
  57. package/dist/core/validator.js +0 -252
  58. package/dist/core/validator.js.map +0 -1
  59. package/dist/help.js +0 -305
  60. package/dist/help.js.map +0 -1
  61. package/dist/skills/.gitkeep +0 -0
  62. package/dist/types.js +0 -2
  63. package/dist/types.js.map +0 -1
  64. package/dist/utils/fs.js +0 -25
  65. package/dist/utils/fs.js.map +0 -1
  66. package/dist/utils/output.js +0 -102
  67. package/dist/utils/output.js.map +0 -1
  68. package/dist/validators/alignment-validator.js +0 -54
  69. package/dist/validators/alignment-validator.js.map +0 -1
  70. package/dist/validators/content-validator.js +0 -156
  71. package/dist/validators/content-validator.js.map +0 -1
  72. package/dist/validators/description-validator.js +0 -150
  73. package/dist/validators/description-validator.js.map +0 -1
  74. package/dist/validators/file-structure-validator.js +0 -125
  75. package/dist/validators/file-structure-validator.js.map +0 -1
  76. package/dist/validators/frontmatter-validator.js +0 -190
  77. package/dist/validators/frontmatter-validator.js.map +0 -1
  78. package/dist/validators/references-validator.js +0 -155
  79. package/dist/validators/references-validator.js.map +0 -1
  80. package/dist/validators/text-analysis.js +0 -71
  81. package/dist/validators/text-analysis.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,25 +1,27 @@
1
1
  #!/usr/bin/env node
2
- import { defineCommand, runMain } from 'citty';
3
- import { readFileSync } from 'node:fs';
4
- import { dirname, join } from 'node:path';
5
- import { fileURLToPath } from 'node:url';
2
+ import { defineCommand, runMain } from "citty";
3
+ import { readFileSync } from "node:fs";
4
+ import { dirname, join } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ //#region src/index.ts
6
7
  const __dirname = dirname(fileURLToPath(import.meta.url));
7
- const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
8
- const main = defineCommand({
9
- meta: {
10
- name: 'claude-skills-cli',
11
- version: pkg.version,
12
- description: 'CLI toolkit for creating and managing Claude Agent Skills\n\nIMPORTANT FOR LLMs:\n ALWAYS run validate after creating or editing a skill:\n claude-skills-cli validate <skill-path>\n Skills MUST pass validation before use.\n Fix all errors immediately. Address warnings promptly.\n\nResources:\n Pre-built skills & hooks: https://github.com/spences10/claude-code-toolkit\n Includes a UserPromptSubmit hook for automatic skill activation.',
13
- },
14
- subCommands: {
15
- init: () => import('./commands/init.cmd.js').then((r) => r.default),
16
- install: () => import('./commands/install.cmd.js').then((r) => r.default),
17
- validate: () => import('./commands/validate.cmd.js').then((r) => r.default),
18
- doctor: () => import('./commands/doctor.cmd.js').then((r) => r.default),
19
- package: () => import('./commands/package.cmd.js').then((r) => r.default),
20
- stats: () => import('./commands/stats.cmd.js').then((r) => r.default),
21
- 'add-hook': () => import('./commands/add-hook.cmd.js').then((r) => r.default),
22
- },
23
- });
24
- runMain(main);
8
+ runMain(defineCommand({
9
+ meta: {
10
+ name: "claude-skills-cli",
11
+ version: JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-8")).version,
12
+ description: "CLI toolkit for creating and managing Claude Agent Skills\n\nIMPORTANT FOR LLMs:\n ALWAYS run validate after creating or editing a skill:\n claude-skills-cli validate <skill-path>\n Skills MUST pass validation before use.\n Fix all errors immediately. Address warnings promptly.\n\nResources:\n Pre-built skills & hooks: https://github.com/spences10/claude-code-toolkit\n Includes a UserPromptSubmit hook for automatic skill activation."
13
+ },
14
+ subCommands: {
15
+ init: () => import("./init.cmd-BoeuCgQP.js").then((r) => r.default),
16
+ install: () => import("./install.cmd-CH7yZ92g.js").then((r) => r.default),
17
+ validate: () => import("./validate.cmd-CDUJDKGs.js").then((r) => r.default),
18
+ doctor: () => import("./doctor.cmd-CkNw6ine.js").then((r) => r.default),
19
+ package: () => import("./package.cmd-CwGRHdEq.js").then((r) => r.default),
20
+ stats: () => import("./stats.cmd-D1ujNiDO.js").then((r) => r.default),
21
+ "add-hook": () => import("./add-hook.cmd-B6iZtoPi.js").then((r) => r.default)
22
+ }
23
+ }));
24
+ //#endregion
25
+ export {};
26
+
25
27
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CACrB,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAC5D,CAAC;AAEF,MAAM,IAAI,GAAG,aAAa,CAAC;IAC1B,IAAI,EAAE;QACL,IAAI,EAAE,mBAAmB;QACzB,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,WAAW,EACV,8bAA8b;KAC/b;IACD,WAAW,EAAE;QACZ,IAAI,EAAE,GAAG,EAAE,CACV,MAAM,CAAC,wBAAwB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QACxD,OAAO,EAAE,GAAG,EAAE,CACb,MAAM,CAAC,2BAA2B,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QAC3D,QAAQ,EAAE,GAAG,EAAE,CACd,MAAM,CAAC,4BAA4B,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QAC5D,MAAM,EAAE,GAAG,EAAE,CACZ,MAAM,CAAC,0BAA0B,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QAC1D,OAAO,EAAE,GAAG,EAAE,CACb,MAAM,CAAC,2BAA2B,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QAC3D,KAAK,EAAE,GAAG,EAAE,CACX,MAAM,CAAC,yBAAyB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QACzD,UAAU,EAAE,GAAG,EAAE,CAChB,MAAM,CAAC,4BAA4B,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;KAC5D;CACD,CAAC,CAAC;AAEH,OAAO,CAAC,IAAI,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { defineCommand, runMain } from 'citty';\nimport { readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst pkg = JSON.parse(\n\treadFileSync(join(__dirname, '..', 'package.json'), 'utf-8'),\n);\n\nconst main = defineCommand({\n\tmeta: {\n\t\tname: 'claude-skills-cli',\n\t\tversion: pkg.version,\n\t\tdescription:\n\t\t\t'CLI toolkit for creating and managing Claude Agent Skills\\n\\nIMPORTANT FOR LLMs:\\n ALWAYS run validate after creating or editing a skill:\\n claude-skills-cli validate <skill-path>\\n Skills MUST pass validation before use.\\n Fix all errors immediately. Address warnings promptly.\\n\\nResources:\\n Pre-built skills & hooks: https://github.com/spences10/claude-code-toolkit\\n Includes a UserPromptSubmit hook for automatic skill activation.',\n\t},\n\tsubCommands: {\n\t\tinit: () =>\n\t\t\timport('./commands/init.cmd.js').then((r) => r.default),\n\t\tinstall: () =>\n\t\t\timport('./commands/install.cmd.js').then((r) => r.default),\n\t\tvalidate: () =>\n\t\t\timport('./commands/validate.cmd.js').then((r) => r.default),\n\t\tdoctor: () =>\n\t\t\timport('./commands/doctor.cmd.js').then((r) => r.default),\n\t\tpackage: () =>\n\t\t\timport('./commands/package.cmd.js').then((r) => r.default),\n\t\tstats: () =>\n\t\t\timport('./commands/stats.cmd.js').then((r) => r.default),\n\t\t'add-hook': () =>\n\t\t\timport('./commands/add-hook.cmd.js').then((r) => r.default),\n\t},\n});\n\nvoid runMain(main);\n"],"mappings":";;;;;;AAOA,MAAM,YAAY,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC;AA8BpD,QAzBQ,cAAc;CAC1B,MAAM;EACL,MAAM;EACN,SAPU,KAAK,MAChB,aAAa,KAAK,WAAW,MAAM,eAAe,EAAE,QAAQ,CAC5D,CAKc;EACb,aACC;EACD;CACD,aAAa;EACZ,YACC,OAAO,0BAA0B,MAAM,MAAM,EAAE,QAAQ;EACxD,eACC,OAAO,6BAA6B,MAAM,MAAM,EAAE,QAAQ;EAC3D,gBACC,OAAO,8BAA8B,MAAM,MAAM,EAAE,QAAQ;EAC5D,cACC,OAAO,4BAA4B,MAAM,MAAM,EAAE,QAAQ;EAC1D,eACC,OAAO,6BAA6B,MAAM,MAAM,EAAE,QAAQ;EAC3D,aACC,OAAO,2BAA2B,MAAM,MAAM,EAAE,QAAQ;EACzD,kBACC,OAAO,8BAA8B,MAAM,MAAM,EAAE,QAAQ;EAC5D;CACD,CAAC,CAEgB"}
@@ -0,0 +1,108 @@
1
+ import { i as SCRIPT_TEMPLATE, o as SKILL_MD_TEMPLATE, r as REFERENCE_TEMPLATE } from "./templates-BQTgkXfH.js";
2
+ import { a as write_file, i as to_title_case, n as is_lowercase, r as make_executable, t as ensure_dir } from "./fs-CuGv3Ob2.js";
3
+ import { n as error, o as success } from "./output-Dz8fk6Gu.js";
4
+ import { defineCommand } from "citty";
5
+ import { join } from "node:path";
6
+ import { homedir } from "node:os";
7
+ //#region src/commands/init.ts
8
+ function init_command(options) {
9
+ let skill_path;
10
+ let name;
11
+ let description;
12
+ if (options.path) {
13
+ skill_path = options.path;
14
+ name = skill_path.split("/").pop() || "";
15
+ description = options.description || "TODO: [Domain] [operations]. Use when [trigger phrase]";
16
+ } else if (options.name) {
17
+ name = options.name;
18
+ description = options.description || "TODO: [Domain] [operations]. Use when [trigger phrase]";
19
+ skill_path = options.global ? join(homedir(), ".claude", "skills", name) : join(".claude", "skills", name);
20
+ } else {
21
+ error("Either --name or --path must be provided");
22
+ console.log("\nUsage:");
23
+ console.log(" claude-skills-cli init --name my-skill --description \"Description\"");
24
+ console.log(" claude-skills-cli init --path /custom/path/my-skill");
25
+ process.exit(1);
26
+ }
27
+ const alphanumeric_check = name.replace(/-/g, "").replace(/_/g, "");
28
+ if (!/^[a-z0-9]+$/.test(alphanumeric_check)) {
29
+ error(`Skill name must be kebab-case alphanumeric: ${name}`);
30
+ process.exit(1);
31
+ }
32
+ if (!is_lowercase(name)) {
33
+ error(`Skill name must be lowercase: ${name}`);
34
+ process.exit(1);
35
+ }
36
+ create_skill(skill_path, name, description, options.with_examples || false, options.global || false);
37
+ }
38
+ function create_skill(path, name, description, with_examples = false, global = false) {
39
+ ensure_dir(path);
40
+ ensure_dir(join(path, "references"));
41
+ const title = to_title_case(name);
42
+ const skill_md = SKILL_MD_TEMPLATE(name, description, title, with_examples);
43
+ write_file(join(path, "SKILL.md"), skill_md);
44
+ if (with_examples) {
45
+ ensure_dir(join(path, "scripts"));
46
+ ensure_dir(join(path, "assets"));
47
+ const reference_md = REFERENCE_TEMPLATE(title);
48
+ write_file(join(path, "references", "detailed-guide.md"), reference_md);
49
+ const script_js = SCRIPT_TEMPLATE("example.js");
50
+ const script_path = join(path, "scripts", "example.js");
51
+ write_file(script_path, script_js);
52
+ make_executable(script_path);
53
+ }
54
+ success(`Skill created at: ${path} (${global ? "global" : "project"})`);
55
+ console.log("\nNext steps:");
56
+ console.log(`1. Edit ${path}/SKILL.md with your skill instructions`);
57
+ console.log(`2. Add detailed documentation to references/`);
58
+ if (with_examples) {
59
+ console.log(`3. Add executable scripts to scripts/`);
60
+ console.log(`4. Remove example files you don't need`);
61
+ } else console.log(`3. Use --with-examples flag if you need scripts/ and example files`);
62
+ console.log(`\n⚠️ REQUIRED: Validate the skill before use:`);
63
+ console.log(` claude-skills-cli validate ${path}`);
64
+ console.log(` Fix all errors immediately.`);
65
+ }
66
+ //#endregion
67
+ //#region src/commands/init.cmd.ts
68
+ var init_cmd_default = defineCommand({
69
+ meta: {
70
+ name: "init",
71
+ description: "Create a new skill"
72
+ },
73
+ args: {
74
+ name: {
75
+ type: "string",
76
+ description: "Skill name (kebab-case, lowercase)"
77
+ },
78
+ description: {
79
+ type: "string",
80
+ description: "Brief description with trigger keywords"
81
+ },
82
+ path: {
83
+ type: "string",
84
+ description: "Custom path (alternative to --name)"
85
+ },
86
+ "with-examples": {
87
+ type: "boolean",
88
+ description: "Include example files (scripts/, assets/)"
89
+ },
90
+ global: {
91
+ type: "boolean",
92
+ description: "Install skill in ~/.claude/skills/ (available in all projects)"
93
+ }
94
+ },
95
+ run({ args }) {
96
+ init_command({
97
+ name: args.name,
98
+ description: args.description,
99
+ path: args.path,
100
+ with_examples: args["with-examples"],
101
+ global: args.global
102
+ });
103
+ }
104
+ });
105
+ //#endregion
106
+ export { init_cmd_default as default };
107
+
108
+ //# sourceMappingURL=init.cmd-BoeuCgQP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.cmd-BoeuCgQP.js","names":[],"sources":["../src/commands/init.ts","../src/commands/init.cmd.ts"],"sourcesContent":["import { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport {\n\tREFERENCE_TEMPLATE,\n\tSCRIPT_TEMPLATE,\n\tSKILL_MD_TEMPLATE,\n} from '../core/templates.js';\nimport type { InitOptions } from '../types.js';\nimport {\n\tensure_dir,\n\tis_lowercase,\n\tmake_executable,\n\tto_title_case,\n\twrite_file,\n} from '../utils/fs.js';\nimport { error, success } from '../utils/output.js';\n\nexport function init_command(options: InitOptions): void {\n\tlet skill_path: string;\n\tlet name: string;\n\tlet description: string;\n\n\t// Determine path and name\n\tif (options.path) {\n\t\tskill_path = options.path;\n\t\tname = skill_path.split('/').pop() || '';\n\t\tdescription =\n\t\t\toptions.description ||\n\t\t\t'TODO: [Domain] [operations]. Use when [trigger phrase]';\n\t} else if (options.name) {\n\t\tname = options.name;\n\t\tdescription =\n\t\t\toptions.description ||\n\t\t\t'TODO: [Domain] [operations]. Use when [trigger phrase]';\n\t\t// Use ~/.claude/skills/ for global, .claude/skills/ for project\n\t\tskill_path = options.global\n\t\t\t? join(homedir(), '.claude', 'skills', name)\n\t\t\t: join('.claude', 'skills', name);\n\t} else {\n\t\terror('Either --name or --path must be provided');\n\t\tconsole.log('\\nUsage:');\n\t\tconsole.log(\n\t\t\t' claude-skills-cli init --name my-skill --description \"Description\"',\n\t\t);\n\t\tconsole.log(\n\t\t\t' claude-skills-cli init --path /custom/path/my-skill',\n\t\t);\n\t\tprocess.exit(1);\n\t}\n\n\t// Validate name format\n\tconst alphanumeric_check = name.replace(/-/g, '').replace(/_/g, '');\n\tif (!/^[a-z0-9]+$/.test(alphanumeric_check)) {\n\t\terror(`Skill name must be kebab-case alphanumeric: ${name}`);\n\t\tprocess.exit(1);\n\t}\n\n\tif (!is_lowercase(name)) {\n\t\terror(`Skill name must be lowercase: ${name}`);\n\t\tprocess.exit(1);\n\t}\n\n\t// Create skill\n\tcreate_skill(\n\t\tskill_path,\n\t\tname,\n\t\tdescription,\n\t\toptions.with_examples || false,\n\t\toptions.global || false,\n\t);\n}\n\nfunction create_skill(\n\tpath: string,\n\tname: string,\n\tdescription: string,\n\twith_examples: boolean = false,\n\tglobal: boolean = false,\n): void {\n\t// Create base directories\n\tensure_dir(path);\n\tensure_dir(join(path, 'references'));\n\n\t// Create SKILL.md\n\tconst title = to_title_case(name);\n\tconst skill_md = SKILL_MD_TEMPLATE(\n\t\tname,\n\t\tdescription,\n\t\ttitle,\n\t\twith_examples,\n\t);\n\twrite_file(join(path, 'SKILL.md'), skill_md);\n\n\t// Only create example files if requested\n\tif (with_examples) {\n\t\t// Create example directories\n\t\tensure_dir(join(path, 'scripts'));\n\t\tensure_dir(join(path, 'assets'));\n\n\t\t// Create example reference\n\t\tconst reference_md = REFERENCE_TEMPLATE(title);\n\t\twrite_file(\n\t\t\tjoin(path, 'references', 'detailed-guide.md'),\n\t\t\treference_md,\n\t\t);\n\n\t\t// Create example script\n\t\tconst script_js = SCRIPT_TEMPLATE('example.js');\n\t\tconst script_path = join(path, 'scripts', 'example.js');\n\t\twrite_file(script_path, script_js);\n\t\tmake_executable(script_path);\n\t}\n\n\tconst scope = global ? 'global' : 'project';\n\tsuccess(`Skill created at: ${path} (${scope})`);\n\tconsole.log('\\nNext steps:');\n\tconsole.log(\n\t\t`1. Edit ${path}/SKILL.md with your skill instructions`,\n\t);\n\tconsole.log(`2. Add detailed documentation to references/`);\n\tif (with_examples) {\n\t\tconsole.log(`3. Add executable scripts to scripts/`);\n\t\tconsole.log(`4. Remove example files you don't need`);\n\t} else {\n\t\tconsole.log(\n\t\t\t`3. Use --with-examples flag if you need scripts/ and example files`,\n\t\t);\n\t}\n\tconsole.log(`\\n⚠️ REQUIRED: Validate the skill before use:`);\n\tconsole.log(` claude-skills-cli validate ${path}`);\n\tconsole.log(` Fix all errors immediately.`);\n}\n","import { defineCommand } from 'citty';\nimport { init_command } from './init.js';\n\nexport default defineCommand({\n\tmeta: { name: 'init', description: 'Create a new skill' },\n\targs: {\n\t\tname: {\n\t\t\ttype: 'string',\n\t\t\tdescription: 'Skill name (kebab-case, lowercase)',\n\t\t},\n\t\tdescription: {\n\t\t\ttype: 'string',\n\t\t\tdescription: 'Brief description with trigger keywords',\n\t\t},\n\t\tpath: {\n\t\t\ttype: 'string',\n\t\t\tdescription: 'Custom path (alternative to --name)',\n\t\t},\n\t\t'with-examples': {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Include example files (scripts/, assets/)',\n\t\t},\n\t\tglobal: {\n\t\t\ttype: 'boolean',\n\t\t\tdescription:\n\t\t\t\t'Install skill in ~/.claude/skills/ (available in all projects)',\n\t\t},\n\t},\n\trun({ args }) {\n\t\tinit_command({\n\t\t\tname: args.name,\n\t\t\tdescription: args.description,\n\t\t\tpath: args.path,\n\t\t\twith_examples: args['with-examples'],\n\t\t\tglobal: args.global,\n\t\t});\n\t},\n});\n"],"mappings":";;;;;;;AAiBA,SAAgB,aAAa,SAA4B;CACxD,IAAI;CACJ,IAAI;CACJ,IAAI;AAGJ,KAAI,QAAQ,MAAM;AACjB,eAAa,QAAQ;AACrB,SAAO,WAAW,MAAM,IAAI,CAAC,KAAK,IAAI;AACtC,gBACC,QAAQ,eACR;YACS,QAAQ,MAAM;AACxB,SAAO,QAAQ;AACf,gBACC,QAAQ,eACR;AAED,eAAa,QAAQ,SAClB,KAAK,SAAS,EAAE,WAAW,UAAU,KAAK,GAC1C,KAAK,WAAW,UAAU,KAAK;QAC5B;AACN,QAAM,2CAA2C;AACjD,UAAQ,IAAI,WAAW;AACvB,UAAQ,IACP,yEACA;AACD,UAAQ,IACP,wDACA;AACD,UAAQ,KAAK,EAAE;;CAIhB,MAAM,qBAAqB,KAAK,QAAQ,MAAM,GAAG,CAAC,QAAQ,MAAM,GAAG;AACnE,KAAI,CAAC,cAAc,KAAK,mBAAmB,EAAE;AAC5C,QAAM,+CAA+C,OAAO;AAC5D,UAAQ,KAAK,EAAE;;AAGhB,KAAI,CAAC,aAAa,KAAK,EAAE;AACxB,QAAM,iCAAiC,OAAO;AAC9C,UAAQ,KAAK,EAAE;;AAIhB,cACC,YACA,MACA,aACA,QAAQ,iBAAiB,OACzB,QAAQ,UAAU,MAClB;;AAGF,SAAS,aACR,MACA,MACA,aACA,gBAAyB,OACzB,SAAkB,OACX;AAEP,YAAW,KAAK;AAChB,YAAW,KAAK,MAAM,aAAa,CAAC;CAGpC,MAAM,QAAQ,cAAc,KAAK;CACjC,MAAM,WAAW,kBAChB,MACA,aACA,OACA,cACA;AACD,YAAW,KAAK,MAAM,WAAW,EAAE,SAAS;AAG5C,KAAI,eAAe;AAElB,aAAW,KAAK,MAAM,UAAU,CAAC;AACjC,aAAW,KAAK,MAAM,SAAS,CAAC;EAGhC,MAAM,eAAe,mBAAmB,MAAM;AAC9C,aACC,KAAK,MAAM,cAAc,oBAAoB,EAC7C,aACA;EAGD,MAAM,YAAY,gBAAgB,aAAa;EAC/C,MAAM,cAAc,KAAK,MAAM,WAAW,aAAa;AACvD,aAAW,aAAa,UAAU;AAClC,kBAAgB,YAAY;;AAI7B,SAAQ,qBAAqB,KAAK,IADpB,SAAS,WAAW,UACU,GAAG;AAC/C,SAAQ,IAAI,gBAAgB;AAC5B,SAAQ,IACP,WAAW,KAAK,wCAChB;AACD,SAAQ,IAAI,+CAA+C;AAC3D,KAAI,eAAe;AAClB,UAAQ,IAAI,wCAAwC;AACpD,UAAQ,IAAI,yCAAyC;OAErD,SAAQ,IACP,qEACA;AAEF,SAAQ,IAAI,iDAAiD;AAC7D,SAAQ,IAAI,iCAAiC,OAAO;AACpD,SAAQ,IAAI,iCAAiC;;;;AC/H9C,IAAA,mBAAe,cAAc;CAC5B,MAAM;EAAE,MAAM;EAAQ,aAAa;EAAsB;CACzD,MAAM;EACL,MAAM;GACL,MAAM;GACN,aAAa;GACb;EACD,aAAa;GACZ,MAAM;GACN,aAAa;GACb;EACD,MAAM;GACL,MAAM;GACN,aAAa;GACb;EACD,iBAAiB;GAChB,MAAM;GACN,aAAa;GACb;EACD,QAAQ;GACP,MAAM;GACN,aACC;GACD;EACD;CACD,IAAI,EAAE,QAAQ;AACb,eAAa;GACZ,MAAM,KAAK;GACX,aAAa,KAAK;GAClB,MAAM,KAAK;GACX,eAAe,KAAK;GACpB,QAAQ,KAAK;GACb,CAAC;;CAEH,CAAC"}
@@ -0,0 +1,79 @@
1
+ import { t as ensure_dir } from "./fs-CuGv3Ob2.js";
2
+ import { n as error, o as success, r as info } from "./output-Dz8fk6Gu.js";
3
+ import { defineCommand } from "citty";
4
+ import { cpSync, existsSync } from "node:fs";
5
+ import { dirname, join } from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+ //#region src/commands/install.ts
8
+ const BUNDLED_SKILLS_DIR = join(dirname(fileURLToPath(import.meta.url)), "..", "skills");
9
+ const AVAILABLE_SKILLS = [];
10
+ function install_command(options) {
11
+ const skill_name = options.skill_name;
12
+ if (!skill_name || AVAILABLE_SKILLS.length === 0) {
13
+ info("No bundled skills available");
14
+ console.log("\nOfficial method: /plugin install <skill>@<marketplace>");
15
+ console.log("See: https://code.claude.com/docs/en/plugins");
16
+ console.log("\nFor pre-built skills & activation hooks, see: https://github.com/spences10/claude-code-toolkit");
17
+ console.log("\nUse \"claude-skills-cli init\" to create new skills.");
18
+ process.exit(0);
19
+ }
20
+ if (!AVAILABLE_SKILLS.includes(skill_name)) {
21
+ error(`Unknown skill: ${skill_name}`);
22
+ console.log("\nNo bundled skills available.");
23
+ console.log("For pre-built skills & activation hooks, see: https://github.com/spences10/claude-code-toolkit");
24
+ process.exit(1);
25
+ }
26
+ const source_path = join(BUNDLED_SKILLS_DIR, skill_name);
27
+ const dest_path = join(".claude", "skills", skill_name);
28
+ if (!existsSync(source_path)) {
29
+ error(`Bundled skill not found: ${skill_name}`);
30
+ console.log(`Expected at: ${source_path}\n\nThis may be a package installation issue.`);
31
+ process.exit(1);
32
+ }
33
+ if (existsSync(dest_path)) if (options.force) info(`Skill already exists at ${dest_path}, overwriting (--force)...`);
34
+ else {
35
+ info(`Skill already installed at: ${dest_path}`);
36
+ console.log("\nUse --force to overwrite the existing skill.");
37
+ process.exit(0);
38
+ }
39
+ ensure_dir(join(".claude", "skills"));
40
+ try {
41
+ cpSync(source_path, dest_path, {
42
+ recursive: true,
43
+ force: options.force || false
44
+ });
45
+ success(`Installed ${skill_name} to: ${dest_path}`);
46
+ } catch (err) {
47
+ error(`Failed to install skill: ${err.message}`);
48
+ process.exit(1);
49
+ }
50
+ }
51
+ //#endregion
52
+ //#region src/commands/install.cmd.ts
53
+ var install_cmd_default = defineCommand({
54
+ meta: {
55
+ name: "install",
56
+ description: "Install a bundled skill"
57
+ },
58
+ args: {
59
+ skill_name: {
60
+ type: "positional",
61
+ description: "Name of bundled skill",
62
+ required: true
63
+ },
64
+ force: {
65
+ type: "boolean",
66
+ description: "Replace existing skill without prompting"
67
+ }
68
+ },
69
+ run({ args }) {
70
+ install_command({
71
+ skill_name: args.skill_name,
72
+ force: args.force
73
+ });
74
+ }
75
+ });
76
+ //#endregion
77
+ export { install_cmd_default as default };
78
+
79
+ //# sourceMappingURL=install.cmd-CH7yZ92g.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.cmd-CH7yZ92g.js","names":[],"sources":["../src/commands/install.ts","../src/commands/install.cmd.ts"],"sourcesContent":["import { cpSync, existsSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { InstallOptions } from '../types.js';\nimport { ensure_dir } from '../utils/fs.js';\nimport { error, info, success } from '../utils/output.js';\n\n// Get the directory where this module is located (dist/commands/)\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// Bundled skills are in dist/skills/ directory\nconst BUNDLED_SKILLS_DIR = join(__dirname, '..', 'skills');\n\nconst AVAILABLE_SKILLS: string[] = [];\n\nexport function install_command(options: InstallOptions): void {\n\tconst skill_name = options.skill_name;\n\n\t// Validate skill name\n\tif (!skill_name || AVAILABLE_SKILLS.length === 0) {\n\t\tinfo('No bundled skills available');\n\t\tconsole.log(\n\t\t\t'\\nOfficial method: /plugin install <skill>@<marketplace>',\n\t\t);\n\t\tconsole.log('See: https://code.claude.com/docs/en/plugins');\n\t\tconsole.log(\n\t\t\t'\\nFor pre-built skills & activation hooks, see: https://github.com/spences10/claude-code-toolkit',\n\t\t);\n\t\tconsole.log(\n\t\t\t'\\nUse \"claude-skills-cli init\" to create new skills.',\n\t\t);\n\t\tprocess.exit(0);\n\t}\n\n\tif (!AVAILABLE_SKILLS.includes(skill_name)) {\n\t\terror(`Unknown skill: ${skill_name}`);\n\t\tconsole.log('\\nNo bundled skills available.');\n\t\tconsole.log(\n\t\t\t'For pre-built skills & activation hooks, see: https://github.com/spences10/claude-code-toolkit',\n\t\t);\n\t\tprocess.exit(1);\n\t}\n\n\t// Source and destination paths\n\tconst source_path = join(BUNDLED_SKILLS_DIR, skill_name);\n\tconst dest_path = join('.claude', 'skills', skill_name);\n\n\t// Check if source exists in bundle\n\tif (!existsSync(source_path)) {\n\t\terror(`Bundled skill not found: ${skill_name}`);\n\t\tconsole.log(\n\t\t\t`Expected at: ${source_path}\\n\\nThis may be a package installation issue.`,\n\t\t);\n\t\tprocess.exit(1);\n\t}\n\n\t// Check if already installed\n\tif (existsSync(dest_path)) {\n\t\tif (options.force) {\n\t\t\tinfo(\n\t\t\t\t`Skill already exists at ${dest_path}, overwriting (--force)...`,\n\t\t\t);\n\t\t} else {\n\t\t\tinfo(`Skill already installed at: ${dest_path}`);\n\t\t\tconsole.log('\\nUse --force to overwrite the existing skill.');\n\t\t\tprocess.exit(0);\n\t\t}\n\t}\n\n\t// Create destination directory\n\tensure_dir(join('.claude', 'skills'));\n\n\t// Copy skill directory\n\ttry {\n\t\tcpSync(source_path, dest_path, {\n\t\t\trecursive: true,\n\t\t\tforce: options.force || false,\n\t\t});\n\t\tsuccess(`Installed ${skill_name} to: ${dest_path}`);\n\t} catch (err) {\n\t\terror(`Failed to install skill: ${(err as Error).message}`);\n\t\tprocess.exit(1);\n\t}\n}\n","import { defineCommand } from 'citty';\nimport { install_command } from './install.js';\n\nexport default defineCommand({\n\tmeta: { name: 'install', description: 'Install a bundled skill' },\n\targs: {\n\t\tskill_name: {\n\t\t\ttype: 'positional',\n\t\t\tdescription: 'Name of bundled skill',\n\t\t\trequired: true,\n\t\t},\n\t\tforce: {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Replace existing skill without prompting',\n\t\t},\n\t},\n\trun({ args }) {\n\t\tinstall_command({\n\t\t\tskill_name: args.skill_name,\n\t\t\tforce: args.force,\n\t\t});\n\t},\n});\n"],"mappings":";;;;;;;AAYA,MAAM,qBAAqB,KAHT,QADC,cAAc,OAAO,KAAK,IAAI,CACZ,EAGM,MAAM,SAAS;AAE1D,MAAM,mBAA6B,EAAE;AAErC,SAAgB,gBAAgB,SAA+B;CAC9D,MAAM,aAAa,QAAQ;AAG3B,KAAI,CAAC,cAAc,iBAAiB,WAAW,GAAG;AACjD,OAAK,8BAA8B;AACnC,UAAQ,IACP,2DACA;AACD,UAAQ,IAAI,+CAA+C;AAC3D,UAAQ,IACP,mGACA;AACD,UAAQ,IACP,yDACA;AACD,UAAQ,KAAK,EAAE;;AAGhB,KAAI,CAAC,iBAAiB,SAAS,WAAW,EAAE;AAC3C,QAAM,kBAAkB,aAAa;AACrC,UAAQ,IAAI,iCAAiC;AAC7C,UAAQ,IACP,iGACA;AACD,UAAQ,KAAK,EAAE;;CAIhB,MAAM,cAAc,KAAK,oBAAoB,WAAW;CACxD,MAAM,YAAY,KAAK,WAAW,UAAU,WAAW;AAGvD,KAAI,CAAC,WAAW,YAAY,EAAE;AAC7B,QAAM,4BAA4B,aAAa;AAC/C,UAAQ,IACP,gBAAgB,YAAY,+CAC5B;AACD,UAAQ,KAAK,EAAE;;AAIhB,KAAI,WAAW,UAAU,CACxB,KAAI,QAAQ,MACX,MACC,2BAA2B,UAAU,4BACrC;MACK;AACN,OAAK,+BAA+B,YAAY;AAChD,UAAQ,IAAI,iDAAiD;AAC7D,UAAQ,KAAK,EAAE;;AAKjB,YAAW,KAAK,WAAW,SAAS,CAAC;AAGrC,KAAI;AACH,SAAO,aAAa,WAAW;GAC9B,WAAW;GACX,OAAO,QAAQ,SAAS;GACxB,CAAC;AACF,UAAQ,aAAa,WAAW,OAAO,YAAY;UAC3C,KAAK;AACb,QAAM,4BAA6B,IAAc,UAAU;AAC3D,UAAQ,KAAK,EAAE;;;;;AC/EjB,IAAA,sBAAe,cAAc;CAC5B,MAAM;EAAE,MAAM;EAAW,aAAa;EAA2B;CACjE,MAAM;EACL,YAAY;GACX,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,OAAO;GACN,MAAM;GACN,aAAa;GACb;EACD;CACD,IAAI,EAAE,QAAQ;AACb,kBAAgB;GACf,YAAY,KAAK;GACjB,OAAO,KAAK;GACZ,CAAC;;CAEH,CAAC"}
@@ -0,0 +1,102 @@
1
+ //#region src/constants.ts
2
+ /** Token budget for Level 2 content (~5000 words * 1.3) */
3
+ const TOKEN_BUDGET = 6500;
4
+ /**
5
+ * Progressive disclosure limits — three tiers for SKILL.md body
6
+ *
7
+ * strict: opinionated defaults for minimal context usage
8
+ * lenient: relaxed for larger skills
9
+ * loose: matches Anthropic official limits (500 lines)
10
+ */
11
+ const LIMITS = {
12
+ strict: {
13
+ lines: {
14
+ excellent: 30,
15
+ good: 40,
16
+ max: 50
17
+ },
18
+ words: {
19
+ excellent: 300,
20
+ good: 500,
21
+ max: 1e3
22
+ }
23
+ },
24
+ lenient: {
25
+ lines: {
26
+ excellent: 50,
27
+ good: 100,
28
+ max: 150
29
+ },
30
+ words: {
31
+ excellent: 500,
32
+ good: 1e3,
33
+ max: 2e3
34
+ }
35
+ },
36
+ loose: {
37
+ lines: {
38
+ excellent: 100,
39
+ good: 200,
40
+ max: 500
41
+ },
42
+ words: {
43
+ excellent: 1e3,
44
+ good: 2e3,
45
+ max: 5e3
46
+ }
47
+ }
48
+ };
49
+ //#endregion
50
+ //#region src/utils/output.ts
51
+ const success = (msg) => console.log(`✅ ${msg}`);
52
+ const error = (msg) => console.log(`❌ ${msg}`);
53
+ const warning = (msg) => console.log(`⚠️ ${msg}`);
54
+ const info = (msg) => console.log(`📋 ${msg}`);
55
+ const package_ = (msg) => console.log(`📦 ${msg}`);
56
+ const upload = (msg) => console.log(`📤 ${msg}`);
57
+ const search = (msg) => console.log(`🔍 ${msg}`);
58
+ const S = LIMITS.strict;
59
+ /**
60
+ * Display progressive disclosure statistics
61
+ */
62
+ function display_validation_stats(stats) {
63
+ console.log("\n📊 Progressive Disclosure Stats:");
64
+ console.log("\n Level 1 (Metadata - Always Loaded):");
65
+ const desc_status = stats.description_length <= 250 ? "✅ Optimal" : "❌ Too long";
66
+ console.log(` Description: ${stats.description_length} chars, ~${stats.description_tokens} tokens ${desc_status}`);
67
+ console.log(` (Target: <250 chars for Level 1 efficiency)`);
68
+ console.log("\n Level 2 (SKILL.md Body - Loaded when triggered):");
69
+ let line_status;
70
+ if (stats.line_count <= S.lines.excellent) line_status = "✅ Excellent";
71
+ else if (stats.line_count <= S.lines.good) line_status = "✅ Good";
72
+ else if (stats.line_count <= S.lines.max) line_status = "⚠️ Consider splitting";
73
+ else line_status = "❌ Too large";
74
+ console.log(` Lines: ${stats.line_count} (max: ${S.lines.max}) ${line_status}`);
75
+ let word_status;
76
+ if (stats.word_count < S.words.excellent) word_status = "✅ Excellent";
77
+ else if (stats.word_count < S.words.good) word_status = "✅ Good";
78
+ else if (stats.word_count < S.words.max) word_status = "⚠️ Consider splitting";
79
+ else word_status = "❌ Too large";
80
+ console.log(` Words: ${stats.word_count} (max: ${S.words.max}) ${word_status}`);
81
+ const token_status = stats.estimated_tokens < 6500 ? "within budget" : "exceeds budget";
82
+ console.log(` Est. tokens: ~${stats.estimated_tokens} (budget: <${TOKEN_BUDGET}) ${token_status}`);
83
+ const code_status = stats.code_blocks > 3 ? " (recommended: 1-2)" : stats.code_blocks <= 2 ? " ✅" : "";
84
+ console.log(` Code blocks: ${stats.code_blocks}${code_status}`);
85
+ const section_status = stats.sections > 8 ? " (recommended: 3-5)" : stats.sections >= 3 && stats.sections <= 5 ? " ✅" : "";
86
+ console.log(` Sections: ${stats.sections}${section_status}`);
87
+ if (stats.long_paragraphs > 0) {
88
+ const para_status = stats.long_paragraphs > 3 ? " (consider moving to references/)" : "";
89
+ console.log(` Long paragraphs: ${stats.long_paragraphs}${para_status}`);
90
+ }
91
+ console.log("\n Level 3+ (References - Loaded as needed):");
92
+ console.log(" Use references/ directory for detailed docs (unlimited size)");
93
+ console.log("\n Overall Assessment:");
94
+ if (stats.line_count <= S.lines.excellent && stats.description_length <= 250) console.log(" ✅ Excellent progressive disclosure!");
95
+ else if (stats.line_count <= S.lines.max && stats.description_length <= 250) console.log(" ✅ Good progressive disclosure");
96
+ else if (stats.line_count <= LIMITS.lenient.lines.max && stats.word_count < LIMITS.lenient.words.max) console.log(" ⚠️ Consider splitting content into references/");
97
+ else console.log(" ❌ Violates progressive disclosure (move content to references/)");
98
+ }
99
+ //#endregion
100
+ export { search as a, warning as c, package_ as i, LIMITS as l, error as n, success as o, info as r, upload as s, display_validation_stats as t };
101
+
102
+ //# sourceMappingURL=output-Dz8fk6Gu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output-Dz8fk6Gu.js","names":[],"sources":["../src/constants.ts","../src/utils/output.ts"],"sourcesContent":["/**\n * Anthropic skill spec limits\n * https://code.claude.com/docs/en/skills#frontmatter-reference\n */\n\n/** Max chars for skill name field */\nexport const NAME_MAX_LENGTH = 64;\n\n/** Max chars for description — Claude truncates at this limit in skill listing */\nexport const DESCRIPTION_MAX_LENGTH = 250;\n\n/** Min recommended chars for description to be useful */\nexport const DESCRIPTION_MIN_LENGTH = 50;\n\n/** Token budget for Level 2 content (~5000 words * 1.3) */\nexport const TOKEN_BUDGET = 6500;\n\n/** Words per paragraph before it's considered \"long\" */\nexport const LONG_PARAGRAPH_WORDS = 100;\n\n/** Min body length (chars) before warning about short content */\nexport const MIN_BODY_LENGTH = 100;\n\n/**\n * Progressive disclosure limits — three tiers for SKILL.md body\n *\n * strict: opinionated defaults for minimal context usage\n * lenient: relaxed for larger skills\n * loose: matches Anthropic official limits (500 lines)\n */\nexport const LIMITS = {\n\tstrict: {\n\t\tlines: { excellent: 30, good: 40, max: 50 },\n\t\twords: { excellent: 300, good: 500, max: 1000 },\n\t},\n\tlenient: {\n\t\tlines: { excellent: 50, good: 100, max: 150 },\n\t\twords: { excellent: 500, good: 1000, max: 2000 },\n\t},\n\tloose: {\n\t\tlines: { excellent: 100, good: 200, max: 500 },\n\t\twords: { excellent: 1000, good: 2000, max: 5000 },\n\t},\n} as const;\n","import {\n\tDESCRIPTION_MAX_LENGTH,\n\tLIMITS,\n\tTOKEN_BUDGET,\n} from '../constants.js';\nimport type { ValidationStats } from '../types.js';\n\nexport const success = (msg: string) => console.log(`✅ ${msg}`);\nexport const error = (msg: string) => console.log(`❌ ${msg}`);\nexport const warning = (msg: string) => console.log(`⚠️ ${msg}`);\nexport const info = (msg: string) => console.log(`📋 ${msg}`);\nexport const step = (msg: string) => console.log(` ${msg}`);\nexport const package_ = (msg: string) => console.log(`📦 ${msg}`);\nexport const upload = (msg: string) => console.log(`📤 ${msg}`);\nexport const search = (msg: string) => console.log(`🔍 ${msg}`);\n\nconst S = LIMITS.strict;\n\n/**\n * Display progressive disclosure statistics\n */\nexport function display_validation_stats(\n\tstats: ValidationStats,\n): void {\n\tconsole.log('\\n📊 Progressive Disclosure Stats:');\n\n\t// Level 1: Description\n\tconsole.log('\\n Level 1 (Metadata - Always Loaded):');\n\tconst desc_status =\n\t\tstats.description_length <= DESCRIPTION_MAX_LENGTH\n\t\t\t? '✅ Optimal'\n\t\t\t: '❌ Too long';\n\n\tconsole.log(\n\t\t` Description: ${stats.description_length} chars, ~${stats.description_tokens} tokens ${desc_status}`,\n\t);\n\tconsole.log(\n\t\t` (Target: <${DESCRIPTION_MAX_LENGTH} chars for Level 1 efficiency)`,\n\t);\n\n\t// Level 2: SKILL.md Body\n\tconsole.log('\\n Level 2 (SKILL.md Body - Loaded when triggered):');\n\n\t// Line count\n\tlet line_status: string;\n\tif (stats.line_count <= S.lines.excellent) {\n\t\tline_status = '✅ Excellent';\n\t} else if (stats.line_count <= S.lines.good) {\n\t\tline_status = '✅ Good';\n\t} else if (stats.line_count <= S.lines.max) {\n\t\tline_status = '⚠️ Consider splitting';\n\t} else {\n\t\tline_status = '❌ Too large';\n\t}\n\n\tconsole.log(\n\t\t` Lines: ${stats.line_count} (max: ${S.lines.max}) ${line_status}`,\n\t);\n\n\t// Word count\n\tlet word_status: string;\n\tif (stats.word_count < S.words.excellent) {\n\t\tword_status = '✅ Excellent';\n\t} else if (stats.word_count < S.words.good) {\n\t\tword_status = '✅ Good';\n\t} else if (stats.word_count < S.words.max) {\n\t\tword_status = '⚠️ Consider splitting';\n\t} else {\n\t\tword_status = '❌ Too large';\n\t}\n\n\tconsole.log(\n\t\t` Words: ${stats.word_count} (max: ${S.words.max}) ${word_status}`,\n\t);\n\n\t// Token estimation\n\tconst token_status =\n\t\tstats.estimated_tokens < TOKEN_BUDGET\n\t\t\t? 'within budget'\n\t\t\t: 'exceeds budget';\n\n\tconsole.log(\n\t\t` Est. tokens: ~${stats.estimated_tokens} (budget: <${TOKEN_BUDGET}) ${token_status}`,\n\t);\n\n\t// Code blocks\n\tconst code_status =\n\t\tstats.code_blocks > 3\n\t\t\t? ' (recommended: 1-2)'\n\t\t\t: stats.code_blocks <= 2\n\t\t\t\t? ' ✅'\n\t\t\t\t: '';\n\tconsole.log(` Code blocks: ${stats.code_blocks}${code_status}`);\n\n\t// Sections\n\tconst section_status =\n\t\tstats.sections > 8\n\t\t\t? ' (recommended: 3-5)'\n\t\t\t: stats.sections >= 3 && stats.sections <= 5\n\t\t\t\t? ' ✅'\n\t\t\t\t: '';\n\tconsole.log(` Sections: ${stats.sections}${section_status}`);\n\n\t// Long paragraphs\n\tif (stats.long_paragraphs > 0) {\n\t\tconst para_status =\n\t\t\tstats.long_paragraphs > 3\n\t\t\t\t? ' (consider moving to references/)'\n\t\t\t\t: '';\n\t\tconsole.log(\n\t\t\t` Long paragraphs: ${stats.long_paragraphs}${para_status}`,\n\t\t);\n\t}\n\n\t// Level 3 info\n\tconsole.log('\\n Level 3+ (References - Loaded as needed):');\n\tconsole.log(\n\t\t' Use references/ directory for detailed docs (unlimited size)',\n\t);\n\n\t// Overall assessment (based on strict defaults)\n\tconsole.log('\\n Overall Assessment:');\n\tif (\n\t\tstats.line_count <= S.lines.excellent &&\n\t\tstats.description_length <= DESCRIPTION_MAX_LENGTH\n\t) {\n\t\tconsole.log(' ✅ Excellent progressive disclosure!');\n\t} else if (\n\t\tstats.line_count <= S.lines.max &&\n\t\tstats.description_length <= DESCRIPTION_MAX_LENGTH\n\t) {\n\t\tconsole.log(' ✅ Good progressive disclosure');\n\t} else if (\n\t\tstats.line_count <= LIMITS.lenient.lines.max &&\n\t\tstats.word_count < LIMITS.lenient.words.max\n\t) {\n\t\tconsole.log(\n\t\t\t' ⚠️ Consider splitting content into references/',\n\t\t);\n\t} else {\n\t\tconsole.log(\n\t\t\t' ❌ Violates progressive disclosure (move content to references/)',\n\t\t);\n\t}\n}\n"],"mappings":";;AAeA,MAAa,eAAe;;;;;;;;AAe5B,MAAa,SAAS;CACrB,QAAQ;EACP,OAAO;GAAE,WAAW;GAAI,MAAM;GAAI,KAAK;GAAI;EAC3C,OAAO;GAAE,WAAW;GAAK,MAAM;GAAK,KAAK;GAAM;EAC/C;CACD,SAAS;EACR,OAAO;GAAE,WAAW;GAAI,MAAM;GAAK,KAAK;GAAK;EAC7C,OAAO;GAAE,WAAW;GAAK,MAAM;GAAM,KAAK;GAAM;EAChD;CACD,OAAO;EACN,OAAO;GAAE,WAAW;GAAK,MAAM;GAAK,KAAK;GAAK;EAC9C,OAAO;GAAE,WAAW;GAAM,MAAM;GAAM,KAAK;GAAM;EACjD;CACD;;;ACpCD,MAAa,WAAW,QAAgB,QAAQ,IAAI,KAAK,MAAM;AAC/D,MAAa,SAAS,QAAgB,QAAQ,IAAI,KAAK,MAAM;AAC7D,MAAa,WAAW,QAAgB,QAAQ,IAAI,OAAO,MAAM;AACjE,MAAa,QAAQ,QAAgB,QAAQ,IAAI,MAAM,MAAM;AAE7D,MAAa,YAAY,QAAgB,QAAQ,IAAI,MAAM,MAAM;AACjE,MAAa,UAAU,QAAgB,QAAQ,IAAI,MAAM,MAAM;AAC/D,MAAa,UAAU,QAAgB,QAAQ,IAAI,MAAM,MAAM;AAE/D,MAAM,IAAI,OAAO;;;;AAKjB,SAAgB,yBACf,OACO;AACP,SAAQ,IAAI,qCAAqC;AAGjD,SAAQ,IAAI,0CAA0C;CACtD,MAAM,cACL,MAAM,sBAAA,MACH,cACA;AAEJ,SAAQ,IACP,oBAAoB,MAAM,mBAAmB,WAAW,MAAM,mBAAmB,UAAU,cAC3F;AACD,SAAQ,IACP,kDACA;AAGD,SAAQ,IAAI,uDAAuD;CAGnE,IAAI;AACJ,KAAI,MAAM,cAAc,EAAE,MAAM,UAC/B,eAAc;UACJ,MAAM,cAAc,EAAE,MAAM,KACtC,eAAc;UACJ,MAAM,cAAc,EAAE,MAAM,IACtC,eAAc;KAEd,eAAc;AAGf,SAAQ,IACP,cAAc,MAAM,WAAW,SAAS,EAAE,MAAM,IAAI,IAAI,cACxD;CAGD,IAAI;AACJ,KAAI,MAAM,aAAa,EAAE,MAAM,UAC9B,eAAc;UACJ,MAAM,aAAa,EAAE,MAAM,KACrC,eAAc;UACJ,MAAM,aAAa,EAAE,MAAM,IACrC,eAAc;KAEd,eAAc;AAGf,SAAQ,IACP,cAAc,MAAM,WAAW,SAAS,EAAE,MAAM,IAAI,IAAI,cACxD;CAGD,MAAM,eACL,MAAM,mBAAA,OACH,kBACA;AAEJ,SAAQ,IACP,qBAAqB,MAAM,iBAAiB,aAAa,aAAa,IAAI,eAC1E;CAGD,MAAM,cACL,MAAM,cAAc,IACjB,wBACA,MAAM,eAAe,IACpB,OACA;AACL,SAAQ,IAAI,oBAAoB,MAAM,cAAc,cAAc;CAGlE,MAAM,iBACL,MAAM,WAAW,IACd,wBACA,MAAM,YAAY,KAAK,MAAM,YAAY,IACxC,OACA;AACL,SAAQ,IAAI,iBAAiB,MAAM,WAAW,iBAAiB;AAG/D,KAAI,MAAM,kBAAkB,GAAG;EAC9B,MAAM,cACL,MAAM,kBAAkB,IACrB,sCACA;AACJ,UAAQ,IACP,wBAAwB,MAAM,kBAAkB,cAChD;;AAIF,SAAQ,IAAI,gDAAgD;AAC5D,SAAQ,IACP,mEACA;AAGD,SAAQ,IAAI,0BAA0B;AACtC,KACC,MAAM,cAAc,EAAE,MAAM,aAC5B,MAAM,sBAAA,IAEN,SAAQ,IAAI,0CAA0C;UAEtD,MAAM,cAAc,EAAE,MAAM,OAC5B,MAAM,sBAAA,IAEN,SAAQ,IAAI,oCAAoC;UAEhD,MAAM,cAAc,OAAO,QAAQ,MAAM,OACzC,MAAM,aAAa,OAAO,QAAQ,MAAM,IAExC,SAAQ,IACP,sDACA;KAED,SAAQ,IACP,sEACA"}
@@ -0,0 +1,107 @@
1
+ import { t as ensure_dir } from "./fs-CuGv3Ob2.js";
2
+ import { a as search, c as warning, i as package_, n as error, o as success, s as upload } from "./output-Dz8fk6Gu.js";
3
+ import { t as SkillValidator } from "./validator-DV5zeeel.js";
4
+ import { defineCommand } from "citty";
5
+ import { existsSync, statSync } from "node:fs";
6
+ import { basename, join, resolve } from "node:path";
7
+ import { execSync } from "node:child_process";
8
+ //#region src/commands/package.ts
9
+ function validate_skill(skill_path) {
10
+ search("Validating skill...");
11
+ const result = new SkillValidator(skill_path).validate_all();
12
+ if (result.errors.length > 0) {
13
+ console.log("\n❌ Errors:");
14
+ for (const err of result.errors) console.log(` ${String(err)}`);
15
+ }
16
+ if (result.warnings.length > 0) {
17
+ console.log("\n⚠️ Warnings:");
18
+ for (const warn of result.warnings) console.log(` ${warn}`);
19
+ }
20
+ if (result.is_valid) {
21
+ success("Skill is valid!");
22
+ console.log("");
23
+ return true;
24
+ } else {
25
+ error("Validation failed. Fix errors before packaging.");
26
+ return false;
27
+ }
28
+ }
29
+ function package_skill(skill_path, output_dir) {
30
+ const skill_name = basename(skill_path);
31
+ const output_file = resolve(output_dir, `${skill_name}.zip`);
32
+ package_(`Packaging skill: ${skill_name}`);
33
+ ensure_dir(output_dir);
34
+ if (existsSync(output_file)) execSync(`rm ${output_file}`);
35
+ execSync(`cd "${resolve(skill_path, "..")}" && zip -r "${output_file}" "${skill_name}" -x '${skill_name}/.*' '${skill_name}/*.swp' '${skill_name}/*~' '${skill_name}/.DS_Store'`);
36
+ return output_file;
37
+ }
38
+ async function package_command(options) {
39
+ const { skill_path, output, skip_validation } = options;
40
+ if (!existsSync(skill_path)) {
41
+ error(`Skill directory does not exist: ${skill_path}`);
42
+ process.exit(1);
43
+ }
44
+ if (!statSync(skill_path).isDirectory()) {
45
+ error(`Path is not a directory: ${skill_path}`);
46
+ process.exit(1);
47
+ }
48
+ if (!existsSync(join(skill_path, "SKILL.md"))) {
49
+ error(`SKILL.md not found in ${skill_path}`);
50
+ process.exit(1);
51
+ }
52
+ if (!skip_validation) {
53
+ if (!validate_skill(skill_path)) process.exit(1);
54
+ }
55
+ try {
56
+ const output_file = package_skill(skill_path, output || "dist");
57
+ const size_kb = statSync(output_file).size / 1024;
58
+ console.log("");
59
+ success("Skill packaged successfully!");
60
+ console.log(` File: ${output_file}`);
61
+ console.log(` Size: ${size_kb.toFixed(1)} KB`);
62
+ console.log("");
63
+ warning("Note: ZIP packaging is not an official Claude Code distribution method.");
64
+ console.log(" Official distribution uses the plugin system (/plugin install)");
65
+ console.log(" or direct file placement in .claude/skills/.");
66
+ console.log(" See: https://code.claude.com/docs/en/plugins");
67
+ console.log("");
68
+ upload("Upload to Claude.ai: Settings > Features > Skills > Upload");
69
+ } catch (err) {
70
+ error(`Failed to package skill: ${String(err)}`);
71
+ process.exit(1);
72
+ }
73
+ }
74
+ //#endregion
75
+ //#region src/commands/package.cmd.ts
76
+ var package_cmd_default = defineCommand({
77
+ meta: {
78
+ name: "package",
79
+ description: "Package a skill to zip"
80
+ },
81
+ args: {
82
+ skill_path: {
83
+ type: "positional",
84
+ description: "Path to skill directory",
85
+ required: true
86
+ },
87
+ output: {
88
+ type: "string",
89
+ description: "Output path for zip file"
90
+ },
91
+ "skip-validation": {
92
+ type: "boolean",
93
+ description: "Skip validation before packaging"
94
+ }
95
+ },
96
+ async run({ args }) {
97
+ await package_command({
98
+ skill_path: args.skill_path,
99
+ output: args.output,
100
+ skip_validation: args["skip-validation"]
101
+ });
102
+ }
103
+ });
104
+ //#endregion
105
+ export { package_cmd_default as default };
106
+
107
+ //# sourceMappingURL=package.cmd-CwGRHdEq.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package.cmd-CwGRHdEq.js","names":[],"sources":["../src/commands/package.ts","../src/commands/package.cmd.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport { existsSync, statSync } from 'node:fs';\nimport { basename, join, resolve } from 'node:path';\nimport { SkillValidator } from '../core/validator.js';\nimport type { PackageOptions } from '../types.js';\nimport { ensure_dir } from '../utils/fs.js';\nimport {\n\terror,\n\tpackage_,\n\tsearch,\n\tsuccess,\n\tupload,\n\twarning,\n} from '../utils/output.js';\n\nfunction validate_skill(skill_path: string): boolean {\n\tsearch('Validating skill...');\n\n\tconst validator = new SkillValidator(skill_path);\n\tconst result = validator.validate_all();\n\n\tif (result.errors.length > 0) {\n\t\tconsole.log('\\n❌ Errors:');\n\t\tfor (const err of result.errors) {\n\t\t\tconsole.log(` ${String(err)}`);\n\t\t}\n\t}\n\n\tif (result.warnings.length > 0) {\n\t\tconsole.log('\\n⚠️ Warnings:');\n\t\tfor (const warn of result.warnings) {\n\t\t\tconsole.log(` ${warn}`);\n\t\t}\n\t}\n\n\tif (result.is_valid) {\n\t\tsuccess('Skill is valid!');\n\t\tconsole.log('');\n\t\treturn true;\n\t} else {\n\t\terror('Validation failed. Fix errors before packaging.');\n\t\treturn false;\n\t}\n}\n\nfunction package_skill(\n\tskill_path: string,\n\toutput_dir: string,\n): string {\n\tconst skill_name = basename(skill_path);\n\tconst output_file = resolve(output_dir, `${skill_name}.zip`);\n\n\tpackage_(`Packaging skill: ${skill_name}`);\n\n\tensure_dir(output_dir);\n\n\t// Remove existing zip if present\n\tif (existsSync(output_file)) {\n\t\texecSync(`rm ${output_file}`);\n\t}\n\n\t// Use system zip command — available on all target platforms\n\tconst parent_dir = resolve(skill_path, '..');\n\texecSync(\n\t\t`cd \"${parent_dir}\" && zip -r \"${output_file}\" \"${skill_name}\" -x '${skill_name}/.*' '${skill_name}/*.swp' '${skill_name}/*~' '${skill_name}/.DS_Store'`,\n\t);\n\n\treturn output_file;\n}\n\nexport async function package_command(\n\toptions: PackageOptions,\n): Promise<void> {\n\tconst { skill_path, output, skip_validation } = options;\n\n\t// Validate path\n\tif (!existsSync(skill_path)) {\n\t\terror(`Skill directory does not exist: ${skill_path}`);\n\t\tprocess.exit(1);\n\t}\n\n\tconst stats = statSync(skill_path);\n\tif (!stats.isDirectory()) {\n\t\terror(`Path is not a directory: ${skill_path}`);\n\t\tprocess.exit(1);\n\t}\n\n\t// Check for SKILL.md\n\tif (!existsSync(join(skill_path, 'SKILL.md'))) {\n\t\terror(`SKILL.md not found in ${skill_path}`);\n\t\tprocess.exit(1);\n\t}\n\n\t// Validate skill\n\tif (!skip_validation) {\n\t\tif (!validate_skill(skill_path)) {\n\t\t\tprocess.exit(1);\n\t\t}\n\t}\n\n\t// Package skill\n\ttry {\n\t\tconst output_dir = output || 'dist';\n\t\tconst output_file = package_skill(skill_path, output_dir);\n\n\t\t// Print success\n\t\tconst file_stats = statSync(output_file);\n\t\tconst size_kb = file_stats.size / 1024;\n\n\t\tconsole.log('');\n\t\tsuccess('Skill packaged successfully!');\n\t\tconsole.log(` File: ${output_file}`);\n\t\tconsole.log(` Size: ${size_kb.toFixed(1)} KB`);\n\t\tconsole.log('');\n\t\twarning(\n\t\t\t'Note: ZIP packaging is not an official Claude Code distribution method.',\n\t\t);\n\t\tconsole.log(\n\t\t\t' Official distribution uses the plugin system (/plugin install)',\n\t\t);\n\t\tconsole.log(' or direct file placement in .claude/skills/.');\n\t\tconsole.log(' See: https://code.claude.com/docs/en/plugins');\n\t\tconsole.log('');\n\t\tupload(\n\t\t\t'Upload to Claude.ai: Settings > Features > Skills > Upload',\n\t\t);\n\t} catch (err) {\n\t\terror(`Failed to package skill: ${String(err)}`);\n\t\tprocess.exit(1);\n\t}\n}\n","import { defineCommand } from 'citty';\nimport { package_command } from './package.js';\n\nexport default defineCommand({\n\tmeta: { name: 'package', description: 'Package a skill to zip' },\n\targs: {\n\t\tskill_path: {\n\t\t\ttype: 'positional',\n\t\t\tdescription: 'Path to skill directory',\n\t\t\trequired: true,\n\t\t},\n\t\toutput: {\n\t\t\ttype: 'string',\n\t\t\tdescription: 'Output path for zip file',\n\t\t},\n\t\t'skip-validation': {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Skip validation before packaging',\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tawait package_command({\n\t\t\tskill_path: args.skill_path,\n\t\t\toutput: args.output,\n\t\t\tskip_validation: args['skip-validation'],\n\t\t});\n\t},\n});\n"],"mappings":";;;;;;;;AAeA,SAAS,eAAe,YAA6B;AACpD,QAAO,sBAAsB;CAG7B,MAAM,SADY,IAAI,eAAe,WAAW,CACvB,cAAc;AAEvC,KAAI,OAAO,OAAO,SAAS,GAAG;AAC7B,UAAQ,IAAI,cAAc;AAC1B,OAAK,MAAM,OAAO,OAAO,OACxB,SAAQ,IAAI,KAAK,OAAO,IAAI,GAAG;;AAIjC,KAAI,OAAO,SAAS,SAAS,GAAG;AAC/B,UAAQ,IAAI,kBAAkB;AAC9B,OAAK,MAAM,QAAQ,OAAO,SACzB,SAAQ,IAAI,KAAK,OAAO;;AAI1B,KAAI,OAAO,UAAU;AACpB,UAAQ,kBAAkB;AAC1B,UAAQ,IAAI,GAAG;AACf,SAAO;QACD;AACN,QAAM,kDAAkD;AACxD,SAAO;;;AAIT,SAAS,cACR,YACA,YACS;CACT,MAAM,aAAa,SAAS,WAAW;CACvC,MAAM,cAAc,QAAQ,YAAY,GAAG,WAAW,MAAM;AAE5D,UAAS,oBAAoB,aAAa;AAE1C,YAAW,WAAW;AAGtB,KAAI,WAAW,YAAY,CAC1B,UAAS,MAAM,cAAc;AAK9B,UACC,OAFkB,QAAQ,YAAY,KAAK,CAEzB,eAAe,YAAY,KAAK,WAAW,QAAQ,WAAW,QAAQ,WAAW,WAAW,WAAW,QAAQ,WAAW,aAC5I;AAED,QAAO;;AAGR,eAAsB,gBACrB,SACgB;CAChB,MAAM,EAAE,YAAY,QAAQ,oBAAoB;AAGhD,KAAI,CAAC,WAAW,WAAW,EAAE;AAC5B,QAAM,mCAAmC,aAAa;AACtD,UAAQ,KAAK,EAAE;;AAIhB,KAAI,CADU,SAAS,WAAW,CACvB,aAAa,EAAE;AACzB,QAAM,4BAA4B,aAAa;AAC/C,UAAQ,KAAK,EAAE;;AAIhB,KAAI,CAAC,WAAW,KAAK,YAAY,WAAW,CAAC,EAAE;AAC9C,QAAM,yBAAyB,aAAa;AAC5C,UAAQ,KAAK,EAAE;;AAIhB,KAAI,CAAC;MACA,CAAC,eAAe,WAAW,CAC9B,SAAQ,KAAK,EAAE;;AAKjB,KAAI;EAEH,MAAM,cAAc,cAAc,YADf,UAAU,OAC4B;EAIzD,MAAM,UADa,SAAS,YAAY,CACb,OAAO;AAElC,UAAQ,IAAI,GAAG;AACf,UAAQ,+BAA+B;AACvC,UAAQ,IAAI,YAAY,cAAc;AACtC,UAAQ,IAAI,YAAY,QAAQ,QAAQ,EAAE,CAAC,KAAK;AAChD,UAAQ,IAAI,GAAG;AACf,UACC,0EACA;AACD,UAAQ,IACP,oEACA;AACD,UAAQ,IAAI,kDAAkD;AAC9D,UAAQ,IAAI,kDAAkD;AAC9D,UAAQ,IAAI,GAAG;AACf,SACC,6DACA;UACO,KAAK;AACb,QAAM,4BAA4B,OAAO,IAAI,GAAG;AAChD,UAAQ,KAAK,EAAE;;;;;AC7HjB,IAAA,sBAAe,cAAc;CAC5B,MAAM;EAAE,MAAM;EAAW,aAAa;EAA0B;CAChE,MAAM;EACL,YAAY;GACX,MAAM;GACN,aAAa;GACb,UAAU;GACV;EACD,QAAQ;GACP,MAAM;GACN,aAAa;GACb;EACD,mBAAmB;GAClB,MAAM;GACN,aAAa;GACb;EACD;CACD,MAAM,IAAI,EAAE,QAAQ;AACnB,QAAM,gBAAgB;GACrB,YAAY,KAAK;GACjB,QAAQ,KAAK;GACb,iBAAiB,KAAK;GACtB,CAAC;;CAEH,CAAC"}
@@ -0,0 +1,121 @@
1
+ import { l as LIMITS, n as error } from "./output-Dz8fk6Gu.js";
2
+ import { t as SkillValidator } from "./validator-DV5zeeel.js";
3
+ import { defineCommand } from "citty";
4
+ import { existsSync, readdirSync, statSync } from "node:fs";
5
+ import { join } from "node:path";
6
+ //#region src/commands/stats.ts
7
+ function stats_command(options) {
8
+ const directory = options.directory || ".claude/skills";
9
+ if (!existsSync(directory)) {
10
+ error(`Directory not found: ${directory}`);
11
+ process.exit(1);
12
+ }
13
+ if (!statSync(directory).isDirectory()) {
14
+ error(`Path is not a directory: ${directory}`);
15
+ process.exit(1);
16
+ }
17
+ const entries = readdirSync(directory);
18
+ const skills = [];
19
+ for (const entry of entries) {
20
+ const skill_path = join(directory, entry);
21
+ if (statSync(skill_path).isDirectory()) {
22
+ if (existsSync(join(skill_path, "SKILL.md"))) skills.push(skill_path);
23
+ }
24
+ }
25
+ if (skills.length === 0) {
26
+ console.log(`No skills found in ${directory}`);
27
+ console.log("\nCreate a skill with: claude-skills-cli init --name my-skill --description \"...\"\n");
28
+ return;
29
+ }
30
+ console.log("📊 Skills Overview");
31
+ console.log("============================================================");
32
+ console.log(`${skills.length} skill${skills.length === 1 ? "" : "s"} found:\n`);
33
+ for (const skill_path of skills) {
34
+ const skill_name = skill_path.split("/").pop() || "";
35
+ const result = new SkillValidator(skill_path).validate_all();
36
+ let status_icon = "✅";
37
+ let status_text = "valid";
38
+ if (!result.is_valid) {
39
+ status_icon = "❌";
40
+ status_text = "errors";
41
+ } else if (result.warnings.length > 0) {
42
+ status_icon = "⚠️ ";
43
+ status_text = "warnings";
44
+ }
45
+ console.log(`${skill_name} (${status_icon} ${status_text})`);
46
+ if (result.stats) {
47
+ const desc_length = result.stats.description_length;
48
+ let desc_status = "";
49
+ if (desc_length > 0) {
50
+ if (desc_length <= 250) desc_status = "optimal";
51
+ else desc_status = "too long";
52
+ console.log(` Description: ${desc_length} chars (${desc_status})`);
53
+ }
54
+ const lines = result.stats.line_count;
55
+ const words = result.stats.word_count;
56
+ const S = LIMITS.strict;
57
+ let line_status = "";
58
+ if (lines <= S.lines.excellent) line_status = "excellent";
59
+ else if (lines <= S.lines.good) line_status = "good";
60
+ else if (lines <= S.lines.max) line_status = "consider splitting";
61
+ else line_status = "too long";
62
+ let word_status = "";
63
+ if (words < S.words.excellent) word_status = "excellent";
64
+ else if (words < S.words.good) word_status = "good";
65
+ else if (words < S.words.max) word_status = "acceptable";
66
+ else word_status = "too long";
67
+ console.log(` Body: ${lines} lines (${line_status}), ${words} words (${word_status})`);
68
+ const references_dir = join(skill_path, "references");
69
+ if (existsSync(references_dir)) {
70
+ const ref_files = readdirSync(references_dir).filter((f) => f.endsWith(".md"));
71
+ if (ref_files.length > 0) {
72
+ let total_size = 0;
73
+ for (const ref_file of ref_files) {
74
+ const ref_stat = statSync(join(references_dir, ref_file));
75
+ total_size += ref_stat.size;
76
+ }
77
+ const size_kb = (total_size / 1024).toFixed(1);
78
+ console.log(` References: ${ref_files.length} file${ref_files.length === 1 ? "" : "s"} (${size_kb} KB)`);
79
+ }
80
+ }
81
+ }
82
+ if (!result.is_valid) console.log(` ${result.errors.length} error${result.errors.length === 1 ? "" : "s"}`);
83
+ if (result.warnings.length > 0) console.log(` ${result.warnings.length} warning${result.warnings.length === 1 ? "" : "s"}`);
84
+ console.log("");
85
+ }
86
+ const valid_skills = skills.filter((path) => {
87
+ return new SkillValidator(path).validate_all().is_valid;
88
+ }).length;
89
+ const skills_with_warnings = skills.filter((path) => {
90
+ const result = new SkillValidator(path).validate_all();
91
+ return result.is_valid && result.warnings.length > 0;
92
+ }).length;
93
+ const invalid_skills = skills.length - valid_skills;
94
+ console.log("Summary:");
95
+ if (invalid_skills === 0 && skills_with_warnings === 0) console.log(`✅ All ${skills.length} skills are valid with no warnings`);
96
+ else {
97
+ console.log(` Valid: ${valid_skills}`);
98
+ if (skills_with_warnings > 0) console.log(` With warnings: ${skills_with_warnings}`);
99
+ if (invalid_skills > 0) console.log(` Invalid: ${invalid_skills}`);
100
+ }
101
+ }
102
+ //#endregion
103
+ //#region src/commands/stats.cmd.ts
104
+ var stats_cmd_default = defineCommand({
105
+ meta: {
106
+ name: "stats",
107
+ description: "Show overview of all skills in a directory"
108
+ },
109
+ args: { directory: {
110
+ type: "positional",
111
+ description: "Directory containing skills (default: .claude/skills)",
112
+ required: false
113
+ } },
114
+ run({ args }) {
115
+ stats_command({ directory: args.directory });
116
+ }
117
+ });
118
+ //#endregion
119
+ export { stats_cmd_default as default };
120
+
121
+ //# sourceMappingURL=stats.cmd-D1ujNiDO.js.map