Five skills covering this repo's own conventions: adding a bootstrap module, adding a CLI to bin/, bumping a pinned version, adding an MCP server, and verifying a module change. Lives in .agents/skills/ because opencode discovers that path natively alongside .opencode/skills/ and .claude/skills/, making it the most tool-neutral of the three. Distinct from the repo's skills/ tree, which ships to every covert-gpt user via sync.sh; these stay in the checkout. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
72 lines
3.3 KiB
Markdown
72 lines
3.3 KiB
Markdown
---
|
|
name: add-bootstrap-module
|
|
description: Use when adding a new top-level module to this dotfiles repo (a new directory with an install.sh that bootstrap.sh runs) — e.g. installing a new runtime, configuring a new service, or dropping a new managed rc file. Covers the module contract, ordering in bootstrap.sh, and the README entry.
|
|
---
|
|
|
|
# Adding a bootstrap module
|
|
|
|
A module is a top-level directory with an `install.sh` that bootstrap runs. It
|
|
must be safe to run standalone *and* to re-run on an already-configured box.
|
|
|
|
## The contract
|
|
|
|
Every module's `install.sh` satisfies all of these. Copy the shape from
|
|
`node/install.sh` — it is the newest and cleanest example.
|
|
|
|
1. **POSIX `sh`, not bash.** `#!/usr/bin/env sh` + `set -eu`. No `[[`, no
|
|
arrays, no `local`. These boxes are RHEL- *and* Debian-family; don't assume
|
|
bash is the `/bin/sh`.
|
|
2. **A `WHY:` header comment.** Not what the script does — the code says that.
|
|
Explain the failure it prevents or the constraint that forced the design.
|
|
`node/install.sh` is the model: it explains that a missing `npx` surfaces
|
|
only as a dead MCP server, which is easy to misdiagnose.
|
|
3. **Locate the repo without depending on `$PWD`:**
|
|
```sh
|
|
SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
|
|
REPO_ROOT="$(dirname -- "$SCRIPT_DIR")"
|
|
```
|
|
4. **Reuse `lib/`.** `lib/os-detect.sh` for `pkg_install` (handles dnf/yum vs
|
|
apt); `lib/fetch.sh` for `fetch_arch`, `have_version`/`mark_version`, and
|
|
the `install_*_bin` helpers. Source with a shellcheck directive:
|
|
```sh
|
|
# shellcheck source=../lib/fetch.sh
|
|
. "$REPO_ROOT/lib/fetch.sh"
|
|
```
|
|
5. **Idempotent, and it verifies rather than assumes.** Check the tool *runs*,
|
|
not just that the file exists — a Kasm redeploy can leave a present-but-
|
|
broken tree behind. `node/` and `ansible/` both guard this way.
|
|
6. **Log to stderr** via a `say()` helper, so stdout stays usable.
|
|
7. **Prefer `$HOME`.** Everything under `~/.local` survives a Kasm redeploy
|
|
(which wipes `/` but keeps `$HOME`) and needs no sudo. If the module *must*
|
|
use sudo, say so in its header comment and in the README — the repo tracks
|
|
which modules do.
|
|
|
|
## Wiring it up
|
|
|
|
**`bootstrap.sh`** — add the call. Order is load-bearing and each existing
|
|
out-of-order entry carries a comment explaining why (`docker/` before `bin/`
|
|
so kind's gate sees the daemon; `docker-rootless-cgroup/` last because it
|
|
needs the rootless daemon already up). If your module has an ordering
|
|
constraint, add it *with* a comment; if it doesn't, append it near related
|
|
modules.
|
|
|
|
**`README.md`** — add a bullet to the `## Modules` list. Match the existing
|
|
voice: what it installs, where it puts it, whether it uses sudo, and any
|
|
host it no-ops on.
|
|
|
|
**`~/.zshrc.local`** — if the module reads a secret or per-machine value, add
|
|
the variable to `zsh/zshrc.local.example` and to the README's variable list.
|
|
Never commit the value itself.
|
|
|
|
## Non-systemd hosts
|
|
|
|
Kasm has no systemd. Anything that would `systemctl enable` must degrade
|
|
gracefully — see `docker/install.sh`, which detects the situation and no-ops
|
|
rather than failing the whole bootstrap run.
|
|
|
|
## Before you're done
|
|
|
|
Run the `verify-module` skill. At minimum: `shellcheck`, run standalone, then
|
|
run a second time and confirm the output says "already present" rather than
|
|
redoing the work.
|