feat(cli-tooling): add generic CLI, tooling and script-placement rules
Extracted from the per-agent profile files and the private ai-agents skill, where they were duplicated and environment-coupled: - discovery over guessing: walk the help tree, never invent flags, never hand-roll a script when a dedicated CLI exists - non-interactive invocation: explicit targets, the tool's own --wait - machine-readable output flags (json/compact/csv) vs. never filtering diagnostics - orient before starting: project instructions, git log, prior work records, and verifying TODOs against the code - script placement: dedicated version-controlled dir, symlinked into PATH - destructive/outward-facing command care; environment drift verification coding-dev.md and code-languages/bash.md now cross-reference it instead of carrying their own one-line versions. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
9571eb52d2
commit
72834167b6
4 files changed
+200
-3
No files matched your search
@@ -9,6 +9,7 @@ A collection of public, reusable agent skills, cheatsheets, and operational work
|
||||
| Skill File | Scope / Topics Covered |
|
||||
| :--- | :--- |
|
||||
| **[`coding-dev.md`](./coding-dev.md)** | Standing rules for all code work: maximum linter/compiler strictness, never filtering build output, reuse-before-reinvent dependency ordering, file/function size limits, test & regression discipline, verification gates, scope control, commit hygiene, and honest reporting. |
|
||||
| **[`cli-tooling.md`](./cli-tooling.md)** | Using command-line tools correctly: reading the help tree instead of guessing flags, preferring an existing CLI over an ad-hoc script, non-interactive invocation, machine-readable output formats, orienting on prior work before starting, script placement & symlinking, and care around destructive commands. |
|
||||
|
||||
### 🔤 Per-Language Rules ([`code-languages/`](./code-languages/))
|
||||
|
||||
|
||||
+189
@@ -0,0 +1,189 @@
|
||||
---
|
||||
name: cli-tooling
|
||||
description: >-
|
||||
Use this skill whenever invoking a command-line tool, choosing between a CLI and an ad-hoc
|
||||
script, writing a standalone utility script, or orienting on unfamiliar work before starting.
|
||||
Covers discovering a CLI's real interface instead of guessing flags, non-interactive and
|
||||
machine-readable invocation, script placement and symlinking, and care around destructive
|
||||
or outward-facing commands.
|
||||
---
|
||||
|
||||
# CLI & Tooling — Discovery, Invocation, and Script Placement
|
||||
|
||||
How to use command-line tools correctly, and where utility scripts belong.
|
||||
Companion to [`coding-dev.md`](./coding-dev.md), which covers writing the code itself.
|
||||
|
||||
---
|
||||
|
||||
## 1. Discovery Over Guessing
|
||||
|
||||
> [!IMPORTANT]
|
||||
> **Read the tool's own help before using it. Never guess subcommands or flags.**
|
||||
> ```bash
|
||||
> <tool> --help
|
||||
> <tool> <subcommand> --help
|
||||
> ```
|
||||
|
||||
A tool's built-in help is authoritative and current; memory and training data are neither.
|
||||
Flags get renamed, subcommands get restructured, and a confidently-invented flag either
|
||||
errors out or — far worse — silently means something else.
|
||||
|
||||
**This applies to listing capabilities, too.** When asked what a tool can do, run its help
|
||||
and report what it actually says. Do not produce a speculative command list; a plausible-
|
||||
looking invented flag is indistinguishable from a real one to whoever reads it next.
|
||||
|
||||
### Walk the whole help tree
|
||||
|
||||
Multi-level CLIs hide most of their surface one level down. `<tool> --help` shows the
|
||||
subcommand list; the flags that matter usually live in `<tool> <subcommand> --help`.
|
||||
|
||||
### Don't reinvent a tool that exists
|
||||
|
||||
**When a dedicated CLI already provides the functionality, use it** rather than writing an
|
||||
ad-hoc script, a one-off `curl` pipeline, or a bespoke API client. The CLI already handles
|
||||
authentication, retries, pagination, error formatting, and the edge cases you have not
|
||||
thought of yet.
|
||||
|
||||
Before writing a script to do something, check whether:
|
||||
- a dedicated CLI for that system is already installed,
|
||||
- the tool you are already using has a subcommand for it,
|
||||
- the project's own `scripts/` directory already contains it.
|
||||
|
||||
---
|
||||
|
||||
## 2. Non-Interactive Invocation
|
||||
|
||||
Anything run from a script, a CI job, or an agent must not depend on a human being present.
|
||||
|
||||
- **Pass required targets explicitly.** A CLI that manages multiple objects will, when no
|
||||
target is given, either prompt interactively or fail — both of which break automation.
|
||||
Always pass `--server <id>`, `--profile <name>`, `--target <x>` rather than relying on a
|
||||
default or a prompt.
|
||||
- **Use the tool's own blocking flag** (`--wait`, `--follow`, `--no-detach`) when you need an
|
||||
operation to finish before the next step. Do not build a polling loop around a command that
|
||||
already knows how to wait — and never write a shell `until`/`while` wait loop
|
||||
(see [`code-languages/bash.md`](./code-languages/bash.md)).
|
||||
- **Prefer a `--dry-run` rehearsal** for anything that deploys, releases, or deletes, when the
|
||||
tool offers one.
|
||||
- Set `--yes` / `--non-interactive` deliberately and only where the action is genuinely safe —
|
||||
not as a reflex to stop a tool from asking.
|
||||
|
||||
---
|
||||
|
||||
## 3. Machine-Readable Output
|
||||
|
||||
When output feeds another program — or an agent's context — ask the tool for a structured
|
||||
format rather than parsing its human-facing table.
|
||||
|
||||
```bash
|
||||
tool list -o json # full fidelity
|
||||
tool list -o compact # minimal tokens, good for agent context
|
||||
tool list -o csv # structured columns for a spreadsheet or script
|
||||
```
|
||||
|
||||
- **Never scrape a table meant for humans.** Column widths, truncation, colour codes, and
|
||||
alignment all change without notice; a structured format is a contract.
|
||||
- Strip colour explicitly (`--color never`, `NO_COLOR=1`) when capturing output, or escape
|
||||
sequences end up in your parsed values.
|
||||
- Keep in mind that a "compact" or summary format is the right default for feeding an agent,
|
||||
while `json` is right for a script that needs every field.
|
||||
|
||||
> [!WARNING]
|
||||
> **Never pipe build, lint, or test output through a filter to make it shorter.** That is a
|
||||
> different situation and the rule there is the opposite — see
|
||||
> [`coding-dev.md` §2](./coding-dev.md). Structured output flags are for data; `grep` on
|
||||
> diagnostics hides warnings.
|
||||
|
||||
---
|
||||
|
||||
## 4. Orient Before Starting
|
||||
|
||||
Before beginning work in an unfamiliar project or one you have not touched recently, spend a
|
||||
moment establishing what has already happened. Cheap, and it prevents the most expensive
|
||||
failure mode: rebuilding something that already exists.
|
||||
|
||||
In rough order of value:
|
||||
1. **The project's own instructions** — `AGENTS.md`, `CLAUDE.md`, `.rules`, `CONTRIBUTING.md`,
|
||||
`README.md`. Read them before touching code.
|
||||
2. **Recent history** — `git log --oneline -20`, and `git status --short` to see what is
|
||||
already in flight so you do not clobber it.
|
||||
3. **Prior work records** — session/conversation history tooling, issue trackers, or notes
|
||||
files, scoped to the project directory.
|
||||
4. **The code itself** — `grep` for the symbol before trusting any document that says it is
|
||||
missing.
|
||||
|
||||
> [!CAUTION]
|
||||
> **Task documents are leads, not facts.** A `TODO.md` entry can be stale, duplicated, or
|
||||
> simply wrong — including when it sounds confident and especially when it sounds familiar.
|
||||
> Verify against the code before acting on one. A single `grep` is cheaper than rediscovering
|
||||
> that the work shipped last week.
|
||||
|
||||
---
|
||||
|
||||
## 5. Where Scripts Live
|
||||
|
||||
> [!IMPORTANT]
|
||||
> **Never write a standalone script directly into a `PATH` directory** (`~/.local/bin`,
|
||||
> `/usr/local/bin`, or similar). Write it into a **dedicated scripts directory** that is
|
||||
> version-controlled, then **symlink** it into `PATH`.
|
||||
|
||||
```bash
|
||||
# write the script to its real home
|
||||
$EDITOR /path/to/scripts/my-tool.sh
|
||||
chmod +x /path/to/scripts/my-tool.sh
|
||||
|
||||
# then expose it
|
||||
ln -s /path/to/scripts/my-tool.sh ~/.local/bin/my-tool
|
||||
```
|
||||
|
||||
**Why:** one versioned source of truth. A script living directly in `PATH` is invisible to
|
||||
version control, easy to clobber on a reinstall, impossible to diff, and indistinguishable
|
||||
from a package-manager-owned binary sitting beside it. The symlink makes the provenance
|
||||
obvious — `ls -l` shows exactly where the real file is.
|
||||
|
||||
The same applies within a project: scripts belong in `scripts/`, referenced by the build
|
||||
system, not scattered at the repository root.
|
||||
|
||||
---
|
||||
|
||||
## 6. Destructive and Outward-Facing Commands
|
||||
|
||||
- **Look at the target before deleting or overwriting it.** Inspect it first — the cost of a
|
||||
wrong `rm` or a wrong overwrite is unbounded and the check is one command.
|
||||
- **Read-only first.** When exploring an unfamiliar tool, use its inspection subcommands
|
||||
(`status`, `list`, `show`, `get`) before any mutating one.
|
||||
- **Mutating commands that rewrite shared configuration** — syncing settings across machines,
|
||||
purging caches or state, patching installed applications — should be confirmed before
|
||||
running, even when they are reversible in principle.
|
||||
- **Never use real data as scratch space.** Real accounts, real configuration directories,
|
||||
live services, and the user's actual files are not disposable test fixtures. Use temporary
|
||||
directories and disposable targets.
|
||||
- Anything that sends, publishes, deploys, or purchases is outward-facing: confirm first, and
|
||||
treat approval as applying to that one action rather than the category.
|
||||
|
||||
---
|
||||
|
||||
## 7. Environment Constraints
|
||||
|
||||
- **Entering a container or changing shells resets the working directory.** Chain `cd` inside
|
||||
the same command string rather than relying on it persisting:
|
||||
```bash
|
||||
container-run <name> -- bash -c "cd /path/to/project && make"
|
||||
```
|
||||
- **Verify what actually exists rather than assuming from documentation.** Container names,
|
||||
tool versions, and installed toolchains drift. A one-command check (`<tool> list`,
|
||||
`<tool> --version`, `command -v <tool>`) costs nothing and prevents a confident invocation
|
||||
of something that was removed months ago.
|
||||
- **Check for an optional dependency before the step that needs it**, and fail loudly if it
|
||||
is missing. A packaging step that silently skips when its tool is absent ships an
|
||||
incomplete release.
|
||||
- **Don't saturate the machine.** A full build consuming every core makes the workstation
|
||||
unusable. When something latency-sensitive is running, reduce the job count and `nice` the
|
||||
work — and say that you did.
|
||||
|
||||
---
|
||||
|
||||
## 8. Related Skills
|
||||
- [`coding-dev.md`](./coding-dev.md) — writing the code these tools build and test.
|
||||
- [`code-languages/bash.md`](./code-languages/bash.md) — writing the scripts themselves:
|
||||
strict mode, quoting, build-gate structure, destructive-command guards.
|
||||
@@ -161,12 +161,15 @@ mistakes before a human does.
|
||||
|
||||
## 9. Script Placement
|
||||
|
||||
Standalone utility scripts belong in a **dedicated scripts directory**, symlinked into `PATH`
|
||||
rather than copied there. Never write a loose script directly into `~/.local/bin` or another
|
||||
`PATH` directory — the source of truth should be one versioned location.
|
||||
Standalone utility scripts belong in a **dedicated, version-controlled scripts directory**,
|
||||
symlinked into `PATH` rather than copied there. Never write a loose script directly into
|
||||
`~/.local/bin` or another `PATH` directory — the source of truth should be one versioned
|
||||
location. See [`../cli-tooling.md` §5](../cli-tooling.md) for the reasoning and the pattern.
|
||||
|
||||
---
|
||||
|
||||
## 10. Related
|
||||
- [`../coding-dev.md`](../coding-dev.md) — the general rules this extends.
|
||||
- [`../cli-tooling.md`](../cli-tooling.md) — invoking other tools *from* these scripts:
|
||||
discovery, non-interactive flags, structured output.
|
||||
- [`python.md`](./python.md) — where a shell script should have become a Python script.
|
||||
@@ -294,8 +294,12 @@ Run the **whole** gate, not the convenient part of it. A typical full gate:
|
||||
|
||||
## 13. Environment & Tooling
|
||||
|
||||
Full version in [`cli-tooling.md`](./cli-tooling.md); the essentials:
|
||||
|
||||
- **Read `<tool> --help` before using a CLI.** Do not guess flags, and do not write an ad-hoc
|
||||
script when an existing tool already does the job.
|
||||
- **Standalone scripts live in a dedicated, version-controlled scripts directory**, symlinked
|
||||
into `PATH` — never written directly into `~/.local/bin` or another `PATH` directory.
|
||||
- **Build inside the project's designated environment** (container, venv, toolchain manager)
|
||||
rather than the host, when the project specifies one. Note that entering a container
|
||||
typically resets the working directory — chain `cd` inside the same command string.
|
||||
|
||||
Reference in new issue
Block a user