@kitnai/cli 0.1.24 → 0.1.26

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
@@ -140,7 +140,7 @@ Outputs a unified diff for each file in the component. Shows "up to date" if the
140
140
 
141
141
  ### `kitn remove <component>`
142
142
 
143
- Remove an installed component. Deletes files and removes tracking from `kitn.json`.
143
+ Remove an installed component. Deletes files and removes tracking from `kitn.lock`.
144
144
 
145
145
  ```bash
146
146
  kitn remove weather-agent
@@ -279,7 +279,8 @@ Created by `kitn init`. Controls where components are installed and which regist
279
279
  | `framework` | `hono` |
280
280
  | `aliases` | Directory paths for each component type |
281
281
  | `registries` | Named registries — each value is a URL string or an object with `url`, `homepage`, `description` |
282
- | `installed` | Auto-managed tracking of installed components (don't edit manually) |
282
+
283
+ > Installed component tracking (file paths, content hashes, versions) is stored separately in `kitn.lock`. This file is auto-managed — don't edit it manually.
283
284
 
284
285
  ### Registry entries
285
286
 
@@ -313,7 +314,7 @@ The CLI automatically detects your package manager by checking for lockfiles in
313
314
 
314
315
  Components are **source code**, not packages. `kitn add` copies TypeScript files directly into your project. You own the code and can modify it freely.
315
316
 
316
- The CLI tracks what it installed in `kitn.json` under `installed`, storing file paths and content hashes. This enables `kitn diff` to detect local changes and `kitn update` to apply registry updates.
317
+ The CLI tracks what it installed in `kitn.lock`, storing file paths and content hashes. This enables `kitn diff` to detect local changes and `kitn update` to apply registry updates.
317
318
 
318
319
  ### Hosting your own registry
319
320
 
package/dist/index.js CHANGED
@@ -157,7 +157,7 @@ var init_update_check = __esm({
157
157
  });
158
158
 
159
159
  // src/utils/config.ts
160
- import { readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
160
+ import { readFile as readFile2, writeFile as writeFile2, unlink } from "fs/promises";
161
161
  import { join as join3 } from "path";
162
162
  import { z } from "zod";
163
163
  function getRegistryUrl(entry) {
@@ -179,6 +179,24 @@ async function writeConfig(projectDir, config) {
179
179
  const data = { $schema: "https://kitn.dev/schema/config.json", ...config };
180
180
  await writeFile2(join3(projectDir, CONFIG_FILE), JSON.stringify(data, null, 2) + "\n");
181
181
  }
182
+ async function readLock(projectDir) {
183
+ try {
184
+ const raw = await readFile2(join3(projectDir, LOCK_FILE), "utf-8");
185
+ return lockSchema.parse(JSON.parse(raw));
186
+ } catch {
187
+ return {};
188
+ }
189
+ }
190
+ async function writeLock(projectDir, lock) {
191
+ if (Object.keys(lock).length === 0) {
192
+ try {
193
+ await unlink(join3(projectDir, LOCK_FILE));
194
+ } catch {
195
+ }
196
+ return;
197
+ }
198
+ await writeFile2(join3(projectDir, LOCK_FILE), JSON.stringify(lock, null, 2) + "\n");
199
+ }
182
200
  function getInstallPath(config, type, fileName, namespace) {
183
201
  const aliasKey = typeToAliasKey[type];
184
202
  const base = config.aliases[aliasKey];
@@ -188,14 +206,14 @@ function getInstallPath(config, type, fileName, namespace) {
188
206
  }
189
207
  return join3(base, fileName);
190
208
  }
191
- var componentType, installedComponentSchema, registryEntrySchema, registryValueSchema, configSchema, FRAMEWORK_TO_ADAPTER, CONFIG_FILE, typeToAliasKey;
209
+ var componentType, installedComponentSchema, registryEntrySchema, registryValueSchema, configSchema, FRAMEWORK_TO_ADAPTER, CONFIG_FILE, LOCK_FILE, lockSchema, typeToAliasKey;
192
210
  var init_config = __esm({
193
211
  "src/utils/config.ts"() {
194
212
  "use strict";
195
213
  componentType = z.enum(["kitn:agent", "kitn:tool", "kitn:skill", "kitn:storage", "kitn:package"]);
196
214
  installedComponentSchema = z.object({
197
215
  registry: z.string().optional(),
198
- type: componentType,
216
+ type: componentType.optional(),
199
217
  slot: z.string().optional(),
200
218
  version: z.string(),
201
219
  installedAt: z.string(),
@@ -220,8 +238,7 @@ var init_config = __esm({
220
238
  skills: z.string(),
221
239
  storage: z.string()
222
240
  }),
223
- registries: z.record(z.string(), registryValueSchema),
224
- installed: z.record(z.string(), installedComponentSchema).optional()
241
+ registries: z.record(z.string(), registryValueSchema)
225
242
  });
226
243
  FRAMEWORK_TO_ADAPTER = {
227
244
  hono: "hono",
@@ -229,6 +246,8 @@ var init_config = __esm({
229
246
  elysia: "elysia"
230
247
  };
231
248
  CONFIG_FILE = "kitn.json";
249
+ LOCK_FILE = "kitn.lock";
250
+ lockSchema = z.record(z.string(), installedComponentSchema);
232
251
  typeToAliasKey = {
233
252
  "kitn:agent": "agents",
234
253
  "kitn:tool": "tools",
@@ -830,7 +849,7 @@ import * as p2 from "@clack/prompts";
830
849
  import pc3 from "picocolors";
831
850
  import { join as join7, dirname as dirname3 } from "path";
832
851
  import { existsSync } from "fs";
833
- import { readFile as readFile6, writeFile as writeFile6, mkdir as mkdir3, unlink } from "fs/promises";
852
+ import { readFile as readFile6, writeFile as writeFile6, mkdir as mkdir3, unlink as unlink2 } from "fs/promises";
834
853
  import { relative as relative2 } from "path";
835
854
  async function addCommand(components, opts) {
836
855
  p2.intro(pc3.bgCyan(pc3.black(" kitn add ")));
@@ -840,6 +859,7 @@ async function addCommand(components, opts) {
840
859
  p2.log.error("No kitn.json found. Run `kitn init` first.");
841
860
  process.exit(1);
842
861
  }
862
+ const lock = await readLock(cwd);
843
863
  if (components.length === 0) {
844
864
  const fetcher2 = new RegistryFetcher(config.registries);
845
865
  const s2 = p2.spinner();
@@ -859,7 +879,7 @@ async function addCommand(components, opts) {
859
879
  p2.log.warn("No components found in configured registries.");
860
880
  process.exit(0);
861
881
  }
862
- const installed = new Set(Object.keys(config.installed ?? {}));
882
+ const installed = new Set(Object.keys(lock));
863
883
  const typeLabels = {
864
884
  "kitn:agent": "Agents",
865
885
  "kitn:tool": "Tools",
@@ -1056,7 +1076,7 @@ async function addCommand(components, opts) {
1056
1076
  const slotReplacements = /* @__PURE__ */ new Map();
1057
1077
  for (const item of resolved) {
1058
1078
  if (!item.slot) continue;
1059
- const existing = Object.entries(config.installed ?? {}).find(
1079
+ const existing = Object.entries(lock).find(
1060
1080
  ([key, entry]) => key !== item.name && entry.slot === item.slot
1061
1081
  );
1062
1082
  if (!existing) continue;
@@ -1079,11 +1099,11 @@ async function addCommand(components, opts) {
1079
1099
  if (slotReplacements.size > 0) {
1080
1100
  const baseDir2 = config.aliases.base ?? "src/ai";
1081
1101
  for (const [oldKey] of slotReplacements) {
1082
- const oldEntry = config.installed[oldKey];
1102
+ const oldEntry = lock[oldKey];
1083
1103
  if (!oldEntry) continue;
1084
1104
  for (const filePath of oldEntry.files) {
1085
1105
  try {
1086
- await unlink(join7(cwd, filePath));
1106
+ await unlink2(join7(cwd, filePath));
1087
1107
  } catch {
1088
1108
  }
1089
1109
  }
@@ -1111,7 +1131,7 @@ async function addCommand(components, opts) {
1111
1131
  await writeFile6(barrelPath2, barrelContent);
1112
1132
  }
1113
1133
  }
1114
- delete config.installed[oldKey];
1134
+ delete lock[oldKey];
1115
1135
  p2.log.info(`Replaced ${pc3.dim(oldKey)} \u2192 ${pc3.cyan(slotReplacements.get(oldKey))}`);
1116
1136
  }
1117
1137
  }
@@ -1128,7 +1148,7 @@ async function addCommand(components, opts) {
1128
1148
  for (const item of resolved) {
1129
1149
  if (item.dependencies) allDeps.push(...item.dependencies);
1130
1150
  if (item.devDependencies) allDevDeps.push(...item.devDependencies);
1131
- const existingInstall = (config.installed ?? {})[item.name];
1151
+ const existingInstall = lock[item.name];
1132
1152
  if (existingInstall && item.type === "kitn:package") {
1133
1153
  const allContent = item.files.map((f) => f.content).join("\n");
1134
1154
  if (contentHash(allContent) === existingInstall.hash) {
@@ -1174,11 +1194,10 @@ async function addCommand(components, opts) {
1174
1194
  break;
1175
1195
  }
1176
1196
  }
1177
- const installed = config.installed ?? {};
1178
1197
  const allContent = item.files.map((f) => f.content).join("\n");
1179
1198
  const ref = refs.find((r) => r.name === item.name) ?? { namespace: "@kitn", name: item.name, version: void 0 };
1180
1199
  const installedKey = ref.namespace === "@kitn" ? item.name : `${ref.namespace}/${item.name}`;
1181
- installed[installedKey] = {
1200
+ lock[installedKey] = {
1182
1201
  registry: ref.namespace,
1183
1202
  type: item.type,
1184
1203
  ...item.slot && { slot: item.slot },
@@ -1188,7 +1207,6 @@ async function addCommand(components, opts) {
1188
1207
  hash: contentHash(allContent),
1189
1208
  registryDependencies: item.registryDependencies
1190
1209
  };
1191
- config.installed = installed;
1192
1210
  } else {
1193
1211
  const ref = refs.find((r) => r.name === item.name) ?? { namespace: "@kitn", name: item.name, version: void 0 };
1194
1212
  const ns = ref.namespace;
@@ -1244,13 +1262,12 @@ async function addCommand(components, opts) {
1244
1262
  break;
1245
1263
  }
1246
1264
  }
1247
- const installed = config.installed ?? {};
1248
1265
  const allContent = item.files.map((f) => {
1249
1266
  const fn = f.path.split("/").pop();
1250
1267
  return rewriteKitnImports(f.content, item.type, fn, config.aliases);
1251
1268
  }).join("\n");
1252
1269
  const installedKey = ns === "@kitn" ? item.name : `${ns}/${item.name}`;
1253
- installed[installedKey] = {
1270
+ lock[installedKey] = {
1254
1271
  registry: ns,
1255
1272
  type: item.type,
1256
1273
  ...item.slot && { slot: item.slot },
@@ -1263,7 +1280,6 @@ async function addCommand(components, opts) {
1263
1280
  hash: contentHash(allContent),
1264
1281
  registryDependencies: item.registryDependencies
1265
1282
  };
1266
- config.installed = installed;
1267
1283
  }
1268
1284
  }
1269
1285
  const BARREL_ELIGIBLE = /* @__PURE__ */ new Set(["kitn:agent", "kitn:tool", "kitn:skill"]);
@@ -1299,7 +1315,7 @@ async function addCommand(components, opts) {
1299
1315
  if (!barrelExisted) {
1300
1316
  p2.note(
1301
1317
  [
1302
- `import { ai } from "./${baseDir.replace(/^src\//, "")}/plugin";`,
1318
+ `import { ai } from "@kitn/plugin";`,
1303
1319
  ``,
1304
1320
  `app.route("/api", ai.router);`
1305
1321
  ].join("\n"),
@@ -1308,6 +1324,7 @@ async function addCommand(components, opts) {
1308
1324
  }
1309
1325
  }
1310
1326
  await writeConfig(cwd, config);
1327
+ await writeLock(cwd, lock);
1311
1328
  const uniqueDeps = [...new Set(allDeps)];
1312
1329
  const uniqueDevDeps = [...new Set(allDevDeps)].filter((d) => !uniqueDeps.includes(d));
1313
1330
  const totalDeps = uniqueDeps.length + uniqueDevDeps.length;
@@ -1344,7 +1361,7 @@ async function addCommand(components, opts) {
1344
1361
  }
1345
1362
  }
1346
1363
  const resolvedNames = new Set(resolved.map((r) => r.name));
1347
- const projectInstalled = new Set(Object.keys(config.installed ?? {}));
1364
+ const projectInstalled = new Set(Object.keys(lock));
1348
1365
  const hints = [];
1349
1366
  const adapterName = resolveRoutesAlias(config);
1350
1367
  if (resolvedNames.has("core") && !resolvedNames.has(adapterName) && !projectInstalled.has(adapterName)) {
@@ -1530,7 +1547,7 @@ async function initCommand(opts = {}) {
1530
1547
  const mountCode = framework === "elysia" ? `app.use(ai.router);` : `app.route("/api", ai.router);`;
1531
1548
  p3.note(
1532
1549
  [
1533
- `import { ai } from "./${baseDir.replace(/^src\//, "")}/plugin";`,
1550
+ `import { ai } from "@kitn/plugin";`,
1534
1551
  ``,
1535
1552
  mountCode
1536
1553
  ].join("\n"),
@@ -1606,7 +1623,7 @@ async function listCommand(typeFilter, opts) {
1606
1623
  for (const e of errors) {
1607
1624
  p4.log.warn(`${pc5.yellow("\u26A0")} Failed to fetch ${e}`);
1608
1625
  }
1609
- const installed = config.installed ?? {};
1626
+ const installed = await readLock(cwd);
1610
1627
  const typeGroups = /* @__PURE__ */ new Map();
1611
1628
  for (const item of allItems) {
1612
1629
  const group = item.type.replace("kitn:", "");
@@ -1699,8 +1716,9 @@ async function diffCommand(componentName) {
1699
1716
  }
1700
1717
  const input = componentName === "routes" ? resolveRoutesAlias(config) : componentName;
1701
1718
  const ref = parseComponentRef(input);
1719
+ const lock = await readLock(cwd);
1702
1720
  const installedKey = ref.namespace === "@kitn" ? ref.name : `${ref.namespace}/${ref.name}`;
1703
- const installed = config.installed?.[installedKey];
1721
+ const installed = lock[installedKey];
1704
1722
  if (!installed) {
1705
1723
  p5.log.error(`Component '${ref.name}' is not installed.`);
1706
1724
  process.exit(1);
@@ -1779,15 +1797,15 @@ __export(remove_exports, {
1779
1797
  import * as p6 from "@clack/prompts";
1780
1798
  import pc6 from "picocolors";
1781
1799
  import { join as join10, relative as relative3, dirname as dirname4 } from "path";
1782
- import { unlink as unlink2, readFile as readFile7, writeFile as writeFile8 } from "fs/promises";
1800
+ import { unlink as unlink3, readFile as readFile7, writeFile as writeFile8 } from "fs/promises";
1783
1801
  import { existsSync as existsSync2 } from "fs";
1784
- async function removeSingleComponent(installedKey, config, cwd) {
1785
- const installed = config.installed?.[installedKey];
1786
- if (!installed) return;
1802
+ async function removeSingleComponent(installedKey, lock, config, cwd) {
1803
+ const entry = lock[installedKey];
1804
+ if (!entry) return;
1787
1805
  const deleted = [];
1788
- for (const filePath of installed.files) {
1806
+ for (const filePath of entry.files) {
1789
1807
  try {
1790
- await unlink2(join10(cwd, filePath));
1808
+ await unlink3(join10(cwd, filePath));
1791
1809
  deleted.push(filePath);
1792
1810
  } catch {
1793
1811
  p6.log.warn(`Could not delete ${filePath} (may have been moved or renamed)`);
@@ -1819,26 +1837,25 @@ async function removeSingleComponent(installedKey, config, cwd) {
1819
1837
  p6.log.info(`Updated barrel file: ${join10(baseDir, "index.ts")}`);
1820
1838
  }
1821
1839
  }
1822
- delete config.installed[installedKey];
1840
+ delete lock[installedKey];
1823
1841
  if (deleted.length > 0) {
1824
1842
  p6.log.success(`Removed ${installedKey}:
