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

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 134c4f0b55fb CAMEL-23566: camel-jbang - Source examples from 
camel-jbang-examples repository (#23375)
134c4f0b55fb is described below

commit 134c4f0b55fbac761a42db7d551b7ac9cc02e8bf
Author: Claus Ibsen <[email protected]>
AuthorDate: Wed May 20 16:02:50 2026 +0200

    CAMEL-23566: camel-jbang - Source examples from camel-jbang-examples 
repository (#23375)
    
    * CAMEL-23566: camel-jbang - Source examples from camel-jbang-examples 
repository
    
    Replace the 3 hardcoded built-in examples with a catalog-driven system
    sourcing examples from the apache/camel-jbang-examples repository.
    
    - Add ExampleHelper with catalog loading, filtering by name/tag/level,
      bundled extraction (with subdirectory support), and GitHub fetch
    - Refactor Run.java --example/--example-list to use the catalog JSON
    - --example-list now shows NAME, LEVEL, DESCRIPTION, SOURCE columns
      and supports filtering (e.g. --example-list beginner, --example-list ai)
    - Bundled examples (7) work offline, others fetch from GitHub on demand
    - Add -Psync-example-catalog Maven profile to download latest catalog
    - Bundle 7 curated examples with READMEs: timer-log, rest-api, cron-log,
      circuit-breaker, groovy, routes, xslt
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
    
    * CAMEL-23566: camel-jbang - Polish --example listing and remove 
--example-list
    
    Remove the separate --example-list flag. Using --example without a value
    now lists available examples. Group examples by level (beginner first),
    sort alphabetically within groups, and use emoji icons for source/docker
    indicators to give descriptions more room.
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
    
    ---------
    
    Co-authored-by: Claude Opus 4.6 <[email protected]>
---
 .../pages/jbang-commands/camel-jbang-debug.adoc    |   3 +-
 .../ROOT/pages/jbang-commands/camel-jbang-run.adoc |   3 +-
 dsl/camel-jbang/camel-jbang-core/pom.xml           |  30 ++
 .../META-INF/camel-jbang-commands-metadata.json    |   4 +-
 .../apache/camel/dsl/jbang/core/commands/Run.java  | 185 +++++++--
 .../camel/dsl/jbang/core/common/ExampleHelper.java | 164 ++++++++
 .../examples/camel-jbang-example-catalog.json      | 436 +++++++++++++++++++++
 .../resources/examples/circuit-breaker/README.adoc |  61 +++
 .../examples/circuit-breaker/route.camel.yaml      |  43 ++
 .../src/main/resources/examples/cron-log.yaml      |  10 -
 .../main/resources/examples/cron-log/README.adoc   |   7 +
 .../examples/cron-log/cron-log.camel.yaml          |  27 ++
 .../src/main/resources/examples/groovy/README.adoc |  76 ++++
 .../examples/groovy/application.properties         |  17 +
 .../resources/examples/groovy/groovy.camel.yaml    |  49 +++
 .../src/main/resources/examples/rest-api.yaml      |  21 -
 .../main/resources/examples/rest-api/README.adoc   |  12 +
 .../examples/rest-api/rest-api.camel.yaml          |  38 ++
 .../main/resources/examples/routes/Greeter.java    |  36 ++
 .../src/main/resources/examples/routes/README.adoc |  78 ++++
 .../src/main/resources/examples/routes/beans.yaml  |  22 ++
 .../resources/examples/routes/routes.camel.yaml    |  29 ++
 .../src/main/resources/examples/timer-log.yaml     |  10 -
 .../main/resources/examples/timer-log/README.adoc  |   7 +
 .../examples/timer-log/timer-log.camel.yaml        |  27 ++
 .../src/main/resources/examples/xslt/README.adoc   |  66 ++++
 .../resources/examples/xslt/consumer.camel.yaml    |  30 ++
 .../main/resources/examples/xslt/input/account.xml |  27 ++
 .../main/resources/examples/xslt/stylesheet.xsl    |  29 ++
 .../camel/dsl/jbang/core/commands/RunTest.java     |  32 +-
 .../dsl/jbang/core/common/ExampleHelperTest.java   | 155 ++++++++
 31 files changed, 1630 insertions(+), 104 deletions(-)

diff --git 
a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-debug.adoc 
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-debug.adoc
index 2ba7c40779cd..85f1d2a3722d 100644
--- a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-debug.adoc
+++ b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-debug.adoc
@@ -31,8 +31,7 @@ camel debug [options]
 | `--dep,--dependency` | Add additional dependencies |  | List
 | `--download` | Whether to allow automatic downloading JAR dependencies (over 
the internet) | true | boolean
 | `--empty` | Run an empty Camel without loading source files | false | boolean
-| `--example` | Run a built-in example by name (e.g., timer-log, rest-api). 
Use --example --list to show available examples. |  | String
-| `--example-list` | List available built-in examples |  | boolean
+| `--example` | Run an example by name, or list available examples when no 
name is given. |  | String
 | `--exclude` | Exclude files by name or pattern |  | List
 | `--fresh` | Make sure we use fresh (i.e. non-cached) resources | false | 
boolean
 | `--gav` | The Maven group:artifact:version (used during exporting) |  | 
String
diff --git 
a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-run.adoc 
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-run.adoc
index 936fd1385e3a..d729c8e3c418 100644
--- a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-run.adoc
+++ b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-run.adoc
@@ -29,8 +29,7 @@ camel run [options]
 | `--dep,--dependency` | Add additional dependencies |  | List
 | `--download` | Whether to allow automatic downloading JAR dependencies (over 
the internet) | true | boolean
 | `--empty` | Run an empty Camel without loading source files | false | boolean
-| `--example` | Run a built-in example by name (e.g., timer-log, rest-api). 
Use --example --list to show available examples. |  | String
-| `--example-list` | List available built-in examples |  | boolean
+| `--example` | Run an example by name, or list available examples when no 
name is given. |  | String
 | `--exclude` | Exclude files by name or pattern |  | List
 | `--fresh` | Make sure we use fresh (i.e. non-cached) resources | false | 
boolean
 | `--gav` | The Maven group:artifact:version (used during exporting) |  | 
String
diff --git a/dsl/camel-jbang/camel-jbang-core/pom.xml 
b/dsl/camel-jbang/camel-jbang-core/pom.xml
index 194fce245ab7..a59b10bcccbc 100644
--- a/dsl/camel-jbang/camel-jbang-core/pom.xml
+++ b/dsl/camel-jbang/camel-jbang-core/pom.xml
@@ -250,4 +250,34 @@
         </plugins>
     </build>
 
+    <profiles>
+        <profile>
+            <id>sync-example-catalog</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-antrun-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>download-example-catalog</id>
+                                <phase>generate-resources</phase>
+                                <goals>
+                                    <goal>run</goal>
+                                </goals>
+                                <configuration>
+                                    <target>
+                                        <get 
src="https://raw.githubusercontent.com/apache/camel-jbang-examples/main/camel-jbang-example-catalog.json";
+                                             
dest="${project.basedir}/src/main/resources/examples/camel-jbang-example-catalog.json"
+                                             usetimestamp="true"/>
+                                    </target>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+
 </project>
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
 
b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
index 055c7288eedb..e9e4c918ffd1 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
@@ -5,7 +5,7 @@
     { "name": "cmd", "fullName": "cmd", "description": "Performs commands in 
the running Camel integrations, such as start\/stop route, or change logging 
levels.", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.action.CamelAction", "options": [ { 
"names": "-h,--help", "description": "Display the help and sub-commands", 
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": 
"browse", "fullName": "cmd browse", "description": "Browse pending messages on 
endpoints [...]
     { "name": "completion", "fullName": "completion", "description": "Generate 
completion script for bash\/zsh", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.Complete", "options": [ { "names": 
"-h,--help", "description": "Display the help and sub-commands", "javaType": 
"boolean", "type": "boolean" } ] },
     { "name": "config", "fullName": "config", "description": "Get and set user 
configuration values", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.config.ConfigCommand", "options": [ { 
"names": "-h,--help", "description": "Display the help and sub-commands", 
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": "get", 
"fullName": "config get", "description": "Display user configuration value", 
"sourceClass": "org.apache.camel.dsl.jbang.core.commands.config. [...]
-    { "name": "debug", "fullName": "debug", "description": "Debug local Camel 
integration", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Debug", 
"options": [ { "names": "--ago", "description": "Use ago instead of yyyy-MM-dd 
HH:mm:ss in timestamp.", "javaType": "boolean", "type": "boolean" }, { "names": 
"--background", "description": "Run in the background", "defaultValue": 
"false", "javaType": "boolean", "type": "boolean" }, { "names": 
"--background-wait", "description": "To  [...]
+    { "name": "debug", "fullName": "debug", "description": "Debug local Camel 
integration", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Debug", 
"options": [ { "names": "--ago", "description": "Use ago instead of yyyy-MM-dd 
HH:mm:ss in timestamp.", "javaType": "boolean", "type": "boolean" }, { "names": 
"--background", "description": "Run in the background", "defaultValue": 
"false", "javaType": "boolean", "type": "boolean" }, { "names": 
"--background-wait", "description": "To  [...]
     { "name": "dependency", "fullName": "dependency", "description": "Displays 
all Camel dependencies required to run", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.DependencyCommand", "options": [ { 
"names": "-h,--help", "description": "Display the help and sub-commands", 
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": 
"copy", "fullName": "dependency copy", "description": "Copies all Camel 
dependencies required to run to a specific directory", "sourc [...]
     { "name": "dirty", "fullName": "dirty", "description": "Check if there are 
dirty files from previous Camel runs that did not terminate gracefully", 
"sourceClass": "org.apache.camel.dsl.jbang.core.commands.process.Dirty", 
"options": [ { "names": "--clean", "description": "Clean dirty files which are 
no longer in use", "defaultValue": "false", "javaType": "boolean", "type": 
"boolean" }, { "names": "-h,--help", "description": "Display the help and 
sub-commands", "javaType": "boolean", " [...]
     { "name": "doc", "fullName": "doc", "description": "Shows documentation 
for kamelet, component, and other Camel resources", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.catalog.CatalogDoc", "options": [ { 
"names": "--camel-version", "description": "To use a different Camel version 
than the default version", "javaType": "java.lang.String", "type": "string" }, 
{ "names": "--download", "description": "Whether to allow automatic downloading 
JAR dependencies (over the internet [...]
@@ -23,7 +23,7 @@
     { "name": "nano", "fullName": "nano", "description": "Nano editor to edit 
file", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Nano", 
"options": [ { "names": "-h,--help", "description": "Display the help and 
sub-commands", "javaType": "boolean", "type": "boolean" } ] },
     { "name": "plugin", "fullName": "plugin", "description": "Manage plugins 
that add sub-commands to this CLI", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.plugin.PluginCommand", "options": [ { 
"names": "-h,--help", "description": "Display the help and sub-commands", 
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": "add", 
"fullName": "plugin add", "description": "Add new plugin", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.plugin.PluginA [...]
     { "name": "ps", "fullName": "ps", "description": "List running Camel 
integrations", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.process.ListProcess", "options": [ { 
"names": "--json", "description": "Output in JSON Format", "javaType": 
"boolean", "type": "boolean" }, { "names": "--pid", "description": "List only 
pid in the output", "javaType": "boolean", "type": "boolean" }, { "names": 
"--remote", "description": "Break down counters into remote\/total pairs", 
"javaType": [...]
-    { "name": "run", "fullName": "run", "description": "Run as local Camel 
integration", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Run", 
"options": [ { "names": "--background", "description": "Run in the background", 
"defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names": 
"--background-wait", "description": "To wait for run in background to startup 
successfully, before returning", "defaultValue": "true", "javaType": "boolean", 
"type": "boolean" }, { [...]
+    { "name": "run", "fullName": "run", "description": "Run as local Camel 
integration", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Run", 
"options": [ { "names": "--background", "description": "Run in the background", 
"defaultValue": "false", "javaType": "boolean", "type": "boolean" }, { "names": 
"--background-wait", "description": "To wait for run in background to startup 
successfully, before returning", "defaultValue": "true", "javaType": "boolean", 
"type": "boolean" }, { [...]
     { "name": "sbom", "fullName": "sbom", "description": "Generate a CycloneDX 
or SPDX SBOM for a specific project", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.SBOMGenerator", "options": [ { 
"names": "--build-property", "description": "Maven build properties, ex. 
--build-property=prop1=foo", "javaType": "java.util.List", "type": "array" }, { 
"names": "--camel-spring-boot-version", "description": "Camel version to use 
with Spring Boot", "javaType": "java.lang.String", "type" [...]
     { "name": "script", "fullName": "script", "description": "Run Camel 
integration as shell script for terminal scripting", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.Script", "options": [ { "names": 
"--logging", "description": "Can be used to turn on logging (logs to file in 
<user home>\/.camel directory)", "defaultValue": "false", "javaType": 
"boolean", "type": "boolean" }, { "names": "--logging-level", "description": 
"Logging level (ERROR, WARN, INFO, DEBUG, TRACE)", "d [...]
     { "name": "shell", "fullName": "shell", "description": "Interactive Camel 
JBang shell.", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Shell", 
"options": [ { "names": "-h,--help", "description": "Display the help and 
sub-commands", "javaType": "boolean", "type": "boolean" } ] },
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
index 9876387f3ac8..2bba0b7f69a8 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
@@ -44,6 +44,7 @@ import org.apache.camel.catalog.CamelCatalog;
 import org.apache.camel.catalog.DefaultCamelCatalog;
 import org.apache.camel.dsl.jbang.core.common.CommandLineHelper;
 import org.apache.camel.dsl.jbang.core.common.EnvironmentHelper;
+import org.apache.camel.dsl.jbang.core.common.ExampleHelper;
 import org.apache.camel.dsl.jbang.core.common.JavaVersionCompletionCandidates;
 import org.apache.camel.dsl.jbang.core.common.LauncherHelper;
 import org.apache.camel.dsl.jbang.core.common.LoggingLevelCompletionCandidates;
@@ -99,7 +100,9 @@ import static 
org.apache.camel.dsl.jbang.core.common.GitHubHelper.fetchGithubUrl
                  "  camel run *",
                  "  camel run hello.java --dev",
                  "  camel run hello.java --port=8080",
-                 "  camel run https://gist.github.com/user/123456"; })
+                 "  camel run https://gist.github.com/user/123456";,
+                 "  camel run --example",
+                 "  camel run --example=timer-log" })
 public class Run extends CamelCommand {
 
     // special template for running camel-jbang in docker containers
@@ -338,14 +341,10 @@ public class Run extends CamelCommand {
     boolean skipPlugins;
 
     @Option(names = { "--example" },
-            description = "Run a built-in example by name (e.g., timer-log, 
rest-api). Use --example --list to show available examples.",
+            description = "Run an example by name, or list available examples 
when no name is given.",
             arity = "0..1", fallbackValue = "")
     String example;
 
-    @Option(names = { "--example-list" },
-            description = "List available built-in examples")
-    boolean exampleList;
-
     public Run(CamelJBangMain main) {
         super(main);
     }
@@ -366,8 +365,8 @@ public class Run extends CamelCommand {
     @Override
     public Integer doCall() throws Exception {
         // handle --example
-        if (exampleList || (example != null && example.isEmpty())) {
-            return listExamples();
+        if (example != null && example.isEmpty()) {
+            return listExamples(null);
         }
         if (example != null) {
             return runExample();
@@ -380,58 +379,162 @@ public class Run extends CamelCommand {
         return run();
     }
 
-    private int listExamples() {
-        printer().println("Available built-in examples:");
+    private int listExamples(String filter) {
+        List<JsonObject> catalog = ExampleHelper.loadCatalog();
+        if (catalog.isEmpty()) {
+            printer().printErr("No example catalog found.");
+            return 1;
+        }
+
+        List<JsonObject> filtered = ExampleHelper.filterExamples(catalog, 
filter);
+        if (filtered.isEmpty()) {
+            printer().printErr("No examples matching: " + filter);
+            return 1;
+        }
+
+        if (filter != null && !filter.isEmpty()) {
+            printer().println("Examples matching '" + filter + "':");
+        } else {
+            printer().println("Available examples:");
+        }
+
+        Map<String, List<JsonObject>> groups = new LinkedHashMap<>();
+        for (String level : new String[] { "beginner", "intermediate", 
"advanced" }) {
+            groups.put(level, new ArrayList<>());
+        }
+        for (JsonObject entry : filtered) {
+            String level = entry.getString("level");
+            if (level == null) {
+                level = "intermediate";
+            }
+            groups.computeIfAbsent(level, k -> new ArrayList<>()).add(entry);
+        }
+
+        for (Map.Entry<String, List<JsonObject>> group : groups.entrySet()) {
+            List<JsonObject> entries = group.getValue();
+            if (entries.isEmpty()) {
+                continue;
+            }
+            entries.sort(Comparator.comparing(e -> e.getString("name")));
+            printer().println();
+            printer().println(group.getKey().substring(0, 1).toUpperCase() + 
group.getKey().substring(1) + ":");
+            printer().printf("       %-30s %s%n", "NAME", "DESCRIPTION");
+            printer().printf("       %-30s %s%n", "----", "-----------");
+            for (JsonObject entry : entries) {
+                String eName = entry.getString("name");
+                String desc = entry.getString("description");
+                StringBuilder icons = new StringBuilder();
+                if (ExampleHelper.isBundled(entry)) {
+                    icons.append("📦");
+                } else {
+                    icons.append("🌐");
+                }
+                if (ExampleHelper.requiresDocker(entry)) {
+                    icons.append("🐳");
+                } else {
+                    icons.append("  ");
+                }
+                printer().printf("  %s %-30s %s%n", icons, eName, desc);
+            }
+        }
         printer().println();
-        printer().printf("  %-20s %s%n", "timer-log", "Simple timer that logs 
messages every second");
-        printer().printf("  %-20s %s%n", "rest-api", "REST API with hello 
endpoints");
-        printer().printf("  %-20s %s%n", "cron-log", "Scheduled task that logs 
every 5 seconds");
+        printer().println("  📦 = bundled (works offline)  🌐 = online (fetched 
from GitHub)  🐳 = requires Docker");
         printer().println();
-        printer().println("Usage: camel run --example <name>");
-        printer().println("       camel run --example <name> --dev");
+        printer().println("Usage: camel run --example=<name>");
+        printer().println("       camel run --example=<name> --dev");
         return 0;
     }
 
-    private static final List<String> EXAMPLE_NAMES = List.of("timer-log", 
"rest-api", "cron-log");
-
     private int runExample() throws Exception {
-        String resourcePath = "examples/" + example + ".yaml";
-        InputStream is = 
Run.class.getClassLoader().getResourceAsStream(resourcePath);
-        if (is == null) {
-            List<String> suggestions
-                    = SuggestSimilarHelper.didYouMean(EXAMPLE_NAMES, example);
+        List<JsonObject> catalog = ExampleHelper.loadCatalog();
+        JsonObject entry = ExampleHelper.findExample(catalog, example);
+
+        if (entry == null) {
+            List<String> names = ExampleHelper.getExampleNames(catalog);
+            List<String> suggestions = SuggestSimilarHelper.didYouMean(names, 
example);
             if (!suggestions.isEmpty()) {
                 printer().printErr("Unknown example: " + example + ". Did you 
mean? " + String.join(", ", suggestions));
             } else {
                 printer().printErr("Unknown example: " + example);
             }
-            printer().printErr("Run 'camel run --example-list' to see 
available examples.");
+            printer().printErr("Run 'camel run --example' to see available 
examples.");
             return 1;
         }
 
-        // extract example to a temp file and run it
-        Path tempDir = Files.createTempDirectory("camel-example-");
-        Path exampleFile = tempDir.resolve(example + ".yaml");
+        if (ExampleHelper.isBundled(entry)) {
+            return runBundledExample(entry);
+        } else {
+            return runGithubExample(entry);
+        }
+    }
+
+    private int runBundledExample(JsonObject entry) throws Exception {
+        String eName = entry.getString("name");
+        Path tempDir = ExampleHelper.extractBundledExample(entry);
+        List<String> exampleFiles = ExampleHelper.getFiles(entry);
+
+        printer().println("Running example: " + eName);
+        for (String f : exampleFiles) {
+            files.add(tempDir.resolve(f).toString());
+        }
+        if ("CamelJBang".equals(name)) {
+            name = eName;
+        }
+
+        if (!exportRun) {
+            printConfigurationValues("Running integration with the following 
configuration:");
+        }
+        return run();
+    }
+
+    private int runGithubExample(JsonObject entry) throws Exception {
+        String eName = entry.getString("name");
+        String url = ExampleHelper.getGithubUrl(entry);
+
+        printer().println("Fetching example from GitHub: " + eName);
+        if (ExampleHelper.requiresDocker(entry)) {
+            printer().println("Note: this example requires Docker/Podman");
+        }
+
+        StringJoiner routes = new StringJoiner(",");
+        StringJoiner kamelets = new StringJoiner(",");
+        StringJoiner properties = new StringJoiner(",");
         try {
-            String content = IOHelper.loadText(is);
-            IOHelper.close(is);
-            Files.writeString(exampleFile, content);
+            fetchGithubUrls(url, routes, kamelets, properties);
+        } catch (Exception e) {
+            printer().printErr("Failed to fetch example from GitHub: " + 
e.getMessage());
+            printer().printErr("This example requires an internet 
connection.");
+            return 1;
+        }
 
-            printer().println("Running example: " + example);
-            files.add(exampleFile.toString());
-            if ("CamelJBang".equals(name)) {
-                name = example;
-            }
+        if (routes.length() == 0 && kamelets.length() == 0 && 
properties.length() == 0) {
+            printer().printErr("No files found for example: " + eName);
+            return 1;
+        }
 
-            if (!exportRun) {
-                printConfigurationValues("Running integration with the 
following configuration:");
+        if (routes.length() > 0) {
+            for (String r : routes.toString().split(",")) {
+                files.add(r);
             }
-            return run();
-        } finally {
-            // clean up temp files on JVM exit
-            exampleFile.toFile().deleteOnExit();
-            tempDir.toFile().deleteOnExit();
         }
+        if (kamelets.length() > 0) {
+            for (String k : kamelets.toString().split(",")) {
+                files.add(k);
+            }
+        }
+        if (properties.length() > 0) {
+            for (String p : properties.toString().split(",")) {
+                files.add(p);
+            }
+        }
+        if ("CamelJBang".equals(name)) {
+            name = eName;
+        }
+
+        if (!exportRun) {
+            printConfigurationValues("Running integration with the following 
configuration:");
+        }
+        return run();
     }
 
     public Integer runExport() throws Exception {
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/ExampleHelper.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/ExampleHelper.java
new file mode 100644
index 000000000000..3ce60b684c1e
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/ExampleHelper.java
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.jbang.core.common;
+
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.camel.util.IOHelper;
+import org.apache.camel.util.json.JsonArray;
+import org.apache.camel.util.json.JsonObject;
+import org.apache.camel.util.json.Jsoner;
+
+public final class ExampleHelper {
+
+    private static final String CATALOG_RESOURCE = 
"examples/camel-jbang-example-catalog.json";
+    private static final String GITHUB_EXAMPLES_URL
+            = "https://github.com/apache/camel-jbang-examples/tree/main/";;
+
+    private ExampleHelper() {
+    }
+
+    public static List<JsonObject> loadCatalog() {
+        List<JsonObject> catalog = new ArrayList<>();
+        try (InputStream is = 
ExampleHelper.class.getClassLoader().getResourceAsStream(CATALOG_RESOURCE)) {
+            if (is == null) {
+                return catalog;
+            }
+            String json = IOHelper.loadText(is);
+            JsonArray array = (JsonArray) Jsoner.deserialize(json);
+            for (Object item : array) {
+                catalog.add((JsonObject) item);
+            }
+        } catch (Exception e) {
+            // ignore
+        }
+        return catalog;
+    }
+
+    public static JsonObject findExample(List<JsonObject> catalog, String 
name) {
+        for (JsonObject entry : catalog) {
+            if (name.equals(entry.getString("name"))) {
+                return entry;
+            }
+        }
+        return null;
+    }
+
+    public static List<String> getExampleNames(List<JsonObject> catalog) {
+        List<String> names = new ArrayList<>();
+        for (JsonObject entry : catalog) {
+            names.add(entry.getString("name"));
+        }
+        return names;
+    }
+
+    public static List<JsonObject> filterExamples(List<JsonObject> catalog, 
String filter) {
+        if (filter == null || filter.isEmpty()) {
+            return catalog;
+        }
+        String lowerFilter = filter.toLowerCase();
+        List<JsonObject> result = new ArrayList<>();
+        for (JsonObject entry : catalog) {
+            if (matches(entry, lowerFilter)) {
+                result.add(entry);
+            }
+        }
+        return result;
+    }
+
+    @SuppressWarnings("unchecked")
+    private static boolean matches(JsonObject entry, String filter) {
+        String name = entry.getString("name");
+        if (name != null && name.toLowerCase().contains(filter)) {
+            return true;
+        }
+        String title = entry.getString("title");
+        if (title != null && title.toLowerCase().contains(filter)) {
+            return true;
+        }
+        String desc = entry.getString("description");
+        if (desc != null && desc.toLowerCase().contains(filter)) {
+            return true;
+        }
+        String level = entry.getString("level");
+        if (level != null && level.toLowerCase().contains(filter)) {
+            return true;
+        }
+        Collection<String> tags = (Collection<String>) entry.get("tags");
+        if (tags != null) {
+            for (String tag : tags) {
+                if (tag.toLowerCase().contains(filter)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public static boolean isBundled(JsonObject entry) {
+        Boolean bundled = entry.getBoolean("bundled");
+        return bundled != null && bundled;
+    }
+
+    public static boolean requiresDocker(JsonObject entry) {
+        Boolean docker = entry.getBoolean("requiresDocker");
+        return docker != null && docker;
+    }
+
+    @SuppressWarnings("unchecked")
+    public static List<String> getFiles(JsonObject entry) {
+        Collection<String> files = (Collection<String>) entry.get("files");
+        if (files == null) {
+            return List.of();
+        }
+        return new ArrayList<>(files);
+    }
+
+    public static Path extractBundledExample(JsonObject entry) throws 
Exception {
+        String name = entry.getString("name");
+        List<String> fileNames = getFiles(entry);
+        Path tempDir = Files.createTempDirectory("camel-example-");
+
+        for (String fileName : fileNames) {
+            String resourcePath = "examples/" + name + "/" + fileName;
+            try (InputStream is = 
ExampleHelper.class.getClassLoader().getResourceAsStream(resourcePath)) {
+                if (is != null) {
+                    String content = IOHelper.loadText(is);
+                    Path targetFile = tempDir.resolve(fileName);
+                    // create parent dirs for nested files like 
input/account.xml
+                    Files.createDirectories(targetFile.getParent());
+                    Files.writeString(targetFile, content);
+                    targetFile.toFile().deleteOnExit();
+                    targetFile.getParent().toFile().deleteOnExit();
+                }
+            }
+        }
+
+        tempDir.toFile().deleteOnExit();
+        return tempDir;
+    }
+
+    public static String getGithubUrl(JsonObject entry) {
+        return GITHUB_EXAMPLES_URL + entry.getString("name");
+    }
+
+}
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/camel-jbang-example-catalog.json
 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/camel-jbang-example-catalog.json
new file mode 100644
index 000000000000..cdd5c70d7a03
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/camel-jbang-example-catalog.json
@@ -0,0 +1,436 @@
+[
+    {
+        "name": "artemis",
+        "title": "Apache ActiveMQ Artemis",
+        "description": "Setup connection factory to a remote Apache ActiveMQ 
Artemis messaging broker",
+        "level": "intermediate",
+        "tags": [
+            "messaging",
+            "jms",
+            "artemis"
+        ],
+        "bundled": false,
+        "requiresDocker": false,
+        "files": [
+            "README.adoc",
+            "application.properties",
+            "consumer.camel.yaml",
+            "producer.camel.yaml"
+        ]
+    },
+    {
+        "name": "aws/aws-s3-event-based",
+        "title": "AWS S3 CDC",
+        "description": "Consume S3 events using EventBridge and SQS for change 
data capture",
+        "level": "advanced",
+        "tags": [
+            "aws",
+            "s3",
+            "sqs",
+            "eventbridge",
+            "cloud"
+        ],
+        "bundled": false,
+        "requiresDocker": false,
+        "files": [
+            "README.adoc",
+            "application.properties",
+            "aws-s3-cdc-log.camel.yaml",
+            "example-file.txt",
+            "policy-queue.json",
+            "terraform/main.tf"
+        ]
+    },
+    {
+        "name": "aws/aws-sqs",
+        "title": "AWS SQS Sink",
+        "description": "Push messages to AWS SQS queue via HTTP service",
+        "level": "advanced",
+        "tags": [
+            "aws",
+            "sqs",
+            "http",
+            "cloud"
+        ],
+        "bundled": false,
+        "requiresDocker": false,
+        "files": [
+            "README.adoc",
+            "application.properties",
+            "http-to-aws-sqs.camel.yaml"
+        ]
+    },
+    {
+        "name": "circuit-breaker",
+        "title": "Circuit Breaker",
+        "description": "Use the circuit breaker EIP for fault tolerance",
+        "level": "beginner",
+        "tags": [
+            "eip",
+            "resilience"
+        ],
+        "bundled": true,
+        "requiresDocker": false,
+        "files": [
+            "README.adoc",
+            "route.camel.yaml"
+        ]
+    },
+    {
+        "name": "cron-log",
+        "title": "Cron Log",
+        "description": "Scheduled task that logs every 5 seconds",
+        "level": "beginner",
+        "tags": [
+            "beginner",
+            "timer",
+            "cron",
+            "log"
+        ],
+        "bundled": true,
+        "requiresDocker": false,
+        "files": [
+            "README.adoc",
+            "cron-log.camel.yaml"
+        ]
+    },
+    {
+        "name": "docling-langchain4j-rag",
+        "title": "Document Analysis with Docling and LangChain4j RAG",
+        "description": "RAG workflow combining Docling document conversion 
with LangChain4j and Ollama",
+        "level": "advanced",
+        "tags": [
+            "ai",
+            "rag",
+            "langchain4j",
+            "docling"
+        ],
+        "bundled": false,
+        "requiresDocker": true,
+        "files": [
+            "README.adoc",
+            "application.properties",
+            "compose.yaml",
+            "docling-langchain4j-rag.yaml",
+            "sample.md"
+        ]
+    },
+    {
+        "name": "financial-doc-analyzer",
+        "title": "Financial Document Analyzer",
+        "description": "Automated financial document analysis with Docling, 
LangChain4j, and market data",
+        "level": "advanced",
+        "tags": [
+            "ai",
+            "langchain4j",
+            "docling",
+            "finance"
+        ],
+        "bundled": false,
+        "requiresDocker": false,
+        "files": [
+            "README.adoc",
+            "application.properties",
+            "examples/banking-sector-brief.pdf",
+            "examples/magnificent-seven-update.pdf",
+            "examples/semiconductor-sector-analysis.pdf",
+            "examples/tesla-q3-2024.pdf",
+            "financial-doc-analyzer.yaml"
+        ]
+    },
+    {
+        "name": "ftp",
+        "title": "ActiveMQ to FTP",
+        "description": "Integrate ActiveMQ messaging with an FTP server",
+        "level": "intermediate",
+        "tags": [
+            "messaging",
+            "ftp",
+            "activemq"
+        ],
+        "bundled": false,
+        "requiresDocker": true,
+        "files": [
+            "README.adoc",
+            "application.properties",
+            "compose.yaml",
+            "ftp.camel.yaml",
+            "jbang.properties"
+        ]
+    },
+    {
+        "name": "groovy",
+        "title": "Groovy",
+        "description": "Use Groovy with extra dependencies and content-based 
routing",
+        "level": "beginner",
+        "tags": [
+            "language",
+            "groovy",
+            "eip"
+        ],
+        "bundled": true,
+        "requiresDocker": false,
+        "files": [
+            "README.adoc",
+            "application.properties",
+            "groovy.camel.yaml"
+        ]
+    },
+    {
+        "name": "keycloak-introspection-rest",
+        "title": "Keycloak Token Introspection REST API",
+        "description": "Secure REST APIs with Keycloak OAuth 2.0 token 
introspection",
+        "level": "advanced",
+        "tags": [
+            "security",
+            "keycloak",
+            "rest",
+            "oauth"
+        ],
+        "bundled": false,
+        "requiresDocker": false,
+        "files": [
+            "README.adoc",
+            "application.properties",
+            "rest-api.camel.yaml"
+        ]
+    },
+    {
+        "name": "keycloak-security-rest",
+        "title": "Keycloak Security REST API",
+        "description": "Secure REST APIs with Keycloak authentication and 
authorization",
+        "level": "advanced",
+        "tags": [
+            "security",
+            "keycloak",
+            "rest",
+            "oauth"
+        ],
+        "bundled": false,
+        "requiresDocker": false,
+        "files": [
+            "README.adoc",
+            "application.properties",
+            "rest-api.camel.yaml"
+        ]
+    },
+    {
+        "name": "mqtt",
+        "title": "MQTT",
+        "description": "Receive MQTT events from an external MQTT broker",
+        "level": "intermediate",
+        "tags": [
+            "messaging",
+            "mqtt",
+            "iot"
+        ],
+        "bundled": false,
+        "requiresDocker": true,
+        "files": [
+            "README.adoc",
+            "application.properties",
+            "compose.yaml",
+            "infra/mosquitto.conf",
+            "mqtt.camel.yaml",
+            "start.sh"
+        ]
+    },
+    {
+        "name": "openai/pii-redaction",
+        "title": "OpenAI PII Redaction",
+        "description": "Redact personal identifiable information from text 
using OpenAI-compatible LLMs",
+        "level": "advanced",
+        "tags": [
+            "ai",
+            "openai",
+            "privacy",
+            "security"
+        ],
+        "bundled": false,
+        "requiresDocker": false,
+        "files": [
+            "README.adoc",
+            "application.properties",
+            "pii-redaction.camel.yaml",
+            "pii.schema.json"
+        ]
+    },
+    {
+        "name": "openapi/client",
+        "title": "OpenAPI Client",
+        "description": "REST client generated from an OpenAPI specification",
+        "level": "intermediate",
+        "tags": [
+            "rest",
+            "openapi",
+            "client"
+        ],
+        "bundled": false,
+        "requiresDocker": false,
+        "files": [
+            "README.adoc",
+            "application.properties",
+            "examples/1001.json",
+            "petstore-api.json",
+            "petstore-client.camel.yaml"
+        ]
+    },
+    {
+        "name": "openapi/server",
+        "title": "OpenAPI Server",
+        "description": "REST service implemented from an OpenAPI 
specification",
+        "level": "intermediate",
+        "tags": [
+            "rest",
+            "openapi",
+            "server"
+        ],
+        "bundled": false,
+        "requiresDocker": false,
+        "files": [
+            "README.adoc",
+            "application.properties",
+            "examples/pet/1000.json",
+            "petstore-api.json",
+            "petstore.camel.yaml"
+        ]
+    },
+    {
+        "name": "rest-api",
+        "title": "REST API",
+        "description": "REST API with hello endpoints",
+        "level": "beginner",
+        "tags": [
+            "beginner",
+            "rest",
+            "http"
+        ],
+        "bundled": true,
+        "requiresDocker": false,
+        "files": [
+            "README.adoc",
+            "rest-api.camel.yaml"
+        ]
+    },
+    {
+        "name": "routes",
+        "title": "Routes",
+        "description": "Define routes in YAML with Java beans",
+        "level": "beginner",
+        "tags": [
+            "beginner",
+            "yaml",
+            "bean"
+        ],
+        "bundled": true,
+        "requiresDocker": false,
+        "files": [
+            "Greeter.java",
+            "README.adoc",
+            "beans.yaml",
+            "routes.camel.yaml"
+        ]
+    },
+    {
+        "name": "smart-log-analyzer",
+        "title": "Smart Log Analyzer",
+        "description": "Intelligent observability correlating OpenTelemetry 
logs and traces with LLM analysis",
+        "level": "advanced",
+        "tags": [
+            "ai",
+            "observability",
+            "opentelemetry",
+            "logging"
+        ],
+        "bundled": false,
+        "requiresDocker": false,
+        "files": [
+            "README.adoc",
+            "analyzer/application-dev.properties",
+            "analyzer/error-analyzer.camel.yaml",
+            "containers/caches/infinispan-events-config.json",
+            "containers/caches/infinispan-events-to-process-config.json",
+            "containers/docker-compose.yaml",
+            "containers/otel-collector-config.yaml",
+            "correlator/application-dev.properties",
+            "correlator/correlated-log-schema.json",
+            "correlator/correlated-trace-schema.json",
+            "correlator/infinispan.camel.yaml",
+            "correlator/kafka-ca-cert.pem",
+            "correlator/kaoto-datamapper-4a94acc3.xsl",
+            "correlator/kaoto-datamapper-8f5bb2dd.xsl",
+            "correlator/logs-mapper.camel.yaml",
+            "correlator/otel-log-record-schema.json",
+            "correlator/otel-logs-schema.json",
+            "correlator/otel-span-schema.json",
+            "correlator/otel-traces-schema.json",
+            "correlator/traces-mapper.camel.yaml",
+            "first-iteration/analyzer.camel.yaml",
+            "first-iteration/application.properties",
+            "first-iteration/load-generator.camel.yaml",
+            "log-generator/agent.properties",
+            "log-generator/application-dev.properties",
+            "log-generator/log-generator.camel.yaml",
+            "log-generator/opentelemetry-javaagent.jar",
+            "ui-console/application-dev.properties",
+            "ui-console/index.html",
+            "ui-console/jms-file-storage.camel.yaml",
+            "ui-console/rest-api.camel.yaml"
+        ]
+    },
+    {
+        "name": "sql",
+        "title": "SQL Database",
+        "description": "Use a SQL database with Camel and Postgres",
+        "level": "intermediate",
+        "tags": [
+            "database",
+            "sql",
+            "postgres"
+        ],
+        "bundled": false,
+        "requiresDocker": true,
+        "files": [
+            "README.adoc",
+            "application.properties",
+            "compose.yaml",
+            "sql.camel.yaml"
+        ]
+    },
+    {
+        "name": "timer-log",
+        "title": "Timer Log",
+        "description": "Simple timer that logs a hello message every second",
+        "level": "beginner",
+        "tags": [
+            "beginner",
+            "timer",
+            "log"
+        ],
+        "bundled": true,
+        "requiresDocker": false,
+        "files": [
+            "README.adoc",
+            "timer-log.camel.yaml"
+        ]
+    },
+    {
+        "name": "xslt",
+        "title": "XSLT Transformation",
+        "description": "Basic XML transformation using XSLT style sheets",
+        "level": "beginner",
+        "tags": [
+            "transformation",
+            "xml",
+            "xslt"
+        ],
+        "bundled": true,
+        "requiresDocker": false,
+        "files": [
+            "README.adoc",
+            "consumer.camel.yaml",
+            "input/account.xml",
+            "stylesheet.xsl"
+        ]
+    }
+]
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/circuit-breaker/README.adoc
 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/circuit-breaker/README.adoc
new file mode 100644
index 000000000000..cca5a275abf1
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/circuit-breaker/README.adoc
@@ -0,0 +1,61 @@
+== Circuit Breaker
+
+This example shows how Camel JBang can use circuit breaker EIP.
+
+=== Install JBang
+
+First install JBang according to https://www.jbang.dev
+
+When JBang is installed then you should be able to run from a shell:
+
+[source,sh]
+----
+$ jbang --version
+----
+
+This will output the version of JBang.
+
+To run this example you can either install Camel on JBang via:
+
+[source,sh]
+----
+$ jbang app install camel@apache/camel
+----
+
+Which allows to run Camel JBang with `camel` as shown below.
+
+=== How to run
+
+You can run this example using:
+
+[source,sh]
+----
+$ camel run *
+----
+
+While the Camel integration is running, then from another terminal type:
+
+[source,sh]
+----
+$ camel get circuit-breaker
+----
+
+Which then output the state of the circuit breaker. You can run this command 
with `--watch` and see
+how the state of the circuit breaker changes from closed to open due to many 
failures.
+
+[source,sh]
+----
+$ camel get circuit-breaker --watch
+----
+
+
+
+=== Help and contributions
+
+If you hit any problem using Camel or have some feedback, then please
+https://camel.apache.org/community/support/[let us know].
+
+We also love contributors, so
+https://camel.apache.org/community/contributing/[get involved] :-)
+
+The Camel riders!
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/circuit-breaker/route.camel.yaml
 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/circuit-breaker/route.camel.yaml
new file mode 100644
index 000000000000..7566bd348447
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/circuit-breaker/route.camel.yaml
@@ -0,0 +1,43 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+- route:
+    from:
+      uri: timer:start
+      steps:
+        - setBody:
+            expression:
+              constant:
+                expression: Hello Camel
+        - circuitBreaker:
+            resilience4jConfiguration:
+              minimumNumberOfCalls: 10
+              failureRateThreshold: 50
+              waitDurationInOpenState: 20
+            steps:
+              - filter:
+                  expression:
+                    simple:
+                      expression: ${random(10)} > 2
+                  steps:
+                    - throwException:
+                        message: Forced error
+                        exceptionType: java.lang.IllegalArgumentException
+        - log:
+            message: "${body} (CircuitBreaker is open: 
${exchangeProperty.CamelCircuitBreakerResponseShortCircuited})"
+      parameters:
+        period: 1000
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/cron-log.yaml 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/cron-log.yaml
deleted file mode 100644
index c31bdb1cec3d..000000000000
--- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/cron-log.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
-- route:
-    id: cron-log
-    from:
-      uri: timer:cron
-      parameters:
-        period: "5000"
-      steps:
-        - setBody:
-            simple: "Scheduled task running at ${date:now:HH:mm:ss}"
-        - log: "${body}"
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/cron-log/README.adoc
 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/cron-log/README.adoc
new file mode 100644
index 000000000000..7a5721140db9
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/cron-log/README.adoc
@@ -0,0 +1,7 @@
+== Cron Log
+
+This example shows a scheduled task that logs the current time every 5 seconds.
+
+=== How to run
+
+    camel run cron-log.camel.yaml
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/cron-log/cron-log.camel.yaml
 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/cron-log/cron-log.camel.yaml
new file mode 100644
index 000000000000..fd729c9f5ea0
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/cron-log/cron-log.camel.yaml
@@ -0,0 +1,27 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+- route:
+    id: cron-log
+    from:
+      uri: timer:cron
+      parameters:
+        period: "5000"
+      steps:
+        - setBody:
+            simple: "Scheduled task running at ${date:now:HH:mm:ss}"
+        - log: "${body}"
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/groovy/README.adoc
 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/groovy/README.adoc
new file mode 100644
index 000000000000..d6910f56215e
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/groovy/README.adoc
@@ -0,0 +1,76 @@
+== Groovy
+
+This example shows how to use Groovy with extra dependencies in Camel JBang.
+
+The route uses `EmailValidator` from 
https://commons.apache.org/proper/commons-validator/[Apache Commons Validator]
+to validate an email address and route the message accordingly using 
content-based routing.
+
+The extra dependency is declared in `application.properties` using the
+`camel.jbang.dependencies` property:
+
+[source,properties]
+----
+camel.jbang.dependencies=commons-validator:commons-validator:1.10.1
+----
+
+=== Install JBang
+
+First install JBang according to https://www.jbang.dev
+
+When JBang is installed then you should be able to run from a shell:
+
+[source,sh]
+----
+$ jbang --version
+----
+
+This will output the version of JBang.
+
+To run this example you can either install Camel on JBang via:
+
+[source,sh]
+----
+$ jbang app install camel@apache/camel
+----
+
+Which allows to run Camel JBang with `camel` as shown below.
+
+=== How to run
+
+You can run this example using:
+
+[source,sh]
+----
+$ camel run *
+----
+
+To see the invalid email branch, edit `groovy.camel.yaml` and change the 
`contactEmail` header in the `once` URI to an invalid value:
+
+[source,yaml]
+----
+uri: once:validate?header.contactEmail=not-a-valid-email
+----
+
+You can also declare dependencies as a modeline comment at the top of the YAML 
route file:
+
+[source,yaml]
+----
+#//DEPS commons-validator:commons-validator:1.10.1
+----
+
+Or pass the dependency on the command line:
+
+[source,sh]
+----
+$ camel run groovy.camel.yaml --dep=commons-validator:commons-validator:1.10.1
+----
+
+=== Help and contributions
+
+If you hit any problem using Camel or have some feedback, then please
+https://camel.apache.org/community/support/[let us know].
+
+We also love contributors, so
+https://camel.apache.org/community/contributing/[get involved] :-)
+
+The Camel riders!
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/groovy/application.properties
 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/groovy/application.properties
new file mode 100644
index 000000000000..0bea6e4cd400
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/groovy/application.properties
@@ -0,0 +1,17 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements.  See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License.  You may obtain a copy of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+camel.jbang.dependencies=commons-validator:commons-validator:1.10.1
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/groovy/groovy.camel.yaml
 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/groovy/groovy.camel.yaml
new file mode 100644
index 000000000000..2b89a31150bb
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/groovy/groovy.camel.yaml
@@ -0,0 +1,49 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+- route:
+    id: route-1681
+    from:
+      id: from-1133
+      uri: once
+      parameters:
+        name: validate
+      steps:
+        - setHeader:
+            id: setHeader-4262
+            constant:
+              expression: [email protected]
+            name: contactEmail
+        - choice:
+            id: choice-1178
+            otherwise:
+              id: otherwise-1234
+              steps:
+                - log:
+                    id: log-3646
+                    message: "Invalid email: ${header.contactEmail}"
+            when:
+              - id: when-1441
+                steps:
+                  - log:
+                      id: log-2349
+                      message: "Valid contact: ${header.contactEmail}"
+                groovy:
+                  expression: >-
+                    import org.apache.commons.validator.routines.EmailValidator
+
+                    
EmailValidator.getInstance().isValid(request.headers['contactEmail'])
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/rest-api.yaml 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/rest-api.yaml
deleted file mode 100644
index 2e1035cf1f0f..000000000000
--- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/rest-api.yaml
+++ /dev/null
@@ -1,21 +0,0 @@
-- rest:
-    path: /api
-    get:
-      - path: /hello
-        to: direct:hello
-      - path: /hello/{name}
-        to: direct:hello-name
-- route:
-    id: hello
-    from:
-      uri: direct:hello
-      steps:
-        - setBody:
-            constant: "Hello from Camel REST API!"
-- route:
-    id: hello-name
-    from:
-      uri: direct:hello-name
-      steps:
-        - setBody:
-            simple: "Hello ${header.name} from Camel REST API!"
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/rest-api/README.adoc
 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/rest-api/README.adoc
new file mode 100644
index 000000000000..c68c2872843b
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/rest-api/README.adoc
@@ -0,0 +1,12 @@
+== REST API
+
+This example shows a REST API with hello endpoints.
+
+=== How to run
+
+    camel run rest-api.camel.yaml
+
+=== Try it
+
+    curl http://localhost:8080/api/hello
+    curl http://localhost:8080/api/hello/World
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/rest-api/rest-api.camel.yaml
 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/rest-api/rest-api.camel.yaml
new file mode 100644
index 000000000000..dda5c6cba0fc
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/rest-api/rest-api.camel.yaml
@@ -0,0 +1,38 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+- rest:
+    path: /api
+    get:
+      - path: /hello
+        to: direct:hello
+      - path: /hello/{name}
+        to: direct:hello-name
+- route:
+    id: hello
+    from:
+      uri: direct:hello
+      steps:
+        - setBody:
+            constant: "Hello from Camel REST API!"
+- route:
+    id: hello-name
+    from:
+      uri: direct:hello-name
+      steps:
+        - setBody:
+            simple: "Hello ${header.name} from Camel REST API!"
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/routes/Greeter.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/routes/Greeter.java
new file mode 100644
index 000000000000..1fe603c4eeef
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/routes/Greeter.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package camel.example;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+
+public class Greeter implements Processor {
+
+    private String message;
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    @Override
+    public void process(Exchange exchange) throws Exception {
+        String body = exchange.getIn().getBody(String.class);
+        exchange.getIn().setBody(message + " " + body);
+    }
+
+}
\ No newline at end of file
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/routes/README.adoc
 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/routes/README.adoc
new file mode 100644
index 000000000000..5cf864ca5b61
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/routes/README.adoc
@@ -0,0 +1,78 @@
+== Routes
+
+This example shows how routes are defined in Yaml.
+
+=== Install JBang
+
+First install JBang according to https://www.jbang.dev
+
+When JBang is installed then you should be able to run from a shell:
+
+[source,sh]
+----
+$ jbang --version
+----
+
+This will output the version of JBang.
+
+To run this example you can either install Camel on JBang via:
+
+[source,sh]
+----
+$ jbang app install camel@apache/camel
+----
+
+Which allows to run Camel JBang with `camel` as shown below.
+
+=== How to run
+
+You can run this example using:
+
+[source,sh]
+----
+$ camel run *
+----
+
+Camel will start a route that periodically provides a greeting message.
+
+=== Live reload
+
+You can run the example in dev mode which allows you to edit the example,
+and hot-reload when the file is saved.
+
+[source,sh]
+----
+$ camel run * --dev
+----
+
+=== Run directly from GitHub
+
+The example can also be run directly by referring to the GitHub URL as shown:
+
+[source,sh]
+----
+$ camel run https://github.com/apache/camel-jbang-examples/tree/main/routes
+----
+
+=== Developer Web Console
+
+You can enable the developer console via `--console` flag as show:
+
+[source,sh]
+----
+$ camel run * --console
+----
+
+Then you can browse: http://localhost:8080/q/dev to introspect the running 
Camel Application.
+Under "beans" Camel should display bean `greeter`.
+
+
+=== Help and contributions
+
+If you hit any problem using Camel or have some feedback, then please
+https://camel.apache.org/community/support/[let us know].
+
+We also love contributors, so
+https://camel.apache.org/community/contributing/[get involved] :-)
+
+The Camel riders!
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/routes/beans.yaml
 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/routes/beans.yaml
new file mode 100644
index 000000000000..70bc6a6d5d35
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/routes/beans.yaml
@@ -0,0 +1,22 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+- beans:
+  - name: "greeter"
+    type: "camel.example.Greeter"
+    properties:
+      message: 'Hello!'
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/routes/routes.camel.yaml
 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/routes/routes.camel.yaml
new file mode 100644
index 000000000000..a1bfb7dcb291
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/routes/routes.camel.yaml
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+- route:
+    id: greeting-route
+    from:
+      uri: timer:start
+      parameters:
+        period: 1000
+      steps:
+        - setBody:
+            simple: I'm ${routeId}
+        - bean:
+            ref: greeter
+        - log: ${body}
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/timer-log.yaml 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/timer-log.yaml
deleted file mode 100644
index cdff71b4d71f..000000000000
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/timer-log.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
-- route:
-    id: timer-log
-    from:
-      uri: timer:tick
-      parameters:
-        period: "1000"
-      steps:
-        - setBody:
-            simple: "Hello Camel! (message 
#${exchangeProperty.CamelTimerCounter})"
-        - log: "${body}"
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/timer-log/README.adoc
 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/timer-log/README.adoc
new file mode 100644
index 000000000000..3abb3a0f9b31
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/timer-log/README.adoc
@@ -0,0 +1,7 @@
+== Timer Log
+
+This example shows a simple timer that logs a hello message every second.
+
+=== How to run
+
+    camel run timer-log.camel.yaml
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/timer-log/timer-log.camel.yaml
 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/timer-log/timer-log.camel.yaml
new file mode 100644
index 000000000000..48124209c60d
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/timer-log/timer-log.camel.yaml
@@ -0,0 +1,27 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+- route:
+    id: timer-log
+    from:
+      uri: timer:tick
+      parameters:
+        period: "1000"
+      steps:
+        - setBody:
+            simple: "Hello Camel! (message 
#${exchangeProperty.CamelTimerCounter})"
+        - log: "${body}"
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/xslt/README.adoc 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/xslt/README.adoc
new file mode 100644
index 000000000000..0d3cc77abf8e
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/xslt/README.adoc
@@ -0,0 +1,66 @@
+== XSLT Transformation
+
+This example shows a basic XML transformation using XSLT style sheet.
+
+=== Install JBang
+
+First install JBang according to https://www.jbang.dev
+
+When JBang is installed then you should be able to run from a shell:
+
+[source,sh]
+----
+$ jbang --version
+----
+
+This will output the version of JBang.
+
+To run this example you can either install Camel on JBang via:
+
+[source,sh]
+----
+$ jbang app install camel@apache/camel
+----
+
+Which allows to run Camel JBang with `camel` as shown below.
+
+=== How to run
+
+Then you can run this example using:
+
+[source,sh]
+----
+$ camel run *
+----
+
+This reads the XML input file from _./input/account.xml_ and applies XSL 
transformation.
+
+=== Live updates of message transformation
+
+You can do live changes to the stylesheet and see the output in real-time with 
Camel JBang by running:
+
+[source,bash]
+----
+$ camel transform message --body=file:input/account.xml --component=xslt 
--template=file:stylesheet.xsl --pretty --watch
+----
+
+You can then edit the `stylesheet.xsl` file, and save the file, and watch the 
terminal for updated result.
+
+=== Run directly from GitHub
+
+The example can also be run directly by referring to the GitHub URL as shown:
+
+[source,sh]
+----
+$ camel run https://github.com/apache/camel-jbang-examples/tree/main/xslt
+----
+
+=== Help and contributions
+
+If you hit any problem using Camel or have some feedback, then please
+https://camel.apache.org/community/support/[let us know].
+
+We also love contributors, so
+https://camel.apache.org/community/contributing/[get involved] :-)
+
+The Camel riders!
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/xslt/consumer.camel.yaml
 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/xslt/consumer.camel.yaml
new file mode 100644
index 000000000000..18c6663e29aa
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/xslt/consumer.camel.yaml
@@ -0,0 +1,30 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+- route:
+    from:
+      uri: file://input
+      parameters:
+        fileName: account.xml
+        noop: true
+      steps:
+        - to:
+            uri: xslt
+            parameters:
+              resourceUri: stylesheet.xsl
+        - log:
+            message: Transformed data:\n ${prettyBody}
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/xslt/input/account.xml
 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/xslt/input/account.xml
new file mode 100644
index 000000000000..50b8c1fe887b
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/xslt/input/account.xml
@@ -0,0 +1,27 @@
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<hash>
+  <id type="integer">1369</id>
+  <uid>8c946e1a-fdc5-40d3-9098-44271bdfad65</uid>
+  <account-number>8673088731</account-number>
+  <iban>GB38EFUA27474531363797</iban>
+  <bank-name>ABN AMRO MEZZANINE (UK) LIMITED</bank-name>
+  <routing-number>053228004</routing-number>
+  <swift-bic>AACCGB21</swift-bic>
+</hash>
\ No newline at end of file
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/xslt/stylesheet.xsl
 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/xslt/stylesheet.xsl
new file mode 100644
index 000000000000..fdbb608b22b7
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/examples/xslt/stylesheet.xsl
@@ -0,0 +1,29 @@
+<?xml version = "1.0"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
+
+  <xsl:template match="/">
+    <bank>
+       <name><xsl:value-of select="/hash/bank-name/text()"/></name>
+       <bic><xsl:value-of select="/hash/swift-bic/text()"/></bic>
+    </bank>
+  </xsl:template>
+
+</xsl:stylesheet>
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/RunTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/RunTest.java
index 60aff3832db7..707dffb184de 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/RunTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/RunTest.java
@@ -58,50 +58,50 @@ class RunTest extends CamelCommandBaseTestSupport {
     @Test
     public void shouldListExamples() throws Exception {
         Run command = new Run(new CamelJBangMain().withPrinter(printer));
-        command.exampleList = true;
+        command.example = "";
         int exit = command.doCall();
 
         Assertions.assertEquals(0, exit);
         String output = printer.getOutput();
-        Assertions.assertTrue(output.contains("Available built-in examples:"));
-        Assertions.assertTrue(output.contains("timer-log"));
-        Assertions.assertTrue(output.contains("rest-api"));
-        Assertions.assertTrue(output.contains("cron-log"));
+        Assertions.assertTrue(output.contains("Available examples:"));
+        Assertions.assertTrue(output.contains("circuit-breaker"));
+        Assertions.assertTrue(output.contains("groovy"));
+        Assertions.assertTrue(output.contains("routes"));
     }
 
     @Test
-    public void shouldListExamplesWithEmptyExampleFlag() throws Exception {
+    public void shouldRejectUnknownExample() throws Exception {
         Run command = new Run(new CamelJBangMain().withPrinter(printer));
-        command.example = "";
+        command.example = "nonexistent";
         int exit = command.doCall();
 
-        Assertions.assertEquals(0, exit);
-        String output = printer.getOutput();
-        Assertions.assertTrue(output.contains("Available built-in examples:"));
+        Assertions.assertEquals(1, exit);
     }
 
     @Test
-    public void shouldRejectUnknownExample() throws Exception {
+    public void shouldSuggestSimilarExample() throws Exception {
         Run command = new Run(new CamelJBangMain().withPrinter(printer));
-        command.example = "nonexistent";
+        command.example = "circuit-brake";
         int exit = command.doCall();
 
         Assertions.assertEquals(1, exit);
+        String output = printer.getOutput();
+        Assertions.assertTrue(output.contains("Did you mean"));
     }
 
     @Test
     public void shouldParseExampleOption() throws Exception {
         Run command = new Run(new CamelJBangMain());
-        CommandLine.populateCommand(command, "--example=timer-log");
+        CommandLine.populateCommand(command, "--example=circuit-breaker");
 
-        Assertions.assertEquals("timer-log", command.example);
+        Assertions.assertEquals("circuit-breaker", command.example);
     }
 
     @Test
     public void shouldParseExampleListOption() throws Exception {
         Run command = new Run(new CamelJBangMain());
-        CommandLine.populateCommand(command, "--example-list");
+        CommandLine.populateCommand(command, "--example");
 
-        Assertions.assertTrue(command.exampleList);
+        Assertions.assertNotNull(command.example);
     }
 }
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/common/ExampleHelperTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/common/ExampleHelperTest.java
new file mode 100644
index 000000000000..1e6473bcfd0f
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/common/ExampleHelperTest.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.jbang.core.common;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+
+import org.apache.camel.util.json.JsonObject;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class ExampleHelperTest {
+
+    @Test
+    void shouldLoadCatalog() {
+        List<JsonObject> catalog = ExampleHelper.loadCatalog();
+        assertFalse(catalog.isEmpty());
+    }
+
+    @Test
+    void shouldFindExample() {
+        List<JsonObject> catalog = ExampleHelper.loadCatalog();
+        JsonObject entry = ExampleHelper.findExample(catalog, 
"circuit-breaker");
+        assertNotNull(entry);
+        assertEquals("Circuit Breaker", entry.getString("title"));
+    }
+
+    @Test
+    void shouldReturnNullForUnknownExample() {
+        List<JsonObject> catalog = ExampleHelper.loadCatalog();
+        JsonObject entry = ExampleHelper.findExample(catalog, 
"does-not-exist");
+        assertNull(entry);
+    }
+
+    @Test
+    void shouldFilterByTag() {
+        List<JsonObject> catalog = ExampleHelper.loadCatalog();
+        List<JsonObject> filtered = ExampleHelper.filterExamples(catalog, 
"security");
+        assertFalse(filtered.isEmpty());
+        for (JsonObject entry : filtered) {
+            String name = entry.getString("name");
+            assertTrue(name.contains("keycloak") || name.contains("pqc") || 
name.contains("ocsf")
+                    || name.contains("pii"),
+                    "Expected security-related example but got: " + name);
+        }
+    }
+
+    @Test
+    void shouldFilterByName() {
+        List<JsonObject> catalog = ExampleHelper.loadCatalog();
+        List<JsonObject> filtered = ExampleHelper.filterExamples(catalog, 
"mqtt");
+        assertEquals(1, filtered.size());
+        assertEquals("mqtt", filtered.get(0).getString("name"));
+    }
+
+    @Test
+    void shouldReturnAllWhenFilterEmpty() {
+        List<JsonObject> catalog = ExampleHelper.loadCatalog();
+        List<JsonObject> filtered = ExampleHelper.filterExamples(catalog, "");
+        assertEquals(catalog.size(), filtered.size());
+    }
+
+    @Test
+    void shouldDetectBundled() {
+        List<JsonObject> catalog = ExampleHelper.loadCatalog();
+        JsonObject circuitBreaker = ExampleHelper.findExample(catalog, 
"circuit-breaker");
+        assertTrue(ExampleHelper.isBundled(circuitBreaker));
+
+        JsonObject mqtt = ExampleHelper.findExample(catalog, "mqtt");
+        assertFalse(ExampleHelper.isBundled(mqtt));
+    }
+
+    @Test
+    void shouldDetectDocker() {
+        List<JsonObject> catalog = ExampleHelper.loadCatalog();
+        JsonObject mqtt = ExampleHelper.findExample(catalog, "mqtt");
+        assertTrue(ExampleHelper.requiresDocker(mqtt));
+
+        JsonObject circuitBreaker = ExampleHelper.findExample(catalog, 
"circuit-breaker");
+        assertFalse(ExampleHelper.requiresDocker(circuitBreaker));
+    }
+
+    @Test
+    void shouldGetFiles() {
+        List<JsonObject> catalog = ExampleHelper.loadCatalog();
+        JsonObject routes = ExampleHelper.findExample(catalog, "routes");
+        List<String> files = ExampleHelper.getFiles(routes);
+        assertTrue(files.contains("routes.camel.yaml"));
+        assertTrue(files.contains("Greeter.java"));
+        assertTrue(files.contains("beans.yaml"));
+    }
+
+    @Test
+    void shouldExtractBundledExample() throws Exception {
+        List<JsonObject> catalog = ExampleHelper.loadCatalog();
+        JsonObject entry = ExampleHelper.findExample(catalog, 
"circuit-breaker");
+        Path tempDir = ExampleHelper.extractBundledExample(entry);
+
+        assertTrue(Files.exists(tempDir.resolve("route.camel.yaml")));
+        String content = Files.readString(tempDir.resolve("route.camel.yaml"));
+        assertFalse(content.isEmpty());
+    }
+
+    @Test
+    void shouldExtractBundledExampleWithSubdirectory() throws Exception {
+        List<JsonObject> catalog = ExampleHelper.loadCatalog();
+        JsonObject entry = ExampleHelper.findExample(catalog, "xslt");
+        Path tempDir = ExampleHelper.extractBundledExample(entry);
+
+        assertTrue(Files.exists(tempDir.resolve("consumer.camel.yaml")));
+        assertTrue(Files.exists(tempDir.resolve("stylesheet.xsl")));
+        assertTrue(Files.exists(tempDir.resolve("input/account.xml")));
+    }
+
+    @Test
+    void shouldGetGithubUrl() {
+        List<JsonObject> catalog = ExampleHelper.loadCatalog();
+        JsonObject entry = ExampleHelper.findExample(catalog, "mqtt");
+        String url = ExampleHelper.getGithubUrl(entry);
+        
assertEquals("https://github.com/apache/camel-jbang-examples/tree/main/mqtt";, 
url);
+    }
+
+    @Test
+    void shouldGetGithubUrlForNestedExample() {
+        List<JsonObject> catalog = ExampleHelper.loadCatalog();
+        JsonObject entry = ExampleHelper.findExample(catalog, "aws/aws-sqs");
+        String url = ExampleHelper.getGithubUrl(entry);
+        
assertEquals("https://github.com/apache/camel-jbang-examples/tree/main/aws/aws-sqs";,
 url);
+    }
+
+    @Test
+    void shouldGetExampleNames() {
+        List<JsonObject> catalog = ExampleHelper.loadCatalog();
+        List<String> names = ExampleHelper.getExampleNames(catalog);
+        assertTrue(names.contains("circuit-breaker"));
+        assertTrue(names.contains("mqtt"));
+        assertTrue(names.contains("aws/aws-sqs"));
+    }
+}

Reply via email to