This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch blog/camel-cli-424
in repository https://gitbox.apache.org/repos/asf/camel-website.git

commit 5064f02df0efc76025936d90b51951e10692f5c5
Author: Claus Ibsen <[email protected]>
AuthorDate: Thu Nov 12 20:42:10 2026 +0100

    Blog: the Camel CLI in Camel 4.24 - fast, on aesh, and an AI can trust it
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 content/blog/2026/11/camel-cli-424/index.md | 200 ++++++++++++++++++++++++++++
 1 file changed, 200 insertions(+)

diff --git a/content/blog/2026/11/camel-cli-424/index.md 
b/content/blog/2026/11/camel-cli-424/index.md
new file mode 100644
index 00000000..549c1dd3
--- /dev/null
+++ b/content/blog/2026/11/camel-cli-424/index.md
@@ -0,0 +1,200 @@
+---
+title: "The Camel CLI in Camel 4.24: starts in a blink, now on aesh"
+date: 2026-11-17
+draft: false
+authors: [davsclaus]
+categories: ["Camel", "Tooling"]
+keywords: ["apache camel", "camel cli", "camel 4.24", "aesh", "picocli", 
"startup", "class data sharing", "exit codes", "ai agents", "self-update"]
+preview: "The Camel CLI in Camel 4.24 runs a command in about 150 ms, where 
4.23 took more than a second. It parses its command lines with aesh instead of 
picocli, and it is a CLI an AI agent can trust and keep up with: documented 
exit codes, errors on stderr, JSON output and timeouts."
+---
+
+You type `camel` many times a day: `camel run`, `camel ps`, `camel get route`, 
`camel log`. And now so do AI agents,
+which call the CLI over and over in a loop. In Camel 4.24 the Camel CLI got a 
lot of attention. This post is about
+three changes:
+
+* it is fast: a command such as `camel version` or `camel ps` takes about 150 
ms, where 4.23 took more than a second
+* it runs on [aesh](https://github.com/aeshell/aesh) instead of picocli
+* it is a CLI an AI agent can trust: exit codes, errors on stderr, JSON output 
and timeouts
+
+And then some of the smaller things that make the day better.
+
+## Fast
+
+This is the time a command takes, from typing it to the prompt coming back. It 
is the median of 15 runs of the
+`camel` launcher of the distribution (4.23.0, and a nightly build of 4.24), on 
an Apple M4 Pro with Java 25:
+
+| Command            | Camel 4.23 | Camel 4.24 |
+|--------------------|-----------:|-----------:|
+| `camel version`    | 1251 ms    | 146 ms     |
+| `camel ps`         | 1292 ms    | 188 ms     |
+| `camel init --help`| 1234 ms    | 149 ms     |
+| `camel get --help` | 1232 ms    | 179 ms     |
+| `camel run --help` | 1239 ms    | 326 ms     |
+| `camel --help`     | 1242 ms    | 329 ms     |
+
+That is about 8 times faster for the commands you use the most. A `camel ps` 
now comes back before you notice it
+was gone. For you that is nice. For an AI agent it matters much more, as we 
will see below.
+
+Where did the second go? Not into one big fix, but many small ones, found by 
measuring first:
+
+* **Only the command you run is created.** The Camel CLI has more than 160 
commands. Camel 4.23 created all of them,
+  with all their options, and those of every plugin, before it ran one. Now 
`camel ps` creates `camel ps`, and a
+  plugin command creates only that plugin.
+* **No logging unless something logs.** Most commands log nothing, yet log4j 
was started for each of them. Also the
+  check for a newer version of the CLI started log4j, before every command.
+* **The launcher script no longer runs `java -version`** to find out the Java 
version. It reads the release file of
+  the JDK instead, which saves starting a second JVM.
+* **The JVM no longer waits at exit** for the thread of an HTTP client that a 
command created but never used, or
+  for the update check.
+* **The distribution runs from plain jars.** Camel 4.23 ran the CLI from one 
Spring Boot fat jar, which has its own
+  class loader for the nested jars. Camel 4.24 has the jars in `lib/`, next to 
a thin launcher jar.
+* **Class data sharing.** Because the jars are plain jars now, the JVM can 
keep the classes a command loads in an
+  archive, and map it in on the next run. The `camel` script does this by 
itself: the first run of a command writes
+  the archive (under `~/.cache/camel-cli/cds/`), and the runs after it are 
faster. Set `CAMEL_CDS=false` to turn it
+  off. Without the archive, `camel version` takes 186 ms instead of 146 ms, 
and `camel --help` 559 ms instead of
+  329 ms.
+* **aesh.** More about that below.
+
+## On aesh instead of picocli
+
+The Camel CLI has used [picocli](https://picocli.info/) from its start. 
picocli served us well, but it moves slowly
+now: its last release was in April 2025. In Camel 4.24 the Camel CLI parses 
its command lines, prints its help and
+completes its commands with [aesh](https://github.com/aeshell/aesh), the Java 
library for command line tools by
+Ståle Pedersen.
+
+The main reason for the move is not speed. It is that aesh is a living 
project, with a maintainer we can talk to. We
+saw that during the port. Before switching, we ported all of the CLI on a 
branch and wrote down every gap and bug we
+found in aesh: 36 issues and 17 pull requests. Ståle fixed or merged nearly 
all of them within days, and released aesh
+3.19 and 3.19.1 with them. Thank you, Ståle!
+
+aesh is a little faster too. In our measurements during the port, aesh took 
about 20 ms off `camel version`, and
+about 60 ms off `camel --help`. That is a small part of the second above, but 
it all adds up.
+
+### What changes for you
+
+For using the Camel CLI, not much. The commands and their options are the 
same. To be sure of that, before the
+switch we wrote a test with 2207 command lines and what picocli made of them, 
and one with the help of all commands
+and the errors of wrong command lines. The aesh port had to give the same 
answers.
+
+The help looks a little different: the default value of an option is on a line 
of its own (`Default: ...`).
+
+An argument `@file` is replaced by the arguments in that file, as it was with 
picocli, such as `camel @run.txt`.
+
+If you wrote your own plugin for the Camel CLI, it must be changed and built 
for Camel 4.24: a plugin adds its
+commands to a `CommandTree` instead of a picocli `CommandLine`, and the 
commands use the aesh annotations. The
+[upgrade guide](/manual/camel-4x-upgrade-guide-4_24.html) has the details.
+
+## A CLI that an AI can trust, and that keeps up with it
+
+More and more, the Camel CLI is not called by a person, but by an AI agent. 
The agent works in a loop: it runs a
+command, reads what came back, decides the next step, and runs the next 
command. To build and fix an integration it
+looks up a component, writes a route, validates it, runs it, reads the log, 
sends a message, checks the routes, and
+goes around again. That is easily 50 or 100 calls of the CLI for one task.
+
+### Fast matters more for an AI than for you
+
+When you type a command, one second is a short pause. You were reading the 
last output anyway. For an agent, every
+call is a stop: the loop waits for the CLI before the model can think about 
the next step. 100 calls of a CLI that
+takes 1.25 seconds is more than two minutes of waiting. At 150 ms it is 15 
seconds.
+
+And it is not only about time. When a check is cheap, an agent does it: it 
looks up the option instead of guessing
+it, it validates after each change, and it checks the routes once more after 
the reload. When every call costs a
+second, there are fewer of those checks for the same time and the same budget, 
and more guessing. A fast CLI makes the
+agent quicker, and it makes it better, because it can afford to verify. 
Running a local model, where the model is
+already the slow part, you want every other part of the loop to be as fast as 
possible.
+
+### An answer an AI can trust
+
+An agent cannot see your screen. All it has is the exit code and the text that 
came back, and it builds its next
+step on that. A person reads "ERROR: no integration found" and knows what to 
do, even when the exit code says `0`. An
+agent that gets `0` for a command that did not work takes it as a fact, and 
goes down the wrong path. A command that
+waits for a terminal that is not there leaves the agent stuck until its own 
timeout. Every answer the CLI gets wrong
+costs the agent more than the command took.
+
+So in Camel 4.24 the Camel CLI has a contract: the
+[exit codes and output](/manual/camel-jbang-exit-codes.html). The same 
contract is good for a script and a CI job too:
+
+| Exit code | Meaning                                                        |
+|----------:|----------------------------------------------------------------|
+| 0         | success                                                        |
+| 1         | the command failed                                             |
+| 2         | usage error: a wrong option or argument                        |
+| 3         | not found: no integration, route, Kamelet or plugin of that name 
|
+| 66        | a file or directory that does not exist                        |
+| 70        | internal error                                                 |
+| 124       | timed out: the integration did not answer in time              |
+
+And with it:
+
+* Errors go to stderr, so the output on stdout can be read as is.
+* With `--json`, stdout is exactly one JSON document, also when the command 
fails, so it can always be parsed. A
+  listing with nothing in it prints `[]`.
+* Commands that talk to a running integration take a `--timeout`, and say so 
when the integration did not answer,
+  instead of waiting forever.
+* No command waits for a terminal that is not there. Without one, `--watch` 
shows the output once, `camel log` does
+  not follow, and a command that needs a terminal, such as `camel debug`, 
exits with `2` instead of hanging a CI job.
+* `camel stop` and `camel restart` wait until the integration has stopped, and 
exit with `124` when it did not stop
+  in time.
+* `camel run --background` waits for the integration to start, and a file that 
does not exist fails before anything
+  starts.
+
+The AI tools of the Camel CLI, the [MCP server](/manual/camel-jbang-mcp.html) 
and `camel ask`, pass these failures on
+to the agent as errors, so the model sees what went wrong instead of guessing 
it.
+
+Fast and trustworthy go together: the agent calls the CLI often because each 
call is cheap, and it can act on what
+comes back because the answer is right.
+
+## Stay up to date
+
+The [web installer](/manual/camel-jbang-launcher-install.html) installs the 
latest release:
+
+```shell
+curl -fsSL https://camel.apache.org/install.sh | sh
+```
+
+You can ask it for the newest LTS release, or the newest release of a line, 
and `camel self-update` stays on it:
+
+```shell
+curl -fsSL https://camel.apache.org/install.sh | sh -s -- --version LTS
+curl -fsSL https://camel.apache.org/install.sh | sh -s -- --version 4.24
+```
+
+And new in 4.24: try what is coming before it is released. Apache publishes a 
nightly build of the Camel CLI, and
+`camel self-update` can switch to it, and back:
+
+```shell
+camel self-update --version SNAPSHOT
+```
+
+Nightly builds are development builds for testing, not Apache releases.
+
+## The smaller things
+
+* `camel cmd send` can feed a route: `--repeat` and `--interval` send many 
messages, and `--body=file:<folder>` sends the
+  files of a folder, one message per file.
+
+  ```shell
+  camel cmd send --endpoint=kafka:refunds --body=file:refund.json --repeat=50 
--interval=100..500
+  ```
+
+* `camel run --data-dir` names the folders with data files under the source 
directory, which dev mode does not watch,
+  so writing a file there does not reload the routes.
+* In dev mode, a reload applies changed `camel.beans` and `camel.component` 
properties, and a dependency added to
+  `camel.jbang.dependencies` while the app runs is downloaded.
+* The log of the previous run is kept, also for the Spring Boot and Quarkus 
runtimes, so you can read why it failed
+  at startup. `camel dirty --clean` removes those logs too.
+* `camel cmd route-diagram`, `route-structure` and `route-topology` read Java 
routes with the Java DSL parser, without
+  compiling them.
+
+## Try it
+
+Try it now with the nightly build:
+
+```shell
+camel self-update --version SNAPSHOT
+```
+
+When Camel 4.24 is released, `camel self-update --version 4.24` switches back 
to the releases. Or install it with the
+web installer above.
+
+And then type `camel ps`, and see how fast it comes back.

Reply via email to