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.
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.
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.
jbang is to java, what uv(x) is to python and what npm/npmx is to javascript.
A single executable is always just one "pyinstaller --onefile --noconsole main.py" away.
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.
Even Eclipse and Intellij ship openjdk based runtimes with their distributions and have even stricter GPL limits.
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.
Write once, run everywhere.
Or use a graal to build a native-image and ship that around.
But that's not what people want. They want an .exe or a .app, or .rpm, or whatever. That's a container for holding that .jar and it is platform specific and there is no workaround to that problem.
No more FreeBSD, Solaris, open Solaris (illumos smartos etc).
https://github.com/psumbera/solaris-openjdk seem to work?
Pretty sure many other runtimes aren't exactly supported on all platforms by single vendor/projects?
So will we see python stop being used?
No, because instead of sitting in corner and mope about it the ecosystem just kept working and filling in the gaps.
Java ecosystems done lot of that - but general public keep having the old changes stuck in their mind.
Lets change that :)
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.
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.
Or do what the rest of the world does, use Eclipse Adoptium (the best JDK in my opinion) or the one from OpenJDK, Microsoft, etc.
You and the parent raising the specter of Oracle's Java licensing isn't applicable any more. It isn't 2009.
Heh, I find this very amusing and ironic, seeing how Write Once Run Anywhere was a stated goal with Java, that failed miserably.
For that use case, was it active content, was it shipping intermediate representation, was it a sandbox? To all three: yes, very poorly.
Type the following prompt into any AI and feel free to argue your point with the AI: "what does jbang solve?"
For end-user apps, this is basically solved: use jpackage to ship an installable app with a bundled, trimmed JRE. Better yet, distribute via the OS app store so updates are handled for you (on Linux, Flatpak is probably the right answer today).
For CLI tools, you’re already assuming a more technical audience. At that point you have two real options:
- ship everything bundled (Go/Rust static binaries, pyinstaller, jpackage)
- ship just the app and rely on a smart launcher/runtime manager (npx, bunx, uvx, jbang), and assume your technical audience can install that first
The real question isn’t "is it a single binary?", it’s "how do users install, run, and update it?". In practice, that’s already been solved by developer package managers like brew and scoop. All the Go and Rust CLIs on my machine are installed via brew, not manually downloaded from GitHub releases.
You also want CLIs on PATH or inside a dev environment (mise, direnv, etc.), so whether that executable is a true single binary or a symlink to a bundle is mostly irrelevant.
So the trade-off becomes, do you support `brew install foo-java-tool` with a bundled JRE, or do you ask users to `brew install jbang` and then `jbang install foo-tool`? Either way, the end result is the same, you run `foo-tool`.
Note, Claude Code for instance supports both options (curl | bash, brew cask, and npm -i), isn't a single binary, and that still hasn't stopped it from being the most popular CLI tool released this/last year.
There’s definitely room for improvement in Java’s packaging story, I just think the focus shouldn’t be on "single binary" as the primary goal.
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.
[2]: https://github.com/kirbylink/warp
[3]: https://repo.autonoma.ca/?action=repo&repo=keenwrite.git&vie...
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.)
I haven't really had the burning need for app+jvm since I used graalvm and made jbang and its now trivial to run app + shared jvm for me - but I can see the utility for it.
Noted down the various pointers and existing attempt to explore in 2026 !
About build and publishing - this I feel is also solvable.
Especially if we stop trying to solve it for all possible mutations of gradle/maven builds and just make it work for jars...this is where jbang/jreleaser really simplifies more than I think many realize.
So in 2026 I'll definitely try get more recipes published on this and also see if we can make something like `jbang publish` "Just Work"
I really think that this aligns with the “paving the on ramp” type of stuff. Making the build tooling first class and simple will help adoption.
GraalVM native image allows doing exactly that. Should be as easy as adding a single gradle plugin
Most devs have npm installed always, I don't like it but its effective at delivering software to my development environment.
and yes, works on npm, uvx, etc. too.
`npx @jbangdev/jbang`
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
Edit: Heh... https://rattlin.blog/bbgum.html
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.
The why is quite simple, in my opinion. I see java devs reaching for other accepted tools for such things and opening a whole can of worms by introducing a new language that is only "required" by convention. I would love a rich java ecosystem of TUI/CLI libraries to reuse all of my existing business logic and company libraries. The lack of extremely streamlined wrappers is the only barrier. In my work environment, this would be a great addition.
I've used a limited amount of Java CLIs, the most obvious ones are things like Gradle which never felt snappy to use - it is annoying when even doing basic things takes 2+ seconds. I guess not the end of the world, but that seems suboptimal to me compared to a system that feels fast to use and hence well engineered.
Python has been much more painful :) no shade on go, of course having a binary built for your system is the most painless.
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!
I wasn’t expecting the main topic of what I’ve been building to appear on the cover of hacker news today, so I was caught a bit unprepared, but they were definitely on the todo list next!
Will definitely check it out.
...where is the jar for brief? :)
curl -L -o brief.zip https://github.com/WilliamAGH/brief/releases/latest/download... unzip brief.zip cd brief-*/ ./bin/brief
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
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".
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
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.
Then when I had ability to write java scripts with dependencies, we added auto download of JDK and then made it so could run any jar (not just scripts) and I suddenly now have full debug support for anything I do + I can install and run this on any docker container or laptop - even my parents or a library computer running some ancient windows. Try that with npm and python :)
All I'm saying - I hear you and I grok why. What I'm saying that for at least close to 5 years at least last 3.5 years there been a way to use the jvm as easy and more reliable than python/nodescript/typescript....run cli's, swing/jfx, backend apps etc.
And in 2026 I want to make java TUI's a reality.
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.
> time dotnet publish
Restore complete (0.4s)
dn-hw net10.0 linux-x64 succeeded (2.4s) → bin/Release/net10.0/linux-x64/publish/
Build succeeded in 3.1s
real 0m3.571s
user 0m2.784s
sys 0m0.673s
> time go build main.go
real 0m3.309s
user 0m8.864s
sys 0m1.741s
Obviously I don't know how that translates to a non-trivial application.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.
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.
I done https://github.com/jbangdev/jbang-jash for shell processes and smallrye process io also done a lot for nice shell apis.
Files access could be another.
jbang provides the similar binary - for now bash+jvm based but all simple installable. I have native jbang binaries which are even less than 70 mb :)
Definitely going to check out babashka more for inspiration.
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.
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
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.
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.
Try building a GraalVM native image. Minutes gone.
I’m not surprised this was not obvious to the LLM that “cleaned up my notes” for the “author”.
$ tim "awk '{}'</n" 'tcc -run /tmp/true.c' 'perl</n' 'py2</n' 'py3</n' 'java -jar helloworld.jar>/n'
97.5 +- 1.5 μs (AlreadySubtracted)static dash Overhead
94.9 +- 3.2 μs awk '{}'</n
376.7 +- 4.6 μs tcc -run /tmp/true.c
525.3 +- 2.7 μs perl</n
3627.7 +- 6.0 μs py2</n
6803 +- 11 μs py3</n
42809 +- 71 μs java -jar helloworld.jar>/n
Also, probably there is some way to tune this, but it used over 128 MiB of RSS.[1]: https://github.com/jarirajari/helloworld [2]: https://github.com/c-blake/bu/blob/main/doc/tim.md
`native-image -jar helloworld.jar helloworld` did take a whopping 17 seconds to compile, what might be the smallest possible project. That does makes me worry for iterations trying to get better perf in a context where startup overhead matters, BUT the executable it produced did run much faster - only about 1.8x slower than `tcc -run`:
97.0 +- 1.7 μs (AlreadySubtracted)Overhead
98.2 +- 2.8 μs awk '{}'</n
376.4 +- 4.4 μs tcc -run /tmp/true.c
527.9 +- 4.0 μs perl</n
686.5 +- 3.9 μs ./helloworld>/n
Perl has 2 more shared libraries for ld.so to link, but is somehow faster. So, there may still be some room for improvement, but anyway, thank you for the correction.(Also, I included 4 of the faster comparative programs to show additionally that the error bars are vaguely credible. In truth, on time shared OSes, the distributions have heavier tails than Gaussian and so a single +- is inadequate.)
--
EDIT: So, the ld.so/dynamic linking overhead was bothering me. I had to get a musl + zlib build environment going, but I did after a few minutes and then found this result with a fully statically linked binary executable:
398.2 +- 4.2 μs ./helloworld-sta>/n
(I should have noted earlier that /n -> /dev/null is just a convenience symlink I put on all my systems. Also, this is all on Linux 6.18.2 and the same CPU as before.)Also, only around 4.2 MiB of RSS compared to ~1.8 MiB for dash & awk. So, 2.4x the space and only ~4X the time of static awk & dash. That might sound like criticism, but those are usually the efficiency champs. The binary size is kind of hefty (~2x like the RAM use):
$ size *sta
text data bss dec hex filename
2856644 3486552 3184 6346380 60d68c helloworld-sta
So, I guess, in 2026, Java start-up overhead is pretty acceptable. I hope that these "real numbers" can maybe add some precision to the discussion. Someone saying "mere milliseconds" just does not mean as much to me as 400 +- 4 microseconds, and perhaps there are others like me.Other ecosystems just have much less "enterprise rules" applied to them - break free :)
class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
java HelloWorld.java
Include the .java extension, you're running the file directly.time java HelloWorld.java
Hello, World!
real 0m0.278s
user 0m0.613s
sys 0m0.066s #!/usr/bin/env java --source 25
void main() {
IO.println("Hello, World!");
}
https://openjdk.org/jeps/330
https://openjdk.org/jeps/458
https://openjdk.org/jeps/512I often combine these approaches with https://get-coursier.io/ when I need to fetch third-party dependencies.
$ python foobar
Nope.
$ gcc foobar
Nope.
$ g++ foobar
Aw,come on.
$ go foobar
Damnit.
$ rust foobar
$ c# foobar
WTF did they use for this program??!!
$ node foobar
This is such a waste of time.
$ java foobar
Bullshit!
$ ocaml foobar
Come on, there arent't that many more programming languages!
$ tcl foobar
Finally!
Lets please not mix up good dev flows with end user flows...this is not unique problem for java.
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?
"java.maven.downloadSources": true in config if you don't just use maven's automatic download for it.
pause all threads does look like a valid omission. Feels like something someone should go contribute - any takers?
on your question - I do actually miss having a good an easy java in terminal editing experience. I use a nvim starter pack to do it BUT here there is no good jbang enabled LSP to make it truly smooth ...also on my 2026 wish list :)
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.
> 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?
As for why Pkl was in Java: it was originally built to configure apps written in Java, and heavily uses Truffle. Pkl is a name chosen for open sourcing, it had a different name internally to Apple before that which made the choices a little more obvious.
There's a poster upthread who seems to have done what you're describing: https://github.com/WilliamAGH/tui4j
This is what writing a CLI application in Go looks like: you download Go and immediately have all the tools needed to manage dependencies, write applications, and compile them into lightweight, distributable binaries with a simple command.
Now, let’s consider how this process looks in Java. First, you need to download A(!) JDK – and there are multiple ones. Many newcomers struggle with the variety of JDKs, but let's move past that. The JDK alone doesn’t handle dependencies; it’s highly likely you’ll end up using either Maven or Gradle, both of which are complex and tiresome, requiring you to deal with either XML (Maven) or Groovy/Kotlin. What seems to be missed is the potential of tools like JBang, which should ideally come out of the box. The Scala people addressed this effectively with scala-cli which is now the default Scala runner. Anyway, you’re still far from finished. You've just figured out how to write applications; now you need to figure out how to distribute them. This involves understanding jpackage – if you want an application smaller than 100MB, you’ll likely need to use jlink beforehand. And, heaven forbid, your application uses Java 9+ modules, as then you'll be wrestling with the complexities of modularity itself. If you’ve managed to navigate all of this, you’ll end up with an application that includes a bundled JRE. A compressed, modularized “hello world” application can easily size at least 30MB and take several hundred milliseconds to start.
Then there's Graal Native, which allows you to compile your applications ahead of time into natively executable binaries. However, compiling Java applications ahead of time is complicated by runtime class initialization, reflection etc. which is why the Graal compiler needs significant configuration beforehand. There are tracing agents to help you compile such configurations, but even with them, it’s incredibly tiresome and not always reliable. Furthermore, the produced binaries tend to be large and don't play well with upx.
I think the JDK developers could learn from Scala CLI, which is now the default Scala runner. I'm convinced it would really help Java if it came with something like that out of the box.
Love you too.
This is what writing a CLI application in Go looks like: you download Go and immediately have all the tools needed to manage dependencies, write applications, and compile them into lightweight, distributable binaries with a simple command.
Check - agreed.
Now, let’s consider how this process looks in Java....<rant>
It feels like you missed the last 5 years of improvements..so let me show you how this works in java when using jbang:
You download JBang, and immediately have all the tools needed to manage dependencies, write applications, and run other Java applications with a simple command.
Since you probably don't believe me I'll show you some of it here:
`jbang init -t cli hello.java` - you get a hello.java that declare picocli dependencies and you can run it as `./hello.java`, you even do `jbang app install hello.java` and just use `hello`. You can do this with your own scripts, preexisting jars or existing Maven artifacts.
- yes it will also have downloaded right JDK for you; you can easily swith to other versions, either `jbang --java 25 hello.java` or even `jbang --java 8 hello.java` if you really wanna go back in time :) The java version can be baked into your script or jar so it is NOT a requirement for your end user to be aware.
`jbang edit hello.java` will offer to install vscodium based IDE that gives you an IDE environment to write java in.
`jbang export fatjar hello.java` gives you a runnable fat.jar
`jbang export maven|gradle hello.java` gives it a full blown maven/gradle if you are forced to be Enterprise Compliant :)
You can even run and distribute these sources by just commiting to a github repo and just do `jbang <repourl>` or use jbang catalogs etc. Lots of opportunities.
Reading this and reddit thread I see that the final publish of jars/executables is still too tedious I'm going to try solve that challenge as we have all the pieces (IMO) with jbang/jreleaser and modern JDKs.
Then there's Graal Native, which allows you to compile your applications ahead of time into natively executable binaries. However, compiling Java applications ahead of time is complicated by runtime class initialization, reflection etc. which is why the Graal compiler needs significant configuration beforehand. There are tracing agents to help you compile such configurations, but even with them, it’s incredibly tiresome and not always reliable. Furthermore, the produced binaries tend to be large and don't play well with upx.
don't play well with upx - how so? yes there is the usual upx overhead but "just works" when I tried using it?
about graalvm native - definitely not going to say its perfect nor easy; but Quarkus definitely have a whole ecosystems of java libraries and framework setup that just works when using native builds.
That said - I think we dont need to go to full native for lots of usecases.
I think the JDK developers could learn from Scala CLI, which is now the default Scala runner. I'm convinced it would really help Java if it came with something like that out of the box.
Yeah, I couldn't wait for JDK developers to do it so I built jbang to make that available today.
Regarding UpX: it simply doesn’t work with Windows binaries generated by Graal – see this issue: https://github.com/oracle/graal/issues/7605. They've been ignoring this for three years instead of fixing it. Meanwhile, it works perfectly with Go binaries or .NET’s AOT compiler. I’m not trying to bash your project, but the reality is that no one with little to no Java experience is going to discover and install jbang. Features like this should be included with Java out of the box.
and still npm, python, and other ecosystems don't do that. they effectively ships what corresponds to jars with dependency metadata.
I also did not say fat jars (even though that works fine too).
Why don't java world be ok with utilizing that option like other ecosystems.
I know why they didn't do it in past when something like jbang did not exist - just like javascript didn't do it before npm (and fast node runtime) came around...
I’ve brought up numerous complaint regarding jpackage and jlink, and none of them have been addressed by jbang.
I explicitly wrote: "Reading this and reddit thread I see that the final publish of jars/executables is still too tedious I'm going to try solve that challenge as we have all the pieces (IMO) with jbang/jreleaser and modern JDKs." so I did not claim jbang solves it - I said I could see how it could be better.
What I did show or at least tried to was that your complaint about something like scala-cli and how Go could do all things out of box...jbang exist to bridge that gap.
Furthermore, you accuse me of not having used Java in the last five years, which is frankly ridiculous;
I did not claim that at all. I said you seem to have missed the last years improvements in this space (jbang being a key one enabling majority of the issues you brought forward).
I've spent almost two decades developing software on the JVM. Funnily enough, I had to write my own sbt plugins because jlink and jpackage are so painful to use.
yes, I agree jlink and jpackage is not good enough.
I haven't tried tackle it yet as I used jreleaser most of time to hide that pain - and I agree its not solved yet...but also trying to show that distributing everything as native OS binaries is NOT an absolute requirement and not what other ecosystems does.
Heck, even Go allow for running git repos by compiling it locally before running it... jbang allow similar workflows - on top of plain java.
Regarding UpX: it simply doesn’t work with Windows binaries generated by Graal – see this issue: https://github.com/oracle/graal/issues/7605. They've been ignoring this for three years instead of fixing it. Meanwhile, it works perfectly with Go binaries or .NET’s AOT compiler.
gotcha - haven't tried it on windows for a while and looks like it did work in GraalVM 21 and just issue on future versions.
I’m not trying to bash your project, but the reality is that no one with little to no Java experience is going to discover and install jbang. Features like this should be included with Java out of the box.
yeah - well neither node, python and others had these to begin with.
Its a very Java'esque mindset to require it in the default toolchain to be considered useful.
I wonder why anyone even still try using maven or gradle or sbt - it does not come with Java itself either :)
But also when running on the JVM, things have improved dramatically over the last few years, e.g. due to things such as AOT class loading and linking. For instance, a single node Kafka broker starts in ~300 ms.
graalvm is literally 500x more overhead than a statically linked dash script.
Maybe not an issue for terminal UIs, but the article mentions both TUIs and CLI tools. A lot of people use CLI tools with a shell. As soon as you do `for file in *.c; do tool "$file"; done` (as a simple example), pure overhead on the order of even 10s of ms becomes noticeable. This is not theoretical. I recently had this trouble with python3, but I didn't want to rewrite all my f-strings into python2. So, it does arise in practice. (At least in the practice of some.)
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.
jshell is amazing, I don't think enough people know about it!
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.
No show —> not easy enough —> too lazy to look it up, already got python/go/ruby quick cli methods. LLM generated even easier.
No thank you.
I am not in the ecosystem anymore but it did a lot of things right.
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.
- "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.
Absolutely shocked Java wasn’t in the terminal
I know I don’t use it, but wow.
Honestly, super impressed that that they’ve got the traction they do without it but, I think the takeaway is that Java developers like having everything in the IDE— so I’d imagine agentic in the ide will yield higher returns than switching modalities
The real blocker isn’t capability, it’s perception: many people stop before even trying Java in the terminal. All while Python/JS are seeing a surge in terminal tooling, despite similar (or worse) startup cost, dependency sprawl, and multi-GB installs — and the reaction there is often “this is fine, let’s ship and use.”
Until Java is visibly normal in the terminal, agentic features in IDEs won’t change that mental model.
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...
Kotlin sure is less awful, for example. But the JVM, as I describe, was always a failed experiment.
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.
C is simpler, Python is simpler, but Go?
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.
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.
I'm happy to say I think all have their upsides and downsides and all of them evolve and should all try not to be stuck in old perceptions. And yes Java is held back by those perceptions and I'm saying lets not get bogged down by perceptions like yours from trying to evolve and improve.
When I started showing that its just fine to name a class, `myapp` and run it with jbang myapp.java people got all weirded out.
No technical constraints in java; just bad old habits limiting peoples mindset ;)