Skip to content

Build CLI command metadata from a checked-in manifest #1914

Closed

Description

@sentry-junior

The CLI rebuilds its command metadata at runtime or with generators that parse source. --help, --fields and introspection read each command's valibot output schema when the command runs, and generate-route-loaders.ts parses src/app.ts with the TypeScript compiler API to find the route tree. Review of #1826 and #1830 settled on a checked-in .ts manifest plus valibot as the only output-schema source, with generators that load both and write per-command data.

Background

  • Runtime readers of output.schema: buildFieldsFlag (--fields parsing and completion) and enrichDocsWithSchema (--help) in src/lib/command.ts, and __jsonSchema → src/lib/introspect.ts. Reading all 67 schemas takes ~21 ms cold, under 1 ms per command, so the gain is mostly the build/runtime split and bundle size, not startup.
  • generate:routes writes src/generated/route-loaders.ts from the buildSentryRoutes({...}) literal in app.ts. perf(cli): Skip loading commands for --version and leading global flags #1826 adds generate-root-help.ts → root-help.json and passes ansiColor through the Stricli renderHelp patch so root help can skip loading commands.
  • Some output schemas also validate API responses at runtime and must stay in runtime code: ConversationListItemSchema, DashboardRevisionSchema, and the list items inside SpansResponseSchema, TransactionsResponseSchema and LogsResponseSchema.

Proposal (from #1826 and #1830 review)

  1. Manifest. A checked-in .ts file with each route's name, brief, aliases, hidden flag, subcommands, and the module/export that implements it. It replaces generate:routes, and root help can be rendered by Stricli from a stub tree built from it, which drops root-help.json and the ansiColor patch change from perf(cli): Skip loading commands for --version and leading global flags #1826.
  2. Build-only output schemas. CLI-only output schemas move into build-only modules keyed by manifest entry. Commands import only their types (import type + InferOutput, as in ref(cli): Derive command output types from their output schemas #1830); a lint rule blocks value imports from runtime code.
  3. Generated per-command data. Generators load (not parse) the manifest and schemas through tsx and write per-command field data (names, descriptions, paths) that --fields, --help, completion and introspection read at runtime.

Out of scope: JSON Schema as an authoring format (data-only artifacts can be emitted from valibot when needed), and moving flags/positionals out of buildCommand.

Related: #1824, #1830, #1826, #1852, #1853.

via @BYK.

--

View Session in Sentry

Activity

  1. linear-code commented on Nov 3, 2026

    @linear-code
  2. sentry-junior commented on Nov 3, 2026

    @sentry-junior
    ContributorAuthor

    Note for parts 2–3: #1919 (open, stacked on #1916) adds a third generated per-command artifact, packages/mcp-core/src/command-catalog.json, for the MCP command surface (#1890). It holds each command's JSON Schema for flags and positionals, permission, exposure, examples, outputFields and API operations. Today it gets outputFields from introspect.ts, which reads each command's valibot schema when the generator runs. When part 3 writes per-command field data, the catalog generator should read that data so there's one source. command-api.json and command-api-access.json (#1916) could come from the same pass.

  3. added a commit that references this issue on Nov 4, 2026
    c969e13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    CLISentry CLI and CLI documentation

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions