Skip to content

Commit 737dada

Browse files
pszymkowiakaneymousamabenyounesclaudeZacaria
authored
feat: 9-tool AI agent support + emoji removal (#704)
* fix: remove all decorative emojis from CLI output (#687) * fix: remove decorative emojis from CLI output (#511) Replace decorative emojis with plain text to reduce token waste. Keep functional symbols (⚠️ ✓ ❌ ✅ ℹ️) that convey meaning in fewer tokens. Signed-off-by: Patrick Szymkowiak <patrick@rtk.ai> Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu> * fix: remove remaining decorative emojis from find_cmd and formatter Missed in initial emoji cleanup pass: 📁 in find_cmd.rs and parser/formatter.rs Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu> * fix: remove all decorative emojis from CLI output (#511) Replace emojis with plain text tokens across all production files for better LLM compatibility. Test fixtures and external tool detection patterns (e.g. Black's "All done!") are preserved. Signed-off-by: Patrick Szymkowiak <patrick@rtk-ai.app> Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu> * fix: remove last decorative emoji from next_cmd.rs Remove ⚡ from Next.js Build header, missed in previous passes. Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu> * fix: remove remaining emojis from gh_cmd.rs and init.rs Replace production emojis: - gh_cmd.rs: 🟣→[merged], ⚪→[unknown]/[pending], ⭐→removed, 🔱→removed - init.rs: ⚪→[--] for "not found" status indicators Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu> * fix: remove all checkmark emojis from CLI output Replace ✓ (U+2713) with plain text across 19 files: - "ok ✓" → "ok" (git add/commit/push/pull) - "✓ cargo test: ..." → "cargo test: ..." (all tool summaries) - Preserved ✓ in input detection patterns and test fixtures LLMs cannot interpret emoji semantics; plain text is clearer. Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu> --------- Signed-off-by: Patrick Szymkowiak <patrick@rtk.ai> Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu> Signed-off-by: Patrick Szymkowiak <patrick@rtk-ai.app> * feat: OpenClaw plugin for transparent exec rewriting (#358) * feat: add OpenClaw plugin for transparent exec rewriting Adds an OpenClaw plugin that intercepts exec tool calls via the before_tool_call hook and rewrites commands to their RTK equivalents. This is the OpenClaw equivalent of hooks/rtk-rewrite.sh for Claude Code. The plugin: - Registers a before_tool_call hook on the exec tool - Rewrites git, grep, find, ls, gh, docker, kubectl, and test commands - Guards against rewriting piped/compound commands and heredocs - Returns properly typed PluginHookBeforeToolCallResult - Supports enabled/verbose config options Measured savings: 48-87% token reduction on common commands. Files: - openclaw/index.ts — plugin source - openclaw/openclaw.plugin.json — plugin manifest - openclaw/README.md — installation and usage docs * refactor: delegate OpenClaw plugin to rtk rewrite Replace 60+ hardcoded regex rules with a single call to `rtk rewrite`, matching the OpenCode plugin pattern (hooks/opencode-rtk.ts). Benefits: - Zero maintenance: new RTK filters work automatically - Single source of truth: rewrite logic in Rust (src/discover/registry.rs) - 122 → 73 lines, no rule duplication Also: rebase on develop, fix homepage URL, bump version to 1.0.0. Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu> * feat: add package.json for npm publishing Enables `openclaw plugins install @rtk-ai/rtk-rewrite` for OpenClaw users. Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu> --------- Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu> Co-authored-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu> * feat: add Gemini CLI support via rtk init --gemini (#573) - Add `rtk hook gemini` command: native Rust hook processor for Gemini CLI BeforeTool hooks. Reads JSON from stdin, delegates to `rewrite_command()` (single source of truth), outputs Gemini-format JSON response. - Add `--gemini` flag to `rtk init`: installs hook wrapper script, GEMINI.md, and patches ~/.gemini/settings.json with BeforeTool hook entry. - Add `rtk init -g --gemini --uninstall`: clean removal of all Gemini artifacts. - 6 unit tests covering hook format, rewrite delegation, and exclusions. Replaces PR #174 which had too many conflicts after upstream restructuring. Signed-off-by: Ousama Ben Younes <benyounes.ousama@gmail.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> * feat(init): add Codex CLI support via AGENTS.md + RTK.md workflow (#377) * feat(init): add Codex CLI support via AGENTS.md + RTK.md workflow Add --codex mode to rtk init for Codex CLI integration using AGENTS.md + RTK.md, while keeping the newer develop init/opencode flow intact. Includes Codex install/show/uninstall handling, ASCII status output, stricter flag validation, and expanded tests for Codex AGENTS lifecycle and patch-mode rejection. Signed-off-by: Zacaria <havesomecode@gmail.com> * docs: fix validation metadata Signed-off-by: Zacaria <havesomecode@gmail.com> --------- Signed-off-by: Zacaria <havesomecode@gmail.com> * feat(copilot): add Copilot hook support (VS Code + CLI) (#605) Add `rtk hook copilot` command that handles both VS Code Copilot Chat (updatedInput rewrite) and GitHub Copilot CLI (deny-with-suggestion). - Auto-detects format: snake_case (VS Code) vs camelCase (Copilot CLI) - Delegates to `rtk rewrite` (single source of truth) - 14 hook tests (format detection, rewrite gating, output shape) - .github/hooks/rtk-rewrite.json for repo-scoped hook config - .github/copilot-instructions.md for RTK awareness - Test script: hooks/test-copilot-rtk-rewrite.sh Rebased on develop (includes Gemini #573, Codex #377, OpenClaw #358). Original work by @jeziellopes, cleaned up and rebased by maintainer. Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu> Co-authored-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu> * feat: add Cursor Agent support via --agent flag (#595) Add `rtk init -g --agent cursor` to install RTK hooks for Cursor Agent. Cursor's preToolUse hook supports command rewriting via updated_input, functionally identical to Claude Code's PreToolUse. Works with both the Cursor editor and cursor-cli (they share ~/.cursor/hooks.json). Changes: - New `--agent <name>` flag (claude|cursor) on `rtk init`, extensible for future agents. Default is claude (backward compatible). - Cursor hook script (hooks/cursor-rtk-rewrite.sh) outputs Cursor's JSON format: {permission, updated_input} vs Claude's hookSpecificOutput. - `rtk init --show` reports Cursor hook and hooks.json status. - `rtk init -g --uninstall` removes Cursor artifacts. - `rtk discover` notes that Cursor sessions are tracked via `rtk gain` (Cursor transcripts lack structured tool_use/tool_result blocks). - Unit tests for Cursor hooks.json patching, detection, and removal. Made-with: Cursor Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu> Co-authored-by: Moisei <1199723+moisei@users.noreply.github.com> * feat: add Windsurf support via rtk init --agent windsurf (#695) (#697) Install RTK rules in .windsurfrules (project-scoped) so Cascade prefixes shell commands with rtk for token savings. Windsurf hooks don't support command rewriting (only blocking), so RTK uses the rules-based approach (like Codex with AGENTS.md). Tested: Windsurf Cascade correctly uses rtk git status after install. Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu> * feat: add Cline/Roo Code support via rtk init --agent cline (#701) (#702) Install RTK rules in .clinerules (project-scoped) so Cline prefixes shell commands with rtk for token savings. Same rules-based approach as Windsurf and Codex. Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu> * fix(skill/rtk-triage): increase PR/issue limit to 200 with pagination hint (#717) * fix(skill/rtk-triage): increase PR/issue limit to 200 with pagination hint Raise gh pr list limit from 60 to 200 to match gh's max per call. Add inline comment explaining how to paginate for repos with >200 open PRs. Update threshold warning from >60 to >200 PRs/issues. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Florian BRUNIAUX <florian@bruniaux.com> * docs(architecture): update module count to 67 (hook_cmd added in #573) hook_cmd.rs was added in feat: add Gemini CLI support (#573) but ARCHITECTURE.md was not updated. Fixes pre-push validation failure. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Florian BRUNIAUX <florian@bruniaux.com> --------- Signed-off-by: Florian BRUNIAUX <florian@bruniaux.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Signed-off-by: Patrick Szymkowiak <patrick@rtk.ai> Signed-off-by: Patrick szymkowiak <patrick.szymkowiak@innovtech.eu> Signed-off-by: Patrick Szymkowiak <patrick@rtk-ai.app> Signed-off-by: Ousama Ben Younes <benyounes.ousama@gmail.com> Signed-off-by: Zacaria <havesomecode@gmail.com> Signed-off-by: Florian BRUNIAUX <florian@bruniaux.com> Co-authored-by: Alex <a.neyman17@gmail.com> Co-authored-by: Ben Younes <benyounes.ousama@gmail.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Zacaria Chtatar <Zacaria@users.noreply.github.com> Co-authored-by: Jeziel Lopes <jeziellcarvalho@gmail.com> Co-authored-by: Moisei Rabinovich <moisei@users.noreply.github.com> Co-authored-by: Moisei <1199723+moisei@users.noreply.github.com> Co-authored-by: Florian BRUNIAUX <florian@bruniaux.com>
1 parent 48e53cb commit 737dada

20 files changed

Lines changed: 2527 additions & 89 deletions

.claude/skills/rtk-triage/SKILL.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,13 @@ gh api "repos/{owner}/{repo}/collaborators" --jq '.[].login'
5757

5858
**PRs** :
5959
```bash
60-
gh pr list --state open --limit 60 \
60+
# Fetcher toutes les PRs ouvertes — paginer si nécessaire (gh limite à 200 par appel)
61+
gh pr list --state open --limit 200 \
6162
--json number,title,author,createdAt,updatedAt,additions,deletions,changedFiles,isDraft,mergeable,reviewDecision,statusCheckRollup,body
6263

64+
# Si le repo a >200 PRs ouvertes, relancer avec --search pour paginer :
65+
# gh pr list --state open --limit 200 --search "is:pr is:open sort:updated-desc" ...
66+
6367
# Pour chaque PR, récupérer les fichiers modifiés (nécessaire pour overlap detection)
6468
# Prioriser les PRs candidates (même domaine, même auteur)
6569
gh pr view {num} --json files --jq '[.files[].path] | join(",")'
@@ -232,6 +236,6 @@ Croisement issues × PRs. {N} PRs ouvertes, {N} issues ouvertes.
232236

233237
- Langue : argument `en`/`fr`. Défaut : `fr`. Les commentaires GitHub restent toujours en anglais.
234238
- Ne jamais poster de commentaires GitHub sans validation utilisateur (AskUserQuestion).
235-
- Si >150 issues ou >60 PRs : prévenir l'utilisateur, proposer de filtrer par label ou date.
239+
- Si >200 issues ou >200 PRs : prévenir l'utilisateur et paginer (relancer avec `--search` ou `gh api` avec pagination).
236240
- L'analyse croisée (Phase 3) est toujours exécutée — c'est la valeur ajoutée de ce skill.
237241
- Le fichier claudedocs est sauvegardé automatiquement sauf si l'utilisateur dit "no save".

.github/copilot-instructions.md

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# Copilot Instructions for rtk
2+
3+
**rtk (Rust Token Killer)** is a CLI proxy that filters and compresses command outputs before they reach an LLM context, saving 60–90% of tokens. It wraps common tools (`git`, `cargo`, `grep`, `pnpm`, `go`, etc.) and outputs condensed summaries instead of raw output.
4+
5+
## Using rtk in this session
6+
7+
**Always prefix commands with `rtk` when running shell commands** — this is the entire point of the project and reduces token consumption for every operation you perform.
8+
9+
```bash
10+
# Instead of: Use:
11+
git status rtk git status
12+
git log -10 rtk git log -10
13+
cargo test rtk cargo test
14+
cargo clippy --all-targets rtk cargo clippy --all-targets
15+
grep -r "pattern" src/ rtk grep -r "pattern" src/
16+
```
17+
18+
**rtk meta-commands** (always use these directly, no prefix needed):
19+
```bash
20+
rtk gain # Show token savings analytics for this session
21+
rtk gain --history # Full command history with per-command savings
22+
rtk discover # Scan session history for missed rtk opportunities
23+
rtk proxy <cmd> # Run a command raw (no filtering) but still track it
24+
```
25+
26+
**Verify rtk is installed before starting:**
27+
```bash
28+
rtk --version # Should print: rtk X.Y.Z
29+
rtk gain # Should show a dashboard (not "command not found")
30+
```
31+
32+
> ⚠️ **Name collision**: `rtk gain` failing means you have `reachingforthejack/rtk` (Rust Type Kit) installed instead of this project. Run `which rtk` and check the binary source.
33+
34+
## Build, Test & Lint
35+
36+
```bash
37+
# Development build
38+
cargo build
39+
40+
# Run all tests
41+
cargo test
42+
43+
# Run a single test by name
44+
cargo test test_filter_git_log
45+
46+
# Run all tests in a module
47+
cargo test git::tests::
48+
49+
# Run tests with stdout
50+
cargo test -- --nocapture
51+
52+
# Pre-commit gate (must all pass before any PR)
53+
cargo fmt --all --check && cargo clippy --all-targets && cargo test
54+
55+
# Smoke tests (requires installed binary)
56+
bash scripts/test-all.sh
57+
```
58+
59+
PRs target the **`develop`** branch, not `main`. All commits require a DCO sign-off (`git commit -s`).
60+
61+
## Architecture
62+
63+
```
64+
main.rs ← Clap Commands enum → specialized module (git.rs, *_cmd.rs, etc.)
65+
66+
execute subprocess
67+
68+
filter/compress output
69+
70+
tracking::TimedExecution → SQLite (~/.local/share/rtk/tracking.db)
71+
```
72+
73+
Key modules:
74+
- **`main.rs`** — Clap `Commands` enum routes every subcommand to its module. Each arm calls `tracking::TimedExecution::start()` before running, then `.track(...)` after.
75+
- **`filter.rs`** — Language-aware filtering with `FilterLevel` (`none` / `minimal` / `aggressive`) and `Language` enum. Used by `read` and `smart` commands.
76+
- **`tracking.rs`** — SQLite persistence for token savings, scoped per project path. Powers `rtk gain`.
77+
- **`tee.rs`** — On filter failure, saves raw output to `~/.local/share/rtk/tee/` and prints a one-line hint so the LLM can re-read without re-running the command.
78+
- **`utils.rs`** — Shared helpers: `truncate`, `strip_ansi`, `execute_command`, package-manager auto-detection (pnpm/yarn/npm/npx).
79+
80+
New commands follow this structure: one file `src/<cmd>_cmd.rs` with a `pub fn run(...)` entry point, registered in the `Commands` enum in `main.rs`.
81+
82+
## Key Conventions
83+
84+
### Error handling
85+
- Use `anyhow::Result` throughout (this is a binary, not a library).
86+
- Always attach context: `operation.context("description")?` — never bare `?` without context.
87+
- No `unwrap()` in production code; `expect("reason")` is acceptable only in tests.
88+
- Every filter must fall back to raw command execution on error — never break the user's workflow.
89+
90+
### Regex
91+
- Compile once with `lazy_static!`, never inside a function body:
92+
```rust
93+
lazy_static! {
94+
static ref RE: Regex = Regex::new(r"pattern").unwrap();
95+
}
96+
```
97+
98+
### Testing
99+
- Unit tests live **inside the module file** in `#[cfg(test)] mod tests { ... }` — not in `tests/`.
100+
- Fixtures are real captured command output in `tests/fixtures/<cmd>_raw.txt`, loaded with `include_str!("../tests/fixtures/...")`.
101+
- Each test module defines its own local `fn count_tokens(text: &str) -> usize` (word-split approximation) — there is no shared utility for this.
102+
- Token savings assertions use `assert!(savings >= 60.0, ...)`.
103+
- Snapshot tests use `assert_snapshot!()` from the `insta` crate; review with `cargo insta review`.
104+
105+
### Adding a new command
106+
1. Create `src/<cmd>_cmd.rs` with `pub fn run(...)`.
107+
2. Add `mod <cmd>_cmd;` at the top of `main.rs`.
108+
3. Add a variant to the `Commands` enum with `#[arg(trailing_var_arg = true, allow_hyphen_values = true)]` for pass-through flags.
109+
4. Route the variant in the `match` block, wrapping execution with `tracking::TimedExecution`.
110+
5. Write a fixture from real output, then unit tests in the module file.
111+
6. Update `README.md` (command list + savings %) and `CHANGELOG.md`.
112+
113+
### Exit codes
114+
Preserve the underlying command's exit code. Use `std::process::exit(code)` when the child process exits non-zero.
115+
116+
### Performance constraints
117+
- Startup must stay under 10ms — no async runtime (no `tokio`/`async-std`).
118+
- No blocking I/O at startup; config is loaded on-demand.
119+
- Binary size target: <5 MB stripped.
120+
121+
### Branch naming
122+
```
123+
fix(scope): short-description
124+
feat(scope): short-description
125+
chore(scope): short-description
126+
```
127+
`scope` is the affected component (e.g. `git`, `filter`, `tracking`).

.github/hooks/rtk-rewrite.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"hooks": {
3+
"PreToolUse": [
4+
{
5+
"type": "command",
6+
"command": "rtk hook",
7+
"cwd": ".",
8+
"timeout": 5
9+
}
10+
]
11+
}
12+
}

ARCHITECTURE.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -293,12 +293,12 @@ SHARED utils.rs Helpers N/A ✓
293293
tee.rs Full output recovery N/A ✓
294294
```
295295

296-
**Total: 66 modules** (44 command modules + 22 infrastructure modules)
296+
**Total: 67 modules** (45 command modules + 22 infrastructure modules)
297297

298298
### Module Count Breakdown
299299

300-
- **Command Modules**: 34 (directly exposed to users)
301-
- **Infrastructure Modules**: 20 (utils, filter, tracking, tee, config, init, gain, toml_filter, verify_cmd, etc.)
300+
- **Command Modules**: 45 (directly exposed to users)
301+
- **Infrastructure Modules**: 22 (utils, filter, tracking, tee, config, init, gain, toml_filter, verify_cmd, trust, etc.)
302302
- **Git Commands**: 7 operations (status, diff, log, add, commit, push, branch/checkout)
303303
- **JS/TS Tooling**: 8 modules (modern frontend/fullstack development)
304304
- **Python Tooling**: 3 modules (ruff, pytest, pip)

README.md

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ rtk gain # Should show token savings stats
102102
# 1. Install hook for Claude Code (recommended)
103103
rtk init --global
104104
# Follow instructions to register in ~/.claude/settings.json
105-
# Claude Code only by default (use --opencode for OpenCode)
105+
# Claude Code only by default (use --opencode for OpenCode, --gemini for Gemini CLI)
106106

107107
# 2. Restart Claude Code, then test
108108
git status # Automatically rewritten to rtk git status
@@ -287,6 +287,27 @@ rtk init --show # Verify installation
287287

288288
After install, **restart Claude Code**.
289289

290+
## Gemini CLI Support (Global)
291+
292+
RTK supports Gemini CLI via a native Rust hook processor. The hook intercepts `run_shell_command` tool calls and rewrites them to `rtk` equivalents using the same rewrite engine as Claude Code.
293+
294+
**Install Gemini hook:**
295+
```bash
296+
rtk init -g --gemini
297+
```
298+
299+
**What it creates:**
300+
- `~/.gemini/hooks/rtk-hook-gemini.sh` (thin wrapper calling `rtk hook gemini`)
301+
- `~/.gemini/GEMINI.md` (RTK awareness instructions)
302+
- Patches `~/.gemini/settings.json` with BeforeTool hook
303+
304+
**Uninstall:**
305+
```bash
306+
rtk init -g --gemini --uninstall
307+
```
308+
309+
**Restart Required**: Restart Gemini CLI, then test with `git status` in a session.
310+
290311
## OpenCode Plugin (Global)
291312

292313
OpenCode supports plugins that can intercept tool execution. RTK provides a global plugin that mirrors the Claude auto-rewrite behavior by rewriting Bash tool commands to `rtk ...` before they execute. This plugin is **not** installed by default.

hooks/cline-rtk-rules.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# RTK - Rust Token Killer (Cline)
2+
3+
**Usage**: Token-optimized CLI proxy for shell commands.
4+
5+
## Rule
6+
7+
Always prefix shell commands with `rtk` to minimize token consumption.
8+
9+
Examples:
10+
11+
```bash
12+
rtk git status
13+
rtk cargo test
14+
rtk ls src/
15+
rtk grep "pattern" src/
16+
rtk find "*.rs" .
17+
rtk docker ps
18+
rtk gh pr list
19+
```
20+
21+
## Meta Commands
22+
23+
```bash
24+
rtk gain # Show token savings
25+
rtk gain --history # Command history with savings
26+
rtk discover # Find missed RTK opportunities
27+
rtk proxy <cmd> # Run raw (no filtering, for debugging)
28+
```
29+
30+
## Why
31+
32+
RTK filters and compresses command output before it reaches the LLM context, saving 60-90% tokens on common operations. Always use `rtk <cmd>` instead of raw commands.

hooks/copilot-rtk-awareness.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# RTK — Copilot Integration (VS Code Copilot Chat + Copilot CLI)
2+
3+
**Usage**: Token-optimized CLI proxy (60-90% savings on dev operations)
4+
5+
## What's automatic
6+
7+
The `.github/copilot-instructions.md` file is loaded at session start by both Copilot CLI and VS Code Copilot Chat.
8+
It instructs Copilot to prefix commands with `rtk` automatically.
9+
10+
The `.github/hooks/rtk-rewrite.json` hook adds a `PreToolUse` safety net via `rtk hook`
11+
a cross-platform Rust binary that intercepts raw bash tool calls and rewrites them.
12+
No shell scripts, no `jq` dependency, works on Windows natively.
13+
14+
## Meta commands (always use directly)
15+
16+
```bash
17+
rtk gain # Token savings dashboard for this session
18+
rtk gain --history # Per-command history with savings %
19+
rtk discover # Scan session history for missed rtk opportunities
20+
rtk proxy <cmd> # Run raw (no filtering) but still track it
21+
```
22+
23+
## Installation verification
24+
25+
```bash
26+
rtk --version # Should print: rtk X.Y.Z
27+
rtk gain # Should show a dashboard (not "command not found")
28+
which rtk # Verify correct binary path
29+
```
30+
31+
> ⚠️ **Name collision**: If `rtk gain` fails, you may have `reachingforthejack/rtk`
32+
> (Rust Type Kit) installed instead. Check `which rtk` and reinstall from rtk-ai/rtk.
33+
34+
## How the hook works
35+
36+
`rtk hook` reads `PreToolUse` JSON from stdin, detects the agent format, and responds appropriately:
37+
38+
**VS Code Copilot Chat** (supports `updatedInput` — transparent rewrite, no denial):
39+
1. Agent runs `git status``rtk hook` intercepts via `PreToolUse`
40+
2. `rtk hook` detects VS Code format (`tool_name`/`tool_input` keys)
41+
3. Returns `hookSpecificOutput.updatedInput.command = "rtk git status"`
42+
4. Agent runs the rewritten command silently — no denial, no retry
43+
44+
**GitHub Copilot CLI** (deny-with-suggestion — CLI ignores `updatedInput` today, see [issue #2013](https://github.com/github/copilot-cli/issues/2013)):
45+
1. Agent runs `git status``rtk hook` intercepts via `PreToolUse`
46+
2. `rtk hook` detects Copilot CLI format (`toolName`/`toolArgs` keys)
47+
3. Returns `permissionDecision: deny` with reason: `"Token savings: use 'rtk git status' instead"`
48+
4. Copilot reads the reason and re-runs `rtk git status`
49+
50+
When Copilot CLI adds `updatedInput` support, only `rtk hook` needs updating — no config changes.
51+
52+
## Integration comparison
53+
54+
| Tool | Mechanism | Hook output | File |
55+
|-----------------------|-----------------------------------------|--------------------------|------------------------------------|
56+
| Claude Code | `PreToolUse` hook with `updatedInput` | Transparent rewrite | `hooks/rtk-rewrite.sh` |
57+
| VS Code Copilot Chat | `PreToolUse` hook with `updatedInput` | Transparent rewrite | `.github/hooks/rtk-rewrite.json` |
58+
| GitHub Copilot CLI | `PreToolUse` deny-with-suggestion | Denial + retry | `.github/hooks/rtk-rewrite.json` |
59+
| OpenCode | Plugin `tool.execute.before` | Transparent rewrite | `hooks/opencode-rtk.ts` |
60+
| (any) | Custom instructions | Prompt-level guidance | `.github/copilot-instructions.md` |

hooks/cursor-rtk-rewrite.sh

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#!/usr/bin/env bash
2+
# rtk-hook-version: 1
3+
# RTK Cursor Agent hook — rewrites shell commands to use rtk for token savings.
4+
# Works with both Cursor editor and cursor-cli (they share ~/.cursor/hooks.json).
5+
# Cursor preToolUse hook format: receives JSON on stdin, returns JSON on stdout.
6+
# Requires: rtk >= 0.23.0, jq
7+
#
8+
# This is a thin delegating hook: all rewrite logic lives in `rtk rewrite`,
9+
# which is the single source of truth (src/discover/registry.rs).
10+
# To add or change rewrite rules, edit the Rust registry — not this file.
11+
12+
if ! command -v jq &>/dev/null; then
13+
echo "[rtk] WARNING: jq is not installed. Hook cannot rewrite commands. Install jq: https://jqlang.github.io/jq/download/" >&2
14+
exit 0
15+
fi
16+
17+
if ! command -v rtk &>/dev/null; then
18+
echo "[rtk] WARNING: rtk is not installed or not in PATH. Hook cannot rewrite commands. Install: https://github.com/rtk-ai/rtk#installation" >&2
19+
exit 0
20+
fi
21+
22+
# Version guard: rtk rewrite was added in 0.23.0.
23+
RTK_VERSION=$(rtk --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
24+
if [ -n "$RTK_VERSION" ]; then
25+
MAJOR=$(echo "$RTK_VERSION" | cut -d. -f1)
26+
MINOR=$(echo "$RTK_VERSION" | cut -d. -f2)
27+
if [ "$MAJOR" -eq 0 ] && [ "$MINOR" -lt 23 ]; then
28+
echo "[rtk] WARNING: rtk $RTK_VERSION is too old (need >= 0.23.0). Upgrade: cargo install rtk" >&2
29+
exit 0
30+
fi
31+
fi
32+
33+
INPUT=$(cat)
34+
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
35+
36+
if [ -z "$CMD" ]; then
37+
echo '{}'
38+
exit 0
39+
fi
40+
41+
# Delegate all rewrite logic to the Rust binary.
42+
# rtk rewrite exits 1 when there's no rewrite — hook passes through silently.
43+
REWRITTEN=$(rtk rewrite "$CMD" 2>/dev/null) || { echo '{}'; exit 0; }
44+
45+
# No change — nothing to do.
46+
if [ "$CMD" = "$REWRITTEN" ]; then
47+
echo '{}'
48+
exit 0
49+
fi
50+
51+
jq -n --arg cmd "$REWRITTEN" '{
52+
"permission": "allow",
53+
"updated_input": { "command": $cmd }
54+
}'

hooks/rtk-awareness-codex.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# RTK - Rust Token Killer (Codex CLI)
2+
3+
**Usage**: Token-optimized CLI proxy for shell commands.
4+
5+
## Rule
6+
7+
Always prefix shell commands with `rtk`.
8+
9+
Examples:
10+
11+
```bash
12+
rtk git status
13+
rtk cargo test
14+
rtk npm run build
15+
rtk pytest -q
16+
```
17+
18+
## Meta Commands
19+
20+
```bash
21+
rtk gain # Token savings analytics
22+
rtk gain --history # Recent command savings history
23+
rtk proxy <cmd> # Run raw command without filtering
24+
```
25+
26+
## Verification
27+
28+
```bash
29+
rtk --version
30+
rtk gain
31+
which rtk
32+
```

0 commit comments

Comments
 (0)