52 lines
2.9 KiB
Markdown
52 lines
2.9 KiB
Markdown
# skill-cli template
|
|
|
|
Scaffold for a **Claude Code skill whose CLI is Python + [click]** instead of a
|
|
bash script — a `SKILL.md`, a thin `.sh` shim that keeps the alias installer
|
|
working, a single-file [PEP 723] uv script holding all the logic, and click
|
|
`CliRunner` tests.
|
|
|
|
Scaffolded with the `new-skill` skill:
|
|
|
|
```bash
|
|
new-skill <name> --description "…" # -> .claude/skills/<name>/
|
|
```
|
|
|
|
This README and `.scaffold-notes.md` document the template itself and are **not**
|
|
copied into the scaffolded skill.
|
|
|
|
## Why Python for a skill CLI
|
|
|
|
From the survey in `data/log/2026-08-10-bash-skills-python-click-ranking.md`:
|
|
bash skills that build or parse JSON, embed `python3` heredocs, take many flags,
|
|
or do HTTP with retries are the ones worth writing in Python. Thin orchestration
|
|
of other CLIs (git, ssh, docker) stays in bash. This template is for the first
|
|
kind.
|
|
|
|
What it encodes, one lesson per file:
|
|
|
|
| file | the lesson |
|
|
|--------------------------|----------------------------------------------------------------------------|
|
|
| `scripts/<name>.sh` | the shim must stay — `install-skill-aliases.sh` only scans `*.sh` for `# @alias:`. |
|
|
| `scripts/<pkg>.py` | uv-script shebang + `# /// script` deps, so `click` needs no venv management. |
|
|
| ↳ `Step` param type | ONE repeatable typed option, not `--wait/--click/--shot` — click collects each option's occurrences separately, so splitting them loses interleaved order. |
|
|
| ↳ `post_json` | dict → `requests(json=…)`: no shell quoting, no `jq`, and no `E2BIG` when a payload carries base64. |
|
|
| ↳ `load_env_claude` | private defaults come from the gitignored `.env.claude`, walked up from the script. |
|
|
| ↳ `err` / `die` / `emit` | stdout = result (`--json` for machines), stderr = chatter, `1` handled failure / `2` usage. |
|
|
| `scripts/test_<pkg>.py` | `CliRunner` gives a skill real tests for the price of one file. |
|
|
|
|
## Placeholders
|
|
|
|
| key | meaning | default |
|
|
|----------------|--------------------------------------------|--------------------|
|
|
| `@@NAME@@` | kebab-case skill name = alias on `PATH` | required |
|
|
| `@@PKG@@` | snake_case module name | `NAME` with `-`→`_` |
|
|
| `@@TITLE@@` | human title in `SKILL.md` | `NAME` |
|
|
| `@@DESCRIPTION@@` | the frontmatter `description:` — this is what makes the skill discoverable, so write it as "what it does + when to use it" | required |
|
|
| `@@ENVPREFIX@@`| env-var prefix, e.g. `@@ENVPREFIX@@_URL` | `NAME` upper, `-`→`_` |
|
|
|
|
Add a placeholder by dropping `@@KEY@@` into a template file and a matching key
|
|
into the vars JSON.
|
|
|
|
[click]: https://click.palletsprojects.com/
|
|
[PEP 723]: https://peps.python.org/pep-0723/
|