Inspiration

Finding a function name in a large C codebase is usually easy. Understanding why that function matters is not.

While reading Linux scheduler code, I repeatedly had to reconstruct behavior spread across headers, designated initializers, function pointers, configuration guards, and direct calls. Text search found individual names, while traditional call graphs produced more structure than reading guidance.

I built CodeTrail to answer a narrower question: what should I read next, and what source evidence connects it?

What it does

CodeTrail is a local VS Code extension that turns an unfamiliar C codebase into a compact reading path.

A developer can search for a term such as schedule, select a ranked symbol, and receive:

  • a file-level route showing which files participate;
  • an ordered function path inside those files;
  • source-backed relationship reasons;
  • confirmed, inferred, or possible confidence labels;
  • direct navigation to the relevant source range.

The same discovery workflow is available through search, CodeLens, Alt+Shift+T, and the editor context menu.

CodeTrail is deliberately not a chat interface or an unrestricted graph canvas. It remains local, deterministic, bounded, and explicit that its output is a static reading order—not a runtime trace.

How I built it

The extension uses Tree-sitter C through packaged WebAssembly assets. A worker indexes C and header files without blocking the extension host.

The analyzer combines structural parsing with a small kernel-aware enrichment layer for scheduler registrations, designated initializers, configuration guards, and function-pointer dispatch. It produces a typed immutable graph in which every relationship retains its source path, range, confidence, and evidence reason.

Deterministic search ranks lexical matches and structural neighbors. Bounded graph traversal then collapses the relevant subgraph into the product’s defining hierarchy: files first, functions second.

Snapshots, worker messages, webview messages, navigation destinations, graph traversals, queues, and response sizes are all validated and bounded.

A secondary read-only MCP adapter exposes the same evidence to coding agents. It is intentionally an adapter over the existing engine, not a separate AI product.

How I used Codex and GPT-5.6

Codex with GPT-5.6 was my engineering partner throughout the development lifecycle, rather than a runtime dependency inside CodeTrail.

I used it to:

  • refine the product boundary and reject a noisy full-graph interface;
  • design the language-neutral contracts and C-first architecture;
  • write failing behavioral tests before production changes;
  • implement parsing, search, relationship discovery, worker isolation, and the VS Code experience;
  • diagnose Tree-sitter ABI, ESM/CommonJS worker, dependency-lock, and cross-platform packaging failures;
  • review security boundaries and validate source navigation;
  • conduct an installed-extension click-through;
  • build reproducible Linux scheduler and MCP evaluations;
  • prepare release packaging, CI, documentation, and the demo.

The repository’s commit history and docs/build-with-codex.md record this sequence. I reviewed the decisions and tested the resulting behavior rather than treating generated code as automatically correct.

CodeTrail itself makes no OpenAI or Codex calls, uploads no source, and requires no account.

Challenges

The hardest problem was representing indirect relationships without presenting guesses as facts. Direct function calls can be confirmed structurally, while registrations and function-pointer dispatch often remain inferred. CodeTrail preserves that distinction in both its contracts and interface.

The Linux kernel also contains macro-heavy GNU C that cannot always be understood without a complete build configuration. CodeTrail retains usable verified structure while showing partial-parse and traversal warnings instead of hiding those limits.

Release engineering uncovered additional real integration failures: incompatible Tree-sitter WASM/runtime versions, worker module-format mismatches, npm lockfile differences between local and hosted environments, and a package verifier that behaved differently on Windows and Ubuntu.

Accomplishments

The reproducible upstream evaluation indexes 50 files from a pinned Linux kernel/sched revision:

  • 3,743 indexed symbols;
  • 33,099 typed relationships;
  • 2,049,984 bytes of source;
  • __schedule ranked first for schedule;
  • entity_eligible ranked second for eevdf eligible;
  • pick_task_fair ranked tenth for register dispatch.

The release contains 128 passing tests, 94.42% statement coverage in the language-neutral core, no known production dependency vulnerabilities, and a cross-platform package gate on Windows and Ubuntu.

For coding agents, two MCP calls retrieved each required answer and its relationship evidence while returning 97.33% to 99.34% less data than the indexed source. This is a context-volume result, not a claim that an LLM became more accurate.

What I learned

The useful output of static analysis is not always the largest possible graph. A smaller path with provenance, confidence, ordering, and visible limits can be more actionable.

I also learned that uncertainty must be part of the product experience. An inferred edge should never quietly become a fact just because it makes the trail look more complete.

What's next

The architecture is language-extensible, but this release is intentionally C-first. Future work would add incremental indexing, additional language adapters, build-configuration-aware preprocessing, and more domain enrichment modules without weakening the shared evidence contracts.

Built With

  • actions
  • api
  • chatgpt
  • code
  • codex
  • context
  • esbuild
  • extension
  • github
  • gpt-5.6
  • model
  • node.js
  • protocol
  • tree-sitter
  • typescript
  • vitest
  • vs
  • webassembly
  • zod
Share this project:

Updates