---
name: ai-era-terminal-tools
description: >
  Use when an AI agent is operating a Linux, WSL, macOS, or Windows terminal and needs bounded filesystem search, text search, web-content extraction, structured-data processing, HTTP testing, GitHub operations, Python project management, diagnostics, benchmarking, or context-efficient command output.
compatibility: >
  Requires terminal access. Tool availability varies by OS; verify the executable and version before use. Network, authentication, or elevated privileges may be required for some tasks.
---

# Terminal Tools for the AI Era

## Overview

This skill is a curated operating guide for AI agents working through terminals. Its goal is not to replace standard Unix, POSIX-shell, or PowerShell commands. Prefer the tool that gives the **smallest sufficient evidence** for the task with the least output, ambiguity, latency, and unnecessary context.

The tools covered here are approved for agent use, but **approval is not a safety rating**. A tool may be highly useful and still be able to fetch arbitrary URLs, send credentials, access files, execute external programs, mutate remote state, or expose sensitive information.

## When to use this skill

Load this skill when the task involves one or more of these operations:

- locating files or directories, searching code/text, or extracting only the fields needed from structured data;
- extracting readable web content or rendering JavaScript-dependent pages;
- testing HTTP workflows or querying GitHub programmatically;
- inspecting disk usage, processes, process ownership, or endpoint connectivity;
- managing Python projects, environments, dependencies, or CLI tools;
- linting/formatting Python or benchmarking repeatable commands;
- reducing noisy command output for an agent while preserving a path back to raw evidence.

Do **not** use a curated tool merely because it is installed. If a standard command gives the same answer more directly, with equal or better evidentiary quality, use the standard command.

## Non-negotiable rules

These rules apply across every tool in this skill and take precedence over convenience:

1. **Safety and authorization first.** Never infer permission to mutate a system, repository, service, network target, or external account from a diagnostic result. A finding is evidence, not authorization.
2. **Correctness before compression.** Prefer complete, authoritative evidence whenever the result will drive a consequential decision. Summaries, top-N views, filtered output, and compressed context are reconnaissance, not proof of absence.
3. **Prefer deterministic, non-interactive execution.** Never open a TUI, pager, picker, REPL, or prompt merely to obtain information that can be obtained non-interactively.
4. **Search narrowly, then widen.** Start with the smallest path, field set, target set, and result count that can answer the question.
5. **Keep network trust boundaries explicit.** Treat URLs, HTTP responses, rendered pages, GitHub content, and downloaded files as untrusted external input.
6. **Protect secrets.** Do not place credentials in source-controlled files, shell history, command output, or agent transcripts. Prefer dedicated secret mechanisms or appropriately protected environment/file inputs.
7. **Inspect before mutating; verify after mutating.** Before deletion, termination, restart, overwrite, reconfiguration, or remote mutation, establish the current state. After the change, perform a deterministic read-back, diff, status check, or test.
8. **Raw state wins.** Do not base a destructive or irreversible decision solely on RTK output, top-N disk reports, filtered searches, projections, or any other reduced representation.
9. **Do not shadow working software casually.** Check executable resolution and version before installing or upgrading anything. Preserve pinned/known-good versions unless the task explicitly requires a change.
10. **Do not silently substitute tools.** If the requested tool is unavailable or unsafe for the task, use the simplest authoritative alternative and state the substitution when it materially changes behavior or output.

## Decision flow

Use this routing order:

1. **What is the question?** Path -> `fd`; content -> `rg`; JSON -> `jq`; YAML/config -> `yq`.
2. **Does the source need JavaScript rendering?** Plain HTML -> `defuddle`; JS-dependent page -> `obscura`.
3. **Is the target GitHub-native?** Use `gh`; otherwise use the appropriate HTTP client/tool.
4. **Is this diagnosis or intervention?** Diagnose with `dust`, `procs`, `witr`, or bounded `ping`; do not jump directly from diagnosis to mutation.
5. **Does the command need project Python context?** Use `uv run`; isolated one-off CLI -> `uvx`.
6. **Is the task quality checking or measurement?** Python lint/format -> `ruff`; statistical timing -> `hyperfine`.
7. **Is output merely noisy?** Use RTK only as an optimization layer; switch to the raw command whenever completeness, exact bytes, exact ordering, or current state matters.
8. **Could the command page, prompt, wait forever, or require a TTY?** Use a documented non-interactive mode or reject the invocation.

## Evidence tiers

Treat outputs according to what they can prove:

| Tier | Evidence | Use |
|---|---|---|
| A | Raw authoritative state / direct filesystem or service query | Final basis for destructive or irreversible decisions |
| B | Structured, complete machine-readable result from the relevant tool | Normal automation and analysis |
| C | Bounded/filtering/summarized output | Reconnaissance and narrowing; follow up before consequential action |
| D | Human-oriented TUI, visual dashboard, or unverified third-party claim | Context only; never the sole machine decision basis |

## Tool policy

Every tool in this skill is `agent: yes`: it has a documented non-interactive path suitable for the supported use cases. Some other terminal tools remain intentionally outside this curated set because they are primarily human-oriented, produce no better agent-facing answer, or lose to an already-approved equivalent for the measured operation.

The sections below define **when to use**, **where to use it**, **how to use it**, **what the output means**, and **when not to use it**. Tool-specific rules do not weaken the global safety rules above.

## Tool-specific precedence

The global rules are the floor, not a suggestion. A tool section may be stricter than the global rules, but never looser.

When instructions conflict, apply them in this order:

1. **Safety / authorization**
2. **Authoritative correctness / completeness**
3. **Non-interactive execution**
4. **Minimal scope and bounded output**
5. **Performance / token efficiency**
6. **Convenience**

A command that is faster but less authoritative is not an optimization; it is a correctness regression.

## Common agent mistakes

These are the failure modes this skill is specifically designed to prevent:

