codebase-wiki 0.1.0 → 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.
package/CHANGELOG.md CHANGED
@@ -1,8 +1,24 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 03a4d29: Initial v0.1.0 release of `code-wiki`.
8
+
9
+ - M1: scaffold + walker + minimal render.
10
+ - M2: tree-sitter extraction for TS/JS/TSX/JSX.
11
+ - M3: 7 more language extractors (Python / Go / Rust / Java / C / C++ / Ruby).
12
+ - M4: graph extraction — imports + dependents; usable by `wiki_callers` / `wiki_callees` MCP tools.
13
+ - M5: MCP resource pagination, smarter auto-nudge hooks (config-driven, freshness-aware).
14
+ - M6: incremental refresh — `codewiki refresh` uses git diff; `codewiki watch` runs chokidar.
15
+ - M7: optional LLM enrichment — file-level Haiku + module-level Sonnet, content-hash cached.
16
+ - M8: Mermaid diagrams in architecture.md and module pages.
17
+
3
18
  ## [Unreleased]
4
19
 
5
20
  ### Fixed
21
+
6
22
  - Slash commands now invoke `${CLAUDE_PLUGIN_ROOT}/dist/codewiki.mjs` directly
7
23
  instead of relying on a globally-installed `codewiki` binary. Plugin is fully
8
24
  self-contained.
@@ -18,11 +34,13 @@
18
34
  similar packages had escaped inlining under the old config).
19
35
 
20
36
  ### Pending
37
+
21
38
  - v0.1.0 tag — all 9 milestones + install fix ready.
22
39
 
23
40
  ## v0.1.0 (in progress, target tag)
24
41
 
25
42
  ### Added
43
+
26
44
  - M1: scaffolding, walker, minimal render, hooks, MCP server stub.
27
45
  - M2: tree-sitter extraction (TS / JS / TSX / JSX).
28
46
  - M3: 7 more language extractors (Python / Go / Rust / Java / C / C++ / Ruby).
package/dist/CHANGELOG.md CHANGED
@@ -1,8 +1,24 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 03a4d29: Initial v0.1.0 release of `code-wiki`.
8
+
9
+ - M1: scaffold + walker + minimal render.
10
+ - M2: tree-sitter extraction for TS/JS/TSX/JSX.
11
+ - M3: 7 more language extractors (Python / Go / Rust / Java / C / C++ / Ruby).
12
+ - M4: graph extraction — imports + dependents; usable by `wiki_callers` / `wiki_callees` MCP tools.
13
+ - M5: MCP resource pagination, smarter auto-nudge hooks (config-driven, freshness-aware).
14
+ - M6: incremental refresh — `codewiki refresh` uses git diff; `codewiki watch` runs chokidar.
15
+ - M7: optional LLM enrichment — file-level Haiku + module-level Sonnet, content-hash cached.
16
+ - M8: Mermaid diagrams in architecture.md and module pages.
17
+
3
18
  ## [Unreleased]
4
19
 
5
20
  ### Fixed
21
+
6
22
  - Slash commands now invoke `${CLAUDE_PLUGIN_ROOT}/dist/codewiki.mjs` directly
7
23
  instead of relying on a globally-installed `codewiki` binary. Plugin is fully
8
24
  self-contained.
@@ -18,11 +34,13 @@
18
34
  similar packages had escaped inlining under the old config).
19
35
 
20
36
  ### Pending
37
+
21
38
  - v0.1.0 tag — all 9 milestones + install fix ready.
22
39
 
23
40
  ## v0.1.0 (in progress, target tag)
24
41
 
25
42
  ### Added
43
+
26
44
  - M1: scaffolding, walker, minimal render, hooks, MCP server stub.
27
45
  - M2: tree-sitter extraction (TS / JS / TSX / JSX).
28
46
  - M3: 7 more language extractors (Python / Go / Rust / Java / C / C++ / Ruby).
@@ -1,10 +1,11 @@
1
1
  import path__default from 'node:path';
2
2
  import { promises } from 'node:fs';
