Skip to content

Add --help-json flag for machine-readable CLI help#4310

Draft
ewels wants to merge 6 commits into
nf-core:devfrom
ewels:help-json
Draft

Add --help-json flag for machine-readable CLI help#4310
ewels wants to merge 6 commits into
nf-core:devfrom
ewels:help-json

Conversation

@ewels

@ewels ewels commented May 29, 2026

Copy link
Copy Markdown
Member

Summary

Adds a global --help-json flag to every nf-core CLI command and group. It prints the current command's full help, usage and parameter detail as JSON, plus a recursive index of subcommand names, so LLMs and tooling can discover the entire CLI one level at a time. (Hat-tip to @awgymer for the idea!)

How it works

  • A small nf_core/cli_schema.py introspects the Click/rich-click command tree (get_params then Param.to_info_dict(), list_commands/get_command, collect_usage_pieces), with no --help text parsing.
  • The flag is injected once via a JSONGroup/JSONCommand class pair on the root group. Because rich-click's group_class is already type, a single cls= on the root propagates --help-json to all commands automatically, with no per-command boilerplate.
  • A footer tip is added to every --help screen (via rich_click's FOOTER_TEXT) so agents landing on the human help are pointed at the JSON flag.

Design notes

  • I originally wanted --help --json but the latter collided, so --help-json it is
  • Progressive disclosure by design. The flag is contextual: it dumps the current command and a names-only index of descendants. Real usage stays cheap, with the root call around 540 tokens, a group around 140 to 310, and a leaf around 140. Agents drill down via subcommands rather than pulling everything at once.
  • Eager flag, so nf-core <any command> --help-json works even when required arguments are missing (like --help).

Examples

Regular --help now advertises the flag (footer)

The tip is appended to every help screen:

CleanShot 2026-05-29 at 10 32 27@2x
nf-core --help-json: root top-level options plus recursive name index of the whole CLI
{
  "name": "nf-core-cli",
  "path": "nf-core",
  "help": "nf-core/tools provides a set of helper tools for use with nf-core Nextflow pipelines.\n\nIt is designed for both end-users running pipelines and also developers creating new pipelines.",
  "usage": "nf-core [OPTIONS] COMMAND [ARGS]...",
  "params": [
    { "name": "version", "kind": "option", "opts": ["--version"], "type": "Bool", "is_flag": true, "help": "Show the version and exit." },
    { "name": "verbose", "kind": "option", "opts": ["-v", "--verbose"], "type": "Bool", "is_flag": true, "help": "Print verbose output to the console." },
    { "name": "hide_progress", "kind": "option", "opts": ["--hide-progress"], "type": "Bool", "is_flag": true, "help": "Don't show progress bars." },
    { "name": "log_file", "kind": "option", "opts": ["-l", "--log-file"], "type": "String", "help": "Save a verbose log to a file." }
  ],
  "subcommands": {
    "interface": {},
    "modules": {
      "bump-versions": {}, "create": {}, "info": {}, "install": {}, "lint": {},
      "list": { "local": {}, "remote": {} },
      "patch": {}, "remove": {}, "test": {}, "update": {}
    },
    "pipelines": {
      "bump-version": {}, "create": {}, "create-logo": {}, "create-params-file": {},
      "download": {}, "launch": {}, "lint": {}, "list": {}, "rocrate": {},
      "schema": { "build": {}, "docs": {}, "lint": {}, "validate": {} },
      "sync": {}
    },
    "subworkflows": {
      "create": {}, "info": {}, "install": {}, "lint": {},
      "list": { "local": {}, "remote": {} },
      "patch": {}, "remove": {}, "test": {}, "update": {}
    },
    "test-datasets": { "list": {}, "list-branches": {}, "search": {} }
  }
}
nf-core modules --help-json: a group, its own options, aliases, and immediate subcommand index
{
  "name": "modules",
  "path": "nf-core modules",
  "help": "Commands to manage Nextflow DSL2 modules (tool wrappers).",
  "usage": "nf-core modules [OPTIONS] COMMAND [ARGS]...",
  "params": [
    { "name": "git_remote", "kind": "option", "opts": ["-g", "--git-remote"], "type": "String", "help": "Remote git repo to fetch files from", "default": "https://github.com/nf-core/modules.git" },
    { "name": "branch", "kind": "option", "opts": ["-b", "--branch"], "type": "String", "help": "Branch of git repository hosting modules." },
    { "name": "no_pull", "kind": "option", "opts": ["-N", "--no-pull"], "type": "Bool", "is_flag": true, "help": "Do not pull in latest changes to local clone of modules repository." }
  ],
  "aliases": ["m", "module"],
  "subcommands": {
    "bump-versions": {}, "create": {}, "info": {}, "install": {}, "lint": {},
    "list": { "local": {}, "remote": {} },
    "patch": {}, "remove": {}, "test": {}, "update": {}
  }
}
nf-core pipelines schema validate --help-json: a leaf command, full options plus positional arguments
{
  "name": "validate",
  "path": "nf-core pipelines schema validate",
  "help": "Validate a set of parameters against a pipeline schema.",
  "usage": "nf-core pipelines schema validate [OPTIONS] <pipeline name> <JSON params file>",
  "params": [
    { "name": "directory", "kind": "option", "opts": ["-d", "--dir"], "type": "Path", "help": "Pipeline directory. [default: current working directory]", "default": "." },
    { "name": "pipeline", "kind": "argument", "opts": ["pipeline"], "type": "String" },
    { "name": "params", "kind": "argument", "opts": ["params"], "type": "Path", "required": true }
  ]
}

Notes

  • All 21 existing tests/test_cli.py tests pass.
  • I noticed a pre-existing UserWarning: The parameter -b is used more than once (a duplicate -b short flag around modules/bump-version) surfaced while introspecting the tree. This is unrelated to this PR, but worth a follow-up fix.

🤖 Generated with Claude Code

ewels and others added 2 commits May 29, 2026 10:22
Adds a global `--help-json` flag to every command and group, printing the
current command's help, usage and full parameter detail as JSON, plus a
recursive index of subcommand names. This lets LLMs and tooling discover the
CLI one level at a time without parsing rendered `--help` text or pulling the
whole command tree into context.

A `--help-json` name (rather than `--json`) is used because several commands
already define their own `--json` data-output flag.

A footer tip is also added to every `--help` screen to advertise the flag.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@codecov

codecov Bot commented May 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.00000% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.36%. Comparing base (03bcc65) to head (80eb908).

Files with missing lines Patch % Lines
nf_core/cli_schema.py 89.47% 6 Missing ⚠️

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

ewels and others added 2 commits May 29, 2026 10:31
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ewels ewels requested review from awgymer and mashehu May 29, 2026 08:35

@awgymer awgymer left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, but should we add a test for this on the top-level command at least?

@ewels

ewels commented Jun 1, 2026

Copy link
Copy Markdown
Member Author

@claude please add a test for the top-level command

@mashehu

mashehu commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Shouldn't this be added upstream in rich-click instead 😉

@ewels

ewels commented Jun 2, 2026

Copy link
Copy Markdown
Member Author

Not a bad idea at all!

@ewels

ewels commented Jun 2, 2026

Copy link
Copy Markdown
Member Author

Added upstream but will leave this PR open so that we don't forget. Will still need to pin updated rich-click and add a config option if it remains opt-in.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

WIP Work in progress

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants