@olorehq/olore 0.1.4 → 0.2.0

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 +74 -0
  2. package/dist/cli.js +348 -166
  3. package/package.json +3 -3
package/README.md ADDED
@@ -0,0 +1,74 @@
1
+ # olore
2
+
3
+ ```
4
+ ██████╗ ██╗ ██████╗ ██████╗ ███████╗
5
+ ██╔═══██╗██║ ██╔═══██╗██╔══██╗██╔════╝
6
+ ██║ ██║██║ ██║ ██║██████╔╝█████╗
7
+ ██║ ██║██║ ██║ ██║██╔══██╗██╔══╝
8
+ ╚██████╔╝███████╗╚██████╔╝██║ ██║███████╗
9
+ ╚═════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝
10
+ O(pen) Lore for AI Agents
11
+ ```
12
+
13
+ Documentation package manager for AI coding agents. Local-first. Offline-ready.
14
+
15
+ ## Quick Start
16
+
17
+ ```bash
18
+ npm install -g @olorehq/olore
19
+ olore install prisma
20
+ olore inject
21
+ ```
22
+
23
+ That's it. Your agent now has Prisma docs. No hallucinations.
24
+
25
+ ## Why olore?
26
+
27
+ Your AI coding agent makes decisions about which tools to invoke. Sometimes it decides wrong — it skips the tool, hallucinates an API, or calls it with bad arguments.
28
+
29
+ **Passive context beats skills.** Vercel's agentic coding eval showed agents with passive documentation context scored **100%** vs **53%** with tool-based retrieval. The difference: passive context is always there. The agent doesn't have to decide to look it up.
30
+
31
+ `olore inject` embeds a compact documentation index directly into your `AGENTS.md` / `CLAUDE.md`. The agent reads it automatically on every session — no invocation decision needed. No network. No retrieval pipeline.
32
+
33
+ - **Version-pinned** — same docs, every run, every machine
34
+ - **Offline** — works on planes, in CI, behind firewalls
35
+ - **Local-first** — docs live in your project, not on someone's server
36
+ - **Any agent** — Claude Code, Codex, OpenCode, anything that reads markdown
37
+
38
+ ## Available Packages
39
+
40
+ `prisma` · `nextjs` · `zod` · `drizzle` · `langchain` · `tanstack-query` · `claude-code` · `codex` · `opencode` · `cargo` · `agentskills`
41
+
42
+ More on the [registry](https://github.com/olorehq/olore). Contributions welcome.
43
+
44
+ ## Supported Agents
45
+
46
+ - **Claude Code** — injects into `CLAUDE.md`
47
+ - **Codex** — injects into `AGENTS.md`
48
+ - **OpenCode** — injects into `AGENTS.md`
49
+
50
+ ## Commands
51
+
52
+ | Command | Description |
53
+ |---|---|
54
+ | `olore install <pkg>` | Install a documentation package |
55
+ | `olore inject` | Inject doc indexes into AGENTS.md / CLAUDE.md |
56
+ | `olore inject --remove` | Remove injected content |
57
+ | `olore list` | List installed packages |
58
+ | `olore remove <pkg>` | Remove a package |
59
+ | `olore search` | Browse available packages |
60
+ | `olore doctor` | Diagnose issues |
61
+
62
+ ## Links
63
+
64
+ - [GitHub](https://github.com/olorehq/olore)
65
+ - [Website](https://www.olore.dev)
66
+ - [Contributing](https://github.com/olorehq/olore/blob/main/CONTRIBUTING.md)
67
+
68
+ ## License
69
+
70
+ MIT
71
+
72
+ ---
73
+
74
+ > *"May the Skill be with you."*
package/dist/cli.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // src/cli.ts
4
4
  import { createRequire } from "module";
5
5
  import { Command } from "commander";
6
- import pc10 from "picocolors";
6
+ import pc11 from "picocolors";
7
7
 
8
8
  // src/commands/doctor.ts
9
9
  import pc from "picocolors";
@@ -705,11 +705,146 @@ Initialized olore package: `) + pc2.cyan(fullName));
705
705
  console.log("");
706
706
  }
707
707
 
708
- // src/commands/install.ts
708
+ // src/commands/inject.ts
709
+ import fs6 from "fs";
709
710
  import path6 from "path";
710
- import fs6 from "fs-extra";
711
- import ora from "ora";
712
711
  import pc3 from "picocolors";
712
+ var MARKER_START = "<!-- olore:start -->";
713
+ var MARKER_END = "<!-- olore:end -->";
714
+ var TARGET_FILES = ["AGENTS.md", "CLAUDE.md"];
715
+ var COMPACT_HEADER = "[olore docs]|STOP. Read these docs before answering \u2014 your training data may be outdated.|Format: keywords=path. For dir paths (ending /), list dir then read files.";
716
+ function extractSectionLines(content) {
717
+ return content.split("\n").filter((line) => line.startsWith("@")).filter((line) => line.length > 0);
718
+ }
719
+ function renderCompactBlock(sectionLines, name, version2, rootPath) {
720
+ return `[${name}@${version2} root:${rootPath}]${sectionLines.join("")}`;
721
+ }
722
+ async function buildInjectedContent() {
723
+ const packages = await getInstalledPackages();
724
+ const packageLines = [];
725
+ let count = 0;
726
+ for (const pkg of packages) {
727
+ const indexPath = path6.join(pkg.path, "INDEX.md");
728
+ if (!fs6.existsSync(indexPath)) continue;
729
+ const rawContent = fs6.readFileSync(indexPath, "utf-8");
730
+ const sectionLines = extractSectionLines(rawContent);
731
+ if (sectionLines.length === 0) continue;
732
+ const resolvedBase = fs6.realpathSync(pkg.path);
733
+ const rootPath = path6.join(resolvedBase, "contents");
734
+ packageLines.push(renderCompactBlock(sectionLines, pkg.name, pkg.version, rootPath));
735
+ count++;
736
+ }
737
+ if (count === 0) {
738
+ return { content: "", count: 0 };
739
+ }
740
+ const combined = [MARKER_START, COMPACT_HEADER, ...packageLines, MARKER_END].join("\n");
741
+ return { content: combined, count };
742
+ }
743
+ function smartMerge(filePath, injectedContent) {
744
+ if (!fs6.existsSync(filePath)) {
745
+ fs6.writeFileSync(filePath, injectedContent + "\n", "utf-8");
746
+ return;
747
+ }
748
+ const existing = fs6.readFileSync(filePath, "utf-8");
749
+ const startIdx = existing.indexOf(MARKER_START);
750
+ const endIdx = existing.indexOf(MARKER_END);
751
+ if (startIdx !== -1 && endIdx !== -1) {
752
+ const before = existing.slice(0, startIdx);
753
+ const after = existing.slice(endIdx + MARKER_END.length);
754
+ fs6.writeFileSync(filePath, before + injectedContent + after, "utf-8");
755
+ } else {
756
+ const separator = existing.endsWith("\n") ? "\n" : "\n\n";
757
+ fs6.writeFileSync(filePath, existing + separator + injectedContent + "\n", "utf-8");
758
+ }
759
+ }
760
+ function removeSection(filePath) {
761
+ if (!fs6.existsSync(filePath)) return false;
762
+ const content = fs6.readFileSync(filePath, "utf-8");
763
+ const startIdx = content.indexOf(MARKER_START);
764
+ const endIdx = content.indexOf(MARKER_END);
765
+ if (startIdx === -1 || endIdx === -1) return false;
766
+ const before = content.slice(0, startIdx);
767
+ const after = content.slice(endIdx + MARKER_END.length);
768
+ const result = (before + after).replace(/\n{3,}/g, "\n\n").trim();
769
+ if (result.length === 0) {
770
+ fs6.unlinkSync(filePath);
771
+ } else {
772
+ fs6.writeFileSync(filePath, result + "\n", "utf-8");
773
+ }
774
+ return true;
775
+ }
776
+ async function inject(options) {
777
+ const cwd = process.cwd();
778
+ if (options.remove) {
779
+ const filesRemoved = [];
780
+ for (const fileName of TARGET_FILES) {
781
+ const filePath = path6.join(cwd, fileName);
782
+ if (removeSection(filePath)) {
783
+ filesRemoved.push(fileName);
784
+ }
785
+ }
786
+ if (options.json) {
787
+ const result = {
788
+ packagesFound: 0,
789
+ packagesInjected: 0,
790
+ filesWritten: filesRemoved,
791
+ removed: true
792
+ };
793
+ console.log(JSON.stringify(result, null, 2));
794
+ return;
795
+ }
796
+ if (filesRemoved.length === 0) {
797
+ console.log(pc3.yellow("No olore sections found in project files."));
798
+ } else {
799
+ console.log(pc3.green(`Removed olore sections from: ${filesRemoved.join(", ")}`));
800
+ }
801
+ return;
802
+ }
803
+ const { content, count } = await buildInjectedContent();
804
+ if (count === 0) {
805
+ if (options.json) {
806
+ const result = {
807
+ packagesFound: 0,
808
+ packagesInjected: 0,
809
+ filesWritten: [],
810
+ removed: false
811
+ };
812
+ console.log(JSON.stringify(result, null, 2));
813
+ return;
814
+ }
815
+ console.log(pc3.yellow("No installed packages have INDEX.md files."));
816
+ console.log(pc3.gray("Build packages with the latest templates to generate INDEX.md."));
817
+ return;
818
+ }
819
+ const filesWritten = [];
820
+ for (const fileName of TARGET_FILES) {
821
+ const filePath = path6.join(cwd, fileName);
822
+ smartMerge(filePath, content);
823
+ filesWritten.push(fileName);
824
+ }
825
+ if (options.json) {
826
+ const result = {
827
+ packagesFound: count,
828
+ packagesInjected: count,
829
+ filesWritten,
830
+ removed: false
831
+ };
832
+ console.log(JSON.stringify(result, null, 2));
833
+ return;
834
+ }
835
+ console.log(
836
+ pc3.green(
837
+ `Injected ${count} package${count === 1 ? "" : "s"} into: ${filesWritten.join(", ")}`
838
+ )
839
+ );
840
+ console.log(pc3.gray("Run olore inject --remove to clean up."));
841
+ }
842
+
843
+ // src/commands/install.ts
844
+ import path7 from "path";
845
+ import fs7 from "fs-extra";
846
+ import ora from "ora";
847
+ import pc4 from "picocolors";
713
848
 
714
849
  // src/core/registry.ts
715
850
  var RegistryError = class extends Error {
@@ -791,22 +926,22 @@ async function resolveVersion(name, version2) {
791
926
  // src/commands/install.ts
792
927
  async function installFromLocal(localPath) {
793
928
  const fullPath = expandPath(localPath);
794
- if (!await fs6.pathExists(fullPath)) {
929
+ if (!await fs7.pathExists(fullPath)) {
795
930
  throw new Error(`Path not found: ${fullPath}`);
796
931
  }
797
- const stat = await fs6.stat(fullPath);
932
+ const stat = await fs7.stat(fullPath);
798
933
  if (!stat.isDirectory()) {
799
934
  throw new Error(`Not a directory: ${fullPath}`);
800
935
  }
801
- const lockPath = path6.join(fullPath, "olore-lock.json");
802
- if (!await fs6.pathExists(lockPath)) {
936
+ const lockPath = path7.join(fullPath, "olore-lock.json");
937
+ if (!await fs7.pathExists(lockPath)) {
803
938
  throw new Error(`Missing olore-lock.json in ${fullPath}`);
804
939
  }
805
- const skillPath = path6.join(fullPath, "SKILL.md");
806
- if (!await fs6.pathExists(skillPath)) {
940
+ const skillPath = path7.join(fullPath, "SKILL.md");
941
+ if (!await fs7.pathExists(skillPath)) {
807
942
  throw new Error(`Missing SKILL.md in ${fullPath}. Run /generate-agent-skills first.`);
808
943
  }
809
- const lock = await fs6.readJson(lockPath);
944
+ const lock = await fs7.readJson(lockPath);
810
945
  const packageName = lock.name;
811
946
  const packageVersion = lock.version;
812
947
  if (!packageName) {
@@ -816,57 +951,57 @@ async function installFromLocal(localPath) {
816
951
  throw new Error(`Invalid olore-lock.json: missing "version" field`);
817
952
  }
818
953
  const skillName = `olore-${packageName}-${packageVersion}`;
819
- const skillContent = await fs6.readFile(skillPath, "utf-8");
954
+ const skillContent = await fs7.readFile(skillPath, "utf-8");
820
955
  const nameMatch = skillContent.match(/^name:\s*(.+)$/m);
821
956
  const skillMdName = nameMatch ? nameMatch[1].trim() : null;
822
957
  if (skillMdName !== skillName) {
823
- console.log(pc3.yellow(`
958
+ console.log(pc4.yellow(`
824
959
  Warning: SKILL.md name mismatch`));
825
- console.log(pc3.gray(` Expected: ${skillName}`));
826
- console.log(pc3.gray(` Found: ${skillMdName || "(none)"}`));
827
- console.log(pc3.yellow(` Updating SKILL.md to fix...`));
960
+ console.log(pc4.gray(` Expected: ${skillName}`));
961
+ console.log(pc4.gray(` Found: ${skillMdName || "(none)"}`));
962
+ console.log(pc4.yellow(` Updating SKILL.md to fix...`));
828
963
  const updatedContent = skillMdName ? skillContent.replace(/^name:\s*.+$/m, `name: ${skillName}`) : skillContent.replace(/^---\n/, `---
829
964
  name: ${skillName}
830
965
  `);
831
- await fs6.writeFile(skillPath, updatedContent);
966
+ await fs7.writeFile(skillPath, updatedContent);
832
967
  }
833
- console.log(pc3.bold(`
968
+ console.log(pc4.bold(`
834
969
  Installing ${packageName}@${packageVersion} from local path...
835
970
  `));
836
971
  const agents = detectAgents();
837
972
  if (agents.length === 0) {
838
- console.log(pc3.yellow("No agents detected. Creating directories anyway."));
973
+ console.log(pc4.yellow("No agents detected. Creating directories anyway."));
839
974
  }
840
975
  const agentPaths = getAgentPaths();
841
976
  const olorePath = getOlorePackagePath(packageName, packageVersion);
842
977
  const spinner = ora("Copying to ~/.olore...").start();
843
- await fs6.ensureDir(path6.dirname(olorePath));
844
- await fs6.remove(olorePath);
845
- await fs6.copy(fullPath, olorePath);
846
- spinner.succeed(`Copied to ${pc3.gray(olorePath)}`);
978
+ await fs7.ensureDir(path7.dirname(olorePath));
979
+ await fs7.remove(olorePath);
980
+ await fs7.copy(fullPath, olorePath);
981
+ spinner.succeed(`Copied to ${pc4.gray(olorePath)}`);
847
982
  const linkSpinner = ora("Linking to agent directories...").start();
848
983
  const linked = [];
849
984
  for (const [agent, skillsDir] of Object.entries(agentPaths)) {
850
- const targetDir = path6.join(skillsDir, skillName);
851
- await fs6.ensureDir(skillsDir);
852
- await fs6.remove(targetDir);
985
+ const targetDir = path7.join(skillsDir, skillName);
986
+ await fs7.ensureDir(skillsDir);
987
+ await fs7.remove(targetDir);
853
988
  await linkOrCopy(olorePath, targetDir);
854
- linked.push(`${pc3.green("\u2713")} ${agent} ${pc3.gray("\u2192")} ${pc3.gray(targetDir)}`);
989
+ linked.push(`${pc4.green("\u2713")} ${agent} ${pc4.gray("\u2192")} ${pc4.gray(targetDir)}`);
855
990
  }
856
991
  linkSpinner.stop();
857
992
  linked.forEach((line) => console.log(` ${line}`));
858
- console.log(pc3.gray(` \u2514\u2500 all linked to ${olorePath}`));
993
+ console.log(pc4.gray(` \u2514\u2500 all linked to ${olorePath}`));
859
994
  console.log("");
860
- console.log(pc3.green("Installation complete!"));
995
+ console.log(pc4.green("Installation complete!"));
861
996
  console.log("");
862
- console.log(pc3.gray("Skill is now available as:"));
863
- console.log(pc3.cyan(` /${skillName}`) + pc3.gray(" (Claude Code)"));
864
- console.log(pc3.cyan(` $${skillName}`) + pc3.gray(" (Codex)"));
865
- console.log(pc3.cyan(` ${skillName}`) + pc3.gray(" (OpenCode)"));
997
+ console.log(pc4.gray("Skill is now available as:"));
998
+ console.log(pc4.cyan(` /${skillName}`) + pc4.gray(" (Claude Code)"));
999
+ console.log(pc4.cyan(` $${skillName}`) + pc4.gray(" (Codex)"));
1000
+ console.log(pc4.cyan(` ${skillName}`) + pc4.gray(" (OpenCode)"));
866
1001
  }
867
1002
  async function install(pkg, options) {
868
1003
  if (options.force) {
869
- console.log(pc3.cyan("\n\u2728 May the Skill be with you.\n"));
1004
+ console.log(pc4.cyan("\n\u2728 May the Skill be with you.\n"));
870
1005
  }
871
1006
  if (isLocalPath(pkg)) {
872
1007
  await installFromLocal(pkg);
@@ -884,10 +1019,35 @@ function parsePackageSpec(spec) {
884
1019
  }
885
1020
  return { name: spec };
886
1021
  }
1022
+ function levenshtein(a, b) {
1023
+ const m = a.length;
1024
+ const n = b.length;
1025
+ const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
1026
+ for (let i = 0; i <= m; i++) dp[i][0] = i;
1027
+ for (let j = 0; j <= n; j++) dp[0][j] = j;
1028
+ for (let i = 1; i <= m; i++) {
1029
+ for (let j = 1; j <= n; j++) {
1030
+ dp[i][j] = a[i - 1] === b[j - 1] ? dp[i - 1][j - 1] : 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]);
1031
+ }
1032
+ }
1033
+ return dp[m][n];
1034
+ }
1035
+ function findSimilarPackages(input, packages, maxResults = 3) {
1036
+ const results = [];
1037
+ for (const [name, entry] of Object.entries(packages)) {
1038
+ const distance = levenshtein(input.toLowerCase(), name.toLowerCase());
1039
+ const isSubstring = name.toLowerCase().includes(input.toLowerCase()) || input.toLowerCase().includes(name.toLowerCase());
1040
+ if (distance <= 3 || isSubstring) {
1041
+ results.push({ name, description: entry.description, distance });
1042
+ }
1043
+ }
1044
+ results.sort((a, b) => a.distance - b.distance);
1045
+ return results.slice(0, maxResults).map(({ name, description }) => ({ name, description }));
1046
+ }
887
1047
  async function installFromRemote(pkg, optionsVersion) {
888
1048
  const { name, version: specVersion } = parsePackageSpec(pkg);
889
1049
  const requestedVersion = optionsVersion || specVersion || "latest";
890
- console.log(pc3.bold(`
1050
+ console.log(pc4.bold(`
891
1051
  Installing ${name}@${requestedVersion} from registry...
892
1052
  `));
893
1053
  const spinner = ora("Fetching package info...").start();
@@ -899,18 +1059,32 @@ Installing ${name}@${requestedVersion} from registry...
899
1059
  spinner.fail("Failed to resolve package");
900
1060
  if (error instanceof RegistryError) {
901
1061
  if (error.code === "NOT_FOUND") {
902
- console.log(pc3.yellow(`
1062
+ console.log(pc4.yellow(`
903
1063
  Package "${name}" not found in registry.`));
904
- console.log(pc3.gray("\nFor local packages, use a path:"));
905
- console.log(pc3.cyan(` olore install ./vault/packages/${name}/<version>`));
1064
+ try {
1065
+ const index = await fetchPackageIndex();
1066
+ const similar = findSimilarPackages(name, index.packages);
1067
+ if (similar.length > 0) {
1068
+ console.log(pc4.bold("\nDid you mean?"));
1069
+ for (const pkg2 of similar) {
1070
+ console.log(` ${pc4.cyan(pkg2.name)} ${pc4.gray("-")} ${pc4.gray(pkg2.description)}`);
1071
+ }
1072
+ }
1073
+ } catch {
1074
+ }
1075
+ console.log(
1076
+ pc4.gray("\nRun ") + pc4.cyan("olore search") + pc4.gray(" to see all available packages.")
1077
+ );
1078
+ console.log(pc4.gray("\nFor local packages, use a path:"));
1079
+ console.log(pc4.cyan(` olore install ./vault/packages/${name}/<version>`));
906
1080
  console.log("");
907
1081
  } else if (error.code === "NETWORK_ERROR" || error.code === "TIMEOUT") {
908
- console.log(pc3.red(`
1082
+ console.log(pc4.red(`
909
1083
  Network error: ${error.message}`));
910
- console.log(pc3.gray("Please check your internet connection and try again."));
1084
+ console.log(pc4.gray("Please check your internet connection and try again."));
911
1085
  }
912
1086
  } else {
913
- console.log(pc3.red(`
1087
+ console.log(pc4.red(`
914
1088
  Error: ${error instanceof Error ? error.message : "Unknown error"}`));
915
1089
  }
916
1090
  process.exit(1);
@@ -918,26 +1092,26 @@ Error: ${error instanceof Error ? error.message : "Unknown error"}`));
918
1092
  const skillName = `olore-${name}-${versionInfo.version}`;
919
1093
  const agents = detectAgents();
920
1094
  if (agents.length === 0) {
921
- console.log(pc3.yellow("No agents detected. Creating directories anyway."));
1095
+ console.log(pc4.yellow("No agents detected. Creating directories anyway."));
922
1096
  }
923
1097
  const agentPaths = getAgentPaths();
924
1098
  const olorePath = getOlorePackagePath(name, versionInfo.version);
925
1099
  const downloadSpinner = ora("Downloading package...").start();
926
1100
  try {
927
1101
  await downloadAndInstall(versionInfo.downloadUrl, olorePath, versionInfo.integrity);
928
- downloadSpinner.succeed(`Downloaded to ${pc3.gray(olorePath)}`);
1102
+ downloadSpinner.succeed(`Downloaded to ${pc4.gray(olorePath)}`);
929
1103
  } catch (error) {
930
1104
  downloadSpinner.fail("Download failed");
931
1105
  if (error instanceof DownloadError) {
932
1106
  if (error.code === "CHECKSUM_MISMATCH") {
933
- console.log(pc3.red("\nChecksum verification failed!"));
934
- console.log(pc3.gray("The downloaded package may be corrupted or tampered with."));
1107
+ console.log(pc4.red("\nChecksum verification failed!"));
1108
+ console.log(pc4.gray("The downloaded package may be corrupted or tampered with."));
935
1109
  } else {
936
- console.log(pc3.red(`
1110
+ console.log(pc4.red(`
937
1111
  Download error: ${error.message}`));
938
1112
  }
939
1113
  } else {
940
- console.log(pc3.red(`
1114
+ console.log(pc4.red(`
941
1115
  Error: ${error instanceof Error ? error.message : "Unknown error"}`));
942
1116
  }
943
1117
  process.exit(1);
@@ -945,47 +1119,47 @@ Error: ${error instanceof Error ? error.message : "Unknown error"}`));
945
1119
  const linkSpinner = ora("Linking to agent directories...").start();
946
1120
  const linked = [];
947
1121
  for (const [agent, skillsDir] of Object.entries(agentPaths)) {
948
- const targetDir = path6.join(skillsDir, skillName);
949
- await fs6.ensureDir(skillsDir);
950
- await fs6.remove(targetDir);
1122
+ const targetDir = path7.join(skillsDir, skillName);
1123
+ await fs7.ensureDir(skillsDir);
1124
+ await fs7.remove(targetDir);
951
1125
  await linkOrCopy(olorePath, targetDir);
952
- linked.push(`${pc3.green("\u2713")} ${agent} ${pc3.gray("\u2192")} ${pc3.gray(targetDir)}`);
1126
+ linked.push(`${pc4.green("\u2713")} ${agent} ${pc4.gray("\u2192")} ${pc4.gray(targetDir)}`);
953
1127
  }
954
1128
  linkSpinner.stop();
955
1129
  linked.forEach((line) => console.log(` ${line}`));
956
- console.log(pc3.gray(` \u2514\u2500 all linked to ${olorePath}`));
1130
+ console.log(pc4.gray(` \u2514\u2500 all linked to ${olorePath}`));
957
1131
  console.log("");
958
- console.log(pc3.green("Installation complete!"));
1132
+ console.log(pc4.green("Installation complete!"));
959
1133
  console.log("");
960
- console.log(pc3.gray("Skill is now available as:"));
961
- console.log(pc3.cyan(` /${skillName}`) + pc3.gray(" (Claude Code)"));
962
- console.log(pc3.cyan(` $${skillName}`) + pc3.gray(" (Codex)"));
963
- console.log(pc3.cyan(` ${skillName}`) + pc3.gray(" (OpenCode)"));
1134
+ console.log(pc4.gray("Skill is now available as:"));
1135
+ console.log(pc4.cyan(` /${skillName}`) + pc4.gray(" (Claude Code)"));
1136
+ console.log(pc4.cyan(` $${skillName}`) + pc4.gray(" (Codex)"));
1137
+ console.log(pc4.cyan(` ${skillName}`) + pc4.gray(" (OpenCode)"));
964
1138
  }
965
1139
 
966
1140
  // src/commands/link.ts
967
- import path7 from "path";
968
- import fs7 from "fs-extra";
1141
+ import path8 from "path";
1142
+ import fs8 from "fs-extra";
969
1143
  import ora2 from "ora";
970
- import pc4 from "picocolors";
1144
+ import pc5 from "picocolors";
971
1145
  async function link(localPath) {
972
1146
  const fullPath = expandPath(localPath);
973
- if (!await fs7.pathExists(fullPath)) {
1147
+ if (!await fs8.pathExists(fullPath)) {
974
1148
  throw new Error(`Path not found: ${fullPath}`);
975
1149
  }
976
- const stat = await fs7.stat(fullPath);
1150
+ const stat = await fs8.stat(fullPath);
977
1151
  if (!stat.isDirectory()) {
978
1152
  throw new Error(`Not a directory: ${fullPath}`);
979
1153
  }
980
- const lockPath = path7.join(fullPath, "olore-lock.json");
981
- if (!await fs7.pathExists(lockPath)) {
1154
+ const lockPath = path8.join(fullPath, "olore-lock.json");
1155
+ if (!await fs8.pathExists(lockPath)) {
982
1156
  throw new Error(`Missing olore-lock.json in ${fullPath}`);
983
1157
  }
984
- const skillPath = path7.join(fullPath, "SKILL.md");
985
- if (!await fs7.pathExists(skillPath)) {
1158
+ const skillPath = path8.join(fullPath, "SKILL.md");
1159
+ if (!await fs8.pathExists(skillPath)) {
986
1160
  throw new Error(`Missing SKILL.md in ${fullPath}. Run /build-docs first.`);
987
1161
  }
988
- const lock = await fs7.readJson(lockPath);
1162
+ const lock = await fs8.readJson(lockPath);
989
1163
  const packageName = lock.name;
990
1164
  const packageVersion = lock.version;
991
1165
  if (!packageName) {
@@ -995,63 +1169,63 @@ async function link(localPath) {
995
1169
  throw new Error(`Invalid olore-lock.json: missing "version" field`);
996
1170
  }
997
1171
  const skillName = `olore-${packageName}-${packageVersion}`;
998
- const skillContent = await fs7.readFile(skillPath, "utf-8");
1172
+ const skillContent = await fs8.readFile(skillPath, "utf-8");
999
1173
  const nameMatch = skillContent.match(/^name:\s*(.+)$/m);
1000
1174
  const skillMdName = nameMatch ? nameMatch[1].trim() : null;
1001
1175
  if (skillMdName !== skillName) {
1002
- console.log(pc4.yellow(`
1176
+ console.log(pc5.yellow(`
1003
1177
  Warning: SKILL.md name mismatch`));
1004
- console.log(pc4.gray(` Expected: ${skillName}`));
1005
- console.log(pc4.gray(` Found: ${skillMdName || "(none)"}`));
1006
- console.log(pc4.yellow(` Updating SKILL.md to fix...`));
1178
+ console.log(pc5.gray(` Expected: ${skillName}`));
1179
+ console.log(pc5.gray(` Found: ${skillMdName || "(none)"}`));
1180
+ console.log(pc5.yellow(` Updating SKILL.md to fix...`));
1007
1181
  const updatedContent = skillMdName ? skillContent.replace(/^name:\s*.+$/m, `name: ${skillName}`) : skillContent.replace(/^---\n/, `---
1008
1182
  name: ${skillName}
1009
1183
  `);
1010
- await fs7.writeFile(skillPath, updatedContent);
1184
+ await fs8.writeFile(skillPath, updatedContent);
1011
1185
  }
1012
- console.log(pc4.bold(`
1186
+ console.log(pc5.bold(`
1013
1187
  Linking ${packageName}@${packageVersion}...
1014
1188
  `));
1015
1189
  const agents = detectAgents();
1016
1190
  if (agents.length === 0) {
1017
- console.log(pc4.yellow("No agents detected. Creating directories anyway."));
1191
+ console.log(pc5.yellow("No agents detected. Creating directories anyway."));
1018
1192
  }
1019
1193
  const agentPaths = getAgentPaths();
1020
1194
  const spinner = ora2(`${getLinkActionText()}...`).start();
1021
1195
  const linked = [];
1022
1196
  for (const [agent, skillsDir] of Object.entries(agentPaths)) {
1023
- const targetDir = path7.join(skillsDir, skillName);
1024
- await fs7.ensureDir(skillsDir);
1025
- await fs7.remove(targetDir);
1197
+ const targetDir = path8.join(skillsDir, skillName);
1198
+ await fs8.ensureDir(skillsDir);
1199
+ await fs8.remove(targetDir);
1026
1200
  await linkOrCopy(fullPath, targetDir);
1027
- linked.push(`${pc4.blue("\u26D3")} ${agent} ${pc4.gray("\u2192")} ${pc4.gray(targetDir)}`);
1201
+ linked.push(`${pc5.blue("\u26D3")} ${agent} ${pc5.gray("\u2192")} ${pc5.gray(targetDir)}`);
1028
1202
  }
1029
1203
  spinner.stop();
1030
1204
  linked.forEach((line) => console.log(` ${line}`));
1031
- console.log(pc4.gray(` \u2514\u2500 ${getLinkTypeText()} ${fullPath}`));
1205
+ console.log(pc5.gray(` \u2514\u2500 ${getLinkTypeText()} ${fullPath}`));
1032
1206
  console.log("");
1033
- console.log(pc4.blue("Link complete!"));
1207
+ console.log(pc5.blue("Link complete!"));
1034
1208
  console.log("");
1035
- console.log(pc4.gray("Skill is now available as:"));
1036
- console.log(pc4.cyan(` /${skillName}`) + pc4.gray(" (Claude Code)"));
1037
- console.log(pc4.cyan(` $${skillName}`) + pc4.gray(" (Codex)"));
1038
- console.log(pc4.cyan(` ${skillName}`) + pc4.gray(" (OpenCode)"));
1209
+ console.log(pc5.gray("Skill is now available as:"));
1210
+ console.log(pc5.cyan(` /${skillName}`) + pc5.gray(" (Claude Code)"));
1211
+ console.log(pc5.cyan(` $${skillName}`) + pc5.gray(" (Codex)"));
1212
+ console.log(pc5.cyan(` ${skillName}`) + pc5.gray(" (OpenCode)"));
1039
1213
  console.log("");
1040
- console.log(pc4.gray(`Development mode: ${getLinkTypeText()} source (bypasses ~/.olore).`));
1041
- console.log(pc4.gray("Changes to source are immediately visible."));
1214
+ console.log(pc5.gray(`Development mode: ${getLinkTypeText()} source (bypasses ~/.olore).`));
1215
+ console.log(pc5.gray("Changes to source are immediately visible."));
1042
1216
  console.log(
1043
- pc4.gray("Use ") + pc4.cyan("olore install") + pc4.gray(" for a stable copy in ~/.olore.")
1217
+ pc5.gray("Use ") + pc5.cyan("olore install") + pc5.gray(" for a stable copy in ~/.olore.")
1044
1218
  );
1045
1219
  }
1046
1220
 
1047
1221
  // src/commands/list.ts
1048
- import pc5 from "picocolors";
1222
+ import pc6 from "picocolors";
1049
1223
  async function list(options) {
1050
1224
  const packages = await getInstalledPackages();
1051
1225
  if (packages.length === 0) {
1052
- console.log(pc5.yellow("\nI find your lack of skills disturbing.\n"));
1053
- console.log(pc5.gray("No packages installed."));
1054
- console.log(`Run ${pc5.cyan("olore install <package>")} to install documentation.`);
1226
+ console.log(pc6.yellow("\nI find your lack of skills disturbing.\n"));
1227
+ console.log(pc6.gray("No packages installed."));
1228
+ console.log(`Run ${pc6.cyan("olore install <package>")} to install documentation.`);
1055
1229
  return;
1056
1230
  }
1057
1231
  if (options.json) {
@@ -1059,29 +1233,29 @@ async function list(options) {
1059
1233
  console.log(JSON.stringify({ packages, issueCount: issues2.length }, null, 2));
1060
1234
  return;
1061
1235
  }
1062
- console.log(pc5.bold("\nInstalled packages:\n"));
1236
+ console.log(pc6.bold("\nInstalled packages:\n"));
1063
1237
  console.log(
1064
- pc5.gray(
1238
+ pc6.gray(
1065
1239
  "PACKAGE".padEnd(25) + "VERSION".padEnd(12) + "TYPE".padEnd(10) + "FILES".padStart(8) + "SIZE".padStart(12)
1066
1240
  )
1067
1241
  );
1068
- console.log(pc5.gray("-".repeat(67)));
1242
+ console.log(pc6.gray("-".repeat(67)));
1069
1243
  for (const pkg of packages) {
1070
- const typeLabel = pkg.installType === "linked" ? pc5.blue("linked") : pkg.installType;
1244
+ const typeLabel = pkg.installType === "linked" ? pc6.blue("linked") : pkg.installType;
1071
1245
  console.log(
1072
1246
  pkg.name.padEnd(25) + pkg.version.padEnd(12) + typeLabel.padEnd(10) + String(pkg.files).padStart(8) + formatSize(pkg.size).padStart(12)
1073
1247
  );
1074
1248
  }
1075
- console.log(pc5.gray("-".repeat(67)));
1076
- console.log(pc5.gray(`Total: ${packages.length} packages`));
1249
+ console.log(pc6.gray("-".repeat(67)));
1250
+ console.log(pc6.gray(`Total: ${packages.length} packages`));
1077
1251
  console.log("");
1078
- console.log(pc5.gray("Types: installed = in ~/.olore, linked = dev symlink, copied = legacy"));
1252
+ console.log(pc6.gray("Types: installed = in ~/.olore, linked = dev symlink, copied = legacy"));
1079
1253
  const { issues } = await diagnose();
1080
1254
  if (issues.length > 0) {
1081
1255
  console.log("");
1082
1256
  console.log(
1083
- pc5.yellow(
1084
- `\u26A0 ${issues.length} issue${issues.length === 1 ? "" : "s"} detected. Run ${pc5.cyan("olore doctor")} for details.`
1257
+ pc6.yellow(
1258
+ `\u26A0 ${issues.length} issue${issues.length === 1 ? "" : "s"} detected. Run ${pc6.cyan("olore doctor")} for details.`
1085
1259
  )
1086
1260
  );
1087
1261
  }
@@ -1093,59 +1267,59 @@ function formatSize(bytes) {
1093
1267
  }
1094
1268
 
1095
1269
  // src/commands/order66.ts
1096
- import path8 from "path";
1097
- import fs8 from "fs-extra";
1270
+ import path9 from "path";
1271
+ import fs9 from "fs-extra";
1098
1272
  import ora3 from "ora";
1099
- import pc6 from "picocolors";
1273
+ import pc7 from "picocolors";
1100
1274
  async function order66() {
1101
- console.log(pc6.red("\n\u26A0\uFE0F Execute Order 66?\n"));
1102
- console.log(pc6.yellow("This will remove ALL installed documentation packages."));
1275
+ console.log(pc7.red("\n\u26A0\uFE0F Execute Order 66?\n"));
1276
+ console.log(pc7.yellow("This will remove ALL installed documentation packages."));
1103
1277
  const packages = await getInstalledPackages();
1104
1278
  if (packages.length === 0) {
1105
- console.log(pc6.gray("\nNo packages to remove. The Jedi are already gone."));
1279
+ console.log(pc7.gray("\nNo packages to remove. The Jedi are already gone."));
1106
1280
  return;
1107
1281
  }
1108
- console.log(pc6.gray(`
1282
+ console.log(pc7.gray(`
1109
1283
  Packages to be removed: ${packages.length}`));
1110
1284
  for (const pkg of packages) {
1111
- console.log(pc6.gray(` - ${pkg.name}@${pkg.version}`));
1285
+ console.log(pc7.gray(` - ${pkg.name}@${pkg.version}`));
1112
1286
  }
1113
- console.log(pc6.red('\n"It will be done, my lord."\n'));
1287
+ console.log(pc7.red('\n"It will be done, my lord."\n'));
1114
1288
  const spinner = ora3("Executing Order 66...").start();
1115
1289
  let removedCount = 0;
1116
1290
  const agentPaths = getAgentPaths();
1117
1291
  for (const pkg of packages) {
1118
1292
  const skillName = `olore-${pkg.name}-${pkg.version}`;
1119
1293
  for (const [, basePath] of Object.entries(agentPaths)) {
1120
- const skillPath = path8.join(basePath, skillName);
1121
- if (await fs8.pathExists(skillPath)) {
1122
- await fs8.remove(skillPath);
1294
+ const skillPath = path9.join(basePath, skillName);
1295
+ if (await fs9.pathExists(skillPath)) {
1296
+ await fs9.remove(skillPath);
1123
1297
  }
1124
1298
  }
1125
1299
  if (pkg.installType === "installed") {
1126
1300
  const olorePath = getOlorePackagePath(pkg.name, pkg.version);
1127
- if (await fs8.pathExists(olorePath)) {
1128
- await fs8.remove(olorePath);
1301
+ if (await fs9.pathExists(olorePath)) {
1302
+ await fs9.remove(olorePath);
1129
1303
  }
1130
1304
  }
1131
1305
  removedCount++;
1132
1306
  }
1133
1307
  spinner.succeed(`Removed ${removedCount} packages`);
1134
- console.log(pc6.gray("\nThe Jedi have been eliminated."));
1308
+ console.log(pc7.gray("\nThe Jedi have been eliminated."));
1135
1309
  }
1136
1310
 
1137
1311
  // src/commands/prune.ts
1138
- import pc7 from "picocolors";
1312
+ import pc8 from "picocolors";
1139
1313
  async function prune(options) {
1140
1314
  if (!options.json) {
1141
- console.log(pc7.bold("\nScanning for issues...\n"));
1315
+ console.log(pc8.bold("\nScanning for issues...\n"));
1142
1316
  }
1143
1317
  const { issues } = await diagnose();
1144
1318
  if (issues.length === 0) {
1145
1319
  if (options.json) {
1146
1320
  console.log(JSON.stringify({ removed: [], failed: [] }, null, 2));
1147
1321
  } else {
1148
- console.log(pc7.green("Nothing to prune. Everything is clean."));
1322
+ console.log(pc8.green("Nothing to prune. Everything is clean."));
1149
1323
  }
1150
1324
  return;
1151
1325
  }
@@ -1155,14 +1329,14 @@ async function prune(options) {
1155
1329
  return;
1156
1330
  }
1157
1331
  console.log(
1158
- pc7.yellow(`Would remove ${issues.length} item${issues.length === 1 ? "" : "s"}:
1332
+ pc8.yellow(`Would remove ${issues.length} item${issues.length === 1 ? "" : "s"}:
1159
1333
  `)
1160
1334
  );
1161
1335
  for (const issue of issues) {
1162
1336
  console.log(` ${issueLabel(issue.type)} ${displayPath(issue.path)}`);
1163
1337
  }
1164
1338
  console.log(`
1165
- Run ${pc7.cyan("olore prune")} (without --dry-run) to remove them.`);
1339
+ Run ${pc8.cyan("olore prune")} (without --dry-run) to remove them.`);
1166
1340
  return;
1167
1341
  }
1168
1342
  const result = await pruneIssues(issues);
@@ -1176,7 +1350,7 @@ Run ${pc7.cyan("olore prune")} (without --dry-run) to remove them.`);
1176
1350
  for (const entry of result.removed) {
1177
1351
  totalFreed += entry.freedBytes;
1178
1352
  console.log(
1179
- ` ${pc7.green("\u2713")} ${displayPath(entry.issue.path)} (${issueLabel(entry.issue.type)})`
1353
+ ` ${pc8.green("\u2713")} ${displayPath(entry.issue.path)} (${issueLabel(entry.issue.type)})`
1180
1354
  );
1181
1355
  }
1182
1356
  if (totalFreed > 0) {
@@ -1187,12 +1361,12 @@ ${formatBytes(totalFreed)} freed.`);
1187
1361
  if (result.failed.length > 0) {
1188
1362
  console.log("");
1189
1363
  console.log(
1190
- pc7.red(
1364
+ pc8.red(
1191
1365
  `Failed to remove ${result.failed.length} item${result.failed.length === 1 ? "" : "s"}:`
1192
1366
  )
1193
1367
  );
1194
1368
  for (const entry of result.failed) {
1195
- console.log(` ${pc7.red("\u2717")} ${displayPath(entry.issue.path)}: ${entry.error}`);
1369
+ console.log(` ${pc8.red("\u2717")} ${displayPath(entry.issue.path)}: ${entry.error}`);
1196
1370
  }
1197
1371
  }
1198
1372
  }
@@ -1210,12 +1384,12 @@ function issueLabel(type) {
1210
1384
  }
1211
1385
 
1212
1386
  // src/commands/remove.ts
1213
- import path9 from "path";
1214
- import fs9 from "fs-extra";
1387
+ import path10 from "path";
1388
+ import fs10 from "fs-extra";
1215
1389
  import ora4 from "ora";
1216
- import pc8 from "picocolors";
1390
+ import pc9 from "picocolors";
1217
1391
  async function remove(pkg) {
1218
- console.log(pc8.bold(`
1392
+ console.log(pc9.bold(`
1219
1393
  Removing ${pkg}...
1220
1394
  `));
1221
1395
  const packages = await getInstalledPackages();
@@ -1231,20 +1405,20 @@ Removing ${pkg}...
1231
1405
  return p.name === name;
1232
1406
  });
1233
1407
  if (matches.length === 0) {
1234
- console.error(pc8.red(`Package not found: ${pkg}`));
1408
+ console.error(pc9.red(`Package not found: ${pkg}`));
1235
1409
  console.log("\nInstalled packages:");
1236
1410
  for (const p of packages) {
1237
- console.log(` ${pc8.cyan(p.name)}@${p.version}`);
1411
+ console.log(` ${pc9.cyan(p.name)}@${p.version}`);
1238
1412
  }
1239
1413
  process.exit(1);
1240
1414
  }
1241
1415
  if (matches.length > 1 && !version2) {
1242
- console.error(pc8.red(`Multiple versions found for ${name}:`));
1416
+ console.error(pc9.red(`Multiple versions found for ${name}:`));
1243
1417
  for (const p of matches) {
1244
- console.log(` ${pc8.cyan(p.name)}@${p.version} (${p.installType})`);
1418
+ console.log(` ${pc9.cyan(p.name)}@${p.version} (${p.installType})`);
1245
1419
  }
1246
1420
  console.log(`
1247
- Specify version: ${pc8.cyan(`olore remove ${name}@<version>`)}`);
1421
+ Specify version: ${pc9.cyan(`olore remove ${name}@<version>`)}`);
1248
1422
  process.exit(1);
1249
1423
  }
1250
1424
  const found = matches[0];
@@ -1253,32 +1427,32 @@ Specify version: ${pc8.cyan(`olore remove ${name}@<version>`)}`);
1253
1427
  const removed = [];
1254
1428
  const agentPaths = getAgentPaths();
1255
1429
  for (const [agent, basePath] of Object.entries(agentPaths)) {
1256
- const skillPath = path9.join(basePath, skillName);
1257
- if (await fs9.pathExists(skillPath)) {
1258
- await fs9.remove(skillPath);
1259
- removed.push(`${pc8.green("\u2713")} ${agent}`);
1430
+ const skillPath = path10.join(basePath, skillName);
1431
+ if (await fs10.pathExists(skillPath)) {
1432
+ await fs10.remove(skillPath);
1433
+ removed.push(`${pc9.green("\u2713")} ${agent}`);
1260
1434
  }
1261
1435
  }
1262
1436
  if (found.installType === "installed") {
1263
1437
  const olorePath = getOlorePackagePath(found.name, found.version);
1264
- if (await fs9.pathExists(olorePath)) {
1265
- await fs9.remove(olorePath);
1266
- removed.push(`${pc8.green("\u2713")} ~/.olore`);
1438
+ if (await fs10.pathExists(olorePath)) {
1439
+ await fs10.remove(olorePath);
1440
+ removed.push(`${pc9.green("\u2713")} ~/.olore`);
1267
1441
  }
1268
1442
  }
1269
1443
  spinner.stop();
1270
1444
  if (removed.length === 0) {
1271
- console.log(pc8.yellow("No files found to remove."));
1445
+ console.log(pc9.yellow("No files found to remove."));
1272
1446
  } else {
1273
1447
  removed.forEach((line) => console.log(` ${line}`));
1274
1448
  console.log("");
1275
- console.log(pc8.green(`Removed ${found.name}@${found.version}`));
1449
+ console.log(pc9.green(`Removed ${found.name}@${found.version}`));
1276
1450
  }
1277
1451
  }
1278
1452
 
1279
1453
  // src/commands/search.ts
1280
1454
  import ora5 from "ora";
1281
- import pc9 from "picocolors";
1455
+ import pc10 from "picocolors";
1282
1456
  async function search(query, options) {
1283
1457
  const spinner = ora5("Fetching package registry...").start();
1284
1458
  let packages;
@@ -1290,15 +1464,15 @@ async function search(query, options) {
1290
1464
  spinner.fail("Failed to fetch registry");
1291
1465
  if (error instanceof RegistryError) {
1292
1466
  if (error.code === "NETWORK_ERROR" || error.code === "TIMEOUT") {
1293
- console.log(pc9.red(`
1467
+ console.log(pc10.red(`
1294
1468
  Network error: ${error.message}`));
1295
- console.log(pc9.gray("Please check your internet connection and try again."));
1469
+ console.log(pc10.gray("Please check your internet connection and try again."));
1296
1470
  } else {
1297
- console.log(pc9.red(`
1471
+ console.log(pc10.red(`
1298
1472
  Error: ${error.message}`));
1299
1473
  }
1300
1474
  } else {
1301
- console.log(pc9.red(`
1475
+ console.log(pc10.red(`
1302
1476
  Error: ${error instanceof Error ? error.message : "Unknown error"}`));
1303
1477
  }
1304
1478
  process.exit(1);
@@ -1312,10 +1486,10 @@ Error: ${error instanceof Error ? error.message : "Unknown error"}`));
1312
1486
  }
1313
1487
  if (entries.length === 0) {
1314
1488
  if (query) {
1315
- console.log(pc9.yellow(`
1489
+ console.log(pc10.yellow(`
1316
1490
  No packages matching '${query}'`));
1317
1491
  } else {
1318
- console.log(pc9.yellow("\nNo packages available in the registry"));
1492
+ console.log(pc10.yellow("\nNo packages available in the registry"));
1319
1493
  }
1320
1494
  return;
1321
1495
  }
@@ -1342,26 +1516,26 @@ No packages matching '${query}'`));
1342
1516
  const colName = 20;
1343
1517
  const colDesc = 44;
1344
1518
  const colVersions = 12;
1345
- console.log(pc9.bold("\nAvailable packages:\n"));
1519
+ console.log(pc10.bold("\nAvailable packages:\n"));
1346
1520
  console.log(
1347
- pc9.gray(
1521
+ pc10.gray(
1348
1522
  "PACKAGE".padEnd(colName) + "DESCRIPTION".padEnd(colDesc) + "VERSIONS".padEnd(colVersions) + "INSTALLED"
1349
1523
  )
1350
1524
  );
1351
- console.log(pc9.gray("\u2500".repeat(colName + colDesc + colVersions + 12)));
1525
+ console.log(pc10.gray("\u2500".repeat(colName + colDesc + colVersions + 12)));
1352
1526
  for (const [name, info] of entries.sort(([a], [b]) => a.localeCompare(b))) {
1353
1527
  const desc = truncate(info.description, colDesc - 2);
1354
1528
  const versions = info.versions.join(", ");
1355
1529
  const installedVersion = installedVersions.get(name);
1356
- const status = installedVersion ? pc9.green(`\u2713 ${installedVersion}`) : "";
1530
+ const status = installedVersion ? pc10.green(`\u2713 ${installedVersion}`) : "";
1357
1531
  console.log(
1358
1532
  name.padEnd(colName) + desc.padEnd(colDesc) + versions.padEnd(colVersions) + status
1359
1533
  );
1360
1534
  }
1361
- console.log(pc9.gray("\u2500".repeat(colName + colDesc + colVersions + 12)));
1362
- console.log(pc9.gray(`${entries.length} package${entries.length === 1 ? "" : "s"} available`));
1535
+ console.log(pc10.gray("\u2500".repeat(colName + colDesc + colVersions + 12)));
1536
+ console.log(pc10.gray(`${entries.length} package${entries.length === 1 ? "" : "s"} available`));
1363
1537
  console.log(`
1364
- Install with: ${pc9.cyan("olore install <package>")}`);
1538
+ Install with: ${pc10.cyan("olore install <package>")}`);
1365
1539
  }
1366
1540
  function truncate(str, maxLen) {
1367
1541
  if (str.length <= maxLen) return str;
@@ -1373,12 +1547,12 @@ var require2 = createRequire(import.meta.url);
1373
1547
  var { version } = require2("../package.json");
1374
1548
  var program = new Command();
1375
1549
  program.name("olore").description("Universal documentation for any AI coding agent").version(version).addHelpText("after", `
1376
- ${pc10.gray("May the Skill be with you.")}`);
1550
+ ${pc11.gray("May the Skill be with you.")}`);
1377
1551
  program.command("init").description("Initialize a documentation package in the current directory").option("-n, --name <name>", "Package name (default: folder name)").option("-v, --version <version>", "Package version (default: latest)").option("-y, --yes", "Skip prompts, use defaults").action(async (options) => {
1378
1552
  try {
1379
1553
  await init(options);
1380
1554
  } catch (error) {
1381
- console.error(pc10.red(`Error: ${error.message}`));
1555
+ console.error(pc11.red(`Error: ${error.message}`));
1382
1556
  process.exit(1);
1383
1557
  }
1384
1558
  });
@@ -1386,7 +1560,7 @@ program.command("install <package>").alias("i").description("Install a documenta
1386
1560
  try {
1387
1561
  await install(pkg, options);
1388
1562
  } catch (error) {
1389
- console.error(pc10.red(`Error: ${error.message}`));
1563
+ console.error(pc11.red(`Error: ${error.message}`));
1390
1564
  process.exit(1);
1391
1565
  }
1392
1566
  });
@@ -1394,7 +1568,7 @@ program.command("link <path>").description("Link a local package for development
1394
1568
  try {
1395
1569
  await link(localPath);
1396
1570
  } catch (error) {
1397
- console.error(pc10.red(`Error: ${error.message}`));
1571
+ console.error(pc11.red(`Error: ${error.message}`));
1398
1572
  process.exit(1);
1399
1573
  }
1400
1574
  });
@@ -1402,7 +1576,7 @@ program.command("list").alias("ls").description("List installed documentation pa
1402
1576
  try {
1403
1577
  await list(options);
1404
1578
  } catch (error) {
1405
- console.error(pc10.red(`Error: ${error.message}`));
1579
+ console.error(pc11.red(`Error: ${error.message}`));
1406
1580
  process.exit(1);
1407
1581
  }
1408
1582
  });
@@ -1410,7 +1584,7 @@ program.command("search [query]").description("Search available packages in the
1410
1584
  try {
1411
1585
  await search(query, options);
1412
1586
  } catch (error) {
1413
- console.error(pc10.red(`Error: ${error.message}`));
1587
+ console.error(pc11.red(`Error: ${error.message}`));
1414
1588
  process.exit(1);
1415
1589
  }
1416
1590
  });
@@ -1418,7 +1592,7 @@ program.command("remove <package>").alias("rm").description("Remove an installed
1418
1592
  try {
1419
1593
  await remove(pkg);
1420
1594
  } catch (error) {
1421
- console.error(pc10.red(`Error: ${error.message}`));
1595
+ console.error(pc11.red(`Error: ${error.message}`));
1422
1596
  process.exit(1);
1423
1597
  }
1424
1598
  });
@@ -1426,7 +1600,7 @@ program.command("doctor").description("Check for issues with installed packages"
1426
1600
  try {
1427
1601
  await doctor(options);
1428
1602
  } catch (error) {
1429
- console.error(pc10.red(`Error: ${error.message}`));
1603
+ console.error(pc11.red(`Error: ${error.message}`));
1430
1604
  process.exit(1);
1431
1605
  }
1432
1606
  });
@@ -1434,7 +1608,15 @@ program.command("prune").description("Remove dangling symlinks, orphaned package
1434
1608
  try {
1435
1609
  await prune(options);
1436
1610
  } catch (error) {
1437
- console.error(pc10.red(`Error: ${error.message}`));
1611
+ console.error(pc11.red(`Error: ${error.message}`));
1612
+ process.exit(1);
1613
+ }
1614
+ });
1615
+ program.command("inject").description("Inject compressed doc indexes into AGENTS.md and CLAUDE.md").option("--remove", "Remove injected content from project files").option("--json", "Output as JSON").action(async (options) => {
1616
+ try {
1617
+ await inject(options);
1618
+ } catch (error) {
1619
+ console.error(pc11.red(`Error: ${error.message}`));
1438
1620
  process.exit(1);
1439
1621
  }
1440
1622
  });
@@ -1442,7 +1624,7 @@ program.command("order66").description(false).action(async () => {
1442
1624
  try {
1443
1625
  await order66();
1444
1626
  } catch (error) {
1445
- console.error(pc10.red(`Error: ${error.message}`));
1627
+ console.error(pc11.red(`Error: ${error.message}`));
1446
1628
  process.exit(1);
1447
1629
  }
1448
1630
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@olorehq/olore",
3
- "version": "0.1.4",
3
+ "version": "0.2.0",
4
4
  "description": "Universal documentation for any AI coding agent",
5
5
  "keywords": [
6
6
  "ai",
@@ -11,14 +11,14 @@
11
11
  "context",
12
12
  "llm"
13
13
  ],
14
- "license": "AGPL-3.0",
14
+ "license": "MIT",
15
15
  "author": "olorehq",
16
16
  "repository": {
17
17
  "type": "git",
18
18
  "url": "git+https://github.com/olorehq/olore.git",
19
19
  "directory": "cli"
20
20
  },
21
- "homepage": "https://github.com/olorehq/olore",
21
+ "homepage": "https://www.olore.dev",
22
22
  "type": "module",
23
23
  "files": [
24
24
  "dist"