Skip to content

Add eager --completions flag and .help() config builder - #43

Merged
kjanat merged 9 commits into
masterfrom
recipe-lsp-help-output
Jun 30, 2026
Merged

kjanat merged 9 commits into
masterfrom
recipe-lsp-help-output

Conversation

@kjanat

@kjanat kjanat commented Jun 29, 2026 •

Copy link
Copy Markdown
Owner

Summary

This PR introduces two major features to enhance CLI customization:

  1. Eager --completions <shell> flag — An alternative to the completions subcommand that exposes shell completion as a root-level flag, ideal for single-command CLIs. The planner intercepts the flag before dispatch, auto-detects the shell from the environment if needed, and prints the completion script.

  2. .help() builder method — Allows configuration of root-help rendering behavior through inlineDefault, showDefaultInCommands, and footer options, merged under runtime options.help.

  3. Shell normalization and detection helpers — Exported normalizeShell() and detectShell() functions that parse shell tokens (bare names, $SHELL paths, Windows executables) and auto-detect from environment variables.

Key Changes

  • .completions({ as: 'flag' }) — New option to register completion as an eager flag instead of a subcommand. When active, the planner intercepts --completions [shell] before dispatch and generates the script. Root help advertises the flag in its Flags: section.

  • Shell auto-detection — --completions without a value resolves the target shell from the environment: $SHELL (parsed as an interpreter path) wins when it names a supported shell; otherwise $PSModulePath presence selects PowerShell (the reliable signal for pwsh).

  • .help(config) builder — New method to configure root-help defaults. Accepts inlineDefault (render default command's args/flags inline), showDefaultInCommands (list default in Commands table), footer (show help hint), plus existing width/hyperlinks. Builder config merges under runtime options.help (runtime wins).

  • Default command as root surface — BREAKING: .default(cmd) now registers the command only as the default, not as a named subcommand. It is the CLI's root surface (its args/flags render inline in help) and is omitted from the Commands: list by default. This change allows a single-command CLI with .completions({ as: 'flag' }) to keep the root clean.

  • Root help refactoring — formatRootHelp() now handles inline default rendering, completions flag advertisement, and configurable footer/command listing. Helper functions resolveSurfaceCommand() and completionsFlagSchema() build the synthetic flag schema for help display.

  • Planner enhancements — New planCompletionsFlag() function detects and validates the eager flag before dispatch, with proper error handling for unknown shells and support for --completions=<shell> syntax.

  • Root surface normalization — RootSurface interface now distinguishes visibleSubcommands (real commands, excluding default) from visibleCommands (all declared commands), with boolean flags hasVisibleSubcommands and hasVisibleDefault.

Implementation Details

  • The eager completions flag is stored in CLISchema.completionsFlag and passed to the planner for interception.
  • Help configuration is stored in CLISchema.helpConfig and merged with runtime options in formatRootHelp().
  • Shell normalization handles pwsh ↔ powershell aliasing and strips Windows executable extensions.
  • The synthetic completions flag schema is built on-demand in resolveSurfaceCommand() so it only appears in help when configured.
  • Comprehensive test coverage added in cli-completions-flag.test.ts covering registration, interception, auto-detection, and help rendering.

…igurable help

Reworks how a default command and built-in completions surface in root help,
and makes root-help rendering configurable by consumers.

- `.default(cmd)` now registers the command only as the root surface, not a
  named subcommand: it is no longer invokable by its own name and is omitted
  from the `Commands:` list by default. Root help renders its args/flags inline
  even alongside sibling commands; a sole default shows its own usage line.
- `.completions({ as: 'flag' })` exposes an eager `--completions <shell>` flag
  instead of a subcommand, intercepted in the planner. `--completions` with no
  value auto-detects the shell from `$SHELL`, falling back to `$PSModulePath`
  for PowerShell (which never sets `$SHELL`). Adds `detectShell`/`normalizeShell`.
- `.help(config)` builder + `inlineDefault`/`showDefaultInCommands`/`footer`
  HelpOptions, merged under runtime `options.help`.

BREAKING CHANGE: a default command is no longer a named route and is hidden from
the root commands list by default; re-enable the list entry with
`.help({ showDefaultInCommands: true })`.
@coderabbitai

coderabbitai Bot commented Jun 29, 2026 •

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto reviews are limited based on label configuration.

🏷️ Required labels (at least one) (1)
  • cr:review
🚫 Excluded labels (none allowed) (2)
  • wip
  • cr:skip

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: f1490264-d3f3-4e61-b7a2-50aa3cc04176

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds an eager root --completions <shell> mode with shell normalisation and environment-based detection. It also changes .default() so the default command is treated as the root surface rather than a named route, and updates root help rendering to support inline default behaviour and configurable help options. Tests and release docs were updated to match the new routing, help, and completion behaviour.

Sequence Diagram(s)

sequenceDiagram
  participant CLIBuilder
  participant planInvocation
  participant execute
  participant detectShell
  CLIBuilder->>planInvocation: argv + schema
  planInvocation->>planInvocation: intercept --completions
  planInvocation-->>execute: root-completions outcome
  execute->>detectShell: detect shell from env if needed
  detectShell-->>execute: resolved shell
  execute->>execute: emit script or JSON
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • kjanat/dreamcli#1: Shares the completion-generation path and shell handling that this PR extends with eager root-flag support.
  • kjanat/dreamcli#7: Touches the same planner.ts, root-help.ts, and default-command dispatch areas now reshaped here.
  • kjanat/dreamcli#37: Also changes default-command routing and root dispatch behaviour in the CLI planner.

Suggested labels

kind: feature, kind: breaking, area: cli, area: completion

Arrr, the root be speaking now.
--completions boards first, before the -- tide.
The default sails as the surface, not a hidden berth.
Help curls tight and tidy, like a well-kept map.
And shell names? Aye, they be sorted properly.

🚥 Pre-merge checks | ✅ 10 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title matches the change, but it misses the required conventional commit style: it should start with a lowercase prefix like add:. Rename it to something like add: eager --completions flag and .help() config builder.
✅ Passed checks (10 passed)
Check name Status Explanation
Description check ✅ Passed The description clearly matches the CLI completions and help builder changes in the patch.
Docstring Coverage ✅ Passed Docstring coverage is 73.91% which is sufficient. The required threshold is 30.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Release Metadata Sync ✅ Passed package.json and deno.json both declare 3.0.0; CHANGELOG.md has a 3.0.0 heading and matching [Unreleased]/[3.0.0] compare links.
Runtime Support Sync ✅ Passed No runtime support minima/claims changed; Node 22.22.2, Bun 1.3, and Deno 2.6.0 stay aligned across package.json, support.ts, README, and docs.
No Generated Docs Artifacts ✅ Passed No changed files fall under docs/.vitepress/dist/ or docs/.vitepress/cache/; the diff only touches source/docs files elsewhere.
Changelog Update ✅ Passed package.json and deno.json are bumped to 3.0.0, and CHANGELOG.md has ## [3.0.0] - 2026-06-29 with Added/Changed sections.
Semver Version Bump Validation ✅ Passed PASS: package.json and deno.json are bumped to 3.0.0, and the diff includes breaking CLI API changes (.default() no longer a named subcommand), so a MAJOR bump fits.
Agents.Md Documentation Updated ✅ Passed PASS: the PR updates AGENTS.md for every affected area, including src/core/cli, completion, help and json-schema, plus the repo root.

Comment @coderabbitai help to get the list of available commands.

@pkg-pr-new

pkg-pr-new Bot commented Jun 29, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

bun add https://pkg.pr.new/@kjanat/dreamcli@43
npm i https://pkg.pr.new/@kjanat/dreamcli@43

commit: 703a0ae

@kjanat kjanat self-assigned this Jun 29, 2026
@kjanat kjanat added the cr:review Allow CodeRabbit review label Jun 29, 2026
@coderabbitai coderabbitai Bot added area: cli CLI dispatch, planning, root UX, or plugins area: completion Shell completion generation and parsing impact: breaking Introduces a breaking API, runtime, or packaging change kind: feature New capability or product enhancement labels Jun 29, 2026
coderabbitai[bot]

This comment was marked as resolved.

- root help: honor HelpOptions.binName in the usage line, merged default-command
  usage, and footer instead of hardcoding schema.name
- root help: advertise the eager --completions flag even when inlineDefault is
  false (it is a root option, not part of the default-command inline surface)
- docs: scope the .completions() snapshot note to subcommand mode; flag mode
  generates from the final schema at execute time
- tests: add binName and inlineDefault-with-completions coverage; add the repo's
  // === / // --- section markers to the new test file
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 29, 2026 •

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
🚫 Deployment cancelled
View logs
dreamcli 703a0ae Jun 30 2026, 11:05 AM

@kjanat kjanat removed the cr:review Allow CodeRabbit review label Jun 29, 2026
- release: bump package.json and deno.json to 3.0.0 and move the CHANGELOG
  [Unreleased] entries under [3.0.0] (breaking: default command is no longer a
  named route)
- cli: reject a command/default flag named `completions` while
  .completions({ as: 'flag' }) is active — the planner intercepts `--completions`
  before dispatch, so such a flag would be unreachable. Enforced in
  .completions({ as: 'flag' }), .command(), and .default(), including nested
  subcommands and long aliases
@kjanat kjanat added cr:review Allow CodeRabbit review and removed cr:review Allow CodeRabbit review labels Jun 29, 2026
coderabbitai[bot]

This comment was marked as resolved.

…ard orders

- the "Could not detect shell" suggestion now references the resolved
  helpOptions.binName instead of schema.name, matching the rest of the
  root-help/completions path
- test: also assert the .completions({ as: 'flag' }) → .command() ordering
  rejects a command reserving the --completions name
@kjanat

This comment was marked as resolved.

@kjanat kjanat changed the title Add eager --completions flag and .help() config builder Add eager --completions flag and .help() config builder Jun 29, 2026
…next`

- bump package.json and deno.json to 3.0.0-rc.1; rename the CHANGELOG section
  and compare links to [3.0.0-rc.1]
- publish-npm.yml: derive the npm dist-tag from the version — prerelease
  versions (containing a `-`) publish under `next`, stable versions under
  `latest` — so the RC never lands on the default `latest` tag
@kjanat kjanat added cr:skip Skip CodeRabbit review and removed cr:review Allow CodeRabbit review labels Jun 29, 2026
kjanat and others added 3 commits June 30, 2026 13:02
Signed-off-by: Kaj Kowalski <info@kajkowalski.nl>
Merging master (#49 numeric constraints) made `numberConstraints` a
required field on `FlagSchema`. The synthetic render-only enum flag
built for the eager `--completions` flag omitted it, breaking
typecheck. Set it to `undefined`, matching every non-number flag.
@kjanat
kjanat merged commit 26ec791 into master Jun 30, 2026
18 of 19 checks passed
@kjanat
kjanat deleted the recipe-lsp-help-output branch June 30, 2026 11:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: cli CLI dispatch, planning, root UX, or plugins area: completion Shell completion generation and parsing cr:skip Skip CodeRabbit review impact: breaking Introduces a breaking API, runtime, or packaging change kind: feature New capability or product enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant