coding-tools 0.8.5

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.

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 okf ct-okf Author and query OKF knowledge bundles — validate, list/query metadata, links, scaffold.
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 await ct-await Wait, boundedly, for an external outcome via a read-only probe.
ct steer ct-steer Steer ad-hoc shell to the ct tool that serves it; install the PreToolUse hook.

ct rules/ct check also host built-in checksdeps (crate-graph), mods (module-graph), and okf (OKF-bundle conformance) invariants — recorded and verified as rules (ct rules … -- deps … / -- mods … / -- okf …), not as separate top-level commands.

ct-search, ct-tree, ct-view, and ct-outline are also OKF-aware: they auto-detect a Markdown concept's YAML frontmatter and surface it additively (ct search --okf-type/--okf-tag, ct tree --sort/--group okf-type, ct view --frontmatter, ct outline --frontmatter) without changing their default output. See the OKF spec.

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. ct-okf --script applies the same standard to a batch of OKF mutations (cascading over an in-memory bundle overlay), so a multi-step authoring change lands all-or-nothing.
  • 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.
  • Update check. ct checks crates.io for a newer release about once a day, in a detached background process (a conditional GET of the sparse index, so it is cheap and never blocks a command). Set CT_UPDATE_CHECK=never to disable, or =weekly / =hourly / a number of seconds to retune. You are told this on first run.

Examples

# 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/specs/commands.md is the suite index.

Steering agents to ct

An agent only benefits from these tools if it actually reaches for them. ct steer closes that gap: installed as a Claude Code PreToolUse hook, it inspects each proposed shell command and, when a ct tool clearly serves it (find | xargs grep, grep -r, sed -i, cat | head, for loops, &&/|| chains), blocks the raw command and feeds back the ct equivalent so the agent re-issues through the suite. The matcher is conservative — high-confidence idioms only, fail-open on everything else — and never re-steers a ct command.

ct steer install            # add the hook to .claude/settings.json (deny mode)

ct steer install --mode ask # softer: ask to confirm instead of denying

ct steer check 'grep -r TODO src'   # see what the hook would decide (exit 1 = steer)

ct steer uninstall          # remove it

Releasing

Publishing to crates.io is manual. Neither cargo nor cargo-workspaces has a native pre-publish hook, so the security audit is enforced in CI: the audit job runs cargo audit on every push and pull request, so main can't go green with a RustSec advisory in the locked tree. Publish only from a green commit:

cargo audit          # the same check CI runs — advisories fail the build

cargo ws publish     # (cargo-workspaces) — or `cargo publish`

Requires cargo install cargo-audit.

License

Apache-2.0. See LICENSE.