@kitnai/cli 0.1.15 → 0.1.17

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 CHANGED
@@ -27,14 +27,27 @@ pnpm dlx @kitnai/cli init
27
27
  Initialize kitn in your project. Creates `kitn.json`, installs the core engine and Hono routes, and sets up tsconfig path aliases.
28
28
 
29
29
  ```bash
30
+ # Interactive (prompts for runtime and base directory)
30
31
  kitn init
32
+
33
+ # Non-interactive with flags
34
+ kitn init --runtime bun --base src/ai
35
+
36
+ # Accept all defaults (runtime=bun, base=src/ai)
37
+ kitn init -y
31
38
  ```
32
39
 
33
- Prompts for:
34
- - **Runtime**: bun, node, or deno
35
- - **Install path**: Base directory for kitn components (defaults to `src/ai`)
40
+ **Flags:**
41
+
42
+ | Flag | Description |
43
+ |------|-------------|
44
+ | `-r, --runtime <runtime>` | Runtime to use (`bun`, `node`, `deno`) — skips runtime prompt |
45
+ | `-b, --base <path>` | Base directory for components (default: `src/ai`) — skips path prompt |
46
+ | `-y, --yes` | Accept all defaults without prompting |
47
+
48
+ When flags are provided, the corresponding prompts are skipped. This enables scripting and CI usage.
36
49
 
37
- After answering, the CLI automatically installs the core engine and HTTP routes into your project.
50
+ After setup, the CLI automatically installs the core engine and HTTP routes into your project.
38
51
 
39
52
  ### `kitn add [components...]`
40
53
 
@@ -180,6 +193,16 @@ kitn build
180
193
  kitn build src/components --output dist/r
