Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

carapace-commander

Generate a carapace completion spec from any commander.js-based command-line tool by parsing its --help output recursively. Point it at a binary, get a carapace-spec YAML in your carapace specs directory.

It exists because carapace bridges clap, cobra, click, yargs, argcomplete, and urfave, but not commander.js, and commander ships no machine-readable completion. Much of the Node CLI ecosystem (including claude) is built on commander, so this fills exactly that gap. One reusable binary instead of a folder of per-tool scripts, and zero config: just name the tool.

Install

cargo install --git https://github.com/futuun/carapace-commander
# or, from a clone:
cargo install --path .

You'll need carapace installed, and the target CLI on your PATH.

Usage

carapace-commander claude          # writes <config-dir>/carapace/specs/claude.yaml
carapace-commander pm2             # any commander.js CLI

Then claude <TAB> completes its flags and subcommands. The first time you generate a spec for a command carapace didn't already know, start a new shell so carapace registers it (it loads the specs directory at startup); later updates to that command are picked up live.

The spec directory follows carapace's own layout (macOS ~/Library/Application Support, Linux $XDG_CONFIG_HOME or ~/.config, Windows %AppData%), under carapace/specs/.

Tools run through a launcher (npx, pnpm dlx, bunx, ...)

For a CLI you invoke through a launcher rather than directly:

carapace-commander npx cypress     # writes npx.yaml with cypress nested inside
carapace-commander npx -y pm2      # accumulates: npx.yaml now has cypress and pm2

npx cypress <TAB> then completes cypress's own subcommands and flags. The wrapped command is nested under the launcher's spec because that's the command you actually type. Re-running is a no-op while the package's version is unchanged, and running carapace-commander npx on its own won't clobber the packages you've nested.

Keeping completions up to date

Re-running is cheap: the spec header records the tool's version, and the run short-circuits when it still matches <cmd> --version. That makes it safe to call on every shell or editor startup. For example, a Claude Code SessionStart hook that keeps claude's completion fresh:

{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "startup",
        "hooks": [
          {
            "type": "command",
            "command": "carapace-commander claude",
            "timeout": 60
          }
        ]
      }
    ]
  }
}

When a regen actually changes the surface (the tool updated), it prints a short changelog of the commands and flags added or removed.

How it works

A small four-stage pipeline behind an always-on version gate:

  1. Fetch: run <cmd> [subpath...] --help through a pipe (commander wraps to its 80-column non-TTY default; the parser folds the wrapping).
  2. Parse: turn the commander help dialect (Options: / Commands: headers, <arg>/[arg] metavars, name|alias aliases, width-wrapped continuation lines) into a command tree, recursing into each subcommand.
  3. Enrich: attach value completions from three generic, config-free layers: machine-readable choices: "a", "b" clauses; the metavar shape (<dir> for directories, <file>/<path> for files); and trailing prose enums like (low, medium, high).
  4. Emit: serialize the tree to YAML under a # header and write it to the specs dir.

The honest cost of staying config-free: values that never appear as an enum in the help (e.g. --model, documented as prose) get no suggestions. The flag still completes, just without value hints.

Notes

  • The target must be a commander.js CLI. carapace-commander detects this by commander's default display help for command and refuses otherwise (other frameworks already have carapace bridges).
  • carapace-commander installs its own completion spec on first run, so carapace-commander <TAB> completes commands on your PATH.

Development

cargo test
cargo clippy --all-targets

The --help fetch is injected as a closure, so the parser is tested against fixture strings without shelling out (see the tests in src/parse.rs).

License

The carapace-commander source code is licensed under MIT.

About

Generate a carapace completion spec from any commander.js CLI by parsing its --help

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages