feat: replace :Forge CLI with a canonical Ex-style command interface #142

Closed
opened 2026-04-11 19:02:07 +00:00 by barrettruth · 0 comments
barrettruth commented 2026-04-11 19:02:07 +00:00

Prerequisites

  • I have searched existing issues.

Problem

The current :Forge command surface is still early and inconsistent:

  • it mixes route-launcher behavior, picker entrypoints, and direct actions
  • it depends too heavily on positional argument order
  • it does not model explicit targeting well enough for fork/upstream workflows
  • it does not give users a canonical way to specify repo + revision + location
  • picker workflows can currently express capabilities that the CLI cannot express cleanly

That makes the command interface hard to reason about and hard to extend.

We have enough freedom right now to replace the current ad hoc syntax with a canonical Ex-style interface before it ossifies.

Proposed solution

Adopt a canonical :Forge command language with these properties:

1. Explicit family/verb structure

Canonical forms should be structured like:

  • :Forge pr list ...
  • :Forge pr review 123 ...
  • :Forge issue create ...
  • :Forge ci list ...
  • :Forge release delete v1.2.3 ...
  • :Forge browse ...

This should become the documented interface; older shorthand should be treated as compatibility sugar at most.

2. Ex-style modifiers, not prose syntax

Use key=value atoms and bare boolean atoms instead of natural-language clauses.

Examples:

  • state=closed
  • repo=upstream
  • rev=main
  • target=upstream@main:README.md#L10-L20
  • base=upstream@main
  • head=@topic
  • all, draft, fill, web, blank

Modifiers must be order-independent.

3. First-class address model

The command language should support explicit addressing for:

  • repo address: upstream, origin, owner/repo, host/group/repo
  • revision address: @main, upstream@main, owner/repo@abc1234
  • location address: upstream@main:path/to/file#L10-L20

This should be a first-class command concept, not an implementation detail.

4. Narrow, Ex-like bang semantics

! should only be allowed on subcommands with a real force variant.

Initial bang matrix:

  • allowed: pr close, issue close, release delete
  • disallowed everywhere else

If ! is supplied where unsupported, Forge should follow normal Ex behavior and error with:

  • E477: No ! allowed

5. CLI parity for semantic operations

Anything meaningful the picker can do or view should have a command form too.

That includes current PR manage operations such as:

  • approve
  • merge
  • mark draft / mark ready

The picker should remain a discovery UI, but not the only way to access domain operations.

6. Defaults stay policy; explicit targets override policy

When users omit addressing, Forge can still apply sensible defaults (upstream-first, branch-remote, etc.). But the language must allow users to override those defaults precisely.

Canonical v1 command families

  • pr list|review|checkout|worktree|browse|ci|manage|close|reopen|create|edit
  • issue list|browse|close|reopen|create
  • ci list|log|watch
  • release list|browse|delete
  • browse

Follow-up issues

  • #143 normalized parser/dispatcher + bang validation
  • #144 explicit repo/revision/location target parsing
  • #145 command parity for picker capabilities
  • #146 contextual command-line completion
  • #147 target alias/default resolution policy
  • #148 shared operation layer for picker/CLI parity

Acceptance criteria

  • final grammar documented in doc/forge.nvim.txt
  • subcommand/mutator matrix finalized
  • target/address syntax finalized
  • bang matrix finalized
  • compatibility policy for old syntax decided explicitly
  • follow-up issues tracked for parser, target resolution, defaults, shared operations, command parity, and completion

Alternatives considered

  • Keep the current ad hoc command interface and extend it incrementally. This keeps short-term churn low but preserves a weak grammar and makes explicit repo/revision targeting harder to add cleanly.
  • Use GNU-style --repo / --state as the primary interface. This is workable but feels less like Ex than key=value modifiers.
  • Use prose syntax such as in upstream or at repo@ref. This reads naturally but does not fit Vim/Neovim command style.

Relevant prior context:

  • #27 (:Forge ci <ref>)
  • #79 (picker-agnostic :Forge workflow)
