Toolbelt Skill
Prefer these tools for interactive terminal work. Check availability on the current machine; repository tooling and the host agent's editing rules take precedence over these defaults.
Table of Contents
Rule of thumb: classic tools for piping inside scripts that must be portable; modern tools for interactive/agent work where clarity and ergonomics win.
Resolve uncertainty
Use command -v, the installed tool's --help, and repository configuration to resolve missing tools or unfamiliar flags. Continue with a supported fallback when it preserves the requested result. Ask when the remaining uncertainty changes scope, risks user data, or requires authority the user has not supplied. A recipe here is not permission to install tools, load-test a service, or mutate remote state.
Substitution table (always-on)
Reach for the right-hand tool by default; fall back to the classic only when the modern one is absent.
| Instead of |
Use |
For |
ls / cat / du |
eza / bat / dust |
listing, viewing, disk usage |
grep / find |
ripgrep (rg) / fd |
text/file search |
grep for code structure |
ast-grep (sg) |
AST-aware search & rewrite |
sed (substitute) |
sd |
find & replace |
git diff |
delta — already wired as the pager |
diff/log/show/blame |
| a noisy reflow diff |
difftastic (difft) |
AST diff, opt-in |
ps / dig / xxd |
procs / doggo / hexyl |
processes, DNS, hex |
curl (API testing) |
xh |
HTTP requests |
jq for non-JSON |
dasel |
YAML/TOML/XML/CSV query+convert |
wc -l (code count) |
tokei |
code statistics (LOC) |
| ad-hoc regex design |
grex |
generate regular expressions |
| spell-check source |
typos |
typo linting in code + docs |
| ad-hoc SQL |
duckdb; psql/sqlx-cli per project |
data + migrations |
| benchmarking |
hyperfine (CLI), oha (HTTP) |
perf checks |
python / pip / pipx |
uv / uvx |
Python runtime, deps, tools |
node / npm / npx |
bun / bunx |
JS/TS runtime, deps, tools |
Tooling discipline (carried from global defaults)
Use these defaults when the project does not specify its own tooling:
- Mise for project tools — pin tools and runtimes in
.mise.toml, and run them with mise exec -- <tool>. Nix/Home Manager supplies the global machine environment. Honor an existing project's devShell until its toolchain is deliberately migrated.
make is the task runner — use the repository's own targets; run make check before commits and make validate before PRs. Verify actual hook configuration before claiming these gates run automatically.
- JSON →
jq — always jq for JSON processing; never python3 -c or inline Python. Reach for dasel the moment the format isn't JSON.
Runtimes & package managers
Use the project's declared runtime and lockfile. For ad-hoc work, prefer uv and bun when compatible.
uv — Python runtime + dependency + project manager (replaces python/pip/venv/pipx/poetry):
uv run script.py (auto-resolves deps), uv run pytest (run a tool in the project env)
uv add httpx / uv remove httpx (manage pyproject.toml), uv sync (install lockfile)
uv venv (create env), uv pip install -r req.txt (pip-compatible shim)
uvx — run a Python CLI tool one-off without installing: uvx ruff check, uvx ruff@0.6 format.
bun — JS/TS runtime + package manager + bundler (replaces node/npm/npx/yarn/pnpm):
bun run script.ts (runs TS directly, no compile step), bun test
bun install (fast install), bun add zod / bun remove zod
bunx — execute a package, downloading it if needed: bunx prettier --check config.json, bunx tsx file.ts.
Caveats: preserve the project's package manager, interpreter, and CI contract; changing runners can change compatibility or lockfiles. For one-off commands, inspect the installed version's help before using version-sensitive flags.
Search & navigate
| Task |
Tool |
Idiom |
| Find text |
ripgrep (rg) |
rg -n "pattern", rg -t rust foo, rg -l pat (files only) |
| Find files |
fd |
fd -e nix, fd -t f name, fd -H (include hidden) |
| List dir |
eza |
eza -la --git, eza --tree --level=2 |
| View file |
bat |
bat file, bat -p (plain, no decorations for piping) |
| Disk usage |
dust |
dust -d 2 (depth 2) |
| Jump dirs |
zoxide |
z proj after visiting once |
Prefer rg/fd over grep -r/find — faster, respects .gitignore, sane defaults. When piping bat output, add -p to strip line numbers/borders.
ast-grep (sg) — structural, syntax-aware code search & rewrite (matches by AST, not regex — immune to formatting/whitespace):
sg run -p 'console.log($A)' -l ts (find every console.log(...) call, any argument)
sg run -p 'foo($$$ARGS)' --rewrite 'bar($$$ARGS)' -l py -U (rename a call, preserving all args; -U applies in place)
- Reach for
sg over rg the moment the pattern is about code shape (a call, an import, a JSX element) rather than literal text — no brittle regex, no false hits inside strings/comments.
Edit text
sd — find & replace, literal-friendly, real regex (no sed escaping pain):
sd 'foo' 'bar' file.txt (in-place, no -i needed)
sd -p 'foo' 'bar' file.txt (preview diff, don't write)
sd '(\w+)@(\w+)' '$2.$1' file (capture groups with $1)
- Reach for
sed only for stream edits in portable scripts.
- For code-structure rewrites (rename a call, swap an API) use
ast-grep --rewrite instead — it edits by AST, not text, so formatting and string/comment matches can't trip it up.
HTTP / API debugging
xh — httpie-style client, faster than curl for hand-driven requests:
xh get https://api.example.com/users (auto-pretty JSON)
xh post api.local/items name=example (JSON body from k=v)
xh -f post url field=val (form), xh --headers get url (headers only)
xh get url Authorization:"Bearer $TOK" (header with :)
- Use
curl in scripts / when exact wire control or --resolve is needed.
oha — load testing: oha -n 1000 -c 50 https://api.local/health.
GitHub and GitLab
gh — GitHub-native repository, PR, release, and workflow operations:
gh repo view OWNER/REPO --json nameWithOwner,defaultBranchRef
gh api repos/OWNER/REPO/releases/tags/v1.2.3 --jq '{name,body,html_url}'
gh pr create --fill, gh pr view, gh run view
- Prefer
gh api over raw HTTP for GitHub metadata; use --jq to keep responses focused.
glab — GitLab-native equivalent for projects, merge requests, releases, and pipelines:
glab mr create --fill, glab mr view, glab pipeline view
Use the provider-native CLI when the task targets GitHub or GitLab state. Keep xh for generic HTTP APIs and curl for scripts requiring exact wire control.
Data & SQL
dasel — one tool to query/convert JSON/YAML/TOML/XML/CSV:
dasel -f config.yaml '.services.web.port'
dasel -f data.json -r json -w yaml (convert JSON→YAML)
dasel put -f config.yaml -v 8080 '.services.web.port' (edit YAML/TOML/etc. in place)
- Use
jq for pure-JSON pipelines (it's still the default for JSON); reach for dasel the moment the format isn't JSON. dasel handles YAML query and edit — it's the one tool for non-JSON structured data here.
tokei — count lines of code quickly:
tokei . (recursive code statistics by language)
duckdb — fast analytical SQL over files, no server:
duckdb -c "select * from 'data.csv' limit 5"
duckdb -c "select count(*) from read_parquet('*.parquet')"
miller (mlr) — CSV/TSV/JSON record processing:
mlr --csv cut -f a,b then sort -nr b data.csv
psql (from postgresql) — Postgres client. Not installed globally: it arrives through a project's .mise.toml (mise exec -- psql) or , psql for a one-off, so check before assuming it is on PATH.
psql "$DATABASE_URL" -c '\dt', psql -h host -U user db
sqlx-cli — Rust SQL toolkit / migrations:
sqlx database create, sqlx migrate add <name>, sqlx migrate run
sqlx migrate revert, cargo sqlx prepare (offline query cache)
Debug & inspect
procs — modern ps:
procs (all), procs nginx (filter by name), procs --tree
procs --sortd cpu (sort by CPU desc), shows ports/TTY/user.
doggo — modern dig for DNS debugging:
doggo example.com, doggo MX example.com
doggo example.com @1.1.1.1 (specific resolver), --json for parsing.
hexyl — colored hex viewer:
hexyl file.bin, hexyl -n 64 file (first 64 bytes), inspect encodings/headers.
tailspin (tspin) — auto-highlight logs: tspin app.log or cmd | tspin.
btop — interactive system monitor.
grex — generate regular expressions from user-provided test cases:
grex a b c (returns ^[a-c]$)
grex -d -w -p email@example.com (generate with digits, words, non-space)
typos — fast source-code spell checker (skips code identifiers sensibly):
typos (check the tree), typos -w (auto-fix), typos path/to/file
- Good as a pre-commit gate and before shipping docs; low false-positive rate.
delta — the git pager, wired in by programs.delta. git diff/log/show/blame render side-by-side with line numbers and n/N to jump hunks. Use git --no-pager diff for raw unified text to parse, or in a narrow terminal.
difftastic (difft) — the opt-in structural diff: compares ASTs, so reflow is not a change. delta highlights a line diff; difft changes what counts as a difference.
difft old.rs new.rs (standalone), or for one command: GIT_EXTERNAL_DIFF=difft git diff
- Reach for it only when a plain diff is noisy because indentation or wrapping moved but the code didn't.
Terminal multiplexing: tmux.
Benchmark
hyperfine — CLI command benchmarking with stats:
hyperfine 'rg foo' 'grep -r foo .' (compare), --warmup 3.
oha — HTTP load (see above).
Domain & infra tools (know these exist)
Candidates for specialized work. Availability varies by machine; check the executable and the project's own targets before choosing one.
| Domain |
Tools |
Reach for it when |
| Nix workflow |
nh (ergonomic nix/home-manager wrapper), nom (nix-output-monitor), nix-tree (closure explorer), nix-locate (which package owns a binary), comma (invoked as a lone , — runs a binary without installing it) |
rebuilding a config, watching a build, asking why something is in the closure, finding or borrowing a missing tool |
| Git extras |
git-cliff (changelog from conventional commits), gh, git-lfs |
generating a release changelog, driving GitHub, large files |
| Kubernetes |
k9s (TUI), kubectl, stern (multi-pod log tail) |
inspecting/driving a cluster, tailing pod logs |
| Cloud & sync |
rclone |
syncing to/from cloud/object storage |
| Containers (Linux) |
podman, buildah, skopeo |
building/running/inspecting OCI images (rootless, daemonless) |
| Secrets |
sops, age |
encrypting/decrypting secrets in the repo |
| Watch & run |
watchexec |
re-run a command on file changes (tests, builds) |
| Lint & format |
shellcheck, shfmt, yamlfmt, prettier, markdownlint-cli2, typos, pre-commit |
linting/formatting shell, YAML, JS/TS, Markdown; spell-check; hook setup |
| Lang tooling |
golangci-lint, ruff/ty (Python), cargo-update/-sweep/-cache |
project-local linting, Rust cargo maintenance |
| Archives & docs |
ouch (compress/extract), typst (doc compiler) |
packing/unpacking archives, typesetting |
| Shell & nav |
navi (interactive cheat sheet), fzf, zoxide, yazi (file manager) |
fuzzy-finding, cheat lookups, browsing files |
| Runtime pinning |
mise (per-project versions via .mise.toml, run with mise x -- <tool>), rustup (Rust toolchains) |
a project pins a language version; switching Rust toolchains |
For tools outside this list, prefer an existing dependency or native capability. Install only within the task's authorization and the project's tool-management convention.
When NOT to substitute
Portable shell scripts that may run on minimal/other machines → stick to POSIX (grep, sed, find, curl) so they don't depend on this toolbelt.
Pure-JSON pipelines → jq remains the default (per global CLAUDE.md).
For a tool command -v cannot find, comma fetches and runs any nixpkgs binary on demand. Its command name is a single comma, so it reads oddly inline:
, ffmpeg -i in.mov out.mp4
Good for a one-off; reaching for the same tool repeatedly is a signal to add it to harus-config. Fall back to the classic when comma is unavailable too.
command -v <tool> is the check. Tool inventories drift: scripts/tools is hand-maintained help text, packages.nix declares intent a machine may not have switched to, and this skill's own table is a third copy. Verify against the machine.
1---2name: toolbelt3description: Choose haru's preferred CLI tools for terminal search, inspection, HTTP, structured data, and benchmarking when tool selection or usage guidance is needed.4---56# Toolbelt Skill78Prefer these tools for interactive terminal work. Check availability on the current machine; repository tooling and the host agent's editing rules take precedence over these defaults.910## Table of Contents11- [Resolve uncertainty](#resolve-uncertainty)12- [Substitution table (always-on)](#substitution-table-always-on)13- [Tooling discipline (carried from global defaults)](#tooling-discipline-carried-from-global-defaults)14- [Runtimes & package managers](#runtimes--package-managers)15- [Search & navigate](#search--navigate)16- [Edit text](#edit-text)17- [HTTP / API debugging](#http--api-debugging)18- [GitHub and GitLab](#github-and-gitlab)19- [Data & SQL](#data--sql)20- [Debug & inspect](#debug--inspect)21- [Benchmark](#benchmark)22- [Domain & infra tools (know these exist)](#domain--infra-tools-know-these-exist)23- [When NOT to substitute](#when-not-to-substitute)2425Rule of thumb: classic tools for piping inside scripts that must be portable; modern tools for interactive/agent work where clarity and ergonomics win.2627## Resolve uncertainty2829Use `command -v`, the installed tool's `--help`, and repository configuration to resolve missing tools or unfamiliar flags. Continue with a supported fallback when it preserves the requested result. Ask when the remaining uncertainty changes scope, risks user data, or requires authority the user has not supplied. A recipe here is not permission to install tools, load-test a service, or mutate remote state.3031## Substitution table (always-on)3233Reach for the right-hand tool by default; fall back to the classic only when the modern one is absent.3435| Instead of | Use | For |36| -------------------- | --------------------------------------- | ------------------------------- |37| `ls` / `cat` / `du` | `eza` / `bat` / `dust` | listing, viewing, disk usage |38| `grep` / `find` | `ripgrep` (`rg`) / `fd` | text/file search |39| `grep` for code structure | `ast-grep` (`sg`) | AST-aware search & rewrite |40| `sed` (substitute) | `sd` | find & replace |41| `git diff` | `delta` — already wired as the pager | `diff`/`log`/`show`/`blame` |42| a noisy reflow diff | `difftastic` (`difft`) | AST diff, opt-in |43| `ps` / `dig` / `xxd` | `procs` / `doggo` / `hexyl` | processes, DNS, hex |44| `curl` (API testing) | `xh` | HTTP requests |45| `jq` for non-JSON | `dasel` | YAML/TOML/XML/CSV query+convert |46| `wc -l` (code count) | `tokei` | code statistics (LOC) |47| ad-hoc regex design | `grex` | generate regular expressions |48| spell-check source | `typos` | typo linting in code + docs |49| ad-hoc SQL | `duckdb`; `psql`/`sqlx-cli` per project | data + migrations |50| benchmarking | `hyperfine` (CLI), `oha` (HTTP) | perf checks |51| `python` / `pip` / `pipx` | `uv` / `uvx` | Python runtime, deps, tools |52| `node` / `npm` / `npx` | `bun` / `bunx` | JS/TS runtime, deps, tools |5354## Tooling discipline (carried from global defaults)5556Use these defaults when the project does not specify its own tooling:5758- **Mise for project tools** — pin tools and runtimes in `.mise.toml`, and run them with `mise exec -- <tool>`. Nix/Home Manager supplies the global machine environment. Honor an existing project's devShell until its toolchain is deliberately migrated.59- **`make` is the task runner** — use the repository's own targets; run `make check` before commits and `make validate` before PRs. Verify actual hook configuration before claiming these gates run automatically.60- **JSON → `jq`** — always `jq` for JSON processing; never `python3 -c` or inline Python. Reach for `dasel` the moment the format isn't JSON.6162## Runtimes & package managers6364Use the project's declared runtime and lockfile. For ad-hoc work, prefer `uv` and `bun` when compatible.6566- **`uv`** — Python runtime + dependency + project manager (replaces `python`/`pip`/`venv`/`pipx`/`poetry`):67 - `uv run script.py` (auto-resolves deps), `uv run pytest` (run a tool in the project env)68 - `uv add httpx` / `uv remove httpx` (manage `pyproject.toml`), `uv sync` (install lockfile)69 - `uv venv` (create env), `uv pip install -r req.txt` (pip-compatible shim)70 - **`uvx`** — run a Python CLI tool one-off without installing: `uvx ruff check`, `uvx ruff@0.6 format`.71- **`bun`** — JS/TS runtime + package manager + bundler (replaces `node`/`npm`/`npx`/`yarn`/`pnpm`):72 - `bun run script.ts` (runs TS directly, no compile step), `bun test`73 - `bun install` (fast install), `bun add zod` / `bun remove zod`74 - **`bunx`** — execute a package, downloading it if needed: `bunx prettier --check config.json`, `bunx tsx file.ts`.7576Caveats: preserve the project's package manager, interpreter, and CI contract; changing runners can change compatibility or lockfiles. For one-off commands, inspect the installed version's help before using version-sensitive flags.7778## Search & navigate7980| Task | Tool | Idiom |81| ---------- | ---------------- | ------------------------------------------------------------- |82| Find text | `ripgrep` (`rg`) | `rg -n "pattern"`, `rg -t rust foo`, `rg -l pat` (files only) |83| Find files | `fd` | `fd -e nix`, `fd -t f name`, `fd -H` (include hidden) |84| List dir | `eza` | `eza -la --git`, `eza --tree --level=2` |85| View file | `bat` | `bat file`, `bat -p` (plain, no decorations for piping) |86| Disk usage | `dust` | `dust -d 2` (depth 2) |87| Jump dirs | `zoxide` | `z proj` after visiting once |8889Prefer `rg`/`fd` over `grep -r`/`find` — faster, respects `.gitignore`, sane defaults. When piping `bat` output, add `-p` to strip line numbers/borders.9091- **`ast-grep` (`sg`)** — structural, syntax-aware code search & rewrite (matches by AST, not regex — immune to formatting/whitespace):92 - `sg run -p 'console.log($A)' -l ts` (find every `console.log(...)` call, any argument)93 - `sg run -p 'foo($$$ARGS)' --rewrite 'bar($$$ARGS)' -l py -U` (rename a call, preserving all args; `-U` applies in place)94 - Reach for `sg` over `rg` the moment the pattern is about code *shape* (a call, an import, a JSX element) rather than literal text — no brittle regex, no false hits inside strings/comments.9596## Edit text9798- **`sd`** — find & replace, literal-friendly, real regex (no `sed` escaping pain):99 - `sd 'foo' 'bar' file.txt` (in-place, no `-i` needed)100 - `sd -p 'foo' 'bar' file.txt` (preview diff, don't write)101 - `sd '(\w+)@(\w+)' '$2.$1' file` (capture groups with `$1`)102 - Reach for `sed` only for stream edits in portable scripts.103 - For *code-structure* rewrites (rename a call, swap an API) use `ast-grep --rewrite` instead — it edits by AST, not text, so formatting and string/comment matches can't trip it up.104105## HTTP / API debugging106107- **`xh`** — httpie-style client, faster than `curl` for hand-driven requests:108 - `xh get https://api.example.com/users` (auto-pretty JSON)109 - `xh post api.local/items name=example` (JSON body from `k=v`)110 - `xh -f post url field=val` (form), `xh --headers get url` (headers only)111 - `xh get url Authorization:"Bearer $TOK"` (header with `:`)112 - Use `curl` in scripts / when exact wire control or `--resolve` is needed.113- **`oha`** — load testing: `oha -n 1000 -c 50 https://api.local/health`.114115## GitHub and GitLab116117- **`gh`** — GitHub-native repository, PR, release, and workflow operations:118 - `gh repo view OWNER/REPO --json nameWithOwner,defaultBranchRef`119 - `gh api repos/OWNER/REPO/releases/tags/v1.2.3 --jq '{name,body,html_url}'`120 - `gh pr create --fill`, `gh pr view`, `gh run view`121 - Prefer `gh api` over raw HTTP for GitHub metadata; use `--jq` to keep responses focused.122- **`glab`** — GitLab-native equivalent for projects, merge requests, releases, and pipelines:123 - `glab mr create --fill`, `glab mr view`, `glab pipeline view`124125Use the provider-native CLI when the task targets GitHub or GitLab state. Keep `xh` for generic HTTP APIs and `curl` for scripts requiring exact wire control.126127## Data & SQL128129- **`dasel`** — one tool to query/convert JSON/YAML/TOML/XML/CSV:130 - `dasel -f config.yaml '.services.web.port'`131 - `dasel -f data.json -r json -w yaml` (convert JSON→YAML)132 - `dasel put -f config.yaml -v 8080 '.services.web.port'` (edit YAML/TOML/etc. in place)133 - Use `jq` for pure-JSON pipelines (it's still the default for JSON); reach for `dasel` the moment the format isn't JSON. `dasel` handles YAML query *and* edit — it's the one tool for non-JSON structured data here.134- **`tokei`** — count lines of code quickly:135 - `tokei .` (recursive code statistics by language)136- **`duckdb`** — fast analytical SQL over files, no server:137 - `duckdb -c "select * from 'data.csv' limit 5"`138 - `duckdb -c "select count(*) from read_parquet('*.parquet')"`139- **`miller`** (`mlr`) — CSV/TSV/JSON record processing:140 - `mlr --csv cut -f a,b then sort -nr b data.csv`141- **`psql`** (from `postgresql`) — Postgres client. Not installed globally: it arrives through a project's `.mise.toml` (`mise exec -- psql`) or `, psql` for a one-off, so check before assuming it is on `PATH`.142 - `psql "$DATABASE_URL" -c '\dt'`, `psql -h host -U user db`143- **`sqlx-cli`** — Rust SQL toolkit / migrations:144 - `sqlx database create`, `sqlx migrate add <name>`, `sqlx migrate run`145 - `sqlx migrate revert`, `cargo sqlx prepare` (offline query cache)146147## Debug & inspect148149- **`procs`** — modern `ps`:150 - `procs` (all), `procs nginx` (filter by name), `procs --tree`151 - `procs --sortd cpu` (sort by CPU desc), shows ports/TTY/user.152- **`doggo`** — modern `dig` for DNS debugging:153 - `doggo example.com`, `doggo MX example.com`154 - `doggo example.com @1.1.1.1` (specific resolver), `--json` for parsing.155- **`hexyl`** — colored hex viewer:156 - `hexyl file.bin`, `hexyl -n 64 file` (first 64 bytes), inspect encodings/headers.157- **`tailspin`** (`tspin`) — auto-highlight logs: `tspin app.log` or `cmd | tspin`.158- **`btop`** — interactive system monitor.159- **`grex`** — generate regular expressions from user-provided test cases:160 - `grex a b c` (returns `^[a-c]$`)161 - `grex -d -w -p email@example.com` (generate with digits, words, non-space)162- **`typos`** — fast source-code spell checker (skips code identifiers sensibly):163 - `typos` (check the tree), `typos -w` (auto-fix), `typos path/to/file`164 - Good as a pre-commit gate and before shipping docs; low false-positive rate.165- **`delta`** — the git pager, wired in by `programs.delta`. `git diff`/`log`/`show`/`blame` render side-by-side with line numbers and `n`/`N` to jump hunks. Use `git --no-pager diff` for raw unified text to parse, or in a narrow terminal.166- **`difftastic` (`difft`)** — the opt-in structural diff: compares ASTs, so reflow is not a change. `delta` highlights a line diff; `difft` changes what counts as a difference.167 - `difft old.rs new.rs` (standalone), or for one command: `GIT_EXTERNAL_DIFF=difft git diff`168 - Reach for it only when a plain diff is noisy because indentation or wrapping moved but the code didn't.169170Terminal multiplexing: `tmux`.171172## Benchmark173174- **`hyperfine`** — CLI command benchmarking with stats:175 - `hyperfine 'rg foo' 'grep -r foo .'` (compare), `--warmup 3`.176- **`oha`** — HTTP load (see above).177178## Domain & infra tools (know these exist)179180Candidates for specialized work. Availability varies by machine; check the executable and the project's own targets before choosing one.181182| Domain | Tools | Reach for it when |183| --- | --- | --- |184| **Nix workflow** | `nh` (ergonomic nix/home-manager wrapper), `nom` (`nix-output-monitor`), `nix-tree` (closure explorer), `nix-locate` (which package owns a binary), `comma` (invoked as a lone `,` — runs a binary without installing it) | rebuilding a config, watching a build, asking why something is in the closure, finding or borrowing a missing tool |185| **Git extras** | `git-cliff` (changelog from conventional commits), `gh`, `git-lfs` | generating a release changelog, driving GitHub, large files |186| **Kubernetes** | `k9s` (TUI), `kubectl`, `stern` (multi-pod log tail) | inspecting/driving a cluster, tailing pod logs |187| **Cloud & sync** | `rclone` | syncing to/from cloud/object storage |188| **Containers (Linux)** | `podman`, `buildah`, `skopeo` | building/running/inspecting OCI images (rootless, daemonless) |189| **Secrets** | `sops`, `age` | encrypting/decrypting secrets in the repo |190| **Watch & run** | `watchexec` | re-run a command on file changes (tests, builds) |191| **Lint & format** | `shellcheck`, `shfmt`, `yamlfmt`, `prettier`, `markdownlint-cli2`, `typos`, `pre-commit` | linting/formatting shell, YAML, JS/TS, Markdown; spell-check; hook setup |192| **Lang tooling** | `golangci-lint`, `ruff`/`ty` (Python), `cargo-update`/`-sweep`/`-cache` | project-local linting, Rust cargo maintenance |193| **Archives & docs** | `ouch` (compress/extract), `typst` (doc compiler) | packing/unpacking archives, typesetting |194| **Shell & nav** | `navi` (interactive cheat sheet), `fzf`, `zoxide`, `yazi` (file manager) | fuzzy-finding, cheat lookups, browsing files |195| **Runtime pinning** | `mise` (per-project versions via `.mise.toml`, run with `mise x -- <tool>`), `rustup` (Rust toolchains) | a project pins a language version; switching Rust toolchains |196197For tools outside this list, prefer an existing dependency or native capability. Install only within the task's authorization and the project's tool-management convention.198199## When NOT to substitute200201- Portable shell scripts that may run on minimal/other machines → stick to POSIX (`grep`, `sed`, `find`, `curl`) so they don't depend on this toolbelt.202- Pure-JSON pipelines → `jq` remains the default (per global CLAUDE.md).203- For a tool `command -v` cannot find, `comma` fetches and runs any nixpkgs binary on demand. Its command name is a single comma, so it reads oddly inline:204205 ```bash206 , ffmpeg -i in.mov out.mp4207 ```208209 Good for a one-off; reaching for the same tool repeatedly is a signal to add it to `harus-config`. Fall back to the classic when `comma` is unavailable too.210- **`command -v <tool>` is the check.** Tool inventories drift: `scripts/tools` is hand-maintained help text, `packages.nix` declares intent a machine may not have switched to, and this skill's own table is a third copy. Verify against the machine.