kiro-kit 0.3.5 → 0.3.7
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/README.md +12 -1
- package/dist/index.js +137 -43
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
npx kiro-kit init
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
Pick from 6 curated presets,
|
|
19
|
+
Pick from 6 curated presets with an interactive selector — arrow keys to move, Enter to select, Enter again to confirm. Your `.kiro/` workspace is ready with agents, skills, commands, hooks, MCP servers, Powers recommendations, and spec templates.
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
22
|
# or install globally
|
|
@@ -70,6 +70,17 @@ Every preset ships **self-contained**: agents, skills, commands, cross-platform
|
|
|
70
70
|
--json Machine-readable output (list, info)
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
+
## CLI Experience
|
|
74
|
+
|
|
75
|
+
The `kiro-kit init` command features a polished terminal UI:
|
|
76
|
+
|
|
77
|
+
- Purple gradient ASCII logo (figlet Slant font)
|
|
78
|
+
- Interactive preset selector with arrow keys, Enter to select, Enter x2 to confirm
|
|
79
|
+
- Live selected count indicator
|
|
80
|
+
- Task progress list with spinners
|
|
81
|
+
- Success summary box with file counts and next steps
|
|
82
|
+
- Graceful fallback for CI/non-TTY environments
|
|
83
|
+
|
|
73
84
|
## Kiro Powers Integration
|
|
74
85
|
|
|
75
86
|
Each preset recommends curated [Kiro Powers](https://kiro.dev/powers/) from the marketplace, organized by priority:
|
package/dist/index.js
CHANGED
|
@@ -11899,13 +11899,20 @@ function loadTerminalLink() {
|
|
|
11899
11899
|
|
|
11900
11900
|
// src/ui/theme.ts
|
|
11901
11901
|
var DEFAULT_PALETTE = {
|
|
11902
|
-
primary: "#
|
|
11903
|
-
|
|
11904
|
-
|
|
11905
|
-
|
|
11906
|
-
|
|
11907
|
-
|
|
11908
|
-
|
|
11902
|
+
primary: "#c084fc",
|
|
11903
|
+
// violet-400 — bright purple
|
|
11904
|
+
secondary: "#818cf8",
|
|
11905
|
+
// indigo-400 — purple-blue
|
|
11906
|
+
muted: "#7c6f9f",
|
|
11907
|
+
// muted purple-gray
|
|
11908
|
+
text: "#f5f3ff",
|
|
11909
|
+
// near-white with purple tint
|
|
11910
|
+
danger: "#f472b6",
|
|
11911
|
+
// pink-400
|
|
11912
|
+
success: "#34d399",
|
|
11913
|
+
// emerald-400
|
|
11914
|
+
warn: "#fbbf24"
|
|
11915
|
+
// amber-400
|
|
11909
11916
|
};
|
|
11910
11917
|
var HEX_REGEX = /^#[0-9a-fA-F]{6}$/;
|
|
11911
11918
|
function validatePalette(palette) {
|
|
@@ -11993,7 +12000,7 @@ async function createTheme(capability, palette) {
|
|
|
11993
12000
|
return `${label} (${url})`;
|
|
11994
12001
|
};
|
|
11995
12002
|
return {
|
|
11996
|
-
logoGradient: [merged.primary, merged.secondary],
|
|
12003
|
+
logoGradient: [merged.primary, "#a78bfa", merged.secondary, "#f472b6"],
|
|
11997
12004
|
heading: headingFn,
|
|
11998
12005
|
command: commandFn,
|
|
11999
12006
|
flag: flagFn,
|
|
@@ -12014,17 +12021,15 @@ function createLogoSync(capability, theme, figlet, gradient) {
|
|
|
12014
12021
|
let line = text;
|
|
12015
12022
|
if (version) line += ` v${version}`;
|
|
12016
12023
|
line = theme.heading(line);
|
|
12017
|
-
if (subtitle)
|
|
12018
|
-
line += `
|
|
12024
|
+
if (subtitle) line += `
|
|
12019
12025
|
${theme.muted(subtitle)}`;
|
|
12020
|
-
}
|
|
12021
12026
|
return line;
|
|
12022
12027
|
}
|
|
12023
12028
|
function render(opts) {
|
|
12024
|
-
const
|
|
12025
|
-
const font = opts.font ?? "ANSI Shadow";
|
|
12029
|
+
const font = opts.font ?? "Slant";
|
|
12026
12030
|
const subtitle = opts.subtitle ?? "";
|
|
12027
12031
|
const version = opts.version ?? "";
|
|
12032
|
+
const text = opts.text ?? "kiro-kit";
|
|
12028
12033
|
if (capability.columns < 60 || !capability.unicode || figlet === null) {
|
|
12029
12034
|
return renderCompact(opts);
|
|
12030
12035
|
}
|
|
@@ -12049,9 +12054,7 @@ ${theme.muted(subtitle)}`;
|
|
|
12049
12054
|
}
|
|
12050
12055
|
if (subtitle || version) {
|
|
12051
12056
|
let tagline = subtitle;
|
|
12052
|
-
if (version) {
|
|
12053
|
-
tagline += (subtitle ? " " : "") + `v${version}`;
|
|
12054
|
-
}
|
|
12057
|
+
if (version) tagline += (subtitle ? " " : "") + `v${version}`;
|
|
12055
12058
|
body += `
|
|
12056
12059
|
${theme.muted(tagline)}`;
|
|
12057
12060
|
}
|
|
@@ -12070,11 +12073,16 @@ async function createLogo(capability, theme) {
|
|
|
12070
12073
|
|
|
12071
12074
|
// src/ui/ThemedBox.ts
|
|
12072
12075
|
var VARIANT_HEX = {
|
|
12073
|
-
info: "#
|
|
12074
|
-
|
|
12075
|
-
|
|
12076
|
-
|
|
12077
|
-
|
|
12076
|
+
info: "#c084fc",
|
|
12077
|
+
// violet-400
|
|
12078
|
+
tip: "#818cf8",
|
|
12079
|
+
// indigo-400
|
|
12080
|
+
success: "#34d399",
|
|
12081
|
+
// emerald-400
|
|
12082
|
+
warn: "#fbbf24",
|
|
12083
|
+
// amber-400
|
|
12084
|
+
error: "#f472b6"
|
|
12085
|
+
// pink-400
|
|
12078
12086
|
};
|
|
12079
12087
|
function drawAsciiBox(content, title, width, padding, colorBorder) {
|
|
12080
12088
|
const innerWidth = width - 2;
|
|
@@ -12190,55 +12198,60 @@ async function createInitScreens(ctx) {
|
|
|
12190
12198
|
createThemedBox(capability, theme)
|
|
12191
12199
|
]);
|
|
12192
12200
|
function welcome(data) {
|
|
12201
|
+
const cols = capability.columns ?? 80;
|
|
12193
12202
|
const logoStr = logo.render({
|
|
12194
12203
|
text: "kiro-kit",
|
|
12195
|
-
font: "
|
|
12204
|
+
font: "Slant",
|
|
12196
12205
|
version: data.cliVersion,
|
|
12197
12206
|
subtitle: "Engineer-grade Kiro presets"
|
|
12198
12207
|
});
|
|
12199
12208
|
process.stdout.write(logoStr + "\n");
|
|
12200
|
-
|
|
12201
|
-
|
|
12202
|
-
|
|
12203
|
-
|
|
12204
|
-
|
|
12205
|
-
|
|
12206
|
-
|
|
12207
|
-
|
|
12209
|
+
const sep = capability.color ? "\x1B[38;2;124;111;159m" + "\u2500".repeat(Math.min(cols - 2, 72)) + "\x1B[0m" : "\u2500".repeat(Math.min(cols - 2, 72));
|
|
12210
|
+
process.stdout.write(sep + "\n\n");
|
|
12211
|
+
process.stdout.write(theme.heading("Commands") + "\n");
|
|
12212
|
+
const icons = {
|
|
12213
|
+
init: "\u25B6",
|
|
12214
|
+
add: "+",
|
|
12215
|
+
list: "\u2261",
|
|
12216
|
+
doctor: "\u2665"
|
|
12217
|
+
};
|
|
12208
12218
|
for (const cmd of data.commands) {
|
|
12209
|
-
const
|
|
12219
|
+
const icon = capability.color ? "\x1B[38;2;192;132;252m" + (icons[cmd.name] ?? "\u25CF") + "\x1B[0m" : icons[cmd.name] ?? "-";
|
|
12220
|
+
const paddedName = theme.command(cmd.name.padEnd(10));
|
|
12210
12221
|
const desc = theme.muted(cmd.description);
|
|
12211
|
-
process.stdout.write(` ${paddedName}${desc}
|
|
12222
|
+
process.stdout.write(` ${icon} ${paddedName} ${desc}
|
|
12212
12223
|
`);
|
|
12213
12224
|
}
|
|
12214
12225
|
process.stdout.write("\n");
|
|
12215
12226
|
}
|
|
12216
12227
|
function summary(data) {
|
|
12217
12228
|
const lines = [];
|
|
12229
|
+
const check = capability.color ? "\x1B[38;2;52;211;153m\u2714\x1B[0m" : "[ok]";
|
|
12230
|
+
const bullet = capability.color ? "\x1B[38;2;192;132;252m\u2022\x1B[0m" : "-";
|
|
12218
12231
|
lines.push(
|
|
12219
|
-
`${theme.success(String(data.filesWritten))} files written
|
|
12232
|
+
`${check} ${theme.success(String(data.filesWritten))} files written` + (data.filesSkipped > 0 ? `, ${theme.muted(String(data.filesSkipped) + " skipped")}` : "")
|
|
12220
12233
|
);
|
|
12221
|
-
lines.push(
|
|
12234
|
+
lines.push(`${bullet} Presets: ${theme.command(data.presets.join(", "))}`);
|
|
12222
12235
|
if (data.setupGuidePath !== void 0) {
|
|
12223
12236
|
const safePath = sanitizePath(data.setupGuidePath);
|
|
12224
|
-
lines.push(
|
|
12237
|
+
lines.push(`${bullet} Setup guide: ${theme.pathStyle(safePath)}`);
|
|
12225
12238
|
}
|
|
12226
12239
|
if (data.envExamplePath !== void 0) {
|
|
12227
12240
|
const safePath = sanitizePath(data.envExamplePath);
|
|
12228
|
-
lines.push(
|
|
12241
|
+
lines.push(`${bullet} Env template: ${theme.pathStyle(safePath)}`);
|
|
12229
12242
|
}
|
|
12230
12243
|
if (data.nextSteps.length > 0) {
|
|
12231
12244
|
lines.push("");
|
|
12232
12245
|
lines.push(theme.heading("Next steps:"));
|
|
12233
12246
|
for (const step of data.nextSteps) {
|
|
12234
|
-
lines.push(` ${
|
|
12247
|
+
lines.push(` ${bullet} ${step}`);
|
|
12235
12248
|
}
|
|
12236
12249
|
}
|
|
12237
12250
|
lines.push("");
|
|
12238
|
-
lines.push(theme.
|
|
12251
|
+
lines.push(` ${theme.muted("Docs:")} ${theme.link("github.com/ihatesea69/kiro-kit", data.docsUrl)}`);
|
|
12239
12252
|
const content = lines.join("\n");
|
|
12240
12253
|
const successBox = box.render(content, {
|
|
12241
|
-
title: "Done!",
|
|
12254
|
+
title: " Done! ",
|
|
12242
12255
|
variant: "success"
|
|
12243
12256
|
});
|
|
12244
12257
|
process.stdout.write("\n" + successBox + "\n");
|
|
@@ -12274,10 +12287,72 @@ async function createPrompt(capability, theme) {
|
|
|
12274
12287
|
if (!process.stdin.readable) {
|
|
12275
12288
|
return [];
|
|
12276
12289
|
}
|
|
12290
|
+
let rawModeWorks = false;
|
|
12291
|
+
try {
|
|
12292
|
+
process.stdin.setRawMode(true);
|
|
12293
|
+
process.stdin.setRawMode(false);
|
|
12294
|
+
rawModeWorks = true;
|
|
12295
|
+
} catch {
|
|
12296
|
+
rawModeWorks = false;
|
|
12297
|
+
}
|
|
12298
|
+
if (rawModeWorks) {
|
|
12299
|
+
return multiPickRaw(items);
|
|
12300
|
+
} else {
|
|
12301
|
+
return multiPickLineMode(items);
|
|
12302
|
+
}
|
|
12303
|
+
}
|
|
12304
|
+
async function multiPickLineMode(items) {
|
|
12305
|
+
return new Promise((resolve2, reject) => {
|
|
12306
|
+
process.stdout.write("\n? Select presets to install (enter numbers separated by commas):\n\n");
|
|
12307
|
+
items.forEach((item, i) => {
|
|
12308
|
+
const num = String(i + 1).padStart(2);
|
|
12309
|
+
const name = item.name.padEnd(12);
|
|
12310
|
+
process.stdout.write(` ${num}. ${name} - ${item.description}
|
|
12311
|
+
`);
|
|
12312
|
+
});
|
|
12313
|
+
process.stdout.write("\nExample: 1,3 or 1-3 or all\n");
|
|
12314
|
+
process.stdout.write("Choice: ");
|
|
12315
|
+
const rl = readline2.createInterface({
|
|
12316
|
+
input: process.stdin,
|
|
12317
|
+
output: process.stdout,
|
|
12318
|
+
terminal: false
|
|
12319
|
+
});
|
|
12320
|
+
rl.once("line", (answer) => {
|
|
12321
|
+
rl.close();
|
|
12322
|
+
const a = answer.trim().toLowerCase();
|
|
12323
|
+
if (a === "all" || a === "a") {
|
|
12324
|
+
resolve2(items.map((item) => item.name));
|
|
12325
|
+
return;
|
|
12326
|
+
}
|
|
12327
|
+
const indices = /* @__PURE__ */ new Set();
|
|
12328
|
+
for (const part of a.split(",")) {
|
|
12329
|
+
const range = part.trim().split("-");
|
|
12330
|
+
if (range.length === 2) {
|
|
12331
|
+
const start = parseInt(range[0], 10);
|
|
12332
|
+
const end = parseInt(range[1], 10);
|
|
12333
|
+
if (!isNaN(start) && !isNaN(end)) {
|
|
12334
|
+
for (let i = start; i <= end; i++) indices.add(i - 1);
|
|
12335
|
+
}
|
|
12336
|
+
} else {
|
|
12337
|
+
const n = parseInt(part.trim(), 10);
|
|
12338
|
+
if (!isNaN(n)) indices.add(n - 1);
|
|
12339
|
+
}
|
|
12340
|
+
}
|
|
12341
|
+
const selected = [...indices].filter((i) => i >= 0 && i < items.length).map((i) => items[i].name);
|
|
12342
|
+
resolve2(selected);
|
|
12343
|
+
});
|
|
12344
|
+
rl.on("SIGINT", () => {
|
|
12345
|
+
rl.close();
|
|
12346
|
+
reject(new Error("SIGINT"));
|
|
12347
|
+
});
|
|
12348
|
+
});
|
|
12349
|
+
}
|
|
12350
|
+
async function multiPickRaw(items) {
|
|
12277
12351
|
return new Promise((resolve2, reject) => {
|
|
12278
12352
|
const selected = /* @__PURE__ */ new Set();
|
|
12279
12353
|
let cursor = 0;
|
|
12280
12354
|
let lineCount = 0;
|
|
12355
|
+
let lastEnterCursor = -1;
|
|
12281
12356
|
const cols = process.stdout.columns ?? 80;
|
|
12282
12357
|
const maxDescWidth = Math.max(0, cols - 23);
|
|
12283
12358
|
const render = () => {
|
|
@@ -12286,8 +12361,14 @@ async function createPrompt(capability, theme) {
|
|
|
12286
12361
|
}
|
|
12287
12362
|
const lines = [];
|
|
12288
12363
|
const heading = capability.color ? theme.heading("? Select presets to install:") : "? Select presets to install:";
|
|
12289
|
-
const hint = capability.color ? theme.muted(" (
|
|
12364
|
+
const hint = capability.color ? theme.muted(" (Up/Down: move Enter: select A: all Enter x2: confirm)") : " (Up/Down: move Enter: select A: all Enter x2: confirm)";
|
|
12290
12365
|
lines.push(heading + hint);
|
|
12366
|
+
if (selected.size > 0) {
|
|
12367
|
+
const countLine = capability.color ? " " + theme.success(`${selected.size} selected`) + theme.muted(" \u2014 press Enter again to confirm") : ` ${selected.size} selected \u2014 press Enter again to confirm`;
|
|
12368
|
+
lines.push(countLine);
|
|
12369
|
+
} else {
|
|
12370
|
+
lines.push(capability.color ? theme.muted(" No presets selected yet") : " No presets selected yet");
|
|
12371
|
+
}
|
|
12291
12372
|
for (let i = 0; i < items.length; i++) {
|
|
12292
12373
|
const marker = cursor === i ? capability.color ? theme.command(">") : ">" : " ";
|
|
12293
12374
|
const check = selected.has(i) ? capability.color ? "\x1B[32m[x]\x1B[0m" : "[x]" : "[ ]";
|
|
@@ -12324,11 +12405,13 @@ async function createPrompt(capability, theme) {
|
|
|
12324
12405
|
const handleArrow = (seq) => {
|
|
12325
12406
|
if (seq === "\x1B[A" || seq === "\x1BOA") {
|
|
12326
12407
|
cursor = (cursor - 1 + items.length) % items.length;
|
|
12408
|
+
lastEnterCursor = -1;
|
|
12327
12409
|
render();
|
|
12328
12410
|
return true;
|
|
12329
12411
|
}
|
|
12330
12412
|
if (seq === "\x1B[B" || seq === "\x1BOB") {
|
|
12331
12413
|
cursor = (cursor + 1) % items.length;
|
|
12414
|
+
lastEnterCursor = -1;
|
|
12332
12415
|
render();
|
|
12333
12416
|
return true;
|
|
12334
12417
|
}
|
|
@@ -12361,14 +12444,25 @@ async function createPrompt(capability, theme) {
|
|
|
12361
12444
|
return;
|
|
12362
12445
|
}
|
|
12363
12446
|
if (key === "\r" || key === "\n" || key === "\r\n") {
|
|
12364
|
-
|
|
12365
|
-
|
|
12366
|
-
|
|
12447
|
+
if (lastEnterCursor === cursor && selected.size > 0) {
|
|
12448
|
+
cleanup();
|
|
12449
|
+
process.stdout.write("\n");
|
|
12450
|
+
resolve2([...selected].map((i) => items[i].name));
|
|
12451
|
+
return;
|
|
12452
|
+
}
|
|
12453
|
+
if (selected.has(cursor)) {
|
|
12454
|
+
selected.delete(cursor);
|
|
12455
|
+
} else {
|
|
12456
|
+
selected.add(cursor);
|
|
12457
|
+
}
|
|
12458
|
+
lastEnterCursor = cursor;
|
|
12459
|
+
render();
|
|
12367
12460
|
return;
|
|
12368
12461
|
}
|
|
12369
12462
|
if (key === " ") {
|
|
12370
12463
|
if (selected.has(cursor)) selected.delete(cursor);
|
|
12371
12464
|
else selected.add(cursor);
|
|
12465
|
+
lastEnterCursor = -1;
|
|
12372
12466
|
render();
|
|
12373
12467
|
return;
|
|
12374
12468
|
}
|