181
194
  ```
182
195
 
196
+ ### `kitn check`
197
+
198
+ Check for CLI updates.
199
+
200
+ ```bash
201
+ kitn check
202
+ ```
203
+
204
+ Shows the current version and whether a newer version is available on npm.
205
+
183
206
  ### `kitn registry`
184
207
 
185
208
  Manage component registries.
package/dist/index.js CHANGED
@@ -9,6 +9,86 @@ var __export = (target, all) => {
9
9
  __defProp(target, name, { get: all[name], enumerable: true });
10
10
  };
11
11
 
12
+ // src/utils/update-check.ts
13
+ import { readFile, writeFile, mkdir } from "fs/promises";
14
+ import { join } from "path";
15
+ import { homedir } from "os";
16
+ import pc from "picocolors";
17
+ async function readCache() {
18
+ try {
19
+ const raw = await readFile(CACHE_FILE, "utf-8");
20
+ return JSON.parse(raw);
21
+ } catch {
22
+ return null;
23
+ }
24
+ }
25
+ async function writeCache(entry) {
26
+ try {
27
+ await mkdir(CACHE_DIR, { recursive: true });
28
+ await writeFile(CACHE_FILE, JSON.stringify(entry));
29
+ } catch {
30
+ }
31
+ }
32
+ async function fetchLatestVersion() {
33
+ try {
34
+ const controller = new AbortController();
35
+ const timeout = setTimeout(() => controller.abort(), 3e3);
36
+ const res = await fetch("https://registry.npmjs.org/@kitnai/cli/latest", {
37
+ signal: controller.signal
38
+ });
39
+ clearTimeout(timeout);
40
+ if (!res.ok) return null;
41
+ const data = await res.json();
42
+ return data.version ?? null;
43
+ } catch {
44
+ return null;
45
+ }
46
+ }
47
+ function isNewer(latest, current) {
48
+ const [lMaj, lMin, lPat] = latest.split(".").map(Number);
49
+ const [cMaj, cMin, cPat] = current.split(".").map(Number);
50
+ if (lMaj !== cMaj) return lMaj > cMaj;
51
+ if (lMin !== cMin) return lMin > cMin;
52
+ return lPat > cPat;
53
+ }
54
+ function startUpdateCheck(currentVersion) {
55
+ let message = "";
56
+ const check = (async () => {
57
+ const cache = await readCache();
58
+ let latest = null;
59
+ if (cache && Date.now() - cache.checkedAt < CHECK_INTERVAL) {
60
+ latest = cache.latest;
61
+ } else {
62
+ latest = await fetchLatestVersion();
63
+ if (latest) {
64
+ await writeCache({ latest, checkedAt: Date.now() });
65
+ }
66
+ }
67
+ if (latest && isNewer(latest, currentVersion)) {
68
+ message = [
69
+ "",
70
+ pc.yellow(` Update available: ${pc.dim(currentVersion)} \u2192 ${pc.green(latest)}`),
71
+ pc.dim(` Run ${pc.cyan("npx @kitnai/cli@latest")} or ${pc.cyan("npm i -g @kitnai/cli")}`),
72
+ ""
73
+ ].join("\n");
74
+ }
75
+ })();
76
+ check.catch(() => {
77
+ });
78
+ return () => {
79
+ if (message) process.stderr.write(message);
80
+ };
81
+ }
82
+ var CACHE_DIR, CACHE_FILE, CHECK_INTERVAL;
83
+ var init_update_check = __esm({
84
+ "src/utils/update-check.ts"() {
85
+ "use strict";
86
+ CACHE_DIR = join(homedir(), ".kitn");
87
+ CACHE_FILE = join(CACHE_DIR, "update-check.json");
88
+ CHECK_INTERVAL = 60 * 60 * 1e3;
89
+ }
90
+ });
91
+
12
92
  // src/utils/config.ts
13
93
  import { readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
14
94
  import { join as join2 } from "path";
@@ -103,6 +183,20 @@ function patchTsconfig(tsconfigContent, paths, removePrefixes) {
103
183
  for (const [key, value] of Object.entries(paths)) {
104
184
  config.compilerOptions.paths[key] = value;
105
185
  }
186
+ const ES_TARGETS = ["es3", "es5", "es6", "es2015", "es2016", "es2017", "es2018", "es2019", "es2020", "es2021"];
187
+ const currentTarget = (config.compilerOptions.target ?? "").toLowerCase();
188
+ if (!currentTarget || ES_TARGETS.includes(currentTarget)) {
189
+ config.compilerOptions.target = "ES2022";
190
+ }
191
+ if (!config.compilerOptions.moduleResolution) {
192
+ config.compilerOptions.moduleResolution = "bundler";
193
+ }
194
+ if (!config.compilerOptions.module) {
195
+ config.compilerOptions.module = "ESNext";
196
+ }
197
+ if (config.compilerOptions.skipLibCheck === void 0) {
198
+ config.compilerOptions.skipLibCheck = true;
199
+ }
106
200
  return JSON.stringify(config, null, 2) + "\n";
107
201
  }
108
202
  async function patchProjectTsconfig(projectDir, paths, removePrefixes) {
@@ -341,6 +435,23 @@ function installDependencies(pm, deps, projectDir) {
341
435
  })();
342
436
  execSync(cmd, { cwd: projectDir, stdio: "pipe" });
343
437
  }
438
+ function installDevDependencies(pm, deps, projectDir) {
439
+ if (deps.length === 0) return;
440
+ const pkgs = deps.join(" ");
441
+ const cmd = (() => {
442
+ switch (pm) {
443
+ case "bun":
444
+ return `bun add -d ${pkgs}`;
445
+ case "pnpm":
446
+ return `pnpm add -D ${pkgs}`;
447
+ case "yarn":
448
+ return `yarn add -D ${pkgs}`;
449
+ case "npm":
450
+ return `npm install -D ${pkgs}`;
451
+ }
452
+ })();
453
+ execSync(cmd, { cwd: projectDir, stdio: "pipe" });
454
+ }
344
455
  var init_dep_installer = __esm({
345
456
  "src/installers/dep-installer.ts"() {
346
457
  "use strict";
@@ -679,8 +790,17 @@ async function addCommand(components, opts) {
679
790
  const updated = [];
680
791
  const skipped = [];
681
792
  const allDeps = [];
793
+ const allDevDeps = [];
682
794
  for (const item of resolved) {
683
795
  if (item.dependencies) allDeps.push(...item.dependencies);
796
+ if (item.devDependencies) allDevDeps.push(...item.devDependencies);
797
+ const existingInstall = (config.installed ?? {})[item.name];
798
+ if (existingInstall && item.type === "kitn:package") {
799
+ const allContent = item.files.map((f) => f.content).join("\n");
800
+ if (contentHash(allContent) === existingInstall.hash) {
801
+ continue;
802
+ }
803
+ }
684
804
  if (item.type === "kitn:package") {
685
805
  const baseDir2 = config.aliases.base ?? "src/ai";
686
806
  for (const file of item.files) {
@@ -850,12 +970,15 @@ async function addCommand(components, opts) {
850
970
  }
851
971
  await writeConfig(cwd, config);
852
972
  const uniqueDeps = [...new Set(allDeps)];
853
- if (uniqueDeps.length > 0) {
973
+ const uniqueDevDeps = [...new Set(allDevDeps)].filter((d) => !uniqueDeps.includes(d));
974
+ const totalDeps = uniqueDeps.length + uniqueDevDeps.length;
975
+ if (totalDeps > 0) {
854
976
  const pm = await detectPackageManager(cwd);
855
977
  if (pm) {
856
- s.start(`Installing ${uniqueDeps.length} npm dependenc${uniqueDeps.length === 1 ? "y" : "ies"}...`);
978
+ s.start(`Installing ${totalDeps} npm dependenc${totalDeps === 1 ? "y" : "ies"}...`);
857
979
  try {
858
- installDependencies(pm, uniqueDeps, cwd);
980
+ if (uniqueDeps.length > 0) installDependencies(pm, uniqueDeps, cwd);
981
+ if (uniqueDevDeps.length > 0) installDevDependencies(pm, uniqueDevDeps, cwd);
859
982
  s.stop("Dependencies installed");
860
983
  } catch {
861
984
  s.stop(pc3.yellow("Some dependencies failed to install"));
@@ -863,7 +986,7 @@ async function addCommand(components, opts) {
863
986
  }
864
987
  }
865
988
  if (created.length > 0) {
866
- p2.log.success(`Created ${created.length} file(s):
989
+ p2.log.success(`Added ${created.length} file(s):
867
990
  ` + created.map((f) => ` ${pc3.green("+")} ${f}`).join("\n"));
