@olorehq/olore 0.1.5 → 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 +74 -0
  2. package/dist/cli.js +464 -169
  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 pc12 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 pc5 from "picocolors";
713
848
 
714
849
  // src/core/registry.ts
715
850
  var RegistryError = class extends Error {
@@ -788,25 +923,174 @@ async function resolveVersion(name, version2) {
788
923
  return versionInfo;
789
924
  }
790
925
 
926
+ // src/core/version-check.ts
927
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
928
+ import { homedir } from "os";
929
+ import { join } from "path";
930
+ import pc4 from "picocolors";
931
+
932
+ // package.json
933
+ var package_default = {
934
+ name: "@olorehq/olore",
935
+ version: "0.2.1",
936
+ description: "Universal documentation for any AI coding agent",
937
+ keywords: [
938
+ "ai",
939
+ "documentation",
940
+ "claude",
941
+ "codex",
942
+ "coding-assistant",
943
+ "context",
944
+ "llm"
945
+ ],
946
+ license: "MIT",
947
+ author: "olorehq",
948
+ repository: {
949
+ type: "git",
950
+ url: "git+https://github.com/olorehq/olore.git",
951
+ directory: "cli"
952
+ },
953
+ homepage: "https://www.olore.dev",
954
+ type: "module",
955
+ files: [
956
+ "dist"
957
+ ],
958
+ bin: {
959
+ olore: "dist/cli.js"
960
+ },
961
+ scripts: {
962
+ build: "tsup",
963
+ "build:bin": "bun build src/cli.ts --compile --outfile dist/olore",
964
+ "build:bin:all": "npm run build:bin:darwin-arm64 && npm run build:bin:darwin-x64 && npm run build:bin:linux-x64 && npm run build:bin:linux-arm64",
965
+ "build:bin:darwin-arm64": "bun build src/cli.ts --compile --target=bun-darwin-arm64 --outfile dist/olore-darwin-arm64",
966
+ "build:bin:darwin-x64": "bun build src/cli.ts --compile --target=bun-darwin-x64 --outfile dist/olore-darwin-x64",
967
+ "build:bin:linux-arm64": "bun build src/cli.ts --compile --target=bun-linux-arm64 --outfile dist/olore-linux-arm64",
968
+ "build:bin:linux-x64": "bun build src/cli.ts --compile --target=bun-linux-x64 --outfile dist/olore-linux-x64",
969
+ dev: "tsup --watch",
970
+ format: "prettier --write src/",
971
+ "format:check": "prettier --check src/",
972
+ lint: "eslint src/",
973
+ test: "vitest",
974
+ typecheck: "tsc --noEmit",
975
+ "generate-registry": "npx tsx scripts/generate-registry.ts"
976
+ },
977
+ dependencies: {
978
+ commander: "^12.1.0",
979
+ "fs-extra": "^11.3.3",
980
+ ora: "^9.0.0",
981
+ picocolors: "^1.1.1",
982
+ tar: "^7.4.3"
983
+ },
984
+ devDependencies: {
985
+ "@ianvs/prettier-plugin-sort-imports": "^4.7.0",
986
+ "@types/fs-extra": "^11.0.4",
987
+ "@types/node": "^22.10.7",
988
+ prettier: "^3.8.0",
989
+ "prettier-plugin-packagejson": "^2.5.22",
990
+ tsup: "^8.3.5",
991
+ typescript: "^5.7.3",
992
+ vitest: "^2.1.8"
993
+ },
994
+ engines: {
995
+ node: ">=18"
996
+ }
997
+ };
998
+
999
+ // src/core/version-check.ts
1000
+ var currentVersion = package_default.version;
1001
+ var NPM_REGISTRY = "https://registry.npmjs.org/@olorehq/olore";
1002
+ var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
1003
+ var CACHE_DIR = join(homedir(), ".olore");
1004
+ var CACHE_FILE = join(CACHE_DIR, "version-check.json");
1005
+ var FETCH_TIMEOUT = 3e3;
1006
+ function readCache() {
1007
+ try {
1008
+ if (existsSync(CACHE_FILE)) {
1009
+ return JSON.parse(readFileSync(CACHE_FILE, "utf-8"));
1010
+ }
1011
+ } catch {
1012
+ }
1013
+ return null;
1014
+ }
1015
+ function writeCache(cache) {
1016
+ try {
1017
+ if (!existsSync(CACHE_DIR)) {
1018
+ mkdirSync(CACHE_DIR, { recursive: true });
1019
+ }
1020
+ writeFileSync(CACHE_FILE, JSON.stringify(cache, null, 2));
1021
+ } catch {
1022
+ }
1023
+ }
1024
+ async function fetchLatestVersion() {
1025
+ try {
1026
+ const controller = new AbortController();
1027
+ const timeoutId = setTimeout(() => controller.abort(), FETCH_TIMEOUT);
1028
+ const response = await fetch(NPM_REGISTRY, {
1029
+ signal: controller.signal,
1030
+ headers: { Accept: "application/json" }
1031
+ });
1032
+ clearTimeout(timeoutId);
1033
+ if (!response.ok) return null;
1034
+ const data = await response.json();
1035
+ return data["dist-tags"]?.latest || null;
1036
+ } catch {
1037
+ return null;
1038
+ }
1039
+ }
1040
+ function compareVersions(current, latest) {
1041
+ const parseVersion = (v) => v.replace(/^v/, "").split(".").map((n) => parseInt(n, 10) || 0);
1042
+ const curr = parseVersion(current);
1043
+ const lat = parseVersion(latest);
1044
+ for (let i = 0; i < 3; i++) {
1045
+ if ((curr[i] || 0) < (lat[i] || 0)) return -1;
1046
+ if ((curr[i] || 0) > (lat[i] || 0)) return 1;
1047
+ }
1048
+ return 0;
1049
+ }
1050
+ async function checkForUpdates() {
1051
+ const cache = readCache();
1052
+ const now = Date.now();
1053
+ if (cache && now - cache.lastCheck < CHECK_INTERVAL_MS) {
1054
+ if (cache.latestVersion && compareVersions(currentVersion, cache.latestVersion) < 0) {
1055
+ printUpdateNotice(cache.latestVersion);
1056
+ }
1057
+ return;
1058
+ }
1059
+ const latestVersion = await fetchLatestVersion();
1060
+ writeCache({
1061
+ lastCheck: now,
1062
+ latestVersion
1063
+ });
1064
+ if (latestVersion && compareVersions(currentVersion, latestVersion) < 0) {
1065
+ printUpdateNotice(latestVersion);
1066
+ }
1067
+ }
1068
+ function printUpdateNotice(latestVersion) {
1069
+ console.log();
1070
+ console.log(
1071
+ pc4.yellow(`\u26A0\uFE0F Update available: ${currentVersion} \u2192 ${latestVersion}`) + pc4.gray(` \u2014 Run `) + pc4.cyan(`npm update -g @olorehq/olore`) + pc4.gray(` to update`)
1072
+ );
1073
+ }
1074
+
791
1075
  // src/commands/install.ts
792
1076
  async function installFromLocal(localPath) {
793
1077
  const fullPath = expandPath(localPath);
794
- if (!await fs6.pathExists(fullPath)) {
1078
+ if (!await fs7.pathExists(fullPath)) {
795
1079
  throw new Error(`Path not found: ${fullPath}`);
796
1080
  }
797
- const stat = await fs6.stat(fullPath);
1081
+ const stat = await fs7.stat(fullPath);
798
1082
  if (!stat.isDirectory()) {
799
1083
  throw new Error(`Not a directory: ${fullPath}`);
800
1084
  }
801
- const lockPath = path6.join(fullPath, "olore-lock.json");
802
- if (!await fs6.pathExists(lockPath)) {
1085
+ const lockPath = path7.join(fullPath, "olore-lock.json");
1086
+ if (!await fs7.pathExists(lockPath)) {
803
1087
  throw new Error(`Missing olore-lock.json in ${fullPath}`);
804
1088
  }
805
- const skillPath = path6.join(fullPath, "SKILL.md");
806
- if (!await fs6.pathExists(skillPath)) {
1089
+ const skillPath = path7.join(fullPath, "SKILL.md");
1090
+ if (!await fs7.pathExists(skillPath)) {
807
1091
  throw new Error(`Missing SKILL.md in ${fullPath}. Run /generate-agent-skills first.`);
808
1092
  }
809
- const lock = await fs6.readJson(lockPath);
1093
+ const lock = await fs7.readJson(lockPath);
810
1094
  const packageName = lock.name;
811
1095
  const packageVersion = lock.version;
812
1096
  if (!packageName) {
@@ -816,57 +1100,58 @@ async function installFromLocal(localPath) {
816
1100
  throw new Error(`Invalid olore-lock.json: missing "version" field`);
817
1101
  }
818
1102
  const skillName = `olore-${packageName}-${packageVersion}`;
819
- const skillContent = await fs6.readFile(skillPath, "utf-8");
1103
+ const skillContent = await fs7.readFile(skillPath, "utf-8");
820
1104
  const nameMatch = skillContent.match(/^name:\s*(.+)$/m);
821
1105
  const skillMdName = nameMatch ? nameMatch[1].trim() : null;
822
1106
  if (skillMdName !== skillName) {
823
- console.log(pc3.yellow(`
1107
+ console.log(pc5.yellow(`
824
1108
  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...`));
1109
+ console.log(pc5.gray(` Expected: ${skillName}`));
1110
+ console.log(pc5.gray(` Found: ${skillMdName || "(none)"}`));
1111
+ console.log(pc5.yellow(` Updating SKILL.md to fix...`));
828
1112
  const updatedContent = skillMdName ? skillContent.replace(/^name:\s*.+$/m, `name: ${skillName}`) : skillContent.replace(/^---\n/, `---
829
1113
  name: ${skillName}
830
1114
  `);
831
- await fs6.writeFile(skillPath, updatedContent);
1115
+ await fs7.writeFile(skillPath, updatedContent);
832
1116
  }
833
- console.log(pc3.bold(`
1117
+ console.log(pc5.bold(`
834
1118
  Installing ${packageName}@${packageVersion} from local path...
835
1119
  `));
836
1120
  const agents = detectAgents();
837
1121
  if (agents.length === 0) {
838
- console.log(pc3.yellow("No agents detected. Creating directories anyway."));
1122
+ console.log(pc5.yellow("No agents detected. Creating directories anyway."));
839
1123
  }
840
1124
  const agentPaths = getAgentPaths();
841
1125
  const olorePath = getOlorePackagePath(packageName, packageVersion);
842
1126
  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)}`);
1127
+ await fs7.ensureDir(path7.dirname(olorePath));
1128
+ await fs7.remove(olorePath);
1129
+ await fs7.copy(fullPath, olorePath);
1130
+ spinner.succeed(`Copied to ${pc5.gray(olorePath)}`);
847
1131
  const linkSpinner = ora("Linking to agent directories...").start();
848
1132
  const linked = [];
849
1133
  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);
1134
+ const targetDir = path7.join(skillsDir, skillName);
1135
+ await fs7.ensureDir(skillsDir);
1136
+ await fs7.remove(targetDir);
853
1137
  await linkOrCopy(olorePath, targetDir);
854
- linked.push(`${pc3.green("\u2713")} ${agent} ${pc3.gray("\u2192")} ${pc3.gray(targetDir)}`);
1138
+ linked.push(`${pc5.green("\u2713")} ${agent} ${pc5.gray("\u2192")} ${pc5.gray(targetDir)}`);
855
1139
  }
856
1140
  linkSpinner.stop();
857
1141
  linked.forEach((line) => console.log(` ${line}`));
858
- console.log(pc3.gray(` \u2514\u2500 all linked to ${olorePath}`));
1142
+ console.log(pc5.gray(` \u2514\u2500 all linked to ${olorePath}`));
859
1143
  console.log("");
860
- console.log(pc3.green("Installation complete!"));
1144
+ console.log(pc5.green("Installation complete!"));
861
1145
  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)"));
1146
+ console.log(pc5.gray("Skill is now available as:"));
1147
+ console.log(pc5.cyan(` /${skillName}`) + pc5.gray(" (Claude Code)"));
1148
+ console.log(pc5.cyan(` $${skillName}`) + pc5.gray(" (Codex)"));
1149
+ console.log(pc5.cyan(` ${skillName}`) + pc5.gray(" (OpenCode)"));
1150
+ await checkForUpdates();
866
1151
  }
867
1152
  async function install(pkg, options) {
868
1153
  if (options.force) {
869
- console.log(pc3.cyan("\n\u2728 May the Skill be with you.\n"));
1154
+ console.log(pc5.cyan("\n\u2728 May the Skill be with you.\n"));
870
1155
  }
871
1156
  if (isLocalPath(pkg)) {
872
1157
  await installFromLocal(pkg);
@@ -912,7 +1197,7 @@ function findSimilarPackages(input, packages, maxResults = 3) {
912
1197
  async function installFromRemote(pkg, optionsVersion) {
913
1198
  const { name, version: specVersion } = parsePackageSpec(pkg);
914
1199
  const requestedVersion = optionsVersion || specVersion || "latest";
915
- console.log(pc3.bold(`
1200
+ console.log(pc5.bold(`
916
1201
  Installing ${name}@${requestedVersion} from registry...
917
1202
  `));
918
1203
  const spinner = ora("Fetching package info...").start();
@@ -924,32 +1209,32 @@ Installing ${name}@${requestedVersion} from registry...
924
1209
  spinner.fail("Failed to resolve package");
925
1210
  if (error instanceof RegistryError) {
926
1211
  if (error.code === "NOT_FOUND") {
927
- console.log(pc3.yellow(`
1212
+ console.log(pc5.yellow(`
928
1213
  Package "${name}" not found in registry.`));
929
1214
  try {
930
1215
  const index = await fetchPackageIndex();
931
1216
  const similar = findSimilarPackages(name, index.packages);
932
1217
  if (similar.length > 0) {
933
- console.log(pc3.bold("\nDid you mean?"));
1218
+ console.log(pc5.bold("\nDid you mean?"));
934
1219
  for (const pkg2 of similar) {
935
- console.log(` ${pc3.cyan(pkg2.name)} ${pc3.gray("-")} ${pc3.gray(pkg2.description)}`);
1220
+ console.log(` ${pc5.cyan(pkg2.name)} ${pc5.gray("-")} ${pc5.gray(pkg2.description)}`);
936
1221
  }
937
1222
  }
938
1223
  } catch {
939
1224
  }
940
1225
  console.log(
941
- pc3.gray("\nRun ") + pc3.cyan("olore search") + pc3.gray(" to see all available packages.")
1226
+ pc5.gray("\nRun ") + pc5.cyan("olore search") + pc5.gray(" to see all available packages.")
942
1227
  );
943
- console.log(pc3.gray("\nFor local packages, use a path:"));
944
- console.log(pc3.cyan(` olore install ./vault/packages/${name}/<version>`));
1228
+ console.log(pc5.gray("\nFor local packages, use a path:"));
1229
+ console.log(pc5.cyan(` olore install ./vault/packages/${name}/<version>`));
945
1230
  console.log("");
946
1231
  } else if (error.code === "NETWORK_ERROR" || error.code === "TIMEOUT") {
947
- console.log(pc3.red(`
1232
+ console.log(pc5.red(`
948
1233
  Network error: ${error.message}`));
949
- console.log(pc3.gray("Please check your internet connection and try again."));
1234
+ console.log(pc5.gray("Please check your internet connection and try again."));
950
1235
  }
951
1236
  } else {
952
- console.log(pc3.red(`
1237
+ console.log(pc5.red(`
953
1238
  Error: ${error instanceof Error ? error.message : "Unknown error"}`));
954
1239
  }
955
1240
  process.exit(1);
@@ -957,26 +1242,26 @@ Error: ${error instanceof Error ? error.message : "Unknown error"}`));
957
1242
  const skillName = `olore-${name}-${versionInfo.version}`;
958
1243
  const agents = detectAgents();
959
1244
  if (agents.length === 0) {
960
- console.log(pc3.yellow("No agents detected. Creating directories anyway."));
1245
+ console.log(pc5.yellow("No agents detected. Creating directories anyway."));
961
1246
  }
962
1247
  const agentPaths = getAgentPaths();
963
1248
  const olorePath = getOlorePackagePath(name, versionInfo.version);
964
1249
  const downloadSpinner = ora("Downloading package...").start();
965
1250
  try {
966
1251
  await downloadAndInstall(versionInfo.downloadUrl, olorePath, versionInfo.integrity);
967
- downloadSpinner.succeed(`Downloaded to ${pc3.gray(olorePath)}`);
1252
+ downloadSpinner.succeed(`Downloaded to ${pc5.gray(olorePath)}`);
968
1253
  } catch (error) {
969
1254
  downloadSpinner.fail("Download failed");
970
1255
  if (error instanceof DownloadError) {
971
1256
  if (error.code === "CHECKSUM_MISMATCH") {
972
- console.log(pc3.red("\nChecksum verification failed!"));
973
- console.log(pc3.gray("The downloaded package may be corrupted or tampered with."));
1257
+ console.log(pc5.red("\nChecksum verification failed!"));
1258
+ console.log(pc5.gray("The downloaded package may be corrupted or tampered with."));
974
1259
  } else {
975
- console.log(pc3.red(`
1260
+ console.log(pc5.red(`
976
1261
  Download error: ${error.message}`));
977
1262
  }
978
1263
  } else {
979
- console.log(pc3.red(`
1264
+ console.log(pc5.red(`
980
1265
  Error: ${error instanceof Error ? error.message : "Unknown error"}`));
981
1266
  }
982
1267
  process.exit(1);
@@ -984,47 +1269,48 @@ Error: ${error instanceof Error ? error.message : "Unknown error"}`));
984
1269
  const linkSpinner = ora("Linking to agent directories...").start();
985
1270
  const linked = [];
986
1271
  for (const [agent, skillsDir] of Object.entries(agentPaths)) {
987
- const targetDir = path6.join(skillsDir, skillName);
988
- await fs6.ensureDir(skillsDir);
989
- await fs6.remove(targetDir);
1272
+ const targetDir = path7.join(skillsDir, skillName);
1273
+ await fs7.ensureDir(skillsDir);
1274
+ await fs7.remove(targetDir);
990
1275
  await linkOrCopy(olorePath, targetDir);
991
- linked.push(`${pc3.green("\u2713")} ${agent} ${pc3.gray("\u2192")} ${pc3.gray(targetDir)}`);
1276
+ linked.push(`${pc5.green("\u2713")} ${agent} ${pc5.gray("\u2192")} ${pc5.gray(targetDir)}`);
992
1277
  }
993
1278
  linkSpinner.stop();
994
1279
  linked.forEach((line) => console.log(` ${line}`));
995
- console.log(pc3.gray(` \u2514\u2500 all linked to ${olorePath}`));
1280
+ console.log(pc5.gray(` \u2514\u2500 all linked to ${olorePath}`));
996
1281
  console.log("");
997
- console.log(pc3.green("Installation complete!"));
1282
+ console.log(pc5.green("Installation complete!"));
998
1283
  console.log("");
999
- console.log(pc3.gray("Skill is now available as:"));
1000
- console.log(pc3.cyan(` /${skillName}`) + pc3.gray(" (Claude Code)"));
1001
- console.log(pc3.cyan(` $${skillName}`) + pc3.gray(" (Codex)"));
1002
- console.log(pc3.cyan(` ${skillName}`) + pc3.gray(" (OpenCode)"));
1284
+ console.log(pc5.gray("Skill is now available as:"));
1285
+ console.log(pc5.cyan(` /${skillName}`) + pc5.gray(" (Claude Code)"));
1286
+ console.log(pc5.cyan(` $${skillName}`) + pc5.gray(" (Codex)"));
1287
+ console.log(pc5.cyan(` ${skillName}`) + pc5.gray(" (OpenCode)"));
1288
+ await checkForUpdates();
1003
1289
  }
1004
1290
 
1005
1291
  // src/commands/link.ts
1006
- import path7 from "path";
1007
- import fs7 from "fs-extra";
1292
+ import path8 from "path";
1293
+ import fs8 from "fs-extra";
1008
1294
  import ora2 from "ora";
1009
- import pc4 from "picocolors";
1295
+ import pc6 from "picocolors";
1010
1296
  async function link(localPath) {
1011
1297
  const fullPath = expandPath(localPath);
1012
- if (!await fs7.pathExists(fullPath)) {
1298
+ if (!await fs8.pathExists(fullPath)) {
1013
1299
  throw new Error(`Path not found: ${fullPath}`);
1014
1300
  }
1015
- const stat = await fs7.stat(fullPath);
1301
+ const stat = await fs8.stat(fullPath);
1016
1302
  if (!stat.isDirectory()) {
1017
1303
  throw new Error(`Not a directory: ${fullPath}`);
1018
1304
  }
1019
- const lockPath = path7.join(fullPath, "olore-lock.json");
1020
- if (!await fs7.pathExists(lockPath)) {
1305
+ const lockPath = path8.join(fullPath, "olore-lock.json");
1306
+ if (!await fs8.pathExists(lockPath)) {
1021
1307
  throw new Error(`Missing olore-lock.json in ${fullPath}`);
1022
1308
  }
1023
- const skillPath = path7.join(fullPath, "SKILL.md");
1024
- if (!await fs7.pathExists(skillPath)) {
1309
+ const skillPath = path8.join(fullPath, "SKILL.md");
1310
+ if (!await fs8.pathExists(skillPath)) {
1025
1311
  throw new Error(`Missing SKILL.md in ${fullPath}. Run /build-docs first.`);
1026
1312
  }
1027
- const lock = await fs7.readJson(lockPath);
1313
+ const lock = await fs8.readJson(lockPath);
1028
1314
  const packageName = lock.name;
1029
1315
  const packageVersion = lock.version;
1030
1316
  if (!packageName) {
@@ -1034,63 +1320,63 @@ async function link(localPath) {
1034
1320
  throw new Error(`Invalid olore-lock.json: missing "version" field`);
1035
1321
  }
1036
1322
  const skillName = `olore-${packageName}-${packageVersion}`;
1037
- const skillContent = await fs7.readFile(skillPath, "utf-8");
1323
+ const skillContent = await fs8.readFile(skillPath, "utf-8");
1038
1324
  const nameMatch = skillContent.match(/^name:\s*(.+)$/m);
1039
1325
  const skillMdName = nameMatch ? nameMatch[1].trim() : null;
1040
1326
  if (skillMdName !== skillName) {
1041
- console.log(pc4.yellow(`
1327
+ console.log(pc6.yellow(`
1042
1328
  Warning: SKILL.md name mismatch`));
1043
- console.log(pc4.gray(` Expected: ${skillName}`));
1044
- console.log(pc4.gray(` Found: ${skillMdName || "(none)"}`));
1045
- console.log(pc4.yellow(` Updating SKILL.md to fix...`));
1329
+ console.log(pc6.gray(` Expected: ${skillName}`));
1330
+ console.log(pc6.gray(` Found: ${skillMdName || "(none)"}`));
1331
+ console.log(pc6.yellow(` Updating SKILL.md to fix...`));
1046
1332
  const updatedContent = skillMdName ? skillContent.replace(/^name:\s*.+$/m, `name: ${skillName}`) : skillContent.replace(/^---\n/, `---
1047
1333
  name: ${skillName}
1048
1334
  `);
1049
- await fs7.writeFile(skillPath, updatedContent);
1335
+ await fs8.writeFile(skillPath, updatedContent);
1050
1336
  }
1051
- console.log(pc4.bold(`
1337
+ console.log(pc6.bold(`
1052
1338
  Linking ${packageName}@${packageVersion}...
1053
1339
  `));
1054
1340
  const agents = detectAgents();
1055
1341
  if (agents.length === 0) {
1056
- console.log(pc4.yellow("No agents detected. Creating directories anyway."));
1342
+ console.log(pc6.yellow("No agents detected. Creating directories anyway."));
1057
1343
  }
1058
1344
  const agentPaths = getAgentPaths();
1059
1345
  const spinner = ora2(`${getLinkActionText()}...`).start();
1060
1346
  const linked = [];
1061
1347
  for (const [agent, skillsDir] of Object.entries(agentPaths)) {
1062
- const targetDir = path7.join(skillsDir, skillName);
1063
- await fs7.ensureDir(skillsDir);
1064
- await fs7.remove(targetDir);
1348
+ const targetDir = path8.join(skillsDir, skillName);
1349
+ await fs8.ensureDir(skillsDir);
1350
+ await fs8.remove(targetDir);
1065
1351
  await linkOrCopy(fullPath, targetDir);
1066
- linked.push(`${pc4.blue("\u26D3")} ${agent} ${pc4.gray("\u2192")} ${pc4.gray(targetDir)}`);
1352
+ linked.push(`${pc6.blue("\u26D3")} ${agent} ${pc6.gray("\u2192")} ${pc6.gray(targetDir)}`);
1067
1353
  }
1068
1354
  spinner.stop();
1069
1355
  linked.forEach((line) => console.log(` ${line}`));
1070
- console.log(pc4.gray(` \u2514\u2500 ${getLinkTypeText()} ${fullPath}`));
1356
+ console.log(pc6.gray(` \u2514\u2500 ${getLinkTypeText()} ${fullPath}`));
1071
1357
  console.log("");
1072
- console.log(pc4.blue("Link complete!"));
1358
+ console.log(pc6.blue("Link complete!"));
1073
1359
  console.log("");
1074
- console.log(pc4.gray("Skill is now available as:"));
1075
- console.log(pc4.cyan(` /${skillName}`) + pc4.gray(" (Claude Code)"));
1076
- console.log(pc4.cyan(` $${skillName}`) + pc4.gray(" (Codex)"));
1077
- console.log(pc4.cyan(` ${skillName}`) + pc4.gray(" (OpenCode)"));
1360
+ console.log(pc6.gray("Skill is now available as:"));
1361
+ console.log(pc6.cyan(` /${skillName}`) + pc6.gray(" (Claude Code)"));
1362
+ console.log(pc6.cyan(` $${skillName}`) + pc6.gray(" (Codex)"));
1363
+ console.log(pc6.cyan(` ${skillName}`) + pc6.gray(" (OpenCode)"));
1078
1364
  console.log("");
1079
- console.log(pc4.gray(`Development mode: ${getLinkTypeText()} source (bypasses ~/.olore).`));
1080
- console.log(pc4.gray("Changes to source are immediately visible."));
1365
+ console.log(pc6.gray(`Development mode: ${getLinkTypeText()} source (bypasses ~/.olore).`));
1366
+ console.log(pc6.gray("Changes to source are immediately visible."));
1081
1367
  console.log(
1082
- pc4.gray("Use ") + pc4.cyan("olore install") + pc4.gray(" for a stable copy in ~/.olore.")
1368
+ pc6.gray("Use ") + pc6.cyan("olore install") + pc6.gray(" for a stable copy in ~/.olore.")
1083
1369
  );
1084
1370
  }
1085
1371
 
1086
1372
  // src/commands/list.ts
1087
- import pc5 from "picocolors";
1373
+ import pc7 from "picocolors";
1088
1374
  async function list(options) {
1089
1375
  const packages = await getInstalledPackages();
1090
1376
  if (packages.length === 0) {
1091
- console.log(pc5.yellow("\nI find your lack of skills disturbing.\n"));
1092
- console.log(pc5.gray("No packages installed."));
1093
- console.log(`Run ${pc5.cyan("olore install <package>")} to install documentation.`);
1377
+ console.log(pc7.yellow("\nI find your lack of skills disturbing.\n"));
1378
+ console.log(pc7.gray("No packages installed."));
1379
+ console.log(`Run ${pc7.cyan("olore install <package>")} to install documentation.`);
1094
1380
  return;
1095
1381
  }
1096
1382
  if (options.json) {
@@ -1098,29 +1384,29 @@ async function list(options) {
1098
1384
  console.log(JSON.stringify({ packages, issueCount: issues2.length }, null, 2));
1099
1385
  return;
1100
1386
  }
1101
- console.log(pc5.bold("\nInstalled packages:\n"));
1387
+ console.log(pc7.bold("\nInstalled packages:\n"));
1102
1388
  console.log(
1103
- pc5.gray(
1389
+ pc7.gray(
1104
1390
  "PACKAGE".padEnd(25) + "VERSION".padEnd(12) + "TYPE".padEnd(10) + "FILES".padStart(8) + "SIZE".padStart(12)
1105
1391
  )
1106
1392
  );
1107
- console.log(pc5.gray("-".repeat(67)));
1393
+ console.log(pc7.gray("-".repeat(67)));
1108
1394
  for (const pkg of packages) {
1109
- const typeLabel = pkg.installType === "linked" ? pc5.blue("linked") : pkg.installType;
1395
+ const typeLabel = pkg.installType === "linked" ? pc7.blue("linked") : pkg.installType;
1110
1396
  console.log(
1111
1397
  pkg.name.padEnd(25) + pkg.version.padEnd(12) + typeLabel.padEnd(10) + String(pkg.files).padStart(8) + formatSize(pkg.size).padStart(12)
1112
1398
  );
1113
1399
  }
1114
- console.log(pc5.gray("-".repeat(67)));
1115
- console.log(pc5.gray(`Total: ${packages.length} packages`));
1400
+ console.log(pc7.gray("-".repeat(67)));
1401
+ console.log(pc7.gray(`Total: ${packages.length} packages`));
1116
1402
  console.log("");
1117
- console.log(pc5.gray("Types: installed = in ~/.olore, linked = dev symlink, copied = legacy"));
1403
+ console.log(pc7.gray("Types: installed = in ~/.olore, linked = dev symlink, copied = legacy"));
1118
1404
  const { issues } = await diagnose();
1119
1405
  if (issues.length > 0) {
1120
1406
  console.log("");
1121
1407
  console.log(
1122
- pc5.yellow(
1123
- `\u26A0 ${issues.length} issue${issues.length === 1 ? "" : "s"} detected. Run ${pc5.cyan("olore doctor")} for details.`
1408
+ pc7.yellow(
1409
+ `\u26A0 ${issues.length} issue${issues.length === 1 ? "" : "s"} detected. Run ${pc7.cyan("olore doctor")} for details.`
1124
1410
  )
1125
1411
  );
1126
1412
  }
@@ -1132,59 +1418,59 @@ function formatSize(bytes) {
1132
1418
  }
1133
1419
 
1134
1420
  // src/commands/order66.ts
1135
- import path8 from "path";
1136
- import fs8 from "fs-extra";
1421
+ import path9 from "path";
1422
+ import fs9 from "fs-extra";
1137
1423
  import ora3 from "ora";
1138
- import pc6 from "picocolors";
1424
+ import pc8 from "picocolors";
1139
1425
  async function order66() {
1140
- console.log(pc6.red("\n\u26A0\uFE0F Execute Order 66?\n"));
1141
- console.log(pc6.yellow("This will remove ALL installed documentation packages."));
1426
+ console.log(pc8.red("\n\u26A0\uFE0F Execute Order 66?\n"));
1427
+ console.log(pc8.yellow("This will remove ALL installed documentation packages."));
1142
1428
  const packages = await getInstalledPackages();
1143
1429
  if (packages.length === 0) {
1144
- console.log(pc6.gray("\nNo packages to remove. The Jedi are already gone."));
1430
+ console.log(pc8.gray("\nNo packages to remove. The Jedi are already gone."));
1145
1431
  return;
1146
1432
  }
1147
- console.log(pc6.gray(`
1433
+ console.log(pc8.gray(`
1148
1434
  Packages to be removed: ${packages.length}`));
1149
1435
  for (const pkg of packages) {
1150
- console.log(pc6.gray(` - ${pkg.name}@${pkg.version}`));
1436
+ console.log(pc8.gray(` - ${pkg.name}@${pkg.version}`));
1151
1437
  }
1152
- console.log(pc6.red('\n"It will be done, my lord."\n'));
1438
+ console.log(pc8.red('\n"It will be done, my lord."\n'));
1153
1439
  const spinner = ora3("Executing Order 66...").start();
1154
1440
  let removedCount = 0;
1155
1441
  const agentPaths = getAgentPaths();
1156
1442
  for (const pkg of packages) {
1157
1443
  const skillName = `olore-${pkg.name}-${pkg.version}`;
1158
1444
  for (const [, basePath] of Object.entries(agentPaths)) {
1159
- const skillPath = path8.join(basePath, skillName);
1160
- if (await fs8.pathExists(skillPath)) {
1161
- await fs8.remove(skillPath);
1445
+ const skillPath = path9.join(basePath, skillName);
1446
+ if (await fs9.pathExists(skillPath)) {
1447
+ await fs9.remove(skillPath);
1162
1448
  }
1163
1449
  }
1164
1450
  if (pkg.installType === "installed") {
1165
1451
  const olorePath = getOlorePackagePath(pkg.name, pkg.version);
1166
- if (await fs8.pathExists(olorePath)) {
1167
- await fs8.remove(olorePath);
1452
+ if (await fs9.pathExists(olorePath)) {
1453
+ await fs9.remove(olorePath);
1168
1454
  }
1169
1455
  }
1170
1456
  removedCount++;
1171
1457
  }
1172
1458
  spinner.succeed(`Removed ${removedCount} packages`);
1173
- console.log(pc6.gray("\nThe Jedi have been eliminated."));
1459
+ console.log(pc8.gray("\nThe Jedi have been eliminated."));
1174
1460
  }
1175
1461
 
1176
1462
  // src/commands/prune.ts
1177
- import pc7 from "picocolors";
1463
+ import pc9 from "picocolors";
1178
1464
  async function prune(options) {
1179
1465
  if (!options.json) {
1180
- console.log(pc7.bold("\nScanning for issues...\n"));
1466
+ console.log(pc9.bold("\nScanning for issues...\n"));
1181
1467
  }
1182
1468
  const { issues } = await diagnose();
1183
1469
  if (issues.length === 0) {
1184
1470
  if (options.json) {
1185
1471
  console.log(JSON.stringify({ removed: [], failed: [] }, null, 2));
1186
1472
  } else {
1187
- console.log(pc7.green("Nothing to prune. Everything is clean."));
1473
+ console.log(pc9.green("Nothing to prune. Everything is clean."));
1188
1474
  }
1189
1475
  return;
1190
1476
  }
@@ -1194,14 +1480,14 @@ async function prune(options) {
1194
1480
  return;
1195
1481
  }
1196
1482
  console.log(
1197
- pc7.yellow(`Would remove ${issues.length} item${issues.length === 1 ? "" : "s"}:
1483
+ pc9.yellow(`Would remove ${issues.length} item${issues.length === 1 ? "" : "s"}:
1198
1484
  `)
1199
1485
  );
1200
1486
  for (const issue of issues) {
1201
1487
  console.log(` ${issueLabel(issue.type)} ${displayPath(issue.path)}`);
1202
1488
  }
1203
1489
  console.log(`
1204
- Run ${pc7.cyan("olore prune")} (without --dry-run) to remove them.`);
1490
+ Run ${pc9.cyan("olore prune")} (without --dry-run) to remove them.`);
1205
1491
  return;
1206
1492
  }
1207
1493
  const result = await pruneIssues(issues);
@@ -1215,7 +1501,7 @@ Run ${pc7.cyan("olore prune")} (without --dry-run) to remove them.`);
1215
1501
  for (const entry of result.removed) {
1216
1502
  totalFreed += entry.freedBytes;
1217
1503
  console.log(
1218
- ` ${pc7.green("\u2713")} ${displayPath(entry.issue.path)} (${issueLabel(entry.issue.type)})`
1504
+ ` ${pc9.green("\u2713")} ${displayPath(entry.issue.path)} (${issueLabel(entry.issue.type)})`
1219
1505
  );
1220
1506
  }
1221
1507
  if (totalFreed > 0) {
@@ -1226,12 +1512,12 @@ ${formatBytes(totalFreed)} freed.`);
1226
1512
  if (result.failed.length > 0) {
1227
1513
  console.log("");
1228
1514
  console.log(
1229
- pc7.red(
1515
+ pc9.red(
1230
1516
  `Failed to remove ${result.failed.length} item${result.failed.length === 1 ? "" : "s"}:`
1231
1517
  )
1232
1518
  );
1233
1519
  for (const entry of result.failed) {
1234
- console.log(` ${pc7.red("\u2717")} ${displayPath(entry.issue.path)}: ${entry.error}`);
1520
+ console.log(` ${pc9.red("\u2717")} ${displayPath(entry.issue.path)}: ${entry.error}`);
1235
1521
  }
1236
1522
  }
1237
1523
  }
@@ -1249,12 +1535,12 @@ function issueLabel(type) {
1249
1535
  }
1250
1536
 
1251
1537
  // src/commands/remove.ts
1252
- import path9 from "path";
1253
- import fs9 from "fs-extra";
1538
+ import path10 from "path";
1539
+ import fs10 from "fs-extra";
1254
1540
  import ora4 from "ora";
1255
- import pc8 from "picocolors";
1541
+ import pc10 from "picocolors";
1256
1542
  async function remove(pkg) {
1257
- console.log(pc8.bold(`
1543
+ console.log(pc10.bold(`
1258
1544
  Removing ${pkg}...
1259
1545
  `));
1260
1546
  const packages = await getInstalledPackages();
@@ -1270,20 +1556,20 @@ Removing ${pkg}...
1270
1556
  return p.name === name;
1271
1557
  });
1272
1558
  if (matches.length === 0) {
1273
- console.error(pc8.red(`Package not found: ${pkg}`));
1559
+ console.error(pc10.red(`Package not found: ${pkg}`));
1274
1560
  console.log("\nInstalled packages:");
1275
1561
  for (const p of packages) {
1276
- console.log(` ${pc8.cyan(p.name)}@${p.version}`);
1562
+ console.log(` ${pc10.cyan(p.name)}@${p.version}`);
1277
1563
  }
1278
1564
  process.exit(1);
1279
1565
  }
1280
1566
  if (matches.length > 1 && !version2) {
1281
- console.error(pc8.red(`Multiple versions found for ${name}:`));
1567
+ console.error(pc10.red(`Multiple versions found for ${name}:`));
1282
1568
  for (const p of matches) {
1283
- console.log(` ${pc8.cyan(p.name)}@${p.version} (${p.installType})`);
1569
+ console.log(` ${pc10.cyan(p.name)}@${p.version} (${p.installType})`);
1284
1570
  }
1285
1571
  console.log(`
1286
- Specify version: ${pc8.cyan(`olore remove ${name}@<version>`)}`);
1572
+ Specify version: ${pc10.cyan(`olore remove ${name}@<version>`)}`);
1287
1573
  process.exit(1);
1288
1574
  }
1289
1575
  const found = matches[0];
@@ -1292,32 +1578,32 @@ Specify version: ${pc8.cyan(`olore remove ${name}@<version>`)}`);
1292
1578
  const removed = [];
1293
1579
  const agentPaths = getAgentPaths();
1294
1580
  for (const [agent, basePath] of Object.entries(agentPaths)) {
1295
- const skillPath = path9.join(basePath, skillName);
1296
- if (await fs9.pathExists(skillPath)) {
1297
- await fs9.remove(skillPath);
1298
- removed.push(`${pc8.green("\u2713")} ${agent}`);
1581
+ const skillPath = path10.join(basePath, skillName);
1582
+ if (await fs10.pathExists(skillPath)) {
1583
+ await fs10.remove(skillPath);
1584
+ removed.push(`${pc10.green("\u2713")} ${agent}`);
1299
1585
  }
1300
1586
  }
1301
1587
  if (found.installType === "installed") {
1302
1588
  const olorePath = getOlorePackagePath(found.name, found.version);
1303
- if (await fs9.pathExists(olorePath)) {
1304
- await fs9.remove(olorePath);
1305
- removed.push(`${pc8.green("\u2713")} ~/.olore`);
1589
+ if (await fs10.pathExists(olorePath)) {
1590
+ await fs10.remove(olorePath);
1591
+ removed.push(`${pc10.green("\u2713")} ~/.olore`);
1306
1592
  }
1307
1593
  }
1308
1594
  spinner.stop();
1309
1595
  if (removed.length === 0) {
1310
- console.log(pc8.yellow("No files found to remove."));
1596
+ console.log(pc10.yellow("No files found to remove."));
1311
1597
  } else {
1312
1598
  removed.forEach((line) => console.log(` ${line}`));
1313
1599
  console.log("");
1314
- console.log(pc8.green(`Removed ${found.name}@${found.version}`));
1600
+ console.log(pc10.green(`Removed ${found.name}@${found.version}`));
1315
1601
  }
1316
1602
  }
1317
1603
 
1318
1604
  // src/commands/search.ts
1319
1605
  import ora5 from "ora";
1320
- import pc9 from "picocolors";
1606
+ import pc11 from "picocolors";
1321
1607
  async function search(query, options) {
1322
1608
  const spinner = ora5("Fetching package registry...").start();
1323
1609
  let packages;
@@ -1329,15 +1615,15 @@ async function search(query, options) {
1329
1615
  spinner.fail("Failed to fetch registry");
1330
1616
  if (error instanceof RegistryError) {
1331
1617
  if (error.code === "NETWORK_ERROR" || error.code === "TIMEOUT") {
1332
- console.log(pc9.red(`
1618
+ console.log(pc11.red(`
1333
1619
  Network error: ${error.message}`));
1334
- console.log(pc9.gray("Please check your internet connection and try again."));
1620
+ console.log(pc11.gray("Please check your internet connection and try again."));
1335
1621
  } else {
1336
- console.log(pc9.red(`
1622
+ console.log(pc11.red(`
1337
1623
  Error: ${error.message}`));
1338
1624
  }
1339
1625
  } else {
1340
- console.log(pc9.red(`
1626
+ console.log(pc11.red(`
1341
1627
  Error: ${error instanceof Error ? error.message : "Unknown error"}`));
1342
1628
  }
1343
1629
  process.exit(1);
@@ -1351,10 +1637,10 @@ Error: ${error instanceof Error ? error.message : "Unknown error"}`));
1351
1637
  }
1352
1638
  if (entries.length === 0) {
1353
1639
  if (query) {
1354
- console.log(pc9.yellow(`
1640
+ console.log(pc11.yellow(`
1355
1641
  No packages matching '${query}'`));
1356
1642
  } else {
1357
- console.log(pc9.yellow("\nNo packages available in the registry"));
1643
+ console.log(pc11.yellow("\nNo packages available in the registry"));
1358
1644
  }
1359
1645
  return;
1360
1646
  }
@@ -1381,26 +1667,27 @@ No packages matching '${query}'`));
1381
1667
  const colName = 20;
1382
1668
  const colDesc = 44;
1383
1669
  const colVersions = 12;
1384
- console.log(pc9.bold("\nAvailable packages:\n"));
1670
+ console.log(pc11.bold("\nAvailable packages:\n"));
1385
1671
  console.log(
1386
- pc9.gray(
1672
+ pc11.gray(
1387
1673
  "PACKAGE".padEnd(colName) + "DESCRIPTION".padEnd(colDesc) + "VERSIONS".padEnd(colVersions) + "INSTALLED"
1388
1674
  )
1389
1675
  );
1390
- console.log(pc9.gray("\u2500".repeat(colName + colDesc + colVersions + 12)));
1676
+ console.log(pc11.gray("\u2500".repeat(colName + colDesc + colVersions + 12)));
1391
1677
  for (const [name, info] of entries.sort(([a], [b]) => a.localeCompare(b))) {
1392
1678
  const desc = truncate(info.description, colDesc - 2);
1393
1679
  const versions = info.versions.join(", ");
1394
1680
  const installedVersion = installedVersions.get(name);
1395
- const status = installedVersion ? pc9.green(`\u2713 ${installedVersion}`) : "";
1681
+ const status = installedVersion ? pc11.green(`\u2713 ${installedVersion}`) : "";
1396
1682
  console.log(
1397
1683
  name.padEnd(colName) + desc.padEnd(colDesc) + versions.padEnd(colVersions) + status
1398
1684
  );
1399
1685
  }
1400
- console.log(pc9.gray("\u2500".repeat(colName + colDesc + colVersions + 12)));
1401
- console.log(pc9.gray(`${entries.length} package${entries.length === 1 ? "" : "s"} available`));
1686
+ console.log(pc11.gray("\u2500".repeat(colName + colDesc + colVersions + 12)));
1687
+ console.log(pc11.gray(`${entries.length} package${entries.length === 1 ? "" : "s"} available`));
1402
1688
  console.log(`
1403
- Install with: ${pc9.cyan("olore install <package>")}`);
1689
+ Install with: ${pc11.cyan("olore install <package>")}`);
1690
+ await checkForUpdates();
1404
1691
  }
1405
1692
  function truncate(str, maxLen) {
1406
1693
  if (str.length <= maxLen) return str;
@@ -1412,12 +1699,12 @@ var require2 = createRequire(import.meta.url);
1412
1699
  var { version } = require2("../package.json");
1413
1700
  var program = new Command();
1414
1701
  program.name("olore").description("Universal documentation for any AI coding agent").version(version).addHelpText("after", `
1415
- ${pc10.gray("May the Skill be with you.")}`);
1702
+ ${pc12.gray("May the Skill be with you.")}`);
1416
1703
  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) => {
1417
1704
  try {
1418
1705
  await init(options);
1419
1706
  } catch (error) {
1420
- console.error(pc10.red(`Error: ${error.message}`));
1707
+ console.error(pc12.red(`Error: ${error.message}`));
1421
1708
  process.exit(1);
1422
1709
  }
1423
1710
  });
@@ -1425,7 +1712,7 @@ program.command("install <package>").alias("i").description("Install a documenta
1425
1712
  try {
1426
1713
  await install(pkg, options);
1427
1714
  } catch (error) {
1428
- console.error(pc10.red(`Error: ${error.message}`));
1715
+ console.error(pc12.red(`Error: ${error.message}`));
1429
1716
  process.exit(1);
1430
1717
  }
1431
1718
  });
@@ -1433,7 +1720,7 @@ program.command("link <path>").description("Link a local package for development
1433
1720
  try {
1434
1721
  await link(localPath);
1435
1722
  } catch (error) {
1436
- console.error(pc10.red(`Error: ${error.message}`));
1723
+ console.error(pc12.red(`Error: ${error.message}`));
1437
1724
  process.exit(1);
1438
1725
  }
1439
1726
  });
@@ -1441,7 +1728,7 @@ program.command("list").alias("ls").description("List installed documentation pa
1441
1728
  try {
1442
1729
  await list(options);
1443
1730
  } catch (error) {
1444
- console.error(pc10.red(`Error: ${error.message}`));
1731
+ console.error(pc12.red(`Error: ${error.message}`));
1445
1732
  process.exit(1);
1446
1733
  }
1447
1734
  });
@@ -1449,7 +1736,7 @@ program.command("search [query]").description("Search available packages in the
1449
1736
  try {
1450
1737
  await search(query, options);
1451
1738
  } catch (error) {
1452
- console.error(pc10.red(`Error: ${error.message}`));
1739
+ console.error(pc12.red(`Error: ${error.message}`));
1453
1740
  process.exit(1);
1454
1741
  }
1455
1742
  });
@@ -1457,7 +1744,7 @@ program.command("remove <package>").alias("rm").description("Remove an installed
1457
1744
  try {
1458
1745
  await remove(pkg);
1459
1746
  } catch (error) {
1460
- console.error(pc10.red(`Error: ${error.message}`));
1747
+ console.error(pc12.red(`Error: ${error.message}`));
1461
1748
  process.exit(1);
1462
1749
  }
1463
1750
  });
@@ -1465,7 +1752,7 @@ program.command("doctor").description("Check for issues with installed packages"
1465
1752
  try {
1466
1753
  await doctor(options);
1467
1754
  } catch (error) {
1468
- console.error(pc10.red(`Error: ${error.message}`));
1755
+ console.error(pc12.red(`Error: ${error.message}`));
1469
1756
  process.exit(1);
1470
1757
  }
1471
1758
  });
@@ -1473,7 +1760,15 @@ program.command("prune").description("Remove dangling symlinks, orphaned package
1473
1760
  try {
1474
1761
  await prune(options);
1475
1762
  } catch (error) {
1476
- console.error(pc10.red(`Error: ${error.message}`));
1763
+ console.error(pc12.red(`Error: ${error.message}`));
1764
+ process.exit(1);
1765
+ }
1766
+ });
1767
+ 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) => {
1768
+ try {
1769
+ await inject(options);
1770
+ } catch (error) {
1771
+ console.error(pc12.red(`Error: ${error.message}`));
1477
1772
  process.exit(1);
1478
1773
  }
1479
1774
  });
@@ -1481,7 +1776,7 @@ program.command("order66").description(false).action(async () => {
1481
1776
  try {
1482
1777
  await order66();
1483
1778
  } catch (error) {
1484
- console.error(pc10.red(`Error: ${error.message}`));
1779
+ console.error(pc12.red(`Error: ${error.message}`));
1485
1780
  process.exit(1);
1486
1781
  }
1487
1782
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@olorehq/olore",
3
- "version": "0.1.5",
3
+ "version": "0.2.1",
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"