* feat: add anonymous telemetry ping (1/day, opt-out)
Fire-and-forget daily ping to track active installs for BPI metrics.
- SHA-256 device hash (hostname:user), no PII
- Opt-out: RTK_TELEMETRY_DISABLED=1 or config.toml [telemetry] enabled=false
- Token injected at compile time via option_env!, not in source
- 23h throttle via marker file, 2s timeout, non-blocking thread
* ci: inject RTK_TELEMETRY_TOKEN at build time in release workflow
All 3 build jobs (binary, DEB, RPM) now receive the token from
GitHub secrets so option_env!() compiles it into release binaries.
* refactor: externalize telemetry URL via option_env!(RTK_TELEMETRY_URL)
URL and token are both injected at compile time — no hardcoded
server address in source code. Builds without the env var simply
skip telemetry silently.
* feat: add `rtk rewrite` command — single source of truth for hook rewrites
Implements `rtk rewrite <cmd>` as the canonical rewrite engine for all
LLM hook integrations (Claude Code, Gemini CLI, future tools).
- Add `rewrite_prefixes` field to `RtkRule` in discover/registry.rs
- Add public `rewrite_command()` with compound command support (&&, ||, ;, |)
- Add `rewrite_segment()`, `rewrite_compound()`, `strip_word_prefix()` helpers
- Handle already-rtk commands (exit 0, identical output)
- Handle unsupported/ignored commands (exit 1, no output)
- Add 20 unit tests covering all branches and edge cases
- Create `src/rewrite_cmd.rs` thin CLI wrapper
- Register `Commands::Rewrite` in main.rs
- Simplify `.claude/hooks/rtk-rewrite.sh` from 357 → 60 lines
Hooks no longer need duplicate mapping logic — a single
`REWRITTEN=$(rtk rewrite "$CMD") || exit 0` handles everything.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: fix version references and module count for 0.22.2
- README.md, CLAUDE.md, ARCHITECTURE.md: 0.20.1 → 0.22.2
- ARCHITECTURE.md: module count 48 → 51 (added rewrite_cmd + 2 from master)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* ci: update hook coverage check to verify registry (not hook script)
Since PR #241, the hook delegates to `rtk rewrite` — command mappings
live in src/discover/registry.rs, not the bash hook script.
Update the "Verify hook coverage" CI step to:
- Check that the hook calls `rtk rewrite` (new architecture)
- Check that registry.rs has rewrite_prefixes for all Python/Go commands
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: support single `&` background operator in compound rewrites
Per feedback from @xDelph: AI agents increasingly use `cmd1 & cmd2`
for parallel execution. This commit adds support alongside existing
`&&`, `||`, `;`, and `|` operators.
Changes:
- rewrite_compound: add match arm for single `&` (after `&&` check)
- rewrite_command: add `" & "` to has_compound detection
- init: show "installed/updated" vs "already up to date" so users
know whether rtk init changed the hook on re-run
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: add Python/Go commands to rewrite registry
Add `ruff`, `pytest`, `pip`, `go`, and `golangci-lint` to both
PATTERNS and RULES in registry.rs so the CI coverage check passes
and `rtk rewrite` correctly identifies these commands.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: update version reference to 0.23.0 in README
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: update version reference to 0.23.0 in CLAUDE.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: update version and module count to 0.23.0/52 in ARCHITECTURE.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: address P0 review feedback on rtk-rewrite PR
P0.1 - Replace 218-line bash hook with 58-line thin delegating hook.
All rewrite logic now lives exclusively in `rtk rewrite` (Rust registry).
`rtk init` installs the thin hook via include_str!.
P0.2 - Fix `head -20 file` crash at runtime.
Generic prefix replacement produced `rtk read -20 file` (invalid clap args).
Now translates `head -N file` → `rtk read file --max-lines N` and skips
unsupported head flags (e.g. -c) by returning exit 1.
P0.3 - Add version guard in hook for rtk < 0.23.0.
Prints a warning to stderr instead of silently doing nothing.
Also adds missing registry entries vs old hook:
- gh release, cargo install
- docker run/exec/build, kubectl describe/apply
- tree, diff
474 tests pass, 0 clippy warnings.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* style: cargo fmt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* refactor(discover): extract rules/patterns into rules.rs
Per aeppling review: registry.rs was too large (~1500 lines).
Extract all static data into src/discover/rules.rs:
- RtkRule struct (with pub fields)
- PATTERNS const array
- RULES const array
- IGNORED_PREFIXES and IGNORED_EXACT const arrays
registry.rs now contains only logic + tests.
rules.rs is the single place to add a new command mapping.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: update version reference to 0.24.0 in README
* docs: update version references to 0.24.0 in CLAUDE.md and ARCHITECTURE.md
* fix(discover): add aws and psql to rewrite registry
rtk aws and rtk psql modules exist since PR #216 but were missing
from the registry rules — rewrite was silently skipping them.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test(discover): exhaustive regression tests for rewrite registry
Cover all command categories added in PR #241 and missing from
the previous test suite:
- aws / psql (PR #216 modules, gap detected during non-reg run)
- Python: ruff, pytest, python -m pytest, pip, uv pip
- Go: go test/build/vet, golangci-lint
- JS/TS: vitest, pnpm vitest, prisma, prettier, pnpm list
- Compound operators: || and ; rewrites, 4-segment chains,
mixed supported/unsupported segments, all-unsupported → None
- sudo prefix rewrite, env var prefix rewrite
- find with native flags
- Registry invariants: PATTERNS/RULES aligned, all rules valid,
all patterns are valid regex
Before: 559 tests. After: 607 tests.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(migration): document breaking change + detect outdated hook in rtk config
CHANGELOG [Unreleased]:
- Migration required: rtk init --global needed after upgrade
- Documents upgrade path and explains no immediate breakage
rtk init --show / rtk config now detects old hook (inline if-else)
vs new thin delegator (rtk rewrite) and prints actionable warning:
⚠️ Hook: ~/.claude/hooks/rtk-rewrite.sh (outdated — inline logic, not thin delegator)
→ Run `rtk init --global` to upgrade to the single source of truth hook
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: update hook references for thin delegator (0.24.0)
- ARCHITECTURE.md: fix hook description (shell script → thin delegator)
- INSTALL.md: add upgrade path for old hook users (pre-0.24 breaking change)
- SECURITY.md: add registry.rs + hook files to Tier 1 critical files
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs(arch): fix module count 52→55, add aws/psql/rewrite to module map
Adds aws_cmd, psql_cmd (PR #216) and rewrite_cmd (this PR) to the
Complete Module Map table. Updates total from 52 to 55 to match main.rs.
Fixes CI validate-docs.sh module count mismatch.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* ci: fix hook coverage check to search rules.rs instead of registry.rs
After the PR #241 refactor, rewrite_prefixes constants moved from
registry.rs to rules.rs. Update grep to search the whole discover/
directory so it finds them in the right file.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
The current x86_64-unknown-linux-gnu release binary dynamically links against glibc, which causes failures on systems with an older glibc version:
rtk: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.39' not found (required by rtk)
Replace the x86_64-unknown-linux-gnu build target with x86_64-unknown-linux-musl, producing a fully statically-linked binary with no libc dependency.
Fixesrtk-ai/rtk#265 - binary fails on systems with old glibc.
* 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>
- Cargo.toml: add homepage field
- README.md: add website/github/install links
- Formula/rtk.rb: update homepage to website
- release.yml: update homepage and docs link in formula template
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Replaces the commented-out TODO homebrew section with a working
automation modeled on rtk-ai/vox's release pipeline.
On each release, the new homebrew job:
1. Downloads checksums.txt from the just-published release
2. Parses sha256 for all 4 platforms (macOS/Linux × Intel/ARM)
3. Generates the formula with correct version and hashes
4. Pushes to rtk-ai/homebrew-tap via GitHub API
Requires HOMEBREW_TAP_TOKEN org secret (already used by vox).
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Closes#73
Three issues prevented release-please from uploading build artifacts:
1. Upload steps had `if: github.event_name == 'workflow_call'` conditions
that evaluated to false when called from release-please (event_name
reflects the caller's `push` event, not `workflow_call`)
2. Missing `secrets: inherit` in release-please.yml workflow_call
3. Dead `on: release: published` trigger (GITHUB_TOKEN actions can't
trigger other workflows)
Fix aligned with working rtk-ai/vox pipeline:
- Remove conditional `if` on upload step (always upload)
- Simplify version detection with `inputs.tag` fallback
- Remove dead `release: published` trigger
- Add `secrets: inherit` to workflow_call
Co-Authored-By: Claude Opus 4.6 <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>
Fixes#27
Tags created by GITHUB_TOKEN don't trigger other workflows. This change
makes release-please call release.yml directly via workflow_call after
creating a release.
Changes:
- release.yml: Add workflow_call trigger with tag input
- release.yml: Handle workflow_call in version detection
- release.yml: Upload assets for workflow_call events
- release-please.yml: Add build-release job that calls release.yml
- release-please.yml: update-latest-tag now waits for build to complete
This approach:
- Requires no PAT/secrets
- Keeps workflows separate and maintainable
- Uses workflow_call (cleaner than workflow_dispatch)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1. CRITICAL: Fix 'latest' tag creation after releases
- Move update-latest-tag job from release.yml to release-please.yml
- release-please creates tags via API (no push event) → must run in same workflow
- Job now conditional on release_created output
2. IMPORTANT: Add npx fallback for ccusage + improve message
- Check binary in PATH first, fallback to 'npx ccusage'
- Updated message: "npm i -g ccusage (or use npx ccusage)"
- Consistent with other JS tooling (next_cmd, tsc_cmd, prettier_cmd)
3. PROCESS: Slow down version bumps with release-please config
- Add release-please-config.json with bump-patch-for-minor-pre-major
- In 0.x versions: feat: → patch bump instead of minor
- Prevents rapid version inflation (0.3.1 → 0.5.0 in 21h)
Fixes issues raised by Patrick after PR #21 merge.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add automated workflow step to update the 'latest' tag after each
successful release. This ensures 'latest' always points to the most
recent stable version without manual intervention.
The new job:
- Runs after successful release completion
- Updates 'latest' tag to point to the new semver tag
- Uses force push to move the tag reference
- Includes version info in tag annotation message
Benefits:
- Install scripts can reliably use /releases/latest/download/
- No manual tag management needed
- Consistent reference for "current stable" across platforms
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
## Release automation
- Add release-please workflow for automatic semantic versioning
- Configure release.yml to only trigger on tags (avoid double-release)
## Benchmark automation
- Extend benchmark.yml with README auto-update
- Add permissions for contents and pull-requests writes
- Auto-create PR with updated metrics via peter-evans/create-pull-request
- Add scripts/update-readme-metrics.sh for CI integration
## Verification
- ✅ Workflows ready for CI/CD pipeline
- ✅ No breaking changes to existing functionality
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add SQLite tracking for all commands (90-day history)
- Add rtk gain command with ASCII graph visualization
- Add config.rs for TOML configuration support
- Integrate tracking in all command modules
- Add CI/CD workflow for multi-platform releases (deb, rpm, win, mac)
- Add LICENSE file and improve .gitignore