coding-tools 0.3.0

Declarative, agent-friendly CLI tools behind one 'ct' command: search, view, verifiable edits, and framed command tests.
Documentation
# coding-tools

Declarative, agent-friendly command-line tools for working in a codebase, behind
one short `ct` command. Each tool replaces an ad-hoc shell pattern with a single,
self-describing command, and every tool is framed the same way — so what you learn
from one transfers to the next, and an agent can discover and drive them uniformly.

```sh
cargo install coding-tools     # installs ct and every ct-* tool below
```

## Tools

`ct <command>` dispatches to `ct-<command>` (git-style), or call each tool by its
full name.

| Command     | Tool        | Purpose                                                                       |
| ----------- | ----------- | ---------------------------------------------------------------------------- |
| `ct search` | `ct-search` | Recursively find files by name, type, size, and content (`find \| xargs grep`). |
| `ct view`   | `ct-view`   | Show a file's lines by range, or the regions around a pattern with context.   |
| `ct tree`   | `ct-tree`   | Report a file tree with per-file line/word/char counts; filter, sort, summarise. |
| `ct edit`   | `ct-edit`   | Find/replace across files, gated by an `--expect` verdict and `--dry-run`.    |
| `ct patch`  | `ct-patch`  | Set/delete nodes by path in JSON/JSONC/JSONL, preserving comments and layout. |
| `ct test`   | `ct-test`   | Run a command as a framed experiment; classify the result from its output.    |
| `ct each`   | `ct-each`   | Run a command template once per item (no shell); aggregate `--expect` verdict. |
| `ct outline`| `ct-outline`| Report a file's declarations — kind, name, `start:end` span — for bounded reads. |
| `ct rules`  | `ct-rules`  | Record the project's invariants in `.ct/rules.jsonc` — verified at the moment they're written. |
| `ct check`  | `ct-check`  | Re-verify every recorded invariant; five lanes, one exit status. Read-only.   |
| `ct deps`   | `ct-deps`   | Assert crate-graph invariants — deny crates, forbid `A=>B` paths, duplicates — with evidence paths. |
| `ct await`  | `ct-await`  | Wait, boundedly, for an external outcome via a read-only probe.               |

## Why

A coding agent's loop is *locate → read → change → verify*. These tools make each
step **bounded, deterministic, and self-verifying**, which is what lets it run with
less supervision:

- **Framed verdicts.** A search or a command run can pose a `--question`, classify
  into a `SUCCESS`/`ERROR` verdict, and `--emit` a templated line; exit status
  follows the verdict. `ct-search --expect none` passes when nothing is found (a
  negative assertion); `ct-edit --expect =1` writes only if exactly one site
  matched, so a wrong-sized change fails loudly instead of applying silently.
- **Preview before write.** `ct-edit --dry-run` shows the diff and verdict without
  touching disk; edits preserve every untouched byte (indentation, terminators).
- **Atomic batches.** `ct-edit --script` runs a whole batch of block edits under
  prepare/confirm/write: every edit is simulated and judged in memory (and every
  target pre-flighted for writability) before anything is written — one failing
  anchor means zero writes, never a half-applied batch.
- **Read-only by default where it matters.** `ct-test` runs only a fixed, immutable
  allowlist of read-only commands; `ct-each` adds the suite's own gated mutating
  tools only behind an explicit `--mutating` flag. There is **no shell mode
  anywhere** — every dispatch is a direct argv launch.
- **Bounded and observable.** Every tool takes `--timeout` (self-bounding for the
  read-only/mutating tools, a child process-group kill folded into the verdict for
  `ct-test`/`ct-each`) and `--heartbeat`, a minimal templated liveness pulse for
  long runs.
- **Machine-readable.** Every tool takes `--json` for structured results, and
  `--explain [md|json]` prints its own documentation / tool-use definition. The
  umbrella's `ct --explain json` is a one-call manifest of the whole suite.

## Shared conventions

- **Pattern promotion.** Any *pattern* argument is promoted with one rule: no
  metacharacters → literal substring; glob metacharacters (`*` `?` `[ ]`) that are
  not a valid regex → glob; otherwise → regex. `--mode literal|glob|regex` pins
  the interpretation (promotion off) for verbatim code anchors.
- **Payload schemes.** Payload-typed values accept `file:PATH` (the file's
  contents, verbatim — never promoted) and `text:VALUE` (the escape for literal
  values starting with a scheme prefix). A multi-line pattern matches as a
  line-anchored literal **block** in `ct-search`/`ct-view`/`ct-edit`, with a
  nearest-miss diagnostic when it matches nothing.
- **Exit status.** `0` = success / verdict `SUCCESS`; `1` = clean negative /
  verdict `ERROR`; `2` = usage or runtime error. The `0`/`1` split composes in
  `&&`/`||` pipelines.
- **`--explain [md|json]`.** Every tool is self-describing for humans and agents.

## Examples

```sh
# Find Rust files mentioning TODO — just yes/no.
ct search --base src --name '*.rs' --grep TODO --quiet

# Assert there are no leftover debug prints (passes when nothing matches).
ct search --base src --name '*.rs' --grep 'dbg!\(' --expect none

# Read a span, or the neighbourhood of a symbol.
ct view src/lib.rs --range 40:80
ct view src/lib.rs --match Verdict --context 3 --json

# Preview a one-site rename, then apply it.
ct edit --base src --name '*.rs' --find 'old_api(' --replace 'new_api(' --expect =1 --dry-run

# Frame a read-only check as a test.
ct test --question "Is the config free of deprecated keys?" \
  --cmd cat -- config.toml --err-match 'old_key' --emit 'result: {RESULT}'

# Dispatch one check over several items — what used to need a bash for-loop.
ct each --items Parser Lexer Emitter -- \
  ct-search --base src --grep '{ITEM}::new' --quiet

# A verbatim block edit with zero quoting — write the payloads as files.
ct edit --base src --name '*.rs' \
  --find file:target/find.block --replace file:target/replace.block \
  --expect =1 --dry-run

# A batch of structural edits, atomic by construction (.ctb script):
# everything is verified in memory; one failing anchor means zero writes.
ct edit --base src --name '*.rs' --script target/edits.ctb
```

The canonical reference for each tool is its `--explain md` output, mirrored under
[`docs/explain/`](docs/explain/); [`docs/specs/commands.md`](docs/specs/commands.md)
is the suite index.

## License

Apache-2.0. See [LICENSE](LICENSE).