Reads a Java/Spring Boot codebase and emits a deterministic knowledge graph — nodes, edges, complexity metrics, Spring-aware annotations — reproducible byte-for-byte across runs.
Status: v1 complete (DC1–DC6) — deterministic graph, LLM enrichment, eval framework, TypeScript/NestJS renderer, run manifest + structured logging, cost-safety floor + multi-provider LLM support. See docs/architecture.md for the full pipeline.
A generation of tools already covers individual pieces of this space: deterministic graph analysis, architecture governance, security scanning, and same-language modernization. Codeograph builds on established patterns and positions itself honestly against that prior art as a narrow extension, not a reinvention or replacement.
Existing property-graph and analysis tools stop at understanding, and transpilers or modernization engines don't build on a shared architectural graph. Codeograph targets the seam between those families: it emits a deterministic, metrics-carrying knowledge graph for a Java/Spring codebase and then uses it to drive a pluggable cross-language renderer that generates NestJS source around a deterministic project scaffold.
Codeograph is built on the belief that codebases should be understood and structured deterministically, and that AI should sit on top of that as an augmentor — explaining, suggesting, and translating, but never quietly becoming the driver. Its stance is to see how far a deterministic knowledge graph can carry cross-stack work — understanding and rendering into new stacks — without handing control to AI.
In v1, Codeograph ships TypeScript/NestJS rendering only and adds Go in v1.1; it does not replace tools that already do governance, SAST, same-language refactoring, or transpilation well.
- Python ≥ 3.12
- Java 17+ (for the bundled AST parser; regex fallback runs without it)
- Maven 3.9+ (only when rebuilding the parser JAR)
pip install -e ".[dev]"
codeograph run /path/to/java/project --out ./outOutput (three files — always start from manifest.json):
| File | Description |
|---|---|
out/manifest.json |
Entry point: run identity, schema_version: "2.0.0", SHA-256 of every artefact, llm_skipped flag |
out/graph.json |
Deterministic AST graph — nodes, edges, complexity metrics |
out/llm-annotations.json |
LLM semantic enrichment (full run only; absent on --ast-only, indicated by llm_skipped: true) |
Input can be a local directory path, a git URL, or a .zip archive.
make test # Python unit tests
make lint # ruff
make typecheck # mypy
make golden-update # refresh Tier 1 / Tier 2 golden graphs
cd codeograph/parser/java
mvn test # Java parser tests (JavaParser-based)codeograph/ Python package
analyzer/ CorpusAnalyzer — pipeline orchestrator
cli/ CLI entry point (run, eval, render, cache)
config/ pydantic-settings + YAML config source
evals/ eval framework — scorecards, checks, runner, report
graph/ GraphBuilder, GraphAssembler, GraphWriter + models
input/ corpus acquisition + source discovery
llm/ LLM provider, prompts, cache, middleware
manifest/ Manifest schema (2.0.0), IO, run_id, schema_cli
parser/ FileParserDispatcher, RegexFallback
java/ Maven module — builds parser.jar (JavaParser AST)
passes/ Pass 1 (annotator), Pass 2 (synthesizer)
prompts/ versioned prompt files (annotate_node, synthesize_corpus)
renderers/ pluggable renderer registry; typescript_nestjs/
rendering/ class selection + domain grouping (ADR-009)
scripts/ verify_gitleaks_pin + operational scripts
telemetry/ JSONL LLM telemetry emitter + aggregation
_generated/
manifest.schema.json committed JSON Schema (regenerated from Pydantic)
docs/
architecture.md current architecture snapshot
adr/ architecture decision records (ADR-001..027)
tests/
fixtures/codeograph-corpus/ Tier 1 surgical fixture
goldens/tier1/ stored golden graphs (byte-equal regression)
... unit tests mirror codeograph/ layout
Codeograph includes an LLM enrichment pipeline (Passes 1 and 2) that adds semantic understanding to the deterministic AST graph:
- Annotated Graph Output: Detailed per-node semantics (Pass 1) and corpus-level synthesis (Pass 2) stored in
llm-annotations.json. - Response Cache: A local SQLite cache (
cache.db) stores responses. You can manage the cache using thecodeograph cacheCLI (e.g.,codeograph cache statsorcodeograph cache purge). - Telemetry: Every LLM call is recorded as a structured JSONL row in the
telemetry/output folder, carrying token usage, latency, and cache-hit details.
The graph tells Codeograph what is there — nodes, edges, framework semantics, and metrics from precise, reproducible deterministic analysis; LLM Pass 1 explains what it means at the per-node level. The LLM passes matter because they add the layer deterministic analysis cannot supply — per-node explanation, onboarding summaries, and role inference grounded in that verified structure, making the graph easier to read and more useful without changing what the system treats as truth. LLM Pass 2 reaches into riskier corpus-level synthesis, but all LLM output stays advisory in separate artefacts and is contained so the deterministic graph stays authoritative.
To prevent accidental runaway API bills during large runs, Codeograph implements a pre-flight cost safety floor and middleware ceiling limits:
- Pre-flight Cost Estimate: Before starting Pass 1, Codeograph parses the corpus (Pass 0), derives the expected call count (
class_count + 1), queries a localized model pricing database (prices.toml), and prints an estimate of the total cost and calls. - TTY Confirmation Gate: If the estimated call count exceeds the default confirmation threshold (
100calls, configurable via--llm-call-confirm-threshold), the pipeline prompts the user on an interactive terminal (TTY) or auto-aborts in non-TTY environments (CI/pipelines). You can override this using--yes/-yor--non-interactive. - Hard Ceilings: You can configure hard limits using
--max-llm-calls Nor--max-tokens-total M. A middleware wrapper checks these ceilings mid-run and aborts execution immediately if either threshold is reached, displaying the partial progress manifest.
Note
Removal Contract: These temporary cost limits are built for v1.0.0 and will be replaced in v1.1.0 by live billing-accurate budget tracking (--max-cost-usd).
codeograph render converts an existing run output into a TypeScript/NestJS project: each selected class is translated into full idiomatic NestJS source — method bodies included, not skeletons — via one LLM call, emitted alongside a deterministic Jinja2 project scaffold (package.json, tsconfig.json, bootstrap main.ts). Features v1 cannot translate faithfully surface as reviewable TODO/stub placeholders or explicit refuse-to-render entries — never silent drops — under a configurable per-feature policy. Rendering is decoupled from LLM execution so you can tune rendering parameters (ORM mode, class budget, domain grouping) without re-running the expensive annotation passes.
codeograph render --from ./out --out ./ts-out --target typescriptKey flags:
| Flag | Default | Description |
|---|---|---|
--from DIR |
required | Output directory from a prior codeograph run |
--out DIR |
required | Destination for the rendered TypeScript project |
--target |
typescript |
Renderer target (--list-targets prints registered targets) |
--db-layer |
config default | Override ORM mode: typeorm, typeorm_raw_sql, or hybrid |
--render-budget N |
config default | Per-domain class cap (stratified sampling, ADR-009) |
--no-scaffold |
off | Skip NestJS scaffold files (package.json, tsconfig, etc.) |
--force |
off | Overwrite --out if non-empty |
Rendering calls the LLM once per selected class. The second run against the same corpus hits the response cache — no additional API cost.
codeograph eval runs scorecard checks against an existing run output. Scorecards are JSON sidecar files written to <out>/evals/.
# Single-corpus scorecard
codeograph eval run ./out
# Cross-corpus comparison across multiple runs
codeograph eval report ./run1 ./run2 ./run3eval run options:
| Flag | Description |
|---|---|
--scorecard graph|ts |
Restrict to specific scorecards (default: all) |
--check <id> |
Run only the named check IDs |
--skip-check <id> |
Skip named check IDs |
The graph scorecard runs 6 deterministic checks (node count, edge count, schema version, sha256 integrity, complexity metrics present, golden-graph agreement). The code-quality scorecard runs 3 checks (compilation, feature coverage, llm_judge — the latter two are skip in v1 pending ADR-020 calibration).
You can also run eval automatically as part of codeograph run using --eval:
codeograph run /path/to/project --out ./out --evalCodeograph emits logs via two channels simultaneously:
- Console (stderr): Human-readable plaintext, default level
INFO. Format:[area] message. - File (
<out>/logs.jsonl): Structured JSONL atDEBUGlevel, always written during arun. Fields:run_id,logger,context,level,ts,msg.
Log level is controlled via global flags (before the subcommand):
codeograph -v run ... # DEBUG console output
codeograph -q run ... # WARNING only
codeograph -qq run ... # ERROR only
codeograph --log-level DEBUG run ... # explicit level (wins over -v/-q)The run manifest (manifest.json) is written once at the terminal checkpoint, after all passes complete. It records the run_id, artefact SHA-256s, schema version (2.0.0), and optional pointers to scorecards and compile-checks. The committed JSON Schema at codeograph/_generated/manifest.schema.json is the external validator contract; a CI gate keeps it in sync with the Pydantic source.
- Maven-only classpath resolution. Gradle projects are detected and source files are parsed, but classpath resolution falls back to source-only mode. Method-call resolution is lower fidelity for Gradle inputs until v1.1.
- TypeScript/NestJS renderer only. The Go renderer (ADR-011) is planned for v1.1.
- Providers: Anthropic, OpenRouter, and any OpenAI-compatible endpoint; Ollama and Bedrock deferred to v1.1. All run through a LangChain-based provider abstraction (
AnthropicProvider,OpenRouterProvider,OpenAICompatibleProviderwith a configurablebase_url).OllamaandBedrockare wired in the resolver but raiseNotImplementedError. A single model (defaultclaude-sonnet-4-6) serves all stages by default; per-stage model overrides (llm_model_fast/deep/render, used by Pass 1 / Pass 2 / rendering) are configurable, but v1 ships no curated differential per-stage mapping — that is v1.1. - Sync LLM calls; no Batch API. All LLM calls are synchronous with prompt caching. The Anthropic Batch API (50% discount) is v1.1.
- CI runs on Linux only. Local tests pass on Windows/macOS; the automated CI infrastructure runs on
ubuntu-latest. Multi-OS CI is a v1.1 extension wired by contributor demand. - No live-LLM tests. The test suite uses a deterministic
MockLlmProvider. No tests make live API calls in v1; the 80% line coverage gate applies tocodeograph/. - Eval covers two committed corpora.
spring-rest-sampleandspring-blog-apiare the baseline corpora;codeograph eval reportprovides cross-corpus comparison. Additional corpora can be added toexamples/perCONTRIBUTING.md. semantic_accuracyandllm_judgechecks are skipped in v1. The graph scorecard reserves these slots; calibration data and the LLM-judge harness land in v1.1 (ADR-020).- Coverage check means feature coverage, not test coverage. The code-quality scorecard
coveragecheck measures which Spring annotation categories from the ADR-010 audit were translated into TypeScript — not pytest line coverage. - Per-run output is
<out>itself. There is no--runs-dirflag. Eachcodeograph runinvocation owns its--outdirectory. To keep multiple run histories, use distinct--outpaths (e.g.--out ./runs/$(date -u +%Y-%m-%dT%H-%M-%SZ)/). - Manifest schema is strict-additive within
2.x. Field removal, rename, type-change, or required/optional flips require a3.0.0major bump and a superseding ADR. New fields land as minor bumps. External consumers can pin a2.xvalidator and rely on forward compatibility. - No log rotation or color output in v1.
logs.jsonlgrows unboundedly per run; no log-level env-var override. These are v1.1 items. - Gitleaks secret scanning is enforced in CI; merges are blocked on detection; no admin bypass. The
pre-commithook is opt-in (pre-commit installafter setup); CI is the mandatory gate. The gitleaks version is exact-pinned in bothsecrets-scan.ymland.pre-commit-config.yamlwith a CI parity check, and a scheduled full-history scan runs nightly (non-blocking). SeeCONTRIBUTING.mdfor the finding-response runbook. - Output stability tracks
schema_version, not the application version. The app version (codeograph --version, currently0.5.0) and the artefactschema_versionare independent version lines. Consumers scripting againstgraph.json/manifest.jsonshould pin or checkschema_version; the app version is not a format-stability guarantee. v1 ships in0.x—1.0.0is published only at the stability gate (ADR-026).
- Running Codeograph — pipeline stages, command order, and exact flag combinations for common scenarios
- Model selection & cost — which model/provider to pick and what it costs
- Architecture snapshot — what's wired today
- ADRs — design decisions and their rationale
- Contributing — commit conventions, branching, CI