@smicolon/ai-kit 0.1.1 → 0.2.1

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.
Files changed (3) hide show
  1. package/README.md +26 -16
  2. package/dist/index.js +156 -62
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -5,7 +5,7 @@ AI coding tool pack manager. Install convention packs (agents, skills, commands,
5
5
  ## Quick Start
6
6
 
7
7
  ```bash
8
- npx @smicolon/ai-kit init
8
+ npx @smicolon/ai-kit@latest init
9
9
  ```
10
10
 
11
11
  This walks you through selecting your AI tools and stack, then installs the right files in the right places.
@@ -17,8 +17,8 @@ This walks you through selecting your AI tools and stack, then installs the righ
17
17
  Interactive first-time setup. Prompts for your AI tools, stack, and component preferences.
18
18
 
19
19
  ```bash
20
- npx @smicolon/ai-kit init
21
- npx @smicolon/ai-kit init --cwd apps/web # monorepo sub-package
20
+ npx @smicolon/ai-kit@latest init
21
+ npx @smicolon/ai-kit@latest init --cwd apps/web # monorepo sub-package
22
22
  ```
23
23
 
24
24
  ### `add <pack>`
@@ -26,11 +26,11 @@ npx @smicolon/ai-kit init --cwd apps/web # monorepo sub-package
26
26
  Add a pack to your project.
27
27
 
28
28
  ```bash
29
- npx @smicolon/ai-kit add django
30
- npx @smicolon/ai-kit add django --skills-only
31
- npx @smicolon/ai-kit add django --agents-only
32
- npx @smicolon/ai-kit add django --rules-only
33
- npx @smicolon/ai-kit add django --tools claude-code,cursor
29
+ npx @smicolon/ai-kit@latest add django
30
+ npx @smicolon/ai-kit@latest add django --skills-only
31
+ npx @smicolon/ai-kit@latest add django --agents-only
32
+ npx @smicolon/ai-kit@latest add django --rules-only
33
+ npx @smicolon/ai-kit@latest add django --tools claude-code,cursor
34
34
  ```
35
35
 
36
36
  ### `list`
@@ -38,8 +38,8 @@ npx @smicolon/ai-kit add django --tools claude-code,cursor
38
38
  Show available or installed packs.
39
39
 
40
40
  ```bash
41
- npx @smicolon/ai-kit list # available packs
42
- npx @smicolon/ai-kit list --installed # installed packs
41
+ npx @smicolon/ai-kit@latest list # available packs
42
+ npx @smicolon/ai-kit@latest list --installed # installed packs
43
43
  ```
44
44
 
45
45
  ### `remove <pack>`
@@ -47,7 +47,17 @@ npx @smicolon/ai-kit list --installed # installed packs
47
47
  Remove a pack and all its installed files.
48
48
 
49
49
  ```bash
50
- npx @smicolon/ai-kit remove django
50
+ npx @smicolon/ai-kit@latest remove django
51
+ ```
52
+
53
+ ### `search <query>`
54
+
55
+ Search packs by name or keyword.
56
+
57
+ ```bash
58
+ npx @smicolon/ai-kit@latest search auth
59
+ npx @smicolon/ai-kit@latest search frontend
60
+ npx @smicolon/ai-kit@latest search tdd
51
61
  ```
52
62
 
53
63
  ### `update [pack]`
@@ -55,8 +65,8 @@ npx @smicolon/ai-kit remove django
55
65
  Update installed packs to latest versions.
56
66
 
57
67
  ```bash
58
- npx @smicolon/ai-kit update # update all
59
- npx @smicolon/ai-kit update django # update one
68
+ npx @smicolon/ai-kit@latest update # update all
69
+ npx @smicolon/ai-kit@latest update django # update one
60
70
  ```
61
71
 
62
72
  ## Supported AI Tools
@@ -116,15 +126,15 @@ your-project/
116
126
  └── .gitignore # auto-updated
117
127
  ```
118
128
 
119
- Config is stored in `.ai-kit.json` which tracks installed packs and all created files for clean removal.
129
+ Tool preferences are stored globally at `~/.config/ai-kit/config.json` (pick once, works in all projects). Local `.ai-kit.json` tracks installed packs and files for clean removal — it's auto-added to `.gitignore`.
120
130
 
121
131
  ## Monorepo Support
122
132
 
123
133
  Use `--cwd` to target a sub-package. Both the sub-package and root `.gitignore` are updated.
124
134
 
125
135
  ```bash
126
- npx @smicolon/ai-kit init --cwd apps/web
127
- npx @smicolon/ai-kit add django --cwd apps/web
136
+ npx @smicolon/ai-kit@latest init --cwd apps/web
137
+ npx @smicolon/ai-kit@latest add django --cwd apps/web
128
138
  ```
129
139
 
130
140
  ## License
package/dist/index.js CHANGED
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import { Command as Command6 } from "commander";
4
+ import { Command as Command7 } from "commander";
5
5
 
6
6
  // src/commands/init.ts
7
7
  import { Command } from "commander";
8
8
  import * as p from "@clack/prompts";
9
9
  import pc from "picocolors";
10
- import path5 from "path";
10
+ import path6 from "path";
11
11
 
12
12
  // src/tools.ts
13
13
  var TOOL_REGISTRY = {
@@ -182,6 +182,8 @@ function resolvePack(plugin, marketplaceDir) {
182
182
  name: plugin.name,
183
183
  version: plugin.version,
184
184
  description: plugin.description,
185
+ category: plugin.category ?? "",
186
+ keywords: plugin.keywords ?? [],
185
187
  sourceDir,
186
188
  agents: resolveFiles(plugin.agents),
187
189
  commands: resolveFiles(plugin.commands),
@@ -201,10 +203,10 @@ function discoverPacks(startDir) {
201
203
  }
202
204
  const marketplaceDir = path.dirname(path.dirname(marketplacePath));
203
205
  const raw = JSON.parse(fs.readFileSync(marketplacePath, "utf-8"));
204
- return raw.plugins.map((p2) => resolvePack(p2, marketplaceDir)).filter((p2) => fs.existsSync(p2.sourceDir));
206
+ return raw.plugins.map((p3) => resolvePack(p3, marketplaceDir)).filter((p3) => fs.existsSync(p3.sourceDir));
205
207
  }
206
208
  function findPack(name, startDir) {
207
- return discoverPacks(startDir).find((p2) => p2.name === name);
209
+ return discoverPacks(startDir).find((p3) => p3.name === name);
208
210
  }
209
211
 
210
212
  // src/config.ts
@@ -258,6 +260,11 @@ function createDefaultConfig(tools) {
258
260
  import fs3 from "fs";
259
261
  import path3 from "path";
260
262
  var MANAGED_COMMENT = "# AI coding tools (managed by @smicolon/ai-kit)";
263
+ var LOCAL_PATTERNS = [
264
+ ".ai-kit.json",
265
+ "**/*.local.*",
266
+ "**/*.local.md"
267
+ ];
261
268
  function findGitRoot(startDir) {
262
269
  let dir = startDir;
263
270
  while (true) {
@@ -295,15 +302,15 @@ ${newEntries.join("\n")}
295
302
  }
296
303
  fs3.writeFileSync(gitignorePath, updated);
297
304
  }
298
- function updateGitignore(projectDir, dirs) {
299
- if (dirs.length === 0) return;
300
- const entries = dirs.map((d) => d.endsWith("/") ? d : `${d}/`);
305
+ function updateGitignore(projectDir) {
301
306
  const projectGitignore = path3.join(projectDir, ".gitignore");
302
- appendToGitignore(projectGitignore, entries);
307
+ appendToGitignore(projectGitignore, LOCAL_PATTERNS);
303
308
  const gitRoot = findGitRoot(projectDir);
304
309
  if (gitRoot && path3.resolve(gitRoot) !== path3.resolve(projectDir)) {
305
310
  const relFromRoot = path3.relative(gitRoot, projectDir);
306
- const rootEntries = entries.map((e) => `${relFromRoot}/${e}`);
311
+ const rootEntries = LOCAL_PATTERNS.map(
312
+ (e) => e.startsWith("**/") ? e : `${relFromRoot}/${e}`
313
+ );
307
314
  appendToGitignore(path3.join(gitRoot, ".gitignore"), rootEntries);
308
315
  }
309
316
  }
@@ -565,32 +572,51 @@ function removePack2(projectDir, files) {
565
572
  }
566
573
  return removed;
567
574
  }
568
- function isSymlink(p2) {
575
+ function isSymlink(p3) {
569
576
  try {
570
- return fs5.lstatSync(p2).isSymbolicLink();
577
+ return fs5.lstatSync(p3).isSymbolicLink();
571
578
  } catch {
572
579
  return false;
573
580
  }
574
581
  }
575
- function getWrittenDirs(tools, hadSkills) {
576
- const dirs = /* @__PURE__ */ new Set();
577
- if (hadSkills) {
578
- dirs.add(CANONICAL_SKILLS_DIR);
579
- }
580
- for (const toolId of tools) {
581
- const config = TOOL_REGISTRY[toolId];
582
- for (const dir of Object.values(config.components)) {
583
- const topLevel = dir.split("/")[0];
584
- dirs.add(topLevel);
585
- }
582
+
583
+ // src/global-config.ts
584
+ import fs6 from "fs";
585
+ import path5 from "path";
586
+ import os from "os";
587
+ function getConfigDir() {
588
+ return path5.join(os.homedir(), ".config", "ai-kit");
589
+ }
590
+ function getConfigPath() {
591
+ return path5.join(getConfigDir(), "config.json");
592
+ }
593
+ function readGlobalConfig() {
594
+ const fp = getConfigPath();
595
+ if (!fs6.existsSync(fp)) return null;
596
+ try {
597
+ return JSON.parse(fs6.readFileSync(fp, "utf-8"));
598
+ } catch {
599
+ return null;
586
600
  }
587
- return [...dirs];
601
+ }
602
+ function writeGlobalConfig(config) {
603
+ const dir = getConfigDir();
604
+ fs6.mkdirSync(dir, { recursive: true });
605
+ fs6.writeFileSync(getConfigPath(), JSON.stringify(config, null, 2) + "\n");
606
+ }
607
+ function getGlobalTools() {
608
+ const config = readGlobalConfig();
609
+ return config?.tools ?? null;
610
+ }
611
+ function saveGlobalTools(tools) {
612
+ const existing = readGlobalConfig();
613
+ writeGlobalConfig({ ...existing, tools });
588
614
  }
589
615
 
590
616
  // src/commands/init.ts
591
617
  var initCommand = new Command("init").description("Interactive first-time setup").option("--cwd <dir>", "Project directory (for monorepo sub-packages)").action(async (opts) => {
592
618
  p.intro(pc.bgCyan(pc.black(" ai-kit ")));
593
- const projectDir = opts.cwd ? path5.resolve(opts.cwd) : process.cwd();
619
+ const projectDir = opts.cwd ? path6.resolve(opts.cwd) : process.cwd();
594
620
  const existing = readConfig(projectDir);
595
621
  if (existing) {
596
622
  const action = await p.select({
@@ -610,13 +636,15 @@ var initCommand = new Command("init").description("Interactive first-time setup"
610
636
  return;
611
637
  }
612
638
  }
613
- const toolSelection = await p.multiselect({
614
- message: "Which AI coding tools do you use?",
639
+ const savedTools = getGlobalTools();
640
+ const toolSelection = await p.autocompleteMultiselect({
641
+ message: "Which AI coding tools do you use? (type to filter)",
615
642
  options: TOOL_IDS.map((id) => ({
616
643
  value: id,
617
644
  label: TOOL_REGISTRY[id].label,
618
645
  hint: TOOL_REGISTRY[id].hint
619
646
  })),
647
+ initialValues: savedTools ?? [],
620
648
  required: true
621
649
  });
622
650
  if (p.isCancel(toolSelection)) {
@@ -624,6 +652,7 @@ var initCommand = new Command("init").description("Interactive first-time setup"
624
652
  return;
625
653
  }
626
654
  const selectedTools = toolSelection;
655
+ saveGlobalTools(selectedTools);
627
656
  let packs;
628
657
  try {
629
658
  packs = discoverPacks();
@@ -632,8 +661,8 @@ var initCommand = new Command("init").description("Interactive first-time setup"
632
661
  p.outro("Setup failed.");
633
662
  return;
634
663
  }
635
- const packSelection = await p.multiselect({
636
- message: "What's your stack?",
664
+ const packSelection = await p.autocompleteMultiselect({
665
+ message: "Which packs do you want to install? (type to filter)",
637
666
  options: packs.map((pack) => ({
638
667
  value: pack.name,
639
668
  label: pack.name,
@@ -682,8 +711,7 @@ var initCommand = new Command("init").description("Interactive first-time setup"
682
711
  const s = p.spinner();
683
712
  s.start("Installing packs...");
684
713
  let config = createDefaultConfig(selectedTools);
685
- const selectedPacks = packs.filter((p2) => selectedPackNames.includes(p2.name));
686
- let hadSkills = false;
714
+ const selectedPacks = packs.filter((p3) => selectedPackNames.includes(p3.name));
687
715
  for (const pack of selectedPacks) {
688
716
  const result = installPack({
689
717
  pack,
@@ -692,40 +720,63 @@ var initCommand = new Command("init").description("Interactive first-time setup"
692
720
  projectDir
693
721
  });
694
722
  config = mergeInstall(config, result);
695
- if (result.installed.skills > 0) hadSkills = true;
696
723
  }
697
724
  writeConfig(projectDir, config);
698
- updateGitignore(projectDir, getWrittenDirs(selectedTools, hadSkills));
725
+ updateGitignore(projectDir);
699
726
  s.stop("Done!");
700
727
  p.log.success(`Installed ${selectedPacks.length} pack(s) for ${selectedTools.length} tool(s):`);
701
728
  for (const pack of selectedPacks) {
702
729
  p.log.message(` ${pc.green("+")} ${pack.name} ${pc.dim(`v${pack.version}`)}`);
703
730
  }
704
- p.outro(pc.dim("Config saved to .ai-kit.json"));
731
+ p.outro(pc.dim("Run ai-kit add <pack> to add more packs anytime."));
705
732
  });
706
733
 
707
734
  // src/commands/add.ts
708
735
  import { Command as Command2 } from "commander";
709
- import path6 from "path";
736
+ import path7 from "path";
710
737
  import pc2 from "picocolors";
711
- var addCommand = new Command2("add").description("Add a pack to your project").argument("<pack>", "Pack name (e.g., django, nextjs)").option("--skills-only", "Only install skills").option("--agents-only", "Only install agents").option("--rules-only", "Only install rules").option("--commands-only", "Only install commands").option("--hooks-only", "Only install hooks").option("--tools <tools>", "Comma-separated tool IDs (overrides config)").option("--cwd <dir>", "Project directory (for monorepo sub-packages)").action(async (packName, opts) => {
712
- const projectDir = opts.cwd ? path6.resolve(opts.cwd) : process.cwd();
738
+ import * as p2 from "@clack/prompts";
739
+ async function resolveTools(toolsFlag, projectDir) {
740
+ if (toolsFlag) {
741
+ return toolsFlag.split(",").map((t) => t.trim());
742
+ }
713
743
  const config = readConfig(projectDir);
714
- if (!config) {
715
- console.error(
716
- pc2.red("No .ai-kit.json found. Run ") + pc2.cyan("ai-kit init") + pc2.red(" first.")
717
- );
718
- process.exit(1);
744
+ if (config?.tools?.length) {
745
+ return config.tools;
719
746
  }
747
+ const globalTools = getGlobalTools();
748
+ if (globalTools?.length) {
749
+ return globalTools;
750
+ }
751
+ const selection = await p2.autocompleteMultiselect({
752
+ message: "Which AI coding tools do you use? (type to filter)",
753
+ options: TOOL_IDS.map((id) => ({
754
+ value: id,
755
+ label: TOOL_REGISTRY[id].label,
756
+ hint: TOOL_REGISTRY[id].hint
757
+ })),
758
+ required: true
759
+ });
760
+ if (p2.isCancel(selection)) return null;
761
+ const tools = selection;
762
+ saveGlobalTools(tools);
763
+ return tools;
764
+ }
765
+ var addCommand = new Command2("add").description("Add a pack to your project").argument("<pack>", "Pack name (e.g., django, nextjs)").option("--skills-only", "Only install skills").option("--agents-only", "Only install agents").option("--rules-only", "Only install rules").option("--commands-only", "Only install commands").option("--hooks-only", "Only install hooks").option("--tools <tools>", "Comma-separated tool IDs (overrides config)").option("--cwd <dir>", "Project directory (for monorepo sub-packages)").action(async (packName, opts) => {
766
+ const projectDir = opts.cwd ? path7.resolve(opts.cwd) : process.cwd();
720
767
  const pack = findPack(packName);
721
768
  if (!pack) {
722
- const available = discoverPacks().map((p2) => p2.name);
769
+ const available = discoverPacks().map((p3) => p3.name);
723
770
  console.error(
724
771
  pc2.red(`Pack "${packName}" not found.`) + "\nAvailable: " + available.join(", ")
725
772
  );
726
773
  process.exit(1);
727
774
  }
728
- const tools = opts.tools ? opts.tools.split(",").map((t) => t.trim()) : config.tools;
775
+ const tools = await resolveTools(opts.tools, projectDir);
776
+ if (!tools) {
777
+ console.log(pc2.dim("Cancelled."));
778
+ return;
779
+ }
729
780
  let filter;
730
781
  if (opts.skillsOnly) filter = ["skills"];
731
782
  else if (opts.agentsOnly) filter = ["agents"];
@@ -733,10 +784,12 @@ var addCommand = new Command2("add").description("Add a pack to your project").a
733
784
  else if (opts.commandsOnly) filter = ["commands"];
734
785
  else if (opts.hooksOnly) filter = ["hooks"];
735
786
  const result = installPack({ pack, tools, filter, projectDir });
787
+ let config = readConfig(projectDir) ?? createDefaultConfig(tools);
788
+ config.tools = tools;
736
789
  const updated = mergeInstall(config, result);
737
790
  updated.packs[pack.name].version = pack.version;
738
791
  writeConfig(projectDir, updated);
739
- updateGitignore(projectDir, getWrittenDirs(tools, result.installed.skills > 0));
792
+ updateGitignore(projectDir);
740
793
  const parts = [];
741
794
  for (const [type, count] of Object.entries(result.installed)) {
742
795
  if (count > 0) parts.push(`${count} ${type}`);
@@ -798,14 +851,14 @@ ${pc3.dim(`${packs.length} packs available`)}`);
798
851
 
