Ever found yourself typing python script.py --output and freezing... "Was it --output_path or --output_base_path? Or maybe just --output?" 😅
We've all been there: hastily hitting Ctrl+C, running python script.py --help, only to realize your carefully crafted command is now lost to the bash history void. And of course, the moment you see the help output, you remember you also needed to set --num-workers.
py-args-autocomplete gives you Tab-completion for the arguments of any Python CLI — with zero configuration and no changes to the target script. Unlike argcomplete (which needs a marker in every script) or click's completion (which only works for click apps), it derives completions from the one interface every CLI already has: its --help output.
A ~40-line shell stub asks a small Python engine for candidates on Tab. The engine resolves what you're running (a python script.py, a python -m pkg, or an installed entry point like vllm), runs its --help once, parses it into a completion spec, and caches the spec on disk. Every Tab after that is a ~45 ms cache hit — even for scripts that take seconds to import.
$ python train.py --[Tab]
--batch-size --epochs --learning-rate --model --num-workers --optimizer
$ python train.py --optimizer [Tab]
adam adamw sgd
$ python train.py --optimizer adam --[Tab] # used args are filtered out
--batch-size --epochs --learning-rate --model --num-workers
- Zero configuration — works with argparse, click, typer, docopt, fire... anything with
--help. - Fast — on-disk spec cache keyed by script mtime; warm Tab ≈ 45 ms. Scripts whose
--helphangs or fails are negative-cached so Tab never hangs twice. - venv-correct with no hooks — the target always runs on the
pythonfrom your currentPATH; activate a venv and completions reflect it. The engine itself stays pinned to its own interpreter. - bash and zsh — native integration for both; on zsh you also get per-option descriptions pulled from the help text.
- Entry points too — on bash ≥ 4.1 and zsh, any command with a python shebang (e.g.
vllm,lm_eval, anything pip installs into your venv) is detected and completed automatically on first Tab. No registration step. - Choice values —
--mode {fast,slow}and click's[red|green|blue]complete their values, including after--mode=. - Alias-aware filtering — using
-chides--config;-h/--helpis never suggested. - Safe by default — a script is only executed for
--helpif it textually looks like a CLI (imports argparse/click/...); execution is sandboxed with a 3 s timeout, closed stdin, and a process-group kill.
pipx install py-args-autocomplete # or: pip install --user py-args-autocompleteThen add one line to your shell config:
# ~/.bashrc
eval "$(py-args-autocomplete init bash)"
# ~/.zshrc (after compinit / after oh-my-zsh loads)
eval "$(py-args-autocomplete init zsh)"Reload your shell, and Tab away.
Upgrading from v1? Your old
source /path/to/repo/src/python_argparse_complete.shline keeps working — it now delegates to the engine above (install it first).detect_venv_commandsand friends are no-ops: v2 detects venv CLIs automatically. The last pure-bash release is preserved at thev1-legacytag.
| Environment variable | Effect |
|---|---|
PYAC_TIMEOUT |
Seconds allowed for a --help run on first Tab (default 3.0) |
PYAC_EXEC |
auto (default): run --help only on CLI-looking scripts; always; never |
PYAC_EXCLUDE |
Space-separated commands the dynamic dispatcher must leave alone |
PYAC_CACHE |
0 disables the spec cache |
PYAC_CACHE_DIR |
Cache location (default ~/.cache/py-args-autocomplete) |
PYAC_DEBUG |
1 lets engine stderr through to the terminal |
Handy commands (also available as the shorter pyac alias):
py-args-autocomplete doctor # check your setup
py-args-autocomplete spec -- python train.py # show the parsed spec as JSON
py-args-autocomplete cache list # what's cached, with status & age
py-args-autocomplete cache refresh -- python train.py # force re-parse one target
py-args-autocomplete cache clear- Nothing completes: run
py-args-autocomplete doctor. On zsh, the eval line must come aftercompinit(oh-my-zsh runs it for you — put the eval after the framework loads). - A script never completes: check
python script.py --helpactually prints a help text; if your script's parser lives in an imported module, setPYAC_EXEC=always. - Stale suggestions after editing a script: the cache invalidates on mtime change automatically;
cache refreshforces it. - First Tab on a heavy script is slow: that one run is the
--helpcost (bounded byPYAC_TIMEOUT); afterwards it's cached. A timeout is remembered for 10 minutes, so Tab won't re-hang.
python3 -m venv .venv && .venv/bin/pip install -e '.[dev]'
.venv/bin/pytest # parser goldens, completer, protocol, real-shell pexpect tests
.venv/bin/python tests/bench/bench_latency.pyThe parser is developed against a golden corpus (tests/corpus/<case>/help.txt → spec.json). After an intentional parser change, run pytest --update-goldens and review the diffs. The v1 behavioral suites live on in tests/cases/*/tests.txt and run through the new engine.
- Check the project page for open features or suggest your own.
- Fork, branch, add tests (corpus cases make great PRs), and run
pytestbefore submitting.
MIT.
- Email: ohayon.daniel4@gmail.com