Use jackknife Maven plugin to explore JARs, search types and members, decompile classes, inspect annotations, and instrument bytecode. Trigger when the user needs to: investigate a JAR or dependency; find where a specific class, interface, annotation, or package is defined; locate which JAR provides a type (ClassNotFoundException, NoSuchMethodError, classpath conflicts); decompile or inspect bytecode of a class.
From javanpx claudepluginhub wesleyegberto/software-engineering-skills --plugin javaThis skill uses the workspace's default tool permissions.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Guides agent creation for Claude Code plugins with file templates, frontmatter specs (name, description, model), triggering examples, system prompts, and best practices.
Adicione o grupo do plugin ao ~/.m2/settings.xml para usar o comando curto mvn jackknife:* sem prefixo de grupo:
<settings>
<pluginGroups>
<pluginGroup>org.tomitribe.jackknife</pluginGroup>
</pluginGroups>
</settings>
Sem essa configuração, os comandos precisam do prefixo completo:
mvn org.tomitribe.jackknife:jackknife-maven-plugin:instrument ...
Two capabilities for working with Java dependencies:
Manifests list every class in every dependency jar. One class name per line.
Grep "CustomField" .jackknife/manifest/
This tells you which jar contains the class and its full package name.
If the class isn't a project dependency, search the local Maven repository:
mvn jackknife:index -Dclass=com.fasterxml.jackson.databind.ObjectMapper
This searches ~/.m2/repository using the package name to narrow the search, finds the latest version, and indexes the jar. The class is then available in the manifest and can be decompiled.
For broader searches across a library family:
mvn jackknife:index -Dscope=repo -Dfilter="**jackson**"
This indexes the latest version of every jar whose path matches the
filter. Use ** to match across directory boundaries.
Check if the class has already been decompiled:
Glob .jackknife/source/**/<ClassName>.java
If found, read it directly. If not, decompile the entire jar (one-time, ~3-5s):
mvn jackknife:decompile -Dclass=com.example.MyClass
Every class in that jar is now available as a .java file. All subsequent reads are direct file access — no Maven invocation needed.
Grep "META-INF/services" .jackknife/manifest/
.jackknife/
├── manifest/ Class listings (all jars, sub-second)
│ └── <groupId>/
│ └── <artifact>-<version>.jar.manifest
├── source/ Decompiled source (per-jar, on demand)
│ └── <groupId>/
│ └── <artifact>-<version>/
│ └── com/example/MyClass.java
├── instrument/ Pending instrumentation configs
├── modified/ Patched jars (applied on next build)
└── USAGE.md This file
mvn test — structured JSON output shows exactly what happenedmvn jackknife:clean -Dpath=modifiedmvn jackknife:instrument -Dmethod="com.example.Foo.bar(java.lang.String,int)"
| Input | What gets instrumented |
|---|---|
com.example.Foo.bar(String,int) | That one method |
com.example.Foo.bar | All overloads of bar |
bar(String,int) | bar(String,int) in any class |
mvn jackknife:instrument -Dmethod="com.example.Foo.bar" -Dmode=timing
mvn test
The next build automatically applies the instrumentation. No special flags.
Jackknife can also instrument your own classes in src/main/ or src/test/.
If the class isn't found in dependency manifests, it checks your project source:
mvn jackknife:instrument -Dclass=com.example.MyService -Dmethod=process
The enhance goal (bound to process-test-classes) modifies the compiled
bytecode in target/classes/ and target/test-classes/ in place. Tests run
against the enhanced bytecode automatically.
Every instrumented call produces one line prefixed with JACKKNIFE:
JACKKNIFE {"event":"register","mode":"debug","method":"org.tomitribe.util.Join.join"}
JACKKNIFE {"event":"call","time":"12.3us","class":"Join","method":"join","args":[", ",["x","y","z"]],"return":"x, y, z"}
The register line confirms instrumentation is active. If you see the register event but no call events, the method was never called by your test.
Grep for all instrumented calls:
Grep "JACKKNIFE" target/surefire-reports/
| Field | Description |
|---|---|
event | "register" or "call" |
time | Elapsed time (ns, us, ms, s) |
class | Simple class name |
method | Method name |
args | JSON array of argument values |
return | Return value (absent on exception) |
exception | {"type":"...","message":"..."} (absent on success) |
status | "returned" or "thrown" (on file-reference lines) |
file | Capture file path (when values too large for one line) |
Strings are JSON-quoted, numbers are bare, null is null, booleans are bare.
Copy values directly from the "return" field into assertEquals:
// From output: "return":"a and b and c"
assertEquals("a and b and c", result);
// From output: "return":42
assertEquals(42, result);
// From output: "return":null
assertNull(result);
When arguments or return values are too large for a single line, the full JSON event is written to a capture file:
JACKKNIFE {"event":"call","time":"2.3ms","class":"Join","method":"join","status":"returned","file":"target/jackknife/captures/capture-0012.txt"}
The console line shows timing, method, and status for quick scanning. Read the capture file for the complete JSON event with all argument and return values.
mvn jackknife:clean # remove all of .jackknife/
mvn jackknife:clean -Dpath=modified # stop instrumentation, keep manifests
mvn jackknife:clean -Dpath=modified/org.tomitribe # remove one groupId's patches
mvn jackknife:clean -Dpath=source # clear decompile cache
After cleaning modified/, the next build uses original unmodified dependencies.