create-cascade-skill 0.1.7 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +238 -110
- package/package.json +3 -2
package/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { resolve, join } from "node:path";
|
|
4
4
|
import process from "node:process";
|
|
5
5
|
import { spawnSync } from "node:child_process";
|
|
@@ -13,8 +13,16 @@ const ANSI_CYAN = "\x1b[36m";
|
|
|
13
13
|
const ANSI_GREEN = "\x1b[32m";
|
|
14
14
|
const ANSI_YELLOW = "\x1b[33m";
|
|
15
15
|
|
|
16
|
-
function getHomeDirectory() {
|
|
17
|
-
|
|
16
|
+
function getHomeDirectory(options) {
|
|
17
|
+
if (options?.home) {
|
|
18
|
+
return options.home;
|
|
19
|
+
}
|
|
20
|
+
return (
|
|
21
|
+
process.env.CASCADE_SKILL_HOME ||
|
|
22
|
+
process.env.HOME ||
|
|
23
|
+
process.env.USERPROFILE ||
|
|
24
|
+
process.cwd()
|
|
25
|
+
);
|
|
18
26
|
}
|
|
19
27
|
|
|
20
28
|
function commandExists(command) {
|
|
@@ -34,9 +42,13 @@ function unique(items) {
|
|
|
34
42
|
return [...new Set(items)];
|
|
35
43
|
}
|
|
36
44
|
|
|
37
|
-
function getAgents() {
|
|
38
|
-
const home = getHomeDirectory();
|
|
39
|
-
const appData =
|
|
45
|
+
function getAgents(options) {
|
|
46
|
+
const home = getHomeDirectory(options);
|
|
47
|
+
const appData =
|
|
48
|
+
options?.appData ||
|
|
49
|
+
process.env.CASCADE_SKILL_APPDATA ||
|
|
50
|
+
process.env.APPDATA ||
|
|
51
|
+
join(home, "AppData", "Roaming");
|
|
40
52
|
return [
|
|
41
53
|
{
|
|
42
54
|
id: "codex",
|
|
@@ -65,6 +77,15 @@ function getAgents() {
|
|
|
65
77
|
installPath: join(home, ".cursor", "skills", "cascadetui", "SKILL.md"),
|
|
66
78
|
flavor: "cursor",
|
|
67
79
|
},
|
|
80
|
+
{
|
|
81
|
+
id: "factory",
|
|
82
|
+
label: "Factory (Droid CLI)",
|
|
83
|
+
description: "Install in ~/.factory/skills/cascadetui/SKILL.md",
|
|
84
|
+
commands: ["droid"],
|
|
85
|
+
detectPaths: [join(home, ".factory")],
|
|
86
|
+
installPath: join(home, ".factory", "skills", "cascadetui", "SKILL.md"),
|
|
87
|
+
flavor: "factory",
|
|
88
|
+
},
|
|
68
89
|
{
|
|
69
90
|
id: "windsurf",
|
|
70
91
|
label: "Windsurf",
|
|
@@ -170,7 +191,9 @@ function parseArgs(argv) {
|
|
|
170
191
|
allDetected: false,
|
|
171
192
|
list: false,
|
|
172
193
|
dryRun: false,
|
|
194
|
+
force: false,
|
|
173
195
|
help: false,
|
|
196
|
+
home: undefined,
|
|
174
197
|
};
|
|
175
198
|
for (let i = 0; i < args.length; i += 1) {
|
|
176
199
|
const arg = args[i];
|
|
@@ -195,6 +218,19 @@ function parseArgs(argv) {
|
|
|
195
218
|
options.dryRun = true;
|
|
196
219
|
continue;
|
|
197
220
|
}
|
|
221
|
+
if (arg === "--force") {
|
|
222
|
+
options.force = true;
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
if (arg === "--home") {
|
|
226
|
+
options.home = args[i + 1];
|
|
227
|
+
i += 1;
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
if (arg.startsWith("--home=")) {
|
|
231
|
+
options.home = arg.slice("--home=".length);
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
198
234
|
if (arg === "--help" || arg === "-h") {
|
|
199
235
|
options.help = true;
|
|
200
236
|
continue;
|
|
@@ -213,6 +249,8 @@ function printHelp() {
|
|
|
213
249
|
console.log(" --all-detected Install for all detected agents");
|
|
214
250
|
console.log(" --list Print supported and detected agents");
|
|
215
251
|
console.log(" --dry-run Preview files without writing");
|
|
252
|
+
console.log(" --force Overwrite SKILL.md when it differs");
|
|
253
|
+
console.log(" --home <path> Override home directory used for detection/install");
|
|
216
254
|
console.log(" -h, --help Show help");
|
|
217
255
|
console.log("");
|
|
218
256
|
console.log("Examples:");
|
|
@@ -220,6 +258,7 @@ function printHelp() {
|
|
|
220
258
|
console.log(" npx create-cascade-skill --all-detected");
|
|
221
259
|
console.log(" npx create-cascade-skill --agents codex,cursor,cline");
|
|
222
260
|
console.log(" npx create-cascade-skill --agents codex --dry-run");
|
|
261
|
+
console.log(" npx create-cascade-skill --agents windsurf --home ./sandbox --dry-run");
|
|
223
262
|
}
|
|
224
263
|
|
|
225
264
|
function detectAgents(agents) {
|
|
@@ -271,8 +310,7 @@ function toSelectableOptions(agents) {
|
|
|
271
310
|
return agents.map((agent) => ({
|
|
272
311
|
id: agent.id,
|
|
273
312
|
label: agent.label,
|
|
274
|
-
description: `${agent.description}${agent.detected ? " [detected]" : ""
|
|
275
|
-
}`,
|
|
313
|
+
description: `${agent.description}${agent.detected ? " [detected]" : ""}`,
|
|
276
314
|
}));
|
|
277
315
|
}
|
|
278
316
|
|
|
@@ -300,9 +338,7 @@ async function selectMany(rl, label, options, preselectedIds) {
|
|
|
300
338
|
const cursor = isCursor
|
|
301
339
|
? `${ANSI_BOLD}${ANSI_CYAN}>${ANSI_RESET}`
|
|
302
340
|
: " ";
|
|
303
|
-
const mark = isSelected
|
|
304
|
-
? `${ANSI_GREEN}[x]${ANSI_RESET}`
|
|
305
|
-
: "[ ]";
|
|
341
|
+
const mark = isSelected ? `${ANSI_GREEN}[x]${ANSI_RESET}` : "[ ]";
|
|
306
342
|
const styleStart = isCursor ? `${ANSI_BOLD}${ANSI_CYAN}` : "";
|
|
307
343
|
const styleEnd = isCursor ? ANSI_RESET : "";
|
|
308
344
|
stdout.write(
|
|
@@ -378,7 +414,7 @@ async function selectMany(rl, label, options, preselectedIds) {
|
|
|
378
414
|
function getSkillFrontmatter(agent) {
|
|
379
415
|
const baseName = "cascadetui";
|
|
380
416
|
const description =
|
|
381
|
-
"Build terminal user interfaces with CascadeTUI. Use this skill
|
|
417
|
+
"Build terminal user interfaces with CascadeTUI. Use this skill to scaffold, debug, and refactor Cascade-based TUIs (layout, input, rendering, keyboard navigation, React/Solid bindings). Triggers: Cascade, CascadeTUI, TUI, terminal UI, keybindings, focus, renderer.";
|
|
382
418
|
let compatibility = "Requires Bun and TypeScript.";
|
|
383
419
|
if (agent.flavor === "claude") {
|
|
384
420
|
compatibility += " Designed for Claude Code.";
|
|
@@ -386,83 +422,141 @@ function getSkillFrontmatter(agent) {
|
|
|
386
422
|
compatibility += " Designed for Cursor.";
|
|
387
423
|
} else if (agent.flavor === "codex") {
|
|
388
424
|
compatibility += " Designed for OpenAI Codex.";
|
|
425
|
+
} else if (agent.flavor === "factory") {
|
|
426
|
+
compatibility += " Designed for Factory (Droid CLI).";
|
|
389
427
|
} else {
|
|
390
428
|
compatibility += ` Designed for ${agent.label}.`;
|
|
391
429
|
}
|
|
392
|
-
|
|
430
|
+
|
|
431
|
+
const allowedTools =
|
|
432
|
+
agent.flavor === "factory"
|
|
433
|
+
? "Read, Bash, Write"
|
|
434
|
+
: "Bash(bun:*) Bash(npm:*) Bash(node:*)";
|
|
435
|
+
|
|
436
|
+
const extraFactoryFrontmatter =
|
|
437
|
+
agent.flavor === "factory"
|
|
438
|
+
? `\nuser-invocable: true\ndisable-model-invocation: false`
|
|
439
|
+
: "";
|
|
440
|
+
|
|
393
441
|
return (
|
|
394
442
|
`---\n` +
|
|
395
443
|
`name: ${baseName}\n` +
|
|
396
444
|
`description: ${description}\n` +
|
|
397
445
|
`compatibility: ${compatibility}\n` +
|
|
398
|
-
`allowed-tools: ${allowedTools}
|
|
446
|
+
`allowed-tools: ${allowedTools}` +
|
|
447
|
+
`${extraFactoryFrontmatter}\n` +
|
|
399
448
|
`metadata:\n` +
|
|
400
449
|
` author: cascadetui\n` +
|
|
401
|
-
` version: "1.
|
|
450
|
+
` version: "1.2"\n` +
|
|
402
451
|
`---`
|
|
403
452
|
);
|
|
404
453
|
}
|
|
405
454
|
|
|
406
455
|
function getSkillBody() {
|
|
407
|
-
return `#
|
|
408
|
-
|
|
409
|
-
##
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
-
|
|
413
|
-
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
-
|
|
457
|
-
-
|
|
458
|
-
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
-
|
|
464
|
-
|
|
465
|
-
|
|
456
|
+
return `# CascadeTUI Engineering Skill
|
|
457
|
+
|
|
458
|
+
## Use This When
|
|
459
|
+
|
|
460
|
+
Activate for tasks involving:
|
|
461
|
+
- Building a new terminal UI (TUI) with CascadeTUI
|
|
462
|
+
- Fixing layout, rendering glitches, or resize bugs
|
|
463
|
+
- Keyboard navigation, focus, selection, shortcuts, input handling
|
|
464
|
+
- React/Solid bindings on top of CascadeTUI core
|
|
465
|
+
- Performance issues (re-render storms, slow lists) or state determinism
|
|
466
|
+
|
|
467
|
+
## Output Expectations
|
|
468
|
+
|
|
469
|
+
When implementing or refactoring, produce:
|
|
470
|
+
- A minimal, runnable entrypoint that demonstrates the behavior
|
|
471
|
+
- Deterministic state updates and predictable render cycles
|
|
472
|
+
- Clear keybindings and focus behavior
|
|
473
|
+
- A short verification checklist (commands + manual steps)
|
|
474
|
+
|
|
475
|
+
## Project Workflow (Bun-first)
|
|
476
|
+
|
|
477
|
+
1) Ensure dependencies
|
|
478
|
+
\`\`\`bash
|
|
479
|
+
bun install
|
|
480
|
+
\`\`\`
|
|
481
|
+
|
|
482
|
+
2) Run the app (or a repro script)
|
|
483
|
+
\`\`\`bash
|
|
484
|
+
bun run dev
|
|
485
|
+
\`\`\`
|
|
486
|
+
|
|
487
|
+
3) Add a tiny repro when debugging
|
|
488
|
+
- Create \`scripts/repro.ts\` or a minimal app entrypoint
|
|
489
|
+
- Keep it self-contained: one screen, one interaction, one bug
|
|
490
|
+
|
|
491
|
+
## Design Rules (CascadeTUI-specific)
|
|
492
|
+
|
|
493
|
+
### Deterministic UI
|
|
494
|
+
- Treat rendering as a pure function of state
|
|
495
|
+
- Avoid hidden mutable globals for UI state
|
|
496
|
+
- Prefer single source of truth (one store or a small set of state atoms)
|
|
497
|
+
|
|
498
|
+
### Layout & Composition
|
|
499
|
+
- Compose screens with containers and consistent spacing
|
|
500
|
+
- Keep one responsibility per component: layout vs input vs domain logic
|
|
501
|
+
- Use stable keys for lists; avoid index keys if items can move
|
|
502
|
+
|
|
503
|
+
### Input, Focus, and Navigation
|
|
504
|
+
- Define a keymap per screen (Up/Down, Enter, Esc, Tab, Ctrl shortcuts)
|
|
505
|
+
- Always document primary actions and an escape/back path
|
|
506
|
+
- Ensure focus is explicit: which element receives keys right now
|
|
507
|
+
- Handle terminal resize: reflow layout and keep selection stable
|
|
508
|
+
|
|
509
|
+
### Rendering & Performance
|
|
510
|
+
- Avoid rebuilding large trees on every keypress
|
|
511
|
+
- For large lists: paginate, virtualize, or reduce per-row computation
|
|
512
|
+
- Batch state updates; avoid cascading updates during render
|
|
513
|
+
|
|
514
|
+
## Debugging Playbook
|
|
515
|
+
|
|
516
|
+
When something is wrong:
|
|
517
|
+
1) Confirm the bug in a tiny repro
|
|
518
|
+
2) Log state transitions around the interaction
|
|
519
|
+
3) Verify input events fire once (no duplicated handlers)
|
|
520
|
+
4) Verify keys/ids are stable (especially lists)
|
|
521
|
+
5) Verify resize behavior by changing terminal size rapidly
|
|
522
|
+
|
|
523
|
+
Common failure modes:
|
|
524
|
+
- Duplicate listeners attached on re-render
|
|
525
|
+
- Non-stable list keys causing selection jumps
|
|
526
|
+
- Async state updates racing; UI shows stale selection
|
|
527
|
+
- Layout constraints (width/height) not propagated as expected
|
|
528
|
+
|
|
529
|
+
## Quick Recipes
|
|
530
|
+
|
|
531
|
+
### Add a consistent keymap footer
|
|
532
|
+
- Show the active shortcuts at the bottom (e.g. \`q\` quit, \`/\` search, arrows navigate)
|
|
533
|
+
- Keep it updated per screen
|
|
534
|
+
|
|
535
|
+
### Search + List pattern
|
|
536
|
+
- Input line at top
|
|
537
|
+
- Filtered list in the middle
|
|
538
|
+
- Details/preview panel (optional)
|
|
539
|
+
- Enter selects, Esc clears/back
|
|
540
|
+
|
|
541
|
+
### React binding guidance
|
|
542
|
+
- Keep bridge components thin
|
|
543
|
+
- Avoid passing unstable props that trigger full-tree rerenders
|
|
544
|
+
- Prefer memoization at boundaries (list row, heavy panels)
|
|
545
|
+
|
|
546
|
+
## Verification Checklist
|
|
547
|
+
|
|
548
|
+
Run:
|
|
549
|
+
\`\`\`bash
|
|
550
|
+
bun run typecheck
|
|
551
|
+
bun run lint
|
|
552
|
+
bun test
|
|
553
|
+
\`\`\`
|
|
554
|
+
|
|
555
|
+
Manual:
|
|
556
|
+
- Start app in small and large terminals
|
|
557
|
+
- Resize while a list item is selected
|
|
558
|
+
- Navigate with keyboard only
|
|
559
|
+
- Confirm exit behavior (Ctrl+C and explicit quit key)
|
|
466
560
|
`;
|
|
467
561
|
}
|
|
468
562
|
|
|
@@ -494,6 +588,22 @@ function getImprovedCursorAppendix() {
|
|
|
494
588
|
`;
|
|
495
589
|
}
|
|
496
590
|
|
|
591
|
+
function getImprovedFactoryAppendix() {
|
|
592
|
+
return `## Factory (Droid CLI) Skill Notes
|
|
593
|
+
|
|
594
|
+
- Skills are discovered from:
|
|
595
|
+
- Workspace: \`<repo>/.factory/skills/<skill-name>/SKILL.md\`
|
|
596
|
+
- Personal: \`~/.factory/skills/<skill-name>/SKILL.md\`
|
|
597
|
+
- Compatibility: \`<repo>/.agent/skills/\` :contentReference[oaicite:1]{index=1}
|
|
598
|
+
- This installer writes to the personal location by default: \`~/.factory/skills/cascadetui/SKILL.md\`.
|
|
599
|
+
- If you want to share the skill with teammates, copy it into your repo under \`.factory/skills/cascadetui/SKILL.md\` and commit it. :contentReference[oaicite:2]{index=2}
|
|
600
|
+
- Invocation control:
|
|
601
|
+
- \`disable-model-invocation: true\` to require manual \`/cascadetui\` invocation
|
|
602
|
+
- \`user-invocable: false\` to hide it from slash commands and keep it model-only :contentReference[oaicite:3]{index=3}
|
|
603
|
+
- Restart \`droid\` after adding/updating skills so it rescans them. :contentReference[oaicite:4]{index=4}
|
|
604
|
+
`;
|
|
605
|
+
}
|
|
606
|
+
|
|
497
607
|
function getGenericAppendix(agent) {
|
|
498
608
|
return `## ${agent.label} Skill Notes
|
|
499
609
|
|
|
@@ -508,34 +618,60 @@ function getSkillContent(agent) {
|
|
|
508
618
|
const frontmatter = getSkillFrontmatter(agent);
|
|
509
619
|
const body = getSkillBody();
|
|
510
620
|
if (agent.flavor === "claude") {
|
|
511
|
-
return (
|
|
512
|
-
frontmatter +
|
|
513
|
-
"\n\n" +
|
|
514
|
-
body +
|
|
515
|
-
"\n\n" +
|
|
516
|
-
getImprovedClaudeAppendix()
|
|
517
|
-
);
|
|
621
|
+
return frontmatter + "\n\n" + body + "\n\n" + getImprovedClaudeAppendix();
|
|
518
622
|
}
|
|
519
623
|
if (agent.flavor === "cursor") {
|
|
520
|
-
return (
|
|
521
|
-
frontmatter + "\n\n" + body + "\n\n" + getImprovedCursorAppendix()
|
|
522
|
-
);
|
|
624
|
+
return frontmatter + "\n\n" + body + "\n\n" + getImprovedCursorAppendix();
|
|
523
625
|
}
|
|
524
|
-
|
|
525
|
-
frontmatter + "\n\n" + body + "\n\n" +
|
|
526
|
-
|
|
626
|
+
if (agent.flavor === "factory") {
|
|
627
|
+
return frontmatter + "\n\n" + body + "\n\n" + getImprovedFactoryAppendix();
|
|
628
|
+
}
|
|
629
|
+
return frontmatter + "\n\n" + body + "\n\n" + getGenericAppendix(agent);
|
|
527
630
|
}
|
|
528
631
|
|
|
529
|
-
function installSkill(agent,
|
|
632
|
+
function installSkill(agent, options) {
|
|
530
633
|
const content = getSkillContent(agent);
|
|
531
634
|
const targetFile = agent.installPath;
|
|
532
635
|
const targetDir = resolve(targetFile, "..");
|
|
533
|
-
if (dryRun) {
|
|
534
|
-
return { agent: agent.id, path: targetFile, written: false };
|
|
636
|
+
if (options.dryRun) {
|
|
637
|
+
return { agent: agent.id, path: targetFile, written: false, skipped: false, reason: "dry-run" };
|
|
638
|
+
}
|
|
639
|
+
if (existsSync(targetFile)) {
|
|
640
|
+
try {
|
|
641
|
+
const existing = readFileSync(targetFile, "utf8");
|
|
642
|
+
if (existing === content) {
|
|
643
|
+
return {
|
|
644
|
+
agent: agent.id,
|
|
645
|
+
path: targetFile,
|
|
646
|
+
written: false,
|
|
647
|
+
skipped: true,
|
|
648
|
+
reason: "already up-to-date",
|
|
649
|
+
};
|
|
650
|
+
}
|
|
651
|
+
if (!options.force) {
|
|
652
|
+
return {
|
|
653
|
+
agent: agent.id,
|
|
654
|
+
path: targetFile,
|
|
655
|
+
written: false,
|
|
656
|
+
skipped: true,
|
|
657
|
+
reason: "exists (use --force to overwrite)",
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
} catch {
|
|
661
|
+
if (!options.force) {
|
|
662
|
+
return {
|
|
663
|
+
agent: agent.id,
|
|
664
|
+
path: targetFile,
|
|
665
|
+
written: false,
|
|
666
|
+
skipped: true,
|
|
667
|
+
reason: "exists (unreadable; use --force to overwrite)",
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
}
|
|
535
671
|
}
|
|
536
672
|
mkdirSync(targetDir, { recursive: true });
|
|
537
673
|
writeFileSync(targetFile, content);
|
|
538
|
-
return { agent: agent.id, path: targetFile, written: true };
|
|
674
|
+
return { agent: agent.id, path: targetFile, written: true, skipped: false, reason: "written" };
|
|
539
675
|
}
|
|
540
676
|
|
|
541
677
|
async function resolveAgentsToInstall(rl, detectedAgents, options) {
|
|
@@ -582,8 +718,7 @@ async function resolveAgentsToInstall(rl, detectedAgents, options) {
|
|
|
582
718
|
rl,
|
|
583
719
|
"No agent selected. Enter comma-separated IDs (or leave empty to cancel): "
|
|
584
720
|
)
|
|
585
|
-
)
|
|
586
|
-
.trim();
|
|
721
|
+
).trim();
|
|
587
722
|
if (!fallback) {
|
|
588
723
|
return [];
|
|
589
724
|
}
|
|
@@ -598,7 +733,7 @@ async function main() {
|
|
|
598
733
|
printHelp();
|
|
599
734
|
return;
|
|
600
735
|
}
|
|
601
|
-
const agents = detectAgents(getAgents());
|
|
736
|
+
const agents = detectAgents(getAgents({ home: options.home }));
|
|
602
737
|
if (options.list) {
|
|
603
738
|
printList(agents);
|
|
604
739
|
return;
|
|
@@ -613,27 +748,22 @@ async function main() {
|
|
|
613
748
|
console.log("Nothing to install.");
|
|
614
749
|
return;
|
|
615
750
|
}
|
|
616
|
-
const selectedAgents = agents.filter((agent) =>
|
|
617
|
-
|
|
618
|
-
);
|
|
619
|
-
const results = selectedAgents.map((agent) =>
|
|
620
|
-
installSkill(agent, options.dryRun)
|
|
621
|
-
);
|
|
751
|
+
const selectedAgents = agents.filter((agent) => selectedIds.includes(agent.id));
|
|
752
|
+
const results = selectedAgents.map((agent) => installSkill(agent, options));
|
|
622
753
|
console.log("");
|
|
623
754
|
console.log(`${ANSI_BOLD}CascadeTUI skill installer${ANSI_RESET}`);
|
|
624
755
|
for (const result of results) {
|
|
625
756
|
const prefix = result.written
|
|
626
757
|
? `${ANSI_GREEN}installed${ANSI_RESET}`
|
|
627
|
-
:
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
);
|
|
758
|
+
: result.skipped
|
|
759
|
+
? `${ANSI_YELLOW}skipped${ANSI_RESET}`
|
|
760
|
+
: `${ANSI_YELLOW}planned${ANSI_RESET}`;
|
|
761
|
+
const suffix = result.reason ? ` (${result.reason})` : "";
|
|
762
|
+
console.log(`- ${result.agent}: ${prefix} -> ${result.path}${suffix}`);
|
|
631
763
|
}
|
|
632
764
|
if (options.dryRun) {
|
|
633
765
|
console.log("");
|
|
634
|
-
console.log(
|
|
635
|
-
"Dry run complete. Re-run without --dry-run to write files."
|
|
636
|
-
);
|
|
766
|
+
console.log("Dry run complete. Re-run without --dry-run to write files.");
|
|
637
767
|
}
|
|
638
768
|
} finally {
|
|
639
769
|
rl.close();
|
|
@@ -641,8 +771,6 @@ async function main() {
|
|
|
641
771
|
}
|
|
642
772
|
|
|
643
773
|
main().catch((error) => {
|
|
644
|
-
console.error(
|
|
645
|
-
error instanceof Error ? error.message : String(error)
|
|
646
|
-
);
|
|
774
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
647
775
|
process.exit(1);
|
|
648
776
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-cascade-skill",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"description": "Install CascadeTUI skills for external coding agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"README.md"
|
|
18
18
|
],
|
|
19
19
|
"scripts": {
|
|
20
|
-
"publish:pkg": "bun scripts/publish.ts"
|
|
20
|
+
"publish:pkg": "bun scripts/publish.ts",
|
|
21
|
+
"test:skill": "bun scripts/user-test.ts"
|
|
21
22
|
}
|
|
22
23
|
}
|