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:
gus,is a symlink to thecommaexecutable.commalooks atargv[0], sees a trailing comma, strips it, and findsgusin the config.- 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_handlehooks. 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, includingxargs,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_handlefallback. The hook only fires when a PATH lookup fails, so it cannot resolve a name whoseNAME,file already exists; it is also bash-only and fights the distro's own hook.comma addinstead refuses to overwrite a foreignNAME,unless you pass--force, and CI/scripts usecomma NAME, .... [commands.<name>]is canonical. Per-command options (env,cwd, ...) live in that sub-table. Thename = "..."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, andcomma'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
.cmdshim layer, which is not implemented yet. - The
comma-commandcrate 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)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| comma_command-0.2.0.tar.gz | 18.6 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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.