Skip to content

tomitribe/jackknife

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

44 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Jackknife

A Maven plugin that lets 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

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:index` in the project. This generates `.jackknife/USAGE.md`
  with 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:…​:

<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:

<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:

  1. Manifests (all jars, sub-second) — lightweight class name listings. Enough to find which jar has a class and search across the classpath.

  2. Decompiled source (per jar, on demand) — full Vineflower decompilation. Triggered on first request for any class in a jar. Every class in that jar is written as an individual .java file 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

About

A Maven plugin for inspecting, decompiling, and instrumenting Java jar dependencies

Resources

License

Stars

Watchers

Forks

Packages