<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mohammad Mostafa Dastjerdi</title>
    <description>The latest articles on DEV Community by Mohammad Mostafa Dastjerdi (@mohammadmd1383).</description>
    <link>https://dev.to/mohammadmd1383</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4246260%2Ff52d8fb5-cdba-46de-b930-e926edf84a2f.jpg</url>
      <title>DEV Community: Mohammad Mostafa Dastjerdi</title>
      <link>https://dev.to/mohammadmd1383</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mohammadmd1383"/>
    <language>en</language>
    <item>
      <title>Give your AI coding agent an IDE for Java and Kotlin jars (with jdx)</title>
      <dc:creator>Mohammad Mostafa Dastjerdi</dc:creator>
      <pubDate>Sun, 15 Nov 2026 16:44:17 +0000</pubDate>
      <link>https://dev.to/mohammadmd1383/give-your-ai-coding-agent-an-ide-for-java-and-kotlin-jars-with-jdx-39h</link>
      <guid>https://dev.to/mohammadmd1383/give-your-ai-coding-agent-an-ide-for-java-and-kotlin-jars-with-jdx-39h</guid>
      <description>&lt;p&gt;AI coding agents are good at writing JVM code. Reading it is another story.&lt;/p&gt;

&lt;p&gt;Ask an agent what a method in one of your dependencies does and watch the transcript: it unzips the jar, runs &lt;code&gt;javap&lt;/code&gt;, greps the output, and then reads an entire source file into its context window. &lt;code&gt;javap&lt;/code&gt; gives it erased signatures and raw opcodes, so it fills the gaps by guessing.&lt;/p&gt;

&lt;p&gt;In this tutorial we'll give the agent the answers an IDE gives a human, using &lt;a href="https://mohammadmd1383.github.io/jdx/" rel="noopener noreferrer"&gt;jdx&lt;/a&gt;, an open-source CLI and MCP server I built for exactly this. Every output below comes from the &lt;a href="https://mohammadmd1383.github.io/jdx/docs/quickstart/" rel="noopener noreferrer"&gt;jdx quickstart&lt;/a&gt;, which is generated by actually running the commands.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you need
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A Java 21+ runtime (Linux, macOS or Windows)&lt;/li&gt;
&lt;li&gt;An MCP-capable agent if you want the integration step (Claude Code, Cursor, Codex CLI, GitHub Copilot CLI, OpenCode, Cline, Kilo Code, Antigravity, or anything else that speaks MCP)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. Install
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl -fsSL https://raw.githubusercontent.com/MohammadMD1383/jdx/main/install-release.sh &lt;span class="o"&gt;|&lt;/span&gt; bash
jdx version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It installs per user (no root) into &lt;code&gt;~/.local/share/jdx&lt;/code&gt; and links &lt;code&gt;~/.local/bin/jdx&lt;/code&gt;. On Windows, use the PowerShell installer from the &lt;a href="https://mohammadmd1383.github.io/jdx/docs/installation/" rel="noopener noreferrer"&gt;installation guide&lt;/a&gt;. &lt;code&gt;jdx doctor&lt;/code&gt; checks your environment if anything looks off.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Releases are unsigned, so macOS Gatekeeper and Windows SmartScreen will warn on first run. The installation guide shows how to clear it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  2. Ask the JDK something, with zero setup
&lt;/h2&gt;

&lt;p&gt;The running JDK is always on the classpath:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;$ jdx members java.util.HashMap --limit 5
members of java.util.HashMap
constructors declared on java.util.HashMap:
  constructor public HashMap&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  constructor public HashMap&lt;span class="o"&gt;(&lt;/span&gt;int initialCapacity&lt;span class="o"&gt;)&lt;/span&gt;
  constructor public HashMap&lt;span class="o"&gt;(&lt;/span&gt;int initialCapacity, float loadFactor&lt;span class="o"&gt;)&lt;/span&gt;
  constructor public HashMap&lt;span class="o"&gt;(&lt;/span&gt;java.util.Map&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;? extends K, ? extends V&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; m&lt;span class="o"&gt;)&lt;/span&gt;
methods declared on java.util.HashMap:
  method public V compute&lt;span class="o"&gt;(&lt;/span&gt;K key, java.util.function.BiFunction&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;? super K, ? super V, ? extends V&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; remappingFunction&lt;span class="o"&gt;)&lt;/span&gt;
