@maxgfr/codeindex 2.7.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 (82) hide show
  1. package/README.md +115 -0
  2. package/docs/MIGRATION.md +100 -0
  3. package/package.json +89 -0
  4. package/scripts/cli.mjs +10 -0
  5. package/scripts/engine.d.mts +618 -0
  6. package/scripts/engine.mjs +10655 -0
  7. package/scripts/grammars/bash.wasm +0 -0
  8. package/scripts/grammars/c.wasm +0 -0
  9. package/scripts/grammars/c_sharp.wasm +0 -0
  10. package/scripts/grammars/cpp.wasm +0 -0
  11. package/scripts/grammars/go.wasm +0 -0
  12. package/scripts/grammars/java.wasm +0 -0
  13. package/scripts/grammars/javascript.wasm +0 -0
  14. package/scripts/grammars/lua.wasm +0 -0
  15. package/scripts/grammars/php.wasm +0 -0
  16. package/scripts/grammars/python.wasm +0 -0
  17. package/scripts/grammars/ruby.wasm +0 -0
  18. package/scripts/grammars/rust.wasm +0 -0
  19. package/scripts/grammars/scala.wasm +0 -0
  20. package/scripts/grammars/tsx.wasm +0 -0
  21. package/scripts/grammars/typescript.wasm +0 -0
  22. package/scripts/grammars/web-tree-sitter.wasm +0 -0
  23. package/src/ast/extract.ts +713 -0
  24. package/src/ast/loader.ts +104 -0
  25. package/src/bm25.ts +156 -0
  26. package/src/callers.ts +0 -0
  27. package/src/calls.ts +131 -0
  28. package/src/categorize.ts +80 -0
  29. package/src/centrality.ts +148 -0
  30. package/src/classify.ts +53 -0
  31. package/src/cli-entry.ts +16 -0
  32. package/src/community.ts +345 -0
  33. package/src/complexity.ts +69 -0
  34. package/src/coupling.ts +0 -0
  35. package/src/deadcode.ts +46 -0
  36. package/src/edit.ts +93 -0
  37. package/src/engine-cli.ts +278 -0
  38. package/src/engine.ts +148 -0
  39. package/src/extract/code.ts +376 -0
  40. package/src/extract/markdown.ts +135 -0
  41. package/src/git.ts +205 -0
  42. package/src/glob.ts +56 -0
  43. package/src/graph.ts +0 -0
  44. package/src/grep.ts +115 -0
  45. package/src/hash.ts +13 -0
  46. package/src/ignore.ts +134 -0
  47. package/src/lang/c.ts +26 -0
  48. package/src/lang/common.ts +68 -0
  49. package/src/lang/csharp.ts +22 -0
  50. package/src/lang/elixir.ts +18 -0
  51. package/src/lang/go.ts +22 -0
  52. package/src/lang/java.ts +19 -0
  53. package/src/lang/js-ts.ts +112 -0
  54. package/src/lang/kotlin.ts +20 -0
  55. package/src/lang/lua.ts +18 -0
  56. package/src/lang/php.ts +24 -0
  57. package/src/lang/python.ts +22 -0
  58. package/src/lang/registry.ts +54 -0
  59. package/src/lang/ruby.ts +17 -0
  60. package/src/lang/rust.ts +22 -0
  61. package/src/lang/scala.ts +19 -0
  62. package/src/lang/shell.ts +17 -0
  63. package/src/lang/swift.ts +23 -0
  64. package/src/mcp.ts +512 -0
  65. package/src/memory.ts +75 -0
  66. package/src/modules.ts +128 -0
  67. package/src/pipeline.ts +59 -0
  68. package/src/query.ts +118 -0
  69. package/src/render/graph-json.ts +16 -0
  70. package/src/render/symbols-json.ts +79 -0
  71. package/src/repomap.ts +52 -0
  72. package/src/resolve.ts +950 -0
  73. package/src/rules.ts +249 -0
  74. package/src/scan.ts +172 -0
  75. package/src/sort.ts +12 -0
  76. package/src/surprise.ts +58 -0
  77. package/src/tests-map.ts +105 -0
  78. package/src/types.ts +201 -0
  79. package/src/util.ts +169 -0
  80. package/src/viz.ts +44 -0
  81. package/src/walk.ts +216 -0
  82. package/src/workspaces.ts +748 -0
