CLI that produces a Markdown context-augmentation artifact for a Java target method using a Code Property Graph produced by Joern. The artifact is designed to be dropped directly into the context of an agentic IDE so the agent can generate a method body with fewer test/build cycles.
The artifact contains:
- Reverse call-graph chains from the target up to the test methods that transitively exercise it, with source snippets and argument back-slices.
- Local context: sibling members the target uses, public API of used types (with enum constants in full), production call sites of the target.
A companion JSON sidecar carries the same data in a stable schema (with reserved slots for V2 negative-memory).
-
Java 21. Verify:
java -versionIf you don't have it:
brew install openjdk@21(macOS) orsdk install java 21.0.4-tem(SDKMAN). -
Joern on PATH (binaries
javasrc2cpgandjoern).macOS / Linux — install via the bundled helper:
bash tools/install-joern.shWindows — Joern's official installer is bash-only. Either:
- Download the latest
joern-cli.zipfrom https://github.com/joernio/joern/releases/latest, extract it, and add the resultingjoern-cli\folder (the one containingjavasrc2cpg.bat) to yourPATH; or - Install via Scoop:
scoop bucket add joernio https://github.com/joernio/joern.git && scoop install joern.
Alternatively, skip
PATHsetup and point graph-tipper at the install directory with--joern-home C:\path\to\joern-cli.Verify:
javasrc2cpg --version # Unix javasrc2cpg.bat --version # Windows - Download the latest
From the repository root:
./gradlew installDist
This produces a launcher at build/install/graph-tipper/bin/graph-tipper
(plus graph-tipper.bat on Windows). Optional: add it to PATH for convenience.
# macOS / Linux
export PATH="$PWD/build/install/graph-tipper/bin:$PATH"
graph-tipper --help
# Windows (PowerShell)
$env:Path = "$PWD\build\install\graph-tipper\bin;$env:Path"
graph-tipper --helpThis walks through generating an artifact for the motivating example —
putValue(int, int, Text) in
picocli.
git clone https://github.com/remkop/picocli /tmp/picocli
graph-tipper \
--project /tmp/picocli \
--target 'src/main/java/picocli/CommandLine.java#TextTable.putValue(int,int,Text)' \
--out /tmp/gt-out
First run will spend ~30–60 seconds invoking Joern to build the CPG. The CPG
is cached under /tmp/gt-out/.cache/<sha256-of-source-tree>/, so subsequent
runs against the same source state finish in under a second.
On success the launcher prints the absolute path of the Markdown artifact, for example:
/tmp/gt-out/3f7a91b0c14d8e22.md
ls /tmp/gt-out
# 3f7a91b0c14d8e22.md ← drop this into the agent's context
# 3f7a91b0c14d8e22.json ← machine-readable sidecar
less /tmp/gt-out/3f7a91b0c14d8e22.md
The Markdown starts with a budget header and is organized as:
# Graph-Tipper Augmentation
> Generated for: picocli @ <hash>
> Target: picocli.CommandLine$TextTable.putValue
> Budget: 18420 / 20000 tokens · Chains: 9 · Truncated: false
## Target ← signature + javadoc + current body
## Test Chains ← chain test → ... → target, with snippets + arg origins
## Local Context ← sibling members, used types (enum constants in full)
## Negative Memory ← reserved for V2
Concatenate the artifact into the agent's prompt:
cat /tmp/gt-out/3f7a91b0c14d8e22.md \
| pbcopy # macOS — paste into your agent UI
Or programmatically (any agent framework):
ARTIFACT=$(cat /tmp/gt-out/3f7a91b0c14d8e22.md)
your-agent-cli --context "$ARTIFACT" --task "Implement putValue per the artifact"graph-tipper [OPTIONS] --project <dir> --target <spec> --out <dir>
| Option | Default | Purpose |
|---|---|---|
--project <dir> |
required | Java project root (containing src/). |
--target <spec> |
required | Target method spec; two forms (see below). |
--out <dir> |
required | Output directory for the artifact and cache. |
--budget-tokens <int> |
20000 |
Markdown token budget. Approximation: 4 chars/token. |
--max-chains <int> |
16 |
Maximum number of chains to keep. |
--treat-test-dirs-as-tests |
off | Also treat methods under src/test/java/** as tests even without @Test. |
--no-cache |
off | Force a fresh Joern build, ignore cache. |
--joern-home <dir> |
unset | Use <dir>/javasrc2cpg etc. instead of relying on PATH. |
--debug-dot |
off | Parsed, but DOT rendering is deferred to V2. |
-h, --help |
— | Print usage. |
Path + signature (matches your javadoc-style references):
src/main/java/picocli/CommandLine.java#TextTable.putValue(int,int,Text)
FQN-only (compact):
picocli.CommandLine$TextTable#putValue(int,int,picocli.CommandLine$Help$Ansi$Text)
The parameter list is optional in both forms. If omitted or ambiguous, the tool prints the candidates and exits with code 2.
| Code | Meaning |
|---|---|
| 0 | Artifact written successfully. |
| 1 | Generic error (Joern failure, I/O, etc.). |
| 2 | Target method not found or ambiguous. |
| 3 | Token budget too small to fit the protected minimum. |
<--out>/
├── <hash>.md ← agent-facing artifact
├── <hash>.json ← machine sidecar (stable schema v1.0)
└── .cache/
└── <src-sha>/ ← Joern CPG cache, keyed by source-tree SHA-256
├── cpg.bin
└── export/export.json
<hash> is derived from the target spec + source-tree SHA-256, so identical
inputs produce identical filenames (good for diff between iterations).
"No tests transitively reach this target" — the artifact is still written, with an empty Test Chains section and an explicit note. This is a valid signal: the target has no test coverage. The agent can still use the local-context block.
"No method matches X" (exit 2) — the tool prints the five nearest signatures. Either fix the spec or omit the parameter list to see all candidates with that name in that class.
"Multiple matches" (exit 2) — disambiguate by providing parameter types. The error message lists them.
"budget exceeded on minimum" (exit 3) — the target's javadoc + current
body + top-1 chain alone exceed the budget. Raise --budget-tokens.
Joern fails on the project — javasrc2cpg is source-only and stumbles on
some unusual generic/lambda shapes. As a workaround, try --no-cache to
force a rebuild. The jimple-based (bytecode) fallback is on the V2 roadmap.
CreateProcess error=2, The system cannot find the file specified
(Windows) — graph-tipper could not find javasrc2cpg.bat or joern.bat.
Confirm javasrc2cpg.bat --version runs in the same shell. If Joern is
installed but not on PATH, pass --joern-home C:\path\to\joern-cli
(the directory that contains the .bat launchers).
./gradlew test
GRAPHTIPPER_PICOCLI_HOME=/tmp/picocli \
./gradlew test --tests com.graphtipper.PicocliSmokeTest
Skipped when the env var is unset.
The cache key is the SHA-256 of all .java files. Editing any source file
invalidates the cache automatically — just re-run the same command. Use
--no-cache only when you suspect a stale cache entry.
See docs/superpowers/specs/2026-05-13-graph-tipper-v1-design.md
for the full V1 design (architecture, schema, slicer algorithms, eviction
order) and known V1 limitations (§14).
The implementation plan is at
docs/superpowers/plans/2026-05-13-graph-tipper-v1.md.