Skip to content

help --json catalog + opt-in dynamic command discovery (Phase 2)#405

Merged
jeremydmiller merged 1 commit into
mainfrom
feat-jasperfx-aspire-command-discovery
May 31, 2026
Merged

help --json catalog + opt-in dynamic command discovery (Phase 2)#405
jeremydmiller merged 1 commit into
mainfrom
feat-jasperfx-aspire-command-discovery

Conversation

@jeremydmiller
Copy link
Copy Markdown
Member

Closes #403. Phase 2 of the JasperFx.Aspire work (A1 #402, A2 #404): make the dashboard buttons self-describing by discovering a service's actual verbs instead of relying only on the curated list.

Core — help --json

A new --json flag on the help command writes the command catalog to stdout as JSON — each verb's name and description, sorted:

dotnet run -- help --json
[ { "name": "check-env", "description": "Execute all environment checks ..." }, ... ]
  • Written with Utf8JsonWriter (no reflection → trim/AOT safe).
  • Pure introspection — no host is built, so it needs no DB/broker and is cheap to call. This is exactly why help --json was chosen over the design's describe --json lean: describe builds the host.
  • HelpCommand.ToCommandCatalogJson is public and unit-tested.

JasperFx.Aspire — opt-in dynamic discovery

builder.AddProject<Projects.Api>("api")
    .WithJasperFxCommands(opts => opts.DiscoverCommands = true);
  • When DiscoverCommands is set, WithJasperFxCommands runs help --json against the already-built project at AppHost build time (dotnet run --no-build), parses the catalog, and renders one button per discovered verb — picking up product-specific and custom commands automatically.
  • JasperFxVerbCatalog.ResolveDiscovered maps discovered verbs through the existing TemplateFor (known verbs keep their curated icon/confirmation/mutating flag; unknown verbs → mutating), honoring the same IncludeMutatingCommands / IncludeVerbs / ExcludeVerbs gating. run/help are never shown.
  • Best-effort. The parser locates the JSON array within noisy stdout (the framework prints Searching '...' for commands before it). Any failure/timeout/parse error falls back to the curated catalog — default behavior is unchanged.

Verification

  • dotnet build jasperfx.slnx -c Release clean; VitePress docs build clean.
  • ✅ 4 core catalog tests + 47 Aspire tests (11 new): catalog JSON shape/sorting, noisy-output parsing, and discovered-verb gating.
  • ✅ Smoke-checked the real dotnet run -- help --json output (clean JSON after the framework's search noise — the parser handles it).

On the mutating classification (#403)

The "mutating vs read-only" source of truth stays in JasperFx.Aspire's catalog (convention + safe-default-to-mutating for unknowns) rather than adding a mutating concept to JasperFx core — core JSON is just { name, description }.

Docs

New "Dynamic command discovery" section on /cli/aspire, plus a general "Machine-readable command catalog" note in the CLI index.

🤖 Generated with Claude Code

…pire (Phase 2)

Phase 2 of the JasperFx.Aspire work (closes #403): make the dashboard buttons
self-describing by discovering a service's actual verbs instead of relying only
on the curated list.

Core — `help --json`:
- New --json flag on `help` writes the command catalog ([{name, description}],
  sorted) to stdout via Utf8JsonWriter (no reflection — trim/AOT safe). Pure
  introspection: no host is built, so it's cheap and needs no DB/broker. Chosen
  over `describe --json` precisely because describe builds the host. HelpCommand
  .ToCommandCatalogJson is public + unit-tested.

JasperFx.Aspire — opt-in dynamic discovery:
- JasperFxCommandOptions.DiscoverCommands (+ DiscoveryTimeout). When set,
  WithJasperFxCommands runs `help --json` against the already-built project at
  AppHost build time (dotnet run --no-build), parses the catalog, and renders one
  button per discovered verb — picking up product-specific and custom commands.
- JasperFxVerbCatalog.ResolveDiscovered maps discovered verbs through the existing
  TemplateFor (known verbs keep curated metadata; unknown → mutating), honoring the
  same IncludeMutating/Include/Exclude gating; run/help are never shown.
- Best-effort: the catalog parser locates the JSON array within noisy stdout (the
  framework prints "Searching '...' for commands" before it); any failure/timeout/
  parse error falls back to the curated catalog. Default behavior is unchanged.

11 new tests (catalog JSON; noisy-output parsing; discovered-verb gating).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jeremydmiller jeremydmiller merged commit e0edf31 into main May 31, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

JasperFx.Aspire Phase 2: self-describing command catalog (describe --json)

1 participant