799
852
  // src/commands/remove.ts
800
853
  import { Command as Command4 } from "commander";
801
- import path7 from "path";
854
+ import path8 from "path";
802
855
  import pc4 from "picocolors";
803
856
  var removeCommand = new Command4("remove").description("Remove a pack from your project").argument("<pack>", "Pack name to remove").option("--cwd <dir>", "Project directory").action((packName, opts) => {
804
- const projectDir = opts.cwd ? path7.resolve(opts.cwd) : process.cwd();
857
+ const projectDir = opts.cwd ? path8.resolve(opts.cwd) : process.cwd();
805
858
  const config = readConfig(projectDir);
806
859
  if (!config) {
807
- console.error(pc4.red("No .ai-kit.json found."));
808
- process.exit(1);
860
+ console.log(pc4.dim("No packs installed."));
861
+ return;
809
862
  }
810
863
  const packConfig = config.packs[packName];
811
864
  if (!packConfig) {
@@ -828,23 +881,19 @@ var removeCommand = new Command4("remove").description("Remove a pack from your
828
881
 
829
882
  // src/commands/update.ts
830
883
  import { Command as Command5 } from "commander";
831
- import path8 from "path";
884
+ import path9 from "path";
832
885
  import pc5 from "picocolors";
833
- var updateCommand = new Command5("update").description("Update installed packs").argument("[pack]", "Pack name (omit to update all)").option("--cwd <dir>", "Project directory").action((packName, opts) => {
834
- const projectDir = opts.cwd ? path8.resolve(opts.cwd) : process.cwd();
886
+ var updateCommand = new Command5("update").description("Update installed packs").argument("[pack]", "Pack name (omit to update all)").option("--cwd <dir>", "Project directory").action(async (packName, opts) => {
887
+ const projectDir = opts.cwd ? path9.resolve(opts.cwd) : process.cwd();
835
888
  const config = readConfig(projectDir);
836
- if (!config) {
837
- console.error(pc5.red("No .ai-kit.json found. Run ") + pc5.cyan("ai-kit init") + pc5.red(" first."));
838
- process.exit(1);
839
- }
840
- const packsToUpdate = packName ? [packName] : Object.keys(config.packs);
841
- if (packsToUpdate.length === 0) {
842
- console.log(pc5.dim("No packs installed."));
889
+ if (!config || Object.keys(config.packs).length === 0) {
890
+ console.log(pc5.dim("No packs installed yet. Starting setup...\n"));
891
+ await initCommand.parseAsync(["init", ...opts.cwd ? ["--cwd", opts.cwd] : []], { from: "user" });
843
892
  return;
844
893
  }
894
+ const packsToUpdate = packName ? [packName] : Object.keys(config.packs);
845
895
  let updated = 0;
846
896
  let skipped = 0;
847
- let hadSkills = false;
848
897
  for (const name of packsToUpdate) {
849
898
  const installed = config.packs[name];
850
899
  if (!installed) {
@@ -874,14 +923,13 @@ var updateCommand = new Command5("update").description("Update installed packs")
874
923
  const merged = mergeInstall(config, result);
875
924
  merged.packs[name].version = available.version;
876
925
  Object.assign(config, merged);
877
- if (result.installed.skills > 0) hadSkills = true;
878
926
  console.log(
879
927
  pc5.green(` ${name}`) + ` ${pc5.dim(installed.version)} \u2192 ${pc5.cyan(available.version)}`
880
928
  );
881
929
  updated++;
882
930
  }
883
931
  writeConfig(projectDir, config);
884
- updateGitignore(projectDir, getWrittenDirs(config.tools, hadSkills));
932
+ updateGitignore(projectDir);
885
933
  if (updated > 0) {
886
934
  console.log(pc5.green(`
887
935
  Updated ${updated} pack(s).`));
@@ -891,11 +939,57 @@ Updated ${updated} pack(s).`));
891
939
  }
892
940
  });
893
941
 
942
+ // src/commands/search.ts
943
+ import { Command as Command6 } from "commander";
944
+ import pc6 from "picocolors";
945
+ var searchCommand = new Command6("search").description("Search available packs by name or keyword").argument("<query>", "Search term (matches name, description, keywords)").action((query) => {
946
+ let packs;
947
+ try {
948
+ packs = discoverPacks();
949
+ } catch {
950
+ console.error(pc6.red("Could not find marketplace.json."));
951
+ process.exit(1);
952
+ }
953
+ const q = query.toLowerCase();
954
+ const matches = packs.filter((pack) => {
955
+ const haystack = [
956
+ pack.name,
957
+ pack.description,
958
+ pack.category,
959
+ ...pack.keywords
960
+ ].join(" ").toLowerCase();
961
+ return haystack.includes(q);
962
+ });
963
+ if (matches.length === 0) {
964
+ console.log(pc6.dim(`No packs matching "${query}".`));
965
+ console.log(pc6.dim(`
966
+ All packs: ${packs.map((p3) => p3.name).join(", ")}`));
967
+ return;
968
+ }
969
+ console.log(pc6.bold(`Found ${matches.length} pack(s):
970
+ `));
971
+ for (const pack of matches) {
972
+ const counts = [];
973
+ if (pack.agents.length) counts.push(`${pack.agents.length} agents`);
974
+ if (pack.skills.length) counts.push(`${pack.skills.length} skills`);
975
+ if (pack.commands.length) counts.push(`${pack.commands.length} commands`);
976
+ if (pack.rules.length) counts.push(`${pack.rules.length} rules`);
977
+ console.log(
978
+ ` ${pc6.cyan(pack.name)} ${pc6.dim(`v${pack.version}`)}
979
+ ${pack.description}
980
+ ${pc6.dim(counts.join(", "))}
981
+ ${pc6.dim(`Install: npx @smicolon/ai-kit@latest add ${pack.name}`)}
982
+ `
983
+ );
984
+ }
985
+ });
986
+
894
987
  // src/index.ts
895
- var program = new Command6().name("ai-kit").description("AI coding tool pack manager").version("0.0.1");
988
+ var program = new Command7().name("ai-kit").description("AI coding tool pack manager").version("0.0.1");
896
989
  program.addCommand(initCommand);
897
990
  program.addCommand(addCommand);
898
991
  program.addCommand(listCommand);
899
992
  program.addCommand(removeCommand);
900
993
  program.addCommand(updateCommand);
994
+ program.addCommand(searchCommand);
901
995
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smicolon/ai-kit",
3
- "version": "0.1.1",
3
+ "version": "0.2.1",
4
4
  "description": "AI coding tool pack manager for Smicolon standards",
5
5
  "license": "MIT",
6
6
  "repository": {