twiddle-standalone: When JBoss Killed Its Best CLI Tool
Hook
When Red Hat released JBoss AS7 in 2011, they quietly removed one of the most beloved tools in every system administrator's arsenal: the twiddle JMX command-line interface. Thousands of production scripts suddenly had no path forward.
Context
For years, JBoss Application Server bundled a deceptively simple tool called twiddle—a command-line JMX client that let administrators query server metrics, invoke MBeans, and automate operations without writing Java code. System administrators loved it because they could script server health checks, trigger garbage collection, or modify runtime configurations with straightforward shell commands. It was the swiss army knife for JBoss operations teams.
When JBoss AS7 was rebranded as WildFly and underwent a massive architectural overhaul, Red Hat made a controversial decision: they deprecated twiddle in favor of the new jboss-cli tool. While jboss-cli was more powerful and aligned with the new management model, it wasn't backward compatible. Organizations running hybrid environments—some servers on JBoss AS 6, others migrating to AS7—found themselves maintaining two completely different operational toolchains. The swesource/twiddle-standalone repository emerged as a pragmatic solution: extract the original twiddle tool from JBoss AS 6.1.0.Final, repackage it with all necessary JARs, and make it work against modern servers through protocol adapters.
Technical Insight
The genius of twiddle-standalone lies in its minimalist repackaging strategy. Rather than rewriting the JMX client from scratch, the authors extracted the original twiddle.sh script and supporting JAR files from JBoss AS 6.1.0.Final, then created a wrapper architecture that handles protocol negotiation. The core insight was recognizing that JMX itself hadn't changed—only the transport protocols evolved.
The tool operates through a two-layer architecture. For legacy JBoss AS 6 servers using the standard JMX remoting protocol, twiddle-standalone is truly self-contained—all necessary JARs are bundled in the lib/ directory. For modern WildFly servers using the remoting-jmx protocol, it dynamically constructs the classpath by referencing modules from your local WildFly installation via the JBOSS_HOME environment variable. Here's how a typical invocation looks:
export JBOSS_HOME=/opt/wildfly-8.0.0.Final
./twiddle.sh -s service:jmx:remoting-jmx://localhost:9999 \
get "jboss.as:subsystem=datasources,data-source=ExampleDS" \
statistics-enabled
This command queries whether statistics are enabled on the ExampleDS datasource. The -s flag specifies the JMX service URL, and the protocol prefix (remoting-jmx://) triggers the dynamic classpath construction. The wrapper script detects this protocol and appends WildFly's remoting JARs to the classpath before invoking the original twiddle client.
The protocol detection happens in the shell script through simple string matching. When you examine the wrapper code, you'll find logic that parses the service URL and conditionally adds JAR paths:
if [[ $SERVICE_URL == *"remoting-jmx"* ]]; then
if [ -z "$JBOSS_HOME" ]; then
echo "ERROR: JBOSS_HOME must be set for remoting-jmx protocol"
exit 1
fi
CLASSPATH="$CLASSPATH:$JBOSS_HOME/modules/system/layers/base/org/jboss/remoting-jmx/main/*"
CLASSPATH="$CLASSPATH:$JBOSS_HOME/modules/system/layers/base/org/jboss/remoting/main/*"
fi
This conditional classpath construction is what allows twiddle-standalone to bridge the gap between JBoss AS 6 and WildFly 8 without maintaining separate codebases. It's essentially a shim layer that translates between different JMX transport implementations.
For automation scenarios, the real power emerges when you chain twiddle commands in shell scripts. Unlike GUI tools like JConsole or VisualVM, twiddle returns plain text that's trivially parseable with standard Unix tools:
#!/bin/bash
# Check heap usage across multiple servers
for server in app01 app02 app03; do
heap_used=$(./twiddle.sh -s service:jmx:remoting-jmx://${server}:9999 \
get "java.lang:type=Memory" HeapMemoryUsage | \
grep "used" | awk '{print $3}')
echo "${server}: ${heap_used} bytes"
done
This script queries the heap memory usage on three servers and extracts just the numeric value—something that would require significant boilerplate in Java or even with jboss-cli's batch processing. The Unix philosophy of small, composable tools is what made twiddle irreplaceable for operations teams.
The architectural limitation is that this approach requires maintaining version-specific protocol JARs. The repository was last updated for WildFly 8.0.0.Beta1, and WildFly's module structure has evolved significantly since 2014. Modern WildFly versions (10+) reorganized the module paths, meaning the hardcoded paths in the wrapper script will fail against contemporary installations. You'd need to manually update the module references for each WildFly version you target.
Gotcha
Despite the "standalone" branding, this tool isn't truly standalone when working with modern WildFly servers. You must have a local WildFly installation to provide the remoting-jmx protocol JARs, which defeats the purpose if you're trying to create a lightweight monitoring container or run operations from a bastion host without deploying a full application server. This creates an awkward deployment scenario where your monitoring tooling has the same disk footprint as the servers you're monitoring.
The second gotcha is temporal fragility. The repository hasn't been updated since 2014, freezing it at WildFly 8.0.0.Beta1 compatibility. If you're running WildFly 10+ or any recent JBoss EAP version, you'll encounter module path mismatches and potentially incompatible remoting protocol versions. The README mentions that JBoss EAP users need to "edit the script file and add the correct version of the modules," which is a polite way of saying you're on your own for maintenance. Protocol-level changes in WildFly's management subsystem could also break the JMX invocations themselves, not just the classpath construction. You're essentially maintaining a fork of an unmaintained tool, which is rarely a sustainable operations strategy.
Verdict
Use if: You're maintaining legacy JBoss AS 6 or early WildFly 8 infrastructure where existing automation scripts already use twiddle syntax, and rewriting them to jboss-cli would be prohibitively expensive. It's also reasonable if you're running hybrid environments during a multi-year migration from AS 6 to AS 7, where standardizing on one tool reduces cognitive overhead for your operations team. The shell-script composability makes it ideal for simple health checks in environments where deploying full monitoring agents is overkill. Skip if: You're working with WildFly 10 or later, starting greenfield projects, or need a truly portable tool without external dependencies. Modern environments are better served by jboss-cli for native operations, jmxterm for genuinely standalone JMX access, or Jolokia for REST-based monitoring that integrates cleanly with container orchestration platforms. The maintenance burden of updating protocol JARs and module paths for each WildFly version outweighs the convenience of familiar syntax unless you're specifically preserving legacy tooling.