Files

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

90 lines
2.5 KiB
TOML
Raw Permalink Normal View History

[package]
name = "rtk"
2026-09-04 12:42:59 +00:00
version = "0.48.0"
chore: migrate to Rust edition 2024 Bump edition 2021 -> 2024. rust-version stays at 1.91, already well above the 1.85 floor the edition needs; docs/guide/resources/troubleshooting.md still claimed 1.70+, which is where a failed `cargo install --git` lands. Four things the edition forces: - std::env::{set_var,remove_var} are unsafe in 2024 with no safe std replacement. Rather than wrap the test call sites in unsafe -- which the crate denies and .semgrep.yml flags -- route them through temp-env, a dev-only dependency whose closure API is safe and which restores the previous value even when the body panics. The hand-rolled CLAUDE_DIR_LOCK and PI_DIR_LOCK guards existed only to serialise those mutations and are now redundant; CWD_LOCK and TEST_ENV_LOCK stay, they order more than the env var itself. - unsafe_op_in_unsafe_fn is on by default, so the libc calls in the proxy signal handler and in stream.rs's relay handler need explicit unsafe blocks, scoped to the libc calls themselves. - `gen` is a reserved keyword, so the closure by that name in diff_cmd.rs becomes make_lines. - Tightened tail-expression temporary scopes let clippy prove the binding in setup_test_env is inlinable, so let_and_return now fires there. if_let_rescope changes when the scrutinee temporary drops in an if let/else. The two sites in show_claude_config take cargo fix --edition's match rewrite, which keeps the 2021 drop timing. rustfmt.toml is kept rather than dropped: cargo fmt passes --edition from Cargo.toml, but a bare rustfmt invocation has no crate context and falls back to edition 2015, which cannot parse the let-chains the next commit introduces. Pinning it there keeps format-on-save and pre-commit hooks in agreement with CI. clippy::collapsible_if is allowed crate-wide for now; the follow-up commit adopts let-chains and removes the allow. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-31 01:19:25 +02:00
edition = "2024"
rust-version = "1.91"
authors = ["Patrick Szymkowiak"]
description = "Rust Token Killer - High-performance CLI proxy to minimize LLM token consumption"
license = "Apache-2.0"
homepage = "https://www.rtk-ai.app"
repository = "https://github.com/rtk-ai/rtk"
readme = "README.md"
keywords = ["cli", "llm", "token", "filter", "productivity"]
categories = ["command-line-utilities", "development-tools"]
[dependencies]
clap = { version = "4", features = ["derive"] }
anyhow = "1.0"
fix(core): decode per line, cover OEM code pages, and centralize on exec_capture Addresses the inline review on #2717. decode_process_output - Decode a line at a time instead of reinterpreting the whole buffer at the first bad byte. Valid UTF-8 lines keep their bytes; only lines that fail UTF-8 validation go through the code page, so one stray byte no longer mangles output that was almost entirely UTF-8. The line is the unit because a byte run is not one: GB18030's four-byte sequences embed bytes in the ASCII digit range, so any rule that ends a run below 0x80 splits them. \n cannot appear as a trail byte in any encoding handled here, and a process does not switch encoding mid-line. - A code page result is only accepted when it decodes cleanly, so a UTF-8 line with a corrupt byte falls back to lossy UTF-8 rather than mojibake. - Replace the hand-written code page table with the codepage crate, as suggested. That also fixes 54936, which was mapped to GBK and now correctly resolves to gb18030. - Add oem_cp for the legacy OEM/DOS pages (437, 850, 852, …) that plain cmd.exe still defaults to in many locales. encoding_rs implements only WHATWG encodings, so codepage alone returns None for them. - Fall back to GetACP when GetConsoleOutputCP reports no console, which is the piped case rtk normally runs in, and warn once instead of falling back to lossy silently. - Cache the code page lookup in a OnceLock. - The mapping and the walk take the code page as a parameter, so they are compiled and unit-tested on every platform rather than only Windows. Call sites - Route the remaining production sites through stream::exec_capture and exec_capture_stdin rather than decoding at each one, so future callers inherit decoding. git commit keeps inherited stdin via the _stdin variant. Test-only sites go back to from_utf8_lossy: they assert on rtk's own UTF-8 output, where a console code page has no meaning. - Decode the streamed path (read_lines_lossy) too — the OEM/ANSI lines its comment describes were still going straight to U+FFFD. - curl keeps its body on from_utf8_lossy: a response body is a network payload whose encoding comes from the HTTP charset, not the local console, and non-UTF-8 bodies already take the binary passthrough for #1087. Only curl's own stderr is code page decoded. git commit summary parsing - parse_commit_output sliced from byte 1, which panics when the first line starts with a multi-byte character — git prints hook output before its summary, and a lossily decoded line starts with a multi-byte U+FFFD. Locate the bracket pair with find instead, so both indices are character boundaries. Verified: unit tests for the walk, GBK, gb18030, CP437/850, mixed lines, truncated input and every byte value; a test pinning that output without a code page stays byte-identical to from_utf8_lossy; and the Windows-only lookup cross-compiled for x86_64-pc-windows-msvc.
2026-08-15 08:20:24 +03:00
# Console code page decoding for child-process output. Kept off the
# cfg(windows) target so the mapping and the incremental UTF-8 walk stay
# compiled — and unit-tested — on every platform; only the code page *lookup*
# is Windows-specific. codepage covers the ANSI/DBCS pages encoding_rs
# implements, oem_cp the legacy OEM/DOS pages (437, 850, …) it does not.
encoding_rs = "0.8"
codepage = "0.1"
oem_cp = "2"
ignore = "0.4"
walkdir = "2"
regex = "1"
serde = { version = "1", features = ["derive"] }
feat(init): auto-patch settings.json for frictionless hook installation ## Summary Eliminates manual settings.json setup friction by automating hook registration with safety (backup, atomic writes, idempotency). ## Changes ### Core Features - **Auto-patch**: Default `rtk init -g` prompts to patch settings.json [y/N] - **CLI flags**: `--auto-patch` (no prompt), `--no-patch` (manual), `--uninstall` (full cleanup) - **Safety**: Automatic backup to `settings.json.bak` before modification - **Idempotency**: Detects existing hook, skips modification - **Status check**: `rtk init --show` now displays settings.json registration ### Implementation - New types: `PatchMode` (Ask/Auto/Skip), `PatchResult` (tracking outcomes) - New functions in `src/init.rs`: - `hook_already_present()` - Detects RTK hook via substring match - `insert_hook_entry()` - Deep-merges hook using idiomatic `entry()` API - `atomic_write()` - Crash-safe writes with tempfile - `patch_settings_json()` - Main orchestrator - `uninstall()` - Complete cleanup (hook, RTK.md, settings.json) - Modified functions: `run()`, `run_default_mode()`, `run_hook_only_mode()`, `show_config()` ### Code Quality Improvements - Refactored `insert_hook_entry()` to use Rust `entry()` API (no manual unwraps) - Simplified `hook_already_present()` with iterator chains (3x shorter) - Improved error messages with file paths and actionable hints - Fixed string allocation (to_str() vs to_string()) ### Dependencies - Added `preserve_order` feature to `serde_json` (key order preservation) - Moved `tempfile` to production dependencies (atomic writes) ### Documentation - **README.md**: Updated Quick Install, added Installation Flags, Uninstalling, Troubleshooting, What Are Hooks sections - **INSTALL.md**: Updated Recommended Setup, added Common User Flows, Uninstalling sections - **CHANGELOG.md**: Documented new feature under Unreleased ### Testing - 11 new unit tests for hook detection, insertion, atomic writes, cleanup - All 249 tests passing - Smoke tested: install, idempotency, show, uninstall ## User Impact **Before**: Users had to manually copy JSON snippet to settings.json **After**: Single command with prompt, automatic backup, clean uninstall ## Breaking Changes None. Backwards compatible - manual setup still works via `--no-patch`. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-07 16:12:40 +01:00
serde_json = { version = "1", features = ["preserve_order"] }
2026-07-28 01:16:32 +09:00
colored = "3"
dirs = "5"
rusqlite = { version = "0.31", features = ["bundled"] }
toml = "0.8"
toml_edit = "0.22"
chrono = "0.4"
feat(init): auto-patch settings.json for frictionless hook installation ## Summary Eliminates manual settings.json setup friction by automating hook registration with safety (backup, atomic writes, idempotency). ## Changes ### Core Features - **Auto-patch**: Default `rtk init -g` prompts to patch settings.json [y/N] - **CLI flags**: `--auto-patch` (no prompt), `--no-patch` (manual), `--uninstall` (full cleanup) - **Safety**: Automatic backup to `settings.json.bak` before modification - **Idempotency**: Detects existing hook, skips modification - **Status check**: `rtk init --show` now displays settings.json registration ### Implementation - New types: `PatchMode` (Ask/Auto/Skip), `PatchResult` (tracking outcomes) - New functions in `src/init.rs`: - `hook_already_present()` - Detects RTK hook via substring match - `insert_hook_entry()` - Deep-merges hook using idiomatic `entry()` API - `atomic_write()` - Crash-safe writes with tempfile - `patch_settings_json()` - Main orchestrator - `uninstall()` - Complete cleanup (hook, RTK.md, settings.json) - Modified functions: `run()`, `run_default_mode()`, `run_hook_only_mode()`, `show_config()` ### Code Quality Improvements - Refactored `insert_hook_entry()` to use Rust `entry()` API (no manual unwraps) - Simplified `hook_already_present()` with iterator chains (3x shorter) - Improved error messages with file paths and actionable hints - Fixed string allocation (to_str() vs to_string()) ### Dependencies - Added `preserve_order` feature to `serde_json` (key order preservation) - Moved `tempfile` to production dependencies (atomic writes) ### Documentation - **README.md**: Updated Quick Install, added Installation Flags, Uninstalling, Troubleshooting, What Are Hooks sections - **INSTALL.md**: Updated Recommended Setup, added Common User Flows, Uninstalling sections - **CHANGELOG.md**: Documented new feature under Unreleased ### Testing - 11 new unit tests for hook detection, insertion, atomic writes, cleanup - All 249 tests passing - Smoke tested: install, idempotency, show, uninstall ## User Impact **Before**: Users had to manually copy JSON snippet to settings.json **After**: Single command with prompt, automatic backup, clean uninstall ## Breaking Changes None. Backwards compatible - manual setup still works via `--no-patch`. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-07 16:12:40 +01:00
tempfile = "3"
sha2 = "0.10"
ureq = "2"
2026-03-27 19:20:15 +01:00
getrandom = "0.4"
flate2 = "1.0"
quick-xml = "0.37"
which = "8"
[target.'cfg(unix)'.dependencies]
libc = "0.2"
[target.'cfg(windows)'.dependencies]
fix(core): decode per line, cover OEM code pages, and centralize on exec_capture Addresses the inline review on #2717. decode_process_output - Decode a line at a time instead of reinterpreting the whole buffer at the first bad byte. Valid UTF-8 lines keep their bytes; only lines that fail UTF-8 validation go through the code page, so one stray byte no longer mangles output that was almost entirely UTF-8. The line is the unit because a byte run is not one: GB18030's four-byte sequences embed bytes in the ASCII digit range, so any rule that ends a run below 0x80 splits them. \n cannot appear as a trail byte in any encoding handled here, and a process does not switch encoding mid-line. - A code page result is only accepted when it decodes cleanly, so a UTF-8 line with a corrupt byte falls back to lossy UTF-8 rather than mojibake. - Replace the hand-written code page table with the codepage crate, as suggested. That also fixes 54936, which was mapped to GBK and now correctly resolves to gb18030. - Add oem_cp for the legacy OEM/DOS pages (437, 850, 852, …) that plain cmd.exe still defaults to in many locales. encoding_rs implements only WHATWG encodings, so codepage alone returns None for them. - Fall back to GetACP when GetConsoleOutputCP reports no console, which is the piped case rtk normally runs in, and warn once instead of falling back to lossy silently. - Cache the code page lookup in a OnceLock. - The mapping and the walk take the code page as a parameter, so they are compiled and unit-tested on every platform rather than only Windows. Call sites - Route the remaining production sites through stream::exec_capture and exec_capture_stdin rather than decoding at each one, so future callers inherit decoding. git commit keeps inherited stdin via the _stdin variant. Test-only sites go back to from_utf8_lossy: they assert on rtk's own UTF-8 output, where a console code page has no meaning. - Decode the streamed path (read_lines_lossy) too — the OEM/ANSI lines its comment describes were still going straight to U+FFFD. - curl keeps its body on from_utf8_lossy: a response body is a network payload whose encoding comes from the HTTP charset, not the local console, and non-UTF-8 bodies already take the binary passthrough for #1087. Only curl's own stderr is code page decoded. git commit summary parsing - parse_commit_output sliced from byte 1, which panics when the first line starts with a multi-byte character — git prints hook output before its summary, and a lossily decoded line starts with a multi-byte U+FFFD. Locate the bracket pair with find instead, so both indices are character boundaries. Verified: unit tests for the walk, GBK, gb18030, CP437/850, mixed lines, truncated input and every byte value; a test pinning that output without a code page stays byte-identical to from_utf8_lossy; and the Windows-only lookup cross-compiled for x86_64-pc-windows-msvc.
2026-08-15 08:20:24 +03:00
windows-sys = { version = "0.59", features = [
"Win32_System_Console",
"Win32_Globalization",
] }
feat: TOML Part 2 — user-global config, shadow warning, rtk init templates, 4 new built-in filters (#351) * docs: update module count to 58 (toml_filter + verify_cmd) * docs: bump version refs to 0.27.1, fix module count to 59 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: TOML DSL PR 2 — user-global config, shadow warning, init templates, 4 new filters - toml_filter: add ~/.config/rtk/filters.toml (priority 2, between project and built-in) - toml_filter: shadow warning when match_command overlaps a Rust-handled command - init: rtk init generates .rtk/filters.toml template (local) and ~/.config/rtk/filters.toml (global) - builtin_filters: add pre-commit, helm, gcloud, ansible-playbook (46/46 inline tests) - README: add "Custom Filters" section with lookup table, primitives, examples, built-in list Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(filters): add quarto-render, pnpm-build, trunk-build from rtk discover data (52/52 tests) * feat(filters): add docker-inspect, sops, docker-compose-ps built-in filters Resolves issues #279, #277, #276 as TOML-native filters (no Rust required). - docker-inspect: strip_ansi + truncate_lines_at=120 + max_lines=60 - sops: strip_ansi + strip_lines_matching blank lines + max_lines=40 - docker-compose-ps: strip_ansi + truncate_lines_at=120 + max_lines=40 6 inline tests added (2 per filter), all passing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor(filters): split monolithic builtin_filters.toml into 28 individual files Replace the 848-line src/builtin_filters.toml monolith with individual files under src/filters/<name>.toml (1 filter + tests per file). Files are concatenated alphabetically by build.rs at compile time into OUT_DIR/builtin_filters.toml, then embedded via a BUILTIN_TOML constant in toml_filter.rs. The build step validates TOML syntax and detects duplicate filter names across files. Benefits: - Zero merge conflicts when multiple PRs add filters (different files) - Clear PR diffs: "+1 file of 30 lines" vs "+30 lines in 850-line file" - Easy onboarding: copy any .toml, rename, edit 3 fields — done - Build-time TOML validation catches syntax errors before tests run Changes: - build.rs (new): concat + validate src/filters/*.toml - Cargo.toml: add [build-dependencies] toml = "0.8" - src/filters/*.toml (28 files): split from monolith - src/filters/README.md (new): contributor guide - src/toml_filter.rs: BUILTIN_TOML const + 5 include_str replacements - src/builtin_filters.toml: deleted Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(filters): add 5 new unit tests for multi-file architecture + wget filter Unit tests added (toml_filter.rs): - test_builtin_toml_has_schema_version: ensures build.rs injects schema_version - test_builtin_all_expected_filters_present: guards against accidental file deletion - test_builtin_filter_count: exact count check (fails if filter added/removed without update) - test_builtin_all_filters_have_inline_tests: prevents shipping filters with no tests - test_new_filter_discoverable_after_concat: simulates build.rs concat, verifies lookup New built-in filter: - src/filters/wget.toml: compact wget download output (strips connection/resolution noise, short-circuits on 'saved [' to 'ok (downloaded)', 2 inline tests) Test results: 661/661 unit tests, 60/60 inline TOML filter tests Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs: add filter-workflow.md with Mermaid diagrams Build pipeline + runtime lookup priority, both as Mermaid flowcharts. Shows the full path from src/filters/*.toml to binary to execution. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: remove dead TOML filters — wget, git-checkout, git-merge, git-remote, cargo-run These filters were never reachable: Clap routes rtk git/cargo commands to their dedicated Rust modules before run_fallback is called. The TOML engine only fires for unknown commands. Shipping dead filters gives false confidence (inline tests pass, but filters never activate in production). Also fixes P1-1 from the PR #386 review: wget was in RUST_HANDLED_COMMANDS and the shadow warning fired at compile time but did not block the build. Removed: cargo-run.toml, git-checkout.toml, git-merge.toml, git-remote.toml, wget.toml Updated test guards: count 29→24, expected list -5 names, concat test 30→25. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: remove 3 dead TOML filters + update guards (PR #351) docker-inspect, docker-compose-ps, and pnpm-build are handled by container.rs and pnpm_cmd.rs before run_fallback is reached — their TOML filters never fire. Remove the files to avoid false documentation. Update toml_filter.rs guards: expected list -3 names, count 24→21, concat test 25→22. Update CONTRIBUTING.md example count to match. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: rebase on PR #349 — apply regex anchors, make on_empty, build.rs clippy, docs macOS path - Add (\\s|$) word-boundary anchors to 6 tofu/mix match_command regexes (tofu-plan, tofu-init, tofu-validate, tofu-fmt, mix-format, mix-compile) - Add on_empty = "make: ok" to make.toml + update existing empty-output test - Fix build.rs clippy: map_or(false, ...) → is_some_and(..) - Add macOS alt path note to filter-workflow.md Mermaid diagram Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 11:02:18 +01:00
[build-dependencies]
toml = "0.8"
chore: migrate to Rust edition 2024 Bump edition 2021 -> 2024. rust-version stays at 1.91, already well above the 1.85 floor the edition needs; docs/guide/resources/troubleshooting.md still claimed 1.70+, which is where a failed `cargo install --git` lands. Four things the edition forces: - std::env::{set_var,remove_var} are unsafe in 2024 with no safe std replacement. Rather than wrap the test call sites in unsafe -- which the crate denies and .semgrep.yml flags -- route them through temp-env, a dev-only dependency whose closure API is safe and which restores the previous value even when the body panics. The hand-rolled CLAUDE_DIR_LOCK and PI_DIR_LOCK guards existed only to serialise those mutations and are now redundant; CWD_LOCK and TEST_ENV_LOCK stay, they order more than the env var itself. - unsafe_op_in_unsafe_fn is on by default, so the libc calls in the proxy signal handler and in stream.rs's relay handler need explicit unsafe blocks, scoped to the libc calls themselves. - `gen` is a reserved keyword, so the closure by that name in diff_cmd.rs becomes make_lines. - Tightened tail-expression temporary scopes let clippy prove the binding in setup_test_env is inlinable, so let_and_return now fires there. if_let_rescope changes when the scrutinee temporary drops in an if let/else. The two sites in show_claude_config take cargo fix --edition's match rewrite, which keeps the 2021 drop timing. rustfmt.toml is kept rather than dropped: cargo fmt passes --edition from Cargo.toml, but a bare rustfmt invocation has no crate context and falls back to edition 2015, which cannot parse the let-chains the next commit introduces. Pinning it there keeps format-on-save and pre-commit hooks in agreement with CI. clippy::collapsible_if is allowed crate-wide for now; the follow-up commit adopts let-chains and removes the allow. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-31 01:19:25 +02:00
[dev-dependencies]
# Safe, closure-scoped env mutation for tests. std::env::set_var is unsafe
# in edition 2024 and has no safe std replacement; temp-env restores the
# previous value on completion or panic and serializes callers internally.
temp-env = "0.3"
[profile.release]
opt-level = 3
lto = true
codegen-units = 1
panic = "abort"
strip = true
# cargo-deb configuration
[package.metadata.deb]
maintainer = "Patrick Szymkowiak"
copyright = "2024 Patrick Szymkowiak"
license-file = ["LICENSE", "0"]
extended-description = "rtk filters and compresses command outputs before they reach your LLM context, saving 60-90% of tokens."
section = "utility"
priority = "optional"
assets = [
["target/release/rtk", "usr/bin/", "755"],
]
# cargo-generate-rpm configuration
[package.metadata.generate-rpm]
assets = [
{ source = "target/release/rtk", dest = "/usr/bin/rtk", mode = "755" },
]
[lints.rust]
unsafe_code = "deny"
warnings = "deny"