--- 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`](skills-public/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 > --help > --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. ` --help` shows the subcommand list; the flags that matter usually live in ` --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 `, `--profile `, `--target ` 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`](skills-public/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](skills-public/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 -- 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 (` list`, ` --version`, `command -v `) 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`](skills-public/coding-dev.md) — writing the code these tools build and test. - [`code-languages/bash.md`](skills-public/code-languages/bash.md) — writing the scripts themselves: strict mode, quoting, build-gate structure, destructive-command guards.