package/README.md ADDED
@@ -0,0 +1,115 @@
1
+ # codeindex
2
+
3
+ Self-contained, deterministic **repo-indexing engine**: file walking, language
4
+ detection, symbol/import extraction (tree-sitter AST with a regex fallback),
5
+ import resolution, a typed cross-file link-graph, and graph analytics — shipped
6
+ as a single zero-dependency `engine.mjs` that consumer tools **vendor** (copy
7
+ into their repo) instead of installing.
8
+
9
+ Extracted from [ultraindex](https://github.com/maxgfr/ultraindex) 5.1.0's core,
10
+ and consumed by the ultra* skill family (ultraindex, ultradoc, ultrasec,
11
+ ultraeval, reconstruct, construct, ultra11y).
12
+
13
+ ## What it does
14
+
15
+ - **Walk** a repo deterministically: ignore lists, binary/lockfile skips, size
16
+ and count caps (`capped` flag, never silent truncation), symlink-cycle guard.
17
+ - **Scan** every file into a `FileRecord`: classification, language, symbols,
18
+ imports, headings, hashes — with an incremental cache fastpath.
19
+ - **Extract symbols** via tree-sitter (10 languages, when the wasm sidecar is
20
+ present) or per-language regex rules (15 languages, always available).
21
+ - **Resolve imports** across languages: tsconfig paths, package `exports`,
22
+ go.mod, Cargo, Java packages, PSR-4, C# namespaces.
23
+ - **Build a typed link-graph**: `import` / `call` / `use` / `doc-link` /
24
+ `mention` edges at file and module level, plus Louvain communities, PageRank/
25
+ betweenness centrality, a tests→code map, and surprise-edge detection.
26
+ - **Render** byte-stable `graph.json` / `symbols.json` (two builds of an
27
+ unchanged repo are byte-identical).
28
+
29
+ ## Use as a library (the vendoring model)
30
+
31
+ Consumers commit `scripts/engine.mjs` + `scripts/engine.d.mts` (fetched at a
32
+ pinned release tag) into `src/vendor/` and import from it; their bundler inlines
33
+ the engine so they still ship a single file:
34
+
35
+ ```ts
36
+ import { buildIndexArtifacts, renderGraphJson } from "./vendor/engine.mjs";
37
+
38
+ const { scan, graph, symbols } = buildIndexArtifacts("/path/to/repo");
39
+ ```
40
+
41
+ The AST tier is optional: without a `grammars/` directory next to the bundle
42
+ the engine silently uses its regex tier. Only tools that want AST precision
43
+ (e.g. ultraindex) also vendor `scripts/grammars/` (~17 MiB of wasm).
44
+
45
+ ## Use from npm
46
+
47
+ For consumers who don't want to vendor the bundle, `@maxgfr/codeindex` also
48
+ resolves as a regular package:
49
+
50
+ ```sh
51
+ npm i @maxgfr/codeindex
52
+ ```
53
+
54
+ ```ts
55
+ import { scanRepo, ENGINE_VERSION } from "@maxgfr/codeindex";
56
+
57
+ const scan = scanRepo("/path/to/repo");
58
+ ```
59
+
60
+ The CLI ships in the same package (`npm i -g @maxgfr/codeindex`, see below).
61
+ Skills should still prefer vendoring: it keeps their own bundle single-file and
62
+ pinned to an exact commit without an npm dependency.
63
+
64
+ ## Use as a CLI
65
+
66
+ ```sh
67
+ brew install maxgfr/tap/codeindex # or: npm i -g @maxgfr/codeindex
68
+
69
+ codeindex index --repo . --out .codeindex # graph + symbols + incremental cache
70
+ codeindex graph --repo . > graph.json
71
+ codeindex callers --repo . # per-symbol caller index
72
+ codeindex grep 'pattern' --repo .
73
+ ```
74
+
75
+ ## Use as an MCP server
76
+
77
+ `codeindex mcp` (or `node scripts/cli.mjs mcp`) serves the engine over stdio —
78
+ tools: `scan_summary`, `graph`, `symbols`, `callers`, `workspaces`, `churn`,
79
+ `grep`. Register it in Claude Code with:
80
+
81
+ ```sh
82
+ claude mcp add codeindex -- codeindex mcp
83
+ ```
84
+
85
+ `engine.mjs` is a pure side-effect-free library (safe for consumers to inline
86
+ into their own CLIs); `cli.mjs` is the thin standalone CLI/MCP wrapper.
87
+
88
+ ## Versioning
89
+
90
+ - `ENGINE_VERSION` — the release tag, embedded greppably in the bundle.
91
+ - `SCHEMA_VERSION` — the `graph.json`/`symbols.json` shape (continues
92
+ ultraindex's lineage; currently 4). Consumers reject mismatched artifacts.
93
+ - `EXTRACTOR_VERSION` — the extraction output shape; incremental caches keyed
94
+ on it are discarded wholesale when it bumps.
95
+
96
+ `buildGraph`/`buildIndexArtifacts` accept `meta: { version, schemaVersion }` so
97
+ a consumer can stamp its own identity into artifacts it persists.
98
+
99
+ ## Development
100
+
101
+ ```sh
102
+ pnpm install
103
+ pnpm test # unit + fixtures + compat + no-wasm gates
104
+ pnpm typecheck
105
+ pnpm build # tsup → scripts/engine.mjs + scripts/engine.d.mts
106
+ pnpm check:build # proves the committed bundle is byte-reproducible
107
+ pnpm test:e2e # opt-in: pinned real-repo builds with ratchets
108
+ ```
109
+
110
+ The compat suite pins the exact bytes ultraindex 5.1.0 produced for the
111
+ `mini-repo` fixture — the proof that extraction was lossless.
112
+
113
+ ## License
114
+
115
+ MIT
@@ -0,0 +1,100 @@
1
+ # Migrating a skill onto the codeindex engine
2
+
3
+ The engine ships as two files, released together at every tag:
4
+
5
+ - `scripts/engine.mjs` — self-contained zero-dependency ESM bundle (library + CLI + MCP server)
6
+ - `scripts/engine.d.mts` — TypeScript declarations for the bundle
7
+
8
+ Consumers **vendor** them (commit a copy) — never an npm dependency — so every
9
+ skill stays standalone-installable.
10
+
11
+ ## Vendoring steps
12
+
13
+ 1. Copy `scripts/sync-engine.mjs` (reference implementation lives in the
14
+ ultraeval repo) into your repo and run:
15
+
16
+ ```sh
17
+ node scripts/sync-engine.mjs --ref v1.0.0
18
+ ```
19
+
20
+ It fetches `engine.mjs` + `engine.d.mts` from
21
+ `https://raw.githubusercontent.com/maxgfr/codeindex/<ref>/scripts/…` into
22
+ `src/vendor/`, greps the bundle's `ENGINE_VERSION` to assert it matches the
23
+ tag, and writes `src/vendor/engine.meta.json` (`{ tag, sha256, syncedAt }`).
24
+
25
+ 2. Import what you need from the vendored file:
26
+
27
+ ```ts
28
+ import { scanRepo, buildGraph, gitChurn } from "../vendor/engine.mjs";
29
+ ```
30
+
31
+ With `moduleResolution: "Bundler"` the sibling `.d.mts` types the import
32
+ with zero config. Your tsup/esbuild build inlines the engine into your own
33
+ single-file bundle — the user installs nothing extra.
34
+
35
+ 3. Exclude `src/vendor/` from your linter, and add
36
+ `node scripts/sync-engine.mjs --check` (offline sha256 check against
37
+ `engine.meta.json`) to your CI so local edits to the vendored file fail
38
+ loudly. Upgrades are a deliberate re-pin: run the sync with a newer tag and
39
+ commit the diff.
40
+
41
+ The AST tier is optional: without a `grammars/` directory next to the vendored
42
+ bundle the engine uses its regex tier (15 languages). Only vendor
43
+ `scripts/grammars/` (~17 MiB wasm) if you need AST-exact symbols (ultraindex
44
+ does; nobody else should).
45
+
46
+ ## Version constants
47
+
48
+ | Constant | Meaning | On mismatch |
49
+ |---|---|---|
50
+ | `ENGINE_VERSION` | the release tag, greppable in the bundle | sync script refuses the fetch |
51
+ | `SCHEMA_VERSION` | `graph.json` / `symbols.json` shape | reject the artifact, rebuild |
52
+ | `EXTRACTOR_VERSION` | extraction output shape | discard incremental caches wholesale |
53
+
54
+ `buildGraph(...)` / `buildIndexArtifacts(...)` accept
55
+ `meta: { version, schemaVersion }` so a consumer stamps its own identity into
56
+ artifacts it persists (ultraindex does this to keep its graph.json lineage).
57
+
58
+ ## Per-skill mapping (what to replace with what)
59
+
60
+ | Skill | Replace | With (engine export) |
61
+ |---|---|---|
62
+ | **ultraeval** | `walkFiles`, `SKIP_DIRS` | `scanRepo` (gitignore on by default) |
63
+ | | `importsOf` + `resolveImport` (JS/TS+py regex) | `FileRecord.refs` (kind `import`) + `buildResolveContext`/`resolveImport` |
64
+ | | `gitChurn`, `changedFiles` | `gitChurn`, `changedSince` |
65
+ | | keeps | cycle DFS, hotspot scoring, todos/maxIndent, ANALYSIS.md rendering |
66
+ | **construct** | walker clone + language histogram + test count | `scanRepo` (`.languages`) + `isTestPath` |
67
+ | **ultraindex** | the whole core (walk/scan/extract/resolve/modules/graph/calls/analytics/renderers) | vendored engine + shim `src/engine.ts` re-exporting it; pass `meta: { version: VERSION, schemaVersion: SCHEMA_VERSION }` to keep graph.json byte-lineage |
68
+ | | keeps | store/manifest, encyclopedia, merge/entries, find/ask, check/verify, embeddings, orchestrate |
69
+ | **ultradoc** | walker, `EXT_LANG` map, symbol `RULES` + `applyExportLists` | `scanRepo`, `extToLang`/`languageOf`, `extractSymbols`/`buildSymbolIndex` |
70
+ | | `PKG_MANIFESTS` workspace probing | `detectWorkspaces` |
71
+ | | `rgSearch` + JS fallback | `grepRepo` |
72
+ | | keeps | issues/PRs/SO/web retrieval, citations, DOC.md |
73
+ | **ultra11y** | walker + glob scoping | `walk`/`scanRepo` with `include`/`exclude` |
74
+ | | tsconfig path-alias resolution | `buildResolveContext` + `resolveImport` |
75
+ | | keeps | its JSX component graph and every WCAG check |
76
+ | **reconstruct** | walker + gitignore parser + `categorize` | `scanRepo`, `categorize` |
77
+ | | `EXT_LANGUAGE` | `extToLang` |
78
+ | | workspace detection + dep graph + cycle + topo | `detectWorkspaces` (packages/dependsOn/cycle/topoOrder) |
79
+ | | `resolveModule` | `resolveImport` |
80
+ | | keeps | framework adapters (routes), data-model inference, PRD rendering |
81
+ | **ultrasec** | walker + gitignore + scope + symlink guard | `scanRepo` (`scope`, `gitignore` — its own semantics, ported here) |
82
+ | | per-language defs/imports/calls extraction | `extractCode` (`symbols`/`refs`/`calls`) |
83
+ | | `resolveImport` | `resolveImport` |
84
+ | | `buildGraph` (import+call edges, symbolDefs, callersBySymbol, enclosingSymbol) | `buildGraph` + `resolveCallEdges` + `buildCallerIndex` + `enclosingSymbol` |
85
+ | | keeps | taint source→sink enumeration, external scanners, EPSS/KEV/CVSS, SARIF |
86
+
87
+ ## Golden-diff adjudication (every migration)
88
+
89
+ Capture the skill's load-bearing artifact **before** touching code (a committed
90
+ snapshot test), migrate, then adjudicate every diff:
91
+
92
+ - **Accept + document**: file-set changes from better ignore rules (gitignore
93
+ honored, lockfile/binary/1 MiB skips) and strictly-more-resolved imports
94
+ (tsconfig paths, package `exports`, go/cargo) — list them in the commit body.
95
+ - **Must be identical**: output schemas, rendering, scoring formulas,
96
+ attribution logic on identical inputs.
97
+ - **Investigate before accepting**: anything else (a cycle, hotspot, finding or
98
+ score changing for an unlisted reason). If the engine is more correct, update
99
+ the golden citing the cause; otherwise **fix codeindex and re-release** —
100
+ never patch around it in the consumer.
package/package.json ADDED
@@ -0,0 +1,89 @@
1
+ {
2
+ "name": "@maxgfr/codeindex",
3
+ "version": "2.7.0",
4
+ "description": "Self-contained, deterministic repo-indexing engine: walk + language detection + symbol/import extraction (tree-sitter AST with regex fallback) + import resolution + typed cross-file link-graph + analytics. Ships as a single zero-dependency engine.mjs that consumer tools vendor.",
5
+ "type": "module",
6
+ "packageManager": "pnpm@10.33.0",
7
+ "main": "./scripts/engine.mjs",
8
+ "types": "./scripts/engine.d.mts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./scripts/engine.d.mts",
12
+ "import": "./scripts/engine.mjs",
13
+ "default": "./scripts/engine.mjs"
14
+ },
15
+ "./package.json": "./package.json"
16
+ },
17
+ "bin": {
18
+ "codeindex": "scripts/cli.mjs"
19
+ },
20
+ "files": [
21
+ "scripts/engine.mjs",
22
+ "scripts/engine.d.mts",
23
+ "scripts/cli.mjs",
24
+ "scripts/grammars",
25
+ "src",
26
+ "docs/MIGRATION.md"
27
+ ],
28
+ "engines": {
29
+ "node": ">=18"
30
+ },
31
+ "scripts": {
32
+ "build": "tsup && node scripts/postbuild.mjs",
33
+ "grammars": "node scripts/fetch-grammars.mjs",
34
+ "test": "vitest run",
35
+ "test:watch": "vitest",
36
+ "test:e2e": "CODEINDEX_E2E=1 vitest run tests/e2e-real-repos.test.ts",
37
+ "typecheck": "tsc --noEmit",
38
+ "check:build": "tsup && node scripts/postbuild.mjs && git diff --exit-code -- scripts/engine.mjs scripts/engine.d.mts scripts/cli.mjs scripts/grammars",
39
+ "demo": "node scripts/cli.mjs graph --repo tests/fixtures/mini-repo",
40
+ "release": "semantic-release"
41
+ },
42
+ "keywords": [
43
+ "code-index",
44
+ "static-analysis",
45
+ "link-graph",
46
+ "symbol-extraction",
47
+ "tree-sitter",
48
+ "repo-indexing"
49
+ ],
50
+ "license": "MIT",
51
+ "author": "maxgfr",
52
+ "repository": {
53
+ "type": "git",
54
+ "url": "https://github.com/maxgfr/codeindex"
55
+ },
56
+ "devDependencies": {
57
+ "@semantic-release/changelog": "^6.0.3",
58
+ "@semantic-release/exec": "^6.0.3",
59
+ "@semantic-release/git": "^10.0.1",
60
+ "@tree-sitter-grammars/tree-sitter-lua": "0.4.1",
61
+ "@types/node": "^20.14.0",
62
+ "semantic-release": "^24.2.0",
63
+ "tree-sitter-bash": "0.25.1",
64
+ "tree-sitter-c": "^0.24.1",
65
+ "tree-sitter-c-sharp": "^0.23.5",
66
+ "tree-sitter-cpp": "^0.23.4",
67
+ "tree-sitter-go": "^0.25.0",
68
+ "tree-sitter-java": "^0.23.5",
69
+ "tree-sitter-javascript": "^0.25.0",
70
+ "tree-sitter-php": "^0.24.2",
71
+ "tree-sitter-python": "^0.25.0",
72
+ "tree-sitter-ruby": "^0.23.1",
73
+ "tree-sitter-rust": "^0.24.0",
74
+ "tree-sitter-scala": "0.24.0",
75
+ "tree-sitter-typescript": "^0.23.2",
76
+ "tsup": "^8.3.0",
77
+ "typescript": "^5.5.0",
78
+ "vitest": "^4.1.0",
79
+ "web-tree-sitter": "^0.26.10"
80
+ },
81
+ "pnpm": {
82
+ "onlyBuiltDependencies": [
83
+ "esbuild"
84
+ ]
85
+ },
86
+ "publishConfig": {
87
+ "access": "public"
88
+ }
89
+ }
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/cli-entry.ts
4
+ import { runCli } from "./engine.mjs";
5
+ try {
6
+ await runCli(process.argv.slice(2));
7
+ } catch (e) {
8
+ console.error(`codeindex: ${e instanceof Error ? e.message : e}`);
9
+ process.exit(2);
10
+ }