RGT: Rust Graph Tracker
Numeric and date provenance tracking for AI coding agents
Install • Quick Start • Commands • Supported Agents • How It Works • Contributing
English • Français • 中文 • 日本語 • 한국어 • Español • Português
RGT gives AI coding agents a persistent, queryable memory of every number and date they read from source files or derive through calculations, then verifies each derivation is mathematically correct. Single Rust binary, 13 supported AI coding tools, hooks that record data only and never rewrite commands.
Agents reason from changing files and can make arithmetic mistakes. RGT tracks the provenance of every numeric value and re-checks the math.
| Operation | What RGT does |
|---|---|
rgt record <file> |
Extracts every number and date from a file into the provenance graph |
rgt status |
Reports total, active, and stale nodes, showing which values are still trustworthy |
rgt derive |
Verifies an agent-computed value against its parents before recording it |
rgt query <id> |
Traces a value's lineage back to its source files |
rgt graph |
Exports the dependency DAG (text, Mermaid, or DOT) |
rgt hook |
Passive capture via each agent's native hook/plugin mechanism |
RGT does not measure savings: it prevents silent errors. Two failure modes motivate it:
- Stale data: an agent reads a file, later the file changes, and the agent keeps reasoning from the old numbers. RGT marks the affected root nodes stale and cascades staleness through every derived value that depends on them (
rgt status). - Wrong math: an agent computes
revenue = price * quantityand gets it wrong. RGT re-computes the expression from the parent values in the database and rejects mismatched derivations (exit 1) before they enter the graph.
Hooks are provenance-capture only: they record (path, content) and never rewrite, filter, or block the agent's tool calls.
curl -fsSL https://raw.githubusercontent.com/rafael-bianchi/rgt/main/install.sh | shInstalls to
~/.local/bin. Add to PATH if needed:echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc # or ~/.bashrc
brew install rafael-bianchi/rgt/rgtThe tap formula is refreshed by each GitHub release.
cargo install --git https://github.com/rafael-bianchi/rgtDownload from releases:
- macOS:
rgt-aarch64-apple-darwin.tar.gz - Linux:
rgt-x86_64-unknown-linux-musl.tar.gz/rgt-aarch64-unknown-linux-gnu.tar.gz - Windows:
rgt-x86_64-pc-windows-msvc.zip
Pre-built binaries for macOS, Linux, and Windows are published with each release.
rgt update # atomically replace the binary with the latest release
rgt update --check # check for a new version without applyingrgt status # Shows the provenance graph state (fresh store starts at 0 nodes)# 1. Configure provenance hooks for your AI tool
rgt init -g # auto-detect every installed supported agent
rgt init -g --agent copilot # or target one: copilot, gemini, vibe, opencode, pi, hermes, ...
rgt init --agent cline # project-scoped agents use project rules files
rgt init --agent codex # Codex / Windsurf / Cline / Antigravity / Kilo use rules files
# 2. Restart your AI tool, then:
rgt record budget.csv # agent reads a data file and records its values
rgt status # inspect the graph
rgt derive --parents node_raw_X,node_raw_Y --operation EXPRESSION --expression "a - b" --result 60000
# agent records a verified derivation
rgt query node_drv_Z # trace the derived value's lineage
rgt graph --format mermaid # export the dependency graph Agent reads a data file Agent computes a derived value
| |
v v
rgt hook post (native hook/plugin) rgt derive --parents <ids>
| |
v (verify against parents)
rgt record extracts {path, content} |
| v
v math correct?
provenance graph ── rgt status ── stale? ── NO ──> value trusted
| |
+---------------- YES --------------> node + dependents marked stale
Three strategies keep the graph trustworthy:
- Capture: native hooks/plugins push every file an agent reads through
rgt record, so values land in the graph without the agent remembering to call it.
Non-text sources (PDF, Excel, images): RGT's passive hook cannot see inside binary files — PDF/image interpretation happens inside the model itself, never as a local text file. The RGT instructions RGT writes to agents tell them to explicitly report such values via
echo "Amount: 1234.56" | rgt record --stdin(or an intermediate.txt/.mdfile). Plain-text/CSV/JSON/Markdown need no such action — they're captured automatically.rgt recordon a binary file returns a clear "unsupported file format" error naming this path.
- Verification: every
rgt deriveis trust-but-verify: RGT re-computes the result from parent values and rejects wrong ones before insertion. - Staleness: when a source file changes, its nodes (and everything derived from them) are flagged stale, so the agent can be told to re-read. Change detection is two-tier (mtime+size, then BLAKE3) with a time-bounded forced re-hash, and distinguishes a genuinely deleted file (
FILE_DELETED) from a permission/lock error (CHECK_FAILED, which does not mark values stale).
rgt init [-g] [--force] [--agent <name>] [--number-format <us|eu|auto>] # configure hooks, detect installed agents
rgt hook pre|post [--agent <name>] # passive capture from agent event JSON (stdin)--number-format persists the locale used to parse numbers (./, separators and signs) for the passive hook path. Valid values: us (. decimal, , thousands), eu (, decimal, . thousands), or auto (inferred per file — the default).
rgt init never destroys your existing configuration. It merges RGT's hook
entries into your agent config additively — JSON/JSONC settings (comments and
trailing commas are tolerated and preserved), TOML configs, and rules files keep
every other hook, keybinding, plugin, and note byte-for-byte. Re-running without
--force is a no-op; --force refreshes only RGT's own delimited block. If a
config file can't be parsed or safely merged, that agent is reported with a
recoverable error and a non-zero exit — other agents are still configured, and a
<file>.rgt.bak backup is kept before any existing file is rewritten.
Exit codes: 0 = success, 1 = at least one agent failed, 2 = invalid
--agent name.
rgt init writes hook commands that invoke the CLI by absolute path (resolved
from the running binary), so capture does not depend on the PATH of the shell
your AI tool spawns. If you relocate the binary (e.g. a package-manager upgrade
installs to a new path), re-run rgt init to refresh the written paths.
rgt doctor # diagnose hook installation and capture healthrgt doctor is a brew doctor-style diagnostic. Exit 0 when healthy or with
advisory warnings, 1 on unambiguous problems (e.g. the store is not
initialized). When hooks are installed but no values have ever been recorded, it
warns that capture may not be active and tells you to verify rgt is resolvable
in the shell context your AI tool uses (hook subprocesses fail open, so a broken
PATH records nothing silently).
rgt update [--check] [--yes] [--version <tag>] [--skip-checksum] [--skip-attestation]rgt update installs only verified binaries: every download is checked
against the release's checksums.txt (SHA-256) and its GitHub Artifact
Attestation — a trust anchor issued independently of the release's own assets
(built-in Sigstore verification, no gh required). A release missing either
verification is refused with a non-zero exit; --skip-checksum /
--skip-attestation are explicit, documented-as-insecure opt-outs that are
never the default. Version comparison uses Semantic Versioning: an older or
equal tag is never installed (no silent downgrades), and --version <tag>
warns when the requested tag is older than the installed version.
rgt record <file> [--number-format <us|eu|auto>] # extract and track values from a file
rgt derive --parents <ids> --operation <op> --expression <expr> --result <val>
# verify and record a derivation
rgt verify --parents <ids> --operation <op> --result <val>
# verify a derived value without recording
rgt status [--stale-only] [--json] # graph state and staleness
rgt query <node_id> [--json] # full lineage for a value
rgt graph [-f text|mermaid|dot] # export the dependency DAG
rgt gc [--vacuum] # remove obsolete (stale, dependent-free) nodesrgt record --number-format overrides the persisted format for one call; otherwise the persisted setting (from rgt init) is used, falling back to auto. Number parsing is locale-aware: a leading - and accounting parentheses (N) are part of the value, thousands/decimal separators are honored per the active format, and values that can't be parsed under that format are skipped (with a warning) rather than split into bogus nodes.
rgt gc removes obsolete nodes — values marked stale that nothing derives from — and reports how many it removed. It never touches non-stale nodes or anything still depended on. rgt gc --vacuum additionally reclaims freed disk pages with SQLite VACUUM (opt-in; the default run only deletes rows).
Operations: EXPRESSION (formulas like a + b * c) and DATE_DIFF (date arithmetic, e.g. date2 - date1). Parent variables map as parent[0]=a, parent[1]=b, ... (at most 26, a–z).
--operation is case-sensitive (EXPRESSION/DATE_DIFF); anything else is rejected with exit code 2 — verification is never silently skipped. --expression is limited to 4096 bytes and 256 levels of parenthesis nesting (over-limit input is rejected with exit 2, never a crash). Expressions evaluate with built-in functions disabled — only your parent variables and + - * / % ^ and parentheses are available, so evaluation is deterministic. DATE_DIFF requires --parents <date1>,<date2> and computes date2 - date1; a negative result (possible swapped order) is rejected.
RGT configures provenance-capture hooks for 13 AI coding tools, using each agent's native mechanism:
| Tool | Install | Method |
|---|---|---|
| Claude Code | rgt init -g |
PreToolUse/PostToolUse shell hook (settings.json); Bash tool reads (cat/head/tail/grep/rtk read, ...) are also captured |
| Cursor | rgt init -g --agent cursor |
pre/postToolUse hook (hooks.json); Bash tool reads captured too |
| GitHub Copilot (VS Code) | rgt init -g --agent copilot |
Copilot Chat hooks (github.copilot.chat.hooks) |
| GitHub Copilot CLI | rgt init -g --agent copilot |
Instructions file (Copilot CLI config dir) |
| Gemini CLI | rgt init -g --agent gemini |
~/.gemini/hooks.toml PostToolUse |
| Mistral Vibe | rgt init -g --agent vibe |
pre_tool hook (hooks.toml) + prompt |
| OpenCode | rgt init -g --agent opencode |
TypeScript plugin |
| Pi | rgt init --agent pi (or -g) |
TypeScript extension |
| Hermes | rgt init --agent hermes |
Python plugin + plugins.enabled |
| Codex CLI | rgt init --agent codex |
AGENTS.md instructions |
| Windsurf | rgt init --agent windsurf |
.windsurfrules |
| Cline / Roo Code | rgt init --agent cline |
.clinerules |
| Google Antigravity | rgt init --agent antigravity |
.agents/rules/antigravity-rgt-rules.md |
| Kilo Code | rgt init --agent kilocode |
.kilocode/rules/rgt-rules.md |
Accepted --agent values: claude-code, cursor, codex, windsurf, copilot, gemini, vibe, opencode, pi, hermes, cline, antigravity, kilocode, plus aliases claude, roo-code, kilo.
RGT stores its graph in .rgt/store.db (SQLite) in the project root, created by rgt init. No external services, no telemetry, no network calls during normal operation.
- AGENTS.md: instructions RGT installs for AI agents (how to record and derive)
- CONTRIBUTING.md: contribution guide
- CHANGELOG.md: release history
RGT was inspired by RTK (Rust Token Killer), a high-performance CLI proxy that compresses shell output for AI coding agents. RGT follows RTK's approach of a single binary with native, agent-specific hook integrations, and mirrors its 13-agent coverage. Where RTK filters command output, RGT tracks the numeric and date provenance of what agents read and derive, and verifies each derivation is mathematically correct.
RGT was built with assistance from DeepSeek AI coding tools.
Contributions welcome! Please open an issue or PR on GitHub.
Licensed under the Apache License, Version 2.0.
