trail-code 0.0.0-stage → 0.28.0-semantic.3
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/LICENSE +21 -0
- package/README.md +567 -2
- package/dist/ai/crux.d.ts +88 -0
- package/dist/ai/crux.d.ts.map +1 -0
- package/dist/ai/crux.js +219 -0
- package/dist/ai/crux.js.map +1 -0
- package/dist/ai/failure.d.ts +60 -0
- package/dist/ai/failure.d.ts.map +1 -0
- package/dist/ai/failure.js +86 -0
- package/dist/ai/failure.js.map +1 -0
- package/dist/ai/llm/anthropic.d.ts +37 -0
- package/dist/ai/llm/anthropic.d.ts.map +1 -0
- package/dist/ai/llm/anthropic.js +144 -0
- package/dist/ai/llm/anthropic.js.map +1 -0
- package/dist/ai/llm/factory.d.ts +28 -0
- package/dist/ai/llm/factory.d.ts.map +1 -0
- package/dist/ai/llm/factory.js +36 -0
- package/dist/ai/llm/factory.js.map +1 -0
- package/dist/ai/llm/litellm.d.ts +34 -0
- package/dist/ai/llm/litellm.d.ts.map +1 -0
- package/dist/ai/llm/litellm.js +45 -0
- package/dist/ai/llm/litellm.js.map +1 -0
- package/dist/ai/llm/openai.d.ts +145 -0
- package/dist/ai/llm/openai.d.ts.map +1 -0
- package/dist/ai/llm/openai.js +629 -0
- package/dist/ai/llm/openai.js.map +1 -0
- package/dist/ai/llm/orcarouter.d.ts +34 -0
- package/dist/ai/llm/orcarouter.d.ts.map +1 -0
- package/dist/ai/llm/orcarouter.js +45 -0
- package/dist/ai/llm/orcarouter.js.map +1 -0
- package/dist/ai/llm/recover-tool.d.ts +21 -0
- package/dist/ai/llm/recover-tool.d.ts.map +1 -0
- package/dist/ai/llm/recover-tool.js +109 -0
- package/dist/ai/llm/recover-tool.js.map +1 -0
- package/dist/ai/llm/types.d.ts +122 -0
- package/dist/ai/llm/types.d.ts.map +1 -0
- package/dist/ai/llm/types.js +33 -0
- package/dist/ai/llm/types.js.map +1 -0
- package/dist/ai/providers.d.ts +59 -0
- package/dist/ai/providers.d.ts.map +1 -0
- package/dist/ai/providers.js +54 -0
- package/dist/ai/providers.js.map +1 -0
- package/dist/ai/summarize.d.ts +25 -0
- package/dist/ai/summarize.d.ts.map +1 -0
- package/dist/ai/summarize.js +34 -0
- package/dist/ai/summarize.js.map +1 -0
- package/dist/ai/synthesize.d.ts +40 -0
- package/dist/ai/synthesize.d.ts.map +1 -0
- package/dist/ai/synthesize.js +230 -0
- package/dist/ai/synthesize.js.map +1 -0
- package/dist/ask/ask.d.ts +199 -0
- package/dist/ask/ask.d.ts.map +1 -0
- package/dist/ask/ask.js +1291 -0
- package/dist/ask/ask.js.map +1 -0
- package/dist/ask/file-rank.d.ts +72 -0
- package/dist/ask/file-rank.d.ts.map +1 -0
- package/dist/ask/file-rank.js +160 -0
- package/dist/ask/file-rank.js.map +1 -0
- package/dist/ask/file-selection.d.ts +22 -0
- package/dist/ask/file-selection.d.ts.map +1 -0
- package/dist/ask/file-selection.js +66 -0
- package/dist/ask/file-selection.js.map +1 -0
- package/dist/ask/fuse.d.ts +195 -0
- package/dist/ask/fuse.d.ts.map +1 -0
- package/dist/ask/fuse.js +344 -0
- package/dist/ask/fuse.js.map +1 -0
- package/dist/ask/graphrank.d.ts +61 -0
- package/dist/ask/graphrank.d.ts.map +1 -0
- package/dist/ask/graphrank.js +130 -0
- package/dist/ask/graphrank.js.map +1 -0
- package/dist/ask/index-file.d.ts +44 -0
- package/dist/ask/index-file.d.ts.map +1 -0
- package/dist/ask/index-file.js +128 -0
- package/dist/ask/index-file.js.map +1 -0
- package/dist/ask/semantic.d.ts +42 -0
- package/dist/ask/semantic.d.ts.map +1 -0
- package/dist/ask/semantic.js +293 -0
- package/dist/ask/semantic.js.map +1 -0
- package/dist/bin/graft.d.ts +3 -0
- package/dist/bin/graft.d.ts.map +1 -0
- package/dist/bin/graft.js +14 -0
- package/dist/bin/graft.js.map +1 -0
- package/dist/bin/trail.d.ts +3 -0
- package/dist/bin/trail.d.ts.map +1 -0
- package/dist/bin/trail.js +13 -0
- package/dist/bin/trail.js.map +1 -0
- package/dist/blast/blast-cli.d.ts +35 -0
- package/dist/blast/blast-cli.d.ts.map +1 -0
- package/dist/blast/blast-cli.js +155 -0
- package/dist/blast/blast-cli.js.map +1 -0
- package/dist/blast/blast.d.ts +128 -0
- package/dist/blast/blast.d.ts.map +1 -0
- package/dist/blast/blast.js +383 -0
- package/dist/blast/blast.js.map +1 -0
- package/dist/blast/diff.d.ts +53 -0
- package/dist/blast/diff.d.ts.map +1 -0
- package/dist/blast/diff.js +193 -0
- package/dist/blast/diff.js.map +1 -0
- package/dist/blast/evidence.d.ts +51 -0
- package/dist/blast/evidence.d.ts.map +1 -0
- package/dist/blast/evidence.js +162 -0
- package/dist/blast/evidence.js.map +1 -0
- package/dist/blast/modules.d.ts +33 -0
- package/dist/blast/modules.d.ts.map +1 -0
- package/dist/blast/modules.js +83 -0
- package/dist/blast/modules.js.map +1 -0
- package/dist/blast/name.d.ts +74 -0
- package/dist/blast/name.d.ts.map +1 -0
- package/dist/blast/name.js +269 -0
- package/dist/blast/name.js.map +1 -0
- package/dist/blast/owners.d.ts +85 -0
- package/dist/blast/owners.d.ts.map +1 -0
- package/dist/blast/owners.js +272 -0
- package/dist/blast/owners.js.map +1 -0
- package/dist/blast/render.d.ts +46 -0
- package/dist/blast/render.d.ts.map +1 -0
- package/dist/blast/render.js +422 -0
- package/dist/blast/render.js.map +1 -0
- package/dist/blast/viz.d.ts +37 -0
- package/dist/blast/viz.d.ts.map +1 -0
- package/dist/blast/viz.js +180 -0
- package/dist/blast/viz.js.map +1 -0
- package/dist/brand.d.ts +111 -0
- package/dist/brand.d.ts.map +1 -0
- package/dist/brand.js +282 -0
- package/dist/brand.js.map +1 -0
- package/dist/claude/build-progress.d.ts +30 -0
- package/dist/claude/build-progress.d.ts.map +1 -0
- package/dist/claude/build-progress.js +81 -0
- package/dist/claude/build-progress.js.map +1 -0
- package/dist/claude/hermes-skill-template.d.ts +16 -0
- package/dist/claude/hermes-skill-template.d.ts.map +1 -0
- package/dist/claude/hermes-skill-template.js +154 -0
- package/dist/claude/hermes-skill-template.js.map +1 -0
- package/dist/claude/init.d.ts +65 -0
- package/dist/claude/init.d.ts.map +1 -0
- package/dist/claude/init.js +258 -0
- package/dist/claude/init.js.map +1 -0
- package/dist/claude/paths.d.ts +9 -0
- package/dist/claude/paths.d.ts.map +1 -0
- package/dist/claude/paths.js +22 -0
- package/dist/claude/paths.js.map +1 -0
- package/dist/claude/session-metrics.d.ts +73 -0
- package/dist/claude/session-metrics.d.ts.map +1 -0
- package/dist/claude/session-metrics.js +209 -0
- package/dist/claude/session-metrics.js.map +1 -0
- package/dist/claude/settings-merge.d.ts +76 -0
- package/dist/claude/settings-merge.d.ts.map +1 -0
- package/dist/claude/settings-merge.js +283 -0
- package/dist/claude/settings-merge.js.map +1 -0
- package/dist/claude/skill-template.d.ts +13 -0
- package/dist/claude/skill-template.d.ts.map +1 -0
- package/dist/claude/skill-template.js +290 -0
- package/dist/claude/skill-template.js.map +1 -0
- package/dist/claude/state.d.ts +85 -0
- package/dist/claude/state.d.ts.map +1 -0
- package/dist/claude/state.js +88 -0
- package/dist/claude/state.js.map +1 -0
- package/dist/claude/stats.d.ts +5 -0
- package/dist/claude/stats.d.ts.map +1 -0
- package/dist/claude/stats.js +24 -0
- package/dist/claude/stats.js.map +1 -0
- package/dist/cli-epilogue.d.ts +12 -0
- package/dist/cli-epilogue.d.ts.map +1 -0
- package/dist/cli-epilogue.js +72 -0
- package/dist/cli-epilogue.js.map +1 -0
- package/dist/cli-meta.d.ts +82 -0
- package/dist/cli-meta.d.ts.map +1 -0
- package/dist/cli-meta.js +238 -0
- package/dist/cli-meta.js.map +1 -0
- package/dist/cli-picker.d.ts +139 -0
- package/dist/cli-picker.d.ts.map +1 -0
- package/dist/cli-picker.js +439 -0
- package/dist/cli-picker.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +1638 -0
- package/dist/cli.js.map +1 -0
- package/dist/context/batches.d.ts +29 -0
- package/dist/context/batches.d.ts.map +1 -0
- package/dist/context/batches.js +130 -0
- package/dist/context/batches.js.map +1 -0
- package/dist/context/build.d.ts +57 -0
- package/dist/context/build.d.ts.map +1 -0
- package/dist/context/build.js +396 -0
- package/dist/context/build.js.map +1 -0
- package/dist/context/check.d.ts +42 -0
- package/dist/context/check.d.ts.map +1 -0
- package/dist/context/check.js +162 -0
- package/dist/context/check.js.map +1 -0
- package/dist/context/map-dir.d.ts +13 -0
- package/dist/context/map-dir.d.ts.map +1 -0
- package/dist/context/map-dir.js +81 -0
- package/dist/context/map-dir.js.map +1 -0
- package/dist/context/node-file.d.ts +109 -0
- package/dist/context/node-file.d.ts.map +1 -0
- package/dist/context/node-file.js +390 -0
- package/dist/context/node-file.js.map +1 -0
- package/dist/context/price.d.ts +49 -0
- package/dist/context/price.d.ts.map +1 -0
- package/dist/context/price.js +83 -0
- package/dist/context/price.js.map +1 -0
- package/dist/context/savings.d.ts +67 -0
- package/dist/context/savings.d.ts.map +1 -0
- package/dist/context/savings.js +125 -0
- package/dist/context/savings.js.map +1 -0
- package/dist/engine.d.ts +85 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +122 -0
- package/dist/engine.js.map +1 -0
- package/dist/graph/bindings.d.ts +64 -0
- package/dist/graph/bindings.d.ts.map +1 -0
- package/dist/graph/bindings.js +713 -0
- package/dist/graph/bindings.js.map +1 -0
- package/dist/graph/build-run.d.ts +25 -0
- package/dist/graph/build-run.d.ts.map +1 -0
- package/dist/graph/build-run.js +121 -0
- package/dist/graph/build-run.js.map +1 -0
- package/dist/graph/build.d.ts +88 -0
- package/dist/graph/build.d.ts.map +1 -0
- package/dist/graph/build.js +386 -0
- package/dist/graph/build.js.map +1 -0
- package/dist/graph/cards.d.ts +46 -0
- package/dist/graph/cards.d.ts.map +1 -0
- package/dist/graph/cards.js +280 -0
- package/dist/graph/cards.js.map +1 -0
- package/dist/graph/check.d.ts +25 -0
- package/dist/graph/check.d.ts.map +1 -0
- package/dist/graph/check.js +192 -0
- package/dist/graph/check.js.map +1 -0
- package/dist/graph/container.d.ts +63 -0
- package/dist/graph/container.d.ts.map +1 -0
- package/dist/graph/container.js +191 -0
- package/dist/graph/container.js.map +1 -0
- package/dist/graph/depth-parser.d.ts +61 -0
- package/dist/graph/depth-parser.d.ts.map +1 -0
- package/dist/graph/depth-parser.js +153 -0
- package/dist/graph/depth-parser.js.map +1 -0
- package/dist/graph/enrich.d.ts +62 -0
- package/dist/graph/enrich.d.ts.map +1 -0
- package/dist/graph/enrich.js +258 -0
- package/dist/graph/enrich.js.map +1 -0
- package/dist/graph/extract-cache.d.ts +101 -0
- package/dist/graph/extract-cache.d.ts.map +1 -0
- package/dist/graph/extract-cache.js +199 -0
- package/dist/graph/extract-cache.js.map +1 -0
- package/dist/graph/extract.d.ts +85 -0
- package/dist/graph/extract.d.ts.map +1 -0
- package/dist/graph/extract.js +2377 -0
- package/dist/graph/extract.js.map +1 -0
- package/dist/graph/fingerprint.d.ts +76 -0
- package/dist/graph/fingerprint.d.ts.map +1 -0
- package/dist/graph/fingerprint.js +160 -0
- package/dist/graph/fingerprint.js.map +1 -0
- package/dist/graph/generic.d.ts +74 -0
- package/dist/graph/generic.d.ts.map +1 -0
- package/dist/graph/generic.js +773 -0
- package/dist/graph/generic.js.map +1 -0
- package/dist/graph/invariants.d.ts +33 -0
- package/dist/graph/invariants.d.ts.map +1 -0
- package/dist/graph/invariants.js +52 -0
- package/dist/graph/invariants.js.map +1 -0
- package/dist/graph/load.d.ts +29 -0
- package/dist/graph/load.d.ts.map +1 -0
- package/dist/graph/load.js +97 -0
- package/dist/graph/load.js.map +1 -0
- package/dist/graph/lsp/client.d.ts +61 -0
- package/dist/graph/lsp/client.d.ts.map +1 -0
- package/dist/graph/lsp/client.js +217 -0
- package/dist/graph/lsp/client.js.map +1 -0
- package/dist/graph/lsp/enrich.d.ts +11 -0
- package/dist/graph/lsp/enrich.d.ts.map +1 -0
- package/dist/graph/lsp/enrich.js +163 -0
- package/dist/graph/lsp/enrich.js.map +1 -0
- package/dist/graph/lsp/registry.d.ts +22 -0
- package/dist/graph/lsp/registry.d.ts.map +1 -0
- package/dist/graph/lsp/registry.js +71 -0
- package/dist/graph/lsp/registry.js.map +1 -0
- package/dist/graph/map.d.ts +107 -0
- package/dist/graph/map.d.ts.map +1 -0
- package/dist/graph/map.js +239 -0
- package/dist/graph/map.js.map +1 -0
- package/dist/graph/markdown.d.ts +22 -0
- package/dist/graph/markdown.d.ts.map +1 -0
- package/dist/graph/markdown.js +143 -0
- package/dist/graph/markdown.js.map +1 -0
- package/dist/graph/native.d.ts +46 -0
- package/dist/graph/native.d.ts.map +1 -0
- package/dist/graph/native.js +169 -0
- package/dist/graph/native.js.map +1 -0
- package/dist/graph/queries/c.scm +13 -0
- package/dist/graph/queries/c_sharp.scm +19 -0
- package/dist/graph/queries/clojure.scm +58 -0
- package/dist/graph/queries/cpp.scm +23 -0
- package/dist/graph/queries/dart.scm +42 -0
- package/dist/graph/queries/elixir.scm +54 -0
- package/dist/graph/queries/gleam.scm +51 -0
- package/dist/graph/queries/java.scm +20 -0
- package/dist/graph/queries/kotlin.scm +43 -0
- package/dist/graph/queries/lua.scm +36 -0
- package/dist/graph/queries/nix.scm +32 -0
- package/dist/graph/queries/php.scm +40 -0
- package/dist/graph/queries/ruby.scm +65 -0
- package/dist/graph/queries/rust.scm +41 -0
- package/dist/graph/queries/scala.scm +66 -0
- package/dist/graph/queries/solidity.scm +43 -0
- package/dist/graph/queries/swift.scm +51 -0
- package/dist/graph/refresh.d.ts +106 -0
- package/dist/graph/refresh.d.ts.map +1 -0
- package/dist/graph/refresh.js +430 -0
- package/dist/graph/refresh.js.map +1 -0
- package/dist/graph/relations.d.ts +14 -0
- package/dist/graph/relations.d.ts.map +1 -0
- package/dist/graph/relations.js +8 -0
- package/dist/graph/relations.js.map +1 -0
- package/dist/graph/resolve.d.ts +17 -0
- package/dist/graph/resolve.d.ts.map +1 -0
- package/dist/graph/resolve.js +716 -0
- package/dist/graph/resolve.js.map +1 -0
- package/dist/graph/root.d.ts +11 -0
- package/dist/graph/root.d.ts.map +1 -0
- package/dist/graph/root.js +40 -0
- package/dist/graph/root.js.map +1 -0
- package/dist/graph/scopes.d.ts +40 -0
- package/dist/graph/scopes.d.ts.map +1 -0
- package/dist/graph/scopes.js +383 -0
- package/dist/graph/scopes.js.map +1 -0
- package/dist/graph/seed.d.ts +38 -0
- package/dist/graph/seed.d.ts.map +1 -0
- package/dist/graph/seed.js +229 -0
- package/dist/graph/seed.js.map +1 -0
- package/dist/graph/source-files.d.ts +46 -0
- package/dist/graph/source-files.d.ts.map +1 -0
- package/dist/graph/source-files.js +118 -0
- package/dist/graph/source-files.js.map +1 -0
- package/dist/graph/traverse-cli.d.ts +55 -0
- package/dist/graph/traverse-cli.d.ts.map +1 -0
- package/dist/graph/traverse-cli.js +189 -0
- package/dist/graph/traverse-cli.js.map +1 -0
- package/dist/graph/traverse.d.ts +112 -0
- package/dist/graph/traverse.d.ts.map +1 -0
- package/dist/graph/traverse.js +192 -0
- package/dist/graph/traverse.js.map +1 -0
- package/dist/graph/types.d.ts +78 -0
- package/dist/graph/types.d.ts.map +1 -0
- package/dist/graph/types.js +14 -0
- package/dist/graph/types.js.map +1 -0
- package/dist/graph/wasm-runtime.d.ts +19 -0
- package/dist/graph/wasm-runtime.d.ts.map +1 -0
- package/dist/graph/wasm-runtime.js +38 -0
- package/dist/graph/wasm-runtime.js.map +1 -0
- package/dist/graph/workspace-cli.d.ts +56 -0
- package/dist/graph/workspace-cli.d.ts.map +1 -0
- package/dist/graph/workspace-cli.js +111 -0
- package/dist/graph/workspace-cli.js.map +1 -0
- package/dist/graph/workspace.d.ts +172 -0
- package/dist/graph/workspace.d.ts.map +1 -0
- package/dist/graph/workspace.js +714 -0
- package/dist/graph/workspace.js.map +1 -0
- package/dist/graph/write.d.ts +13 -0
- package/dist/graph/write.d.ts.map +1 -0
- package/dist/graph/write.js +86 -0
- package/dist/graph/write.js.map +1 -0
- package/dist/hosts/antigravity.d.ts +14 -0
- package/dist/hosts/antigravity.d.ts.map +1 -0
- package/dist/hosts/antigravity.js +59 -0
- package/dist/hosts/antigravity.js.map +1 -0
- package/dist/hosts/auto.d.ts +37 -0
- package/dist/hosts/auto.d.ts.map +1 -0
- package/dist/hosts/auto.js +141 -0
- package/dist/hosts/auto.js.map +1 -0
- package/dist/hosts/claude-global.d.ts +72 -0
- package/dist/hosts/claude-global.d.ts.map +1 -0
- package/dist/hosts/claude-global.js +230 -0
- package/dist/hosts/claude-global.js.map +1 -0
- package/dist/hosts/config-write.d.ts +36 -0
- package/dist/hosts/config-write.d.ts.map +1 -0
- package/dist/hosts/config-write.js +64 -0
- package/dist/hosts/config-write.js.map +1 -0
- package/dist/hosts/init.d.ts +28 -0
- package/dist/hosts/init.d.ts.map +1 -0
- package/dist/hosts/init.js +89 -0
- package/dist/hosts/init.js.map +1 -0
- package/dist/hosts/instructions.d.ts +14 -0
- package/dist/hosts/instructions.d.ts.map +1 -0
- package/dist/hosts/instructions.js +95 -0
- package/dist/hosts/instructions.js.map +1 -0
- package/dist/hosts/mcp-config.d.ts +78 -0
- package/dist/hosts/mcp-config.d.ts.map +1 -0
- package/dist/hosts/mcp-config.js +251 -0
- package/dist/hosts/mcp-config.js.map +1 -0
- package/dist/hosts/plan.d.ts +32 -0
- package/dist/hosts/plan.d.ts.map +1 -0
- package/dist/hosts/plan.js +73 -0
- package/dist/hosts/plan.js.map +1 -0
- package/dist/hosts/registry.d.ts +41 -0
- package/dist/hosts/registry.d.ts.map +1 -0
- package/dist/hosts/registry.js +164 -0
- package/dist/hosts/registry.js.map +1 -0
- package/dist/hosts/retract.d.ts +47 -0
- package/dist/hosts/retract.d.ts.map +1 -0
- package/dist/hosts/retract.js +520 -0
- package/dist/hosts/retract.js.map +1 -0
- package/dist/hosts/sections.d.ts +47 -0
- package/dist/hosts/sections.d.ts.map +1 -0
- package/dist/hosts/sections.js +127 -0
- package/dist/hosts/sections.js.map +1 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +32 -0
- package/dist/index.js.map +1 -0
- package/dist/ingest/fs.d.ts +79 -0
- package/dist/ingest/fs.d.ts.map +1 -0
- package/dist/ingest/fs.js +306 -0
- package/dist/ingest/fs.js.map +1 -0
- package/dist/init-guard.d.ts +16 -0
- package/dist/init-guard.d.ts.map +1 -0
- package/dist/init-guard.js +27 -0
- package/dist/init-guard.js.map +1 -0
- package/dist/mcp/instructions.d.ts +5 -0
- package/dist/mcp/instructions.d.ts.map +1 -0
- package/dist/mcp/instructions.js +64 -0
- package/dist/mcp/instructions.js.map +1 -0
- package/dist/mcp/kept-listing.d.ts +27 -0
- package/dist/mcp/kept-listing.d.ts.map +1 -0
- package/dist/mcp/kept-listing.js +63 -0
- package/dist/mcp/kept-listing.js.map +1 -0
- package/dist/mcp/server.d.ts +4 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +147 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tool-names.d.ts +27 -0
- package/dist/mcp/tool-names.d.ts.map +1 -0
- package/dist/mcp/tool-names.js +47 -0
- package/dist/mcp/tool-names.js.map +1 -0
- package/dist/mcp/tools.d.ts +22 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +440 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/node-version.d.ts +15 -0
- package/dist/node-version.d.ts.map +1 -0
- package/dist/node-version.js +23 -0
- package/dist/node-version.js.map +1 -0
- package/dist/search/grep-cli.d.ts +35 -0
- package/dist/search/grep-cli.d.ts.map +1 -0
- package/dist/search/grep-cli.js +115 -0
- package/dist/search/grep-cli.js.map +1 -0
- package/dist/search/grep.d.ts +60 -0
- package/dist/search/grep.d.ts.map +1 -0
- package/dist/search/grep.js +143 -0
- package/dist/search/grep.js.map +1 -0
- package/dist/search/ignored-code.d.ts +9 -0
- package/dist/search/ignored-code.d.ts.map +1 -0
- package/dist/search/ignored-code.js +73 -0
- package/dist/search/ignored-code.js.map +1 -0
- package/dist/search/user-regexp.d.ts +26 -0
- package/dist/search/user-regexp.d.ts.map +1 -0
- package/dist/search/user-regexp.js +150 -0
- package/dist/search/user-regexp.js.map +1 -0
- package/dist/telemetry/contract.d.ts +117 -0
- package/dist/telemetry/contract.d.ts.map +1 -0
- package/dist/telemetry/contract.js +341 -0
- package/dist/telemetry/contract.js.map +1 -0
- package/dist/telemetry/flush.d.ts +21 -0
- package/dist/telemetry/flush.d.ts.map +1 -0
- package/dist/telemetry/flush.js +85 -0
- package/dist/telemetry/flush.js.map +1 -0
- package/dist/telemetry/gate.d.ts +30 -0
- package/dist/telemetry/gate.d.ts.map +1 -0
- package/dist/telemetry/gate.js +81 -0
- package/dist/telemetry/gate.js.map +1 -0
- package/dist/telemetry/identity.d.ts +40 -0
- package/dist/telemetry/identity.d.ts.map +1 -0
- package/dist/telemetry/identity.js +80 -0
- package/dist/telemetry/identity.js.map +1 -0
- package/dist/telemetry/index.d.ts +18 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +16 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/telemetry/key.d.ts +21 -0
- package/dist/telemetry/key.d.ts.map +1 -0
- package/dist/telemetry/key.js +49 -0
- package/dist/telemetry/key.js.map +1 -0
- package/dist/telemetry/notice.d.ts +19 -0
- package/dist/telemetry/notice.d.ts.map +1 -0
- package/dist/telemetry/notice.js +93 -0
- package/dist/telemetry/notice.js.map +1 -0
- package/dist/telemetry/queue.d.ts +35 -0
- package/dist/telemetry/queue.d.ts.map +1 -0
- package/dist/telemetry/queue.js +162 -0
- package/dist/telemetry/queue.js.map +1 -0
- package/dist/telemetry/send.d.ts +19 -0
- package/dist/telemetry/send.d.ts.map +1 -0
- package/dist/telemetry/send.js +84 -0
- package/dist/telemetry/send.js.map +1 -0
- package/dist/telemetry/sessions.d.ts +25 -0
- package/dist/telemetry/sessions.d.ts.map +1 -0
- package/dist/telemetry/sessions.js +104 -0
- package/dist/telemetry/sessions.js.map +1 -0
- package/dist/telemetry/track.d.ts +62 -0
- package/dist/telemetry/track.d.ts.map +1 -0
- package/dist/telemetry/track.js +143 -0
- package/dist/telemetry/track.js.map +1 -0
- package/dist/upkeep-run.d.ts +22 -0
- package/dist/upkeep-run.d.ts.map +1 -0
- package/dist/upkeep-run.js +85 -0
- package/dist/upkeep-run.js.map +1 -0
- package/dist/upkeep.d.ts +127 -0
- package/dist/upkeep.d.ts.map +1 -0
- package/dist/upkeep.js +252 -0
- package/dist/upkeep.js.map +1 -0
- package/dist/util/actions-folder.d.ts +2 -0
- package/dist/util/actions-folder.d.ts.map +1 -0
- package/dist/util/actions-folder.js +9 -0
- package/dist/util/actions-folder.js.map +1 -0
- package/dist/util/browser.d.ts +3 -0
- package/dist/util/browser.d.ts.map +1 -0
- package/dist/util/browser.js +14 -0
- package/dist/util/browser.js.map +1 -0
- package/dist/util/child-process.d.ts +15 -0
- package/dist/util/child-process.d.ts.map +1 -0
- package/dist/util/child-process.js +15 -0
- package/dist/util/child-process.js.map +1 -0
- package/dist/util/front-matter.d.ts +46 -0
- package/dist/util/front-matter.d.ts.map +1 -0
- package/dist/util/front-matter.js +113 -0
- package/dist/util/front-matter.js.map +1 -0
- package/dist/util/id.d.ts +7 -0
- package/dist/util/id.d.ts.map +1 -0
- package/dist/util/id.js +14 -0
- package/dist/util/id.js.map +1 -0
- package/dist/util/paths.d.ts +29 -0
- package/dist/util/paths.d.ts.map +1 -0
- package/dist/util/paths.js +71 -0
- package/dist/util/paths.js.map +1 -0
- package/dist/util/private-file.d.ts +14 -0
- package/dist/util/private-file.d.ts.map +1 -0
- package/dist/util/private-file.js +82 -0
- package/dist/util/private-file.js.map +1 -0
- package/dist/util/source.d.ts +4 -0
- package/dist/util/source.d.ts.map +1 -0
- package/dist/util/source.js +12 -0
- package/dist/util/source.js.map +1 -0
- package/dist/util/spinner.d.ts +15 -0
- package/dist/util/spinner.d.ts.map +1 -0
- package/dist/util/spinner.js +52 -0
- package/dist/util/spinner.js.map +1 -0
- package/dist/util/state.d.ts +120 -0
- package/dist/util/state.d.ts.map +1 -0
- package/dist/util/state.js +264 -0
- package/dist/util/state.js.map +1 -0
- package/dist/vendor/grammars/tree-sitter-go.LICENSE +21 -0
- package/dist/vendor/grammars/tree-sitter-go.wasm +0 -0
- package/dist/vendor/grammars/tree-sitter-java.LICENSE +21 -0
- package/dist/vendor/grammars/tree-sitter-java.wasm +0 -0
- package/dist/vendor/grammars/tree-sitter-kotlin.LICENSE +9 -0
- package/dist/vendor/grammars/tree-sitter-kotlin.wasm +0 -0
- package/dist/vendor/grammars/tree-sitter-php.LICENSE +22 -0
- package/dist/vendor/grammars/tree-sitter-php.wasm +0 -0
- package/dist/vendor/grammars/tree-sitter-python.LICENSE +21 -0
- package/dist/vendor/grammars/tree-sitter-python.wasm +0 -0
- package/dist/vendor/grammars/tree-sitter-r.LICENSE +9 -0
- package/dist/vendor/grammars/tree-sitter-r.wasm +0 -0
- package/dist/vendor/grammars/tree-sitter-swift.LICENSE +21 -0
- package/dist/vendor/grammars/tree-sitter-swift.wasm +0 -0
- package/dist/vendor/grammars/tree-sitter-tsx.wasm +0 -0
- package/dist/vendor/grammars/tree-sitter-typescript.LICENSE +21 -0
- package/dist/vendor/grammars/tree-sitter-typescript.wasm +0 -0
- package/dist/viewer/app.js +2 -0
- package/dist/viewer/index.html +49 -0
- package/dist/viewer/style.css +154 -0
- package/dist/viz/assemble.d.ts +83 -0
- package/dist/viz/assemble.d.ts.map +1 -0
- package/dist/viz/assemble.js +101 -0
- package/dist/viz/assemble.js.map +1 -0
- package/dist/viz/export.d.ts +39 -0
- package/dist/viz/export.d.ts.map +1 -0
- package/dist/viz/export.js +98 -0
- package/dist/viz/export.js.map +1 -0
- package/dist/viz/serve.d.ts +13 -0
- package/dist/viz/serve.d.ts.map +1 -0
- package/dist/viz/serve.js +130 -0
- package/dist/viz/serve.js.map +1 -0
- package/package.json +115 -4
- package/scripts/build-grammar-wasm.mjs +112 -0
- package/scripts/build-viewer.mjs +44 -0
- package/scripts/graph-quality.mjs +117 -0
- package/scripts/pack-trail.mjs +53 -0
- package/scripts/postinstall.mjs +65 -0
- package/scripts/run-tests.mjs +72 -0
- package/scripts/stamp-telemetry-key.mjs +56 -0
- package/scripts/tally-audit.mjs +140 -0
- package/scripts/vendor-grammars.mjs +53 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Context Graph Engine contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,568 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<picture>
|
|
4
|
+
<source media="(prefers-color-scheme: dark)" srcset="assets/trail-code-banner-dark.png">
|
|
5
|
+
<img src="assets/trail-code-banner.png" alt="Trail-code: a map of a codebase, with the callers of one function lit up." width="100%"/>
|
|
6
|
+
</picture>
|
|
7
|
+
|
|
8
|
+
### A code map for your coding agents.
|
|
9
|
+
|
|
10
|
+
Trail-code parses a repository with tree-sitter into a graph of every file, function and caller, and serves that graph to Claude Code, Cursor, Codex and other coding agents over the CLI or MCP. No model, no API key, no network: a build is deterministic and costs nothing. An optional local semantic index covers the prose — specs, docs, system cards — the call graph can't answer for.
|
|
11
|
+
|
|
12
|
+
Tells your agent *where* things are. It does not tell it *why* — that is your repository's job, and this fork leaves it there.
|
|
13
|
+
|
|
14
|
+
<p>
|
|
15
|
+
<a href="https://github.com/jastorgalj/Trail-Code"><img src="https://img.shields.io/badge/fork%20of-trailhq%2FTrail--Code-8A2BE2?style=for-the-badge&logo=github&logoColor=white" /></a>
|
|
16
|
+
<a href="https://nodejs.org"><img src="https://img.shields.io/badge/node-22.3%2B-339933?style=for-the-badge&logo=nodedotjs&logoColor=white" /></a>
|
|
17
|
+
<img src="https://img.shields.io/badge/TypeScript-strict-3178C6?style=for-the-badge&logo=typescript&logoColor=white" />
|
|
18
|
+
<img src="https://img.shields.io/badge/License-MIT-20C997?style=for-the-badge" />
|
|
19
|
+
<a href="TELEMETRY.md"><img src="https://img.shields.io/badge/telemetry-anonymous%2C%20opt--out-546FFF?style=for-the-badge" /></a>
|
|
20
|
+
</p>
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install -g trail-code && trail init
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
> [!NOTE]
|
|
29
|
+
> **This is a fork.** It keeps upstream's code map and drops everything around it that wrote to git on its own: **no learnings, no notes, no team/cloud, no hooks, no statusline, no automatic branches or pushes.** `trail` only reads git. Durable context here lives in OpenSpec (`openspec/specs/` and `openspec/changes/`), reviewed by a human — and indexed as markdown nodes, so `trail ask` still finds it.
|
|
30
|
+
>
|
|
31
|
+
> What the fork adds on top of upstream (semantic search, the `grep` fix, workspace viz, worktree seeding) is listed with `file:line` evidence in [FORK.md](FORK.md).
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## What changes in your agent
|
|
36
|
+
|
|
37
|
+
| Without Trail-code | With Trail-code |
|
|
38
|
+
|---|---|
|
|
39
|
+
| Greps and opens file after file to find the code it needs | Gets the right files and functions with your prompt |
|
|
40
|
+
| Guesses how the code is wired, and misses the caller two directories away | Sees who calls what, and what a change can break, before editing |
|
|
41
|
+
| Rebuilds a picture of the codebase it mapped an hour ago | Starts from a graph that is already there, and correct |
|
|
42
|
+
| Reads a whole file to learn one thing | Reads the crux: the lines that carry the logic, inlined at the hit |
|
|
43
|
+
| Answers about today's code from a stale index | Every query refreshes the graph against the working tree first |
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Contents
|
|
48
|
+
|
|
49
|
+
- [How Trail-code works](#how-trail-code-works)
|
|
50
|
+
- [Quick start](#quick-start)
|
|
51
|
+
- [The map](#the-map)
|
|
52
|
+
- [What stays on your machine](#what-stays-on-your-machine)
|
|
53
|
+
- [FAQ](#faq)
|
|
54
|
+
- Reference: [How the graph gets built](#how-the-graph-gets-built) · [Supported languages](#supported-languages) · [What's in a node](#whats-in-a-node) · [What runs where](#what-runs-where) · [Agent integration](#agent-integration) · [MCP server](#mcp-server) · [CLI](#cli) · [Search & orient](#search--orient-trail-grep--trail-map) · [Monorepos](#monorepos-submodules--multi-repo-folders) · [Worktrees](#worktrees) · [Visualize it](#visualize-it-trail-viz) · [Semantic search](#semantic-search) · [What is on disk](#what-is-on-disk) · [Environment](#environment)
|
|
55
|
+
- [Contributing](#contributing) · [License](#license)
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## How Trail-code works
|
|
60
|
+
|
|
61
|
+
Trail-code has one part, and it runs on your machine.
|
|
62
|
+
|
|
63
|
+
**The map: your code.** `trail init` parses your repo with tree-sitter into a graph of every file, function and who calls what. No model, no API key, no network. Every query checks the working tree first and rebuilds only what changed, so answers describe the code as it is right now — uncommitted edits included. Your agent gets pointers to the matching files and functions with each prompt, and can trace what depends on a symbol before it touches it.
|
|
64
|
+
|
|
65
|
+
The map tells your agent *where* things are. Everything else — what the team decided, why the code is the way it is — stays in your repository, in files a human reviewed.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Quick start
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
npm install -g trail-code # install the CLI, once
|
|
73
|
+
trail init # in your repo: build the map, create .trail/, wire your agents
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
That is the whole setup. `trail init` asks which of your coding agents to wire up, builds the map from your code, and creates `.trail/` for the repo's cache. No daemon, no server, nothing to babysit: it is all files.
|
|
77
|
+
|
|
78
|
+
> [!TIP]
|
|
79
|
+
> **`npm install -g` says EACCES?** Your Node's global folder needs sudo. Skip sudo, or every upgrade will need it too: run `mkdir -p ~/.npm-global && npm config set prefix ~/.npm-global`, add `~/.npm-global/bin` to your `PATH`, open a new terminal and install again. Trail needs Node 22.3 or newer (20.16 works too).
|
|
80
|
+
|
|
81
|
+
> [!TIP]
|
|
82
|
+
> **CUDA 13 machine and the install dies in `onnxruntime-node`'s postinstall?** That build ships binaries only for older CUDA. Skip its GPU download; the semantic index runs on CPU: `ONNXRUNTIME_NODE_INSTALL_CUDA=skip npm i -g trail-code`. [`CONTRIBUTING.md`](CONTRIBUTING.md#cuda-13-and-the-onnxruntime-postinstall) has the long version and a fallback.
|
|
83
|
+
|
|
84
|
+
Commit the wiring so your teammates get it too. The map itself, in `.trail/cache/`, is a local cache like `node_modules` and is gitignored, so it stays out of the commit:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
git add .trail .gitignore # plus AGENTS.md, if you wired Hermes
|
|
88
|
+
git commit -m "set up trail-code"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
`trail init --dry-run` prints the plan, but the plan is inherited from upstream and still lists the hook, statusline and `.claude/settings.json` writes this fork no longer does — the run writes none of them (see the note below). `trail init --agents claude` wires Claude Code alone.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## The map
|
|
96
|
+
|
|
97
|
+
Without a map, your coding agent starts every task blind. It greps a term, opens a file, follows an import, backs out and tries again, rebuilding a picture of a codebase it mapped an hour ago and threw away. That rediscovery burns most of a run's tool calls, tokens and time. People onboard to a codebase once. Agents onboard every single time.
|
|
98
|
+
|
|
99
|
+
The map builds that understanding once, and keeps it current:
|
|
100
|
+
|
|
101
|
+
- **Every file, function and caller.** Parsed with tree-sitter into a graph of symbols and who calls what. Deterministic, no model, no network, 24 languages.
|
|
102
|
+
- **The right code with every prompt.** The skill file `init` writes tells the agent to run `trail ask` before it greps or opens a file; Hermes gets the same instruction in an `AGENTS.md` section. Any agent that can run a command or speak MCP gets the same map.
|
|
103
|
+
- **Always fresh.** Every query checks the working tree first (a few tens of milliseconds when nothing moved) and rebuilds only what changed, so answers describe the code as it is right now, uncommitted edits included.
|
|
104
|
+
- **Plain files you can read.** Linked markdown nodes your agent opens and greps like any other file. No embeddings needed for the code itself, no index to keep warm.
|
|
105
|
+
- **Summaries if you want them.** `trail build --deep` adds plain-English summaries of each part of the system, written by the model provider you choose, under your own key.
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## What stays on your machine
|
|
110
|
+
|
|
111
|
+
- **Your code.** The map is built on your machine with tree-sitter. No model, no network. The optional `trail build --deep` summaries go to the model provider you choose, under your own key.
|
|
112
|
+
- **The map itself.** A local cache under `.trail/cache/` (or `graft/` in a repo never wired by `init`). Never uploaded.
|
|
113
|
+
- **The semantic index.** `embeddings.db` next to it: vectors from a local ONNX model (`Xenova/all-mpnet-base-v2`), computed on your machine.
|
|
114
|
+
- **Anonymous usage stats.** A daily npm version check and one batched usage ping, buckets and fixed labels only: never your code, file paths, repo name, symbols, queries or error messages. [`TELEMETRY.md`](TELEMETRY.md) lists every field. Turn it off with `trail telemetry disable` or `DO_NOT_TRACK=1`.
|
|
115
|
+
- **Git.** `trail` reads it. It never commits, branches or pushes: there are no hooks, and nothing writes outside the files `init` names.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## FAQ
|
|
120
|
+
|
|
121
|
+
**Is this graft?** It is graft's code, plus upstream's rename to trail-code. `trail` and `graft` are the same binary in this package; the map is the "graft map" upstream talks about.
|
|
122
|
+
|
|
123
|
+
**How is this different from CLAUDE.md or AGENTS.md?** Those are yours to write and keep current; `trail init` never touches your `CLAUDE.md` and only maintains its own marked section in `AGENTS.md`. What the map adds is the part you cannot maintain by hand: a graph of every caller, refreshed every query.
|
|
124
|
+
|
|
125
|
+
**Will it fill up my context window?** No. `trail ask` returns pointers and the crux of each hit, not files: your agent pays for the code only when it asks for more.
|
|
126
|
+
|
|
127
|
+
**Do I need an API key?** No. The map, every search command, the MCP tools and `trail blast` work without one. A key only adds the written summaries from `trail build --deep` (`GRAFT_PROVIDER`, `GRAFT_API_KEY`, `GRAFT_MODEL`).
|
|
128
|
+
|
|
129
|
+
**Do I need to sign in?** No. There is no account, no workspace and no cloud in this fork. Everything runs on your machine and travels through git if you choose to commit it.
|
|
130
|
+
|
|
131
|
+
**Which agents does it work with?** Claude Code (a skill file under `~/.claude/skills/trail/`) and Hermes (the same skill plus an `AGENTS.md` section) are what `init` wires. Any other agent — Codex, Cursor, Gemini CLI, Copilot, Windsurf, Kiro, Antigravity, Grok, AdaL — reaches the map by running `trail` itself or through the MCP server, registered by hand; see [MCP server](#mcp-server).
|
|
132
|
+
|
|
133
|
+
**Does it write hooks or a statusline?** No. This fork removed them; upstream has them. `init` writes instruction files, `.trail/` and the skill file, and nothing that runs on its own.
|
|
134
|
+
|
|
135
|
+
**Does it work in monorepos?** Yes: one repo with many packages, submodules, and folders of separate repos. See [Monorepos](#monorepos-submodules--multi-repo-folders).
|
|
136
|
+
|
|
137
|
+
**What does it cost?** Nothing. The CLI is free and open source under the MIT license.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## How the graph gets built
|
|
142
|
+
|
|
143
|
+
The map is built in layers. Tier 1 is tree-sitter: every symbol and call edge, no model, no key. `trail build --deep` adds two language-model passes on top:
|
|
144
|
+
|
|
145
|
+
1. **Read each file.** Every source file is summarized once into a short description of what it does.
|
|
146
|
+
2. **Group into nodes.** Those summaries are grouped into a curated set of nodes (subsystems, key files, and concepts) with typed links between them. The map chooses the right level of detail for you instead of making one node per file, so a big repo becomes a few dozen readable nodes.
|
|
147
|
+
|
|
148
|
+
```mermaid
|
|
149
|
+
flowchart LR
|
|
150
|
+
S[Source files] --> T["Tier 1: tree-sitter<br/>no model, no key"]
|
|
151
|
+
S --> P1["Pass 1: LLM summarizes<br/>each file (--deep)"]
|
|
152
|
+
T --> W[".trail/cache/.graph/wiring.json<br/>per-symbol code graph"]
|
|
153
|
+
P1 --> P2["Pass 2: group into nodes<br/>+ typed links"]
|
|
154
|
+
P2 --> N[".trail/cache/*.md<br/>markdown node graph"]
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Every pass is cached by content hash, the LLM ones and the tree-sitter parse alike. Re-running only touches the files that changed, so the second build is fast and cheap. `trail build --no-reuse` forces a cold re-parse.
|
|
158
|
+
|
|
159
|
+
That cheapness is what lets **every query refresh the graph before it answers**. A retrieval call stats the tree against the last build's fingerprint (about 50ms on this repo), and rebuilds only if something moved, so `ask`/`grep`/`callers`/`skeleton`/`map` describe the code as it is right now, including edits that are unsaved to git: uncommitted, unstaged, or staged all look the same. Git determines the visible file set; freshness compares the working-tree bytes rather than commit or index state. The refresh is structural and `$0`; it never calls the LLM. Turn it off per-command with `--no-refresh`, or everywhere with `GRAFT_NO_REFRESH=1`.
|
|
160
|
+
|
|
161
|
+
Alongside the markdown graph, `trail build` writes `wiring.json` (a per-symbol code graph) plus a per-file wiring card mirroring your source tree. Tier 1 is pure tree-sitter (every function, class, and call edge; deterministic, no model, no network), which is why plain `trail build` needs no key. The `--deep` pass adds a one-line summary and a crux excerpt per symbol, cached by body hash.
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Supported languages
|
|
166
|
+
|
|
167
|
+
The map parses with tree-sitter at two levels of fidelity, plus an optional
|
|
168
|
+
compiler-grade layer, all `$0` and deterministic (no model, no key):
|
|
169
|
+
|
|
170
|
+
- **Full-fidelity**: hand-written extractors with scope-aware, cross-file call
|
|
171
|
+
and import resolution:
|
|
172
|
+
**TypeScript / JavaScript** (incl. JSX & TSX), **Python**, **Go**, **Java**,
|
|
173
|
+
**Kotlin**, **PHP**, **Swift** (classes, structs, enums, actors, protocols;
|
|
174
|
+
extension members attach to the extended type), **R** (`.R`/`.r`: plain
|
|
175
|
+
functions, S3/S4/R6 classes and methods, roxygen `@export`,
|
|
176
|
+
`library()`/`source()` imports), and **Vue** single-file components (their
|
|
177
|
+
`<script>` blocks go through the TypeScript extractor).
|
|
178
|
+
|
|
179
|
+
- **Broad**: symbols (functions, classes, methods, types, …) plus name-resolved
|
|
180
|
+
call edges via a generic tree-sitter extractor, one grammar per language:
|
|
181
|
+
**Rust, C, C++, C#, Ruby, Scala, Elixir, Solidity,
|
|
182
|
+
Dart, Clojure, Nix, Lua, Gleam**, and **OCaml, Zig** (symbols only for now, no call edges).
|
|
183
|
+
|
|
184
|
+
- **Compiler-grade edges (opt-in)**: `trail build --lsp` adds precise
|
|
185
|
+
`lsp_resolved` call edges (member calls the static pass can't type) when a
|
|
186
|
+
language server is on your `PATH`. It uses the first one installed, in this
|
|
187
|
+
order, one server per build: **rust-analyzer** (Rust), **clangd** (C/C++),
|
|
188
|
+
**gopls** (Go), **pyright** (Python), **typescript-language-server** (TS/JS).
|
|
189
|
+
It's best-effort: with no server installed the graph is unchanged.
|
|
190
|
+
|
|
191
|
+
Twenty-four languages, plus Vue single-file components. A file whose language isn't listed is skipped, not
|
|
192
|
+
indexed. Adding a broad-tier language is a small contribution; see
|
|
193
|
+
[CREDITS.md](CREDITS.md) for the folks who added the current set.
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## What's in a node
|
|
198
|
+
|
|
199
|
+
A node is a single markdown file. Most code maps stop at an address: this thing lives in that file, on that line. That tells an agent where to look, not what it will find, so it still has to open the source and read. A node here holds the meaning inline, so the agent learns what it needs up front and opens the file only when it wants more.
|
|
200
|
+
|
|
201
|
+
Each node holds:
|
|
202
|
+
|
|
203
|
+
| Part | What it holds |
|
|
204
|
+
|---|---|
|
|
205
|
+
| **Summary** | A plain-English explanation of what the code does, written by the model and cached. It is there whether or not the code was ever documented, and it is regenerated when the source changes. |
|
|
206
|
+
| **Crux** | The handful of lines that actually carry the logic: the guard, the skip condition, the state change. Lifted straight from the source and stored inline, so the agent sees *how* it works, not just what. |
|
|
207
|
+
| **Sources** | The exact files the node is built from, each tracked by a content hash, so the map can tell precisely when a node has gone stale. |
|
|
208
|
+
| **Links** | Typed connections to other nodes (`depends_on`, `part_of`, `uses`, `implements`, `produces`), written as `[[wikilinks]]` your agent can follow. |
|
|
209
|
+
| **Your text** | Anything you write below the generated block. It is preserved across regenerations, so your own context is never overwritten. |
|
|
210
|
+
|
|
211
|
+
That is three depths in one file: the summary says *what* the code does, the crux shows *how*, and the sources point to the rest if the agent needs it. A plain index makes it read a whole file to learn one thing. A node hands it the answer inline, and the follow-up read often never happens.
|
|
212
|
+
|
|
213
|
+
The crux is stored as the code itself, not as a line range, on purpose. Line numbers drift whenever unrelated code above them shifts, but the lines that matter do not. Keeping the text, not the numbers, means the crux stays correct even as the file around it moves.
|
|
214
|
+
|
|
215
|
+
_Summary, sources, links, and your text ship today in markdown nodes. The crux ships per-symbol in the code graph (`trail build --deep`); inlining it into markdown nodes is next._
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## What runs where
|
|
220
|
+
|
|
221
|
+
- **On your machine, no key, no network:** the structural code graph. `trail build` (wiring graph + per-file cards), `trail build --check`, `trail ask`, `trail grep`, `trail callers`, `trail skeleton`, `trail map` and `trail blast` are deterministic. They never call a model.
|
|
222
|
+
- **On your machine, local model:** the semantic index. `trail build` embeds each node with `Xenova/all-mpnet-base-v2` (ONNX, downloaded once) and `trail_search_semantic` / `trail ask --semantic` search it. Skip it with `--no-semantic`.
|
|
223
|
+
- **Through your provider key:** the LLM-written parts. `trail build --deep` adds the concept nodes (file summaries + node synthesis) and the per-symbol summaries and cruxes. The map is vendor-neutral: set `GRAFT_PROVIDER` (`openai` for any OpenAI-compatible endpoint, `anthropic` for the native API, or `litellm` / `orcarouter` for a gateway that speaks the OpenAI-compatible format), your `GRAFT_API_KEY`, `GRAFT_MODEL`, and, for the `openai` wire format, `GRAFT_BASE_URL` to point at OpenRouter, Fireworks, Groq, a LiteLLM proxy, a local server, or OpenAI itself. Or pass `--provider/--model/--api-key/--base-url` on the command line.
|
|
224
|
+
- **Anonymous usage stats:** a daily npm version check and one batched usage ping. The ping carries buckets and fixed labels only: never your code, file paths, repo name, symbols, queries or error messages. [`TELEMETRY.md`](TELEMETRY.md) is the complete list and `trail telemetry debug` prints exactly what your machine would send. `DO_NOT_TRACK=1` disables both network calls; `trail telemetry disable` disables only the usage ping.
|
|
225
|
+
|
|
226
|
+
Settings keep their `GRAFT_` names. See [`.env.example`](.env.example) for the full list (model, base URL, graph directory).
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Agent integration
|
|
231
|
+
|
|
232
|
+
One command sets the repo up for your agents:
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
npm install -g trail-code && trail init
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
`trail init` writes these, and nothing that runs on its own:
|
|
239
|
+
|
|
240
|
+
| Where | What |
|
|
241
|
+
|---|---|
|
|
242
|
+
| `~/.claude/skills/trail/SKILL.md` | the Claude Code skill: run `trail ask` before grepping or opening source, and how to install the CLI if it's missing |
|
|
243
|
+
| `~/.hermes/skills/trail/SKILL.md` | the same skill for Hermes, when `~/.hermes` exists on the machine |
|
|
244
|
+
| `AGENTS.md` | with `--agents hermes`: a marker-fenced trail section, for the CLIs and editors that read `AGENTS.md` |
|
|
245
|
+
| `.trail/` | the cache directory, plus its `.gitignore` entry |
|
|
246
|
+
| the map | the first build, unless you pass `--no-build` |
|
|
247
|
+
|
|
248
|
+
No hooks, no statusline, no `~/.claude/settings.json`: nothing of trail's runs when you open a session, and `init` never touches your `CLAUDE.md`. Re-running updates its own section or skill file and leaves the rest of your content alone. `--no-global` keeps every write inside the repo, `~/.claude` and `~/.hermes` included.
|
|
249
|
+
|
|
250
|
+
> [!IMPORTANT]
|
|
251
|
+
> This fork kept only two of upstream's hosts: **Claude Code** and **Hermes**. `--list-agents` still prints upstream's roster (`agents`, `adal`, `cursor`, `gemini`, `grok`, `hermes`, `antigravity`, `copilot`, `kiro`, `windsurf`, `claude`) and `--dry-run` still plans their hooks, statusline and `.mcp.json` writes — but the run wires nothing for the other nine, because the multi-host layer went with the rest of the git-writing code (`src/cli.ts:1532`). For those agents, register the MCP server by hand; that path works.
|
|
252
|
+
|
|
253
|
+
With no TTY to prompt on (CI, a Dockerfile, a piped shell), `init` writes **nothing** and prints the command to run instead. Pass `--agents <ids>` or `--yes` to make a scripted run explicit.
|
|
254
|
+
|
|
255
|
+
| Flag | Effect |
|
|
256
|
+
|---|---|
|
|
257
|
+
| `--agents <ids...>` | wire only these, no prompt (this fork writes Claude Code and Hermes; the rest are accepted and skipped) |
|
|
258
|
+
| `--yes`, `-y` | skip the prompt and wire every **detected** agent |
|
|
259
|
+
| `--dry-run` | print the plan, then exit without writing |
|
|
260
|
+
| `--all-agents` | select every known agent (same limit as `--agents`) |
|
|
261
|
+
| `--list-agents` | print the known agent ids and exit |
|
|
262
|
+
| `--no-build` | wire the files only; don't build the map |
|
|
263
|
+
| `--no-global` | skip writes outside this repo (`~/.claude`, `~/.hermes`) |
|
|
264
|
+
| `--verbose` | print the build report when done |
|
|
265
|
+
|
|
266
|
+
### MCP server
|
|
267
|
+
|
|
268
|
+
`trail mcp [dir]` serves the map over stdio. This fork's `init` registers the server nowhere — upstream's registration went with the hooks — so add it yourself, to the agent that needs it:
|
|
269
|
+
|
|
270
|
+
| Tool | Takes | What it's for |
|
|
271
|
+
|---|---|---|
|
|
272
|
+
| `trail_find_code` | a question | Ranked nodes with file:line, source inlined; usually the full answer, no follow-up read needed. |
|
|
273
|
+
| `trail_file_api` | a file path | Every signature in that file, no bodies: the API surface for a tenth of the tokens. |
|
|
274
|
+
| `trail_trace_calls` | a symbol | Who depends on it, or what it depends on with `direction: out`, N levels deep for blast radius. |
|
|
275
|
+
| `trail_find_all` | a regex | Every hit, grouped by enclosing symbol, ranked by how coupled that symbol is. |
|
|
276
|
+
| `trail_repo_map` | nothing | A first look at an unfamiliar repo: directory clusters, hubs, hotspots. |
|
|
277
|
+
| `trail_check_freshness` | nothing | Whether the local map has drifted from the code. |
|
|
278
|
+
| `trail_search_semantic` | a question | Vector search over the semantic index: prose, specs and docs. **Added by this fork.** |
|
|
279
|
+
| `trail_build` | nothing | Rebuild graph + semantic index in the background. |
|
|
280
|
+
| `trail_set_scope` | a path | Pin later queries to one subtree of a workspace. |
|
|
281
|
+
|
|
282
|
+
The same server answers the `graft_*` tool names too. A JSON host (Claude Code's `.mcp.json`, Cursor, Antigravity):
|
|
283
|
+
|
|
284
|
+
```json
|
|
285
|
+
{ "mcpServers": { "trail": { "command": "npx", "args": ["-y", "trail-code", "mcp"] } } }
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
Prefer a bare `{"command": "trail", "args": ["mcp"]}` when the CLI is installed globally: no `npx` resolution on every start. Hermes (`~/.hermes/config.yaml`):
|
|
289
|
+
|
|
290
|
+
```yaml
|
|
291
|
+
mcp_servers:
|
|
292
|
+
trail:
|
|
293
|
+
command: trail
|
|
294
|
+
args: [mcp]
|
|
295
|
+
timeout: 60
|
|
296
|
+
enabled: true
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## CLI
|
|
302
|
+
|
|
303
|
+
`trail --help` lists the commands in four groups. Every `graft` command still works too.
|
|
304
|
+
|
|
305
|
+
```bash
|
|
306
|
+
# find code · your agent runs these
|
|
307
|
+
trail ask "<task>" [dir] # the matching code: ranked nodes + exact file:line (no LLM, no key)
|
|
308
|
+
trail ask "<task>" --source # inline the code at each hit (with --full: whole definitions)
|
|
309
|
+
trail ask "<task>" --json # machine-readable result
|
|
310
|
+
trail ask "<task>" --in <scope> # narrow to one sub-project of a monorepo/multi-repo folder
|
|
311
|
+
trail ask "<task>" --semantic # search the vector index instead of the lexical one
|
|
312
|
+
|
|
313
|
+
trail grep "<regex>" [dir] # exhaustive regex search over indexed files, grouped by enclosing symbol (no LLM, no key)
|
|
314
|
+
trail grep "<regex>" --in <path> # narrow to files at or under this path prefix
|
|
315
|
+
trail grep "<regex>" -i --fixed # case-insensitive; treat the pattern as a literal string, not a regex
|
|
316
|
+
|
|
317
|
+
trail skeleton <file> [dir] # every signature in one file, no bodies: the API surface for ~1/10th the tokens
|
|
318
|
+
trail callers <symbol> [dir] # who calls/references/imports/implements/extends a symbol
|
|
319
|
+
trail callers <symbol> --direction out # the reverse: what the symbol itself calls/references
|
|
320
|
+
trail callers <symbol> -d all # walk transitively: the full blast radius
|
|
321
|
+
|
|
322
|
+
trail map [dir] # token-budgeted repo orientation: dir clusters, hubs, hotspots
|
|
323
|
+
trail map --max-dirs N # raise/lower the number of directories shown
|
|
324
|
+
|
|
325
|
+
# ask / grep / skeleton / callers / map / blast all refresh the map first if the working tree moved:
|
|
326
|
+
# --no-refresh # answer from the map exactly as it is on disk
|
|
327
|
+
# GRAFT_NO_REFRESH=1 # same, for every command
|
|
328
|
+
# GRAFT_REFRESH=hash # hash every file instead of trusting size+mtime
|
|
329
|
+
|
|
330
|
+
# setup
|
|
331
|
+
trail init [dir] # pick which agents to wire (prompts on a terminal; writes nothing until you choose)
|
|
332
|
+
trail init --dry-run # print the plan, then exit (upstream's plan: it still lists hooks/statusline writes this fork does not do)
|
|
333
|
+
trail init --agents claude hermes # wire only these agents, no prompt
|
|
334
|
+
trail init --yes # no prompt; wire every detected agent
|
|
335
|
+
trail init --no-global # skip writes outside this repo (~/.claude, ~/.hermes)
|
|
336
|
+
trail init --no-build # wire the files only; don't build the map
|
|
337
|
+
trail init --list-agents # list known agent ids and exit
|
|
338
|
+
|
|
339
|
+
trail build [dir] # build the map in .trail/cache/: wiring graph + per-file cards (no LLM, no key)
|
|
340
|
+
trail build --deep # add the LLM layer: concept nodes + per-symbol summary/crux (cached)
|
|
341
|
+
trail build --check # build nothing: fail (exit 1) if the map has drifted from the code, for CI
|
|
342
|
+
trail build --deep -e .ts .py # with --deep: only summarize these extensions
|
|
343
|
+
trail build --no-reuse # re-parse every file instead of replaying unchanged ones from cache
|
|
344
|
+
trail build --lsp # add compiler-grade call edges (needs rust-analyzer/clangd/gopls/…)
|
|
345
|
+
trail build --include-md # index .md as nodes (persisted per repo)
|
|
346
|
+
trail build --md-only-dir specs # limit .md indexing to one directory
|
|
347
|
+
trail build --no-semantic # skip the vector index
|
|
348
|
+
trail build --follow-submodules # include initialized submodules; persist the choice for builds + MCP refresh
|
|
349
|
+
trail build --follow-nested-repos # include nested git clones the index doesn't track; persist the choice
|
|
350
|
+
|
|
351
|
+
trail status [dir] # code map, freshness and tokens saved, on one screen
|
|
352
|
+
trail stats [dir] # this agent session's usage mix and tokens saved
|
|
353
|
+
trail config # read or update workspace or global trail configuration
|
|
354
|
+
trail upgrade # npm install -g the latest published version
|
|
355
|
+
trail uninstall [dir] # remove every file and config entry it wrote here (the inverse of init)
|
|
356
|
+
trail uninstall -y # actually remove (without -y it prints what it would remove and exits)
|
|
357
|
+
trail uninstall --keep-cache # wiring only; leave the cache and the .gitignore entry
|
|
358
|
+
trail telemetry [status|enable|disable|debug] # anonymous usage stats; debug prints exactly what would be sent
|
|
359
|
+
|
|
360
|
+
# CI
|
|
361
|
+
trail blast [dir] # blast radius of a diff: what depends on the lines this change touched (no LLM, no key)
|
|
362
|
+
trail blast --base origin/main # diff against the merge base with HEAD (what a PR job runs)
|
|
363
|
+
trail blast --format markdown # a PR comment with a Mermaid diagram
|
|
364
|
+
trail blast --name # name those areas with one cached LLM call, instead of a full --deep build
|
|
365
|
+
trail blast --export-viz site/ # also write the interactive page for this radius (what a PR comment links to)
|
|
366
|
+
trail blast --no-owners # skip "who to tag" (by default, git history names the people behind each area)
|
|
367
|
+
trail blast --depth all --format json # the full transitive closure, machine-readable
|
|
368
|
+
|
|
369
|
+
# not listed in --help, still there
|
|
370
|
+
trail viz [dir] # see the map: serves an interactive viewer on localhost
|
|
371
|
+
trail viz --export site/ --title "PR #12" # one self-contained index.html for CI, GitHub Pages, or a build artifact
|
|
372
|
+
trail mcp [dir] # run the MCP server by hand
|
|
373
|
+
|
|
374
|
+
# global
|
|
375
|
+
trail --dir <path> # context dir other than the default (.trail/cache/, or graft/)
|
|
376
|
+
trail --version, -v # print the installed version and exit
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
Method calls resolve through the receiver's type, using constructor assignments
|
|
380
|
+
(`self.router = APIRouter()`) and type annotations, not just the call-site
|
|
381
|
+
name, so `callers`/`grep --in` return calls bound to the right
|
|
382
|
+
type on method-heavy code, not every method anywhere with that name.
|
|
383
|
+
|
|
384
|
+
## Search & orient (`trail grep` / `trail map`)
|
|
385
|
+
|
|
386
|
+
`trail grep "<regex>"` is exhaustive over every indexed file and groups hits
|
|
387
|
+
by enclosing symbol, ranked by the same in-edge coupling `trail map` uses.
|
|
388
|
+
It's built for "every occurrence of this pattern" tasks where `trail ask`'s
|
|
389
|
+
ranked top-N isn't enough:
|
|
390
|
+
|
|
391
|
+
```
|
|
392
|
+
"NEEDLE" — 2 hits in 2 symbols across 1 files (searched 1 indexed files)
|
|
393
|
+
|
|
394
|
+
heavilyCalled · function · src/a.ts:L1-L3 · 3 in-edges
|
|
395
|
+
L2: console.log("NEEDLE hit in heavilyCalled");
|
|
396
|
+
|
|
397
|
+
rarelyCalled · function · src/a.ts:L4-L6 · 0 in-edges
|
|
398
|
+
L5: console.log("NEEDLE hit in rarelyCalled");
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
`trail map` is a token-budgeted first look at a repo: directory clusters
|
|
402
|
+
with file/symbol counts, each dir's local hubs, and the global hotspots,
|
|
403
|
+
all ranked by in-degree, no LLM, no key:
|
|
404
|
+
|
|
405
|
+
```
|
|
406
|
+
repo map — 313 files · 2349 symbols · 8148 edges · javascript, typescript
|
|
407
|
+
|
|
408
|
+
src/ 157 files · 1804 symbols hubs: wiringPath (write.ts, 48←), cmd (brand.ts, 45←), buildGraph (build.ts, 39←)
|
|
409
|
+
test/ 144 files · 467 symbols hubs: tmpRepo (helpers.ts, 46←), fetch (app-identity.test.ts, 7←), fakeProviders (helpers.ts, 5←)
|
|
410
|
+
viewer/ 5 files · 71 symbols hubs: $ (main.ts, 9←), cvar (data.ts, 6←), activeGraph (main.ts, 5←)
|
|
411
|
+
scripts/ 7 files · 7 symbols hubs: bump (graph-quality.mjs, 1←), defaultTranscriptDir (tally-audit.mjs, 1←), flush (tally-audit.mjs, 1←)
|
|
412
|
+
|
|
413
|
+
hotspots: wiringPath · function · src/graph/write.ts:L20-L22 · 48← tmpRepo · function · test/helpers.ts:L30-L32 · 46← cmd · function · src/brand.ts:L63-L70 · 45← ...
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
## Monorepos, submodules & multi-repo folders
|
|
417
|
+
|
|
418
|
+
The map supports these layouts:
|
|
419
|
+
|
|
420
|
+
- **A monorepo with one `.git`** (a `pnpm-workspace.yaml`/`package.json`
|
|
421
|
+
`workspaces`, or per-package `go.mod`/`pyproject.toml`/`Cargo.toml`):
|
|
422
|
+
`trail build` discovers each sub-project as a ranking scope. `ask`/`map`
|
|
423
|
+
rank every scope on its own terms and fuse the results, so the biggest
|
|
424
|
+
sub-project can't drown a small one; hits carry `[scope/]` labels, and
|
|
425
|
+
`trail map` groups its directory clusters by scope first.
|
|
426
|
+
- **A Git superproject with initialized submodules**: submodules stay excluded
|
|
427
|
+
by default. Run `trail build --follow-submodules` to fold initialized gitlinks
|
|
428
|
+
into one graph, prefixing child paths (for example,
|
|
429
|
+
`deps/parser/src/index.ts`) while honoring each submodule's own Git ignore
|
|
430
|
+
rules. Visible untracked files are included too; uninitialized submodules
|
|
431
|
+
remain absent until `git submodule update --init` checks them out. The choice
|
|
432
|
+
is saved in the repo's config, so later no-flag builds and MCP automatic
|
|
433
|
+
refreshes behave the same way. Run `trail build --no-follow-submodules` to
|
|
434
|
+
restore and persist the default boundary.
|
|
435
|
+
- **A git repo with other repos cloned inside it** (no gitlink, no index entry): the shape multi-repo manifest tools like `west`, `repo`, `gclient` and `tsrc` check dependencies out into, and the shape you get by cloning an upstream into the tree to patch it locally. `--follow-submodules` cannot reach these: they have no `160000` index entry to follow. Run `trail build --follow-nested-repos` to fold them into one graph, prefixing child paths (for example, `external/parser/src/index.ts`) while honoring each clone's own Git ignore rules. A clone at a git-ignored path stays absent, since Git never reports it. The choice is saved and is independent of `--follow-submodules`; neither flag implies the other. Prefer this over the multi-repo split below when the nested repos import from each other and you want those edges in one graph; prefer the split when you want each repo scored and refreshed on its own.
|
|
436
|
+
- **A folder of separate git repos** (no `.git` at the top): `trail build`
|
|
437
|
+
auto-splits: each child gets its own (git-ignored) cache directory, and the parent
|
|
438
|
+
gets a `workspace.json` index. Queries from the parent federate across
|
|
439
|
+
every child, always labeled `<child>/`. Run `trail build` inside a child to
|
|
440
|
+
work on just that repo. A linked worktree (`.git` is a file) is not counted as a child: the repo is scored once.
|
|
441
|
+
|
|
442
|
+
In every layout, narrow to one sub-project with `trail ask "<task>" --in <scope>/`
|
|
443
|
+
once you know where you're working.
|
|
444
|
+
|
|
445
|
+
`trail init` at the parent of a multi-repo folder wires **every child repo too**,
|
|
446
|
+
not just the parent. An agent session opens at a repo root and reads its
|
|
447
|
+
instruction files from there, so each child needs its own. A session started in
|
|
448
|
+
the parent gets the federated view; one started in a child sees that repo alone.
|
|
449
|
+
|
|
450
|
+
Commands also find the map from a subdirectory: with no `[dir]` argument they
|
|
451
|
+
walk up to the nearest cache directory, so `trail ask` works from `src/deep/inside/`
|
|
452
|
+
without a `cd` to the repo root.
|
|
453
|
+
|
|
454
|
+
## Worktrees
|
|
455
|
+
|
|
456
|
+
A linked worktree (`.git` is a file) has no cache of its own, because the cache is git-ignored. **There is nothing to run first.** The first query copies the main checkout's graph — lexical graph, `ask` index and the vector index — and then patches the difference between the two branches. The answer is about that worktree's code, not about whatever branch the main checkout happens to be on. `GRAFT_NO_SEED=1` turns the seeding off.
|
|
457
|
+
|
|
458
|
+
## Visualize it (`trail viz`)
|
|
459
|
+
|
|
460
|
+
`trail viz` opens a local, interactive view of the map. No install, no dev server; the viewer ships prebuilt inside the package.
|
|
461
|
+
|
|
462
|
+
<p align="center">
|
|
463
|
+
<img src="assets/graft-viz-demo.gif" alt="The graph viewer: searching a symbol and jumping to it lights up its dependency graph: amber edges are what it depends on, indigo is what depends on it" width="820"/>
|
|
464
|
+
<br/><sub>search → jump to a node → dependency graph lights up</sub>
|
|
465
|
+
</p>
|
|
466
|
+
|
|
467
|
+
- **Context** tab: the architecture graph from the markdown nodes. Nodes colored by type, sized by connectedness.
|
|
468
|
+
- **Code** tab: the per-symbol graph from `wiring.json` (run `trail build` first).
|
|
469
|
+
- **Outline** tab: the file → class → method hierarchy as a collapsible tree.
|
|
470
|
+
|
|
471
|
+
What this fork adds to the viewer: **workspace federation** (one page with every child repo's code nodes, and `--repos a b` / `--skip a b` to pick which), **tests hidden by default** (`--include-tests` brings them back; only the view filters, the index keeps every node), and `trail` branding instead of `graft`.
|
|
472
|
+
|
|
473
|
+
```bash
|
|
474
|
+
trail viz # http://127.0.0.1:4400, three tabs
|
|
475
|
+
trail viz --repos frontend backend # workspace: only these
|
|
476
|
+
trail viz --skip openspec docs # workspace: all but these
|
|
477
|
+
trail viz --include-tests # show test files in the graph
|
|
478
|
+
trail viz --export out/ --title "PR #12" # self-contained HTML for CI
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
Edges speak the code's language. Every link is one of a closed set of verbs, each
|
|
482
|
+
answering a question someone building or reviewing code actually asks:
|
|
483
|
+
|
|
484
|
+
| Verb | The question it answers |
|
|
485
|
+
|---|---|
|
|
486
|
+
| `part_of` / `contains` | where does this live? |
|
|
487
|
+
| `uses` / `calls` / `imports` / `depends_on` | what breaks if I change this? |
|
|
488
|
+
| `produces` | where does this output come from? |
|
|
489
|
+
| `configures` | what changes its behavior without a code change? |
|
|
490
|
+
| `validates` | what checks or judges this? (tests, drift checks, scoring) |
|
|
491
|
+
| `extends` / `implements` | what contract must this honor? |
|
|
492
|
+
| `references` | what names this without calling it? (drawn as faint dots) |
|
|
493
|
+
|
|
494
|
+
Select a node and its edges take on direction: **amber = what it depends on,
|
|
495
|
+
indigo = what depends on it**, with the verb written on each highlighted edge.
|
|
496
|
+
Chips above the canvas filter by verb; edges the parser resolved exactly draw
|
|
497
|
+
solid, while edges matched by name alone draw dashed. The viewer live-reloads when the cache
|
|
498
|
+
changes on disk.
|
|
499
|
+
|
|
500
|
+
## Semantic search
|
|
501
|
+
|
|
502
|
+
`trail build` builds the vector index by default (skip it with `--no-semantic`); the first run downloads `Xenova/all-mpnet-base-v2` (~420 MB) once, and every later build only re-embeds nodes whose `body_hash` changed. Deleted nodes are pruned. The index is a fork addition: embeddings live in `embeddings.db` (SQLite + sqlite-vec) next to the graph.
|
|
503
|
+
|
|
504
|
+
The model is trained on natural language, so `trail_search_semantic` earns its keep on `.md` (specs, docs, system cards) and adds little for code symbols — use `trail_find_code` or `trail ask` for those. Scope it in a workspace with `in=`:
|
|
505
|
+
|
|
506
|
+
```python
|
|
507
|
+
trail_search_semantic(query="cómo se calcula la cuota mínima", in="default-core", limit=5)
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
Filter hits below ~0.25 as noise; 0.44+ is a solid hit, 0.50+ high confidence.
|
|
511
|
+
|
|
512
|
+
### Indexing markdown
|
|
513
|
+
|
|
514
|
+
```bash
|
|
515
|
+
trail build --include-md # index .md as nodes (persisted per repo)
|
|
516
|
+
trail build --include-md --md-only-dir specs # limit it to one directory
|
|
517
|
+
trail build --no-include-md # revert
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
OpenSpec `.md` under `openspec/specs/` and `openspec/changes/` is indexed without any
|
|
521
|
+
flag (archive excluded; `--include-openspec-archive` includes it). That is where this fork keeps the context that upstream kept in learnings: reviewed, versioned, and searchable by `trail ask`.
|
|
522
|
+
|
|
523
|
+
## What is on disk
|
|
524
|
+
|
|
525
|
+
Everything lives under the repo's cache directory — `.trail/cache/` in a repo wired by
|
|
526
|
+
`trail init`, `graft/` elsewhere. This is what a first `trail build` leaves there:
|
|
527
|
+
|
|
528
|
+
| File | What it is |
|
|
529
|
+
|---|---|
|
|
530
|
+
| `.graph/wiring.json` | The graph: nodes (id, kind, path, span, signature) + edges |
|
|
531
|
+
| `.cache/ask-index.json` | BM25 sidecar for `trail ask` / `trail_find_code` |
|
|
532
|
+
| `.cache/extract.<hash>.json` | Per-file parse memo, so a rebuild replays unchanged files |
|
|
533
|
+
| `.cache/fingerprint.<hash>.json` | The freshness probe's record (size, mtime, hash per file) |
|
|
534
|
+
| `.cache/embeddings.db` | SQLite + sqlite-vec: one vector per node (skipped with `--no-semantic`) |
|
|
535
|
+
| `INDEX.md`, `*.md` cards | Markdown projections, written by an explicit `trail build` |
|
|
536
|
+
|
|
537
|
+
None of it is committed: `trail build` adds the directory to `.gitignore` (skip with
|
|
538
|
+
`--no-gitignore`) and writes a `.ignore` so a ripgrep run doesn't descend into it
|
|
539
|
+
(`--no-ignore`). Delete the cache directory to force a cold build.
|
|
540
|
+
|
|
541
|
+
## Environment
|
|
542
|
+
|
|
543
|
+
| Variable | Effect |
|
|
544
|
+
|---|---|
|
|
545
|
+
| `GRAFT_NO_REFRESH` | Never refresh the map on the query path |
|
|
546
|
+
| `GRAFT_REFRESH=hash` | Confirm every file by bytes instead of trusting size+mtime |
|
|
547
|
+
| `GRAFT_DIR` | Cache directory override, for every entry point |
|
|
548
|
+
| `GRAFT_NO_SEED` | Never seed a worktree from the main checkout |
|
|
549
|
+
| `GRAFT_FIRST_BUILD_WAIT_MS` | How long the first query waits for a repo's first build |
|
|
550
|
+
| `GRAFT_MCP_NPX=1` | Force the `npx` form in the MCP entries `init` writes, instead of the bare `trail` command |
|
|
551
|
+
| `GRAFT_API_KEY` / `GRAFT_PROVIDER` / `GRAFT_MODEL` / `GRAFT_BASE_URL` | The optional `--deep` LLM pass |
|
|
552
|
+
| `DO_NOT_TRACK` | Disable the version check and the usage ping |
|
|
553
|
+
|
|
554
|
+
---
|
|
555
|
+
|
|
556
|
+
## Contributing
|
|
557
|
+
|
|
558
|
+
This is a fork and it is worked on directly: clone, build and test it with the steps in
|
|
559
|
+
[`CONTRIBUTING.md`](CONTRIBUTING.md). That file also has the Node and CUDA requirements, why
|
|
560
|
+
`npm test` has a known set of failures on this fork, how the fork relates to upstream, and how
|
|
561
|
+
publishing works.
|
|
562
|
+
|
|
563
|
+
The pre-push gate is typecheck and tests; the code map is not part of it, it refreshes itself on
|
|
564
|
+
the query path.
|
|
565
|
+
|
|
566
|
+
## License
|
|
567
|
+
|
|
568
|
+
MIT, the same as upstream. See [LICENSE](LICENSE).
|