Skip to content

feat(cli): support Ruby's short subcommand aliases - #15

Merged
bougyman merged 1 commit into
mainfrom
issue-14
Aug 9, 2026
Merged

feat(cli): support Ruby's short subcommand aliases#15
bougyman merged 1 commit into
mainfrom
issue-14

Conversation

@bougyman

@bougyman bougyman commented Aug 9, 2026

Copy link
Copy Markdown
Member

Summary

Closes #14.

lc i dev CRY-37 failed - Optimus's subcommand spec has no alias mechanism (verified: no alias support in vendor/optimus/lib/optimus/subcommand.ex), so only canonical subcommand names worked. Ruby registers short aliases via each command module's ALIASES constant (cli.rb's register/register_sub!); the full table below was pulled from those constants directly, not the Readme's incomplete prose list (which was missing new/add/me/who/teams/projects/issues/t/p/v).

Command Aliases
whoami me, w, who, whodat
version v
issue i, issues
team t, teams
project p, projects
issue create c, new, add
issue develop d, dev
issue list l, ls
issue update u
issue pr pull-request
team list l, ls
project list l, ls

issue take has no alias in Ruby either, so none was invented for it here. completion (dry-cli-specific) and console/pry (Ruby dev tooling) have no equivalent in this port, so they're intentionally excluded.

Implementation is the same pre-parse-rewrite pattern as normalize_aliases/1 (flag aliases): expand the leading 1-2 argv tokens to their canonical form via a plain map lookup before Optimus.parse!/3 ever sees them. Has to run before normalize_help/1, since Optimus's help <path> only recognizes canonical subcommand names, not aliases - verified via a dedicated test (lc i dev --help composes to the real issue develop help).

Also updates Readme.adoc with the alias table, and adds a docs!-adjacent doc fix that was bundled into this branch.

Test plan

  • mix test - 180 passed (added: unit tests on the pure rewrite for every alias category, an end-to-end dispatch test for 4 aliased invocations, and a composition test proving alias-expansion + --help interact correctly)
  • mix format --check-formatted - clean
  • Rebuilt the real macOS Burrito binary and manually verified lc i (bare) now shows issue's own subcommand help instead of nothing useful, and lc i dev --help shows the real issue develop help

Optimus's subcommand spec has no alias mechanism (verified: no `alias`
support in vendor/optimus/lib/optimus/subcommand.ex), so `lc i dev
CRY-37` failed - only canonical names worked. Ruby registers these via
each command module's ALIASES constant (cli.rb's register/register_sub!);
sourced the full table from there rather than the Readme's incomplete
prose list, which was missing several (new/add/me/who/teams/projects/
issues/t/p/v).

Same pre-parse-rewrite pattern as normalize_aliases/1 (flag aliases):
expand the leading 1-2 tokens to their canonical form via a plain map
lookup before Optimus.parse!/3 ever sees them. Has to run before
normalize_help/1, since Optimus's `help <path>` only recognizes
canonical subcommand names, not aliases.

completion (dry-cli-specific) and console/pry (Ruby dev tooling) have
no equivalent here, so they're intentionally not included. `issue take`
has no alias in Ruby either, so none was invented for it here.

Closes #14.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 9, 2026 20:42
@bougyman
bougyman merged commit 9fca6b5 into main Aug 9, 2026
2 of 3 checks passed
@bougyman
bougyman deleted the issue-14 branch August 9, 2026 20:42

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds Ruby-compatible short aliases for top-level commands and select subcommands in the Elixir CLI by rewriting argv tokens pre-parse, ensuring downstream Optimus parsing and --help composition work with canonical subcommand paths.

Changes:

  • Introduces normalize_subcommand_aliases/1 and wires it into the argv normalization pipeline before normalize_help/1.
  • Adds unit + integration tests covering alias rewrites, end-to-end dispatch via aliases, and alias + --help composition.
  • Updates Readme.adoc to document the complete alias table and provide example invocations.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
Readme.adoc Documents supported command/subcommand aliases and example usage.
app/test/linear_cli/cli_test.exs Adds tests validating alias rewriting behavior and end-to-end dispatch/help behavior for aliased invocations.
app/lib/linear_cli/cli.ex Implements alias rewrite maps and applies the rewrite step before help normalization.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread app/lib/linear_cli/cli.ex
Comment on lines +108 to +121
@doc false
def normalize_subcommand_aliases([first | rest]) do
canonical_first = Map.get(@command_aliases, first, first)

case {Map.fetch(@subcommand_aliases, canonical_first), rest} do
{{:ok, sub_aliases}, [second | more]} ->
[canonical_first, Map.get(sub_aliases, second, second) | more]