| Mistake | Correct response |
|---|---|
| Using a path-search tool to answer a content question | Use `fd` for paths and `rg` for contents. |
| Searching an entire repository by default | Start with the smallest relevant subtree and widen deliberately. |
| Using a TUI/pager/picker in an unattended run | Reject it unless a documented non-interactive mode exists. |
| Treating filtered, truncated, compressed, or top-N output as complete | Re-run the authoritative underlying query before consequential action. |
| Trusting a command name without checking what binary resolves | Use `command -v` / `type -a` or `where.exe`, then `--version`. |
| Copying a flag from memory or another tool | Verify the installed tool's `--help` and current upstream documentation first. |
| Passing secrets through command lines or output | Use the tool's secret/environment mechanisms and keep transcripts clean. |
| Disabling SSRF/private-network protections because a page is blocked | Establish authorization for the private target first; otherwise keep the protection. |
| Jumping from diagnosis straight to `kill`, `rm`, restart, or remote mutation | Complete the destructive-action checklist and use raw authoritative state. |
| Using RTK output as ground truth | Use RTK for reconnaissance only; fall back to the underlying command for exact state. |
| Benchmarking a command that is not safe to repeat | Isolate it or do not benchmark it with `hyperfine`. |

Never invent a flag, subcommand, package name, or safety exception. If the exact invocation cannot be verified, stop and use an authoritative alternative.

## 1. Operating Contract

### 1.1 Core principles

1. **Correctness beats convenience.** Never choose a shorter or prettier command when it hides information needed to make a correct decision.
2. **Search narrowly, then widen.** Start with the smallest path, file type, field set, host set or result count that can answer the question.
3. **Machine-readable beats human-formatted output.** Prefer JSON, raw values, explicit fields, counts, filenames or bounded lists.
4. **Never use a TUI when a non-interactive equivalent exists.** No picker, dashboard, pager or REPL merely to obtain what a deterministic command can provide.
5. **A summary is not evidence of absence.** Filtered, truncated, compressed, top-N or summarized output can omit data. Reconnaissance, not proof.
6. **Inspect before mutating.** Before deleting, killing, restarting, overwriting, reconfiguring or otherwise acting irreversibly, establish current state with an authoritative, sufficiently complete command.
7. **Raw output is the final authority for destructive decisions.** Never authorize deletion, termination, restart or replacement from `rtk`, a top-N disk report, a filtered search, a single selected JSON field, or any other reduced representation.
8. **Verify meaningful changes.** After a mutation, use a deterministic read-back, diff, status, test or other authoritative check.
9. **Do not install or upgrade tools unnecessarily.** Check what is available first; do not shadow a pinned or known-good version with a newer copy merely because it is convenient.
10. **Do not silently substitute tools.** State any substitution in the result.
11. **Do not expose secrets in command lines or output.** Use environment variables, dedicated secret mechanisms, or files with appropriate permissions; never print credentials just to inspect them.
12. **Do not treat a diagnostic result as permission to act.** Discovery and intervention are separate decisions.

### 1.2 Shell and platform note

Examples primarily use POSIX-style shell syntax. On native PowerShell, do not copy `eval "$(... init bash)"` snippets literally; use the tool's PowerShell/native-shell integration or an equivalent PowerShell command. Adapt pipelines, quoting, environment variables and command-resolution checks to the active shell. WSL or Git Bash can use the POSIX examples when those environments are actually running the commands.

## 2. Fast Tool Selection

Use the first matching tool; combine tools only when each has a distinct purpose.

| Need | Primary tool | Safe agent mode |
|---|---|---|
| Find files/directories by name/path characteristics | `fd` | Normal CLI |
| Search file contents/code | `rg` | Normal CLI; bound scope |
| Extract readable article content from existing HTML | `defuddle` | `defuddle parse ...` |
| Render JavaScript-dependent pages | `obscura` | `fetch` / `scrape`; keep private-network blocking enabled |
| Query/filter JSON | `jq` | Normal CLI; slice output |
| Query/edit YAML and other structured config | `yq` | Normal CLI; `-i` for deliberate structural edits |
| Test/replay HTTP workflows | `hurl` | `hurl --test ...` or explicit request execution |
| Work with GitHub repositories/issues/PRs/releases/actions | `gh` | Explicit subcommand + structured fields where applicable |
| Find large directories/files | `dust` | `dust -j -d 1 -n 20 <path>` for JSON, or bounded human output |
| Inspect processes/resources | `procs` | Normal CLI; `--tree` for ancestry |
| Explain why a process/port/container exists | `witr` | Normal CLI; machine-readable output when supported |
| Measure endpoint latency/loss | bounded `ping -c` (fallback) | `ping -c 5 -q <host>`; always bounded |
| Manage Python environments/projects/tools | `uv` | `uv run`, `uvx`, `uv add`, `uv sync` |
| Lint/format Python | `ruff` | `ruff check`, `ruff format`; respect project config |
| Benchmark commands statistically | `hyperfine` | Non-interactive commands; warm up and export results |
| Reach a known directory | `cd` / absolute path | no agent-approved navigation tool; ranking is non-authoritative |
| Reduce noisy supported command output | `rtk` | Use normal commands when transparent integration is enabled |

## 3. File and Text Discovery

### 3.1 `fd`: filesystem/path discovery

#### Use when

The question is **where something is**: locating files or directories by name/pattern, filtering by extension, type, depth, age, owner or size, or finding a bounded set of candidate paths before reading them.

#### Agent rules

- Starters: `fd notes` - `fd -e py src/` - `fd --type d --max-depth 3 src/` - `fd --type f --changed-within 7d .`
- `fd` is for **paths**; `rg` is for **content**. Scope the starting directory explicitly when possible.
- Bound broad searches with `--type`, `--extension`, `--max-depth`, `--changed-within`, or another meaningful filter.
- `fd` respects common ignore rules and does not behave like a raw `find` over every hidden/ignored path by default; widen deliberately when those files are part of the question.

#### Do not