## Prerequisites - [x] I have searched existing issues. ## Problem The current `:Forge` command surface is still early and inconsistent: - it mixes route-launcher behavior, picker entrypoints, and direct actions - it depends too heavily on positional argument order - it does not model explicit targeting well enough for fork/upstream workflows - it does not give users a canonical way to specify repo + revision + location - picker workflows can currently express capabilities that the CLI cannot express cleanly That makes the command interface hard to reason about and hard to extend. We have enough freedom right now to replace the current ad hoc syntax with a canonical Ex-style interface before it ossifies. ## Proposed solution Adopt a canonical `:Forge` command language with these properties: ### 1. Explicit family/verb structure Canonical forms should be structured like: - `:Forge pr list ...` - `:Forge pr review 123 ...` - `:Forge issue create ...` - `:Forge ci list ...` - `:Forge release delete v1.2.3 ...` - `:Forge browse ...` This should become the documented interface; older shorthand should be treated as compatibility sugar at most. ### 2. Ex-style modifiers, not prose syntax Use `key=value` atoms and bare boolean atoms instead of natural-language clauses. Examples: - `state=closed` - `repo=upstream` - `rev=main` - `target=upstream@main:README.md#L10-L20` - `base=upstream@main` - `head=@topic` - `all`, `draft`, `fill`, `web`, `blank` Modifiers must be order-independent. ### 3. First-class address model The command language should support explicit addressing for: - repo address: `upstream`, `origin`, `owner/repo`, `host/group/repo` - revision address: `@main`, `upstream@main`, `owner/repo@abc1234` - location address: `upstream@main:path/to/file#L10-L20` This should be a first-class command concept, not an implementation detail. ### 4. Narrow, Ex-like bang semantics `!` should only be allowed on subcommands with a real force variant. Initial bang matrix: - allowed: `pr close`, `issue close`, `release delete` - disallowed everywhere else If `!` is supplied where unsupported, Forge should follow normal Ex behavior and error with: - `E477: No ! allowed` ### 5. CLI parity for semantic operations Anything meaningful the picker can do or view should have a command form too. That includes current PR manage operations such as: - approve - merge - mark draft / mark ready The picker should remain a discovery UI, but not the only way to access domain operations. ### 6. Defaults stay policy; explicit targets override policy When users omit addressing, Forge can still apply sensible defaults (upstream-first, branch-remote, etc.). But the language must allow users to override those defaults precisely. ### Canonical v1 command families - `pr list|review|checkout|worktree|browse|ci|manage|close|reopen|create|edit` - `issue list|browse|close|reopen|create` - `ci list|log|watch` - `release list|browse|delete` - `browse` ### Follow-up issues - [ ] #143 normalized parser/dispatcher + bang validation - [ ] #144 explicit repo/revision/location target parsing - [ ] #145 command parity for picker capabilities - [ ] #146 contextual command-line completion - [ ] #147 target alias/default resolution policy - [ ] #148 shared operation layer for picker/CLI parity ### Acceptance criteria - [ ] final grammar documented in `doc/forge.nvim.txt` - [ ] subcommand/mutator matrix finalized - [ ] target/address syntax finalized - [ ] bang matrix finalized - [ ] compatibility policy for old syntax decided explicitly - [ ] follow-up issues tracked for parser, target resolution, defaults, shared operations, command parity, and completion ## Alternatives considered - Keep the current ad hoc command interface and extend it incrementally. This keeps short-term churn low but preserves a weak grammar and makes explicit repo/revision targeting harder to add cleanly. - Use GNU-style `--repo` / `--state` as the primary interface. This is workable but feels less like Ex than `key=value` modifiers. - Use prose syntax such as `in upstream` or `at repo@ref`. This reads naturally but does not fit Vim/Neovim command style. Relevant prior context: - #27 (`:Forge ci <ref>`) - #79 (picker-agnostic `:Forge` workflow)
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
barrettruth/forge.nvim#142
No description provided.