_ ->
[canonical_first | rest]
end
end

def normalize_subcommand_aliases(argv), do: argv
bougyman pushed a commit that referenced this pull request Aug 9, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.3.0](v0.2.1...v0.3.0)
(2026-08-09)


### ⚠ BREAKING CHANGES

* add Readme/LICENSE, feat: wire up the issue list --project picker
([#12](#12))

### Features

* **api:** add LinearCli.Api GraphQL client (Phase 1)
([723f3f6](723f3f6))
* **cli:** add issue create/develop/pr/take/update write commands (Phase
6)
([1649618](1649618))
* **cli:** support Ruby's short subcommand aliases
([#15](#15))
([9fca6b5](9fca6b5))
* initial commit with ash submodule
([c2ceafb](c2ceafb))
* **linear:** add Ash domain resources for
Issue/Project/Team/User/Label/WorkflowState/Comment (Phase 2)
([e2a27f3](e2a27f3))
* **oban:** add scheduled monthly project rollover (Phase 7)
([11afb43](11afb43))
* phase 4 from initial plan -&gt; complete
([012866e](012866e))
* phase 8 - packaging, releasing, and CI
([#1](#1))
([905c238](905c238))
* scaffold Elixir port and enforce conventional commits
([a4d03a0](a4d03a0))


### Bug Fixes

* **ci:** create releases as drafts so assets survive Immutable Releases
([#19](#19))
([8572623](8572623))
* **cli:** reject unrecognized flags instead of treating them as issue
ids ([#2](#2))
([#4](#4))
([e697ff6](e697ff6))


### Performance Improvements

* **linear:** fan out find-by-ids and per-team project fetches (Phase 5)
([fb00153](fb00153))


### Documentation

* add Readme/LICENSE, feat: wire up the issue list --project picker
([#12](#12))
([eb42c69](eb42c69))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
This was referenced Aug 9, 2026
bougyman pushed a commit that referenced this pull request Aug 9, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.4.0](v0.3.1...v0.4.0)
(2026-08-09)


### ⚠ BREAKING CHANGES

* add Readme/LICENSE, feat: wire up the issue list --project picker
([#12](#12))

### Features

* **api:** add LinearCli.Api GraphQL client (Phase 1)
([723f3f6](723f3f6))
* **cli:** add issue create/develop/pr/take/update write commands (Phase
6)
([1649618](1649618))
* **cli:** support Ruby's short subcommand aliases
([#15](#15))
([9fca6b5](9fca6b5))
* initial commit with ash submodule
([c2ceafb](c2ceafb))
* **linear:** add Ash domain resources for
Issue/Project/Team/User/Label/WorkflowState/Comment (Phase 2)
([e2a27f3](e2a27f3))
* **oban:** add scheduled monthly project rollover (Phase 7)
([11afb43](11afb43))
* phase 4 from initial plan -&gt; complete
([012866e](012866e))
* phase 8 - packaging, releasing, and CI
([#1](#1))
([905c238](905c238))
* scaffold Elixir port and enforce conventional commits
([a4d03a0](a4d03a0))


### Bug Fixes

* **ci:** create releases as drafts so assets survive Immutable Releases
([#19](#19))
([8572623](8572623))
* **ci:** package release binaries with the wrapper scripts
([#24](#24))
([5fb24a4](5fb24a4))
* **cli:** reject unrecognized flags instead of treating them as issue
ids ([#2](#2))
([#4](#4))
([e697ff6](e697ff6))


### Performance Improvements

* **linear:** fan out find-by-ids and per-team project fetches (Phase 5)
([fb00153](fb00153))


### Documentation

* add Readme/LICENSE, feat: wire up the issue list --project picker
([#12](#12))
([eb42c69](eb42c69))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
bougyman pushed a commit that referenced this pull request Aug 9, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.5.0](v0.4.0...v0.5.0)
(2026-08-09)


### ⚠ BREAKING CHANGES

* add Readme/LICENSE, feat: wire up the issue list --project picker
([#12](#12))

### Features

* **api:** add LinearCli.Api GraphQL client (Phase 1)
([723f3f6](723f3f6))
* **cli:** add issue create/develop/pr/take/update write commands (Phase
6)
([1649618](1649618))
* **cli:** support Ruby's short subcommand aliases
([#15](#15))
([9fca6b5](9fca6b5))
* initial commit with ash submodule
([c2ceafb](c2ceafb))
* **linear:** add Ash domain resources for
Issue/Project/Team/User/Label/WorkflowState/Comment (Phase 2)
([e2a27f3](e2a27f3))
* **oban:** add scheduled monthly project rollover (Phase 7)
([11afb43](11afb43))
* phase 4 from initial plan -&gt; complete
([012866e](012866e))
* phase 8 - packaging, releasing, and CI
([#1](#1))
([905c238](905c238))
* scaffold Elixir port and enforce conventional commits
([a4d03a0](a4d03a0))


### Bug Fixes

* **ci:** create releases as drafts so assets survive Immutable Releases
([#19](#19))
([8572623](8572623))
* **ci:** package release binaries with the wrapper scripts
([#24](#24))
([5fb24a4](5fb24a4))
* **cli:** reject unrecognized flags instead of treating them as issue
ids ([#2](#2))
([#4](#4))
([e697ff6](e697ff6))


### Performance Improvements

* **linear:** fan out find-by-ids and per-team project fetches (Phase 5)
([fb00153](fb00153))


### Documentation

* add Readme/LICENSE, feat: wire up the issue list --project picker
([#12](#12))
([eb42c69](eb42c69))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
bougyman pushed a commit that referenced this pull request Aug 9, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.6.0](v0.5.0...v0.6.0)
(2026-08-09)


### ⚠ BREAKING CHANGES

* add Readme/LICENSE, feat: wire up the issue list --project picker
([#12](#12))

### Features

* **api:** add LinearCli.Api GraphQL client (Phase 1)
([723f3f6](723f3f6))
* **cli:** add issue create/develop/pr/take/update write commands (Phase
6)
([1649618](1649618))
* **cli:** support Ruby's short subcommand aliases
([#15](#15))
([9fca6b5](9fca6b5))
* initial commit with ash submodule
([c2ceafb](c2ceafb))
* **linear:** add Ash domain resources for
Issue/Project/Team/User/Label/WorkflowState/Comment (Phase 2)
([e2a27f3](e2a27f3))
* **oban:** add scheduled monthly project rollover (Phase 7)
([11afb43](11afb43))
* phase 4 from initial plan -&gt; complete
([012866e](012866e))
* phase 8 - packaging, releasing, and CI
([#1](#1))
([905c238](905c238))
* scaffold Elixir port and enforce conventional commits
([a4d03a0](a4d03a0))


### Bug Fixes

* **ci:** create releases as drafts so assets survive Immutable Releases
([#19](#19))
([8572623](8572623))
* **ci:** package release binaries with the wrapper scripts
([#24](#24))
([5fb24a4](5fb24a4))
* **cli:** reject unrecognized flags instead of treating them as issue
ids ([#2](#2))
([#4](#4))
([e697ff6](e697ff6))


### Performance Improvements

* **linear:** fan out find-by-ids and per-team project fetches (Phase 5)
([fb00153](fb00153))


### Documentation

* add Readme/LICENSE, feat: wire up the issue list --project picker
([#12](#12))
([eb42c69](eb42c69))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
bougyman pushed a commit that referenced this pull request Aug 9, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.7.0](v0.6.0...v0.7.0)
(2026-08-09)


### ⚠ BREAKING CHANGES

* add Readme/LICENSE, feat: wire up the issue list --project picker
([#12](#12))

### Features

* **api:** add LinearCli.Api GraphQL client (Phase 1)
([723f3f6](723f3f6))
* **cli:** add issue create/develop/pr/take/update write commands (Phase
6)
([1649618](1649618))
* **cli:** support Ruby's short subcommand aliases
([#15](#15))
([9fca6b5](9fca6b5))
* initial commit with ash submodule
([c2ceafb](c2ceafb))
* **linear:** add Ash domain resources for
Issue/Project/Team/User/Label/WorkflowState/Comment (Phase 2)
([e2a27f3](e2a27f3))
* **oban:** add scheduled monthly project rollover (Phase 7)
([11afb43](11afb43))
* phase 4 from initial plan -&gt; complete
([012866e](012866e))
* phase 8 - packaging, releasing, and CI
([#1](#1))
([905c238](905c238))
* scaffold Elixir port and enforce conventional commits
([a4d03a0](a4d03a0))


### Bug Fixes

* **ci:** create releases as drafts so assets survive Immutable Releases
([#19](#19))
([8572623](8572623))
* **ci:** package release binaries with the wrapper scripts
([#24](#24))
([5fb24a4](5fb24a4))
* **cli:** reject unrecognized flags instead of treating them as issue
ids ([#2](#2))
([#4](#4))
([e697ff6](e697ff6))


### Performance Improvements

* **linear:** fan out find-by-ids and per-team project fetches (Phase 5)
([fb00153](fb00153))


### Documentation

* add Readme/LICENSE, feat: wire up the issue list --project picker
([#12](#12))
([eb42c69](eb42c69))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
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.

Support Ruby's short subcommand aliases (lc i dev CRY-37, etc.)

2 participants