+ 7 from java.lang.Object &lt;span class="o"&gt;(&lt;/span&gt;--from java.lang.Object to expand&lt;span class="o"&gt;)&lt;/span&gt;
5 of 53 members shown &lt;span class="o"&gt;(&lt;/span&gt;--limit 53 to see more&lt;span class="o"&gt;)&lt;/span&gt;
source: java.base &lt;span class="o"&gt;(&lt;/span&gt;jrt&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things matter here for an agent. The output is &lt;strong&gt;bounded&lt;/strong&gt;, and the footer says exactly what was cut and how to get the rest. And the &lt;code&gt;source:&lt;/code&gt; line says where the answer came from.&lt;/p&gt;

&lt;p&gt;Now read one method, and only that method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;$ jdx body &lt;span class="s1"&gt;'java.util.HashMap#get(java.lang.Object)'&lt;/span&gt;
java.util.HashMap#get&lt;span class="o"&gt;(&lt;/span&gt;java.lang.Object&lt;span class="o"&gt;)&lt;/span&gt;
  source: src.zip · java.base/java/util/HashMap.java:562-565
    public V get&lt;span class="o"&gt;(&lt;/span&gt;Object key&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        Node&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;K,V&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; e&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nb"&gt;return&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;e &lt;span class="o"&gt;=&lt;/span&gt; getNode&lt;span class="o"&gt;(&lt;/span&gt;key&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; null ? null : e.value&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
next: jdx show java.util.HashMap
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quote references in your shell: &lt;code&gt;#&lt;/code&gt;, &lt;code&gt;(&lt;/code&gt; and &lt;code&gt;$&lt;/code&gt; are shell syntax.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Ask about a library by its Maven coordinate
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;--coord&lt;/code&gt; resolves a library from your local Gradle and Maven caches. &lt;code&gt;--fetch&lt;/code&gt; allows downloading it (and its &lt;code&gt;-sources.jar&lt;/code&gt;) from Maven Central once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;$ jdx body &lt;span class="s1"&gt;'com.google.gson.Gson#toJson(Object)'&lt;/span&gt; --coord com.google.code.gson:gson:2.14.0
com.google.gson.Gson#toJson&lt;span class="o"&gt;(&lt;/span&gt;java.lang.Object&lt;span class="o"&gt;)&lt;/span&gt;
  source: gson-2.14.0-sources.jar · com/google/gson/Gson.java:542-547
  public String toJson&lt;span class="o"&gt;(&lt;/span&gt;Object src&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;src &lt;span class="o"&gt;==&lt;/span&gt; null&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="nb"&gt;return&lt;/span&gt; toJson&lt;span class="o"&gt;(&lt;/span&gt;JsonNull.INSTANCE&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="nb"&gt;return&lt;/span&gt; toJson&lt;span class="o"&gt;(&lt;/span&gt;src, src.getClass&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
next: jdx show com.google.gson.Gson
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Gson is a multi-release jar, so on JDK 21 jdx also prints a &lt;code&gt;warning MULTI_RELEASE_VARIANT&lt;/code&gt; line; I've trimmed it from the outputs in this article.)&lt;/p&gt;

&lt;p&gt;If there is no sources jar, jdx decompiles the method with Vineflower and marks the output &lt;code&gt;⚠ reconstructed&lt;/code&gt;, so the agent knows it's reading a reconstruction. (&lt;code&gt;--engine javap&lt;/code&gt; gives raw bytecode instead.)&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Let it refuse to guess
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;toJson&lt;/code&gt; has eight overloads. jdx won't pick one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;$ jdx body &lt;span class="s1"&gt;'com.google.gson.Gson#toJson'&lt;/span&gt; --coord com.google.code.gson:gson:2.14.0
ambiguous: 8 candidates &lt;span class="k"&gt;for&lt;/span&gt; com.google.gson.Gson#toJson
  com.google.gson.Gson#toJson&lt;span class="o"&gt;(&lt;/span&gt;com.google.gson.JsonElement&lt;span class="o"&gt;)&lt;/span&gt;
  com.google.gson.Gson#toJson&lt;span class="o"&gt;(&lt;/span&gt;com.google.gson.JsonElement, com.google.gson.stream.JsonWriter&lt;span class="o"&gt;)&lt;/span&gt;
  com.google.gson.Gson#toJson&lt;span class="o"&gt;(&lt;/span&gt;com.google.gson.JsonElement, java.lang.Appendable&lt;span class="o"&gt;)&lt;/span&gt;
  com.google.gson.Gson#toJson&lt;span class="o"&gt;(&lt;/span&gt;java.lang.Object&lt;span class="o"&gt;)&lt;/span&gt;
  com.google.gson.Gson#toJson&lt;span class="o"&gt;(&lt;/span&gt;java.lang.Object, java.lang.Appendable&lt;span class="o"&gt;)&lt;/span&gt;
  com.google.gson.Gson#toJson&lt;span class="o"&gt;(&lt;/span&gt;java.lang.Object, java.lang.reflect.Type&lt;span class="o"&gt;)&lt;/span&gt;
  com.google.gson.Gson#toJson&lt;span class="o"&gt;(&lt;/span&gt;java.lang.Object, java.lang.reflect.Type, com.google.gson.stream.JsonWriter&lt;span class="o"&gt;)&lt;/span&gt;
  com.google.gson.Gson#toJson&lt;span class="o"&gt;(&lt;/span&gt;java.lang.Object, java.lang.reflect.Type, java.lang.Appendable&lt;span class="o"&gt;)&lt;/span&gt;
hint: re-run with one of the refs above
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt; 2&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exit code 2 means "ambiguous", and every candidate is a paste-ready reference. An agent can branch on the exit code without parsing prose, and the next call is a copy-paste, not a reconstruction. Other outcomes (not found, no index, bad usage) have their own exit codes, and every command has &lt;code&gt;--json&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Navigate: hierarchy and callers
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;$ jdx hierarchy com.google.gson.JsonElement --coord com.google.code.gson:gson:2.14.0
hierarchy of &lt;span class="s1"&gt;'com.google.gson.JsonElement'&lt;/span&gt;
  supertypes
    extends java.lang.Object  java.base
  subtypes &lt;span class="k"&gt;in&lt;/span&gt; workspace &lt;span class="o"&gt;(&lt;/span&gt;4&lt;span class="o"&gt;)&lt;/span&gt;
    class com.google.gson.JsonArray  gson-2.14.0.jar
    class com.google.gson.JsonNull  gson-2.14.0.jar
    class com.google.gson.JsonObject  gson-2.14.0.jar
    class com.google.gson.JsonPrimitive  gson-2.14.0.jar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;$ jdx callers &lt;span class="s1"&gt;'com.google.gson.JsonParser#parseReader(com.google.gson.stream.JsonReader)'&lt;/span&gt; --coord com.google.code.gson:gson:2.14.0
callers of &lt;span class="s1"&gt;'com.google.gson.JsonParser#parseReader(com.google.gson.stream.JsonReader)'&lt;/span&gt;
  call com.google.gson.JsonParser#parse&lt;span class="o"&gt;(&lt;/span&gt;com.google.gson.stream.JsonReader&lt;span class="o"&gt;)&lt;/span&gt;  gson-2.14.0.jar
  call com.google.gson.JsonParser#parseReader&lt;span class="o"&gt;(&lt;/span&gt;java.io.Reader&lt;span class="o"&gt;)&lt;/span&gt;  gson-2.14.0.jar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;--depth N&lt;/code&gt; follows the call graph transitively (cycle-safe). &lt;code&gt;jdx usages&lt;/code&gt; and &lt;code&gt;jdx implementors&lt;/code&gt; work across every jar on the classpath, not just one. More in &lt;a href="https://mohammadmd1383.github.io/jdx/docs/navigating-code/" rel="noopener noreferrer"&gt;Usages, hierarchy &amp;amp; calls&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Ask what a dependency upgrade breaks
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;$ jdx diff com.google.code.gson:gson:2.11.0 com.google.code.gson:gson:2.14.0 --fetch
api diff com.google.code.gson:gson:2.11.0 -&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; com.google.code.gson:gson:2.14.0 &lt;span class="o"&gt;(&lt;/span&gt;public surface&lt;span class="o"&gt;)&lt;/span&gt;
info  TYPE_ADDED  com.google.gson.internal.GsonTypes
...
info  MEMBER_ADDED  com.google.gson.stream.JsonReader#setNestingLimit&lt;span class="o"&gt;(&lt;/span&gt;int&lt;span class="o"&gt;)&lt;/span&gt;
info  FIELD_CONSTANT_VALUE_CHANGED  com.google.gson.internal.GsonBuildConfig#VERSION: &lt;span class="s2"&gt;"2.11.0"&lt;/span&gt; -&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"2.14.0"&lt;/span&gt;
0 breaking · 0 suspicious · 17 informational · 2 types added · 0 types removed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every finding names a rule (&lt;code&gt;MEMBER_REMOVED&lt;/code&gt;, &lt;code&gt;RETURN_TYPE_CHANGED&lt;/code&gt;, &lt;code&gt;KOTLIN_NULLABILITY_CHANGED&lt;/code&gt;, …) at &lt;code&gt;breaking&lt;/code&gt;, &lt;code&gt;suspicious&lt;/code&gt; or &lt;code&gt;info&lt;/code&gt;. Add &lt;code&gt;--fail-on breaking&lt;/code&gt; and it becomes a CI gate. See &lt;a href="https://mohammadmd1383.github.io/jdx/docs/api-diff/" rel="noopener noreferrer"&gt;API diff for upgrades&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Name your classpath once
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jdx ws create gson --coord com.google.code.gson:gson:2.14.0
jdx -w gson usages com.google.gson.TypeAdapter
jdx ws use gson        &lt;span class="c"&gt;# make it the default&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside a Gradle or Maven project you often need nothing: jdx discovers the project's sources and dependency jars from the local caches, without running the build.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Hand it to your agent
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jdx setup --agent claude-code --scope project   &lt;span class="c"&gt;# then restart Claude Code&lt;/span&gt;
&lt;span class="c"&gt;# or: cursor, codex, copilot, opencode, cline, kilo, antigravity, windsurf, aider&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any other MCP client takes one line of config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"jdx"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"jdx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"mcp"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The MCP server exposes each query as a typed tool (&lt;code&gt;jdx_members&lt;/code&gt;, &lt;code&gt;jdx_body&lt;/code&gt;, &lt;code&gt;jdx_usages&lt;/code&gt;, &lt;code&gt;jdx_callers&lt;/code&gt;, &lt;code&gt;jdx_diff&lt;/code&gt;, …) and keeps the index warm, so queries take about 20 ms instead of about 250 ms for a cold CLI call. If you'd rather use the CLI from your agent, &lt;code&gt;jdx help --agent&lt;/code&gt; prints a compact block to paste into &lt;code&gt;CLAUDE.md&lt;/code&gt; or &lt;code&gt;AGENTS.md&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Per-agent setup pages: &lt;a href="https://mohammadmd1383.github.io/jdx/integrations/claude-code/" rel="noopener noreferrer"&gt;Claude Code&lt;/a&gt;, &lt;a href="https://mohammadmd1383.github.io/jdx/integrations/cursor/" rel="noopener noreferrer"&gt;Cursor&lt;/a&gt;, &lt;a href="https://mohammadmd1383.github.io/jdx/integrations/codex/" rel="noopener noreferrer"&gt;Codex CLI&lt;/a&gt;, &lt;a href="https://mohammadmd1383.github.io/jdx/integrations/" rel="noopener noreferrer"&gt;all integrations&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  New in v1.7.0: the questions IDEs don't answer
&lt;/h2&gt;

&lt;p&gt;Agents also ask things an IDE never made easy. v1.7.0 adds commands for them (see the &lt;a href="https://mohammadmd1383.github.io/jdx/docs/reference/" rel="noopener noreferrer"&gt;command reference&lt;/a&gt; for every flag):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;jdx literals&lt;/code&gt; — search string constants (&lt;code&gt;LDC&lt;/code&gt; loads and &lt;code&gt;ConstantValue&lt;/code&gt; fields) and &lt;code&gt;.properties&lt;/code&gt; keys/values across the workspace: "where does this log message / resource key come from?"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;jdx services&lt;/code&gt; — &lt;code&gt;META-INF/services&lt;/code&gt; SPI providers: "who provides &lt;code&gt;com.foo.Spi&lt;/code&gt;?"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;jdx modules&lt;/code&gt; — JPMS &lt;code&gt;module-info&lt;/code&gt; (requires / exports / opens / uses / provides).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;jdx manifest&lt;/code&gt; and &lt;code&gt;jdx resources&lt;/code&gt; — &lt;code&gt;MANIFEST.MF&lt;/code&gt; attributes and non-class resources (&lt;code&gt;--cat&lt;/code&gt; prints a text resource).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;jdx annotated&lt;/code&gt; — classes and members carrying an annotation, with recipes such as &lt;code&gt;deprecated&lt;/code&gt;, &lt;code&gt;forRemoval&lt;/code&gt;, &lt;code&gt;test&lt;/code&gt; and &lt;code&gt;bean&lt;/code&gt;; &lt;code&gt;jdx usages --where&lt;/code&gt; filters on annotation values.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;callers&lt;/code&gt; is now override-aware by default (&lt;code&gt;--exact&lt;/code&gt; for invoke-owner matching), bytecode usages carry &lt;code&gt;file:line&lt;/code&gt;, and &lt;code&gt;usages --context&lt;/code&gt; shows inline snippets.&lt;/li&gt;
&lt;li&gt;Kotlin nullability is rendered from &lt;code&gt;@Metadata&lt;/code&gt;, and there's a PowerShell installer for Windows.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Does it actually save context?
&lt;/h2&gt;

&lt;p&gt;On one task from the README, "list Gson's API, then show only &lt;code&gt;toJson(Object)&lt;/code&gt;" on gson-2.14.0:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Calls&lt;/th&gt;
&lt;th&gt;Output in context&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;unzip&lt;/code&gt; + &lt;code&gt;javap&lt;/code&gt; + &lt;code&gt;grep&lt;/code&gt; + &lt;code&gt;sed&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;~17.5 KB (~4.4k tokens), and &lt;code&gt;head -200&lt;/code&gt; missed the method entirely&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;jdx members&lt;/code&gt; + &lt;code&gt;jdx body&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;~4.6 KB (~1.2k tokens)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The method body alone is 267 bytes, against 60,590 for &lt;code&gt;javap -c&lt;/code&gt; and 58,251 for the full &lt;code&gt;Gson.java&lt;/code&gt;. That's one task, not a benchmark suite, but you can rerun it yourself with &lt;code&gt;sh docs/bench-compare.sh&lt;/code&gt; from the repo.&lt;/p&gt;

&lt;h2&gt;
  
  
  A note on safety
&lt;/h2&gt;

&lt;p&gt;jdx parses bytecode with ASM and never loads the classes it inspects, so no static initialiser or other code from those jars runs. It only touches the network when you pass &lt;code&gt;--fetch&lt;/code&gt;, run &lt;code&gt;jdx upgrade&lt;/code&gt;, or run &lt;code&gt;jdx kotlin install&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Kotlin
&lt;/h2&gt;

&lt;p&gt;Kotlin binaries are read through &lt;code&gt;@Metadata&lt;/code&gt;, so the agent sees nullability, &lt;code&gt;suspend&lt;/code&gt; functions, properties, default arguments and &lt;code&gt;@JvmName&lt;/code&gt; mappings instead of the JVM projection. Reading Kotlin sources needs a one-time &lt;code&gt;jdx kotlin install&lt;/code&gt;. Details in &lt;a href="https://mohammadmd1383.github.io/jdx/docs/reading-code/#kotlin" rel="noopener noreferrer"&gt;Reading code&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;jdx is free and open source (Apache-2.0). Start with the &lt;a href="https://mohammadmd1383.github.io/jdx/docs/quickstart/" rel="noopener noreferrer"&gt;quickstart&lt;/a&gt;, browse the &lt;a href="https://mohammadmd1383.github.io/jdx/" rel="noopener noreferrer"&gt;docs&lt;/a&gt;, and if it gives your agent a wrong answer, please &lt;a href="https://github.com/MohammadMD1383/jdx/issues" rel="noopener noreferrer"&gt;open an issue&lt;/a&gt; with the command and what you expected.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: &lt;a href="https://github.com/MohammadMD1383/jdx" rel="noopener noreferrer"&gt;github.com/MohammadMD1383/jdx&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>kotlin</category>
      <category>ai</category>
      <category>mcp</category>
    </item>
  </channel>
</rss>
