diff --git a/docs/cli.md b/docs/cli.md
index 29c67ecf82..f576bd73d9 100644
--- a/docs/cli.md
+++ b/docs/cli.md
@@ -524,6 +524,29 @@ Use this to learn about command-specific options, refresh your memory about synt
$ nextflow help run
```
+(cli-machine-readable-help)=
+
+### Machine-readable help
+
+:::{versionadded} 26.06.0-edge
+:::
+
+The `-help-json` option prints the help and options for a command as JSON instead of the human-formatted help text. This provides a stable, structured description of the CLI for tools and AI agents to consume, without scraping the rendered `-help` output.
+
+The option is contextual, so you can discover the CLI one command at a time. At the top level, it lists the global options and an index of every available command:
+
+```console
+$ nextflow -help-json
+```
+
+Add it to any command to get that command's full options and arguments:
+
+```console
+$ nextflow run -help-json
+```
+
+The output describes each option with its name, flags, type, help text, and default value (where applicable). The schema is derived directly from the CLI definitions, so it stays in sync with the available commands and options.
+
### Version information
The `-v` and `-version` options print Nextflow version information.
diff --git a/docs/reference/cli.md b/docs/reference/cli.md
index bb9895f0d8..363028bb91 100644
--- a/docs/reference/cli.md
+++ b/docs/reference/cli.md
@@ -33,6 +33,12 @@ Available options:
`-h`
: Print available commands and options.
+`-help-json`
+: :::{versionadded} 26.06.0-edge
+ :::
+: Print the help and options as JSON, for consumption by tools and LLMs (see {ref}`cli-machine-readable-help`).
+: Works as a top-level option (`nextflow -help-json`) and on any command (e.g. `nextflow run -help-json`).
+
`-log`
: Set Nextflow log file path (default: `.nextflow.log`). Must be a local path.
diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CliOptions.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CliOptions.groovy
index 66988dc367..abaf10af89 100644
--- a/modules/nextflow/src/main/groovy/nextflow/cli/CliOptions.groovy
+++ b/modules/nextflow/src/main/groovy/nextflow/cli/CliOptions.groovy
@@ -75,6 +75,9 @@ class CliOptions {
@Parameter(names = ['-h'], description = 'Print this help', help = true)
boolean help
+ @Parameter(names = ['-help-json'], description = 'Print the command help and options as JSON (for tools and LLMs)', help = true)
+ boolean helpJson
+
@Parameter(names = ['-q','-quiet'], description = 'Do not print information messages' )
boolean quiet
diff --git a/modules/nextflow/src/main/groovy/nextflow/cli/CliSchema.groovy b/modules/nextflow/src/main/groovy/nextflow/cli/CliSchema.groovy
new file mode 100644
index 0000000000..dbfdb5e270
--- /dev/null
+++ b/modules/nextflow/src/main/groovy/nextflow/cli/CliSchema.groovy
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2013-2026, Seqera Labs
+ *
+ * Licensed 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 nextflow.cli
+
+import java.lang.reflect.Field
+
+import com.beust.jcommander.DynamicParameter
+import com.beust.jcommander.Parameter
+import com.beust.jcommander.Parameters
+import groovy.json.JsonOutput
+import groovy.transform.CompileDynamic
+import groovy.transform.CompileStatic
+
+/**
+ * Build a machine-readable (JSON) description of the Nextflow command line
+ * interface by introspecting the JCommander {@link Parameter} / {@link Parameters}
+ * annotations.
+ *
+ * This powers the global {@code -help-json} flag, which lets tools and LLMs
+ * discover the CLI one command at a time without scraping the rendered
+ * {@code -help} text:
+ *
+ *
+ * nextflow -help-json # global options + index of all commands
+ * nextflow run -help-json # full option/argument detail for `run`
+ *
+ *
+ * @author Phil Ewels
+ */
+@CompileStatic
+class CliSchema {
+
+ /**
+ * Build the schema for the top-level program: the global options plus a
+ * name + description index of every available command.
+ */
+ static String root(CliOptions options, List commands) {
+ final schema = [
+ name : 'nextflow',
+ path : 'nextflow',
+ usage : 'nextflow [options] COMMAND [arg...]',
+ params : paramsOf(CliOptions),
+ subcommands : commandIndex(commands),
+ ]
+ return render(schema)
+ }
+
+ /**
+ * Build the schema for a single command: its usage, options and positional
+ * arguments.
+ */
+ static String command(CmdBase cmd) {
+ final clazz = cmd.getClass()
+ final params = paramsOf(clazz)
+ final schema = [
+ name : cmd.name,
+ path : "nextflow ${cmd.name}".toString(),
+ usage : usageOf(cmd, params),
+ params : params,
+ ] as Map
+
+ final description = descriptionOf(clazz)
+ if( description )
+ schema.help = description
+ final aliases = aliasesOf(clazz)
+ if( aliases )
+ schema.aliases = aliases
+
+ return render(schema)
+ }
+
+ /**
+ * Map each command name to its description and aliases. Nextflow commands
+ * are flat (no nested groups), so a single index lists them all; drill into
+ * any one with {@code nextflow -help-json}.
+ */
+ @CompileDynamic
+ private static Map commandIndex(List commands) {
+ final index = new TreeMap()
+ for( CmdBase cmd : commands ) {
+ final clazz = cmd.getClass()
+ final description = descriptionOf(clazz)
+ // only advertise commands that opt in with a description, matching `-help`
+ if( !description )
+ continue
+ final entry = [help: description] as Map
+ final aliases = aliasesOf(clazz)
+ if( aliases )
+ entry.aliases = aliases
+ index[cmd.name] = entry
+ }
+ return index
+ }
+
+ /**
+ * Introspect the {@link Parameter} / {@link DynamicParameter} annotations of
+ * a command (or options) class into a list of JSON-friendly maps. Inherited
+ * fields are included; hidden and meta options ({@code -h}, {@code -help},
+ * {@code -help-json}) are skipped.
+ */
+ @CompileDynamic
+ private static List