Skip to main content

comma-command

Run any command you have installed from any shell, as if it were a shell builtin:

$ gus, hello world
# → too talk gus -- hello world

Register an entry once. From then on, NAME, any words is the whole interface — no aliases to source, no shell hook, no TUI.

Install

$ uv tool install comma-command    # or: pipx install comma-command
$ comma init --write               # puts the shim directory on PATH
$ exec $SHELL                      # or open a new terminal

Quickstart

$ comma add gus -- too talk gus --
added gus, → too talk gus --

$ comma add pyi -- uv run ipython --
added pyi, → uv run ipython --

$ gus, hello world          # runs: too talk gus -- hello world
$ pyi, --pdb script.py      # runs: uv run ipython -- --pdb script.py
$ comma ls
gus,  too talk gus --
pyi,  uv run ipython --

comma add does two things: writes the entry to ~/.config/comma/config.toml and creates an executable named exactly gus, in ~/.local/share/comma/bin.

How it works

The shim is a multicall dispatcher — the same trick busybox and git use for subcommands, applied to names:

  1. gus, is a symlink to the comma executable.
  2. comma looks at argv[0], sees a trailing comma, strips it, and finds gus in the config.
  3. It calls os.execvpe("too", ["too", "talk", "gus", "--", "hello", "world"]).

If the shim directory is not on PATH — a CI job, a container, a repo where nobody ran comma init — comma gus, hello world reaches the same dispatch path. comma takes NAME, rather than bare NAME so that a registered name can never collide with the management subcommands (ls, run, doctor, ...).

Because the final step replaces the process instead of spawning a child, the target command inherits the terminal, stdin, signals and job control directly, and its exit status reaches your shell unchanged. comma, adds no wrapping layer.

Why not the alternatives:

  • Shell aliases/functions. gus, is not a portable function name in bash or fish, and functions only exist in interactive shells you have sourced.
  • command_not_found_handle hooks. Bash-only, collides with distro handlers (Nix, Debian's package suggestion hook), and silently does nothing in non-interactive shells, sh -c, cron, or most editors' task runners.
  • Shims on PATH. Work everywhere a real executable works, including xargs, find -exec, CI scripts, Makefiles and shell completion.

Configuration

~/.config/comma/config.toml — managed by comma, but hand-editable:

[commands.gus]
cmd = ["too", "talk", "gus", "--"]

# shorthand is fine too
[commands.pyi]
cmd = "uv run ipython --"

This [commands.<name>] table is the canonical schema: per-command options such as env and cwd will live in it. The name = "..." shorthand is accepted as input sugar and is shown here only so you can read someone else's config.

Arguments are appended verbatim, so -- at the end of cmd is the usual way to keep flags from being swallowed by the target's own option parser.

Per-command settings live in the same table:

[commands.deploy]
cmd = ["kubectl", "apply", "-f", "k8s/"]
cwd = "~/src/infra"
env = { KUBECONFIG = "~/.kube/staging" }
env_unset = ["HTTP_PROXY"]

env is merged into the inherited environment, so PATH and HOME keep working, and env_unset drops inherited variables first — a name may not appear in both. cwd is ~-expanded and applied before the target runs. The same options exist on the command line: comma add --env K=V --unset K --cwd DIR NAME -- CMD....

Commands

Command What it does
comma add [--env K=V] [--unset K] [--cwd DIR] NAME -- CMD... register a name and create its NAME, shim
comma edit open the config in $EDITOR, re-validate it, reconcile the shims
comma rm NAME unregister a name and remove its shim
comma ls [--json] list registered names
comma run NAME [--] [ARG...] run a name without going through the shim
comma NAME, [ARG...] the shell spelling, without the shim on PATH (handy in CI)
comma which NAME show the shim path and the command it runs
comma init [--write] [--shell S] print or install PATH + completion setup
comma doctor check config, PATH, shims and targets
comma completion bash|zsh|fish print a completion script

Names must be shell-safe words: letters, digits, ., _, +, -. The comma is added for you, so comma add gus, -- ... is rejected rather than silently creating gus,,.

Design decisions

Recorded so they do not get relitigated every release:

  • No command_not_found_handle fallback. The hook only fires when a PATH lookup fails, so it cannot resolve a name whose NAME, file already exists; it is also bash-only and fights the distro's own hook. comma add instead refuses to overwrite a foreign NAME, unless you pass --force, and CI/scripts use comma NAME, ....
  • [commands.<name>] is canonical. Per-command options (env, cwd, ...) live in that sub-table. The name = "..." shorthand stays as input sugar and is not documented twice.
  • No argument completion for target commands. Command-position completion is free because the shims are real files on PATH, and comma's own subcommands have completion. Completing a target's arguments would need a completion protocol per target — out of scope for 0.1, and better designed once someone actually needs it.

Limits

  • POSIX first. Windows would need a .cmd shim layer, which is not implemented yet.
  • The comma-command crate on crates.io is a name reservation for a future native binary; the Python implementation is the one to install today.

Development

$ uv venv && uv pip install -e '.[dev]'
$ uv run pytest
$ uv run ruff check .

MIT licensed.

Metadata

Release files for comma-command 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for comma-command 0.2.0
File Size Uploaded Provenance
comma_command-0.2.0.tar.gz 18.6 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for comma-command 0.2.0
File Interpreter ABI Platform
comma_command-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 34.0 kB

Release files / comma_command-0.2.0.tar.gz

Download URL comma_command-0.2.0.tar.gz
Size 18.6 kB
Tags Source
SHA-256 checksum
How to use checksums
d42a3f758a2ee9d5c982123016c916e491172289b124e3986fdd9b62d93da8e1
BLAKE2b-256 checksum
How to use checksums
4f9f97c5d80d0674d37649430c7b1dce68e08494ba0a965313b75971b30c3fd1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.0 {"installer":{"name":"uv","version":"0.10.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / comma_command-0.2.0-py3-none-any.whl

Download URL comma_command-0.2.0-py3-none-any.whl
Size 15.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c8e2f5b3bb1aa9d390e389c17935c448333edf46f645eb2365d545f84ec6da7c
BLAKE2b-256 checksum
How to use checksums
f83a4123b9b2f2f0d53c0fd460092bb571a1d6b299132ae1ba0e68f71a5482a5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.0 {"installer":{"name":"uv","version":"0.10.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for comma-command 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page