868
991
  }
869
992
  if (updated.length > 0) {
@@ -881,13 +1004,14 @@ async function addCommand(components, opts) {
881
1004
  p2.log.info(`${pc3.bold(item.name)}: ${item.docs}`);
882
1005
  }
883
1006
  }
884
- const installedNames = new Set(resolved.map((r) => r.name));
1007
+ const resolvedNames = new Set(resolved.map((r) => r.name));
1008
+ const projectInstalled = new Set(Object.keys(config.installed ?? {}));
885
1009
  const hints = [];
886
- if (installedNames.has("core") && !installedNames.has(config.framework ?? "hono")) {
1010
+ const fw = config.framework ?? "hono";
1011
+ if (resolvedNames.has("core") && !resolvedNames.has(fw) && !projectInstalled.has(fw)) {
887
1012
  hints.push(`Run ${pc3.cyan(`kitn add routes`)} to install the HTTP adapter.`);
888
1013
  }
889
- const fw = config.framework ?? "hono";
890
- if (installedNames.has(fw) || installedNames.has("core") && installedNames.has(fw)) {
1014
+ if (resolvedNames.has(fw)) {
891
1015
  hints.push(`Configure your AI provider in ${pc3.bold(baseDir + "/plugin.ts")}, then add to your server:`);
892
1016
  hints.push("");
893
1017
  hints.push(pc3.dim(` import { ai } from "./${baseDir.replace(/^src\//, "")}/plugin";`));
@@ -928,43 +1052,66 @@ import * as p3 from "@clack/prompts";
928
1052
  import pc4 from "picocolors";
929
1053
  import { mkdir as mkdir4, writeFile as writeFile7 } from "fs/promises";
930
1054
  import { join as join8 } from "path";
931
- async function initCommand() {
1055
+ async function initCommand(opts = {}) {
932
1056
  p3.intro(pc4.bgCyan(pc4.black(" kitn init ")));
933
1057
  const cwd = process.cwd();
934
1058
  const existing = await readConfig(cwd);
935
1059
  if (existing) {
936
- p3.log.warn("kitn.json already exists in this directory.");
937
- const shouldContinue = await p3.confirm({
938
- message: "Overwrite existing configuration?",
939
- initialValue: false
1060
+ if (opts.yes) {
1061
+ p3.log.warn("kitn.json already exists \u2014 overwriting (--yes).");
1062
+ } else {
1063
+ p3.log.warn("kitn.json already exists in this directory.");
1064
+ const shouldContinue = await p3.confirm({
1065
+ message: "Overwrite existing configuration?",
1066
+ initialValue: false
1067
+ });
1068
+ if (p3.isCancel(shouldContinue) || !shouldContinue) {
1069
+ p3.cancel("Init cancelled.");
1070
+ process.exit(0);
1071
+ }
1072
+ }
1073
+ }
1074
+ let runtime;
1075
+ if (opts.runtime) {
1076
+ if (!["bun", "node", "deno"].includes(opts.runtime)) {
1077
+ p3.log.error(`Invalid runtime: ${opts.runtime}. Must be bun, node, or deno.`);
1078
+ process.exit(1);
1079
+ }
1080
+ runtime = opts.runtime;
1081
+ } else if (opts.yes) {
1082
+ runtime = "bun";
1083
+ } else {
1084
+ const selected = await p3.select({
1085
+ message: "Which runtime do you use?",
1086
+ options: [
1087
+ { value: "bun", label: "Bun", hint: "recommended" },
1088
+ { value: "node", label: "Node.js" },
1089
+ { value: "deno", label: "Deno" }
1090
+ ]
940
1091
  });
941
- if (p3.isCancel(shouldContinue) || !shouldContinue) {
1092
+ if (p3.isCancel(selected)) {
942
1093
  p3.cancel("Init cancelled.");
943
1094
  process.exit(0);
944
1095
  }
1096
+ runtime = selected;
945
1097
  }
946
- const runtime = await p3.select({
947
- message: "Which runtime do you use?",
948
- options: [
949
- { value: "bun", label: "Bun", hint: "recommended" },
950
- { value: "node", label: "Node.js" },
951
- { value: "deno", label: "Deno" }
952
- ]
953
- });
954
- if (p3.isCancel(runtime)) {
955
- p3.cancel("Init cancelled.");
956
- process.exit(0);
957
- }
958
- const base = await p3.text({
959
- message: "Where should kitn components be installed?",
960
- initialValue: "src/ai",
961
- placeholder: "src/ai"
962
- });
963
- if (p3.isCancel(base)) {
964
- p3.cancel("Init cancelled.");
965
- process.exit(0);
1098
+ let baseDir;
1099
+ if (opts.base) {
1100
+ baseDir = opts.base;
1101
+ } else if (opts.yes) {
1102
+ baseDir = "src/ai";
1103
+ } else {
1104
+ const base = await p3.text({
1105
+ message: "Where should kitn components be installed?",
1106
+ initialValue: "src/ai",
1107
+ placeholder: "src/ai"
1108
+ });
1109
+ if (p3.isCancel(base)) {
1110
+ p3.cancel("Init cancelled.");
1111
+ process.exit(0);
1112
+ }
1113
+ baseDir = base;
966
1114
  }
967
- const baseDir = base;
968
1115
  const config = {
969
1116
  runtime,
970
1117
  framework: "hono",
@@ -1011,6 +1158,15 @@ async function initCommand() {
1011
1158
  ].join("\n"),
1012
1159
  "Add this to your server entry point:"
1013
1160
  );
1161
+ p3.log.message(
1162
+ [
1163
+ pc4.bold("Add your first agent:"),
1164
+ ` ${pc4.cyan("kitn add weather-agent")}`,
1165
+ "",
1166
+ pc4.bold("Browse all components:"),
1167
+ ` ${pc4.cyan("kitn list")}`
1168
+ ].join("\n")
1169
+ );
1014
1170
  p3.outro("Done!");
1015
1171
  }
1016
1172
  var PLUGIN_TEMPLATE;
@@ -1422,8 +1578,8 @@ async function scanForComponents(cwd, paths) {
1422
1578
  const resolvedCwd = resolve(cwd);
1423
1579
  if (paths && paths.length > 0) {
1424
1580
  const results = [];
1425
- for (const p12 of paths) {
1426
- const absPath = resolve(resolvedCwd, p12);
1581
+ for (const p13 of paths) {
1582
+ const absPath = resolve(resolvedCwd, p13);
1427
1583
  if (await fileExists(join11(absPath, "registry.json"))) {
1428
1584
  results.push(absPath);
1429
1585
  continue;
@@ -2063,6 +2219,39 @@ var init_info = __esm({
2063
2219
  }
2064
2220
  });
2065
2221
 
2222
+ // src/commands/check.ts
2223
+ var check_exports = {};
2224
+ __export(check_exports, {
2225
+ checkCommand: () => checkCommand
2226
+ });
2227
+ import * as p11 from "@clack/prompts";
2228
+ import pc10 from "picocolors";
2229
+ async function checkCommand(currentVersion) {
2230
+ p11.intro(pc10.bgCyan(pc10.black(" kitn check ")));
2231
+ p11.log.info(`kitn v${currentVersion}`);
2232
+ const s = p11.spinner();
2233
+ s.start("Checking for updates...");
2234
+ const latest = await fetchLatestVersion();
2235
+ if (!latest) {
2236
+ s.stop(pc10.yellow("Could not reach the npm registry"));
2237
+ p11.outro("Try again later.");
2238
+ return;
2239
+ }
2240
+ if (isNewer(latest, currentVersion)) {
2241
+ s.stop(pc10.yellow(`Update available: ${currentVersion} \u2192 ${latest}`));
2242
+ p11.log.message(` Run: ${pc10.cyan("npm i -g @kitnai/cli")}`);
2243
+ } else {
2244
+ s.stop(pc10.green("You're on the latest version"));
2245
+ }
2246
+ p11.outro("");
2247
+ }
2248
+ var init_check = __esm({
2249
+ "src/commands/check.ts"() {
2250
+ "use strict";
2251
+ init_update_check();
2252
+ }
2253
+ });
2254
+
2066
2255
  // src/commands/registry.ts
2067
2256
  var registry_exports = {};
2068
2257
  __export(registry_exports, {
@@ -2070,8 +2259,8 @@ __export(registry_exports, {
2070
2259
  registryListCommand: () => registryListCommand,
2071
2260
  registryRemoveCommand: () => registryRemoveCommand
2072
2261
  });
2073
- import * as p11 from "@clack/prompts";
2074
- import pc10 from "picocolors";
2262
+ import * as p12 from "@clack/prompts";
2263
+ import pc11 from "picocolors";
2075
2264
  async function registryAddCommand(namespace, url, opts = {}) {
2076
2265
  const cwd = opts.cwd ?? process.cwd();
2077
2266
  const config = await readConfig(cwd);
@@ -2097,10 +2286,10 @@ async function registryAddCommand(namespace, url, opts = {}) {
2097
2286
  config.registries[namespace] = url;
2098
2287
  }
2099
2288
  await writeConfig(cwd, config);
2100
- p11.log.success(`Added registry ${pc10.bold(namespace)}`);
2101
- p11.log.message(pc10.dim(` ${url}`));
2102
- if (opts.homepage) p11.log.message(pc10.dim(` Homepage: ${opts.homepage}`));
2103
- if (opts.description) p11.log.message(pc10.dim(` ${opts.description}`));
2289
+ p12.log.success(`Added registry ${pc11.bold(namespace)}`);
2290
+ p12.log.message(pc11.dim(` ${url}`));
2291
+ if (opts.homepage) p12.log.message(pc11.dim(` Homepage: ${opts.homepage}`));
2292
+ if (opts.description) p12.log.message(pc11.dim(` ${opts.description}`));
2104
2293
  }
2105
2294
  async function registryRemoveCommand(namespace, opts = {}) {
2106
2295
  const cwd = opts.cwd ?? process.cwd();
@@ -2122,10 +2311,10 @@ async function registryRemoveCommand(namespace, opts = {}) {
2122
2311
  }
2123
2312
  delete config.registries[namespace];
2124
2313
  await writeConfig(cwd, config);
2125
- p11.log.success(`Removed registry ${pc10.bold(namespace)}`);
2314
+ p12.log.success(`Removed registry ${pc11.bold(namespace)}`);
2126
2315
  if (affectedComponents.length > 0) {
2127
- p11.log.warn(`${affectedComponents.length} installed component(s) referenced this registry:
2128
- ` + affectedComponents.map((name) => ` ${pc10.yellow("!")} ${name}`).join("\n"));
2316
+ p12.log.warn(`${affectedComponents.length} installed component(s) referenced this registry:
2317
+ ` + affectedComponents.map((name) => ` ${pc11.yellow("!")} ${name}`).join("\n"));
2129
2318
  }
2130
2319
  return { affectedComponents };
2131
2320
  }
@@ -2140,15 +2329,15 @@ async function registryListCommand(opts = {}) {
2140
2329
  return { namespace, url, homepage, description };
2141
2330
  });
2142
2331
  if (entries.length === 0) {
2143
- p11.log.message(pc10.dim(" No registries configured."));
2332
+ p12.log.message(pc11.dim(" No registries configured."));
2144
2333
  } else {
2145
2334
  const lines = [];
2146
2335
  for (const { namespace, url, homepage, description } of entries) {
2147
- lines.push(` ${pc10.bold(namespace.padEnd(16))} ${pc10.dim(url)}`);
2336
+ lines.push(` ${pc11.bold(namespace.padEnd(16))} ${pc11.dim(url)}`);
2148
2337
  if (description) lines.push(` ${" ".repeat(16)} ${description}`);
2149
- if (homepage) lines.push(` ${" ".repeat(16)} ${pc10.dim(homepage)}`);
2338
+ if (homepage) lines.push(` ${" ".repeat(16)} ${pc11.dim(homepage)}`);
2150
2339
  }
2151
- p11.log.message(lines.join("\n"));
2340
+ p12.log.message(lines.join("\n"));
2152
2341
  }
2153
2342
  return entries;
2154
2343
  }
@@ -2160,89 +2349,14 @@ var init_registry = __esm({
2160
2349
  });
2161
2350
 
2162
2351
  // src/index.ts
2352
+ init_update_check();
2163
2353
  import { Command } from "commander";
2164
-
2165
- // src/utils/update-check.ts
2166
- import { readFile, writeFile, mkdir } from "fs/promises";
2167
- import { join } from "path";
2168
- import { homedir } from "os";
2169
- import pc from "picocolors";
2170
- var CACHE_DIR = join(homedir(), ".kitn");
2171
- var CACHE_FILE = join(CACHE_DIR, "update-check.json");
2172
- var CHECK_INTERVAL = 60 * 60 * 1e3;
2173
- async function readCache() {
2174
- try {
2175
- const raw = await readFile(CACHE_FILE, "utf-8");
2176
- return JSON.parse(raw);
2177
- } catch {
2178
- return null;
2179
- }
2180
- }
2181
- async function writeCache(entry) {
2182
- try {
2183
- await mkdir(CACHE_DIR, { recursive: true });
2184
- await writeFile(CACHE_FILE, JSON.stringify(entry));
2185
- } catch {
2186
- }
2187
- }
2188
- async function fetchLatestVersion() {
2189
- try {
2190
- const controller = new AbortController();
2191
- const timeout = setTimeout(() => controller.abort(), 3e3);
2192
- const res = await fetch("https://registry.npmjs.org/@kitnai/cli/latest", {
2193
- signal: controller.signal
2194
- });
2195
- clearTimeout(timeout);
2196
- if (!res.ok) return null;
2197
- const data = await res.json();
2198
- return data.version ?? null;
2199
- } catch {
2200
- return null;
2201
- }
2202
- }
2203
- function isNewer(latest, current) {
2204
- const [lMaj, lMin, lPat] = latest.split(".").map(Number);
2205
- const [cMaj, cMin, cPat] = current.split(".").map(Number);
2206
- if (lMaj !== cMaj) return lMaj > cMaj;
2207
- if (lMin !== cMin) return lMin > cMin;
2208
- return lPat > cPat;
2209
- }
2210
- function startUpdateCheck(currentVersion) {
2211
- let message = "";
2212
- const check = (async () => {
2213
- const cache = await readCache();
2214
- let latest = null;
2215
- if (cache && Date.now() - cache.checkedAt < CHECK_INTERVAL) {
2216
- latest = cache.latest;
2217
- } else {
2218
- latest = await fetchLatestVersion();
2219
- if (latest) {
2220
- await writeCache({ latest, checkedAt: Date.now() });
2221
- }
2222
- }
2223
- if (latest && isNewer(latest, currentVersion)) {
2224
- message = [
2225
- "",
2226
- pc.yellow(` Update available: ${pc.dim(currentVersion)} \u2192 ${pc.green(latest)}`),
2227
- pc.dim(` Run ${pc.cyan("npx @kitnai/cli@latest")} or ${pc.cyan("npm i -g @kitnai/cli")}`),
2228
- ""
2229
- ].join("\n");
2230
- }
2231
- })();
2232
- check.catch(() => {
2233
- });
2234
- return () => {
2235
- if (message) process.stderr.write(message);
2236
- };
2237
- }
2238
-
2239
- // src/index.ts
2240
- var VERSION = true ? "0.1.15" : "0.0.0-dev";
2354
+ var VERSION = true ? "0.1.17" : "0.0.0-dev";
2241
2355
  var printUpdateNotice = startUpdateCheck(VERSION);
2242
2356
  var program = new Command().name("kitn").description("Install AI agent components from the kitn registry").version(VERSION);
2243
- program.command("init").description("Initialize kitn in your project").action(async () => {
2357
+ program.command("init").description("Initialize kitn in your project").option("-r, --runtime <runtime>", "runtime to use (bun, node, deno)").option("-b, --base <path>", "base directory for components (default: src/ai)").option("-y, --yes", "accept all defaults without prompting").action(async (opts) => {
2244
2358
  const { initCommand: initCommand2 } = await Promise.resolve().then(() => (init_init(), init_exports));
2245
- await initCommand2();
2359
+ await initCommand2(opts);
2246
2360
  });
2247
2361
  program.command("add").description("Add components from the kitn registry").argument("[components...]", "component names to install").option("-o, --overwrite", "overwrite existing files without prompting").option("-t, --type <type>", "filter by component type").action(async (components, opts) => {
2248
2362
  const { addCommand: addCommand2 } = await Promise.resolve().then(() => (init_add(), add_exports));
@@ -2276,6 +2390,10 @@ program.command("info").description("Show details about a component").argument("
2276
2390
  const { infoCommand: infoCommand2 } = await Promise.resolve().then(() => (init_info(), info_exports));
2277
2391
  await infoCommand2(component);
2278
2392
  });
2393
+ program.command("check").description("Check for CLI updates").action(async () => {
2394
+ const { checkCommand: checkCommand2 } = await Promise.resolve().then(() => (init_check(), check_exports));
2395
+ await checkCommand2(VERSION);
2396
+ });
2279
2397
  var registry = program.command("registry").description("Manage component registries");
2280
2398
  registry.command("add").description("Add a component registry").argument("<namespace>", "registry namespace (e.g. @myteam)").argument("<url>", "URL template with {type} and {name} placeholders").option("-o, --overwrite", "overwrite if namespace already exists").option("--homepage <url>", "registry homepage URL").option("--description <text>", "short description of the registry").action(async (namespace, url, opts) => {
2281
2399
  const { registryAddCommand: registryAddCommand2 } = await Promise.resolve().then(() => (init_registry(), registry_exports));