outclaw 0.1.0

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.
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,952 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/cli.ts
4
+ import { Command } from "commander";
5
+
6
+ // src/commands/init.ts
7
+ import { input, checkbox, confirm } from "@inquirer/prompts";
8
+
9
+ // src/core/skill-manager.ts
10
+ import * as fs3 from "fs/promises";
11
+ import * as path3 from "path";
12
+
13
+ // src/parsers/skill-parser.ts
14
+ import * as fs from "fs/promises";
15
+ import * as path from "path";
16
+ import matter from "gray-matter";
17
+
18
+ // src/schemas/skill.schema.ts
19
+ import { z } from "zod";
20
+ var SkillFrontmatterSchema = z.object({
21
+ name: z.string().min(1, "Name is required").regex(/^[a-z0-9-]+$/, "Name must be lowercase alphanumeric with hyphens"),
22
+ description: z.string().min(10, "Description should be detailed for good triggering"),
23
+ version: z.string().regex(/^\d+\.\d+\.\d+$/, "Version must be semver format").optional(),
24
+ "disable-model-invocation": z.boolean().optional().default(false),
25
+ "user-invocable": z.boolean().optional().default(true),
26
+ "allowed-tools": z.union([z.string(), z.array(z.string())]).optional().transform((val) => {
27
+ if (typeof val === "string") {
28
+ return val.split(",").map((t) => t.trim());
29
+ }
30
+ return val;
31
+ }),
32
+ "argument-hint": z.string().optional(),
33
+ model: z.string().optional(),
34
+ context: z.enum(["normal", "fork"]).optional(),
35
+ agent: z.string().optional(),
36
+ license: z.string().optional(),
37
+ author: z.union([
38
+ z.string(),
39
+ z.object({
40
+ name: z.string(),
41
+ email: z.string().email().optional(),
42
+ url: z.string().url().optional()
43
+ })
44
+ ]).optional(),
45
+ keywords: z.array(z.string()).optional(),
46
+ repository: z.string().optional()
47
+ });
48
+ var SkillSchema = SkillFrontmatterSchema.extend({
49
+ content: z.string().min(1, "Skill content is required"),
50
+ path: z.string()
51
+ });
52
+
53
+ // src/parsers/skill-parser.ts
54
+ var SkillParser = class {
55
+ basePath;
56
+ constructor(basePath) {
57
+ this.basePath = basePath;
58
+ }
59
+ /**
60
+ * Parse SKILL.md and return the full skill object
61
+ */
62
+ async parse() {
63
+ const skillMdPath = path.join(this.basePath, "SKILL.md");
64
+ const content = await fs.readFile(skillMdPath, "utf-8");
65
+ const { data, content: body } = matter(content);
66
+ const frontmatter = SkillFrontmatterSchema.parse(data);
67
+ return {
68
+ ...frontmatter,
69
+ content: body.trim(),
70
+ path: this.basePath
71
+ };
72
+ }
73
+ /**
74
+ * Parse only the frontmatter without validating
75
+ */
76
+ async parseFrontmatter() {
77
+ const skillMdPath = path.join(this.basePath, "SKILL.md");
78
+ const content = await fs.readFile(skillMdPath, "utf-8");
79
+ const { data } = matter(content);
80
+ return SkillFrontmatterSchema.parse(data);
81
+ }
82
+ /**
83
+ * Get the structure of the skill directory
84
+ */
85
+ async getStructure() {
86
+ const structure = {
87
+ hasSkillMd: false,
88
+ hasReferences: false,
89
+ hasScripts: false,
90
+ hasExamples: false,
91
+ files: []
92
+ };
93
+ try {
94
+ const entries = await fs.readdir(this.basePath, { withFileTypes: true });
95
+ for (const entry of entries) {
96
+ if (entry.isFile() && entry.name === "SKILL.md") {
97
+ structure.hasSkillMd = true;
98
+ } else if (entry.isDirectory()) {
99
+ switch (entry.name) {
100
+ case "references":
101
+ structure.hasReferences = true;
102
+ break;
103
+ case "scripts":
104
+ structure.hasScripts = true;
105
+ break;
106
+ case "examples":
107
+ structure.hasExamples = true;
108
+ break;
109
+ }
110
+ }
111
+ structure.files.push(entry.name);
112
+ }
113
+ } catch {
114
+ }
115
+ return structure;
116
+ }
117
+ /**
118
+ * Check if a valid skill exists at this path
119
+ */
120
+ async isValid() {
121
+ try {
122
+ await this.parse();
123
+ return true;
124
+ } catch {
125
+ return false;
126
+ }
127
+ }
128
+ };
129
+ function generateSkillMd(frontmatter, body) {
130
+ const yamlLines = [];
131
+ if (frontmatter.name) {
132
+ yamlLines.push(`name: ${frontmatter.name}`);
133
+ }
134
+ if (frontmatter.description) {
135
+ yamlLines.push(`description: ${frontmatter.description}`);
136
+ }
137
+ if (frontmatter.version) {
138
+ yamlLines.push(`version: ${frontmatter.version}`);
139
+ }
140
+ if (frontmatter["disable-model-invocation"] !== void 0) {
141
+ yamlLines.push(`disable-model-invocation: ${frontmatter["disable-model-invocation"]}`);
142
+ }
143
+ if (frontmatter["user-invocable"] !== void 0) {
144
+ yamlLines.push(`user-invocable: ${frontmatter["user-invocable"]}`);
145
+ }
146
+ if (frontmatter["allowed-tools"]?.length) {
147
+ const tools = Array.isArray(frontmatter["allowed-tools"]) ? frontmatter["allowed-tools"].join(", ") : frontmatter["allowed-tools"];
148
+ yamlLines.push(`allowed-tools: ${tools}`);
149
+ }
150
+ if (frontmatter["argument-hint"]) {
151
+ yamlLines.push(`argument-hint: ${frontmatter["argument-hint"]}`);
152
+ }
153
+ if (frontmatter.model) {
154
+ yamlLines.push(`model: ${frontmatter.model}`);
155
+ }
156
+ if (frontmatter.context) {
157
+ yamlLines.push(`context: ${frontmatter.context}`);
158
+ }
159
+ if (frontmatter.agent) {
160
+ yamlLines.push(`agent: ${frontmatter.agent}`);
161
+ }
162
+ return `---
163
+ ${yamlLines.join("\n")}
164
+ ---
165
+
166
+ ${body}
167
+ `;
168
+ }
169
+
170
+ // src/utils/paths.ts
171
+ import * as path2 from "path";
172
+ import * as os from "os";
173
+ import * as fs2 from "fs/promises";
174
+ function getSkillsPath(scope) {
175
+ if (scope === "global") {
176
+ return path2.join(os.homedir(), ".claude", "skills");
177
+ }
178
+ return path2.join(process.cwd(), ".claude", "skills");
179
+ }
180
+ function getManifestPath(scope) {
181
+ const skillsPath = getSkillsPath(scope);
182
+ return path2.join(skillsPath, ".outclaw-manifest.json");
183
+ }
184
+ function getSkillPath(skillName, scope) {
185
+ return path2.join(getSkillsPath(scope), skillName);
186
+ }
187
+ async function ensureDir(dirPath) {
188
+ await fs2.mkdir(dirPath, { recursive: true });
189
+ }
190
+ async function pathExists(filePath) {
191
+ try {
192
+ await fs2.access(filePath);
193
+ return true;
194
+ } catch {
195
+ return false;
196
+ }
197
+ }
198
+
199
+ // src/core/skill-manager.ts
200
+ var SkillManager = class {
201
+ scope;
202
+ basePath;
203
+ constructor(scope = "project") {
204
+ this.scope = scope;
205
+ this.basePath = getSkillsPath(scope);
206
+ }
207
+ /**
208
+ * List all installed skills
209
+ */
210
+ async listSkills() {
211
+ const skills = [];
212
+ try {
213
+ const dirs = await fs3.readdir(this.basePath);
214
+ for (const dir of dirs) {
215
+ if (dir.startsWith(".")) continue;
216
+ const skillPath = path3.join(this.basePath, dir);
217
+ const stat2 = await fs3.stat(skillPath);
218
+ if (stat2.isDirectory()) {
219
+ try {
220
+ const parser = new SkillParser(skillPath);
221
+ const skill = await parser.parse();
222
+ skills.push({ ...skill, scope: this.scope });
223
+ } catch {
224
+ }
225
+ }
226
+ }
227
+ } catch {
228
+ }
229
+ return skills;
230
+ }
231
+ /**
232
+ * Get a specific skill by name
233
+ */
234
+ async getSkill(name) {
235
+ const skillPath = getSkillPath(name, this.scope);
236
+ try {
237
+ const parser = new SkillParser(skillPath);
238
+ const skill = await parser.parse();
239
+ return { ...skill, scope: this.scope };
240
+ } catch {
241
+ return null;
242
+ }
243
+ }
244
+ /**
245
+ * Check if a skill exists
246
+ */
247
+ async skillExists(name) {
248
+ const skillPath = getSkillPath(name, this.scope);
249
+ return await pathExists(path3.join(skillPath, "SKILL.md"));
250
+ }
251
+ /**
252
+ * Create a new skill
253
+ */
254
+ async createSkill(options) {
255
+ const skillPath = getSkillPath(options.name, options.scope);
256
+ if (await pathExists(skillPath)) {
257
+ throw new Error(`Skill "${options.name}" already exists at ${skillPath}`);
258
+ }
259
+ await ensureDir(skillPath);
260
+ const frontmatter = {
261
+ name: options.name,
262
+ description: options.description,
263
+ version: options.version || "1.0.0"
264
+ };
265
+ if (options.disableModelInvocation !== void 0) {
266
+ frontmatter["disable-model-invocation"] = options.disableModelInvocation;
267
+ }
268
+ if (options.userInvocable !== void 0) {
269
+ frontmatter["user-invocable"] = options.userInvocable;
270
+ }
271
+ if (options.allowedTools?.length) {
272
+ frontmatter["allowed-tools"] = options.allowedTools;
273
+ }
274
+ if (options.argumentHint) {
275
+ frontmatter["argument-hint"] = options.argumentHint;
276
+ }
277
+ if (options.model) {
278
+ frontmatter.model = options.model;
279
+ }
280
+ if (options.context) {
281
+ frontmatter.context = options.context;
282
+ }
283
+ if (options.agent) {
284
+ frontmatter.agent = options.agent;
285
+ }
286
+ const content = options.content || `# ${options.name}
287
+
288
+ Your skill instructions here...
289
+ `;
290
+ const skillMdContent = generateSkillMd(frontmatter, content);
291
+ await fs3.writeFile(path3.join(skillPath, "SKILL.md"), skillMdContent, "utf-8");
292
+ return skillPath;
293
+ }
294
+ /**
295
+ * Install a skill from content
296
+ */
297
+ async installSkill(name, skillMdContent, options) {
298
+ const skillPath = getSkillPath(name, this.scope);
299
+ if (!options.force && await pathExists(skillPath)) {
300
+ throw new Error(`Skill "${name}" already exists. Use --force to overwrite.`);
301
+ }
302
+ await ensureDir(skillPath);
303
+ await fs3.writeFile(path3.join(skillPath, "SKILL.md"), skillMdContent, "utf-8");
304
+ await this.updateManifest(name, options.source);
305
+ return skillPath;
306
+ }
307
+ /**
308
+ * Uninstall a skill
309
+ */
310
+ async uninstallSkill(name) {
311
+ const skillPath = getSkillPath(name, this.scope);
312
+ if (!await pathExists(skillPath)) {
313
+ throw new Error(`Skill "${name}" not found`);
314
+ }
315
+ await fs3.rm(skillPath, { recursive: true, force: true });
316
+ await this.removeFromManifest(name);
317
+ }
318
+ /**
319
+ * Get manifest
320
+ */
321
+ async getManifest() {
322
+ const manifestPath = getManifestPath(this.scope);
323
+ try {
324
+ const content = await fs3.readFile(manifestPath, "utf-8");
325
+ return JSON.parse(content);
326
+ } catch {
327
+ return { version: 1, skills: [] };
328
+ }
329
+ }
330
+ /**
331
+ * Update manifest with new skill
332
+ */
333
+ async updateManifest(name, source) {
334
+ const manifestPath = getManifestPath(this.scope);
335
+ const manifest = await this.getManifest();
336
+ const entry = {
337
+ name,
338
+ version: "1.0.0",
339
+ installedAt: (/* @__PURE__ */ new Date()).toISOString(),
340
+ source,
341
+ scope: this.scope
342
+ };
343
+ const index = manifest.skills.findIndex((s) => s.name === name);
344
+ if (index >= 0) {
345
+ manifest.skills[index] = entry;
346
+ } else {
347
+ manifest.skills.push(entry);
348
+ }
349
+ await ensureDir(path3.dirname(manifestPath));
350
+ await fs3.writeFile(manifestPath, JSON.stringify(manifest, null, 2));
351
+ }
352
+ /**
353
+ * Remove skill from manifest
354
+ */
355
+ async removeFromManifest(name) {
356
+ const manifestPath = getManifestPath(this.scope);
357
+ try {
358
+ const content = await fs3.readFile(manifestPath, "utf-8");
359
+ const manifest = JSON.parse(content);
360
+ manifest.skills = manifest.skills.filter((s) => s.name !== name);
361
+ await fs3.writeFile(manifestPath, JSON.stringify(manifest, null, 2));
362
+ } catch {
363
+ }
364
+ }
365
+ };
366
+
367
+ // src/ui/logger.ts
368
+ import chalk from "chalk";
369
+ var logger = {
370
+ info: (message) => {
371
+ console.log(message);
372
+ },
373
+ success: (message) => {
374
+ console.log(chalk.green("\u2713"), message);
375
+ },
376
+ error: (message) => {
377
+ console.error(chalk.red("\u2717"), message);
378
+ },
379
+ warn: (message) => {
380
+ console.log(chalk.yellow("\u26A0"), message);
381
+ },
382
+ dim: (message) => {
383
+ console.log(chalk.dim(message));
384
+ },
385
+ skill: (info) => {
386
+ console.log();
387
+ console.log(chalk.bold.cyan(info.name));
388
+ console.log(chalk.dim(info.description));
389
+ if (info.author) {
390
+ console.log(chalk.dim(`by ${info.author}`));
391
+ }
392
+ if (info.installCmd) {
393
+ console.log(chalk.dim(`$ ${info.installCmd}`));
394
+ }
395
+ },
396
+ box: (title, content) => {
397
+ const lines = content.split("\n");
398
+ const maxLen = Math.max(title.length, ...lines.map((l) => l.length));
399
+ const border = "\u2500".repeat(maxLen + 2);
400
+ console.log(`\u250C${border}\u2510`);
401
+ console.log(`\u2502 ${chalk.bold(title.padEnd(maxLen))} \u2502`);
402
+ console.log(`\u251C${border}\u2524`);
403
+ for (const line of lines) {
404
+ console.log(`\u2502 ${line.padEnd(maxLen)} \u2502`);
405
+ }
406
+ console.log(`\u2514${border}\u2518`);
407
+ }
408
+ };
409
+
410
+ // src/commands/init.ts
411
+ var AVAILABLE_TOOLS = [
412
+ { name: "Read - Read files", value: "Read" },
413
+ { name: "Write - Write files", value: "Write" },
414
+ { name: "Edit - Edit files", value: "Edit" },
415
+ { name: "Grep - Search file contents", value: "Grep" },
416
+ { name: "Glob - Find files by pattern", value: "Glob" },
417
+ { name: "Bash - Execute shell commands", value: "Bash" },
418
+ { name: "WebFetch - Fetch web content", value: "WebFetch" },
419
+ { name: "WebSearch - Search the web", value: "WebSearch" }
420
+ ];
421
+ async function initCommand(options) {
422
+ try {
423
+ const scope = options.global ? "global" : "project";
424
+ let name = options.name;
425
+ if (!name) {
426
+ name = await input({
427
+ message: "Skill name:",
428
+ validate: (value) => {
429
+ if (!value) return "Name is required";
430
+ if (!/^[a-z0-9-]+$/.test(value)) {
431
+ return "Name must be lowercase alphanumeric with hyphens (e.g., my-skill)";
432
+ }
433
+ return true;
434
+ }
435
+ });
436
+ }
437
+ const manager = new SkillManager(scope);
438
+ if (await manager.skillExists(name)) {
439
+ logger.error(`Skill "${name}" already exists`);
440
+ process.exit(1);
441
+ }
442
+ let description;
443
+ let userInvocable = true;
444
+ let disableModelInvocation = false;
445
+ let allowedTools = [];
446
+ let argumentHint;
447
+ let context;
448
+ if (options.yes) {
449
+ description = `${name} skill for Claude Code`;
450
+ } else {
451
+ description = await input({
452
+ message: "Description (for trigger matching):",
453
+ validate: (value) => {
454
+ if (!value || value.length < 10) {
455
+ return "Description should be at least 10 characters for good trigger matching";
456
+ }
457
+ return true;
458
+ }
459
+ });
460
+ userInvocable = await confirm({
461
+ message: "User-invocable (can be called via /skill-name)?",
462
+ default: true
463
+ });
464
+ disableModelInvocation = await confirm({
465
+ message: "Disable automatic model invocation (only manual trigger)?",
466
+ default: false
467
+ });
468
+ allowedTools = await checkbox({
469
+ message: "Select allowed tools (tools that can be used without permission):",
470
+ choices: AVAILABLE_TOOLS
471
+ });
472
+ const wantsArgs = await confirm({
473
+ message: "Does this skill accept arguments?",
474
+ default: false
475
+ });
476
+ if (wantsArgs) {
477
+ argumentHint = await input({
478
+ message: "Argument hint (e.g., [file-path] [options]):"
479
+ });
480
+ }
481
+ const runInSubagent = await confirm({
482
+ message: "Run in isolated subagent context?",
483
+ default: false
484
+ });
485
+ if (runInSubagent) {
486
+ context = "fork";
487
+ }
488
+ }
489
+ const skillPath = await manager.createSkill({
490
+ name,
491
+ description,
492
+ scope,
493
+ userInvocable,
494
+ disableModelInvocation,
495
+ allowedTools,
496
+ argumentHint,
497
+ context
498
+ });
499
+ logger.success(`Skill created at: ${skillPath}`);
500
+ logger.info("");
501
+ logger.info("Next steps:");
502
+ logger.dim(` 1. Edit ${skillPath}/SKILL.md to add your skill instructions`);
503
+ logger.dim(` 2. Use /${name} in Claude Code to invoke your skill`);
504
+ logger.info("");
505
+ } catch (error) {
506
+ if (error instanceof Error) {
507
+ logger.error(error.message);
508
+ } else {
509
+ logger.error("An unexpected error occurred");
510
+ }
511
+ process.exit(1);
512
+ }
513
+ }
514
+
515
+ // src/ui/table.ts
516
+ import Table from "cli-table3";
517
+ import chalk2 from "chalk";
518
+ function renderTable(options) {
519
+ const table = new Table({
520
+ head: options.headers.map((h) => chalk2.bold.cyan(h)),
521
+ style: {
522
+ head: [],
523
+ border: []
524
+ }
525
+ });
526
+ for (const row of options.rows) {
527
+ table.push(row);
528
+ }
529
+ console.log(table.toString());
530
+ }
531
+
532
+ // src/commands/list.ts
533
+ async function listCommand(options) {
534
+ try {
535
+ const scopes = [];
536
+ if (options.global) {
537
+ scopes.push("global");
538
+ } else if (options.project) {
539
+ scopes.push("project");
540
+ } else {
541
+ scopes.push("global", "project");
542
+ }
543
+ const allSkills = [];
544
+ for (const scope of scopes) {
545
+ const manager = new SkillManager(scope);
546
+ const skills = await manager.listSkills();
547
+ allSkills.push(...skills);
548
+ }
549
+ if (allSkills.length === 0) {
550
+ logger.info("No skills installed.");
551
+ logger.info("");
552
+ logger.dim("Install skills with: outclaw install <skill>");
553
+ logger.dim("Create a new skill with: outclaw init");
554
+ return;
555
+ }
556
+ if (options.json) {
557
+ console.log(JSON.stringify(allSkills, null, 2));
558
+ return;
559
+ }
560
+ logger.info(`Found ${allSkills.length} skill(s):
561
+ `);
562
+ renderTable({
563
+ headers: ["Name", "Version", "Scope", "Description"],
564
+ rows: allSkills.map((s) => [
565
+ s.name,
566
+ s.version || "-",
567
+ s.scope,
568
+ s.description.length > 50 ? s.description.slice(0, 47) + "..." : s.description
569
+ ])
570
+ });
571
+ } catch (error) {
572
+ if (error instanceof Error) {
573
+ logger.error(error.message);
574
+ } else {
575
+ logger.error("An unexpected error occurred");
576
+ }
577
+ process.exit(1);
578
+ }
579
+ }
580
+
581
+ // src/commands/install.ts
582
+ import { confirm as confirm2 } from "@inquirer/prompts";
583
+
584
+ // src/ui/spinner.ts
585
+ import ora from "ora";
586
+ function spinner(text) {
587
+ return ora({
588
+ text,
589
+ spinner: "dots"
590
+ });
591
+ }
592
+
593
+ // src/commands/install.ts
594
+ function parseSkillSpecifier(specifier) {
595
+ if (specifier.startsWith("github:")) {
596
+ const rest = specifier.slice(7);
597
+ const [ownerRepo, ...pathParts] = rest.split("/");
598
+ const [owner, repoWithRef] = ownerRepo.includes("/") ? [ownerRepo.split("/")[0], ownerRepo.split("/").slice(1).join("/")] : [ownerRepo, pathParts[0]];
599
+ let repo = repoWithRef || pathParts[0] || "";
600
+ let ref;
601
+ if (repo.includes("@")) {
602
+ [repo, ref] = repo.split("@");
603
+ }
604
+ const skillPath = pathParts.slice(1).join("/");
605
+ return {
606
+ type: "github",
607
+ owner,
608
+ repo,
609
+ ref,
610
+ skillPath: skillPath || void 0
611
+ };
612
+ }
613
+ if (specifier.includes("github.com")) {
614
+ const url = new URL(specifier);
615
+ const parts = url.pathname.slice(1).split("/");
616
+ const owner = parts[0];
617
+ let repo = parts[1];
618
+ let ref;
619
+ if (repo?.endsWith(".git")) {
620
+ repo = repo.slice(0, -4);
621
+ }
622
+ if (parts[2] === "tree" && parts[3]) {
623
+ ref = parts[3];
624
+ }
625
+ const skillPath = parts.slice(4).join("/");
626
+ return {
627
+ type: "github",
628
+ owner,
629
+ repo,
630
+ ref,
631
+ skillPath: skillPath || void 0
632
+ };
633
+ }
634
+ if (specifier.startsWith("http://") || specifier.startsWith("https://")) {
635
+ return {
636
+ type: "url",
637
+ url: specifier
638
+ };
639
+ }
640
+ if (specifier.startsWith("./") || specifier.startsWith("/") || specifier.startsWith("../")) {
641
+ return {
642
+ type: "local",
643
+ localPath: specifier
644
+ };
645
+ }
646
+ if (specifier.includes("/")) {
647
+ const [owner, repoWithRef] = specifier.split("/");
648
+ let repo = repoWithRef;
649
+ let ref;
650
+ if (repo?.includes("@")) {
651
+ [repo, ref] = repo.split("@");
652
+ }
653
+ return {
654
+ type: "github",
655
+ owner,
656
+ repo,
657
+ ref
658
+ };
659
+ }
660
+ throw new Error(
661
+ `Cannot resolve "${specifier}". Use github:owner/repo or a full URL.`
662
+ );
663
+ }
664
+ async function fetchFromGitHub(source) {
665
+ const { owner, repo, ref = "main", skillPath = "" } = source;
666
+ const basePath = skillPath ? `${skillPath}/` : "";
667
+ const skillMdUrl = `https://raw.githubusercontent.com/${owner}/${repo}/${ref}/${basePath}SKILL.md`;
668
+ const response = await fetch(skillMdUrl);
669
+ if (!response.ok) {
670
+ if (response.status === 404) {
671
+ throw new Error(`SKILL.md not found at ${skillMdUrl}`);
672
+ }
673
+ throw new Error(`Failed to fetch skill: ${response.statusText}`);
674
+ }
675
+ const content = await response.text();
676
+ const nameMatch = content.match(/^name:\s*(.+)$/m);
677
+ const name = nameMatch ? nameMatch[1].trim() : repo;
678
+ return { name, content };
679
+ }
680
+ async function installCommand(specifier, options) {
681
+ const spin = spinner("Resolving skill...").start();
682
+ try {
683
+ const source = parseSkillSpecifier(specifier);
684
+ if (source.type === "local") {
685
+ spin.fail("Local installation not yet implemented");
686
+ process.exit(1);
687
+ }
688
+ if (source.type === "url") {
689
+ spin.fail("URL installation not yet implemented");
690
+ process.exit(1);
691
+ }
692
+ spin.text = `Fetching from GitHub: ${source.owner}/${source.repo}...`;
693
+ const { name, content } = await fetchFromGitHub(source);
694
+ spin.text = `Found skill: ${name}`;
695
+ const scope = options.global ? "global" : "project";
696
+ const manager = new SkillManager(scope);
697
+ if (await manager.skillExists(name)) {
698
+ if (!options.force) {
699
+ spin.stop();
700
+ if (!options.yes) {
701
+ const proceed = await confirm2({
702
+ message: `Skill "${name}" already exists. Overwrite?`,
703
+ default: false
704
+ });
705
+ if (!proceed) {
706
+ logger.info("Installation cancelled");
707
+ return;
708
+ }
709
+ }
710
+ spin.start("Installing...");
711
+ }
712
+ }
713
+ spin.text = `Installing ${name}...`;
714
+ const skillSource = {
715
+ type: "github",
716
+ url: `https://github.com/${source.owner}/${source.repo}`,
717
+ ref: source.ref
718
+ };
719
+ const skillPath = await manager.installSkill(name, content, {
720
+ force: options.force || false,
721
+ source: skillSource
722
+ });
723
+ spin.succeed(`Installed ${name} to ${skillPath}`);
724
+ logger.info("");
725
+ logger.dim(`Use /${name} in Claude Code to invoke this skill`);
726
+ } catch (error) {
727
+ spin.fail("Installation failed");
728
+ if (error instanceof Error) {
729
+ logger.error(error.message);
730
+ }
731
+ process.exit(1);
732
+ }
733
+ }
734
+
735
+ // src/commands/uninstall.ts
736
+ import { confirm as confirm3 } from "@inquirer/prompts";
737
+ async function uninstallCommand(name, options) {
738
+ try {
739
+ const scope = options.global ? "global" : "project";
740
+ const manager = new SkillManager(scope);
741
+ const skill = await manager.getSkill(name);
742
+ if (!skill) {
743
+ logger.error(`Skill "${name}" not found in ${scope} skills`);
744
+ process.exit(1);
745
+ }
746
+ if (!options.yes) {
747
+ const proceed = await confirm3({
748
+ message: `Are you sure you want to uninstall "${name}"?`,
749
+ default: false
750
+ });
751
+ if (!proceed) {
752
+ logger.info("Uninstall cancelled");
753
+ return;
754
+ }
755
+ }
756
+ const spin = spinner(`Uninstalling ${name}...`).start();
757
+ await manager.uninstallSkill(name);
758
+ spin.succeed(`Uninstalled ${name}`);
759
+ } catch (error) {
760
+ if (error instanceof Error) {
761
+ logger.error(error.message);
762
+ } else {
763
+ logger.error("An unexpected error occurred");
764
+ }
765
+ process.exit(1);
766
+ }
767
+ }
768
+
769
+ // src/commands/search.ts
770
+ var MOCK_SKILLS = [
771
+ {
772
+ name: "code-review",
773
+ description: "Performs comprehensive code reviews with best practices",
774
+ author: "anthropic",
775
+ downloads: 15234,
776
+ repository: "github:anthropics/skills"
777
+ },
778
+ {
779
+ name: "test-generator",
780
+ description: "Generates unit tests for your code automatically",
781
+ author: "community",
782
+ downloads: 8432,
783
+ repository: "github:skills/test-generator"
784
+ },
785
+ {
786
+ name: "api-docs",
787
+ description: "Generates API documentation from code comments",
788
+ author: "community",
789
+ downloads: 5621,
790
+ repository: "github:skills/api-docs"
791
+ },
792
+ {
793
+ name: "refactor",
794
+ description: "Suggests and performs code refactoring",
795
+ author: "anthropic",
796
+ downloads: 12345,
797
+ repository: "github:anthropics/skills"
798
+ },
799
+ {
800
+ name: "commit-message",
801
+ description: "Generates meaningful commit messages from staged changes",
802
+ author: "community",
803
+ downloads: 9876,
804
+ repository: "github:skills/commit-message"
805
+ }
806
+ ];
807
+ async function searchCommand(query, options) {
808
+ const spin = spinner(`Searching for "${query}"...`).start();
809
+ try {
810
+ await new Promise((resolve) => setTimeout(resolve, 500));
811
+ const results = MOCK_SKILLS.filter(
812
+ (skill) => skill.name.toLowerCase().includes(query.toLowerCase()) || skill.description.toLowerCase().includes(query.toLowerCase())
813
+ ).slice(0, options.limit);
814
+ spin.stop();
815
+ if (results.length === 0) {
816
+ logger.info(`No skills found matching "${query}"`);
817
+ logger.info("");
818
+ logger.dim("Note: Registry search is not yet fully implemented.");
819
+ logger.dim("You can install directly from GitHub: outclaw install github:owner/repo");
820
+ return;
821
+ }
822
+ if (options.json) {
823
+ console.log(JSON.stringify(results, null, 2));
824
+ return;
825
+ }
826
+ logger.info(`Found ${results.length} skill(s):
827
+ `);
828
+ for (const skill of results) {
829
+ logger.skill({
830
+ name: skill.name,
831
+ description: skill.description,
832
+ author: skill.author,
833
+ installCmd: `outclaw install ${skill.repository}`
834
+ });
835
+ }
836
+ logger.info("");
837
+ logger.dim("Note: This is sample data. Full registry support coming soon.");
838
+ } catch (error) {
839
+ spin.fail("Search failed");
840
+ if (error instanceof Error) {
841
+ logger.error(error.message);
842
+ }
843
+ process.exit(1);
844
+ }
845
+ }
846
+
847
+ // src/commands/info.ts
848
+ import chalk3 from "chalk";
849
+ async function infoCommand(name, options) {
850
+ try {
851
+ const scopes = options.global ? ["global"] : ["project", "global"];
852
+ let skill = null;
853
+ let foundScope = null;
854
+ for (const scope of scopes) {
855
+ const manager = new SkillManager(scope);
856
+ skill = await manager.getSkill(name);
857
+ if (skill) {
858
+ foundScope = scope;
859
+ break;
860
+ }
861
+ }
862
+ if (!skill || !foundScope) {
863
+ logger.error(`Skill "${name}" not found`);
864
+ logger.dim("");
865
+ logger.dim("Search for skills: outclaw search <query>");
866
+ process.exit(1);
867
+ }
868
+ console.log();
869
+ console.log(chalk3.bold.cyan(` ${skill.name}`));
870
+ console.log();
871
+ console.log(chalk3.dim(" Description:"), skill.description);
872
+ console.log(chalk3.dim(" Version:"), skill.version || "unversioned");
873
+ console.log(chalk3.dim(" Scope:"), foundScope);
874
+ console.log(chalk3.dim(" Path:"), skill.path);
875
+ if (skill["user-invocable"] !== void 0) {
876
+ console.log(chalk3.dim(" User-invocable:"), skill["user-invocable"] ? "yes" : "no");
877
+ }
878
+ if (skill["disable-model-invocation"] !== void 0) {
879
+ console.log(
880
+ chalk3.dim(" Model invocation:"),
881
+ skill["disable-model-invocation"] ? "disabled" : "enabled"
882
+ );
883
+ }
884
+ if (skill["allowed-tools"]?.length) {
885
+ console.log(chalk3.dim(" Allowed tools:"), skill["allowed-tools"].join(", "));
886
+ }
887
+ if (skill["argument-hint"]) {
888
+ console.log(chalk3.dim(" Arguments:"), skill["argument-hint"]);
889
+ }
890
+ if (skill.context) {
891
+ console.log(chalk3.dim(" Context:"), skill.context);
892
+ }
893
+ if (skill.agent) {
894
+ console.log(chalk3.dim(" Agent:"), skill.agent);
895
+ }
896
+ if (skill.model) {
897
+ console.log(chalk3.dim(" Model:"), skill.model);
898
+ }
899
+ console.log();
900
+ console.log(chalk3.dim(" \u2500".repeat(30)));
901
+ console.log();
902
+ console.log(chalk3.dim(" Content preview:"));
903
+ console.log();
904
+ const lines = skill.content.split("\n").slice(0, 10);
905
+ for (const line of lines) {
906
+ console.log(chalk3.dim(" \u2502 ") + line);
907
+ }
908
+ if (skill.content.split("\n").length > 10) {
909
+ console.log(chalk3.dim(" \u2502 ..."));
910
+ }
911
+ console.log();
912
+ } catch (error) {
913
+ if (error instanceof Error) {
914
+ logger.error(error.message);
915
+ } else {
916
+ logger.error("An unexpected error occurred");
917
+ }
918
+ process.exit(1);
919
+ }
920
+ }
921
+
922
+ // src/cli.ts
923
+ var VERSION = "0.1.0";
924
+ var cli = new Command();
925
+ cli.name("outclaw").description("CLI tool for managing Claude Code Skills").version(VERSION);
926
+ cli.command("init [name]").description("Create a new skill project").option("-g, --global", "Create in global skills directory (~/.claude/skills)").option("-t, --template <type>", "Skill template (minimal, standard, complete)", "minimal").option("-y, --yes", "Skip prompts and use defaults").action(async (name, options) => {
927
+ await initCommand({ name, ...options });
928
+ });
929
+ cli.command("install <skill>").alias("i").alias("add").description("Install a skill from registry, GitHub, or URL").option("-g, --global", "Install globally (~/.claude/skills)").option("-f, --force", "Overwrite existing skill").option("-y, --yes", "Skip confirmation prompts").action(async (skill, options) => {
930
+ await installCommand(skill, options);
931
+ });
932
+ cli.command("uninstall <skill>").alias("rm").alias("remove").description("Uninstall a skill").option("-g, --global", "Uninstall from global directory").option("-y, --yes", "Skip confirmation prompts").action(async (skill, options) => {
933
+ await uninstallCommand(skill, options);
934
+ });
935
+ cli.command("list").alias("ls").description("List installed skills").option("-g, --global", "List only global skills").option("-p, --project", "List only project skills").option("--json", "Output as JSON").action(async (options) => {
936
+ await listCommand(options);
937
+ });
938
+ cli.command("search <query>").alias("find").description("Search for skills in the registry").option("-l, --limit <number>", "Maximum results", "20").option("--json", "Output as JSON").action(async (query, options) => {
939
+ await searchCommand(query, { ...options, limit: parseInt(options.limit) });
940
+ });
941
+ cli.command("info <skill>").description("Show detailed information about a skill").option("-g, --global", "Look in global skills").action(async (skill, options) => {
942
+ await infoCommand(skill, options);
943
+ });
944
+ cli.on("command:*", () => {
945
+ console.error(`Unknown command: ${cli.args.join(" ")}`);
946
+ console.log('Run "outclaw --help" for available commands.');
947
+ process.exit(1);
948
+ });
949
+
950
+ // src/index.ts
951
+ cli.parse();
952
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts","../src/commands/init.ts","../src/core/skill-manager.ts","../src/parsers/skill-parser.ts","../src/schemas/skill.schema.ts","../src/utils/paths.ts","../src/ui/logger.ts","../src/ui/table.ts","../src/commands/list.ts","../src/commands/install.ts","../src/ui/spinner.ts","../src/commands/uninstall.ts","../src/commands/search.ts","../src/commands/info.ts","../src/index.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { initCommand } from './commands/init.js';\nimport { listCommand } from './commands/list.js';\nimport { installCommand } from './commands/install.js';\nimport { uninstallCommand } from './commands/uninstall.js';\nimport { searchCommand } from './commands/search.js';\nimport { infoCommand } from './commands/info.js';\n\nconst VERSION = '0.1.0';\n\nexport const cli = new Command();\n\ncli\n .name('outclaw')\n .description('CLI tool for managing Claude Code Skills')\n .version(VERSION);\n\n// init command\ncli\n .command('init [name]')\n .description('Create a new skill project')\n .option('-g, --global', 'Create in global skills directory (~/.claude/skills)')\n .option('-t, --template <type>', 'Skill template (minimal, standard, complete)', 'minimal')\n .option('-y, --yes', 'Skip prompts and use defaults')\n .action(async (name, options) => {\n await initCommand({ name, ...options });\n });\n\n// install command\ncli\n .command('install <skill>')\n .alias('i')\n .alias('add')\n .description('Install a skill from registry, GitHub, or URL')\n .option('-g, --global', 'Install globally (~/.claude/skills)')\n .option('-f, --force', 'Overwrite existing skill')\n .option('-y, --yes', 'Skip confirmation prompts')\n .action(async (skill, options) => {\n await installCommand(skill, options);\n });\n\n// uninstall command\ncli\n .command('uninstall <skill>')\n .alias('rm')\n .alias('remove')\n .description('Uninstall a skill')\n .option('-g, --global', 'Uninstall from global directory')\n .option('-y, --yes', 'Skip confirmation prompts')\n .action(async (skill, options) => {\n await uninstallCommand(skill, options);\n });\n\n// list command\ncli\n .command('list')\n .alias('ls')\n .description('List installed skills')\n .option('-g, --global', 'List only global skills')\n .option('-p, --project', 'List only project skills')\n .option('--json', 'Output as JSON')\n .action(async (options) => {\n await listCommand(options);\n });\n\n// search command\ncli\n .command('search <query>')\n .alias('find')\n .description('Search for skills in the registry')\n .option('-l, --limit <number>', 'Maximum results', '20')\n .option('--json', 'Output as JSON')\n .action(async (query, options) => {\n await searchCommand(query, { ...options, limit: parseInt(options.limit) });\n });\n\n// info command\ncli\n .command('info <skill>')\n .description('Show detailed information about a skill')\n .option('-g, --global', 'Look in global skills')\n .action(async (skill, options) => {\n await infoCommand(skill, options);\n });\n\n// Handle unknown commands\ncli.on('command:*', () => {\n console.error(`Unknown command: ${cli.args.join(' ')}`);\n console.log('Run \"outclaw --help\" for available commands.');\n process.exit(1);\n});\n","import { input, select, checkbox, confirm } from '@inquirer/prompts';\nimport { SkillManager } from '../core/skill-manager.js';\nimport { logger } from '../ui/logger.js';\nimport type { Scope } from '../utils/paths.js';\n\nconst AVAILABLE_TOOLS = [\n { name: 'Read - Read files', value: 'Read' },\n { name: 'Write - Write files', value: 'Write' },\n { name: 'Edit - Edit files', value: 'Edit' },\n { name: 'Grep - Search file contents', value: 'Grep' },\n { name: 'Glob - Find files by pattern', value: 'Glob' },\n { name: 'Bash - Execute shell commands', value: 'Bash' },\n { name: 'WebFetch - Fetch web content', value: 'WebFetch' },\n { name: 'WebSearch - Search the web', value: 'WebSearch' },\n];\n\nexport interface InitOptions {\n name?: string;\n global?: boolean;\n template?: 'minimal' | 'standard' | 'complete';\n yes?: boolean;\n}\n\nexport async function initCommand(options: InitOptions): Promise<void> {\n try {\n // Determine scope\n const scope: Scope = options.global ? 'global' : 'project';\n\n // Get skill name\n let name = options.name;\n if (!name) {\n name = await input({\n message: 'Skill name:',\n validate: (value) => {\n if (!value) return 'Name is required';\n if (!/^[a-z0-9-]+$/.test(value)) {\n return 'Name must be lowercase alphanumeric with hyphens (e.g., my-skill)';\n }\n return true;\n },\n });\n }\n\n // Check if skill already exists\n const manager = new SkillManager(scope);\n if (await manager.skillExists(name)) {\n logger.error(`Skill \"${name}\" already exists`);\n process.exit(1);\n }\n\n let description: string;\n let userInvocable = true;\n let disableModelInvocation = false;\n let allowedTools: string[] = [];\n let argumentHint: string | undefined;\n let context: 'normal' | 'fork' | undefined;\n\n if (options.yes) {\n // Use defaults\n description = `${name} skill for Claude Code`;\n } else {\n // Interactive prompts\n description = await input({\n message: 'Description (for trigger matching):',\n validate: (value) => {\n if (!value || value.length < 10) {\n return 'Description should be at least 10 characters for good trigger matching';\n }\n return true;\n },\n });\n\n userInvocable = await confirm({\n message: 'User-invocable (can be called via /skill-name)?',\n default: true,\n });\n\n disableModelInvocation = await confirm({\n message: 'Disable automatic model invocation (only manual trigger)?',\n default: false,\n });\n\n allowedTools = await checkbox({\n message: 'Select allowed tools (tools that can be used without permission):',\n choices: AVAILABLE_TOOLS,\n });\n\n const wantsArgs = await confirm({\n message: 'Does this skill accept arguments?',\n default: false,\n });\n\n if (wantsArgs) {\n argumentHint = await input({\n message: 'Argument hint (e.g., [file-path] [options]):',\n });\n }\n\n const runInSubagent = await confirm({\n message: 'Run in isolated subagent context?',\n default: false,\n });\n\n if (runInSubagent) {\n context = 'fork';\n }\n }\n\n // Create the skill\n const skillPath = await manager.createSkill({\n name,\n description,\n scope,\n userInvocable,\n disableModelInvocation,\n allowedTools,\n argumentHint,\n context,\n });\n\n logger.success(`Skill created at: ${skillPath}`);\n logger.info('');\n logger.info('Next steps:');\n logger.dim(` 1. Edit ${skillPath}/SKILL.md to add your skill instructions`);\n logger.dim(` 2. Use /${name} in Claude Code to invoke your skill`);\n logger.info('');\n } catch (error) {\n if (error instanceof Error) {\n logger.error(error.message);\n } else {\n logger.error('An unexpected error occurred');\n }\n process.exit(1);\n }\n}\n","import * as fs from 'fs/promises';\nimport * as path from 'path';\nimport { SkillParser, generateSkillMd } from '../parsers/skill-parser.js';\nimport {\n getSkillsPath,\n getSkillPath,\n getManifestPath,\n ensureDir,\n pathExists,\n type Scope,\n} from '../utils/paths.js';\nimport type { Skill, SkillFrontmatter } from '../schemas/skill.schema.js';\nimport type { OutclawManifest, SkillManifest, SkillSource } from '../schemas/manifest.schema.js';\n\nexport interface SkillInfo extends Skill {\n scope: Scope;\n}\n\nexport interface CreateSkillOptions {\n name: string;\n description: string;\n version?: string;\n disableModelInvocation?: boolean;\n userInvocable?: boolean;\n allowedTools?: string[];\n argumentHint?: string;\n model?: string;\n context?: 'normal' | 'fork';\n agent?: string;\n scope: Scope;\n content?: string;\n}\n\nexport interface InstallOptions {\n force?: boolean;\n source: SkillSource;\n}\n\nexport class SkillManager {\n private scope: Scope;\n private basePath: string;\n\n constructor(scope: Scope = 'project') {\n this.scope = scope;\n this.basePath = getSkillsPath(scope);\n }\n\n /**\n * List all installed skills\n */\n async listSkills(): Promise<SkillInfo[]> {\n const skills: SkillInfo[] = [];\n\n try {\n const dirs = await fs.readdir(this.basePath);\n\n for (const dir of dirs) {\n // Skip hidden files and manifest\n if (dir.startsWith('.')) continue;\n\n const skillPath = path.join(this.basePath, dir);\n const stat = await fs.stat(skillPath);\n\n if (stat.isDirectory()) {\n try {\n const parser = new SkillParser(skillPath);\n const skill = await parser.parse();\n skills.push({ ...skill, scope: this.scope });\n } catch {\n // Skip invalid skills\n }\n }\n }\n } catch {\n // Directory doesn't exist\n }\n\n return skills;\n }\n\n /**\n * Get a specific skill by name\n */\n async getSkill(name: string): Promise<SkillInfo | null> {\n const skillPath = getSkillPath(name, this.scope);\n\n try {\n const parser = new SkillParser(skillPath);\n const skill = await parser.parse();\n return { ...skill, scope: this.scope };\n } catch {\n return null;\n }\n }\n\n /**\n * Check if a skill exists\n */\n async skillExists(name: string): Promise<boolean> {\n const skillPath = getSkillPath(name, this.scope);\n return await pathExists(path.join(skillPath, 'SKILL.md'));\n }\n\n /**\n * Create a new skill\n */\n async createSkill(options: CreateSkillOptions): Promise<string> {\n const skillPath = getSkillPath(options.name, options.scope);\n\n // Check if skill already exists\n if (await pathExists(skillPath)) {\n throw new Error(`Skill \"${options.name}\" already exists at ${skillPath}`);\n }\n\n // Create skill directory\n await ensureDir(skillPath);\n\n // Build frontmatter\n const frontmatter: Partial<SkillFrontmatter> = {\n name: options.name,\n description: options.description,\n version: options.version || '1.0.0',\n };\n\n if (options.disableModelInvocation !== undefined) {\n frontmatter['disable-model-invocation'] = options.disableModelInvocation;\n }\n if (options.userInvocable !== undefined) {\n frontmatter['user-invocable'] = options.userInvocable;\n }\n if (options.allowedTools?.length) {\n frontmatter['allowed-tools'] = options.allowedTools;\n }\n if (options.argumentHint) {\n frontmatter['argument-hint'] = options.argumentHint;\n }\n if (options.model) {\n frontmatter.model = options.model;\n }\n if (options.context) {\n frontmatter.context = options.context;\n }\n if (options.agent) {\n frontmatter.agent = options.agent;\n }\n\n // Generate SKILL.md content\n const content = options.content || `# ${options.name}\\n\\nYour skill instructions here...\\n`;\n const skillMdContent = generateSkillMd(frontmatter, content);\n\n // Write SKILL.md\n await fs.writeFile(path.join(skillPath, 'SKILL.md'), skillMdContent, 'utf-8');\n\n return skillPath;\n }\n\n /**\n * Install a skill from content\n */\n async installSkill(\n name: string,\n skillMdContent: string,\n options: InstallOptions\n ): Promise<string> {\n const skillPath = getSkillPath(name, this.scope);\n\n // Check if skill already exists\n if (!options.force && (await pathExists(skillPath))) {\n throw new Error(`Skill \"${name}\" already exists. Use --force to overwrite.`);\n }\n\n // Create skill directory\n await ensureDir(skillPath);\n\n // Write SKILL.md\n await fs.writeFile(path.join(skillPath, 'SKILL.md'), skillMdContent, 'utf-8');\n\n // Update manifest\n await this.updateManifest(name, options.source);\n\n return skillPath;\n }\n\n /**\n * Uninstall a skill\n */\n async uninstallSkill(name: string): Promise<void> {\n const skillPath = getSkillPath(name, this.scope);\n\n if (!(await pathExists(skillPath))) {\n throw new Error(`Skill \"${name}\" not found`);\n }\n\n await fs.rm(skillPath, { recursive: true, force: true });\n await this.removeFromManifest(name);\n }\n\n /**\n * Get manifest\n */\n async getManifest(): Promise<OutclawManifest> {\n const manifestPath = getManifestPath(this.scope);\n\n try {\n const content = await fs.readFile(manifestPath, 'utf-8');\n return JSON.parse(content);\n } catch {\n return { version: 1, skills: [] };\n }\n }\n\n /**\n * Update manifest with new skill\n */\n private async updateManifest(name: string, source: SkillSource): Promise<void> {\n const manifestPath = getManifestPath(this.scope);\n const manifest = await this.getManifest();\n\n const entry: SkillManifest = {\n name,\n version: '1.0.0',\n installedAt: new Date().toISOString(),\n source,\n scope: this.scope,\n };\n\n // Update or add skill entry\n const index = manifest.skills.findIndex((s) => s.name === name);\n if (index >= 0) {\n manifest.skills[index] = entry;\n } else {\n manifest.skills.push(entry);\n }\n\n await ensureDir(path.dirname(manifestPath));\n await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2));\n }\n\n /**\n * Remove skill from manifest\n */\n private async removeFromManifest(name: string): Promise<void> {\n const manifestPath = getManifestPath(this.scope);\n\n try {\n const content = await fs.readFile(manifestPath, 'utf-8');\n const manifest: OutclawManifest = JSON.parse(content);\n manifest.skills = manifest.skills.filter((s) => s.name !== name);\n await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2));\n } catch {\n // Manifest doesn't exist, nothing to update\n }\n }\n}\n","import * as fs from 'fs/promises';\nimport * as path from 'path';\nimport matter from 'gray-matter';\nimport { SkillFrontmatterSchema, type Skill, type SkillFrontmatter } from '../schemas/skill.schema.js';\n\nexport interface SkillStructure {\n hasSkillMd: boolean;\n hasReferences: boolean;\n hasScripts: boolean;\n hasExamples: boolean;\n files: string[];\n}\n\nexport class SkillParser {\n private basePath: string;\n\n constructor(basePath: string) {\n this.basePath = basePath;\n }\n\n /**\n * Parse SKILL.md and return the full skill object\n */\n async parse(): Promise<Skill> {\n const skillMdPath = path.join(this.basePath, 'SKILL.md');\n const content = await fs.readFile(skillMdPath, 'utf-8');\n\n const { data, content: body } = matter(content);\n\n // Validate frontmatter with Zod\n const frontmatter = SkillFrontmatterSchema.parse(data);\n\n return {\n ...frontmatter,\n content: body.trim(),\n path: this.basePath,\n };\n }\n\n /**\n * Parse only the frontmatter without validating\n */\n async parseFrontmatter(): Promise<SkillFrontmatter> {\n const skillMdPath = path.join(this.basePath, 'SKILL.md');\n const content = await fs.readFile(skillMdPath, 'utf-8');\n\n const { data } = matter(content);\n return SkillFrontmatterSchema.parse(data);\n }\n\n /**\n * Get the structure of the skill directory\n */\n async getStructure(): Promise<SkillStructure> {\n const structure: SkillStructure = {\n hasSkillMd: false,\n hasReferences: false,\n hasScripts: false,\n hasExamples: false,\n files: [],\n };\n\n try {\n const entries = await fs.readdir(this.basePath, { withFileTypes: true });\n\n for (const entry of entries) {\n if (entry.isFile() && entry.name === 'SKILL.md') {\n structure.hasSkillMd = true;\n } else if (entry.isDirectory()) {\n switch (entry.name) {\n case 'references':\n structure.hasReferences = true;\n break;\n case 'scripts':\n structure.hasScripts = true;\n break;\n case 'examples':\n structure.hasExamples = true;\n break;\n }\n }\n structure.files.push(entry.name);\n }\n } catch {\n // Directory doesn't exist\n }\n\n return structure;\n }\n\n /**\n * Check if a valid skill exists at this path\n */\n async isValid(): Promise<boolean> {\n try {\n await this.parse();\n return true;\n } catch {\n return false;\n }\n }\n}\n\n/**\n * Generate SKILL.md content from frontmatter and body\n */\nexport function generateSkillMd(frontmatter: Partial<SkillFrontmatter>, body: string): string {\n const yamlLines: string[] = [];\n\n if (frontmatter.name) {\n yamlLines.push(`name: ${frontmatter.name}`);\n }\n if (frontmatter.description) {\n yamlLines.push(`description: ${frontmatter.description}`);\n }\n if (frontmatter.version) {\n yamlLines.push(`version: ${frontmatter.version}`);\n }\n if (frontmatter['disable-model-invocation'] !== undefined) {\n yamlLines.push(`disable-model-invocation: ${frontmatter['disable-model-invocation']}`);\n }\n if (frontmatter['user-invocable'] !== undefined) {\n yamlLines.push(`user-invocable: ${frontmatter['user-invocable']}`);\n }\n if (frontmatter['allowed-tools']?.length) {\n const tools = Array.isArray(frontmatter['allowed-tools'])\n ? frontmatter['allowed-tools'].join(', ')\n : frontmatter['allowed-tools'];\n yamlLines.push(`allowed-tools: ${tools}`);\n }\n if (frontmatter['argument-hint']) {\n yamlLines.push(`argument-hint: ${frontmatter['argument-hint']}`);\n }\n if (frontmatter.model) {\n yamlLines.push(`model: ${frontmatter.model}`);\n }\n if (frontmatter.context) {\n yamlLines.push(`context: ${frontmatter.context}`);\n }\n if (frontmatter.agent) {\n yamlLines.push(`agent: ${frontmatter.agent}`);\n }\n\n return `---\n${yamlLines.join('\\n')}\n---\n\n${body}\n`;\n}\n","import { z } from 'zod';\n\n// SKILL.md frontmatter schema\nexport const SkillFrontmatterSchema = z.object({\n name: z\n .string()\n .min(1, 'Name is required')\n .regex(/^[a-z0-9-]+$/, 'Name must be lowercase alphanumeric with hyphens'),\n\n description: z\n .string()\n .min(10, 'Description should be detailed for good triggering'),\n\n version: z\n .string()\n .regex(/^\\d+\\.\\d+\\.\\d+$/, 'Version must be semver format')\n .optional(),\n\n 'disable-model-invocation': z.boolean().optional().default(false),\n\n 'user-invocable': z.boolean().optional().default(true),\n\n 'allowed-tools': z\n .union([z.string(), z.array(z.string())])\n .optional()\n .transform((val) => {\n if (typeof val === 'string') {\n return val.split(',').map((t) => t.trim());\n }\n return val;\n }),\n\n 'argument-hint': z.string().optional(),\n\n model: z.string().optional(),\n\n context: z.enum(['normal', 'fork']).optional(),\n\n agent: z.string().optional(),\n\n license: z.string().optional(),\n\n author: z\n .union([\n z.string(),\n z.object({\n name: z.string(),\n email: z.string().email().optional(),\n url: z.string().url().optional(),\n }),\n ])\n .optional(),\n\n keywords: z.array(z.string()).optional(),\n\n repository: z.string().optional(),\n});\n\n// Full skill schema including content\nexport const SkillSchema = SkillFrontmatterSchema.extend({\n content: z.string().min(1, 'Skill content is required'),\n path: z.string(),\n});\n\nexport type SkillFrontmatter = z.infer<typeof SkillFrontmatterSchema>;\nexport type Skill = z.infer<typeof SkillSchema>;\n","import * as path from 'path';\nimport * as os from 'os';\nimport * as fs from 'fs/promises';\n\nexport type Scope = 'global' | 'project';\n\n/**\n * Get the skills directory path for a given scope\n */\nexport function getSkillsPath(scope: Scope): string {\n if (scope === 'global') {\n return path.join(os.homedir(), '.claude', 'skills');\n }\n return path.join(process.cwd(), '.claude', 'skills');\n}\n\n/**\n * Get the manifest file path for a given scope\n */\nexport function getManifestPath(scope: Scope): string {\n const skillsPath = getSkillsPath(scope);\n return path.join(skillsPath, '.outclaw-manifest.json');\n}\n\n/**\n * Get the path to a specific skill\n */\nexport function getSkillPath(skillName: string, scope: Scope): string {\n return path.join(getSkillsPath(scope), skillName);\n}\n\n/**\n * Get the SKILL.md path for a specific skill\n */\nexport function getSkillMdPath(skillName: string, scope: Scope): string {\n return path.join(getSkillPath(skillName, scope), 'SKILL.md');\n}\n\n/**\n * Ensure directory exists\n */\nexport async function ensureDir(dirPath: string): Promise<void> {\n await fs.mkdir(dirPath, { recursive: true });\n}\n\n/**\n * Check if a path exists\n */\nexport async function pathExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Get config directory path\n */\nexport function getConfigPath(): string {\n return path.join(os.homedir(), '.config', 'outclaw');\n}\n","import chalk from 'chalk';\n\nexport const logger = {\n info: (message: string) => {\n console.log(message);\n },\n\n success: (message: string) => {\n console.log(chalk.green('✓'), message);\n },\n\n error: (message: string) => {\n console.error(chalk.red('✗'), message);\n },\n\n warn: (message: string) => {\n console.log(chalk.yellow('⚠'), message);\n },\n\n dim: (message: string) => {\n console.log(chalk.dim(message));\n },\n\n skill: (info: { name: string; description: string; author?: string; installCmd?: string }) => {\n console.log();\n console.log(chalk.bold.cyan(info.name));\n console.log(chalk.dim(info.description));\n if (info.author) {\n console.log(chalk.dim(`by ${info.author}`));\n }\n if (info.installCmd) {\n console.log(chalk.dim(`$ ${info.installCmd}`));\n }\n },\n\n box: (title: string, content: string) => {\n const lines = content.split('\\n');\n const maxLen = Math.max(title.length, ...lines.map((l) => l.length));\n const border = '─'.repeat(maxLen + 2);\n\n console.log(`┌${border}┐`);\n console.log(`│ ${chalk.bold(title.padEnd(maxLen))} │`);\n console.log(`├${border}┤`);\n for (const line of lines) {\n console.log(`│ ${line.padEnd(maxLen)} │`);\n }\n console.log(`└${border}┘`);\n },\n};\n","import Table from 'cli-table3';\nimport chalk from 'chalk';\n\nexport interface TableOptions {\n headers: string[];\n rows: string[][];\n}\n\nexport function renderTable(options: TableOptions): void {\n const table = new Table({\n head: options.headers.map((h) => chalk.bold.cyan(h)),\n style: {\n head: [],\n border: [],\n },\n });\n\n for (const row of options.rows) {\n table.push(row);\n }\n\n console.log(table.toString());\n}\n","import { SkillManager, type SkillInfo } from '../core/skill-manager.js';\nimport { logger } from '../ui/logger.js';\nimport { renderTable } from '../ui/table.js';\nimport type { Scope } from '../utils/paths.js';\n\nexport interface ListOptions {\n global?: boolean;\n project?: boolean;\n json?: boolean;\n}\n\nexport async function listCommand(options: ListOptions): Promise<void> {\n try {\n const scopes: Scope[] = [];\n\n if (options.global) {\n scopes.push('global');\n } else if (options.project) {\n scopes.push('project');\n } else {\n scopes.push('global', 'project');\n }\n\n const allSkills: SkillInfo[] = [];\n\n for (const scope of scopes) {\n const manager = new SkillManager(scope);\n const skills = await manager.listSkills();\n allSkills.push(...skills);\n }\n\n if (allSkills.length === 0) {\n logger.info('No skills installed.');\n logger.info('');\n logger.dim('Install skills with: outclaw install <skill>');\n logger.dim('Create a new skill with: outclaw init');\n return;\n }\n\n if (options.json) {\n console.log(JSON.stringify(allSkills, null, 2));\n return;\n }\n\n logger.info(`Found ${allSkills.length} skill(s):\\n`);\n\n renderTable({\n headers: ['Name', 'Version', 'Scope', 'Description'],\n rows: allSkills.map((s) => [\n s.name,\n s.version || '-',\n s.scope,\n s.description.length > 50 ? s.description.slice(0, 47) + '...' : s.description,\n ]),\n });\n } catch (error) {\n if (error instanceof Error) {\n logger.error(error.message);\n } else {\n logger.error('An unexpected error occurred');\n }\n process.exit(1);\n }\n}\n","import { confirm } from '@inquirer/prompts';\nimport { SkillManager } from '../core/skill-manager.js';\nimport { logger } from '../ui/logger.js';\nimport { spinner } from '../ui/spinner.js';\nimport type { Scope } from '../utils/paths.js';\nimport type { SkillSource } from '../schemas/manifest.schema.js';\n\nexport interface InstallOptions {\n global?: boolean;\n force?: boolean;\n yes?: boolean;\n}\n\ninterface ParsedSource {\n type: 'github' | 'url' | 'local';\n owner?: string;\n repo?: string;\n skillPath?: string;\n ref?: string;\n url?: string;\n localPath?: string;\n}\n\n/**\n * Parse skill specifier to determine source\n * Formats:\n * - github:owner/repo\n * - github:owner/repo@ref\n * - github:owner/repo/path/to/skill\n * - https://github.com/owner/repo\n * - ./local/path\n */\nfunction parseSkillSpecifier(specifier: string): ParsedSource {\n // GitHub shorthand: github:owner/repo[@ref][/path]\n if (specifier.startsWith('github:')) {\n const rest = specifier.slice(7);\n const [ownerRepo, ...pathParts] = rest.split('/');\n const [owner, repoWithRef] = ownerRepo.includes('/')\n ? [ownerRepo.split('/')[0], ownerRepo.split('/').slice(1).join('/')]\n : [ownerRepo, pathParts[0]];\n\n let repo = repoWithRef || pathParts[0] || '';\n let ref: string | undefined;\n\n if (repo.includes('@')) {\n [repo, ref] = repo.split('@');\n }\n\n const skillPath = pathParts.slice(1).join('/');\n\n return {\n type: 'github',\n owner,\n repo,\n ref,\n skillPath: skillPath || undefined,\n };\n }\n\n // GitHub URL\n if (specifier.includes('github.com')) {\n const url = new URL(specifier);\n const parts = url.pathname.slice(1).split('/');\n const owner = parts[0];\n let repo = parts[1];\n let ref: string | undefined;\n\n // Handle .git suffix\n if (repo?.endsWith('.git')) {\n repo = repo.slice(0, -4);\n }\n\n // Handle tree/branch reference\n if (parts[2] === 'tree' && parts[3]) {\n ref = parts[3];\n }\n\n const skillPath = parts.slice(4).join('/');\n\n return {\n type: 'github',\n owner,\n repo,\n ref,\n skillPath: skillPath || undefined,\n };\n }\n\n // Generic URL\n if (specifier.startsWith('http://') || specifier.startsWith('https://')) {\n return {\n type: 'url',\n url: specifier,\n };\n }\n\n // Local path\n if (specifier.startsWith('./') || specifier.startsWith('/') || specifier.startsWith('../')) {\n return {\n type: 'local',\n localPath: specifier,\n };\n }\n\n // Assume it's a registry name (for future registry support)\n // For now, treat as GitHub shorthand without prefix\n if (specifier.includes('/')) {\n const [owner, repoWithRef] = specifier.split('/');\n let repo = repoWithRef;\n let ref: string | undefined;\n\n if (repo?.includes('@')) {\n [repo, ref] = repo.split('@');\n }\n\n return {\n type: 'github',\n owner,\n repo,\n ref,\n };\n }\n\n // Single name - assume registry (future feature)\n throw new Error(\n `Cannot resolve \"${specifier}\". Use github:owner/repo or a full URL.`\n );\n}\n\nasync function fetchFromGitHub(source: ParsedSource): Promise<{ name: string; content: string }> {\n const { owner, repo, ref = 'main', skillPath = '' } = source;\n\n // Construct raw GitHub URL for SKILL.md\n const basePath = skillPath ? `${skillPath}/` : '';\n const skillMdUrl = `https://raw.githubusercontent.com/${owner}/${repo}/${ref}/${basePath}SKILL.md`;\n\n const response = await fetch(skillMdUrl);\n\n if (!response.ok) {\n if (response.status === 404) {\n throw new Error(`SKILL.md not found at ${skillMdUrl}`);\n }\n throw new Error(`Failed to fetch skill: ${response.statusText}`);\n }\n\n const content = await response.text();\n\n // Extract name from frontmatter or use repo name\n const nameMatch = content.match(/^name:\\s*(.+)$/m);\n const name = nameMatch ? nameMatch[1].trim() : repo!;\n\n return { name, content };\n}\n\nexport async function installCommand(specifier: string, options: InstallOptions): Promise<void> {\n const spin = spinner('Resolving skill...').start();\n\n try {\n // Parse specifier\n const source = parseSkillSpecifier(specifier);\n\n if (source.type === 'local') {\n spin.fail('Local installation not yet implemented');\n process.exit(1);\n }\n\n if (source.type === 'url') {\n spin.fail('URL installation not yet implemented');\n process.exit(1);\n }\n\n // Fetch from GitHub\n spin.text = `Fetching from GitHub: ${source.owner}/${source.repo}...`;\n const { name, content } = await fetchFromGitHub(source);\n\n spin.text = `Found skill: ${name}`;\n\n // Check for existing skill\n const scope: Scope = options.global ? 'global' : 'project';\n const manager = new SkillManager(scope);\n\n if (await manager.skillExists(name)) {\n if (!options.force) {\n spin.stop();\n\n if (!options.yes) {\n const proceed = await confirm({\n message: `Skill \"${name}\" already exists. Overwrite?`,\n default: false,\n });\n\n if (!proceed) {\n logger.info('Installation cancelled');\n return;\n }\n }\n\n spin.start('Installing...');\n }\n }\n\n // Install\n spin.text = `Installing ${name}...`;\n\n const skillSource: SkillSource = {\n type: 'github',\n url: `https://github.com/${source.owner}/${source.repo}`,\n ref: source.ref,\n };\n\n const skillPath = await manager.installSkill(name, content, {\n force: options.force || false,\n source: skillSource,\n });\n\n spin.succeed(`Installed ${name} to ${skillPath}`);\n logger.info('');\n logger.dim(`Use /${name} in Claude Code to invoke this skill`);\n } catch (error) {\n spin.fail('Installation failed');\n if (error instanceof Error) {\n logger.error(error.message);\n }\n process.exit(1);\n }\n}\n","import ora, { type Ora } from 'ora';\n\nexport function spinner(text: string): Ora {\n return ora({\n text,\n spinner: 'dots',\n });\n}\n\nexport { type Ora };\n","import { confirm } from '@inquirer/prompts';\nimport { SkillManager } from '../core/skill-manager.js';\nimport { logger } from '../ui/logger.js';\nimport { spinner } from '../ui/spinner.js';\nimport type { Scope } from '../utils/paths.js';\n\nexport interface UninstallOptions {\n global?: boolean;\n yes?: boolean;\n}\n\nexport async function uninstallCommand(name: string, options: UninstallOptions): Promise<void> {\n try {\n const scope: Scope = options.global ? 'global' : 'project';\n const manager = new SkillManager(scope);\n\n // Check if skill exists\n const skill = await manager.getSkill(name);\n\n if (!skill) {\n logger.error(`Skill \"${name}\" not found in ${scope} skills`);\n process.exit(1);\n }\n\n // Confirm uninstall\n if (!options.yes) {\n const proceed = await confirm({\n message: `Are you sure you want to uninstall \"${name}\"?`,\n default: false,\n });\n\n if (!proceed) {\n logger.info('Uninstall cancelled');\n return;\n }\n }\n\n const spin = spinner(`Uninstalling ${name}...`).start();\n\n await manager.uninstallSkill(name);\n\n spin.succeed(`Uninstalled ${name}`);\n } catch (error) {\n if (error instanceof Error) {\n logger.error(error.message);\n } else {\n logger.error('An unexpected error occurred');\n }\n process.exit(1);\n }\n}\n","import { logger } from '../ui/logger.js';\nimport { spinner } from '../ui/spinner.js';\n\nexport interface SearchOptions {\n limit: number;\n json?: boolean;\n}\n\n// Mock registry data for now\n// In a real implementation, this would fetch from a registry API\nconst MOCK_SKILLS = [\n {\n name: 'code-review',\n description: 'Performs comprehensive code reviews with best practices',\n author: 'anthropic',\n downloads: 15234,\n repository: 'github:anthropics/skills',\n },\n {\n name: 'test-generator',\n description: 'Generates unit tests for your code automatically',\n author: 'community',\n downloads: 8432,\n repository: 'github:skills/test-generator',\n },\n {\n name: 'api-docs',\n description: 'Generates API documentation from code comments',\n author: 'community',\n downloads: 5621,\n repository: 'github:skills/api-docs',\n },\n {\n name: 'refactor',\n description: 'Suggests and performs code refactoring',\n author: 'anthropic',\n downloads: 12345,\n repository: 'github:anthropics/skills',\n },\n {\n name: 'commit-message',\n description: 'Generates meaningful commit messages from staged changes',\n author: 'community',\n downloads: 9876,\n repository: 'github:skills/commit-message',\n },\n];\n\nexport async function searchCommand(query: string, options: SearchOptions): Promise<void> {\n const spin = spinner(`Searching for \"${query}\"...`).start();\n\n try {\n // Simulate API delay\n await new Promise((resolve) => setTimeout(resolve, 500));\n\n // Filter mock data\n const results = MOCK_SKILLS.filter(\n (skill) =>\n skill.name.toLowerCase().includes(query.toLowerCase()) ||\n skill.description.toLowerCase().includes(query.toLowerCase())\n ).slice(0, options.limit);\n\n spin.stop();\n\n if (results.length === 0) {\n logger.info(`No skills found matching \"${query}\"`);\n logger.info('');\n logger.dim('Note: Registry search is not yet fully implemented.');\n logger.dim('You can install directly from GitHub: outclaw install github:owner/repo');\n return;\n }\n\n if (options.json) {\n console.log(JSON.stringify(results, null, 2));\n return;\n }\n\n logger.info(`Found ${results.length} skill(s):\\n`);\n\n for (const skill of results) {\n logger.skill({\n name: skill.name,\n description: skill.description,\n author: skill.author,\n installCmd: `outclaw install ${skill.repository}`,\n });\n }\n\n logger.info('');\n logger.dim('Note: This is sample data. Full registry support coming soon.');\n } catch (error) {\n spin.fail('Search failed');\n if (error instanceof Error) {\n logger.error(error.message);\n }\n process.exit(1);\n }\n}\n","import chalk from 'chalk';\nimport { SkillManager } from '../core/skill-manager.js';\nimport { logger } from '../ui/logger.js';\nimport type { Scope } from '../utils/paths.js';\n\nexport interface InfoOptions {\n global?: boolean;\n}\n\nexport async function infoCommand(name: string, options: InfoOptions): Promise<void> {\n try {\n // Try both scopes if not specified\n const scopes: Scope[] = options.global ? ['global'] : ['project', 'global'];\n\n let skill = null;\n let foundScope: Scope | null = null;\n\n for (const scope of scopes) {\n const manager = new SkillManager(scope);\n skill = await manager.getSkill(name);\n if (skill) {\n foundScope = scope;\n break;\n }\n }\n\n if (!skill || !foundScope) {\n logger.error(`Skill \"${name}\" not found`);\n logger.dim('');\n logger.dim('Search for skills: outclaw search <query>');\n process.exit(1);\n }\n\n // Display skill info\n console.log();\n console.log(chalk.bold.cyan(` ${skill.name}`));\n console.log();\n console.log(chalk.dim(' Description:'), skill.description);\n console.log(chalk.dim(' Version:'), skill.version || 'unversioned');\n console.log(chalk.dim(' Scope:'), foundScope);\n console.log(chalk.dim(' Path:'), skill.path);\n\n if (skill['user-invocable'] !== undefined) {\n console.log(chalk.dim(' User-invocable:'), skill['user-invocable'] ? 'yes' : 'no');\n }\n\n if (skill['disable-model-invocation'] !== undefined) {\n console.log(\n chalk.dim(' Model invocation:'),\n skill['disable-model-invocation'] ? 'disabled' : 'enabled'\n );\n }\n\n if (skill['allowed-tools']?.length) {\n console.log(chalk.dim(' Allowed tools:'), skill['allowed-tools'].join(', '));\n }\n\n if (skill['argument-hint']) {\n console.log(chalk.dim(' Arguments:'), skill['argument-hint']);\n }\n\n if (skill.context) {\n console.log(chalk.dim(' Context:'), skill.context);\n }\n\n if (skill.agent) {\n console.log(chalk.dim(' Agent:'), skill.agent);\n }\n\n if (skill.model) {\n console.log(chalk.dim(' Model:'), skill.model);\n }\n\n console.log();\n console.log(chalk.dim(' ─'.repeat(30)));\n console.log();\n console.log(chalk.dim(' Content preview:'));\n console.log();\n\n // Show first 10 lines of content\n const lines = skill.content.split('\\n').slice(0, 10);\n for (const line of lines) {\n console.log(chalk.dim(' │ ') + line);\n }\n\n if (skill.content.split('\\n').length > 10) {\n console.log(chalk.dim(' │ ...'));\n }\n\n console.log();\n } catch (error) {\n if (error instanceof Error) {\n logger.error(error.message);\n } else {\n logger.error('An unexpected error occurred');\n }\n process.exit(1);\n }\n}\n","import { cli } from './cli.js';\n\ncli.parse();\n"],"mappings":"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","names":["fs","path","path","fs","stat","chalk","confirm","confirm","confirm","confirm","chalk","chalk"]}
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "outclaw",
3
+ "version": "0.1.0",
4
+ "description": "CLI tool for managing Claude Code Skills - A complete registry system",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "bin": {
9
+ "outclaw": "./dist/index.js",
10
+ "ocl": "./dist/index.js"
11
+ },
12
+ "files": [
13
+ "dist",
14
+ "templates"
15
+ ],
16
+ "scripts": {
17
+ "dev": "tsup --watch",
18
+ "build": "tsup",
19
+ "typecheck": "tsc --noEmit",
20
+ "lint": "eslint src --ext .ts",
21
+ "test": "vitest",
22
+ "prepublishOnly": "npm run build"
23
+ },
24
+ "keywords": [
25
+ "claude",
26
+ "claude-code",
27
+ "skills",
28
+ "cli",
29
+ "registry",
30
+ "ai",
31
+ "agent",
32
+ "agent-skills"
33
+ ],
34
+ "author": "",
35
+ "license": "MIT",
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "git+https://github.com/yourusername/outclaw.git"
39
+ },
40
+ "homepage": "https://github.com/yourusername/outclaw#readme",
41
+ "bugs": {
42
+ "url": "https://github.com/yourusername/outclaw/issues"
43
+ },
44
+ "engines": {
45
+ "node": ">=18.0.0"
46
+ },
47
+ "dependencies": {
48
+ "@inquirer/prompts": "^7.2.1",
49
+ "chalk": "^5.3.0",
50
+ "cli-table3": "^0.6.5",
51
+ "commander": "^12.1.0",
52
+ "conf": "^13.0.1",
53
+ "gray-matter": "^4.0.3",
54
+ "ora": "^8.1.1",
55
+ "semver": "^7.6.3",
56
+ "simple-git": "^3.27.0",
57
+ "zod": "^3.24.1"
58
+ },
59
+ "devDependencies": {
60
+ "@types/node": "^22.10.7",
61
+ "@types/semver": "^7.5.8",
62
+ "tsup": "^8.3.5",
63
+ "typescript": "^5.7.3",
64
+ "vitest": "^2.1.8"
65
+ }
66
+ }
package/readme.md ADDED
@@ -0,0 +1,155 @@
1
+ # Outclaw
2
+
3
+ CLI tool for managing Claude Code Skills - A complete registry system.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g outclaw
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Create a new skill
14
+
15
+ ```bash
16
+ # Interactive mode
17
+ outclaw init
18
+
19
+ # With name
20
+ outclaw init my-skill
21
+
22
+ # Create in global directory
23
+ outclaw init my-skill --global
24
+ ```
25
+
26
+ ### Install a skill
27
+
28
+ ```bash
29
+ # From GitHub
30
+ outclaw install github:owner/repo
31
+ outclaw install github:owner/repo@branch
32
+
33
+ # From GitHub (shorthand)
34
+ outclaw install owner/repo
35
+
36
+ # From URL
37
+ outclaw install https://github.com/owner/repo
38
+
39
+ # Install globally
40
+ outclaw install github:owner/repo --global
41
+ ```
42
+
43
+ ### List installed skills
44
+
45
+ ```bash
46
+ # List all skills
47
+ outclaw list
48
+
49
+ # List only global skills
50
+ outclaw list --global
51
+
52
+ # List only project skills
53
+ outclaw list --project
54
+
55
+ # Output as JSON
56
+ outclaw list --json
57
+ ```
58
+
59
+ ### Search for skills
60
+
61
+ ```bash
62
+ outclaw search <query>
63
+
64
+ # Limit results
65
+ outclaw search react --limit 10
66
+ ```
67
+
68
+ ### Show skill info
69
+
70
+ ```bash
71
+ outclaw info my-skill
72
+ ```
73
+
74
+ ### Uninstall a skill
75
+
76
+ ```bash
77
+ outclaw uninstall my-skill
78
+
79
+ # Uninstall global skill
80
+ outclaw uninstall my-skill --global
81
+ ```
82
+
83
+ ## Claude Code Skills Format
84
+
85
+ Skills follow the [Agent Skills](https://agentskills.io) open standard.
86
+
87
+ ### Directory Structure
88
+
89
+ ```
90
+ my-skill/
91
+ ├── SKILL.md # Main instructions (required)
92
+ ├── references/ # Reference documentation (optional)
93
+ ├── examples/ # Example outputs (optional)
94
+ └── scripts/ # Executable scripts (optional)
95
+ ```
96
+
97
+ ### SKILL.md Format
98
+
99
+ ```yaml
100
+ ---
101
+ name: my-skill
102
+ description: What this skill does and when to use it
103
+ version: 1.0.0
104
+ disable-model-invocation: false
105
+ user-invocable: true
106
+ allowed-tools: Read, Grep, Glob
107
+ argument-hint: [file-path]
108
+ ---
109
+
110
+ Your skill instructions here...
111
+ ```
112
+
113
+ ### Frontmatter Options
114
+
115
+ | Field | Description |
116
+ |-------|-------------|
117
+ | `name` | Skill name (lowercase, alphanumeric, hyphens) |
118
+ | `description` | What the skill does (used for trigger matching) |
119
+ | `version` | Semantic version |
120
+ | `disable-model-invocation` | Prevent automatic triggering |
121
+ | `user-invocable` | Allow manual invocation via `/skill-name` |
122
+ | `allowed-tools` | Tools that can be used without permission |
123
+ | `argument-hint` | Hint for autocomplete |
124
+ | `model` | Override model for this skill |
125
+ | `context` | Run in `fork` for isolated subagent |
126
+ | `agent` | Subagent type when using `context: fork` |
127
+
128
+ ### Skills Location
129
+
130
+ - **Global**: `~/.claude/skills/<skill-name>/SKILL.md`
131
+ - **Project**: `.claude/skills/<skill-name>/SKILL.md`
132
+
133
+ ## Using as a Claude Code Skill
134
+
135
+ You can create a skill to help manage skills:
136
+
137
+ ```yaml
138
+ ---
139
+ name: outclaw
140
+ description: Manage Claude Code skills - create, install, search, and publish
141
+ disable-model-invocation: true
142
+ allowed-tools: Bash
143
+ ---
144
+
145
+ Use outclaw CLI to manage Claude Code skills:
146
+
147
+ - Create new skill: `outclaw init <name>`
148
+ - Install skill: `outclaw install <skill>`
149
+ - List skills: `outclaw list`
150
+ - Search skills: `outclaw search <query>`
151
+ ```
152
+
153
+ ## License
154
+
155
+ MIT
@@ -0,0 +1,32 @@
1
+ ---
2
+ name: {{name}}
3
+ description: {{description}}
4
+ version: 1.0.0
5
+ {{#if disableModelInvocation}}
6
+ disable-model-invocation: true
7
+ {{/if}}
8
+ {{#if userInvocable}}
9
+ user-invocable: true
10
+ {{/if}}
11
+ {{#if allowedTools}}
12
+ allowed-tools: {{allowedTools}}
13
+ {{/if}}
14
+ {{#if argumentHint}}
15
+ argument-hint: {{argumentHint}}
16
+ {{/if}}
17
+ {{#if context}}
18
+ context: {{context}}
19
+ {{/if}}
20
+ ---
21
+
22
+ # {{name}}
23
+
24
+ Your skill instructions here...
25
+
26
+ ## Usage
27
+
28
+ Describe how to use this skill and what it does.
29
+
30
+ ## Examples
31
+
32
+ Provide examples of when this skill should be triggered.