rtk (Rust Token Killer) - A high-performance CLI proxy that minimizes LLM token consumption through intelligent output filtering and compression.
This document provides a comprehensive architectural overview of rtk, including system design, data flows, module organization, and implementation patterns.
- System Overview
- Command Lifecycle
- Module Organization
- Filtering Strategies
- Shared Infrastructure
- Token Tracking System
- Global Flags Architecture
- Error Handling
- Configuration System
- Module Development Pattern
- Build Optimizations
- Extensibility Guide
┌────────────────────────────────────────────────────────────────────────┐
│ rtk - Token Optimization Proxy │
└────────────────────────────────────────────────────────────────────────┘
User Input CLI Layer Router Module Layer
────────── ───────── ────── ────────────
$ rtk git log ─→ Clap Parser ─→ Commands ─→ git::run()
-v --oneline (main.rs) enum match
• Parse args Execute: git log
• Extract flags Capture output
• Route command ↓
Filter/Compress
↓
$ 3 commits ←─ Terminal ←─ Format ←─ Compact Stats
+142/-89 colored optimized (90% reduction)
output ↓
tracking::track()
↓
SQLite INSERT
(~/.local/share/rtk/)
| Component | Location | Responsibility |
|---|---|---|
| CLI Parser | main.rs | Clap-based argument parsing, global flags |
| Command Router | main.rs | Dispatch to specialized modules |
| Module Layer | src/*_cmd.rs, src/git.rs, etc. | Command execution + filtering |
| Shared Utils | utils.rs | Package manager detection, text processing |
| Filter Engine | filter.rs | Language-aware code filtering |
| Tracking | tracking.rs | SQLite-based token metrics |
| Config | config.rs, init.rs | User preferences, LLM integration |
- Single Responsibility: Each module handles one command type
- Minimal Overhead: ~5-15ms proxy overhead per command
- Exit Code Preservation: CI/CD reliability through proper exit code propagation
- Fail-Safe: If filtering fails, fall back to original output
- Transparent: Users can always see raw output with
-vflags
┌────────────────────────────────────────────────────────────────────────┐
│ Command Execution Lifecycle │
└────────────────────────────────────────────────────────────────────────┘
Phase 1: PARSE
──────────────
$ rtk git log --oneline -5 -v
Clap Parser extracts:
• Command: Commands::Git
• Args: ["log", "--oneline", "-5"]
• Flags: verbose = 1
ultra_compact = false
↓
Phase 2: ROUTE
──────────────
main.rs:match Commands::Git { args, .. }
↓
git::run(args, verbose)
↓
Phase 3: EXECUTE
────────────────
std::process::Command::new("git")
.args(["log", "--oneline", "-5"])
.output()?
Output captured:
• stdout: "abc123 Fix bug\ndef456 Add feature\n..." (500 chars)
• stderr: "" (empty)
• exit_code: 0
↓
Phase 4: FILTER
───────────────
git::format_git_output(stdout, "log", verbose)
Strategy: Stats Extraction
• Count commits: 5
• Extract stats: +142/-89
• Compress: "5 commits, +142/-89"
Filtered: 20 chars (96% reduction)
↓
Phase 5: PRINT
──────────────
if verbose > 0 {
eprintln!("Git log summary:"); // Debug
}
println!("{}", colored_output); // User output
Terminal shows: "5 commits, +142/-89 ✓"
↓
Phase 6: TRACK
──────────────
tracking::track(
original_cmd: "git log --oneline -5",
rtk_cmd: "rtk git log --oneline -5",
input: &raw_output, // 500 chars
output: &filtered // 20 chars
)
↓
SQLite INSERT:
• input_tokens: 125 (500 / 4)
• output_tokens: 5 (20 / 4)
• savings_pct: 96.0
• timestamp: now()
Database: ~/.local/share/rtk/history.db
-v (Level 1): Show debug messages
Example: eprintln!("Git log summary:");
-vv (Level 2): Show command being executed
Example: eprintln!("Executing: git log --oneline -5");
-vvv (Level 3): Show raw output before filtering
Example: eprintln!("Raw output:\n{}", stdout);
┌────────────────────────────────────────────────────────────────────────┐
│ Module Organization │
└────────────────────────────────────────────────────────────────────────┘
Category Module Commands Savings File
──────────────────────────────────────────────────────────────────────────
GIT git.rs status, diff, log 85-99% ✓
add, commit, push
branch, checkout
CODE SEARCH grep_cmd.rs grep 60-80% ✓
diff_cmd.rs diff 70-85% ✓
find_cmd.rs find 50-70% ✓
FILE OPS ls.rs ls 50-70% ✓
read.rs read 40-90% ✓
EXECUTION runner.rs err, test 60-99% ✓
summary.rs smart (heuristic) 50-80% ✓
local_llm.rs smart (LLM mode) 60-90% ✓
LOGS/DATA log_cmd.rs log 70-90% ✓
json_cmd.rs json 80-95% ✓
JS/TS STACK lint_cmd.rs lint 84% ✓
tsc_cmd.rs tsc 83% ✓
next_cmd.rs next 87% ✓
prettier_cmd.rs prettier 70% ✓
playwright_cmd.rs playwright 94% ✓
prisma_cmd.rs prisma 88% ✓
vitest_cmd.rs vitest 99.5% ✓
pnpm_cmd.rs pnpm 70-90% ✓
CONTAINERS container.rs podman, docker 60-80% ✓
VCS gh_cmd.rs gh 26-87% ✓
NETWORK wget_cmd.rs wget 85-95% ✓
DEPENDENCIES deps.rs deps 80-90% ✓
ENVIRONMENT env_cmd.rs env 60-80% ✓
SYSTEM init.rs init N/A ✓
gain.rs gain N/A ✓
config.rs (internal) N/A ✓
SHARED utils.rs Helpers N/A ✓
filter.rs Language filters N/A ✓
tracking.rs Token tracking N/A ✓
Total: 30 modules (24 command modules + 6 infrastructure modules)
- Command Modules: 24 (directly exposed to users)
- Infrastructure Modules: 6 (utils, filter, tracking, config, init, gain)
- Git Commands: 7 operations (status, diff, log, add, commit, push, branch/checkout)
- JS/TS Tooling: 8 modules (modern frontend/fullstack development)
┌────────────────────────────────────────────────────────────────────────┐
│ Filtering Strategy Taxonomy │
└────────────────────────────────────────────────────────────────────────┘
Strategy Modules Technique Reduction
──────────────────────────────────────────────────────────────────────────
1. STATS EXTRACTION
┌──────────────┐
│ Raw: 5000 │ → Count/aggregate → "3 files, +142/-89" 90-99%
│ lines │ Drop details
└──────────────┘
Used by: git status, git log, git diff, pnpm list
2. ERROR ONLY
┌──────────────┐
│ stdout+err │ → stderr only → "Error: X failed" 60-80%
│ Mixed │ Drop stdout
└──────────────┘
Used by: runner (err mode), test failures
3. GROUPING BY PATTERN
┌──────────────┐
│ 100 errors │ → Group by rule → "no-unused-vars: 23" 80-90%
│ Scattered │ Count/summarize "semi: 45"
└──────────────┘
Used by: lint, tsc, grep (group by file/rule/error code)
4. DEDUPLICATION
┌──────────────┐
│ Repeated │ → Unique + count → "[ERROR] ... (×5)" 70-85%
│ Log lines │
└──────────────┘
Used by: log_cmd (identify patterns, count occurrences)
5. STRUCTURE ONLY
┌──────────────┐
│ JSON with │ → Keys + types → {user: {...}, ...} 80-95%
│ Large values │ Strip values
└──────────────┘
Used by: json_cmd (schema extraction)
6. CODE FILTERING
┌──────────────┐
│ Source code │ → Filter by level:
│ │ • none → Keep all 0%
│ │ • minimal → Strip comments 20-40%
│ │ • aggressive → Strip bodies 60-90%
└──────────────┘
Used by: read, smart (language-aware stripping via filter.rs)
7. FAILURE FOCUS
┌──────────────┐
│ 100 tests │ → Failures only → "2 failed:" 94-99%
│ Mixed │ Hide passing " • test_auth"
└──────────────┘
Used by: vitest, playwright, runner (test mode)
8. TREE COMPRESSION
┌──────────────┐
│ Flat list │ → Tree hierarchy → "src/" 50-70%
│ 50 files │ Aggregate dirs " ├─ lib/ (12)"
└──────────────┘
Used by: ls (directory tree with counts)
9. PROGRESS FILTERING
┌──────────────┐
│ ANSI bars │ → Strip progress → "✓ Downloaded" 85-95%
│ Live updates │ Final result
└──────────────┘
Used by: wget, pnpm install (strip ANSI escape sequences)
// FilterLevel::None - Keep everything
fn calculate_total(items: &[Item]) -> i32 {
// Sum all items
items.iter().map(|i| i.value).sum()
}
// FilterLevel::Minimal - Strip comments only (20-40% reduction)
fn calculate_total(items: &[Item]) -> i32 {
items.iter().map(|i| i.value).sum()
}
// FilterLevel::Aggressive - Strip comments + function bodies (60-90% reduction)
fn calculate_total(items: &[Item]) -> i32 { ... }Language Support: Rust, Python, JavaScript, TypeScript, Go, C, C++, Java
Detection: File extension-based with fallback heuristics
┌────────────────────────────────────────────────────────────────────────┐
│ Shared Utilities Layer │
└────────────────────────────────────────────────────────────────────────┘
utils.rs provides common functionality:
┌─────────────────────────────────────────┐
│ truncate(s: &str, max: usize) → String │ Text truncation with "..."
├─────────────────────────────────────────┤
│ strip_ansi(text: &str) → String │ Remove ANSI color codes
├─────────────────────────────────────────┤
│ execute_command(cmd, args) │ Shell execution helper
│ → (stdout, stderr, exit_code) │ with error context
└─────────────────────────────────────────┘
Used by: All command modules (24 modules depend on utils.rs)
Critical Infrastructure for JS/TS Stack (8 modules)
┌────────────────────────────────────────────────────────────────────────┐
│ Package Manager Detection Flow │
└────────────────────────────────────────────────────────────────────────┘
Detection Order:
┌─────────────────────────────────────┐
│ 1. Check: pnpm-lock.yaml exists? │
│ → Yes: pnpm exec -- <tool> │
│ │
│ 2. Check: yarn.lock exists? │
│ → Yes: yarn exec -- <tool> │
│ │
│ 3. Fallback: Use npx │
│ → npx --no-install -- <tool> │
└─────────────────────────────────────┘
Example (lint_cmd.rs:50-77):
let is_pnpm = Path::new("pnpm-lock.yaml").exists();
let is_yarn = Path::new("yarn.lock").exists();
let mut cmd = if is_pnpm {
Command::new("pnpm").arg("exec").arg("--").arg("eslint")
} else if is_yarn {
Command::new("yarn").arg("exec").arg("--").arg("eslint")
} else {
Command::new("npx").arg("--no-install").arg("--").arg("eslint")
};
Affects: lint, tsc, next, prettier, playwright, prisma, vitest, pnpm
Why This Matters:
- CWD Preservation: pnpm/yarn exec preserve working directory correctly
- Monorepo Support: Works in nested package.json structures
- No Global Installs: Uses project-local dependencies only
- CI/CD Reliability: Consistent behavior across environments
┌────────────────────────────────────────────────────────────────────────┐
│ Token Tracking Architecture │
└────────────────────────────────────────────────────────────────────────┘
Flow:
1. ESTIMATION (tracking.rs:235-238)
────────────
estimate_tokens(text: &str) → usize {
(text.len() as f64 / 4.0).ceil() as usize
}
Heuristic: ~4 characters per token (GPT-style tokenization)
↓
2. CALCULATION
───────────
input_tokens = estimate_tokens(raw_output)
output_tokens = estimate_tokens(filtered_output)
saved_tokens = input_tokens - output_tokens
savings_pct = (saved / input) × 100.0
↓
3. RECORD (tracking.rs:48-59)
──────
INSERT INTO commands (
timestamp, -- RFC3339 format
original_cmd, -- "git log --oneline -5"
rtk_cmd, -- "rtk git log --oneline -5"
input_tokens, -- 125
output_tokens, -- 5
saved_tokens, -- 120
savings_pct, -- 96.0
exec_time_ms -- 15 (execution duration in milliseconds)
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
↓
4. STORAGE
───────
Database: ~/.local/share/rtk/history.db
Schema:
┌─────────────────────────────────────────┐
│ commands │
├─────────────────────────────────────────┤
│ id INTEGER PRIMARY KEY │
│ timestamp TEXT NOT NULL │
│ original_cmd TEXT NOT NULL │
│ rtk_cmd TEXT NOT NULL │
│ input_tokens INTEGER NOT NULL │
│ output_tokens INTEGER NOT NULL │
│ saved_tokens INTEGER NOT NULL │
│ savings_pct REAL NOT NULL │
│ exec_time_ms INTEGER DEFAULT 0 │
└─────────────────────────────────────────┘
Note: exec_time_ms tracks command execution duration
(added in v0.7.1, historical records default to 0)
↓
5. CLEANUP (tracking.rs:96-104)
───────
Auto-cleanup on each INSERT:
DELETE FROM commands
WHERE timestamp < datetime('now', '-90 days')
Retention: 90 days (HISTORY_DAYS constant)
↓
6. REPORTING (gain.rs)
────────
$ rtk gain
Query:
SELECT
COUNT(*) as total_commands,
SUM(saved_tokens) as total_saved,
AVG(savings_pct) as avg_savings,
SUM(exec_time_ms) as total_time_ms,
AVG(exec_time_ms) as avg_time_ms
FROM commands
WHERE timestamp > datetime('now', '-90 days')
Output:
┌──────────────────────────────────────┐
│ Token Savings Report (90 days) │
├──────────────────────────────────────┤
│ Commands executed: 1,234 │
│ Average savings: 78.5% │
│ Total tokens saved: 45,678 │
│ Total exec time: 8m50s (573ms) │
│ │
│ Top commands: │
│ • rtk git status (234 uses) │
│ • rtk lint (156 uses) │
│ • rtk test (89 uses) │
└──────────────────────────────────────┘
Note: Time column shows average execution
duration per command (added in v0.7.1)
// tracking.rs:9-11
lazy_static::lazy_static! {
static ref TRACKER: Mutex<Option<Tracker>> = Mutex::new(None);
}Design: Single-threaded execution with Mutex for future-proofing. Current State: No multi-threading, but Mutex enables safe concurrent access if needed.
┌────────────────────────────────────────────────────────────────────────┐
│ Verbosity Levels │
└────────────────────────────────────────────────────────────────────────┘
main.rs:47-49
#[arg(short, long, action = clap::ArgAction::Count, global = true)]
verbose: u8,
Levels:
┌─────────┬──────────────────────────────────────────────────────┐
│ Flag │ Behavior │
├─────────┼──────────────────────────────────────────────────────┤
│ (none) │ Compact output only │
│ -v │ + Debug messages (eprintln! statements) │
│ -vv │ + Command being executed │
│ -vvv │ + Raw output before filtering │
└─────────┴──────────────────────────────────────────────────────┘
Example (git.rs:67-69):
if verbose > 0 {
eprintln!("Git diff summary:");
}
┌────────────────────────────────────────────────────────────────────────┐
│ Ultra-Compact Mode (-u) │
└────────────────────────────────────────────────────────────────────────┘
main.rs:51-53
#[arg(short = 'u', long, global = true)]
ultra_compact: bool,
Features:
┌──────────────────────────────────────────────────────────────────────┐
│ • ASCII icons instead of words (✓ ✗ → ⚠) │
│ • Inline formatting (single-line summaries) │
│ • Maximum compression for LLM contexts │
└──────────────────────────────────────────────────────────────────────┘
Example (gh_cmd.rs:521):
if ultra_compact {
println!("✓ PR #{} merged", number);
} else {
println!("Pull request #{} successfully merged", number);
}
┌────────────────────────────────────────────────────────────────────────┐
│ Error Handling Architecture │
└────────────────────────────────────────────────────────────────────────┘
Propagation Chain:
main() → Result<()>
↓
match cli.command {
Commands::Git { args, .. } => git::run(&args, verbose)?,
...
}
↓ .context("Git command failed")
git::run(args: &[String], verbose: u8) → Result<()>
↓ .context("Failed to execute git")
git::execute_git_command() → Result<String>
↓ .context("Git process error")
Command::new("git").output()?
↓ Error occurs
anyhow::Error
↓ Bubble up through ?
main.rs error display
↓
eprintln!("Error: {:#}", err)
↓
std::process::exit(1)
┌────────────────────────────────────────────────────────────────────────┐
│ Exit Code Handling Strategy │
└────────────────────────────────────────────────────────────────────────┘
Standard Pattern (git.rs:45-48, PR #5):
let output = Command::new("git").args(args).output()?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
eprintln!("{}", stderr);
std::process::exit(output.status.code().unwrap_or(1));
}
Exit Codes:
┌─────────┬──────────────────────────────────────────────────────┐
│ Code │ Meaning │
├─────────┼──────────────────────────────────────────────────────┤
│ 0 │ Success │
│ 1 │ rtk internal error (parsing, filtering, etc.) │
│ N │ Preserved exit code from underlying tool │
│ │ (e.g., git returns 128, lint returns 1) │
└─────────┴──────────────────────────────────────────────────────┘
Why This Matters:
• CI/CD pipelines rely on exit codes to determine build success/failure
• Pre-commit hooks need accurate failure signals
• Git workflows require proper exit code propagation (PR #5 fix)
Modules with Exit Code Preservation:
• git.rs (all git commands)
• lint_cmd.rs (linter failures)
• tsc_cmd.rs (TypeScript errors)
• vitest_cmd.rs (test failures)
• playwright_cmd.rs (E2E test failures)
┌────────────────────────────────────────────────────────────────────────┐
│ Configuration Architecture │
└────────────────────────────────────────────────────────────────────────┘
1. User Settings (config.toml)
───────────────────────────
Location: ~/.config/rtk/config.toml
Format:
[general]
default_filter_level = "minimal"
enable_tracking = true
retention_days = 90
Loaded by: config.rs (main.rs:650-656)
2. LLM Integration (CLAUDE.md)
────────────────────────────
Locations:
• Global: ~/.config/rtk/CLAUDE.md
• Local: ./CLAUDE.md (project-specific)
Purpose: Instruct LLM (Claude Code) to use rtk prefix
Created by: rtk init [--global]
Template (init.rs:40-60):
# CLAUDE.md
Use `rtk` prefix for all commands:
- rtk git status
- rtk grep "pattern"
- rtk read file.rs
Benefits: 60-90% token reduction
┌────────────────────────────────────────────────────────────────────────┐
│ rtk init Workflow │
└────────────────────────────────────────────────────────────────────────┘
$ rtk init [--global]
↓
Check existing CLAUDE.md:
• --global? → ~/.config/rtk/CLAUDE.md
• else → ./CLAUDE.md
↓
├─ Exists? → Warn user, ask to overwrite
└─ Not exists? → Continue
↓
Prompt: "Initialize rtk for LLM usage? [y/N]"
↓ Yes
Write template:
┌─────────────────────────────────────┐
│ # CLAUDE.md │
│ │
│ Use `rtk` prefix for commands: │
│ - rtk git status │
│ - rtk lint │
│ - rtk test │
│ │
│ Benefits: 60-90% token reduction │
└─────────────────────────────────────┘
↓
Success: "✓ Initialized rtk for LLM integration"
// src/example_cmd.rs
use anyhow::{Context, Result};
use std::process::Command;
use crate::{tracking, utils};
/// Public entry point called by main.rs router
pub fn run(args: &[String], verbose: u8) -> Result<()> {
// 1. Execute underlying command
let raw_output = execute_command(args)?;
// 2. Apply filtering strategy
let filtered = filter_output(&raw_output, verbose);
// 3. Print result
println!("{}", filtered);
// 4. Track token savings
tracking::track(
"original_command",
"rtk command",
&raw_output,
&filtered
);
Ok(())
}
/// Execute the underlying tool
fn execute_command(args: &[String]) -> Result<String> {
let output = Command::new("tool")
.args(args)
.output()
.context("Failed to execute tool")?;
// Preserve exit codes (critical for CI/CD)
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
eprintln!("{}", stderr);
std::process::exit(output.status.code().unwrap_or(1));
}
Ok(String::from_utf8_lossy(&output.stdout).to_string())
}
/// Apply filtering strategy
fn filter_output(raw: &str, verbose: u8) -> String {
// Choose strategy: stats, grouping, deduplication, etc.
// See "Filtering Strategies" section for options
if verbose >= 3 {
eprintln!("Raw output:\n{}", raw);
}
// Apply compression logic
let compressed = compress(raw);
compressed
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_filter_output() {
let raw = "verbose output here";
let filtered = filter_output(raw, 0);
assert!(filtered.len() < raw.len());
}
}// Detect lockfiles
let is_pnpm = Path::new("pnpm-lock.yaml").exists();
let is_yarn = Path::new("yarn.lock").exists();
// Build command
let mut cmd = if is_pnpm {
Command::new("pnpm").arg("exec").arg("--").arg("eslint")
} else if is_yarn {
Command::new("yarn").arg("exec").arg("--").arg("eslint")
} else {
Command::new("npx").arg("--no-install").arg("--").arg("eslint")
};lazy_static::lazy_static! {
static ref PATTERN: Regex = Regex::new(r"ERROR:.*").unwrap();
}
// Usage: compiled once, reused across invocations
let matches: Vec<_> = PATTERN.find_iter(text).collect();if verbose > 0 {
eprintln!("Debug: Processing {} files", count);
}
if verbose >= 2 {
eprintln!("Executing: {:?}", cmd);
}
if verbose >= 3 {
eprintln!("Raw output:\n{}", raw);
}[profile.release]
opt-level = 3 # Maximum optimization
lto = true # Link-time optimization
codegen-units = 1 # Single codegen unit for better optimization
strip = true # Remove debug symbols
panic = "abort" # Smaller binary size┌────────────────────────────────────────────────────────────────────────┐
│ Performance Metrics │
└────────────────────────────────────────────────────────────────────────┘
Binary:
• Size: ~4.1 MB (stripped release build)
• Startup: ~5-10ms (cold start)
• Memory: ~2-5 MB (typical usage)
Runtime Overhead (estimated):
┌──────────────────────┬──────────────┬──────────────┐
│ Operation │ rtk Overhead │ Total Time │
├──────────────────────┼──────────────┼──────────────┤
│ rtk git status │ +8ms │ 58ms │
│ rtk grep "pattern" │ +12ms │ 145ms │
│ rtk read file.rs │ +5ms │ 15ms │
│ rtk lint │ +15ms │ 2.5s │
└──────────────────────┴──────────────┴──────────────┘
Note: Overhead measurements are estimates. Actual performance varies
by system, command complexity, and output size.
Overhead Sources:
• Clap parsing: ~2-3ms
• Command execution: ~1-2ms
• Filtering/compression: ~2-8ms (varies by strategy)
• SQLite tracking: ~1-3ms
# Development build (fast compilation, debug symbols)
cargo build
# Release build (optimized, stripped)
cargo build --release
# Check without building (fast feedback)
cargo check
# Run tests
cargo test
# Lint with clippy
cargo clippy --all-targets
# Format code
cargo fmtStep-by-step process to add a new rtk command:
touch src/mycmd.rsuse anyhow::{Context, Result};
use std::process::Command;
use crate::tracking;
pub fn run(args: &[String], verbose: u8) -> Result<()> {
// Execute underlying command
let output = Command::new("mycmd")
.args(args)
.output()
.context("Failed to execute mycmd")?;
let raw = String::from_utf8_lossy(&output.stdout);
// Apply filtering strategy
let filtered = filter(&raw, verbose);
// Print result
println!("{}", filtered);
// Track savings
tracking::track("mycmd", "rtk mycmd", &raw, &filtered);
Ok(())
}
fn filter(raw: &str, verbose: u8) -> String {
// Implement your filtering logic
raw.lines().take(10).collect::<Vec<_>>().join("\n")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_filter() {
let raw = "line1\nline2\n";
let result = filter(raw, 0);
assert!(result.contains("line1"));
}
}// Add to module declarations (alphabetically)
mod mycmd;#[derive(Subcommand)]
enum Commands {
// ... existing commands ...
/// Description of your command
Mycmd {
/// Arguments your command accepts
#[arg(trailing_var_arg = true, allow_hyphen_values = true)]
args: Vec<String>,
},
}match cli.command {
// ... existing matches ...
Commands::Mycmd { args } => {
mycmd::run(&args, verbose)?;
}
}# Build and test
cargo build
./target/debug/rtk mycmd arg1 arg2
# Run tests
cargo test mycmd::tests
# Check with clippy
cargo clippy --all-targetsUpdate CLAUDE.md:
### New Commands
**rtk mycmd** - Description of what it does
- Strategy: [stats/grouping/filtering/etc.]
- Savings: X-Y%
- Used by: [workflow description]When implementing a new command, consider:
- Filtering Strategy: Which of the 9 strategies fits best?
- Exit Code Preservation: Does your command need to preserve exit codes for CI/CD?
- Verbosity Support: Add debug output for
-v,-vv,-vvv - Error Handling: Use
.context()for meaningful error messages - Package Manager Detection: For JS/TS tools, use the standard detection pattern
- Tests: Add unit tests for filtering logic
- Token Tracking: Integrate with
tracking::track() - Documentation: Update CLAUDE.md with token savings and use cases
- Performance: ~5-15ms overhead per command (negligible for user experience)
- Safety: No runtime errors from null pointers, data races, etc.
- Single Binary: No runtime dependencies (distribute one executable)
- Cross-Platform: Works on macOS, Linux, Windows without modification
- Zero Config: No server setup, works out-of-the-box
- Lightweight: ~100KB database for 90 days of history
- Reliable: ACID compliance for data integrity
- Queryable: Rich analytics via SQL (gain report)
- Context:
.context()adds meaningful error messages throughout call chain - Ergonomic:
?operator for concise error propagation - User-Friendly: Error display shows full context chain
- Derive Macros: Less boilerplate (declarative CLI definition)
- Auto-Generated Help:
--helpgenerated automatically - Type Safety: Parse arguments directly into typed structs
- Global Flags:
-vand-uwork across all commands
- README.md: User guide, installation, examples
- CLAUDE.md: Developer documentation, module details, PR history
- Cargo.toml: Dependencies, build profiles, package metadata
- src/: Source code organized by module
- .github/workflows/: CI/CD automation (multi-platform builds, releases)
| Term | Definition |
|---|---|
| Token | Unit of text processed by LLMs (~4 characters on average) |
| Filtering | Reducing output size while preserving essential information |
| Proxy Pattern | rtk sits between user and tool, transforming output |
| Exit Code Preservation | Passing through tool's exit code for CI/CD reliability |
| Package Manager Detection | Identifying pnpm/yarn/npm to execute JS/TS tools correctly |
| Verbosity Levels | -v/-vv/-vvv for progressively more debug output |
| Ultra-Compact | -u flag for maximum compression (ASCII icons, inline format) |
Last Updated: 2026-01-29 Architecture Version: 2.0 rtk Version: 0.3.0+