Skip to content

feat: support subcommand aliases#236

Merged
pi0 merged 1 commit intomainfrom
feat/subcommand-aliases
Mar 15, 2026
Merged

feat: support subcommand aliases#236
pi0 merged 1 commit intomainfrom
feat/subcommand-aliases

Conversation

@pi0
Copy link
Copy Markdown
Member

@pi0 pi0 commented Mar 15, 2026

Summary

Adds support for defining aliases on subcommands via CommandMeta.alias, resolving #152.

defineCommand({
  subCommands: {
    install: {
      meta: { alias: ["i", "add"] },
      run: () => { /* ... */ },
    },
  },
})
  • alias field accepts string | string[] on CommandMeta
  • Direct subcommand key matches take priority over alias lookups
  • Aliases are displayed in --help output (e.g. install, i, add)
  • Works with nested subcommands

Consolidates work from #155, #170, and #224 — all three original authors are credited.

Lazy loading

Alias resolution is designed to minimize unnecessary subcommand loading:

  • Direct key match (fast path): name in subCommands is a plain property check — no subcommand is resolved or imported.
  • Alias fallback: Only reached when the direct key doesn't match. Subcommands are resolved one-by-one and iteration stops at the first alias hit, so dynamic imports (() => import("./cmd.ts")) are only triggered as needed.
  • Worst case: An unknown command resolves all subcommands before erroring — acceptable since it's already an error path.

Hoisting aliases into a separate top-level map was considered but rejected to keep the DX simple (single source of truth in meta).

Test plan

  • Single alias resolution (iinstall)
  • Array alias resolution (addinstall)
  • Nested alias resolution (ws lsworkspace list)
  • Direct key match takes priority over alias
  • Unknown command still throws E_UNKNOWN_COMMAND
  • Aliases appear in usage/help output
  • Full test suite passes (76/76)

🤖 Generated with Claude Code

Co-Authored-By: 苏向夜 67710306+fu050409@users.noreply.github.com
Co-Authored-By: Horu HigherOrderLogic@users.noreply.github.com
Co-Authored-By: TJ ratiofu@users.noreply.github.com

Add `alias` field to `CommandMeta` allowing subcommands to be invoked by
alternate names (e.g. `i` for `install`). Direct key matches are preferred
over alias lookups. Aliases are displayed in help/usage output.

Closes #152

Co-Authored-By: 苏向夜 <67710306+fu050409@users.noreply.github.com>
Co-Authored-By: Horu <HigherOrderLogic@users.noreply.github.com>
Co-Authored-By: TJ <ratiofu@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 15, 2026

📝 Walkthrough

Walkthrough

This PR introduces alias support for subcommands, enabling commands to be resolved by alternative names. A new _findSubCommand helper prioritizes direct key matches before checking aliases. Command metadata now includes an optional alias property, and usage output displays these aliases alongside command names.

Changes

Cohort / File(s) Summary
Type Definition
src/types.ts
Added optional alias?: string | string[] property to CommandMeta interface.
Command Resolution and Execution
src/command.ts
Introduced internal _findSubCommand helper to resolve subcommands via direct match or alias lookup. Updated run and resolveSubCommand methods to use this helper. Added imports for toArray utility and SubCommandsDef type.
Usage Rendering
src/usage.ts
Updated subcommand rendering to display aliases alongside command names using toArray(meta?.alias), combining the original command name with all resolved aliases in the usage output.
Test Suite
test/main.test.ts
Added comprehensive test suite validating alias resolution across single aliases, multiple aliases, nested subcommands, direct match precedence, unknown commands, and usage output formatting.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 Hops through names both old and new,
Aliases bloom in the morning dew,
Direct matches first, then secrets unfold,
Sub-commands dance as they're told! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: support subcommand aliases' clearly and concisely summarizes the main change of the pull request, which is adding alias support for subcommands.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/subcommand-aliases
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@pi0 pi0 changed the title feat(command): support subcommand aliases feat: support subcommand aliases Mar 15, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
test/main.test.ts (1)

263-266: Use an inline snapshot for usage output assertions.

Lines 264-265 currently use substring checks; switch this usage-output test to an inline snapshot to match repo test conventions.

As per coding guidelines, Tests should use inline snapshots for usage output verification.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/main.test.ts` around lines 263 - 266, Replace the two substring
assertions that check usage with a single inline snapshot assertion: call
renderUsage(command) into the usage variable (as already done) and replace
expect(usage).toContain(...) lines with
expect(usage).toMatchInlineSnapshot(...). Update the test in the same test block
that uses renderUsage/usage/command to assert the full usage output as an inline
snapshot (you can run the test to capture the actual usage string or paste the
expected usage text into the snapshot).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@test/main.test.ts`:
- Around line 263-266: Replace the two substring assertions that check usage
with a single inline snapshot assertion: call renderUsage(command) into the
usage variable (as already done) and replace expect(usage).toContain(...) lines
with expect(usage).toMatchInlineSnapshot(...). Update the test in the same test
block that uses renderUsage/usage/command to assert the full usage output as an
inline snapshot (you can run the test to capture the actual usage string or
paste the expected usage text into the snapshot).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 262a9bd9-c344-40c7-8176-b0c7b992c4cb

📥 Commits

Reviewing files that changed from the base of the PR and between 69252d4 and b4d9a96.

📒 Files selected for processing (4)
  • src/command.ts
  • src/types.ts
  • src/usage.ts
  • test/main.test.ts

@pi0 pi0 merged commit 6840275 into main Mar 15, 2026
3 checks passed
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.

1 participant