3
- import { c as repoRel, a as log, t as toPosix, l as loadConfig, d as child, f as configSummary, w as writeJson, b as atomicWriteText, e as exists } from './config.mjs';
3
+ import { b as repoRel, l as log, t as toPosix, c as child, w as writeJson, a as atomicWriteText, e as exists } from '../shared/codebase-wiki.CzOYKZWm.mjs';
4
+ import { loadConfig, configSummary } from './config.mjs';
4
5
  import ignore from 'ignore';
5
6
  import { globby } from 'globby';
7
+ import { c as countTokens, g as groupModules, m as moduleForFile } from '../shared/codebase-wiki.Wp4qpPB-.mjs';
6
8
  import { createHash } from 'node:crypto';
7
- import { encode } from 'gpt-tokenizer/encoding/cl100k_base';
8
9
  import { Language, Parser, Query } from 'web-tree-sitter';
9
10
 
10
11
  const EXT_TO_LANG = {
@@ -83,82 +84,10 @@ const walker = {
83
84
  walkFiles: walkFiles
84
85
  };
85
86
 
86
- const TEST_PATTERNS = [
87
- /(^|\/)__tests__\//,
88
- /\.test\.[a-z]+$/,
89
- /\.spec\.[a-z]+$/,
90
- /(^|\/)test_(.+)\.[a-z]+$/,
91
- /(^|\/)(.+)_test\.[a-z]+$/,
92
- /(^|\/)spec\//
93
- ];
94
- function isTestFile(repoPath) {
95
- return TEST_PATTERNS.some((re) => re.test(repoPath));
96
- }
97
- function moduleForFile(repoPath, cfg) {
98
- if (isTestFile(repoPath)) return "_tests";
99
- for (const [from, to] of Object.entries(cfg.modules.alias)) {
100
- if (repoPath === from || repoPath.startsWith(`${from}/`)) {
101
- const remainder = repoPath.slice(from.length).replace(/^\//, "");
102
- const top2 = remainder.split("/")[0] || "_root";
103
- const candidate = `${to}/${remainder === "" ? "" : top2}`.replace(/\/$/, "");
104
- return candidate.split("/")[0] || "_root";
105
- }
106
- }
107
- const top = repoPath.split("/")[0];
108
- return top || "_root";
109
- }
110
- function groupModules(files, cfg) {
111
- const map = /* @__PURE__ */ new Map();
112
- for (const f of files) {
113
- if (f.repoPath.startsWith(".codewiki/")) continue;
114
- const id = moduleForFile(f.repoPath, cfg);
115
- let entry = map.get(id);
116
- if (!entry) {
117
- entry = {
118
- id,
119
- title: id,
120
- files: [],
121
- publicSurface: []
122
- };
123
- map.set(id, entry);
124
- }
125
- entry.files.push(f.repoPath);
126
- for (const s of f.publicSymbols) {
127
- entry.publicSurface.push(`${s.kind === "method" ? "method" : s.kind} ${s.name}`);
128
- }
129
- }
130
- for (const id of [...map.keys()]) {
131
- if (cfg.modules.ignore.includes(id)) {
132
- map.delete(id);
133
- }
134
- }
135
- return map;
136
- }
137
-
138
87
  function sha256Hex(input) {
139
88
  return createHash("sha256").update(input).digest("hex");
140
89
  }
141
90
 
142
- function countTokens(input) {
143
- if (!input) return 0;
144
- return encode(input).length;
145
- }
146
- function truncateToTokens(text, budget, ellipsis = "\u2026") {
147
- const current = countTokens(text);
148
- if (current <= budget) return text;
149
- let lo = 0;
150
- let hi = text.length;
151
- while (lo < hi) {
152
- const mid = lo + hi + 1 >> 1;
153
- if (countTokens(text.slice(0, mid)) <= budget - 1) {
154
- lo = mid;
155
- } else {
156
- hi = mid - 1;
157
- }
158
- }
159
- return text.slice(0, lo).trimEnd() + (lo > 0 ? " " + ellipsis : "");
160
- }
161
-
162
91
  const GENERATOR = `code-wiki`;
163
92
  const VERSION = "0.1.0";
164
93
  function frontmatter(page) {
@@ -1973,4 +1902,4 @@ async function replaceDir(target, replacement) {
1973
1902
  await promises.rename(replacement, target);
1974
1903
  }
1975
1904
 
1976
- export { walker as a, buildWiki as b, countTokens as c, detectLanguage as d, groupModules as g, moduleForFile as m, truncateToTokens as t, walkFiles as w };
1905
+ export { walker as a, buildWiki as b, detectLanguage as d, walkFiles as w };
@@ -1,59 +1,9 @@
1
- import pino from 'pino';
2
1
  import { promises } from 'node:fs';
3
2
  import path__default from 'node:path';
3
+ import { r as readJson, t as toPosix } from '../shared/codebase-wiki.CzOYKZWm.mjs';
4
+ import 'pino';
4
5
  import 'node:os';
5
6
 
6
- const level = process.env.CODEWIKI_LOG ?? (process.env.NODE_ENV === "test" ? "silent" : "info");
7
- const log = pino({
8
- level,
9
- base: { name: "code-wiki" },
10
- timestamp: pino.stdTimeFunctions.isoTime
11
- });
12
- const child = (bindings) => log.child(bindings);
13
-
14
- function toPosix(p) {
15
- return p.replace(/\\/g, "/");
16
- }
17
- async function exists(filePath) {
18
- try {
19
- await promises.access(filePath);
20
- return true;
21
- } catch {
22
- return false;
23
- }
24
- }
25
- async function readText(filePath) {
26
- return promises.readFile(filePath, "utf8");
27
- }
28
- async function readJson(filePath) {
29
- try {
30
- const text = await readText(filePath);
31
- return JSON.parse(text);
32
- } catch {
33
- return null;
34
- }
35
- }
36
- async function writeText(filePath, content) {
37
- const dir = path__default.dirname(filePath);
38
- await promises.mkdir(dir, { recursive: true });
39
- await promises.writeFile(filePath, content, "utf8");
40
- }
41
- async function writeJson(filePath, value) {
42
- const text = JSON.stringify(value, null, 2) + "\n";
43
- await writeText(filePath, text);
44
- }
45
- async function atomicWriteText(target, content) {
46
- const dir = path__default.dirname(target);
47
- await promises.mkdir(dir, { recursive: true });
48
- const tmp = path__default.join(dir, `.tmp.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2, 8)}`);
49
- await promises.writeFile(tmp, content, "utf8");
50
- await promises.rename(tmp, target);
51
- }
52
- function repoRel(absolute, root) {
53
- const rel = path__default.relative(root, absolute);
54
- return toPosix(rel).replace(/^\.\//, "");
55
- }
56
-
57
7
  const DEFAULT_CONFIG = {
58
8
  outDir: ".codewiki",
59
9
  sourceRoots: ["."],
@@ -164,11 +114,4 @@ function configSummary(c) {
164
114
  ].join(" ");
165
115
  }
166
116
 
167
- const config = {
168
- __proto__: null,
169
- DEFAULT_CONFIG: DEFAULT_CONFIG,
170
- configSummary: configSummary,
171
- loadConfig: loadConfig
172
- };
173
-
174
- export { DEFAULT_CONFIG as D, log as a, atomicWriteText as b, repoRel as c, child as d, exists as e, configSummary as f, config as g, loadConfig as l, readJson as r, toPosix as t, writeJson as w };
117
+ export { DEFAULT_CONFIG, configSummary, loadConfig };
@@ -4,14 +4,11 @@ import { createHash } from 'node:crypto';
4
4
  import Anthropic from '@anthropic-ai/sdk';
5
5
  import PQueue from 'p-queue';
6
6
  import pRetry from 'p-retry';
7
- import { a as log, r as readJson, w as writeJson } from './config.mjs';
8
- import { g as groupModules, c as countTokens } from './build.mjs';
7
+ import { l as log, r as readJson, w as writeJson } from '../shared/codebase-wiki.CzOYKZWm.mjs';
8
+ import { g as groupModules, c as countTokens } from '../shared/codebase-wiki.Wp4qpPB-.mjs';
9
9
  import 'pino';
10
10
  import 'node:os';
11
- import 'ignore';
12
- import 'globby';
13
11
  import 'gpt-tokenizer/encoding/cl100k_base';
14
- import 'web-tree-sitter';
15
12
 
16
13
  const SYSTEM_PROMPT = "You are a precise code summarizer. Output ONLY a one-line PURPOSE and a 1-3 sentence NOTES section. No bullet lists, no headings, no markdown formatting. Tone: terse, technical, factual.";
17
14
  function client(opts) {
@@ -188,7 +185,7 @@ async function enrichAll(opts) {
188
185
  return { files, modules };
189
186
  }
190
187
  async function runEnrichmentCli(cwd, opts = {}) {
191
- const { loadConfig } = await import('./config.mjs').then(function (n) { return n.g; });
188
+ const { loadConfig } = await import('./config.mjs');
192
189
  const { walkFiles } = await import('./build.mjs').then(function (n) { return n.a; });
193
190
  const cfg = await loadConfig(cwd);
194
191
  const walked = await walkFiles({ root: cwd, ignoreGlobs: cfg.ignore });
@@ -4,7 +4,8 @@ import path__default from 'node:path';
4
4
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
5
5
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
6
6
  import { ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
7
- import { l as loadConfig, r as readJson, a as log } from './chunks/config.mjs';
7
+ import { r as readJson, l as log } from './shared/codebase-wiki.CzOYKZWm.mjs';
8
+ import { loadConfig } from './chunks/config.mjs';
8
9
  import 'pino';
9
10
  import 'node:fs';
10
11
  import 'node:os';
@@ -1,11 +1,13 @@
1
- export { b as buildWiki, c as countTokens, d as detectLanguage, g as groupModules, m as moduleForFile, t as truncateToTokens, w as walkFiles } from './chunks/build.mjs';
2
- export { D as DEFAULT_CONFIG, l as loadConfig } from './chunks/config.mjs';
1
+ export { b as buildWiki, d as detectLanguage, w as walkFiles } from './chunks/build.mjs';
2
+ export { DEFAULT_CONFIG, loadConfig } from './chunks/config.mjs';
3
+ export { c as countTokens, g as groupModules, m as moduleForFile, t as truncateToTokens } from './shared/codebase-wiki.Wp4qpPB-.mjs';
3
4
  import 'node:path';
4
5
  import 'node:fs';
6
+ import './shared/codebase-wiki.CzOYKZWm.mjs';
7
+ import 'pino';
8
+ import 'node:os';
5
9
  import 'ignore';
6
10
  import 'globby';
7
11
  import 'node:crypto';
8
- import 'gpt-tokenizer/encoding/cl100k_base';
9
12
  import 'web-tree-sitter';
10
- import 'pino';
11
- import 'node:os';
13
+ import 'gpt-tokenizer/encoding/cl100k_base';
package/dist/codewiki.mjs CHANGED
@@ -2,6 +2,7 @@
2
2
  import process$1 from 'node:process';
3
3
  import * as path from 'node:path';
4
4
  import path__default, { resolve, join, relative, sep } from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
5
6
  import { Command } from 'commander';
6
7
  import { EventEmitter } from 'node:events';
7
8
  import { unwatchFile, watchFile, watch as watch$1, stat as stat$1 } from 'node:fs';
@@ -9,12 +10,14 @@ import { lstat, stat, readdir, realpath, open } from 'node:fs/promises';
9
10
  import { Readable } from 'node:stream';
10
11
  import { type } from 'node:os';
11
12
  import { b as buildWiki } from './chunks/build.mjs';
12
- import { r as readJson, w as writeJson, b as atomicWriteText, l as loadConfig, e as exists } from './chunks/config.mjs';
13
+ import { loadConfig } from './chunks/config.mjs';
14
+ import { r as readJson, w as writeJson, a as atomicWriteText, e as exists } from './shared/codebase-wiki.CzOYKZWm.mjs';
13
15
  import { simpleGit } from 'simple-git';
14
16
  import 'ignore';
15
17
  import 'globby';
16
- import 'node:crypto';
18
+ import './shared/codebase-wiki.Wp4qpPB-.mjs';
17
19
  import 'gpt-tokenizer/encoding/cl100k_base';
20
+ import 'node:crypto';
18
21
  import 'web-tree-sitter';
19
22
  import 'pino';
20
23
 
@@ -1768,7 +1771,24 @@ async function enqueueInvalidation(cwd, repoPath) {
1768
1771
  await atomicWriteText(p, JSON.stringify(state, null, 2));
1769
1772
  }
1770
1773
 
1771
- const pkg = { version: "0.1.0" };
1774
+ const here = path__default.dirname(fileURLToPath(import.meta.url));
1775
+ let pkgVersion = "0.0.0";
1776
+ for (const candidate of [
1777
+ path__default.join(here, "..", "package.json"),
1778
+ path__default.join(here, "..", "..", "package.json"),
1779
+ path__default.join(here, "..", "..", "..", "package.json")
1780
+ ]) {
1781
+ try {
1782
+ const txt = await import('node:fs/promises').then((m) => m.readFile(candidate, "utf8"));
1783
+ const parsed = JSON.parse(txt);
1784
+ if (parsed?.name === "codebase-wiki" && parsed.version) {
1785
+ pkgVersion = parsed.version;
1786
+ break;
1787
+ }
1788
+ } catch {
1789
+ }
1790
+ }
1791
+ const pkg = { version: pkgVersion };
1772
1792
  async function main() {
1773
1793
  const program = new Command();
1774
1794
  program.name("codewiki").description("Token-efficient code wiki generator and Claude Code plugin entry point").version(pkg.version).option("--cwd <path>", "project root", process$1.cwd());
@@ -1935,11 +1955,12 @@ async function main() {
1935
1955
  const cfg = await loadConfig(cwd);
1936
1956
  const wikiBase = path__default.join(cwd, cfg.outDir);
1937
1957
  const rel = String(pathOrSymbol).replace(/^\.\//, "");
1958
+ const symbolPath = rel.includes("::") ? rel.replace(/::/g, "/") + ".md" : null;
1938
1959
  const candidates = [
1939
1960
  path__default.join(wikiBase, rel.endsWith(".md") ? rel : `${rel}.md`),
1940
1961
  path__default.join(wikiBase, "files", `${rel}.md`),
1941
1962
  path__default.join(wikiBase, "modules", `${rel}.md`),
1942
- path__default.join(wikiBase, "symbols", `${rel.replace("::", "/")}.md`)
1963
+ ...symbolPath ? [path__default.join(wikiBase, "symbols", symbolPath)] : []
1943
1964
  ];
1944
1965
  for (const c of candidates) {
1945
1966
  if (await exists(c)) {
@@ -0,0 +1,57 @@
1
+ import pino from 'pino';
2
+ import { promises } from 'node:fs';
3
+ import path__default from 'node:path';
4
+ import 'node:os';
5
+
6
+ const level = process.env.CODEWIKI_LOG ?? (process.env.NODE_ENV === "test" ? "silent" : "info");
7
+ const log = pino({
8
+ level,
9
+ base: { name: "code-wiki" },
10
+ timestamp: pino.stdTimeFunctions.isoTime
11
+ });
12
+ const child = (bindings) => log.child(bindings);
13
+
14
+ function toPosix(p) {
15
+ return p.replace(/\\/g, "/");
16
+ }
17
+ async function exists(filePath) {
18
+ try {
19
+ await promises.access(filePath);
20
+ return true;
21
+ } catch {
22
+ return false;
23
+ }
24
+ }
25
+ async function readText(filePath) {
26
+ return promises.readFile(filePath, "utf8");
27
+ }
28
+ async function readJson(filePath) {
29
+ try {
30
+ const text = await readText(filePath);
31
+ return JSON.parse(text);
32
+ } catch {
33
+ return null;
34
+ }
35
+ }
36
+ async function writeText(filePath, content) {
37
+ const dir = path__default.dirname(filePath);
38
+ await promises.mkdir(dir, { recursive: true });
39
+ await promises.writeFile(filePath, content, "utf8");
40
+ }
41
+ async function writeJson(filePath, value) {
42
+ const text = JSON.stringify(value, null, 2) + "\n";
43
+ await writeText(filePath, text);
44
+ }
45
+ async function atomicWriteText(target, content) {
46
+ const dir = path__default.dirname(target);
47
+ await promises.mkdir(dir, { recursive: true });
48
+ const tmp = path__default.join(dir, `.tmp.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2, 8)}`);
49
+ await promises.writeFile(tmp, content, "utf8");
50
+ await promises.rename(tmp, target);
51
+ }
52
+ function repoRel(absolute, root) {
53
+ const rel = path__default.relative(root, absolute);
54
+ return toPosix(rel).replace(/^\.\//, "");
55
+ }
56
+
57
+ export { atomicWriteText as a, repoRel as b, child as c, exists as e, log as l, readJson as r, toPosix as t, writeJson as w };
@@ -0,0 +1,75 @@
1
+ import { encode } from 'gpt-tokenizer/encoding/cl100k_base';
2
+
3
+ const TEST_PATTERNS = [
4
+ /(^|\/)__tests__\//,
5
+ /\.test\.[a-z]+$/,
6
+ /\.spec\.[a-z]+$/,
7
+ /(^|\/)test_(.+)\.[a-z]+$/,
8
+ /(^|\/)(.+)_test\.[a-z]+$/,
9
+ /(^|\/)spec\//
10
+ ];
11
+ function isTestFile(repoPath) {
12
+ return TEST_PATTERNS.some((re) => re.test(repoPath));
13
+ }
14
+ function moduleForFile(repoPath, cfg) {
15
+ if (isTestFile(repoPath)) return "_tests";
16
+ for (const [from, to] of Object.entries(cfg.modules.alias)) {
17
+ if (repoPath === from || repoPath.startsWith(`${from}/`)) {
18
+ const remainder = repoPath.slice(from.length).replace(/^\//, "");
19
+ const top2 = remainder.split("/")[0] || "_root";
20
+ const candidate = `${to}/${remainder === "" ? "" : top2}`.replace(/\/$/, "");
21
+ return candidate.split("/")[0] || "_root";
22
+ }
23
+ }
24
+ const top = repoPath.split("/")[0];
25
+ return top || "_root";
26
+ }
27
+ function groupModules(files, cfg) {
28
+ const map = /* @__PURE__ */ new Map();
29
+ for (const f of files) {
30
+ if (f.repoPath.startsWith(".codewiki/")) continue;
31
+ const id = moduleForFile(f.repoPath, cfg);
32
+ let entry = map.get(id);
33
+ if (!entry) {
34
+ entry = {
35
+ id,
36
+ title: id,
37
+ files: [],
38
+ publicSurface: []
39
+ };
40
+ map.set(id, entry);
41
+ }
42
+ entry.files.push(f.repoPath);
43
+ for (const s of f.publicSymbols) {
44
+ entry.publicSurface.push(`${s.kind === "method" ? "method" : s.kind} ${s.name}`);
45
+ }
46
+ }
47
+ for (const id of [...map.keys()]) {
48
+ if (cfg.modules.ignore.includes(id)) {
49
+ map.delete(id);
50
+ }
51
+ }
52
+ return map;
53
+ }
54
+
55
+ function countTokens(input) {
56
+ if (!input) return 0;
57
+ return encode(input).length;
58
+ }
59
+ function truncateToTokens(text, budget, ellipsis = "\u2026") {
60
+ const current = countTokens(text);
61
+ if (current <= budget) return text;
62
+ let lo = 0;
63
+ let hi = text.length;
64
+ while (lo < hi) {
65
+ const mid = lo + hi + 1 >> 1;
66
+ if (countTokens(text.slice(0, mid)) <= budget - 1) {
67
+ lo = mid;
68
+ } else {
69
+ hi = mid - 1;
70
+ }
71
+ }
72
+ return text.slice(0, lo).trimEnd() + (lo > 0 ? " " + ellipsis : "");
73
+ }
74
+
75
+ export { countTokens as c, groupModules as g, moduleForFile as m, truncateToTokens as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codebase-wiki",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "Token-efficient code wiki for Claude Code. Generates a browsable .codewiki/ index so models read summaries on-demand.",
5
5
  "homepage": "https://github.com/harrycjs/code-wiki",
6
6
  "repository": {