1825
1843
  ` + deleted.map((f) => ` ${pc6.red("-")} ${f}`).join("\n"));
1826
1844
  }
1827
1845
  }
1828
- async function offerOrphanRemoval(removedDeps, config, cwd) {
1846
+ async function offerOrphanRemoval(removedDeps, lock, config, cwd) {
1829
1847
  if (removedDeps.size === 0) return;
1830
- const remaining = Object.entries(config.installed ?? {});
1848
+ const remaining = Object.entries(lock);
1831
1849
  const neededDeps = /* @__PURE__ */ new Set();
1832
1850
  for (const [, entry] of remaining) {
1833
- const deps = entry.registryDependencies;
1834
- if (deps) {
1835
- for (const dep of deps) {
1851
+ if (entry.registryDependencies) {
1852
+ for (const dep of entry.registryDependencies) {
1836
1853
  neededDeps.add(dep);
1837
1854
  }
1838
1855
  }
1839
1856
  }
1840
1857
  const orphans = [...removedDeps].filter(
1841
- (dep) => dep !== "core" && !neededDeps.has(dep) && config.installed?.[dep]
1858
+ (dep) => dep !== "core" && !neededDeps.has(dep) && lock[dep]
1842
1859
  );
1843
1860
  if (orphans.length === 0) return;
1844
1861
  const selected = await p6.multiselect({
@@ -1846,14 +1863,14 @@ async function offerOrphanRemoval(removedDeps, config, cwd) {
1846
1863
  options: orphans.map((dep) => ({
1847
1864
  value: dep,
1848
1865
  label: dep,
1849
- hint: `${config.installed[dep].files.length} file(s)`
1866
+ hint: `${lock[dep].files.length} file(s)`
1850
1867
  })),
1851
1868
  initialValues: orphans
1852
1869
  // all checked by default
1853
1870
  });
1854
1871
  if (p6.isCancel(selected)) return;
1855
1872
  for (const key of selected) {
1856
- await removeSingleComponent(key, config, cwd);
1873
+ await removeSingleComponent(key, lock, config, cwd);
1857
1874
  }
1858
1875
  }
1859
1876
  async function removeCommand(componentName) {
@@ -1863,9 +1880,9 @@ async function removeCommand(componentName) {
1863
1880
  p6.log.error("No kitn.json found. Run `kitn init` first.");
1864
1881
  process.exit(1);
1865
1882
  }
1883
+ const lock = await readLock(cwd);
1866
1884
  if (!componentName) {
1867
- const installed2 = config.installed ?? {};
1868
- const installedKeys = Object.keys(installed2);
1885
+ const installedKeys = Object.keys(lock);
1869
1886
  if (installedKeys.length === 0) {
1870
1887
  p6.log.warn("No components installed.");
1871
1888
  process.exit(0);
@@ -1875,7 +1892,7 @@ async function removeCommand(componentName) {
1875
1892
  options: installedKeys.map((key) => ({
1876
1893
  value: key,
1877
1894
  label: key,
1878
- hint: `${installed2[key].files.length} file(s)`
1895
+ hint: `${lock[key].files.length} file(s)`
1879
1896
  }))
1880
1897
  });
1881
1898
  if (p6.isCancel(selected)) {
@@ -1887,46 +1904,43 @@ async function removeCommand(componentName) {
1887
1904
  p6.log.warn("No components selected.");
1888
1905
  process.exit(0);
1889
1906
  }
1890
- for (const key of selectedKeys) {
1891
- await removeSingleComponent(key, config, cwd);
1892
- }
1893
1907
  const allRemovedDeps = /* @__PURE__ */ new Set();
1894
1908
  for (const key of selectedKeys) {
1895
- const entry = installed2[key];
1896
- if (entry?.registryDependencies) {
1897
- for (const dep of entry.registryDependencies) {
1909
+ const entry2 = lock[key];
1910
+ if (entry2?.registryDependencies) {
1911
+ for (const dep of entry2.registryDependencies) {
1898
1912
  allRemovedDeps.add(dep);
1899
1913
  }
1900
1914
  }
1901
1915
  }
1902
- await offerOrphanRemoval(allRemovedDeps, config, cwd);
1903
- await writeConfig(cwd, config);
1916
+ for (const key of selectedKeys) {
1917
+ await removeSingleComponent(key, lock, config, cwd);
1918
+ }
1919
+ await offerOrphanRemoval(allRemovedDeps, lock, config, cwd);
1920
+ await writeLock(cwd, lock);
1904
1921
  p6.outro(pc6.green("Done!"));
1905
1922
  return;
1906
1923
  }
1907
1924
  const input = componentName === "routes" ? resolveRoutesAlias(config) : componentName;
1908
1925
  const ref = parseComponentRef(input);
1909
1926
  const installedKey = ref.namespace === "@kitn" ? ref.name : `${ref.namespace}/${ref.name}`;
1910
- const installed = config.installed?.[installedKey];
1911
- if (!installed) {
1927
+ const entry = lock[installedKey];
1928
+ if (!entry) {
1912
1929
  p6.log.error(`Component '${ref.name}' is not installed.`);
1913
1930
  process.exit(1);
1914
1931
  }
1915
1932
  const shouldRemove = await p6.confirm({
1916
- message: `Remove ${ref.name}? This will delete ${installed.files.length} file(s).`,
1933
+ message: `Remove ${ref.name}? This will delete ${entry.files.length} file(s).`,
1917
1934
  initialValue: false
1918
1935
  });
1919
1936
  if (p6.isCancel(shouldRemove) || !shouldRemove) {
1920
1937
  p6.cancel("Remove cancelled.");
1921
1938
  process.exit(0);
1922
1939
  }
1923
- await removeSingleComponent(installedKey, config, cwd);
1924
- const removedDeps = new Set(installed.registryDependencies ?? []);
1925
- await offerOrphanRemoval(removedDeps, config, cwd);
1926
- if (Object.keys(config.installed).length === 0) {
1927
- delete config.installed;
1928
- }
1929
- await writeConfig(cwd, config);
1940
+ const removedDeps = new Set(entry.registryDependencies ?? []);
1941
+ await removeSingleComponent(installedKey, lock, config, cwd);
1942
+ await offerOrphanRemoval(removedDeps, lock, config, cwd);
1943
+ await writeLock(cwd, lock);
1930
1944
  }
1931
1945
  var init_remove = __esm({
1932
1946
  "src/commands/remove.ts"() {
@@ -1951,12 +1965,12 @@ async function updateCommand(components) {
1951
1965
  p7.log.error("No kitn.json found. Run `kitn init` first.");
1952
1966
  process.exit(1);
1953
1967
  }
1954
- const installed = config.installed;
1955
- if (!installed || Object.keys(installed).length === 0) {
1968
+ const lock = await readLock(cwd);
1969
+ if (Object.keys(lock).length === 0) {
1956
1970
  p7.log.info("No installed components to update.");
1957
1971
  return;
1958
1972
  }
1959
- components = Object.keys(installed);
1973
+ components = Object.keys(lock);
1960
1974
  }
1961
1975
  await addCommand(components, { overwrite: true });
1962
1976
  }
@@ -2232,7 +2246,8 @@ async function infoCommand(component) {
2232
2246
  if (fileCount > maxShown) {
2233
2247
  console.log(` ${pc8.dim(`... and ${fileCount - maxShown} more`)}`);
2234
2248
  }
2235
- const installed = config.installed?.[item.name];
2249
+ const lock = await readLock(cwd);
2250
+ const installed = lock[item.name];
2236
2251
  if (installed) {
2237
2252
  console.log();
2238
2253
  console.log(
@@ -2355,12 +2370,11 @@ async function registryRemoveCommand(namespace, opts = {}) {
2355
2370
  if (namespace === "@kitn" && !opts.force) {
2356
2371
  throw new Error("Cannot remove the default @kitn registry. Use --force to override.");
2357
2372
  }
2373
+ const lock = await readLock(cwd);
2358
2374
  const affectedComponents = [];
2359
- if (config.installed) {
2360
- for (const [name, entry] of Object.entries(config.installed)) {
2361
- if (entry.registry === namespace) {
2362
- affectedComponents.push(name);
2363
- }
2375
+ for (const [name, entry] of Object.entries(lock)) {
2376
+ if (entry.registry === namespace) {
2377
+ affectedComponents.push(name);
2364
2378
  }
2365
2379
  }
2366
2380
  delete config.registries[namespace];
@@ -2405,7 +2419,7 @@ var init_registry = __esm({
2405
2419
  // src/index.ts
2406
2420
  init_update_check();
2407
2421
  import { Command } from "commander";
2408
- var VERSION = true ? "0.1.24" : "0.0.0-dev";
2422
+ var VERSION = true ? "0.1.26" : "0.0.0-dev";
2409
2423
  var printUpdateNotice = startUpdateCheck(VERSION);
2410
2424
  var program = new Command().name("kitn").description("Install AI agent components from the kitn registry").version(VERSION);
2411
2425
  program.command("init").description("Initialize kitn in your project").option("-r, --runtime <runtime>", "runtime to use (bun, node, deno)").option("-f, --framework <framework>", "HTTP framework (hono, hono-openapi, elysia)").option("-b, --base <path>", "base directory for components (default: src/ai)").option("-y, --yes", "accept all defaults without prompting").action(async (opts) => {