Skip to content

refactor(rr): decouple CLI into actions, services, and a plugin facade#235

Merged
rqbazan merged 1 commit into
mainfrom
port/rrlab-decoupling
Jun 1, 2026
Merged

refactor(rr): decouple CLI into actions, services, and a plugin facade#235
rqbazan merged 1 commit into
mainfrom
port/rrlab-decoupling

Conversation

@rqbazan

@rqbazan rqbazan commented Jun 1, 2026

Copy link
Copy Markdown
Member

Summary

Completes the @rrlab/* CLI decoupling. Command bodies become free-function actions, plugin resolution moves behind a ctx.plugins facade, the kernel-internal plugin contract vocabulary is renamed (capabilitiesservices, PluginKindPluginCapability), and the help surface is rebuilt on commander's native formatter.

Key changes

Layering

  • Commands are thin wrappers that resolve their service via ctx.plugins.getServiceOrThrow(...) and delegate to exactly one action (src/actions/*). Actions never import the CLI framework.
  • New ctx.plugins facade (services/plugin-services.ts) over PluginRegistry; getJsChecker() composes lint + format into a StaticCheckService when no plugin claims jsc directly.
  • createContext / ContextContextService / ContextValue.

Plugin contract (kernel-internal)

  • PluginKindPluginCapability; the capability-map type → PluginServices; runtime capabilities()services().
  • definePlugin takes a plain definition object (not a factory); it owns only narrowing + the dedup bin-probe.
  • bin dropped from the capability interfaces — ui is the only display field.
  • Official plugin list → src/lib/plugin/directory.ts; MissingPluginError(capability) derives its install hint from providersOf(capability).

Help surface

  • Root is a RunRunCmd subclass grouping commands + banner/footer.
  • Per-command Powered by: / See also: are auto-derived from each command's declared capabilities by the Cmd base class; the per-tool doctor subcommand is always present (lazy resolution), keeping the --usage KDL spec stable across machines.

clibuddy: drop the muted palette token and route callers through palette.dim.

Test plan

  • pnpm build && pnpm rr check && pnpm test — all green (8 packages lint/format/tsc; 16 build+test tasks).
  • Restored unit coverage for the composed jsc checker as static-checker.test.ts.
  • CLAUDE.md (×3), decisions/, and the changesets reconciled to the final shape.

Changesets

  • @rrlab/cli minor; @rrlab/{biome,oxc,ts,tsdown}-plugin patch (track the internal contract).
  • @vlandoss/clibuddy + @vlandoss/vland patch (palette muteddim).

🤖 Generated with Claude Code

Command bodies become free-function actions (src/actions/*) taking a single
<Name>ActionConfig object; commands are thin wrappers that resolve their service
via the ctx.plugins facade (throwing MissingPluginError when no configured
plugin provides the capability) and delegate to exactly one action. Actions
depend only on services/render/lib, never on the CLI framework.

Plugin contract & SDK:
- Rename the contract vocabulary: PluginKind -> PluginCapability, the
  capabilities map type -> PluginServices, and a plugin's runtime method
  capabilities() -> services(). definePlugin now takes a plain definition
  object (not a factory), applying `only` narrowing + dedup bin-probe itself.
- Drop the `bin` field from the capability interfaces; `ui` is the only display
  field (ToolService keeps bin private). Label dedup is dropped accordingly.
- Move the SDK to src/lib/plugin/*; ad-hoc errors become domain error classes
  (src/errors/* for the kernel, src/lib/plugin/errors.ts for the SDK).

Plugin resolution:
- PluginRegistry exposes getService/getServiceOrThrow, providerOf/providersOf,
  and getAllServices (distinct services deduped by reference, for rr doctor).
- A ctx.plugins facade (services/plugin-services.ts) is the only resolution
  surface commands touch; getJsChecker() composes lint+format into a
  StaticCheckService when no plugin claims jsc directly.
- The official plugin list moves to src/lib/plugin/directory.ts; each entry
  lists its capabilities, and MissingPluginError derives its install hint via
  providersOf(capability).
- createContext/Context become ContextService/ContextValue.

Help surface:
- Rebuilt on commander's native formatter: the root is a RunRunCmd subclass that
  groups commands and attaches a banner + installed/available plugins footer.
  Per-command "Powered by:" / "See also:" lines are auto-derived from each
  command's declared capabilities by the Cmd base class (src/program/base.ts);
  the per-tool doctor subcommand is always present (lazy resolution).

clibuddy: drop the `muted` palette token and route callers through palette.dim.

Regenerate CLI docs, add decision 015, restore the composed-jsc coverage as
static-checker.test.ts, and ship scoped changesets (@rrlab/* and @vlandoss/*).

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

changeset-bot Bot commented Jun 1, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 4903a88

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 7 packages
Name Type
@vlandoss/clibuddy Patch
@vlandoss/vland Patch
@rrlab/cli Minor
@rrlab/biome-plugin Patch
@rrlab/oxc-plugin Patch
@rrlab/ts-plugin Patch
@rrlab/tsdown-plugin Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@rqbazan rqbazan added the preview Ready to run CI/CD label Jun 1, 2026
@vland-bot

vland-bot Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Preview release

Latest commit: 4903a88

Some packages have been released:

Package Version Install
@rrlab/biome-plugin 1.1.1-git-4903a88.0 @rrlab/biome-plugin@1.1.1-git-4903a88.0
@rrlab/cli 1.1.1-git-4903a88.0 @rrlab/cli@1.1.1-git-4903a88.0
@rrlab/oxc-plugin 1.1.1-git-4903a88.0 @rrlab/oxc-plugin@1.1.1-git-4903a88.0
@rrlab/ts-plugin 1.1.1-git-4903a88.0 @rrlab/ts-plugin@1.1.1-git-4903a88.0
@rrlab/tsdown-plugin 1.1.1-git-4903a88.0 @rrlab/tsdown-plugin@1.1.1-git-4903a88.0
@vlandoss/clibuddy 0.7.1-git-4903a88.0 @vlandoss/clibuddy@0.7.1-git-4903a88.0
@vlandoss/vland 0.3.2-git-4903a88.0 @vlandoss/vland@0.3.2-git-4903a88.0

Note

Use the PR number as tag to install any package. For instance:

pnpm add @rrlab/biome-plugin@pr-235

@rqbazan rqbazan merged commit c82191d into main Jun 1, 2026
6 checks passed
@rqbazan rqbazan deleted the port/rrlab-decoupling branch June 1, 2026 23:23
@vland-bot vland-bot Bot mentioned this pull request Jun 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

preview Ready to run CI/CD

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant