Files
template-skill-cli/README.md

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/