Skip to content

dev-call cli-info reports hidden commands as public: inspect and capabilities missing from hiddenCommands list #14751

Description

@mcanouil

I have:

  • searched the issue tracker for similar issues
  • installed the latest version of Quarto CLI
  • formatted my issue following the Bug Reports guide

Bug description

quarto dev-call cli-info reports inspect and capabilities as hidden: false, even though both call .hidden() on their Cliffy command and are correctly absent from quarto --help. The hidden flag in that JSON does not come from Cliffy: it comes from a hardcoded hiddenCommands array, whose own comment says it exists because Cliffy doesn't expose the property.

  • // Cliffy doesn't export the "hidden" property, so we maintain our own list
    // here
    const hiddenCommands = [
    "dev-call",
    "editor-support",
    "create-project",
    ];
    // deno-lint-ignore no-explicit-any
    const cmdAsJson = (cmd: any): CommandInfo => {
    return {
    name: cmd.getName(),
    hidden: hiddenCommands.includes(cmd.getName()),

That array only lists dev-call, editor-support, create-project. This is an omission, not a drift: the array was introduced complete-as-written by 68ea0b28c ("expose hidden field to cli-info json object", 2025-05-09) with exactly those three entries, and no commit has touched it since. inspect and capabilities were never in it, even though both call .hidden() on their own command definitions.

  • export const inspectCommand = new Command()
    .name("inspect")
    .arguments("[path] [output]")
    .description(
    "Inspect a Quarto project or input path.\n\nInspecting a project returns its config and engines.\n" +
    "Inspecting an input path return its formats, engine, and dependent resources.\n\n" +
    "Emits results of inspection as JSON to output (or stdout if not provided).",
    )
    .hidden()
  • export const capabilitiesCommand = new Command()
    .name("capabilities")
    .description(
    "Query for current capabilities (formats, engines, kernels etc.)",
    )
    .hidden()

It went unnoticed for eight months because the consumer arrived later. quarto-web generates its CLI reference from this JSON and filters on !hidden.

Its whole docs/cli/ tree, including inspect.qmd and capabilities.qmd, was only created on 2026-01-08 by b841c7264 ("Feature/cli autogen #1659"), so both commands now have published reference pages linked from the CLI reference landing page, while the CLI itself treats them as hidden.

Steps to reproduce

This is a CLI metadata bug, so the reproduction is shell commands rather than a Quarto document.

quarto --help | grep -E "inspect|capabilities"
# no output: both hidden from help

quarto dev-call cli-info | jq -r '.commands[] | select(.name=="inspect" or .name=="capabilities" or .name=="editor-support" or .name=="dev-call" or .name=="create-project") | "\(.name) -> hidden: \(.hidden)"'
# but cli-info reports inspect and capabilities as public

curl -s https://quarto.org/docs/cli/ | grep -oE "(inspect|capabilities|editor-support|dev-call|create-project).html" | sort -u
# and the generated docs are live

Actual behavior

Step 2 prints:

create-project -> hidden: true
capabilities -> hidden: false
inspect -> hidden: false
editor-support -> hidden: true
dev-call -> hidden: true

Step 3 prints:

capabilities.html
inspect.html

Both pages are live and linked from the CLI reference index, while editor-support, dev-call, and create-project are correctly excluded.

Expected behavior

cli-info's hidden flag should agree with the command's actual .hidden() state, so the generated reference and quarto --help cannot disagree. The evidence points opposite ways for the two commands.

For inspect, the .hidden() looks like the stale side, and dropping it would resolve the inconsistency in the direction the documentation already went. It has had deliberate, hand-written documentation since 2024, together with two published JSON schemas for its output.

That page recommends quarto inspect outright: "particularly useful for authors of downstream tools and libraries which analyze Quarto content. Whenever possible, we recommend using quarto inspect instead of direct inspection of documents or projects." It was written two years after the .hidden() call, and publishing a stable output schema is not normal for an internal command. Third-party tooling relies on it, so removing its reference page has real cost, while making it visible costs nothing. Concretely: remove .hidden() from inspectCommand.

For capabilities, there is no hand-written documentation on quarto.org outside the generated CLI reference. It reads as a sibling of editor-support, an IDE-facing internal, so honouring its .hidden() and adding it to hiddenCommands looks consistent with intent.

Either way, the underlying mechanism should stop being a hand-maintained list, since it will drift again. Cliffy v1.0.0-rc.3 (the pinned version) does keep isHidden private with no public getter, so the source comment is accurate, but the state is still derivable without duplicating it: getCommands and getBaseCommands both take a hidden flag and filter on the same private field internally.

Diffing root.getCommands(true) against root.getCommands() yields the hidden set with no list to maintain. A root command with every subcommand already registered is assembled in quartoCommand.

  • quarto-cli/src/quarto.ts

    Lines 169 to 183 in f9dd09c

    const quartoCommand = new Command()
    .name("quarto")
    .help({ colors: false })
    .version(quartoConfig.version() + "\n")
    .description("Quarto CLI")
    .throwErrors();
    commands().forEach((command) => {
    // turn off colors
    command.help({ colors: false });
    quartoCommand.command(
    command.getName(),
    cmdHandler !== undefined ? cmdHandler(command) : command,
    );

For completeness: docs/advanced/inspect/index.qmd is not linked from quarto-web's navigation, so it is published but not prominent, reachable by direct URL, sitemap, and search rather than by browsing.

Your environment

  • IDE: N/A, CLI-only bug
  • OS: macOS 26.6 (build 25G72)
  • Quarto: local dev build of main at f9dd09cd2aee9f107a6c3f497e9210d55ceeebca

Quarto check output

$ quarto check
Quarto 99.9.9
[✓] Checking environment information...
      Quarto cache location: /Users/mcanouil/Library/Caches/quarto
[✓] Checking versions of quarto binary dependencies...
      Pandoc version 3.10.0: OK
      Dart Sass version 1.101.0: OK
      Deno version 2.7.14: OK
      Typst version 0.15.1: OK
[✓] Checking versions of quarto dependencies......OK
[✓] Checking Quarto installation......OK
      Version: 99.9.9
      commit: f9dd09cd2aee9f107a6c3f497e9210d55ceeebca
      Path: /Users/mcanouil/Projects/quarto-dev/quarto-cli/package/dist/bin
[✓] Checking tools....................OK
      TinyTeX: v2026.07
      Chrome Headless Shell: (not installed)
      VeraPDF: (not installed)
[✓] Checking LaTeX....................OK
      Using: TinyTex
      Path: /Users/mcanouil/Library/TinyTeX/bin/universal-darwin
      Version: 2026
[✓] Checking Chrome Headless....................OK
      Using: Chrome from QUARTO_CHROMIUM
      Path: /Applications/Brave Browser.app/Contents/MacOS/Brave Browser
[✓] Checking basic markdown render....OK
ℹ R version 4.6.1 (2026-06-24)
! Config '~/.Rprofile' was loaded!
[✓] Checking R installation...........OK
      Version: 4.6.1
      Path: /Library/Frameworks/R.framework/Resources
      LibPaths:
        - /Library/Frameworks/R.framework/Versions/4.6/Resources/library
      knitr: 1.51
      rmarkdown: 2.31
[✓] Checking Knitr engine render......OK
[✓] Checking Python 3 installation....OK
      Version: 3.14.6
      Path: /opt/homebrew/opt/python@3.14/bin/python3.14
      Jupyter: (None)
      Jupyter is not available in this Python installation.
      Install with python3 -m pip install jupyter
[✓] Checking Julia installation...

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions