Files
skills-public/cli-tooling.md
T
BluscreamandClaude Opus 5 72834167b6 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>
2026-09-18 12:40:55 +02:00

8.4 KiB

name, description
name description
cli-tooling 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, 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.

<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).
  • 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.

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. 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.

# 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:
    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.

  • coding-dev.md — writing the code these tools build and test.
  • code-languages/bash.md — writing the scripts themselves: strict mode, quoting, build-gate structure, destructive-command guards.