- Run a bare `fd` from `/` or a large home directory when a bounded search suffices.
- Treat a missing result as proof a file does not exist if the target may be hidden, ignored, inaccessible or outside the searched root.
- Use `rg --files` as the default path-search mechanism when `fd` expresses the question directly.

### 3.2 `ripgrep` (`rg`): content/code search

#### Use when

The question is **what text or code exists, where, or how often**: `rg 'TODO' src/` - `rg -g '*.ts' 'token' src/` - `rg -l 'os\.environ' .` - `rg -c 'TODO' .`

#### Agent rules

- Search the narrowest relevant subtree first; widen only when that gives insufficient evidence.
- `-g`/`-t` constrain file types; `-l` gives filenames only; `-c` gives counts only.
- `rg` normally skips binary files and obeys ignore rules. Inspect the actual search scope before claiming something is absent.

#### Do not

- Dump an entire repository into context for a question answerable with filenames, counts or a narrower match.
- Search generated or dependency-heavy trees such as `.git`, `node_modules`, `target`, `dist`, `.venv` or `__pycache__` unless those locations are part of the question.
- Assume no textual match means an object does not exist inside a binary, image, PDF, database or other non-text representation.

## 4. Web Content Acquisition and Extraction

### 4.1 `defuddle`: article extraction from existing HTML

#### Use when

Turning a web page into readable Markdown: the article, not navigation, comments, ads, cookie banners, footers or script noise. The source can be a URL, a file or stdin: `defuddle parse https://example.com/article --md` (URL) - `defuddle parse -m page.html` (file) - `curl -L URL | defuddle parse -m` (piped) - `defuddle parse -p title page.html` (one metadata field).

#### Agent rules

- `defuddle` fetches URLs itself. You do **not** need `curl` first. What it is not is a **browser**: it extracts the HTML the server returns, so content that appears only after JavaScript execution comes back as an empty shell.
- Pass the URL straight to `defuddle parse` rather than fetching separately; do not pipe `curl` into it by default. Use `--md`/`-m` when Markdown is the useful representation, frontmatter when the page description is needed, and `-p` when one field is required.
- No private-network guard: only hand it URLs you chose.
- If the initial HTML is only a shell (`Loading`, empty root node, client-side app), switch to `obscura` instead of trying more extraction flags.

#### Do not

- Use it as the primary solution for pages whose meaningful content appears only after JavaScript execution.
- Assume extraction is semantically perfect. Readability extraction is heuristic; verify important facts against the source page.

### 4.2 `obscura`: lightweight JavaScript-capable headless browser

#### Use when

A target page needs a real JavaScript-capable browser to render meaningful content that a plain HTTP fetch cannot obtain. `obscura fetch --dump markdown https://example.com` - `obscura fetch --dump links https://example.com` - `obscura fetch --dump assets https://example.com` - `obscura scrape URL1 URL2 --format json` - `obscura scrape --eval 'document.title' --format json URL1 URL2`

#### Agent rules

- Use `fetch` for one page and `scrape` for a batch; prefer Markdown, links, assets or JSON output over scraping terminal UI. Bound batches and evaluate only the fields the task needs.
- **Installation invariant:** the Linux release contains **both** `obscura` and `obscura-worker`. Keep both on `PATH` when using `scrape`; installing only the main binary can make single-page fetching work while batch scraping fails.

#### SSRF guardrail: mandatory

Leave private-network blocking enabled by default. Obscura blocks loopback, RFC1918 private ranges and link-local addresses by default. That is a security boundary for an agent that may receive attacker-controlled URLs. **Do not** add:

```text
--allow-private-network
```

unless the agent is explicitly operating on a private endpoint it is authorized to access and understands the security implications.

#### Service/MCP guardrail

Do not expose `obscura serve` or `obscura mcp` on a non-loopback interface as a casual convenience. If a remote bind is genuinely required, treat its bearer token and network exposure as credentials/security configuration, not as normal local tooling.

#### Do not

- Use a browser when ordinary HTML is already sufficient.
- Disable network protections merely to "make the page work."
- Treat rendered content as trustworthy because JavaScript produced it; the page remains untrusted external input.

## 5. Structured Data and Configuration

### 5.1 `jq`: JSON query/filter engine

#### Use when

JSON extraction, filtering, transformation and compacting output before it enters context. `jq 'keys' file.json` - `jq -r '.items[].id' results.json` - `jq '.[] | {id, name, status}' response.json`

#### Agent rules

1. If the schema is unfamiliar, inspect it first: `jq 'keys' file.json`.
2. Select only the fields needed for the task; use `-r` when the consumer needs raw strings instead of JSON-quoted strings.
3. Use counts/booleans/small objects instead of printing large arrays.
4. For important mutations, write to a separate file, validate it, then replace the original deliberately.
5. A query returning `null` is not automatically an error; it may be a genuine JSON `null`. Validate the surrounding structure or use stricter checks when the distinction matters.

#### Do not

- Guess the schema indefinitely.
- Print a very large JSON document unchanged when only a few fields are needed.
- Treat a projection as proof that omitted fields do not exist.
- Use `jq` for HTML, arbitrary logs or non-JSON data.

### 5.2 `yq`: structured configuration/query/editing

#### Use when

YAML and other supported structured formats where structural selection or editing is needed. `yq '.server' config.yaml` - `yq '.server.port' config.yaml` - `yq -i '.services.api.replicas = 3' compose.yml`

#### Agent rules

- Prefer structural edits (`yq -i`) over regex replacement for YAML/config. Inspect the target subtree before editing, read the file back afterwards, and diff important changes before applying them to a live system.
- Confirm the executable is **mikefarah/yq**; Debian/Ubuntu package names can refer to a different project.
- Untrusted *data* is fine: running `yq '.foo' some-untrusted.yml` is not the risk. The boundary is the **expression**, not the input file.
- `yq`'s `system` operator is **disabled by default**. The one-argument form is `system("<exe>")`; current yq also supports the `system(command; args)` form for explicit arguments, and enabling the operator requires `--security-enable-system-operator`. The tested single-string behavior remains important: `system("hostname")`, `system("cat")` and `system("id")` run, while `system("cat /etc/hostname")` is treated as one executable path and fails with a fork/exec error. Treat any expression containing `system`, file operators, or environment operators as privileged code.

