Why? It's not well suited to it - fundamentally the language semantics lead to very large distributions, slow startup and expecting a runtime on the machine. Okay, I hear this can be solved by Graal, but that's a whole piece of its own complexity that you'd never have to worry about with a tool written in something like Go.
Python has many similar properties, but at least there I can understand that Python is a 'pretty' language to write things in. Java has never been something that I have ever wanted to choose, and far, far less so when there's a big hill to climb like this.
I guess I fundamentally disagree with all the statements in the article like "This needs to change". I don't think it does. I would much rather than people wrote CLIs in Go or Rust than Java, 100% of the time the latter has been more painful for me to consume.
I spent a long time caring about JVM startup time and CLI suitability (and wrote nailgun [0] over 20 years ago and jsap [1] shortly after specifically because of it), so it's pretty wild to see how far things have come. Modern JVM startup speed and GraalVM native-image have eliminated most of the old excuses. jlink+jpackage help a lot with distribution, and JBang takes it to another level. I've used JBang before but still learned some new tricks from this post. Honestly, it feels like what JNLP/WebStart should have evolved into.
I'm not convinced that requiring users to already have JBang installed is the best adoption strategy. But a native package that pulls in JBang if needed and drops a shim launcher/desktop shortcut seems like a natural approach and maybe a fun project.
On the TUI side, java could really use something as approachable and pretty as go's Charmbracelet [2]. Once developers regularly see compelling java TUIs in the wild, it'll change their perception.
The tooling is here, or at least really close. At this point, it's mostly outdated opinions holding java back in the terminal.
Java will never become a player in CLI tooling until build packaging becomes first class. Go, Rust, and other languages are so common because their build tooling is dead simple. You can easily get a single file distributable in a single command. go build, cargo build, dotnet publish —-self-contained.
Java on the other hand makes it impossible to get a single distributable. There is no way to get your jar + the vm into a binary. You could use graal native image, but build times are super slow, use too many resources, and it’s non-trivial to get working.
Build tooling in the Java ecosystem just isn’t good enough.
I think the python counterexample speaks a lot. A lot of languages "hide" their footprint in /usr/local or in a venv somewhere; out of sight, out of mind.
The JVM installs cleanly and is self contained, but any artifacts, by default, are not shared system wide as this _always_ have been seen as a security risk. The hot term for it today is "supply chain attack".
Instead, most Java programs tow their dependencies, giving it a bloated feel because its all just there, present in front of you, stored and running as your own user.
I know Python has been big in the space for longer than uv's existence, but uv (https://docs.astral.sh/uv/) has made Python packaging dead simple to me
I don't think uv makes distribution simple? Unless I've missed something, it doesn't do anything out of the box to help you produce a standalone artifact - it builds wheels but those are only useful for a user that already has python and pip, and don't do anything to deal with Python version drift etc.
uv can install a version of python of your choosing in addition to pulling the specific versions of libraries specified in your lockfile. it's extremely dummy-resistant.
Java SHOULD never become a player in anything more until Oracle stops being such a threat. Oracle just wants to be a parasite on companies that actually build.
I gave up on Java when Oracle took over, because I thought that it was such a horrific move, but, to their credit, they haven't ruined it for everyone (yet)
They've kept it alive, allowed it to grow, and innovate, even let Green threads back in.
I'm not planning on going back to Java, but that's no longer because Oracle.
Yeah it’s funny how “Java runs everywhere” was a huge selling point of the JVM. But now it’s not even included in macOS by default, so if you want somebody to use you Java/clojure CLI they have to install Java. And that will raise eyebrows and make people think “what is this, 2010??”
Bundling the JRE in the bundle typically results in something that is not redistributable with the default OpenJDK license: The Java ecosystem is heavily tilted towards the Apache license, but Hotspot is licensed under the GPL v2 only (no classpath exception). The Apache license and older GPL versions (before 3) are generally assumed to be incompatible.
You're asking about a fundamentally different thing.
An app bundle (.app, .rpm, .deb, .msi/.exe etc.) are things jpackage can build for you and are a single shippable artifact for a user with a JRE included so they don't need to do that. It's designed to make it easy to ship Java applications around.
I'm not asking about a fundamentally different thing. The success of other languages isn't because they produce installers. Have you tried native image for a non-trivial application? I've been using it since it came out; I was the first adopter of native-image for Quarkus on Windows. I even wrote the documentation for it at the time. It is not trivial to use, the compile times are extremely long, and the resources it requires are sometimes more than a developers machine can provide.
> There is no way to get your jar + the vm into a binary.
My text editor, KeenWrite[1], offered binaries for Linux, macOS, and Windows. The Windows binary was axed due code signing costs and requiring third-party builds, rather than any technical issues with cross-platform packaging.
One way is to create self-extracting executable binaries using a tool such as warp[2]. I've built an installer script[3] (install.sh) to create platform-specific launchers. Running `time keenwrite.bin --version` on Linux shows 0.327s; after the first run, subsequent launches are quick.
I worked at a couple of startups that were mostly Java based and had several CLI tools. The focus was building "fat jars" then running them with "java -jar ...", or running scripts that did that. The Java VM was a system dependency and getting it baked into the binary just wasn't a practical concern.
I work at a startup that ships a Java cli to our clients. It is a giant pain in the butt. There are constant support requests from users that are using the wrong version of Java, too old or too new. Sometimes they have to wait weeks for authorization to even install the Java runtime. IT departments are extremely strict about installing Java.
> IT departments are extremely strict about installing Java.
Understandably so, given that some Java runtimes (most notably, Oracle's) require a paid license for commercial use. Having users installing that can get the company in hot water.
I could see how that could be annoying. My experience was with internal apps whee we managed all the infrastructure. Some IT departments are often extremely strict about installing anything. Some won't even let you access a web site without it being proxied through something like ZScaler.
It's not dynamic linking, despite excellent support for very late binding in historic Java versions. (Newer versions require specific launcher configurations to use certain platform features, which breaks late loading of classes that use those features.)
Non-trivial, doesn’t work with standard build tooling, and unless something has changed it produces installers that extract into several different files. You don’t just get a standalone statically linked binary that you can hand off.
It combines a port of BubbleTea from Go, and Textual and other inspired rewrites of other functionality.
It’s a fork of someone’s earlier work that I sought to expand/stabilize.
I built a beautifully simple LLM chat interface with full dialog windows, animations, and full support for keyboard and mouse interactivity parity, showing what this Java library is capable of.
Java startup time shouldn't really be an issue with a terminal program. I have written some pretty complex Java and Rust and C++ terminal programs, they are basically indistinguishable on run time. The reason Java starts up slow for most people is that they are running webapps with Spring and 50 dependencies and loading Tomcat, not because they are just booting a JVM and running through some functions.
Getting AoT compiled Java programs has been a life saver. Running java -jar main.java -foo -bar is very annoying and not friendly. It needs to be packaged so you can just run tool -foo -bar
+1 on the AOT compilation. I was surprised there is still a noticeable difference between Graal and a "standard" JVM even if you have eliminated all the other cruft. Both are practically usable, no question, but the latter really felt "instant".
I was amazed when I tried Graal the first time, but also had to think that this is probably what C/C++ or Rust devs just see as "normal".
I've been a Java developer for twenty years. I've used it for everything front front end to distributed systems. I've built gradle plug-ins and clips with JAVA. I have every shortcut in intellij memorized.
Even with all this it takes me substantially less time to get go, python, or ts working as a cli. Java cli is a solution looking for a problem
I’m about the same. I’ve had one Java project going for over 10 years. It’s a collection of utilities that I use for work everyday that has grown substantially over the years. It is a CLI program that runs in my Mac, Linux servers and Linux HPC clusters. It is built with a fat-JAR concatenated to a shell stub in front that makes it effectively a single-file install. I also wrote a complete library for defining CLI programs. It is pretty easy to use, but it relies on reflection and annotations, so Graal has been difficult to get working (or was the last time I tried).
All of that to say, I’m also familiar with the problem.
For the past 3-4 years I’ve reached more for Go to my new CLI projects. Small differences in installed Java versions across clusters can be a problem, but for me the biggest issue is dealing with JVM arguments. I writing code for working with genomics data files. Sometimes these are large, and sometimes they are small. And I hate having to tell both my job scheduler (SLURM mainly these days) and the JVM how much memory to use.
This isn’t a problem in Go. So, that’s the language I gravitate to these days.
That's a great way of putting it. I'm a Java developer also; I'm most comfortable with Java and, dare I say, I like Java. But Java would be far down the list of tools I'd use to make a CL program.
Same here. Was using Java in the alpha/beta/gamma days. Have built a lot with it. Would not use it for command line tooling by default, only if it happened to be the simplest option (like maybe a library or something does nearly everything needed).
Maybe some of the old beliefs regarding startup time etc are no longer valid. Maybe the programming model isn’t as verbose as it used to be. But I don’t want to distribute a 200MB+ binary. I have colleagues who tell me that c# scripting is so awesome. One only needs .NET installed or use AOT or whatever. Sorry but Go and Rust and good forgive a python script is smaller and mostly easier to read and write then most stuff I seen other languages shoehorning into. I have nothing against Java but it isn’t the right hammer for this problem. At least for me. And I wish people wouldn’t constantly strive for the single language for every problem mindset. Yes in a Java shop it might make more sense to write cli tools and scripts also in Java. But that doesn’t mean it is the most effective toolchain in the long run.
Our Go CLI tools are like 100MB+ and often we bundle them in containers that are in the GB+ territory. Nobody cares or at least has cared enough to tell us to minimize stuff.
As a practical example for a Java-based CLI tool in the wild, here's kcctl, a command line client for Kafka Connect: https://github.com/kcctl/kcctl/. It's a native binary (via GraalVM), starting up in a few ms, so that it actually be invoked during tab completions and do a round-trip to the Kafka Connect REST API without any noticeable delay whatsoever.
Installation is via brew, so same experience as for all the other CLI tools you're using. The binary size is on the higher end (52 MB), but I don't think this makes any relevant difference for practical purposes. Build times with GraalVM are still not ideal (though getting better). Cross compilation is another sore point, I'm managing it via platform-specific GitHub Action runners. From a user perspective, non of this matters, I'd bet most users don't know that kcctl is written in Java.
Babashka has been available and has had a growing following since 2019. I have many babashka shebang deployed scripts with fast startup. While I would never desire to use Java syntax, AOT capable JVM based Clojure libraries are available and can be loaded dynamically. Built via graal. https://babashka.org
babashka comes with some excellent namespaces. Highlights include babashka.fs -- a functional and effective wrapper around Java file system classes, and babashka.process -- useful functions for interacting with shell processes, i/o and pipelines. I find babashka packaging to be minimal and much more convenient than python for scripting. No massive virtual environments, just a smaller than 70mb binary needs to be available on my machine. Borkdude FTW.
The article makes no compelling points to me as an avid user of these applications.
I would rather shove ice picks covered in lemon juice than provide Java or Ellison anymore room in the digital ecosystem. And I’m not talking politics here wrt Ellison, just awful
Someone else on the page commented about Oracle. Why are there still people hung up on Oracle or Ellison when if anything, they've helped Java to thrive more.
The real threat has been and continues to be ... Google. They pulled a Microsoft move (that they got busted for) and Google got away with it. Google killed Eclipse as the IDE for Android development and threw that business over to their Russian buddies at JetBrains.
I get the argument from this article that it’s possible.
But I don’t get the argument that this is somehow desirable. Just because it’s possible to smash a square peg into a round hole doesn’t make it a good idea.
My biggest complaint about Java development is the state of LSP/DAP support. I’ve tried writing Java in VS Code, and the support is still very incomplete. There are two features I want the most: (1) automatically downloading source code for dependencies, and (2) pausing all threads when a breakpoint is hit (https://github.com/microsoft/vscode-java-debug/issues/722
).
I can’t find any editor or IDE that comes close to IntelliJ. If we want Java in the terminal, we may also need to think how to write Java in the terminal or are they orthogonal?
I'm not saying we should phase Java out. But it's pretty clear to me that Java was a bad experiment in almost every aspect, and we should at least not add new use cases for it.
So no. No, please god no, no Java in the terminal.
Agree, Java also had straight single file execution forever now. Java foo.java. I use it instead of scripts all the time. Solid language with a lot of flexibility, Oracle has done a good job in last few years. Newer Java frameworks are fairly easy and light to use. We have natively image Lambda functions in production. Work well.
A hasty generalization with a little confirmation bias, perhaps?
$ time keenwrite.bin --version
KeenWrite version 3.6.5
Copyright 2016-2025 White Magic Software, Ltd.
user 0m0.329s
From Claude:
> It's worth noting this is a common perception about Java, and there's some historical truth to it (especially with Swing desktop applications from the 2000s). However, the absolute statement "no Java app... ever" is the fallacy - it's an overgeneralization from limited personal experience to a universal claim.
Go was originally designed to make life easier for googlers and make software engineering easy. In 2025, I can attest to the fact that Go is simple. Go is easy. Whether you can accomplish what you want in Go is another story. However, Go has a very basic structure and easy flow. Complexity comes from not understanding the go philosophy.
Yes - Go is both a simpler language than Java which does not lend itself to (nor does the ecosystem tolerate) the kind of architectural malpractice that enterprise Java typically becomes.
Languages lose users when the tooling becomes too heavy.
You have to learn ( and maintain knowledge of ) build tooling, unit test frameworks, tools for front end / back end development, distribution and packaging systems, directory structures to accommodate all those, etc. ad nauseum.
Then something new and shiny comes out, with much smaller tooling. The lure of easy software construction seduces the user.
I've been writing Java utils for the terminal since forever. Mostly because I was extremely familiar with Java. It's never been really slow unless you were loading shitload of classes, like apps that package the entire kitchen sink do or as Clojure does for example. For Clojure now there's Babashka: super quick.
And GraalVM compiled Java is more than speedy.
Back in, say, 2005, two decades ago, on computers from back then, sure, the java startup time from the CLI were noticeable. But on today's computers?
Nowadays when it comes to terminal apps I wrote both Clojure (Babashka), Bash and Java (recently I needed something from a .jar and had no convenient Clojure wrapper and didn't want to bother, so I just wrote my CLI app in Java).
Maybe, maybe, maybe that I do feel the startup time when I run my CLI Java app on Raspberry Pis. Raspberry Pi 2 and 3s that is (for I don't have any newer).
Startup times aren't an issue. But there may be other reasons to prefer other languages to write CLI apps.
There are approximately no use cases that would get me to run a CLI written in Java on my machine, especially if it required having a JVM installed. There's just no reason for it.
The rounding error there is Pkl, which is at least built using Graal Native Image, but (IMO) would _still_ have better adoption if it was written in something else.
That said, if the Java community wanted to port reasonable tooling to their platform, I'm sure Claude could do a reasonable job of getting a decent chunk of BubbleTea and friends bootstrapped.
> That said, if the Java community wanted to port reasonable tooling to their platform, I'm sure Claude could do a reasonable job of getting a decent chunk of BubbleTea and friends bootstrapped.
Assuming JVM installation is not required (to which I agree, it shouldn't be), why would you care which language a CLI tool is written in? I mean, do you even know whether a given binary is implemented in Go, Rust, etc.? I don't see how it makes any meaningful difference from a user perspective.
> Pkl, which is at least built using Graal Native Image, but (IMO) would _still_ have better adoption if it was written in something else.
I concur with Nick, and the last time I programmed Java professionally was late 2024, with all of the latest and greatest frameworks (obviously not my choice) and tooling (which, to be fair to the Java ecosystem, is second to none).
The experience after having spent over a decade primarily doing Go, Rust and Erlang (with a smattering of TypeScript, C#, Python, Swift, C, C++ etc) was the final push over the line to leave that employer.
I'm not sure I'd go so far as to claim it was definitely written by AI (after all, LLMs tend to write the way they do because it reflects their training material), but it does have a large number of suspicious constructions that suggest it could have been:
- "Look, I’m going to say something that might sound crazy...."
- But here’s the thing: there’s nothing stopping us...
- Emdashes. I don't believe that alone they are a tell for AI any more than they are a tell for the cultured, but in combination with other things, maybe.
Well, the year is 2003 and I am on a hot dungeon with bad Air Conditioning, figuring out the correct spells for a black magic ant build. A few years later I am writing tons of XML, first for vanilla J2EE, then for spring. We complained, we wondered, nobody cared until one day we decided "fuck that shit, I don't care if ruby is slow as molasses, I just want the pain to go away!"
Forgive me if in 2026 I get triggered at the mere mention of the phrase "java build".
Lots of us had long relationships with Java, relationships marked by toxicity and abuse. We moved on. Now Java says it is changed, it has matured. Well, it could be true, probably it is even true, but on the other hand, now your toxic ex found out his father, and his name is Larry Ellison.
Why? It's not well suited to it - fundamentally the language semantics lead to very large distributions, slow startup and expecting a runtime on the machine. Okay, I hear this can be solved by Graal, but that's a whole piece of its own complexity that you'd never have to worry about with a tool written in something like Go.
Python has many similar properties, but at least there I can understand that Python is a 'pretty' language to write things in. Java has never been something that I have ever wanted to choose, and far, far less so when there's a big hill to climb like this.
I guess I fundamentally disagree with all the statements in the article like "This needs to change". I don't think it does. I would much rather than people wrote CLIs in Go or Rust than Java, 100% of the time the latter has been more painful for me to consume.
I spent a long time caring about JVM startup time and CLI suitability (and wrote nailgun [0] over 20 years ago and jsap [1] shortly after specifically because of it), so it's pretty wild to see how far things have come. Modern JVM startup speed and GraalVM native-image have eliminated most of the old excuses. jlink+jpackage help a lot with distribution, and JBang takes it to another level. I've used JBang before but still learned some new tricks from this post. Honestly, it feels like what JNLP/WebStart should have evolved into.
I'm not convinced that requiring users to already have JBang installed is the best adoption strategy. But a native package that pulls in JBang if needed and drops a shim launcher/desktop shortcut seems like a natural approach and maybe a fun project.
On the TUI side, java could really use something as approachable and pretty as go's Charmbracelet [2]. Once developers regularly see compelling java TUIs in the wild, it'll change their perception.
The tooling is here, or at least really close. At this point, it's mostly outdated opinions holding java back in the terminal.
[0] https://martiansoftware.com/nailgun
[1] https://martiansoftware.com/jsap/
[2] https://github.com/charmbracelet
Java will never become a player in CLI tooling until build packaging becomes first class. Go, Rust, and other languages are so common because their build tooling is dead simple. You can easily get a single file distributable in a single command. go build, cargo build, dotnet publish —-self-contained.
Java on the other hand makes it impossible to get a single distributable. There is no way to get your jar + the vm into a binary. You could use graal native image, but build times are super slow, use too many resources, and it’s non-trivial to get working.
Build tooling in the Java ecosystem just isn’t good enough.
> Java will never become a player in CLI tooling until build packaging becomes first class.
Python packaging has always been painful and it’s a popular option for CLI regardless.
I don’t think there only rational explanations, technology choices are a lot about culture and dogmas too.
I think the python counterexample speaks a lot. A lot of languages "hide" their footprint in /usr/local or in a venv somewhere; out of sight, out of mind.
The JVM installs cleanly and is self contained, but any artifacts, by default, are not shared system wide as this _always_ have been seen as a security risk. The hot term for it today is "supply chain attack".
Instead, most Java programs tow their dependencies, giving it a bloated feel because its all just there, present in front of you, stored and running as your own user.
I know Python has been big in the space for longer than uv's existence, but uv (https://docs.astral.sh/uv/) has made Python packaging dead simple to me
I don't think uv makes distribution simple? Unless I've missed something, it doesn't do anything out of the box to help you produce a standalone artifact - it builds wheels but those are only useful for a user that already has python and pip, and don't do anything to deal with Python version drift etc.
uv can install a version of python of your choosing in addition to pulling the specific versions of libraries specified in your lockfile. it's extremely dummy-resistant.
> Java on the other hand makes it impossible to get a single distributable.
Heh, I find this very amusing and ironic, seeing how Write Once Run Anywhere was a stated goal with Java, that failed miserably.
Java SHOULD never become a player in anything more until Oracle stops being such a threat. Oracle just wants to be a parasite on companies that actually build.
I gave up on Java when Oracle took over, because I thought that it was such a horrific move, but, to their credit, they haven't ruined it for everyone (yet)
They've kept it alive, allowed it to grow, and innovate, even let Green threads back in.
I'm not planning on going back to Java, but that's no longer because Oracle.
Yeah it’s funny how “Java runs everywhere” was a huge selling point of the JVM. But now it’s not even included in macOS by default, so if you want somebody to use you Java/clojure CLI they have to install Java. And that will raise eyebrows and make people think “what is this, 2010??”
jpackage
It does all of this work for you and its a standard tool that dumps out a platform specific application bundle.
The only people living in 2010 are the ones that choose to live there with incredibly outdated takes on things they dont understand.
Bundling the JRE in the bundle typically results in something that is not redistributable with the default OpenJDK license: The Java ecosystem is heavily tilted towards the Apache license, but Hotspot is licensed under the GPL v2 only (no classpath exception). The Apache license and older GPL versions (before 3) are generally assumed to be incompatible.
Has jpackage been updated to create things that are not installers and don't extract themselves into several files?
You're asking about a fundamentally different thing.
An app bundle (.app, .rpm, .deb, .msi/.exe etc.) are things jpackage can build for you and are a single shippable artifact for a user with a JRE included so they don't need to do that. It's designed to make it easy to ship Java applications around.
If you want a fully statically linked binary you're diving into graalvm and native-image: https://www.graalvm.org/latest/reference-manual/native-image.... This will give you what you want which is basically something you can wget and chmod +x.
I'm not asking about a fundamentally different thing. The success of other languages isn't because they produce installers. Have you tried native image for a non-trivial application? I've been using it since it came out; I was the first adopter of native-image for Quarkus on Windows. I even wrote the documentation for it at the time. It is not trivial to use, the compile times are extremely long, and the resources it requires are sometimes more than a developers machine can provide.
Every time I've tried to get native-image working with anything more than a basic Swing app it has been absolute hell.
graalvm native binaries?
Openjdk also dropped a lot of OS support, it basically just windows, Mac and Linux now. And AIX.
No more FreeBSD, Solaris, open Solaris (illumos smartos etc).
> There is no way to get your jar + the vm into a binary.
My text editor, KeenWrite[1], offered binaries for Linux, macOS, and Windows. The Windows binary was axed due code signing costs and requiring third-party builds, rather than any technical issues with cross-platform packaging.
One way is to create self-extracting executable binaries using a tool such as warp[2]. I've built an installer script[3] (install.sh) to create platform-specific launchers. Running `time keenwrite.bin --version` on Linux shows 0.327s; after the first run, subsequent launches are quick.
[1]: https://keenwrite.com
[2]: https://github.com/kirbylink/warp
[3]: https://repo.autonoma.ca/?action=repo&repo=keenwrite.git&vie...
I worked at a couple of startups that were mostly Java based and had several CLI tools. The focus was building "fat jars" then running them with "java -jar ...", or running scripts that did that. The Java VM was a system dependency and getting it baked into the binary just wasn't a practical concern.
I work at a startup that ships a Java cli to our clients. It is a giant pain in the butt. There are constant support requests from users that are using the wrong version of Java, too old or too new. Sometimes they have to wait weeks for authorization to even install the Java runtime. IT departments are extremely strict about installing Java.
> IT departments are extremely strict about installing Java.
Understandably so, given that some Java runtimes (most notably, Oracle's) require a paid license for commercial use. Having users installing that can get the company in hot water.
I could see how that could be annoying. My experience was with internal apps whee we managed all the infrastructure. Some IT departments are often extremely strict about installing anything. Some won't even let you access a web site without it being proxied through something like ZScaler.
Yeah after we got bought our own IT department wouldn't let me use ngrok even though engineering was paying for licensing for it.
What's wrong with Maven and building fat JARs?
It's not dynamic linking, despite excellent support for very late binding in historic Java versions. (Newer versions require specific launcher configurations to use certain platform features, which breaks late loading of classes that use those features.)
The article, which you may not have read, specifically calls out the use of JBang[1]for this purpose.
[1] https://www.jbang.dev/
I absolutely did read it when Max posted it to /r/java. Jbang doesn’t solve what you think it solves.
https://docs.oracle.com/en/java/javase/17/docs/specs/man/jpa...
Non-trivial, doesn’t work with standard build tooling, and unless something has changed it produces installers that extract into several different files. You don’t just get a standalone statically linked binary that you can hand off.
Yeah even js is better for CLI, just npm install it. The way its distributed also makes a huge difference.
It just so happens that I’ve built one already: TUI4J (Terminal User Interface for Java).
https://github.com/WilliamAGH/tui4j
It combines a port of BubbleTea from Go, and Textual and other inspired rewrites of other functionality.
It’s a fork of someone’s earlier work that I sought to expand/stabilize.
I built a beautifully simple LLM chat interface with full dialog windows, animations, and full support for keyboard and mouse interactivity parity, showing what this Java library is capable of.
Example chat app: https://github.com/WilliamAGH/brief
Would love to see others build similar things with it!
Java startup time shouldn't really be an issue with a terminal program. I have written some pretty complex Java and Rust and C++ terminal programs, they are basically indistinguishable on run time. The reason Java starts up slow for most people is that they are running webapps with Spring and 50 dependencies and loading Tomcat, not because they are just booting a JVM and running through some functions.
Getting AoT compiled Java programs has been a life saver. Running java -jar main.java -foo -bar is very annoying and not friendly. It needs to be packaged so you can just run tool -foo -bar
+1 on the AOT compilation. I was surprised there is still a noticeable difference between Graal and a "standard" JVM even if you have eliminated all the other cruft. Both are practically usable, no question, but the latter really felt "instant".
I was amazed when I tried Graal the first time, but also had to think that this is probably what C/C++ or Rust devs just see as "normal".
I've been a Java developer for twenty years. I've used it for everything front front end to distributed systems. I've built gradle plug-ins and clips with JAVA. I have every shortcut in intellij memorized.
Even with all this it takes me substantially less time to get go, python, or ts working as a cli. Java cli is a solution looking for a problem
I’m about the same. I’ve had one Java project going for over 10 years. It’s a collection of utilities that I use for work everyday that has grown substantially over the years. It is a CLI program that runs in my Mac, Linux servers and Linux HPC clusters. It is built with a fat-JAR concatenated to a shell stub in front that makes it effectively a single-file install. I also wrote a complete library for defining CLI programs. It is pretty easy to use, but it relies on reflection and annotations, so Graal has been difficult to get working (or was the last time I tried).
All of that to say, I’m also familiar with the problem.
For the past 3-4 years I’ve reached more for Go to my new CLI projects. Small differences in installed Java versions across clusters can be a problem, but for me the biggest issue is dealing with JVM arguments. I writing code for working with genomics data files. Sometimes these are large, and sometimes they are small. And I hate having to tell both my job scheduler (SLURM mainly these days) and the JVM how much memory to use.
This isn’t a problem in Go. So, that’s the language I gravitate to these days.
> Java cli is a solution looking for a problem
That's a great way of putting it. I'm a Java developer also; I'm most comfortable with Java and, dare I say, I like Java. But Java would be far down the list of tools I'd use to make a CL program.
Same here. Was using Java in the alpha/beta/gamma days. Have built a lot with it. Would not use it for command line tooling by default, only if it happened to be the simplest option (like maybe a library or something does nearly everything needed).
Maybe some of the old beliefs regarding startup time etc are no longer valid. Maybe the programming model isn’t as verbose as it used to be. But I don’t want to distribute a 200MB+ binary. I have colleagues who tell me that c# scripting is so awesome. One only needs .NET installed or use AOT or whatever. Sorry but Go and Rust and good forgive a python script is smaller and mostly easier to read and write then most stuff I seen other languages shoehorning into. I have nothing against Java but it isn’t the right hammer for this problem. At least for me. And I wish people wouldn’t constantly strive for the single language for every problem mindset. Yes in a Java shop it might make more sense to write cli tools and scripts also in Java. But that doesn’t mean it is the most effective toolchain in the long run.
Using modules and jlink your Java image would be much smaller than 200mb. Full desktop apps with ui’s can get down to 30mb.
I’m confused by your disregard of C# AOT. It produces binaries as small as go or rust. 1.1 MB for hello world on linux.
This ship sailed a long time ago.
Our Go CLI tools are like 100MB+ and often we bundle them in containers that are in the GB+ territory. Nobody cares or at least has cared enough to tell us to minimize stuff.
As a practical example for a Java-based CLI tool in the wild, here's kcctl, a command line client for Kafka Connect: https://github.com/kcctl/kcctl/. It's a native binary (via GraalVM), starting up in a few ms, so that it actually be invoked during tab completions and do a round-trip to the Kafka Connect REST API without any noticeable delay whatsoever.
Installation is via brew, so same experience as for all the other CLI tools you're using. The binary size is on the higher end (52 MB), but I don't think this makes any relevant difference for practical purposes. Build times with GraalVM are still not ideal (though getting better). Cross compilation is another sore point, I'm managing it via platform-specific GitHub Action runners. From a user perspective, non of this matters, I'd bet most users don't know that kcctl is written in Java.
Babashka has been available and has had a growing following since 2019. I have many babashka shebang deployed scripts with fast startup. While I would never desire to use Java syntax, AOT capable JVM based Clojure libraries are available and can be loaded dynamically. Built via graal. https://babashka.org
babashka comes with some excellent namespaces. Highlights include babashka.fs -- a functional and effective wrapper around Java file system classes, and babashka.process -- useful functions for interacting with shell processes, i/o and pipelines. I find babashka packaging to be minimal and much more convenient than python for scripting. No massive virtual environments, just a smaller than 70mb binary needs to be available on my machine. Borkdude FTW.
The article makes no compelling points to me as an avid user of these applications.
I would rather shove ice picks covered in lemon juice than provide Java or Ellison anymore room in the digital ecosystem. And I’m not talking politics here wrt Ellison, just awful
Someone else on the page commented about Oracle. Why are there still people hung up on Oracle or Ellison when if anything, they've helped Java to thrive more.
The real threat has been and continues to be ... Google. They pulled a Microsoft move (that they got busted for) and Google got away with it. Google killed Eclipse as the IDE for Android development and threw that business over to their Russian buddies at JetBrains.
Google is the threat to Java, not Oracle.
Java is legacy... when you started working with Python, Golang, Rust, Typescript, Swift... still need Java??
> Try a GraalVM native image. Milliseconds. Gone.
Try building a GraalVM native image. Minutes gone.
More gigabytes of ram than your machine has will be gone too.
Luckily, that's only during aot compilation and not runtime.
Right but the inspiration for this article is using Java as a terminal vibe coding language, so the aot step would be part of the critical path.
I’m not surprised this was not obvious to the LLM that “cleaned up my notes” for the “author”.
Java in the terminal works exquisitely well already, and it’s called Babashka. Clojure rocks, Bash reaches, and Java provides a rock-solid foundation.
Will 2026 be the year hammers get a little phillips head on the back in case you run into one of those weird ribbed nails?
I get the argument from this article that it’s possible.
But I don’t get the argument that this is somehow desirable. Just because it’s possible to smash a square peg into a round hole doesn’t make it a good idea.
My biggest complaint about Java development is the state of LSP/DAP support. I’ve tried writing Java in VS Code, and the support is still very incomplete. There are two features I want the most: (1) automatically downloading source code for dependencies, and (2) pausing all threads when a breakpoint is hit (https://github.com/microsoft/vscode-java-debug/issues/722 ).
I can’t find any editor or IDE that comes close to IntelliJ. If we want Java in the terminal, we may also need to think how to write Java in the terminal or are they orthogonal?
I'm not saying we should phase Java out. But it's pretty clear to me that Java was a bad experiment in almost every aspect, and we should at least not add new use cases for it.
So no. No, please god no, no Java in the terminal.
More ranting here: https://blog.habets.se/2022/08/Java-a-fractal-of-bad-experim...
And yet Java is more then Java. There are lots of more modern languages on the JVM. The ecosystem is huge and still has lots of inertia.
Yeah. Some of my critique applies to the language, some on the JVM and thus cross language.
Kotlin sure is less awful, for example. But the JVM, as I describe, was always a failed experiment.
Article meta comment: show me, don’t tell me.
No show —> not easy enough —> too lazy to look it up, already got python/go/ruby quick cli methods. LLM generated even easier.
Agree, Java also had straight single file execution forever now. Java foo.java. I use it instead of scripts all the time. Solid language with a lot of flexibility, Oracle has done a good job in last few years. Newer Java frameworks are fairly easy and light to use. We have natively image Lambda functions in production. Work well.
how does this handle classpath
from https://old.reddit.com/r/java/comments/1pzfmka/2026_the_year...
https://www.jbang.dev/
Strangely, not a mention of groovy which I seem to remember was somewhat motivated by use cases such as this?
I didn't know about JBang, it looks awesome. Does it work somewhat like uv?
I wish the article dug deeper into how the workflow would look like in the practical sense when using jBang and jReleaser.
2026 is going to be the year of learning languages as you review LLM generated code
how about jshell? it comes with every java distribution
But latency. No Java app I have used in 25ish years has ever started in a reasonable amount of time.
> started in a reasonable amount of time
A hasty generalization with a little confirmation bias, perhaps?
From Claude:> It's worth noting this is a common perception about Java, and there's some historical truth to it (especially with Swing desktop applications from the 2000s). However, the absolute statement "no Java app... ever" is the fallacy - it's an overgeneralization from limited personal experience to a universal claim.
The moment you introduce the jvm, is the moment people flee.
Graal would be needed and then your binaries would be huge.
No thanks. Go is much simpler. Rust is much smaller. Java can go die in the office storage closet.
Go and "simpler"? Really?
C is simpler, Python is simpler, but Go?
Indeed
https://leapcell.io/blog/the-origins-and-design-philosophy-o...
Go was originally designed to make life easier for googlers and make software engineering easy. In 2025, I can attest to the fact that Go is simple. Go is easy. Whether you can accomplish what you want in Go is another story. However, Go has a very basic structure and easy flow. Complexity comes from not understanding the go philosophy.
Go is one of the simplest languages there is. Not always easy to create something at scale IMO, but certainly simple.
Yes - Go is both a simpler language than Java which does not lend itself to (nor does the ecosystem tolerate) the kind of architectural malpractice that enterprise Java typically becomes.
Languages lose users when the tooling becomes too heavy.
You have to learn ( and maintain knowledge of ) build tooling, unit test frameworks, tools for front end / back end development, distribution and packaging systems, directory structures to accommodate all those, etc. ad nauseum.
Then something new and shiny comes out, with much smaller tooling. The lure of easy software construction seduces the user.
It never ends.
No, Java (or frankly anything JVM-based) on the terminal is a terrible experience.
I've been writing Java utils for the terminal since forever. Mostly because I was extremely familiar with Java. It's never been really slow unless you were loading shitload of classes, like apps that package the entire kitchen sink do or as Clojure does for example. For Clojure now there's Babashka: super quick.
And GraalVM compiled Java is more than speedy.
Back in, say, 2005, two decades ago, on computers from back then, sure, the java startup time from the CLI were noticeable. But on today's computers?
Nowadays when it comes to terminal apps I wrote both Clojure (Babashka), Bash and Java (recently I needed something from a .jar and had no convenient Clojure wrapper and didn't want to bother, so I just wrote my CLI app in Java).
Maybe, maybe, maybe that I do feel the startup time when I run my CLI Java app on Raspberry Pis. Raspberry Pi 2 and 3s that is (for I don't have any newer).
Startup times aren't an issue. But there may be other reasons to prefer other languages to write CLI apps.
There are approximately no use cases that would get me to run a CLI written in Java on my machine, especially if it required having a JVM installed. There's just no reason for it.
The rounding error there is Pkl, which is at least built using Graal Native Image, but (IMO) would _still_ have better adoption if it was written in something else.
That said, if the Java community wanted to port reasonable tooling to their platform, I'm sure Claude could do a reasonable job of getting a decent chunk of BubbleTea and friends bootstrapped.
> That said, if the Java community wanted to port reasonable tooling to their platform, I'm sure Claude could do a reasonable job of getting a decent chunk of BubbleTea and friends bootstrapped.
There's a poster upthread who seems to have done what you're describing: https://github.com/WilliamAGH/tui4j
Assuming JVM installation is not required (to which I agree, it shouldn't be), why would you care which language a CLI tool is written in? I mean, do you even know whether a given binary is implemented in Go, Rust, etc.? I don't see how it makes any meaningful difference from a user perspective.
> Pkl, which is at least built using Graal Native Image, but (IMO) would _still_ have better adoption if it was written in something else.
Why do you think is this?
The question mark at the end is an easy out for us to claim Betteridge’s law.
"Does binarymax understand the concept of yes-no questions?"
Very clearly written by AI. Java in the terminal sounds awful. Programming Java is awful.
No thank you.
When did you last program Java? It’s changed a lot from the Java 8 days.
I am not in the ecosystem anymore but it did a lot of things right.
I concur with Nick, and the last time I programmed Java professionally was late 2024, with all of the latest and greatest frameworks (obviously not my choice) and tooling (which, to be fair to the Java ecosystem, is second to none).
The experience after having spent over a decade primarily doing Go, Rust and Erlang (with a smattering of TypeScript, C#, Python, Swift, C, C++ etc) was the final push over the line to leave that employer.
Can you back up your claim the post is written by AI?
I'm not sure I'd go so far as to claim it was definitely written by AI (after all, LLMs tend to write the way they do because it reflects their training material), but it does have a large number of suspicious constructions that suggest it could have been:
- "Look, I’m going to say something that might sound crazy...."
- But here’s the thing: there’s nothing stopping us...
- Emdashes. I don't believe that alone they are a tell for AI any more than they are a tell for the cultured, but in combination with other things, maybe.
- The question/answer style.
- The "It's not X, It's Y" construction.
This is all in the first sections.
I agree. The entire "The Path Forward" and "The Bottom Line" breakdowns at the bottom gave me the same impression.
I think it’s a mix of human and LLM writing
use rust or go, please
single binary, no complex deps, ftw
I would use this instead, https://babashka.org/
babashka is for clojure
clojure is java. you have full access to the entire ecosystem, with none of the headaches.
came here to say the same
Go?
Well, the year is 2003 and I am on a hot dungeon with bad Air Conditioning, figuring out the correct spells for a black magic ant build. A few years later I am writing tons of XML, first for vanilla J2EE, then for spring. We complained, we wondered, nobody cared until one day we decided "fuck that shit, I don't care if ruby is slow as molasses, I just want the pain to go away!"
Forgive me if in 2026 I get triggered at the mere mention of the phrase "java build".
Lots of us had long relationships with Java, relationships marked by toxicity and abuse. We moved on. Now Java says it is changed, it has matured. Well, it could be true, probably it is even true, but on the other hand, now your toxic ex found out his father, and his name is Larry Ellison.
Looking forward to implementing a AbstractCommandlineParserFactoryBeanServicePatternFactory
> AbstractCommandlineParserFactoryBeanServicePatternFactory
...Locator