Jackknife
A Maven plugin for inspecting, decompiling, and instrumenting Java jar dependencies
Install / Use
/learn @tomitribe/JackknifeREADME
= Jackknife
A Maven plugin that lets https://claude.ai/claude-code[Claude Code] inspect, decompile, and instrument classes in your jar dependencies.
- No source jars required — decompile any dependency on the classpath
- No System.out.println — instrument methods for args, return values, timing
- No dirty diffs — instrumentation is bytecode-level, source code untouched
- No forgotten debug code — delete
.jackknife/and everything reverts
One mvn command bootstraps everything; after that, Claude reads files directly with zero Maven overhead.
== Commands
[cols="1,3"]
|===
| mvn jackknife:index | Build lightweight manifests of all dependency jars (sub-second). Generates .jackknife/USAGE.md with full instructions for Claude.
| mvn jackknife:decompile -Dclass=... | Decompile a class. First request decompiles the entire jar; subsequent reads are instant file access.
| mvn jackknife:instrument -Dmethod=... -Dmode=... | Instrument methods for runtime observation (debug or timing mode).
|===
After mvn jackknife:index, Claude greps the manifests and reads decompiled source directly — no further Maven invocations needed for most lookups.
== Setup
Three steps, once per machine and once per parent pom.
=== 1. CLAUDE.md
Add to your global ~/.claude/CLAUDE.md:
Jackknife
- When you need to inspect, decompile, or find classes in jar dependencies,
run
mvn jackknife:indexin the project. This generates.jackknife/USAGE.mdwith full instructions. Read that file — it has everything you need.
=== 2. Maven settings
Add the plugin group to ~/.m2/settings.xml so you can use the shorthand mvn jackknife:...:
[source,xml]
<pluginGroups> <pluginGroup>org.tomitribe.jackknife</pluginGroup> </pluginGroups> ----=== 3. Parent pom
Add the jackknife profile to your parent pom. It auto-activates when a .jackknife/ directory exists and does nothing otherwise:
[source,xml]
<profile> <id>jackknife</id> <activation> <file><exists>.jackknife</exists></file> </activation> <build> <plugins> <plugin> <groupId>org.tomitribe.jackknife</groupId> <artifactId>jackknife-maven-plugin</artifactId> <version>0.2</version> <executions> <execution> <goals> <goal>process</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </profile> ----Tomitribe projects: already included in org.tomitribe:oss-parent:14+ and com.tomitribe:tomitribe-parent:14+.
=== 4. .gitignore
Add .jackknife/ to your .gitignore.
== How It Works
=== Manifest + Decompile (two-tier architecture)
Jackknife uses two tiers, optimized for minimal overhead:
- Manifests (all jars, sub-second) — lightweight class name listings. Enough to find which jar has a class and search across the classpath.
- Decompiled source (per jar, on demand) — full https://github.com/Vineflower/vineflower[Vineflower] decompilation. Triggered on first request for any class in a jar. Every class in that jar is written as an individual
.javafile for direct read access.
After the first decompile of a jar, Claude reads .jackknife/source/<groupId>/<artifact>/<path>/MyClass.java directly. No Maven, no startup overhead, no output noise.
=== Instrumentation
Jackknife renames instrumented methods (e.g., process becomes jackknife$process) and generates a wrapper that delegates to a java.lang.reflect.InvocationHandler. The handler chain is composable:
TimingHandler -> DebugHandler -> ProceedHandler
- TimingHandler measures elapsed time
- DebugHandler logs args, return values, and exceptions
- ProceedHandler calls the renamed original method via reflection
Each handler wraps the next. Adding new capabilities is just writing a new InvocationHandler.
Large captured values (over threshold or containing newlines) are written to target/jackknife/captures/ with a file reference in the console output — Claude reads the file directly for test assertions.
=== Filesystem as state machine
.jackknife/ +-- manifest/ Class listings (all jars, sub-second) | +-- <groupId>/ | +-- <artifact>.jar.manifest +-- source/ Decompiled source (per jar, on demand) | +-- <groupId>/ | +-- <artifact>-<version>/ | +-- com/example/MyClass.java +-- instrument/ Instrumentation inbox | +-- <groupId>/ | +-- <artifact>.jar.properties +-- modified/ Patched jars + receipts | +-- <groupId>/ | +-- <artifact>.jar | +-- <artifact>.jar.properties +-- USAGE.md Auto-generated reference (do not edit)
- File in
instrument/-> needs processing - File in
modified/-> done, actively swapped in - File deleted -> reverted
rm -rf .jackknife/-> fully clean
== Requirements
- Java 17+
- Maven 3.9+
== License
Apache License 2.0