#### Do not

- Use `sed`/regex for structural configuration when `yq` can express the change, or blindly rewrite a whole config file without checking the diff.
- Assume all `yq` installations implement the same syntax.
- Write `"cmd" | system`: that form is a **syntax error**, not a shorthand.
- Execute an expression you did not write that contains the `system` operator (it runs a program) or file/env operators, regardless of where the input YAML came from. `--security-disable-env-ops` and `--security-disable-file-ops` turn off those built-ins; do not reach for them to make a borrowed expression run.

## 6. HTTP Workflows and GitHub

### 6.1 `hurl`: declarative HTTP request runner/tester

#### Use when

Repeatable HTTP request scenarios, assertions, captures and regression tests.

```hurl
GET https://example.com/api/item
HTTP 200
[Asserts]
jsonpath "$.status" == "ok"
```

Run with `hurl --test test.hurl`.

#### Agent rules

- Store repeatable workflows as `.hurl` files rather than reconstructing ad-hoc `curl` commands.
- Assert the semantics that matter, not just transport-level success, and capture values for multi-step workflows to pass to later requests.
- Use `--test` for CI/test-style execution where a concise result matters. Hurl test mode runs files in parallel by default; when order or shared test state matters, use an explicit `--jobs 1`.
- Use Hurl's secret mechanisms (`--secret`, secret files, or supported environment variables) instead of embedding credentials in request files or arguments.

#### Do not

- Treat HTTP 200 alone as proof of business success.
- Use Hurl as a load/stress generator, or send requests to systems you do not have authorization to test.
- Put live credentials directly into source-controlled `.hurl` files.

### 6.2 `gh`: GitHub CLI

#### Use when

GitHub-native operations: repositories, issues, pull requests, releases, GitHub Actions, authenticated GitHub API queries. `gh repo view OWNER/REPO --json name,description,stargazerCount,url` - `gh pr list --json number,title,state`

#### Agent rules

- Prefer explicit `--json` fields when the subcommand supports them, and request only the fields actually needed. A human-formatted `gh` table is not a stable machine interface.
- Use `GH_TOKEN` or another supported environment mechanism rather than placing tokens directly in commands, and treat live fields such as star counts as time-varying measurements.
- For unattended flows, ensure authentication is already established and disable interactive prompting with `GH_PROMPT_DISABLED=1` when appropriate; a missing auth path must not turn into a hidden prompt.
- Use `gh` for GitHub-shaped work; use Hurl or another HTTP client for other hosts.
- Telemetry ships **on by default**: it records which subcommand and flags you ran plus a persisted `device_id`, never your token or output. Disable with `GH_TELEMETRY=false`, `DO_NOT_TRACK=1`, or `gh config set telemetry disabled`; inspect the payload with `GH_TELEMETRY=log` rather than guessing.

#### Do not

- Commit or print tokens, or put secrets directly in shell history or agent transcripts.
- Use `gh` as a general HTTP client.

## 7. System Inspection and Diagnosis

### 7.1 `dust`: bounded disk-usage discovery

#### Use when

- You need to know where disk space is being consumed.
- You need a quick first-pass ranking before a deeper inspection.

#### Agent rules

