Add opt-in audit logging to the RTK rewrite hook and a new `rtk hook-audit`
command to analyze the collected metrics. This provides verifiable data on
hook reliability (rewrite rate, skip reasons, top commands) instead of
relying on anecdotal claims.
- Add `_rtk_audit_log()` function to rtk-rewrite.sh (opt-in via RTK_HOOK_AUDIT=1)
- Log each invocation: timestamp | action | original_cmd | rewritten_cmd
- Actions: rewrite, skip:already_rtk, skip:heredoc, skip:no_match, skip:no_deps, skip:empty
- New `src/hook_audit_cmd.rs` module with log parser and stats display
- New `rtk hook-audit --since N` subcommand (default: last 7 days)
- 8 Rust unit tests + 7 hook bash tests for audit mode
- Make HOOK var overridable in test suite for repo-local testing
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: tee raw output to file for LLM re-read without re-run (#86)
When RTK filters command output, LLM agents lose failure details
(stack traces, assertions) and re-run the same command 2-3x. The tee
feature saves raw output to ~/.local/share/rtk/tee/ on failure and
prints a one-line hint so the agent can read the file instead.
- Add src/tee.rs: core module with tee_raw(), tee_and_hint(), rotation
- Add TeeConfig to config.rs: enabled, mode, max_files, max_file_size
- Integrate in 7 modules: cargo, runner, vitest, pytest, lint, tsc, go
- Default: failures only, skip <500 chars, 20 file rotation, 1MB cap
- Env overrides: RTK_TEE=0 (disable), RTK_TEE_DIR (custom directory)
- 14 unit tests, 352 total tests passing, zero regressions
Closes#86
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add tee.rs to ARCHITECTURE.md module count (47 modules)
CI validate-docs requires main.rs module count == ARCHITECTURE.md count.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(gain): add colored dashboard with efficiency meter and impact bars
Upgrade `rtk gain` output with rich terminal visualization:
- Colored percentage cells (green ≥70%, yellow ≥40%, red <40%)
- Efficiency meter: ASCII progress bar with savings percentage
- Impact bars: proportional block charts per command
- Styled section headers (bold green)
- Command names in bright cyan
- History tier indicators (▲/■/•)
- Dynamic column widths for clean table alignment
- KPI-style key-value layout for summary metrics
All visual features are TTY-aware via std::io::IsTerminal — output
degrades gracefully to plain text when piped or redirected.
No new dependencies (uses existing `colored` crate).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Add dashboard visualization screenshot
Shows colored terminal output of `rtk gain -p` with:
- Project-scoped token savings header
- Efficiency meter with color gradient
- Per-command table with colored Avg% and Impact bars
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Replace naive append-or-skip logic in run_claude_md_mode with
upsert_rtk_block() that handles all 4 cases:
- Added: no existing block → append
- Updated: stale block → replace in-place
- Unchanged: current block → no-op
- Malformed: opening marker without closing → warn safely
Includes 4 unit tests covering each case.
Add token-optimized filtering for `cargo nextest` output: strip
compilation noise, PASS lines, and post-summary recaps; show only
failure details and a compact summary. Extract flush_failure_block
helper to DRY up failure block collection (was repeated 4 times).
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(cargo): aggregate test output into single line (#83)
Problem: `cargo test` shows 24+ summary lines even when all pass.
An LLM only needs to know IF something failed, not 24x "ok".
Before (24 lines):
```
✓ test result: ok. 2 passed; 0 failed; ...
✓ test result: ok. 0 passed; 0 failed; ...
... (x24)
```
After (1 line):
```
✓ cargo test: 137 passed (24 suites, 1.45s)
```
Changes:
- Add AggregatedTestResult struct with regex parsing
- Merge multiple test summaries when all pass
- Format: "N passed, M ignored, P filtered out (X suites, Ys)"
- Fallback to original behavior if parsing fails
- Failures still show full details (no aggregation)
Tests: 6 new + 1 modified, covering all cases:
- Multi-suite aggregation
- Single suite (singular "suite")
- Zero tests
- With ignored/filtered out
- Failures → no aggregation (detail preserved)
- Regex fallback
Closes#83
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* feat: add Python and Go support (#88)
* feat(cargo): aggregate test output into single line (#83)
Problem: `cargo test` shows 24+ summary lines even when all pass.
An LLM only needs to know IF something failed, not 24x "ok".
Before (24 lines):
```
✓ test result: ok. 2 passed; 0 failed; ...
✓ test result: ok. 0 passed; 0 failed; ...
... (x24)
```
After (1 line):
```
✓ cargo test: 137 passed (24 suites, 1.45s)
```
Changes:
- Add AggregatedTestResult struct with regex parsing
- Merge multiple test summaries when all pass
- Format: "N passed, M ignored, P filtered out (X suites, Ys)"
- Fallback to original behavior if parsing fails
- Failures still show full details (no aggregation)
Tests: 6 new + 1 modified, covering all cases:
- Multi-suite aggregation
- Single suite (singular "suite")
- Zero tests
- With ignored/filtered out
- Failures → no aggregation (detail preserved)
- Regex fallback
Closes#83
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* feat: add Python and Go language support
Implements comprehensive support for Python and Go development tooling
with 70-90% token reduction across all commands.
Python commands (3):
- rtk ruff: Linter/formatter with JSON (check) and text (format) parsing (80%+)
- rtk pytest: Test runner with state machine text parser (90%+)
- rtk pip: Package manager with auto-detect uv (70-85%)
Go commands (4):
- rtk go test: NDJSON streaming parser for interleaved test events (90%+)
- rtk go build: Text filter showing errors only (80%)
- rtk go vet: Text filter for issues (75%)
- rtk golangci-lint: JSON parser grouped by rule (85%)
Architecture:
- Standalone Python commands (mirror lint/prettier pattern)
- Go sub-enum (mirror git/cargo pattern)
- 5 new modules: ruff_cmd, pytest_cmd, pip_cmd, go_cmd, golangci_cmd
- Hook integration in rtk-rewrite.sh for transparent rewrites
- Comprehensive tests (47 new tests, all passing)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* feat(benchmark): add Python and Go commands
Add benchmark sections for Python (ruff, pytest, pip) and Go (go test/build/vet, golangci-lint) to validate >80% token savings in CI pipeline.
Sections conditionally execute based on project markers (pyproject.toml, go.mod) and tool availability.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
* feat: make install-local.sh self-contained (#89)
- Build from source automatically instead of requiring a pre-built binary
- Default install dir to ~/.cargo/bin
- Skip rebuild when binary is up to date
- Warn if install dir is not in PATH
* chore(master): release 0.15.0 (#90)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* fix(vitest): robust JSON extraction for pnpm/dotenv prefixes (#92)
* fix(vitest): robust JSON extraction for pnpm/dotenv prefixes
Problem: RTK's vitest parser forces --reporter=json but pnpm/dotenv prepend
non-JSON text to stdout (banners, env messages), causing 100% Tier 1 failure
and useless 500-char passthrough.
Solution:
- Add extract_json_object() to parser/mod.rs (shared utility)
- Algorithm: find "numTotalTests" or first standalone {, brace-balance forward
- VitestParser now tries direct parse → extract+parse → regex → passthrough
- Replace hardcoded Command::new("pnpm") with package_manager_exec("vitest")
- Delete orphan doc comment on line 203
Impact:
- Before: 100% Tier 3 passthrough with pnpm workflows
- After: Tier 1 success with prefixes, maintains 99.5% token savings
Tests:
- 6 tests for extract_json_object (clean, pnpm, dotenv, nested, no-json, strings)
- 3 tests for VitestParser with prefixes
- All 277 tests pass
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* chore(benchmark): add vitest, pnpm, and gh commands
Add benchmarks for recently implemented commands:
- vitest run (PR #92 - JSON extraction fix)
- pnpm list/outdated (PR #6)
- gh pr list/run list (existing gh support)
These commands are now tested in CI to ensure token savings are maintained.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
* fix: improve CI reliability and hook coverage (#95)
* feat(cargo): aggregate test output into single line (#83)
Problem: `cargo test` shows 24+ summary lines even when all pass.
An LLM only needs to know IF something failed, not 24x "ok".
Before (24 lines):
```
✓ test result: ok. 2 passed; 0 failed; ...
✓ test result: ok. 0 passed; 0 failed; ...
... (x24)
```
After (1 line):
```
✓ cargo test: 137 passed (24 suites, 1.45s)
```
Changes:
- Add AggregatedTestResult struct with regex parsing
- Merge multiple test summaries when all pass
- Format: "N passed, M ignored, P filtered out (X suites, Ys)"
- Fallback to original behavior if parsing fails
- Failures still show full details (no aggregation)
Tests: 6 new + 1 modified, covering all cases:
- Multi-suite aggregation
- Single suite (singular "suite")
- Zero tests
- With ignored/filtered out
- Failures → no aggregation (detail preserved)
- Regex fallback
Closes#83
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* fix(ci): prevent Python/Go benchmark sections from being silently skipped
**Problem:**
Python and Go benchmark sections were silently skipped in CI because
the RTK repository doesn't contain pyproject.toml or go.mod files.
The sections only ran when these project files existed.
**Solution:**
1. Create temporary fixtures with minimal project structure:
- Python: pyproject.toml + sample.py + test_sample.py
- Go: go.mod + main.go + main_test.go
2. Resolve RTK to absolute path to work after cd into temp dirs
3. Install required tools in CI workflow:
- Python: ruff, pytest
- Go: stable version + golangci-lint
**Impact:**
- Python/Go sections now appear in CI benchmark output
- Self-contained fixtures ensure consistent benchmarking
- No dependency on RTK project structure
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(hooks): add missing RTK command rewrites
Add 8 missing command rewrites to rtk-rewrite.sh and rtk-suggest.sh:
- cargo check/install/fmt
- tree, find, diff
- head → rtk read (with --max-lines transformation)
- wget
Fixes BSD sed compatibility for head transformation by using literal
spaces instead of \s+ (which doesn't work on macOS).
Impact: ~18.2K tokens saved on previously missed commands discovered
by `rtk discover`.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
* chore(master): release 0.15.1 (#96)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* feat(python): add lint dispatcher + universal format command
Phase 1: Enhanced rtk lint
- Add pylint JSON2 parser (80-85% token savings)
- Add mypy text parser (75-80% token savings)
- Smart dispatcher: Python tools (pip) vs JS tools (npm)
- Reuse ruff_cmd JSON parser for rtk lint ruff
Phase 2: New rtk format command
- Universal formatter: black/ruff/prettier
- Auto-detect from pyproject.toml/package.json
- Implement black output parser (70-85% savings)
- Reuse existing prettier/ruff formatters
Phase 3: Hook integration
- Auto-rewrite: pylint → rtk lint pylint
- Auto-rewrite: mypy → rtk lint mypy
- Auto-rewrite: black --check → rtk format black
Files changed:
- src/lint_cmd.rs: +454 lines (pylint/mypy parsers, dispatcher)
- src/format_cmd.rs: +386 lines (NEW - universal formatter)
- src/ruff_cmd.rs: Export filter functions as pub
- src/prettier_cmd.rs: Export filter_prettier_output as pub
- src/main.rs: Add Commands::Format + routing
- hooks/rtk-rewrite.sh: Add Python tool rewrite rules
Testing: 10 new unit tests, all 313 tests passing
Impact: 80-90% token savings on Python workflows
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: Michael Coen <mhcoen@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* fix: prevent UTF-8 panics on multi-byte characters (Thai, emoji, CJK)
Replace all byte-indexed string slicing (`&s[..n]`) with char-aware
operations across 10 locations in 7 files. Rust strings are UTF-8, so
byte slicing can land mid-character on Thai (3 bytes), emoji (4 bytes),
or CJK text and panic at runtime.
Fixes applied:
- git.rs: filter_log_output, format_status_output
- log_cmd.rs: error/warning message truncation (2 locations)
- env_cmd.rs: long value display, mask_value
- parser/mod.rs: truncate_output
- grep_cmd.rs: clean_line (pattern context + fallback truncation)
- wget_cmd.rs: compact_url, truncate_line, parse_error
Also adds safe_char_boundary() utility and 20 regression tests covering
Thai, emoji, and CJK input across all affected modules.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: collect chars once in compact_url to avoid redundant iteration
Address review feedback: collect chars into Vec once instead of
calling .chars() multiple times. Also fixes byte-vs-char length check.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: remove unused safe_char_boundary function and tests
Address review: function was defined but never called anywhere.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: convert remaining is_char_boundary to full .chars() approach
Address review: use consistent .chars() everywhere instead of
mixing byte-based is_char_boundary with char-based operations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(cargo): aggregate test output into single line (#83)
Problem: `cargo test` shows 24+ summary lines even when all pass.
An LLM only needs to know IF something failed, not 24x "ok".
Before (24 lines):
```
✓ test result: ok. 2 passed; 0 failed; ...
✓ test result: ok. 0 passed; 0 failed; ...
... (x24)
```
After (1 line):
```
✓ cargo test: 137 passed (24 suites, 1.45s)
```
Changes:
- Add AggregatedTestResult struct with regex parsing
- Merge multiple test summaries when all pass
- Format: "N passed, M ignored, P filtered out (X suites, Ys)"
- Fallback to original behavior if parsing fails
- Failures still show full details (no aggregation)
Tests: 6 new + 1 modified, covering all cases:
- Multi-suite aggregation
- Single suite (singular "suite")
- Zero tests
- With ignored/filtered out
- Failures → no aggregation (detail preserved)
- Regex fallback
Closes#83
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* feat: add Python and Go language support
Implements comprehensive support for Python and Go development tooling
with 70-90% token reduction across all commands.
Python commands (3):
- rtk ruff: Linter/formatter with JSON (check) and text (format) parsing (80%+)
- rtk pytest: Test runner with state machine text parser (90%+)
- rtk pip: Package manager with auto-detect uv (70-85%)
Go commands (4):
- rtk go test: NDJSON streaming parser for interleaved test events (90%+)
- rtk go build: Text filter showing errors only (80%)
- rtk go vet: Text filter for issues (75%)
- rtk golangci-lint: JSON parser grouped by rule (85%)
Architecture:
- Standalone Python commands (mirror lint/prettier pattern)
- Go sub-enum (mirror git/cargo pattern)
- 5 new modules: ruff_cmd, pytest_cmd, pip_cmd, go_cmd, golangci_cmd
- Hook integration in rtk-rewrite.sh for transparent rewrites
- Comprehensive tests (47 new tests, all passing)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* feat(benchmark): add Python and Go commands
Add benchmark sections for Python (ruff, pytest, pip) and Go (go test/build/vet, golangci-lint) to validate >80% token savings in CI pipeline.
Sections conditionally execute based on project markers (pyproject.toml, go.mod) and tool availability.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Problem: `cargo test` shows 24+ summary lines even when all pass.
An LLM only needs to know IF something failed, not 24x "ok".
Before (24 lines):
```
✓ test result: ok. 2 passed; 0 failed; ...
✓ test result: ok. 0 passed; 0 failed; ...
... (x24)
```
After (1 line):
```
✓ cargo test: 137 passed (24 suites, 1.45s)
```
Changes:
- Add AggregatedTestResult struct with regex parsing
- Merge multiple test summaries when all pass
- Format: "N passed, M ignored, P filtered out (X suites, Ys)"
- Fallback to original behavior if parsing fails
- Failures still show full details (no aggregation)
Tests: 6 new + 1 modified, covering all cases:
- Multi-suite aggregation
- Single suite (singular "suite")
- Zero tests
- With ignored/filtered out
- Failures → no aggregation (detail preserved)
- Regex fallback
Closes#83
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Strip dep compilation, downloading, locking noise from cargo install output.
Keep only installed/replaced/error lines with compact summary format.
Closes#69
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
## Code Quality Improvements
**Extracted helper functions:**
- `prepare_hook_paths()`: Prepare hook directory and paths (DRY)
- `ensure_hook_installed()`: Idempotent hook installation with chmod
- `write_if_changed()`: Generic file write with idempotence
**Before (duplicated):**
- Hook path logic repeated in default_mode + hook_only_mode
- Hook write logic repeated (lost idempotence in hook-only)
- RTK.md write logic duplicated
**After (DRY):**
- Single source of truth for each operation
- Consistent idempotence across all modes
- Reusable helpers for future file operations
## Error Handling Enhancements
**Improved error context:**
- `.with_context(|| format!("Failed to write hook to {}", path))`
- All fs operations now include the path that failed
- Migration warnings include line numbers and actionable steps
**Better Windows messaging:**
- Clear explanation of platform limitations
- Explicit fallback behavior
## API Improvements
**Idiomatic Rust:**
- `&PathBuf` → `&Path` for all function parameters
- Pattern match tuple instead of if/else chain
- `anyhow::bail!` for Windows hook-only error
## Impact
- **Maintainability**: Single place to update hook/file logic
- **Debuggability**: Error messages show exact paths
- **Robustness**: Consistent idempotence prevents conflicts
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Problem:
- `rtk git add -A` failed with "unexpected argument '-A' found"
- Git flags like -A, -p, --all were rejected by Clap parser
- Only filenames could be passed to `git add`
Solution:
- Add `allow_hyphen_values = true` to Add command args (following PR #5 pattern)
- Change Add enum variant from `Add { files }` to `Add` (unified with other git commands)
- Modify run_add() to accept args slice and pass all arguments to git
- Add exit code propagation for consistency with other git commands
Impact:
- All native git add flags now work: -A, -p, --all, --update, etc.
- Maintains RTK compact output format ("ok ✓ 2 files changed, ...")
- Preserves backward compatibility (no args defaults to ".")
Testing:
- Manual: `rtk git add -A` works correctly
- All existing tests pass (154 passed)
- Smoke tests unchanged (git add not included in test-all.sh)
Fixes: Argument parsing error for git add with native flags
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
The previous implementation grouped errors by error code within each
file, showing only the first message when multiple errors shared the
same code (e.g. TS2322). This hid critical debugging information and
forced users to bypass rtk entirely.
Changes:
- Show each error individually with line number and full message
- Capture and display tsc continuation/context lines
- Increase message truncation from 60 to 120 chars
- Remove artificial limits (was: 3 codes/file, 10 files max)
- Compact top-codes summary to a single line
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- ls: rewrite to strip permissions/owner/group/dates, show only
names with dir/ suffix and human sizes. Properly handle flag
ordering (path -l), -lh, multi-paths, --all.
- discover: remove orphan diff pattern that caused index out of
bounds panic (PATTERNS had 22 entries vs RULES 21)
- benchmark: add 8 ls test cases
- test-all: add 5 ls smoke tests
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove rtk diff from docs, tests, discover registry (command exists
but was over-promoted)
- docker ps: include container ID in compact output
- diff_cmd: widen truncation from 35 to 70 chars per side
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- find: replace fd/find subprocess with ignore::WalkBuilder for native
.gitignore support, fix "." pattern, fix --max file counting
- json: add stdin support via "-" path (same pattern as read)
- benchmark: one-line-per-test format with icons for CI logs,
local debug files only when not in CI, remove md upload/PR steps
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add ability to read from stdin using the special path "-", following
Unix conventions. Also fixes a pre-existing bug in git.rs push output.
Changes:
- src/main.rs: Check for Path::new("-") and route to run_stdin()
- src/read.rs: Add run_stdin() function for stdin processing
- src/read.rs: Use Language::Unknown for stdin (no file extension)
- src/git.rs: Fix unused format! result in push command
- Unit test: test_stdin_support_signature verifies function exists
- Smoke tests: 1 assertion for stdin pipe
Usage:
echo "code" | rtk read -
cat file.txt | rtk read - --level aggressive
somecommand | rtk read - -n
Note: Stdin detection requires explicit "-" path to avoid hanging.
No automatic stdin detection is performed.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add support for passing additional ripgrep arguments to rtk grep
while preserving RTK's token-optimized output formatting.
Changes:
- src/main.rs: Add extra_args field to Grep command variant
- src/main.rs: Pass extra_args to grep_cmd::run()
- src/grep_cmd.rs: Add extra_args parameter to run() signature
- src/grep_cmd.rs: Inject extra_args into ripgrep command
- Unit test: test_extra_args_accepted verifies parameter exists
- Smoke tests: 2 assertions for -i and -A flags
Usage note: Extra args must come AFTER pattern and path:
✓ rtk grep "pattern" src/ -i
✗ rtk grep "pattern" -i (clap interprets -i as path)
This enables full ripgrep functionality (case-insensitive, context
lines, word boundaries, globs) while maintaining RTK's compact output.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add external_subcommand variant to PnpmCommands enum to handle
unsupported pnpm operations by passing them through directly.
Changes:
- src/pnpm_cmd.rs: Add run_passthrough() function with OsString support
- src/pnpm_cmd.rs: Add OsString import
- src/main.rs: Add PnpmCommands::Other variant with external_subcommand
- src/main.rs: Add match arm for pnpm passthrough
- Unit test: test_run_passthrough_accepts_args verifies signature
- Smoke tests: Conditional test for pnpm help if pnpm is available
This maintains compatibility with all pnpm commands while preserving
RTK's token-optimized versions for list/outdated/install.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add external_subcommand variant to GitCommands enum to handle
unsupported git operations (tag, remote, rev-parse, etc.) by
passing them through directly to git.
Changes:
- src/git.rs: Add run_passthrough() function with OsString support
- src/main.rs: Add GitCommands::Other variant with external_subcommand
- src/main.rs: Add OsString import and match arm for passthrough
- Unit test: test_run_passthrough_accepts_args verifies signature
- Smoke tests: 3 new assertions for tag, remote, rev-parse
This preserves all git functionality while maintaining RTK's
token-optimized commands for supported operations.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Changes:
- Fix discover issues URL: FlorianBruniaux → rtk-ai upstream repo
- Document suggest hook pattern as non-intrusive alternative to auto-rewrite
- Add rtk-suggest.sh template with systemMessage strategy
- Provide comparison table and setup instructions
The suggest hook emits system reminders instead of rewriting commands,
giving Claude Code explicit visibility into rtk alternatives while
preserving user control over execution decisions.
Use cases:
- Learning rtk patterns with visibility into rewrite logic
- Auditing command choices without forced adoption
- Debugging workflows requiring exact command preservation
- User preference for explicit control over transparency
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Previously, `rtk git status` was the only git subcommand that rejected
all arguments. This fix aligns it with other git subcommands (diff, log,
show, etc.) by accepting native git flags.
Changes:
- Extract format_status_output() as pure testable function
- Add args variant to Clap Status command with trailing_var_arg
- Modify run_status() to accept args parameter
- Passthrough mode: if user provides flags (--short, -s, --porcelain),
forward directly to git without RTK formatting
- Default mode: no flags = RTK compact formatting (unchanged behavior)
- Add 5 unit tests for format_status_output (clean, modified, untracked,
mixed, truncation)
- Add 4 smoke tests for flag passthrough (--short, -s, --porcelain)
Test results:
- 151 unit tests passed (5 new)
- 69 smoke tests passed (4 new for status flags)
Fixes the issue where commands like `rtk git status --short` were
rejected with "unexpected argument" error.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add exec_time_ms column to SQLite schema and track execution time
for all rtk commands. Display time metrics in gain summary, daily/
weekly/monthly breakdowns, and JSON/CSV exports.
Changes:
- tracking.rs: Add exec_time_ms column, TimedExecution struct
- display_helpers.rs: Add format_duration() helper, update tables
- gain.rs: Display total/avg exec time in summary and by-command
- All command modules: Apply TimedExecution timer wrapper
- Exports: Include total_time_ms and avg_time_ms in JSON/CSV
Example output:
Total exec time: 24.6s (avg 34ms)
rtk cargo test 7 -86.1% 349ms avg
rtk git status 111 -84.1% 1ms avg
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
BREAKING CHANGE: Removes --depth, --format (tree/flat/json) flags
Before: `rtk ls` was a reimplementation using WalkBuilder that didn't
support native ls flags like -l, -a, -h, -R.
After: `rtk ls` proxies to native ls, supporting all flags:
- `rtk ls -la` works
- `rtk ls -alh` works
- `rtk ls -R src/` works
- Default: `-la` when no args
Token optimization: filters "total X" line from output.
This aligns with rtk philosophy: proxy and filter, don't reimplement.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
rtk git push and rtk git pull now accept trailing arguments and forward
them to git. Fixes the auto-rewrite hook failing on commands like
`git push -u origin feat/branch`.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- New `rtk discover` command scans Claude Code JSONL session history to
identify missed RTK savings and suggest unhandled commands for issues.
Modular architecture: registry (RegexSet classification), provider
(SessionProvider trait + ClaudeProvider), report (text/json formatting).
- New PreToolUse auto-rewrite hook transparently intercepts Bash commands
and rewrites them to rtk equivalents before execution, ensuring 100%
adoption across all conversations including subagents.
- New `rtk git show` command with compact output: one-line commit summary
+ stat + compacted diff (reuses compact_diff from git diff).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix test_analyze_logs: use normalizable paths instead of distinct IPs
- Fix test_filter_outdated: match real pnpm outdated output format
- Fix test_filter_ansi_colors: add missing Tests line for stats parsing
- Add .claude/skills/rtk-tdd/ with Red-Green-Refactor workflow
- Add testing-patterns.md reference with untested modules backlog
- Update CLAUDE.md Testing Strategy with TDD mandate and pre-commit gate
- Add 17 tests to diff_cmd.rs (similarity, truncate, compute_diff, condense)
- Test suite: 102/105 → 122/122
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Execute curl -s, auto-detect JSON responses
- JSON output piped through filter_json_string() for schema view
- Non-JSON output truncated to 30 lines with byte count
New module: src/curl_cmd.rs with 4 unit tests
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- git branch: compact listing (current/local/remote-only)
- git fetch: "ok fetched (N new refs)" confirmation
- git stash: list/show/pop/apply/drop with compact output
- git worktree: compact listing with home dir abbreviation
4 new tests in git.rs
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>