How RTK's Tee System Facilitates Failure Recovery and Full-Output Retrieval
RTK's tee system captures raw, unfiltered command output to timestamped log files when failures occur or filters truncate data, then surfaces a retrievable file path hint that enables LLMs and users to access the complete original output for debugging.
The rtk-ai/rtk repository implements a sophisticated tee subsystem that solves the critical problem of lost diagnostic information in AI-assisted command workflows. When token-saving filters compress or truncate command output, this system automatically persists full execution logs to disk, ensuring that no essential debugging data disappears during the filtering pipeline.
Configuration and Operating Modes
The tee behavior is governed by TeeConfig in src/core/config.rs (lines 41‑50), which exposes several tunable parameters:
enabled– Global boolean switch that activates the entire subsystem.mode– Enum controlling when files are written:failures(only on non‑zero exit codes),always(every execution), ornever(disabled entirely). Defaults tofailures.max_files– Rotation limit keeping only the 20 most recent logs per directory.max_file_size– 1,048,576 byte cap per file; larger output truncates safely at UTF‑8 boundaries.directory– Optional custom path; otherwise defaults to~/.local/share/rtk/tee/.
The TeeMode enum itself is defined in src/core/tee.rs (lines 31‑39), providing the type safety for these configuration options.
Decision Logic: When to Capture Output
The core decision function should_tee in src/core/tee.rs (lines 84‑100) applies a series of guards before writing any data:
- Global enable check – Returns immediately if
config.enabledis false. - Mode evaluation –
Neveraborts;Failuresrequiresexit_code != 0;Alwaysproceeds unconditionally. - Minimum size threshold – Outputs smaller than 500 bytes (
MIN_TEE_SIZE) are ignored to prevent clutter. - Directory resolution – Confirms a valid tee directory exists via
get_tee_dir, which checks theRTK_TEE_DIRenvironment variable, the config field, or falls back to the platform data directory.
fn should_tee(
config: &TeeConfig,
raw_len: usize,
exit_code: i32,
tee_dir: Option<PathBuf>,
) -> Option<PathBuf> {
if !config.enabled { return None; }
match config.mode {
TeeMode::Never => return None,
TeeMode::Failures => { if exit_code == 0 { return None; } }
TeeMode::Always => {}
}
if raw_len < MIN_TEE_SIZE { return None; }
tee_dir
}
File Writing and Rotation Mechanisms
Once should_tee approves the operation, write_tee_file in src/core/tee.rs (lines 112‑155) handles the persistence:
- Safe filename construction – Generates
{epoch}_{command_slug}.logwhere non‑alphanumeric characters in the slug convert to underscores and truncate to 40 characters. - UTF‑8 safe truncation – Uses
char_indicesto split only at valid character boundaries when output exceedsmax_file_size, appending a--- truncated ... ---notice. - Automatic rotation –
cleanup_old_filessorts existing logs by epoch prefix and deletes the oldest entries when the count exceedsmax_files.
The system creates the directory tree recursively if missing, ensuring robust operation in fresh environments.
User Hints and Recovery Workflow
The public entry point tee_and_hint in src/core/tee.rs (lines 188‑191) orchestrates the capture and user notification:
- Checks for the
RTK_TEE=0environment override. - Loads configuration and resolves the tee directory.
- Executes the
should_teeguard logic. - Writes the file and returns a formatted hint string.
pub fn tee_and_hint(raw: &str, command_slug: &str, exit_code: i32) -> Option<String> {
// Environment override & config loading...
let tee_dir = should_tee(&config.tee, raw.len(), exit_code, Some(tee_dir))?;
write_tee_file(...).map(format_hint)
}
When RTK prints [full output: ~/rtk/tee/1701234567_cargo_test.log], users or LLMs can read that file to obtain the unfiltered original, bypassing any compression or truncation that occurred in the main output stream.
Forced Tees on Filter Truncation
Some filters (such as the AWS output processor) may truncate content while still returning a successful exit code. The force_tee_hint function in src/core/tee.rs (lines 199‑213) bypasses the mode check and always writes the file when FilterResult.truncated is true, provided the output meets the minimum size threshold. This ensures that large payloads intentionally clipped by filters remain recoverable even when the command technically succeeded.
Integration Points
The tee system hooks into RTK's execution flow at three critical locations:
Command Runner (src/main.rs, lines 66‑78): After a subprocess completes, if !output.status.success(), the system calls tee_and_hint with the merged stdout and stderr, then prints the hint after the filtered output.
Filtered Runners (src/core/runner.rs, lines 9‑12): When filtered commands return successfully but the filter forces a tee, print_with_hint appends the path to the filtered output.
Streamed Mode (src/core/runner.rs, lines 25‑31): Even during real‑time streaming, the system checks opts.tee_label and prints the hint after capture completes, ensuring streamed failures also leave a recoverable log.
Environment Overrides
Two environment variables provide runtime control without editing configuration files:
RTK_TEE=0– Disables teeing entirely for the current process, checked at the entry points oftee_raw,tee_and_hint, andforce_tee_hint.RTK_TEE_DIR=/custom/path– Overrides the storage location, useful in CI/CD pipelines where the default~/.local/share/rtk/tee/may not be writable or persistent.
Example usage:
export RTK_TEE_DIR=/tmp/rtk_logs
rtk cargo test # Failure logs write to /tmp/rtk_logs
Summary
- RTK's tee system automatically persists raw command output to log files when configured conditions are met.
- The
should_teefunction insrc/core/tee.rsgates writes based on mode, exit code, and minimum size thresholds. - Files are safely truncated at UTF‑8 boundaries and automatically rotated to respect
max_fileslimits. - User hints provide direct paths to full output, enabling LLMs to reference complete logs even after aggressive filtering.
- Environment variables
RTK_TEEandRTK_TEE_DIRoffer flexible runtime control for CI pipelines and debugging sessions.
Frequently Asked Questions
Where does RTK store tee log files by default?
By default, RTK writes tee logs to ~/.local/share/rtk/tee/ on Linux and macOS, or the equivalent platform data directory on other systems. You can customize this path via the directory field in TeeConfig or by setting the RTK_TEE_DIR environment variable to an absolute path.
How can I force RTK to save output even when a command succeeds?
Set the tee mode to always in your configuration, or use the force_tee_hint function programmatically when implementing custom filters. The always mode bypasses the exit code check in should_tee, writing a log file for every execution that meets the minimum size requirement.
What happens when tee output exceeds the maximum file size?
When output exceeds the max_file_size limit (default 1,048,576 bytes), RTK truncates the content at the nearest valid UTF‑8 character boundary using char_indices and appends a --- truncated ... --- marker. This prevents file corruption while still preserving the initial actionable portion of large outputs.
Can I completely disable the tee system for specific commands?
Yes. Set the environment variable RTK_TEE=0 before running RTK, or configure enabled: false in the TeeConfig section of your settings file. The environment variable is checked early in the tee_and_hint execution path, ensuring zero overhead for that process.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →