文件最后提交记录最后更新时间
fix(truncate): global caps reduce (avoid underflow and 0 results) - Avoid underflow + 0 results caused by overwrite of global constant CAPS - Soon user will be able to apply global configuration, this will change global CAPS and should not cause any underflow or 0 results, if overwrite sub >= CAPS -> use CAPS. 14 天前
fix(hooks): address transparent prefix review 28 天前
fix(cleaning): constant extract 2 个月前
chore(refacto-codebase): Folders + Technical docs - codebase more clear for humans and AI agents - alignement on vision and filter quality in technical docs 2 个月前
fix: grep false negatives, output mangling, and truncation annotations - grep: use --no-ignore-vcs so .gitignore'd files aren't silently skipped (matches grep -r behavior, avoids false negatives in large monorepos) - grep: passthrough raw output for <=50 matches so AI agents can parse standard file:line:content format without retry loops - filter: replace smart_truncate heuristic with clean first-N-lines truncation and a single [X more lines] suffix (eliminates synthetic // ... markers that AI agents misread as code, causing parsing confusion and retries) 1 个月前
refacto(truncations): Set global CAPS for truncation Following tee and hint refacto Add global CAP constant to be inherited , to enable easier global configuration later 15 天前
20 天前
fix(git): stream push output via FilterMode::Streaming (#963) ## Problem (#963) rtk git push reportedly times out: users see bash tool terminated command after exceeding timeout 30000 ms while plain git push to the same remote completes fine. P1-critical because every Claude Code git push goes through rtk. ## Root cause run_push used cmd.stdin(Stdio::inherit()).output(). Command::output() captures both stdout and stderr until the child exits. Git push prints its progress (Counting objects / Compressing objects / `Writing objects`) to stderr and may prompt for SSH passphrases or HTTPS credentials. With stderr captured, Claude Code's bash tool saw zero output for 30+ seconds and killed the command — exactly the 30000 ms message in the issue. ## Fix Rewrite run_push on top of the streaming infrastructure that already exists for this exact purpose (stream::run_streaming + FilterMode::Streaming, added in 0.37.0). Add a counterpart to BlockStreamFilter<H: BlockHandler> in src/core/stream.rs: LineStreamFilter<H: LineHandler>. Where BlockStreamFilter defaults to DROP and emits only collected blocks, LineStreamFilter defaults to KEEP and lets handlers opt into dropping noise. Trait surface mirrors BlockHandler: - should_skip(&mut self, line: &str) -> bool — default false - observe_line(&mut self, line: &str) — default no-op - format_summary(&self, exit_code, raw) -> Option<String> This lets future streaming commands reuse the line-oriented pattern. GitPushLineHandler then becomes a tiny LineHandler impl: - should_skip drops the high-volume progress phases (Enumerating / Counting / Compressing / Writing objects, Delta compression, Total) and blank lines. - observe_line captures the up-to-date sentinel and the first ref update target (e.g. master) for the summary. - format_summary emits ok <ref> / ok (up-to-date) / ok on success; nothing on failure (raw error lines already flowed through). Stdin is inherited (StdinMode::Inherit) so SSH passphrase and HTTPS credential prompts still reach the user. Tracking now records the real raw output and the filtered output. ## Test plan - [x] cargo fmt --all -- --check - [x] cargo clippy --all-targets -- -D warnings — clean - [x] cargo test --all — 1880 passed, 0 failed, 6 ignored - Six unit tests cover the push handler: progress-prefix drop, up-to-date summary, remote message passthrough, no-summary-on-failure, first-ref-wins, and token-savings (>=60% on a representative payload). - Four unit tests cover the new LineStreamFilter trait: default-keep-all, skip-drops-matching, summary-propagates-exit-code, observe-only-called-for-kept-lines. ## Notes - Behaviour change: users now see git's native output line-by-line (with progress phases stripped) plus a final ok <ref> summary, instead of just the compact summary. This matches plain git push more closely and is what the issue reporter expects. - No regression for other filters: run_pull, run_fetch, run_clone are untouched; only run_push is modified. Closes #963 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- _Vibe Coded by Ousama Ben Younes_ _Developed With Ora Studio (Claude Code)_ Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> 20 天前
feat(hints): add tail hints for tee & hints + address reviews - fix signal truncation gaps + kush reviews - added a new tee and hints function to give an hint with tail (avoid re-ingest of the head) - extracted patterns in constants 19 天前
Merge pull request #1181 from rtk-ai/rgpd-telemetry1 个月前
Update telemetry documentation link to use 'master' branch 28 天前
Add liquibase TOML filter 1 个月前
chore: fix clippy warnings - **Path Centralization:** Hardcoded directory and file paths across all hook logic () are replaced with dedicated, exported constants in . This prevents magic strings and simplifies maintenance when system directories change. - **Code Cleanup:** Move all code only used by tests behind cfg(test) attribute - **Refactoring:** Apply Clippy fixes and address remaining warnings Signed-off-by: Nicolas Le Cam <niko.lecam@gmail.com> 1 个月前
fix(truncate): global caps reduce (avoid underflow and 0 results) - Avoid underflow + 0 results caused by overwrite of global constant CAPS - Soon user will be able to apply global configuration, this will change global CAPS and should not cause any underflow or 0 results, if overwrite sub >= CAPS -> use CAPS. 14 天前
fix(tee): safe truncation caps and compose-ps tee content fix Replace all bare magic offset literals (e.g. 21 for cap=20) with named constants (MAX_XXX + 1) so offsets stay in sync if caps change. Fix compose_ps to tee pre-formatted lines instead of raw tab-separated input, so tail -n +N gives the agent readable content. All 13 affected modules updated: container, dotnet, gh, glab, go, lint, pnpm, pytest, rubocop, cargo, aws. 1884 tests pass. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> 16 天前
README.md

Core Infrastructure

See also docs/contributing/TECHNICAL.md for the full architecture overview

Scope

Domain-agnostic building blocks with no knowledge of any specific command, hook, or agent. If a module references "git", "cargo", "claude", or any external tool by name, it does not belong here. Core is a leaf in the dependency graph — it is consumed by all other components but imports from none of them.

Owns: configuration loading, token tracking persistence, TOML filter engine, tee output recovery, display formatting, telemetry, and shared utilities.

Does not own: command-specific filtering logic (that's cmds/), hook lifecycle management (that's src/hooks/), or analytics dashboards (that's analytics/).

Purpose

Core infrastructure shared by all RTK command modules. Every filter, tracker, and command handler depends on these modules. No inward dependencies — leaf in the dependency graph (no circular imports possible).

TOML Filter Pipeline

The TOML DSL applies 8 stages in order:

  1. strip_ansi: Remove ANSI escape codes if enabled
  2. replace: Line-by-line regex substitutions (chainable, supports backreferences)
  3. match_output: Short-circuit rules (if output matches pattern, return message; unless field prevents swallowing errors)
  4. strip/keep_lines: Filter lines by regex (mutually exclusive)
  5. truncate_lines_at: Truncate each line to N chars (unicode-safe)
  6. head/tail_lines: Keep first N or last N lines (with omit message)
  7. max_lines: Absolute line cap applied after head/tail
  8. on_empty: Return message if result is empty after all stages

Three-tier filter lookup (first match wins):

  1. .rtk/filters.toml (project-local, requires rtk trust)
  2. ~/.config/rtk/filters.toml (user-global)
  3. Built-in filters concatenated by build.rs at compile time

Tracking Database Schema

CREATE TABLE commands (
  id INTEGER PRIMARY KEY,
  timestamp TEXT,              -- UTC ISO8601
  original_cmd TEXT,           -- "ls -la"
  rtk_cmd TEXT,                -- "rtk ls"
  project_path TEXT,           -- cwd (for project-scoped stats)
  input_tokens INTEGER,        -- estimated from raw output
  output_tokens INTEGER,       -- estimated from filtered output
  saved_tokens INTEGER,        -- input - output
  savings_pct REAL,            -- (saved / input) * 100
  exec_time_ms INTEGER         -- elapsed milliseconds
);

CREATE TABLE parse_failures (
  id INTEGER PRIMARY KEY,
  timestamp TEXT,
  raw_command TEXT,
  error_message TEXT,
  fallback_succeeded INTEGER   -- 1=yes, 0=no
);

Project-scoped queries use GLOB patterns (not LIKE) to avoid _/% wildcard issues in paths.

Config Sections

[tracking]
enabled = true
history_days = 90
database_path = "/custom/path/to/tracking.db"  # Optional

[display]
colors = true
emoji = true
max_width = 120

[tee]
enabled = true
mode = "failures"  # failures | always | never
max_files = 20
max_file_size = 1048576
directory = "/custom/tee/dir"

[telemetry]
enabled = true

[hooks]
exclude_commands = ["curl", "playwright"]  # Never auto-rewrite these

[limits]
grep_max_results = 200
grep_max_per_file = 25
status_max_files = 15
status_max_untracked = 10
passthrough_max_chars = 2000

Shared Utilities (utils.rs)

Key functions available to all command modules:

Function Purpose
truncate(s, max) Truncate string with ... suffix
strip_ansi(text) Remove ANSI escape/color codes
resolved_command(name) Find command in PATH, returns Command
tool_exists(name) Check if a CLI tool is available
detect_package_manager() Detect pnpm/yarn/npm from lockfiles
package_manager_exec(tool) Build Command using detected package manager
ruby_exec(tool) Auto-detect bundle exec when Gemfile exists
count_tokens(text) Estimate tokens: ceil(chars / 4.0)

Consumer Contracts

Core provides infrastructure that cmds/ and other components consume. These contracts define expected usage.

Tracking (TimedExecution)

Consumers must call timer.track() on all code paths — success, failure, and fallback. Calling std::process::exit() before track() loses metrics. The raw string passed to track() should include both stdout and stderr to produce accurate savings percentages.

Tee (tee_and_hint)

Consumers that parse structured output (JSON, NDJSON, state machines) should call tee::tee_and_hint() to save raw output for LLM recovery on failure. Tee must be called before std::process::exit().

For truncation recovery on success (e.g., list truncated at 20 items), use tee::force_tee_hint() which bypasses the tee mode check and writes regardless of exit code. This ensures LLMs always have a [full output: ...] recovery path instead of burning tokens working around missing data.

When the truncated output is a flat list and the hidden items start at a predictable line, prefer tee::force_tee_tail_hint(content, slug, offset). It writes the same tee file but emits a directly runnable hint — [see remaining: tail -n +{offset} ~/path] — so the agent jumps to exactly the first hidden item without scanning the whole file. The offset is header_lines + MAX_CAP + 1. Use force_tee_hint instead when the output has multiple sections (e.g. running + stopped containers) and no single offset cleanly covers the gap.

Truncation Caps (truncate)

src/core/truncate.rs defines four global cap policies — CAP_ERRORS, CAP_WARNINGS, CAP_LIST, CAP_INVENTORY — for the data classes RTK filters truncate. Each filter binds the right CAP to a local const MAX_* so the cap is one named jump away from the call site. These CAPs are the staging point for filter-level cap configuration (planned, not yet implemented): once the config surface lands, overriding CAP_LIST in ~/.config/rtk/config.toml will tune every list filter in one place instead of editing 20+ files.

Config policy. Configured values are accepted as-is, including 0, which means "summary only" — the filter still prints the count and the [full output: …] recovery hint, just no individual items. Caps are never refused and rtk never aborts on them, in keeping with the never-block-the-user fallback philosophy.

Deviating from a cap. A filter whose items are unusually verbose (multi-line entries, backtraces) may show fewer than its class cap. Use truncate::reduced(cap, by) rather than a bare cap - by: reduced returns cap - by, except when the reduction would empty the list (by >= cap), in which case it drops the deviation and uses the full cap. This guarantees a deviation can never hide every item, and — crucially — stays a usize-underflow-safe const fn once caps become runtime-configurable (a bare CAP_WARNINGS - 5 would panic or wrap to "no truncation" if a user set CAP_WARNINGS below 5). Never deviate with a bare literal or with *// (those scale unboundedly). Each deviation needs a one-line comment stating why.

Adding New Functionality

Place new infrastructure code here if it meets all of these criteria: (1) it has no dependencies on command modules or hooks, (2) it is used by two or more other modules, and (3) it provides a general-purpose utility rather than command-specific logic. Follow the existing pattern of lazy-initialized resources (lazy_static! for regex, on-demand config loading) to preserve the <10ms startup target. Add #[cfg(test)] mod tests with unit tests in the same file.