- Required mode: `-j` emits a JSON tree: `dust -j -d 1 -n 20 /var | jq -r '.children[] | "\(.size)\t\(.name)"'`. Human-readable bounded survey: `dust -d 1 -n 20 /var` - `dust -d 2 -n 30 /myservices` - `dust -D -d 1 -n 20 /`.
- `-d` bounds depth; `-n` bounds the number of reported entries. Threading is `-T`/`--threads`, **not** `-j`: in `dust`, `-j` is `--output-json`.
- Approved as a **near competitor**, not for speed: 4-vCPU WSL2 `dust` 1.32 s against `du`+`sort`+`tail` 3.24 s, but `-T1` 3.76 s, **slower** than `du`, and on 8-vCPU native `du` was faster by 2.3x. The win is parallelism, and its size is a property of the machine: `-T1` 3756 ms, `-T2` 2219 ms, `-T4` 1306 ms, `-T8` 878 ms, `-T16` 768 ms, CPU roughly flat at ~700-770 ms at any thread count against `du`'s ~470-480 ms. It is kept for the two things `du` cannot do: a bounded ranked answer straight from `-n` instead of a `| sort | tail` bolted on, and a native JSON tree from `-j`.
- Size semantics: the two ways this is not `du`:
  - Reports **allocated** size, the same thing `du` reports by default, not `du --apparent-size`. On a real `/usr` tree: `du --apparent-size` 5,956,757 KiB, `du` default 6,193,888 KiB, `dust` 5.9Gi. A `--apparent-size` comparison is not like-for-like.
  - **Includes hidden files by default**, and `-i`/`--ignore-hidden` *excludes* them - the flag name reads like "include" and means "ignore". On a controlled fixture (10 MB hidden plus 2 MB visible, 12,000,000 bytes by Python's count) `dust` reported 11Mi by default and 1.9Mi with `-i`.
- Always bound broad scans with depth and/or result count, starting in the smallest relevant directory rather than `/`; traversal itself can be expensive on large trees.
- Treat output as reconnaissance and follow up with raw filesystem state before deciding what to delete.

#### Do not

- Run an unbounded `dust /` just to "see everything."
- Delete based only on a top-N result.
- Assume the largest directory is safe to remove.

### 7.2 `procs`: process inspection

#### Use when

A readable process table, process hierarchy, or resource/metadata overview. `procs --tree` - `procs python`

#### Agent rules

- Use `--tree` first when investigating an unexpected process hierarchy; filter by name only when the question is specifically about a process class.
- `procs --json` is real but absent from its man page and README. Invalid JSON when a column is skipped by `--only`/`--tree` affects the current release, so verify the output parses before relying on it with those two flags.
- Environment exposure: the `Env` column prints a foreign process's full environment.
- Escalate to authoritative system interfaces when necessary: `/proc`, `ps` with explicit columns, `ss`, `systemctl`, `docker inspect`, container-runtime commands, etc.
- Treat a PID/name as a clue, not as authorization to terminate it.

#### Do not

- Kill a process merely because it appears in the list.
- Infer service ownership solely from a process name such as `python3`, `node` or `java`.
- Replace authoritative service/container state with a summarized process view.

### 7.3 `witr`: causality/ownership diagnosis

#### Use when

The question is **why this is running, and what started or supervises it?** It traces processes and related targets such as ports/containers back through their causal chain, with human-readable or machine-readable output.

```text
unexpected process/port/container
        v
        witr
        v
owner / parent / supervisor / service / container
        v
authoritative inspection
        v
decision
        v
only then: stop / restart / modify
```

#### Agent rules

- Run it **before** terminating or restarting an unfamiliar process or freeing an occupied port, and prefer a current target/name over stale PID assumptions when practical.
- Read warnings such as root execution, public binds, restarts, high memory or other risk indicators, then cross-check important conclusions against the authoritative service/container manager before intervention.

#### Do not

- `kill -9` simply because `witr` identifies a process as the owner of a port.
- Assume the process should be stopped merely because it is unexpected.
- Treat witr's causal attribution as a license to modify the service.

## 8. Network Diagnosis

For endpoint latency or packet loss, use bounded `ping` - unprivileged, with a machine-parseable summary.

```bash
ping -c 5 -q 1.1.1.1                     # rtt min/avg/max/mdev + loss
ping -c 5 -q -i 0.2 1.1.1.1             # tighter sampling, bounded count
```

- Always bound it with `-c`; an unbounded `ping` never returns.
- Read `rtt min/avg/max/mdev` for spread and the loss line for reachability.
- Reach for a full traceroute (`traceroute`/`tracepath`) only when asked about the *path* rather than the endpoint, and treat it as slow and often-unprivileged-only.
- Do not run an unbounded `ping`, or repeat it indefinitely to "confirm" a result.
- Do not infer application-layer failure from a ping result: a path symptom and an application failure are different problems.

## 9. Python Project Management and Quality

### 9.1 `uv`: Python projects, environments, dependencies and tools

#### Use when

Modern Python project/environment management, and one-shot Python tools. `uv init` - `uv add requests` - `uv run python main.py` - `uv sync` - `uvx ruff --version`

#### Agent rules

- Prefer `uv run <command>` for project commands instead of manually activating a virtual environment.
- Use `uvx`/`uv tool run` for isolated one-off CLI tools. `uvx` runs them in a temporary, isolated tool environment; use `uv run` when a command must run with the project environment.
- Keep `uv.lock` authoritative when the project uses it, use `uv add` / `uv remove` / `uv sync` for project dependency state, and keep project and system Python environments separate.

#### Do not

- Mix arbitrary `pip install` operations into an environment whose dependency lifecycle is being managed by `uv`, or install project dependencies into system Python for convenience.
- Use `uvx` for a tool that must see or modify the project environment unless that isolation is intentional.

### 9.2 `ruff`: Python linting and formatting

#### Use when

After Python changes, and as part of automated quality gates. `ruff check .` - `ruff check --output-format=json .` - `ruff format --check .` - `ruff format .`

#### Agent rules

- Respect `pyproject.toml`, `ruff.toml` and repository-specific configuration.
- Run `ruff check` after modifying Python, and prefer safe automatic fixes when appropriate: `ruff check --fix`.
- Use machine-readable output for programmatic processing, and run formatting separately from linting when the project expects formatter checks or formatter changes.

#### Unsafe-fix guardrail

Do not enable:

```bash
--unsafe-fixes
```

casually. Ruff explicitly distinguishes unsafe fixes because they can change runtime behavior or otherwise alter intent. Require a conscious decision and subsequent verification before applying them.

#### Do not

- Treat a clean lint as proof the program is correct.
- Override repository configuration simply to suppress a warning.
- Apply broad fixes without reviewing the resulting diff.
- Claim Ruff replaces type checking, tests or semantic review.

## 10. Performance Measurement

### 10.1 `hyperfine`: statistical command benchmarking

#### Use when

Evidence that one command/workload is faster or slower than another. `hyperfine --warmup 3 'command A' 'command B'`. Export results when they will be compared, recorded or processed.

#### Agent rules

1. Define equivalent workloads.
2. Establish a baseline before optimizing.
3. Use warmups when startup/caching effects matter.
4. Run enough repetitions to reduce noise.
5. Export the benchmark result for later comparison.

#### Critical side-effect guardrail

Hyperfine **repeats commands**. Never benchmark a command that deletes files; changes production state; sends irreversible requests; mutates external systems; consumes one-time credentials/tokens; or creates unbounded data - unless the experiment is explicitly isolated and the command is designed to be safe to repeat.

#### Do not

- Compare non-equivalent workloads.
- Declare a meaningful speedup from differences that are within measurement noise.
- Benchmark something merely because the tool is available; benchmarking has a cost and should answer a real performance question.

## 11. Context Compression with `rtk`

### 11.1 `rtk`: output compression/filtering layer

#### Use when

Reducing redundant command output before it reaches the agent's context. `rtk` is an **output proxy/filter**, not a replacement for the underlying CLI command.

#### Agent rules

- Transparent integration: when an environment integration transparently rewrites supported commands, continue to issue the normal command (`git status`). Do **not** manually add `rtk` if the integration is already doing the rewrite.
- If RTK is not installed, not enabled or unavailable, use the underlying command directly. RTK is an optimization layer, not a prerequisite for correct execution.
- Use explicit `rtk <command>` only when the command is not transparently integrated, an RTK-specific capability is required, or you are debugging RTK itself.
- On-disk footprint: RTK archives full unfiltered output of failing commands locally - name that file and check whether others can read it.
- Mandatory correctness rule: if RTK's summarized output is insufficient, immediately fall back to the raw command.
- For authoritative current Git/filesystem state, especially immediately after a mutation or inside a worktree, prefer the resolved underlying executable rather than treating RTK as a source of truth. RTK is an optimization layer, not a consistency boundary.
- Destructive-action protocol: 1. Use RTK for reconnaissance if helpful. 2. Decide what exact object/action is considered. 3. Run the raw underlying command. 4. Verify the raw state. 5. Perform the mutation. 6. Read back/verify the result.

#### Do not

- Double-wrap commands when a transparent integration is already active, or treat omitted output as proof that something does not exist.
- Use RTK where byte-for-byte output, complete enumeration or exact diffs are required, or as the authorization basis for destructive actions.

## 12. Cross-Tool Workflows

Each line is one pipeline plus the guardrail that governs it; every tool has its own non-interactive mode above.

```text
12.1 fd -e py src/ --max-depth 4 -> rg -n 'class Target|def target' src/
     paths first, content second; never a bare repo dump

12.2 curl -s "$URL" | jq '.items[] | {id, name, status}'
     projection, never the raw response body

12.3 curl -L "$URL" | defuddle parse -m
     escalate to obscura only when content depends on JavaScript

12.4 obscura scrape --eval 'document.title' --format json PAGE1 PAGE2
     private-network protection stays enabled unless private access is authorized

12.5 yq '.services.api' compose.yml -> yq -i '.services.api.replicas = 3' compose.yml
     -> git --no-pager diff -- compose.yml -> yq '.services.api.replicas' compose.yml
     never an ad-hoc regex where yq expresses the change

12.6 procs --tree -> witr <current target>
     -> systemctl status / docker inspect / service-specific authority -> decision
     never jump directly from procs to kill

12.7 dust -d 1 -n 20 /var, then exact inspection of the candidate with ordinary
     filesystem commands; delete nothing based only on the top-N report

12.8 ping -c 5 -q example.com and ping -c 5 -q 1.1.1.1
     bounded -c count, repeated - never run indefinitely

12.9 ruff check . -> ruff format --check . -> uv run pytest
     a clean lint is a quality signal, not proof of semantic correctness

12.10 hyperfine --warmup 3 'baseline-command' 'candidate-command'
     only repeatable/isolate-able workloads; keep the result when it matters
```

## 13. Destructive-Action Guardrails

These rules supersede tool-specific convenience.

### Before deletion

1. Find the target with `fd`/`rg` or another authoritative query.
2. Confirm the exact path.
3. Confirm the exact raw target.
4. Confirm the target is not a mount point, active data directory, system path, or otherwise special object.
5. Only then delete.

### Before killing/stopping/restarting a process

1. Inspect with `procs`.
2. Trace ownership/causality with `witr`.
3. Check the authoritative service/container manager.
4. Understand dependencies and expected role.
5. Prefer a graceful/service-level stop before a signal escalation.
6. Verify the resulting state.

### Before editing configuration

1. Read the relevant subtree.
2. Make the smallest structural change.
3. Produce/read the diff.
4. Validate syntax/schema.
5. Apply/reload only after validation.
6. Verify runtime state.

### Before changing network behavior

1. Establish current latency/loss with `ping -c 5 -q <host>`.
2. Repeat the measurement.
3. Distinguish a path symptom from application-layer failure.
4. Make the smallest change.
5. Re-measure.

### Before running a benchmark

1. Confirm the command is repeatable.
2. Confirm the environment/workload is equivalent.
3. Use warmups where needed.
4. Capture/export the result.
5. Do not benchmark production mutations casually.

## 14. Non-Interactive Enforcement

Hard constraints for agent execution:

- `dust`: **bounded** depth/result mode for broad paths.
- No directory-jump wrapper: use an absolute path, or `fd`/`find` from a real root. Never a frecency score.
- `obscura`: keep SSRF/private-network blocking enabled by default.
- `rtk`: never replace an exact/raw command when completeness matters.
- Any command that can page, prompt or wait for a keyboard must have a known non-interactive mode or be rejected.

If the tool has no safe non-interactive invocation for the required task, stop and use a different command rather than improvising around the TTY requirement.

## 15. Installation and Environment Hygiene

This skill governs **use**, not blanket installation.

1. Check whether the command already exists, and what will actually run - `command -v <tool>` reports the resolved path, honouring shell functions and aliases.
2. If PATH shadowing is suspected (an older copy winning over the one just installed), list **all** candidates with `type -a <tool>`. `type -a` is the portable builtin; prefer it over `which`, which is not present by default on many minimal systems and does not see shell functions. On Windows use `where.exe <tool>`.
3. Check the installed version: `<tool> --version`.
4. Do not silently shadow an existing pinned version, or install a second implementation under the same executable name, without understanding PATH precedence.
5. `rtk` is optional. If it is not installed or its integration is unavailable, use the underlying command directly; never delay or distort a task merely to obtain RTK-compressed output.
6. Prefer the project's existing package/dependency manager.
7. For downloaded release binaries, verify integrity using the publisher's documented checksums/signatures when available.
8. Treat package-manager and installer scripts as code, not as trusted metadata. Read the command, verify the source and target version, and do not pipe arbitrary network content into a privileged shell without deliberate authorization.

## 16. Output Discipline for AI Agents

When reporting tool output back to a model/user:

**Prefer**

- filenames instead of file bodies;
- counts instead of repeated rows;
- selected JSON fields instead of complete API responses;
- bounded directory reports;
- explicit process names and parent chains;
- machine-readable JSON for network diagnostics;
- diffs for configuration/code changes;
- test exit status plus concise failure evidence.

**Avoid**

- ANSI color codes;
- decorative tables when plain text is enough;
- full repository dumps;
- full API responses;
- unbounded recursive output;
- TUI screenshots as the primary evidence;
- compressed/summarized output as the only evidence for destructive actions.

The best agent command is not necessarily the shortest command. It is the one that produces the **smallest sufficient evidence set**.

## 17. Failure and Escalation Protocol

When a tool fails:

1. Read its exit status and error output.
2. Do not immediately repeat the identical invocation.
3. Check: executable resolution/PATH; version; current working directory; permissions; input format; interactive/TTY assumptions; network/security restrictions.
4. Fall back to the simplest authoritative underlying command.
5. If the failure can cause a hang, prompt, repeated external request, or repeated mutation, do not retry blindly; change the invocation or tool first.
6. Report the substitution if it materially changes behavior or output.

Examples: `defuddle` fails to extract -> inspect raw HTML; if content is JS-generated, move to `obscura`. `obscura` blocks a private target -> do not disable the guard automatically; confirm private access is authorized first. `yq` syntax differs -> verify which `yq` implementation is installed. `rtk` output is insufficient -> use the raw command. Never run an unbounded `ping`; always pass `-c N`. `uvx` cannot see project dependencies -> use `uv run` when project context is required. Ruff reports a fix that may change behavior -> do not auto-apply unsafe fixes without deliberate review.

## 18. Quick Reference

```text
PATH DISCOVERY
  fd <pattern> <dir>                     fd -e py <dir>
  fd --type d --max-depth 3 <dir>
CONTENT SEARCH
  rg 'pattern' <dir>                     rg -l 'pattern' <dir>
  rg -c 'pattern' <dir>                  rg -g '*.rs' 'pattern' src/
HTML ARTICLE EXTRACTION
  defuddle parse URL --md                # preferred: it fetches the URL itself
  curl -L URL | defuddle parse -m
JAVASCRIPT-RENDERED WEB
  obscura fetch --dump markdown URL
  obscura scrape --format json URL1 URL2  # --eval form: see 4.2
JSON
  jq 'keys' file.json                    jq -r '.items[].id' file.json
  jq '.[] | {id, name, status}' file.json
YAML / STRUCTURED CONFIG
  yq '.server' config.yaml               yq -i '.server.port = 8080' config.yaml
HTTP TESTING
  hurl --test scenario.hurl
GITHUB
  gh repo view OWNER/REPO --json name,description,url
  gh pr list --json number,title,state
DISK USAGE
  dust -j -d 1 -n 20 <dir>               dust -d 1 -n 20 <dir>
PROCESSES
  procs --tree                           procs <name>
PROCESS CAUSALITY
  witr <target>
NETWORK
  ping -c 5 -q <host>
PYTHON
  uv run python ...                      uvx <tool> ...
  uv add <package>                       uv sync
PYTHON QUALITY
  ruff check .                           ruff check --fix
  ruff format --check .                  ruff format .
BENCHMARK
  hyperfine --warmup 3 'A' 'B'
DIRECTORY NAVIGATION
  cd /absolute/path        # no scored navigation tool is agent-approved
CONTEXT COMPRESSION
  <normal command>    # preferred under transparent RTK integration
  rtk <command>       # explicit only when needed
```

## 19. Upstream References

Derived from the supplied Terminal Tools for the AI Era catalogue and its agent classifications, with command/safety details cross-checked against upstream documentation where practical.

- fd: https://github.com/sharkdp/fd
- ripgrep: https://github.com/BurntSushi/ripgrep
- defuddle: https://github.com/kepano/defuddle
- obscura: https://github.com/h4ckf0r0day/obscura
- jq: https://github.com/jqlang/jq
- yq: https://github.com/mikefarah/yq
- hurl: https://github.com/Orange-OpenSource/hurl
- gh: https://github.com/cli/cli
- dust: https://github.com/bootandy/dust
- procs: https://github.com/dalance/procs
- witr: https://github.com/pranshuparmar/witr
- uv: https://github.com/astral-sh/uv
- ruff: https://github.com/astral-sh/ruff
- hyperfine: https://github.com/sharkdp/hyperfine
 - rtk: https://github.com/rtk-ai/rtk

## Version and evidence policy

This skill contains both upstream-derived rules and measured observations from the tool catalogue that produced it. **Do not silently generalize a measured observation into an eternal tool property.** Version-specific facts stay labeled as version-specific. Empirical benchmarks keep their original environment, fixture, and comparison scope.

When updating the skill:

- verify the current upstream release and relevant `--help` output;
- preserve the exact tested command forms and empirical output claims unless they have been deliberately re-tested and the change is explicitly intended;
- distinguish tool capability, agent suitability, and security posture;
- prefer a loud failure over a silent wrong program, wrong version, wrong target, or wrong PATH resolution;
- re-check every code fence, link, anchor, command, and safety statement before publishing.

## Appendix A: Research & Maintenance Contract

> **Maintainer material, not normal runtime instruction.** Use this appendix only when updating this skill or the associated article. Runtime agents should follow the main body, especially Sec. 2 (routing), Sec. 13 (destructive-action guardrails), and Sec. 14 (non-interactive enforcement).

Treat the source catalogue as evidence to re-check, not as a specification.

### A.1 Method

1. **Know the scope.** Curated entry point, not a specification, security audit or exhaustive manual. Research only what the article actually claims; depth belongs upstream, and an uncertain detail gets linked upstream and flagged rather than expanded.
2. **Source order:** repository README *and* `docs/`, docs site, man page / `--help`, changelog, **GitHub release notes**, then source code, then advisories. A change can be announced only in the release notes, so never conclude "undocumented" from one source being silent. Read the stated `Default:` line, not the sample snippet.
3. **Never judge machine-readability from the man page or README alone** - some flags surface only in `--help` or on a site page. **Check the current release**, separately from any version named in a caption; no recommendation rests on a version with known unpatched vulnerabilities.
4. **Re-derive every classification**, including one in this file. **Scriptable is not agent-useful**: a non-interactive mode does not earn `agent: yes`, and neither does "AI-agent compatible" marketing. **Check TTY behaviour per tool** - some auto-disable pagers, some do not, some change row count when piped. Verify, never generalise.
5. **Name the exact machine-output flag** and whether it is the default or opt-in. For stateful tools, state what is stored by default separately from what is optional.
6. **No blanket claims.** "Stores all env vars" or "not encrypted at all" need proof; absence of a config knob is not proof of unencrypted data. Confirm a partially removed feature is really gone by checking the config key *and* the write path both survive - a crate, a dependency or a leftover subcommand proves nothing.
7. **Upstream docs are not necessarily self-consistent:** name the authoritative file, link both briefly, and state the uncertainty instead of guessing. **No invented benchmarks** - bytes != tokens, characters != tokens, and most "token savings" figures are byte or character heuristics that must be labelled so.
8. **Keep agent usefulness, interactive suitability and security safety separate.** A badge says one; the section carries the other two. `agent: yes` never means "safe": `defuddle` and `obscura` fetch any URL handed to them, `hurl` transmits credentials, `gh` holds a token, `yq` exposes a `system` operator disabled unless `--security-enable-system-operator` is passed. Exclusion is a *workflow* judgement, not a capability limit: some excluded tools have a pipeable mode, but they emit an endless stream rather than an answer.
9. **Preserve the author's voice** (short, informal, developer-voice notes) and edit the real source file in place, after reading it in full. **Verify afterwards:** re-check every claim, command and link, and confirm no tool was lost, duplicated or given conflicting invocations in two places. Then run `skills-ref validate ./ai-era-terminal-tools`, `npm --prefix MyBlog run build` and `npm --prefix MyBlog run check` - the build catches a missing `:::` container closer or an unbalanced code fence, which fail silently and surface only at prerender.

### A.2 Conditional tools were benchmarked, not just labelled

A `agent: yes, with --flag` badge is a weak claim: it says a flag exists, not that using the tool beats not using it. Each conditional tool was measured against the tool an agent would otherwise reach for, and each pair was classified *before* it was timed - a faster tool does not win unless it produces an equivalent result.

Excluded despite a machine flag, with the measured evidence: `fzf --exact --filter` (near competitor to `grep -F`/`rg -F`, no win on a recursive tree), `fq -V` (same JSON as `jq -c` and 7.3x slower, though it also reads binary formats), `pastel format rgb` (shell arithmetic within noise over 50 iterations), and `trippy -m json` (ping plus traceroute; needs root, and its `-u` unprivileged mode is unsupported on WSL). Approved: `dust -d -n`, a near competitor with no machine-independent speed rule, because `-n` returns a bounded ranking and `-j` returns native JSON.

### A.3 Rules the measurements produced

1. **Classify the relationship before you time anything.** `exact competitor` (same result), `partial competitor` (same purpose, narrower features), `fallback` (useful for the task, not equivalent), `unrelated`. Speed only decides between exact competitors; a partial competitor stays because the faster tool cannot do the whole job.
2. **Verify output equivalence before the timing.** Comparisons can look different purely because of formatting; normalise both sides, and only then is a multiple real.
3. **Use at least three fixtures, one adversarial, and benchmark the version you ship.** A fuzzy default or one easy fixture can fake equivalence; the fixture that fails is what proves the flag matters. A different build than the documented one misstates the gap.
4. **Check output order, not just bytes.** Two tools can be byte-identical raw and still differ in line order, and a `> /dev/null` multiple is an artifact of the sink: measure both a pipe sink and a `/dev/null` sink.
5. **A result that does not reproduce is not a result.** Never credit a win to parallelism without an isolated re-run that isolates it, and do not swing to the opposite absolute - publish "within noise at equal scope" rather than "always slower".
6. **One burst is not a measurement.** A single `hyperfine` run gives a mean and sigma *within* one burst, not *between* bursts. If the spread overlaps the claimed gap, publish the range, not the multiple; if the losing command wins its best burst, drop the claim entirely.
7. **Prove side effects do not pass silently.** The harness must show the command under test is the command that ran, and that repeating it is safe.
8. **Check that the flags actually exist.** A documented-looking invocation can still be wrong: a subcommand taking a colour where a background was assumed, or an unprivileged flag the platform does not support. Verify before it enters a recommendation.

The general rule: "has a machine flag" is not a reason to use a tool, and if an agent-facing answer can be produced more cheaply by a tool already on the approved list - one that covers the operation in practice - prefer it and do not document the slower one, even if the slower one is a better program.

### A.4 Package and crate names are part of the factual content

Install commands were wrong more often than prose, and two errors were silent - the command succeeded and installed the wrong program. `cargo install dust` installs an unrelated Rust testing library; the crate is `du-dust` and the binary is still `dust`. Suite availability moves: across the Debian bookworm, trixie and sid indexes, `procs` arrived only in trixie and `fd` needs `fd-find` in stable, so "in apt" is not a stable statement.

1. **Check the package name against the distribution, not the binary name.** They differ routinely (`fd` -> `fd-find`); verify against the `Packages` index for the suite you target, not a package page or a blog post, including this one.
2. **Prefer the failure mode that is loud.** A command that errors is better than one that exits 0 with the wrong thing on `PATH`.
3. **Scoop's `suggest` field is advisory, not a dependency.** It prints the hint after installing, installs nothing, and exits 0 either way - so a missing MSVC runtime is a silent launch failure behind a successful install.
4. **Never claim a tool is packaged without checking the actual package index** for the distribution and release you name.

---

## Attribution

Adapted from **Terminal Tools for the AI Era** by Ali Abdi.

Original article:
https://abditory.ir/006_ai-era-terminal-tools
