Bootstrap a single-file CLI.
The 100-line utility you keep meaning to write. Proper argparse, real error handling, ships as one file you can pip install.
You have a repetitive task — a log parser, a batch renamer, a report generator. You've been meaning to write the tool for weeks. This prompt gets you a working, well-structured one-file CLI in the language you specify, with proper argument parsing and error handling, ready to actually use.
THE PROMPT
Write me a single-file CLI in [LANGUAGE] that does the following: [DESCRIBE THE TASK IN 2-3 SENTENCES] Requirements: - Single file, no external config - Standard-library-only arg parsing (argparse for Python, clap-derive-free for Rust, flag for Go — pick the idiomatic minimal option) - Meaningful `--help` output that documents every flag with an example - Non-zero exit code on failure with a message on stderr, not stdout - A `--version` flag that reads from a single `VERSION` constant at the top of the file - One block of tests at the bottom of the file if the language supports it inline (Python `unittest`, Rust `#[cfg(test)]`, Go `_test.go` acceptable as a note); otherwise a comment showing how to add them Structure the response as: 1. The full file, in one code block, ready to save and run. 2. A three-line "How to run" block below it. 3. Any dependencies I need to install, if the file isn't truly stdlib-only. Do not add commentary before or after. If a design choice was non-obvious, put a short comment inline in the code where you made it — not in the prose around it.
```python
#!/usr/bin/env python3
"""renamer.py — batch-rename files matching a glob using a template."""
import argparse
import sys
from pathlib import Path
VERSION = "0.1.0"
def rename(pattern: str, template: str, dry_run: bool) -> int:
matches = sorted(Path().glob(pattern))
if not matches:
print(f"no files matched {pattern!r}", file=sys.stderr)
return 2
for i, src in enumerate(matches):
# template supports {i} for zero-padded index, {stem}, {ext}
dst = src.parent / template.format(i=i, stem=src.stem, ext=src.suffix)
if dst == src:
continue
if dry_run:
print(f"[dry] {src} -> {dst}")
else:
src.rename(dst)
print(f"{src} -> {dst}")
return 0
def main() -> int:
p = argparse.ArgumentParser(description="Batch rename files.")
p.add_argument("pattern", help="glob pattern, e.g. '*.jpg'")
p.add_argument("template", help="destination template, e.g. 'photo_{i:03d}{ext}'")
p.add_argument("--dry-run", action="store_true", help="preview without renaming")
p.add_argument("--version", action="version", version=f"renamer.py {VERSION}")
args = p.parse_args()
return rename(args.pattern, args.template, args.dry_run)
if __name__ == "__main__":
sys.exit(main())
```
**How to run**
- Save as `renamer.py`, `chmod +x renamer.py`
- `./renamer.py '*.jpg' 'photo_{i:03d}{ext}' --dry-run`
- Remove `--dry-run` when you're satisfied.
**Dependencies**
None. Python 3.9+.