Skip to content

feat: tee raw output to file for LLM re-read without re-run#134

Merged
pszymkowiak merged 2 commits intomasterfrom
feat/tee-output
Feb 16, 2026
Merged

feat: tee raw output to file for LLM re-read without re-run#134
pszymkowiak merged 2 commits intomasterfrom
feat/tee-output

Conversation

@FlorianBruniaux
Copy link
Collaborator

@FlorianBruniaux FlorianBruniaux commented Feb 15, 2026

Summary

Closes #86

  • Problem: RTK filters command output aggressively, LLM agents lose failure details (stack traces, assertion messages) and re-run the same command 2-3x — wasting tokens
  • Solution: Save raw unfiltered output to ~/.local/share/rtk/tee/ on failure, print a one-line hint [full output: ~/.local/share/rtk/tee/...] so the agent reads the file instead of re-running
  • Scope: 7 modules integrated (cargo, runner, vitest, pytest, lint, tsc, go), 14 new tests, 352 total passing

Changes

File Change
src/tee.rs NEW — core module: tee_raw(), tee_and_hint(), sanitization, rotation, truncation
src/config.rs Add TeeConfig struct (enabled, mode, max_files, max_file_size, directory)
src/main.rs Register mod tee
src/cargo_cmd.rs Integrate tee in run_cargo_filtered() (covers build/test/clippy/check/install/nextest)
src/runner.rs Integrate tee in run_err() and run_test()
src/vitest_cmd.rs Integrate tee with slug vitest_run
src/pytest_cmd.rs Integrate tee with slug pytest
src/lint_cmd.rs Integrate tee with slug lint
src/tsc_cmd.rs Integrate tee with slug tsc
src/go_cmd.rs Integrate tee in run_test(), run_build(), run_vet()
README.md Document tee feature, config, env overrides
CLAUDE.md Add tee.rs to architecture docs

Design decisions

  • Failures only by default: Targets actual problem (re-runs on failure), no noise on success
  • 500 char minimum: Tiny outputs don't need recovery
  • Silent errors (.ok()?): Tee failure never affects command output or exit code
  • 20 file rotation, 1MB cap: Predictable disk usage (~20MB worst case)
  • 3 lines per module: Minimal invasion via tee_and_hint() helper

Test plan

  • 14 new unit tests in src/tee.rs (sanitize, should_tee, write, truncation, cleanup, config, serde)
  • Full test suite: 352 tests passing, zero regressions
  • cargo fmt --all --check clean
  • cargo clippy --all-targets zero new warnings
  • Manual smoke test: rtk cargo test -- nonexistent should produce tee file + hint

🤖 Generated with Claude Code

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>
Copilot AI review requested due to automatic review settings February 15, 2026 19:44
CI validate-docs requires main.rs module count == ARCHITECTURE.md count.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request adds a "tee" feature to RTK that saves raw unfiltered command output to files when commands fail. This addresses a significant token waste issue where LLM agents repeatedly re-run the same failing commands to get error details that were filtered out by RTK.

Changes:

  • Added new tee.rs module with configurable file output, rotation, and truncation
  • Integrated tee feature into 7 command modules (cargo, runner, vitest, pytest, lint, tsc, go)
  • Extended config system with TeeConfig struct and environment variable overrides
  • Updated documentation in README.md and CLAUDE.md to explain the feature

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/tee.rs New module implementing core tee functionality: file writing, rotation, sanitization, and configuration
src/config.rs Added tee field to Config struct with default initialization
src/main.rs Registered the new tee module
src/cargo_cmd.rs Integrated tee in run_cargo_filtered() covering all cargo subcommands
src/runner.rs Integrated tee in run_err() and run_test() helper functions
src/vitest_cmd.rs Integrated tee for vitest test runner output
src/pytest_cmd.rs Integrated tee for pytest test runner output
src/lint_cmd.rs Integrated tee for linter command output
src/tsc_cmd.rs Integrated tee for TypeScript compiler output
src/go_cmd.rs Integrated tee in run_test(), run_build(), and run_vet()
README.md Documented tee feature configuration and usage
CLAUDE.md Added tee.rs to architecture documentation
src/gain.rs Unrelated formatting change to improve code readability

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +121 to +125
// Truncate at max_file_size
let content = if raw.len() > max_file_size {
format!(
"{}\n\n--- truncated at {} bytes ---",
&raw[..max_file_size],
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The string slicing &raw[..max_file_size] on line 125 can panic if the slice boundary falls in the middle of a multi-byte UTF-8 character. This could happen when truncating command output containing Unicode characters (e.g., emoji in test output, special characters in paths).

Use a safe truncation method that respects UTF-8 character boundaries. You can use str::char_indices() to find a safe boundary or use chars().take(n).collect(). For example:

let content = if raw.len() > max_file_size {
    let truncate_at = raw.char_indices()
        .take_while(|(idx, _)| *idx < max_file_size)
        .last()
        .map(|(idx, ch)| idx + ch.len_utf8())
        .unwrap_or(0);
    format!(
        "{}\n\n--- truncated at {} bytes ---",
        &raw[..truncate_at],
        max_file_size
    )
} else {
    raw.to_string()
};
Suggested change
// Truncate at max_file_size
let content = if raw.len() > max_file_size {
format!(
"{}\n\n--- truncated at {} bytes ---",
&raw[..max_file_size],
// Truncate at max_file_size, respecting UTF-8 character boundaries
let content = if raw.len() > max_file_size {
let truncate_at = raw
.char_indices()
.take_while(|(idx, _)| *idx < max_file_size)
.last()
.map(|(idx, ch)| idx + ch.len_utf8())
.unwrap_or(0);
format!(
"{}\n\n--- truncated at {} bytes ---",
&raw[..truncate_at],

Copilot uses AI. Check for mistakes.
Comment on lines +27 to +28
if sanitized.len() > 40 {
sanitized[..40].to_string()
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The string slicing sanitized[..40] on line 28 could theoretically panic if a non-ASCII character somehow gets through the sanitization. While the current sanitization logic replaces all non-ASCII characters with underscores (which are single-byte), this creates a fragile dependency between the two parts of the code.

For defensive programming and consistency with the codebase pattern (see utils::truncate), consider using character-based truncation:

if sanitized.chars().count() > 40 {
    sanitized.chars().take(40).collect()
} else {
    sanitized
}

This makes the code more resilient to future changes in the sanitization logic.

Suggested change
if sanitized.len() > 40 {
sanitized[..40].to_string()
if sanitized.chars().count() > 40 {
sanitized.chars().take(40).collect()

Copilot uses AI. Check for mistakes.
Comment on lines +114 to +118
let epoch = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.ok()?
.as_secs();
let filename = format!("{}_{}.log", epoch, slug);
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The filename format {epoch}_{slug}.log could lead to file overwrites if two commands with the same slug complete within the same second (same epoch timestamp). While rare, this could happen when running the same command multiple times quickly (e.g., in a test script or CI pipeline).

Consider adding nanosecond precision or a random suffix to ensure uniqueness:

let nanos = std::time::SystemTime::now()
    .duration_since(std::time::UNIX_EPOCH)
    .ok()?
    .as_nanos();
let filename = format!("{}_{}.log", nanos, slug);

Or use a shorter approach with subsecond precision:

let micros = epoch * 1_000_000 + (duration.subsec_micros() as u64);
let filename = format!("{}_{}.log", micros, slug);
Suggested change
let epoch = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.ok()?
.as_secs();
let filename = format!("{}_{}.log", epoch, slug);
let duration = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.ok()?;
let micros = duration.as_secs()
.saturating_mul(1_000_000)
+ duration.subsec_micros() as u64;
let filename = format!("{}_{}.log", micros, slug);

Copilot uses AI. Check for mistakes.
Comment on lines +99 to +111
let table_width = 3
+ 2
+ cmd_width
+ 2
+ count_width
+ 2
+ saved_width
+ 2
+ 6
+ 2
+ time_width
+ 2
+ impact_width;
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This formatting change to break the arithmetic expression across multiple lines is unrelated to the tee feature and is not mentioned in the PR description. While the change improves readability, it should either be:

  1. Documented in the PR description as an incidental formatting improvement, or
  2. Moved to a separate PR focused on code style/formatting

Including unrelated changes in a feature PR makes code review more difficult and can obscure the actual feature changes.

Copilot uses AI. Check for mistakes.
@ahundt
Copy link

ahundt commented Feb 15, 2026

Tee seems like a cool and useful feature.

It might also help to be configurable and enabled / disabled and the destination configurable. It might also in the long run make sense to have there be a daemon that manages "sessions" and provides output uuids for saved full responses that can be re-queried, and automatically discarded based on the CLI policy. Or maybe the SQLite database could store such info. This may be worth some thought about how to revise it for better integration.

I might have missed some of the implementation details based on the summary though!

@FlorianBruniaux
Copy link
Collaborator Author

Thanks for the feedback! Good news — most of what you describe is already implemented in this PR:

Already done:

  • Configurable & enable/disable: [tee] section in config.toml with enabled = true/false and mode = "failures" | "always" | "never" + RTK_TEE=0 env var to disable entirely
  • Destination configurable: directory field in config or RTK_TEE_DIR env var override
  • Auto-discard policy: Count-based rotation (max_files = 20 default), size cap (max_file_size = 1MB), oldest files cleaned up automatically

Future ideas you raised:

  • Session daemon + UUIDs: Interesting direction. Right now the file-based approach is intentionally simple (zero runtime overhead, no daemon process). A daemon would add complexity but could enable cross-command correlation within a session
  • SQLite integration: The tracking DB (tracking.rs) already records command metadata. Storing tee output references there (path + command + timestamp) would be a natural evolution — keeps the file-based storage but adds queryable metadata

The current design prioritizes zero-overhead simplicity (file write + hint line, ~25 tokens overhead) while solving the immediate re-run problem. The daemon/SQLite ideas make sense as a v2 if usage patterns justify it.

Full implementation details in src/tee.rs if you want to take a closer look!

@pszymkowiak pszymkowiak merged commit a08a62b into master Feb 16, 2026
4 checks passed
ahundt added a commit to ahundt/rtk that referenced this pull request Feb 16, 2026
Rust binary replaces 204-line bash script as Claude Code PreToolUse hook.
Adds rtk hook claude, rtk run -c, and Windows support via cfg!(windows).
Closes rtk-ai#112 (chained commands missed).

Based on updated master (70c3786) which includes:
- Hook audit mode (rtk-ai#151)
- Claude Code agents and skills (d8f4659)
- tee raw output feature (rtk-ai#134)

Migrated from feat/rust-hooks (571bd86) with conflict resolution for:
- src/main.rs: Commands enum (preserved both hook audit + our hook commands)
- src/init.rs: Hook registration (integrated both approaches)

New files (src/cmd/ module):
- mod.rs: Module declarations (10 modules, excluding safety/trash/gemini for PR 1)
- hook.rs: Shared hook decision logic (21 tests, 3 safety tests removed for PR 2)
- claude_hook.rs: Claude Code JSON protocol handler (18 tests)
- lexer.rs: Quote-aware tokenizer (28 tests)
- analysis.rs: Chain parsing and shellism detection (10 tests)
- builtins.rs: cd/export/pwd/echo/true/false (8 tests)
- exec.rs: Command executor with recursion guard (22 tests, safety dispatch removed for PR 2)
- filters.rs: Output filter registry (5 tests)
- predicates.rs: Context predicates (4 tests)
- test_helpers.rs: Test utilities

Modified files:
- src/main.rs: Added Commands::Run, Commands::Hook, HookCommands enum, routing
- src/init.rs: Changed patch_settings_json to use rtk hook claude binary command
- hooks/rtk-rewrite.sh: Replaced 204-line bash script with 4-line shim (exec rtk hook claude)
- Cargo.toml: Added which = 7 for PATH resolution
- INSTALL.md: Added Windows installation section

Windows support:
- exec.rs:175-176: cfg!(windows) selects cmd /C vs sh -c for shell passthrough
- predicates.rs:26: USERPROFILE fallback for Windows home directory
- No bash, node, or bun dependency - rtk hook claude is a compiled Rust binary

Tests: All 541 tests pass
edsai pushed a commit to edsai/rtk that referenced this pull request Feb 19, 2026
Rust binary replaces 204-line bash script as Claude Code PreToolUse hook.
Adds rtk hook claude, rtk run -c, and Windows support via cfg!(windows).
Closes rtk-ai#112 (chained commands missed).

Based on updated master (70c3786) which includes:
- Hook audit mode (rtk-ai#151)
- Claude Code agents and skills (d8f4659)
- tee raw output feature (rtk-ai#134)

Migrated from feat/rust-hooks (571bd86) with conflict resolution for:
- src/main.rs: Commands enum (preserved both hook audit + our hook commands)
- src/init.rs: Hook registration (integrated both approaches)

New files (src/cmd/ module):
- mod.rs: Module declarations (10 modules, excluding safety/trash/gemini for PR 1)
- hook.rs: Shared hook decision logic (21 tests, 3 safety tests removed for PR 2)
- claude_hook.rs: Claude Code JSON protocol handler (18 tests)
- lexer.rs: Quote-aware tokenizer (28 tests)
- analysis.rs: Chain parsing and shellism detection (10 tests)
- builtins.rs: cd/export/pwd/echo/true/false (8 tests)
- exec.rs: Command executor with recursion guard (22 tests, safety dispatch removed for PR 2)
- filters.rs: Output filter registry (5 tests)
- predicates.rs: Context predicates (4 tests)
- test_helpers.rs: Test utilities

Modified files:
- src/main.rs: Added Commands::Run, Commands::Hook, HookCommands enum, routing
- src/init.rs: Changed patch_settings_json to use rtk hook claude binary command
- hooks/rtk-rewrite.sh: Replaced 204-line bash script with 4-line shim (exec rtk hook claude)
- Cargo.toml: Added which = 7 for PATH resolution
- INSTALL.md: Added Windows installation section

Windows support:
- exec.rs:175-176: cfg!(windows) selects cmd /C vs sh -c for shell passthrough
- predicates.rs:26: USERPROFILE fallback for Windows home directory
- No bash, node, or bun dependency - rtk hook claude is a compiled Rust binary

Tests: All 541 tests pass
edsai pushed a commit to edsai/rtk that referenced this pull request Feb 19, 2026
Rust binary replaces 204-line bash script as Claude Code PreToolUse hook.
Adds rtk hook claude, rtk run -c, and Windows support via cfg!(windows).
Closes rtk-ai#112 (chained commands missed).

Based on updated master (70c3786) which includes:
- Hook audit mode (rtk-ai#151)
- Claude Code agents and skills (d8f4659)
- tee raw output feature (rtk-ai#134)

Migrated from feat/rust-hooks (571bd86) with conflict resolution for:
- src/main.rs: Commands enum (preserved both hook audit + our hook commands)
- src/init.rs: Hook registration (integrated both approaches)

New files (src/cmd/ module):
- mod.rs: Module declarations (10 modules, excluding safety/trash/gemini for PR 1)
- hook.rs: Shared hook decision logic (21 tests, 3 safety tests removed for PR 2)
- claude_hook.rs: Claude Code JSON protocol handler (18 tests)
- lexer.rs: Quote-aware tokenizer (28 tests)
- analysis.rs: Chain parsing and shellism detection (10 tests)
- builtins.rs: cd/export/pwd/echo/true/false (8 tests)
- exec.rs: Command executor with recursion guard (22 tests, safety dispatch removed for PR 2)
- filters.rs: Output filter registry (5 tests)
- predicates.rs: Context predicates (4 tests)
- test_helpers.rs: Test utilities

Modified files:
- src/main.rs: Added Commands::Run, Commands::Hook, HookCommands enum, routing
- src/init.rs: Changed patch_settings_json to use rtk hook claude binary command
- hooks/rtk-rewrite.sh: Replaced 204-line bash script with 4-line shim (exec rtk hook claude)
- Cargo.toml: Added which = 7 for PATH resolution
- INSTALL.md: Added Windows installation section

Windows support:
- exec.rs:175-176: cfg!(windows) selects cmd /C vs sh -c for shell passthrough
- predicates.rs:26: USERPROFILE fallback for Windows home directory
- No bash, node, or bun dependency - rtk hook claude is a compiled Rust binary

Tests: All 541 tests pass
edsai pushed a commit to edsai/rtk that referenced this pull request Feb 19, 2026
Rust binary replaces 204-line bash script as Claude Code PreToolUse hook.
Adds rtk hook claude, rtk run -c, and Windows support via cfg!(windows).
Closes rtk-ai#112 (chained commands missed).

Based on updated master (70c3786) which includes:
- Hook audit mode (rtk-ai#151)
- Claude Code agents and skills (d8f4659)
- tee raw output feature (rtk-ai#134)

Migrated from feat/rust-hooks (571bd86) with conflict resolution for:
- src/main.rs: Commands enum (preserved both hook audit + our hook commands)
- src/init.rs: Hook registration (integrated both approaches)

New files (src/cmd/ module):
- mod.rs: Module declarations (10 modules, excluding safety/trash/gemini for PR 1)
- hook.rs: Shared hook decision logic (21 tests, 3 safety tests removed for PR 2)
- claude_hook.rs: Claude Code JSON protocol handler (18 tests)
- lexer.rs: Quote-aware tokenizer (28 tests)
- analysis.rs: Chain parsing and shellism detection (10 tests)
- builtins.rs: cd/export/pwd/echo/true/false (8 tests)
- exec.rs: Command executor with recursion guard (22 tests, safety dispatch removed for PR 2)
- filters.rs: Output filter registry (5 tests)
- predicates.rs: Context predicates (4 tests)
- test_helpers.rs: Test utilities

Modified files:
- src/main.rs: Added Commands::Run, Commands::Hook, HookCommands enum, routing
- src/init.rs: Changed patch_settings_json to use rtk hook claude binary command
- hooks/rtk-rewrite.sh: Replaced 204-line bash script with 4-line shim (exec rtk hook claude)
- Cargo.toml: Added which = 7 for PATH resolution
- INSTALL.md: Added Windows installation section

Windows support:
- exec.rs:175-176: cfg!(windows) selects cmd /C vs sh -c for shell passthrough
- predicates.rs:26: USERPROFILE fallback for Windows home directory
- No bash, node, or bun dependency - rtk hook claude is a compiled Rust binary

Tests: All 541 tests pass
ahundt pushed a commit to ahundt/rtk that referenced this pull request Feb 23, 2026
* feat: tee raw output to file for LLM re-read without re-run (rtk-ai#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 rtk-ai#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>
ahundt added a commit to ahundt/rtk that referenced this pull request Feb 23, 2026
Rust binary replaces 204-line bash script as Claude Code PreToolUse hook.
Adds rtk hook claude, rtk run -c, and Windows support via cfg!(windows).
Closes rtk-ai#112 (chained commands missed).

Based on updated master (0b0071d) which includes:
- Hook audit mode (rtk-ai#151)
- Claude Code agents and skills (d8b5bb0)
- tee raw output feature (rtk-ai#134)

Migrated from feat/rust-hooks (571bd86) with conflict resolution for:
- src/main.rs: Commands enum (preserved both hook audit + our hook commands)
- src/init.rs: Hook registration (integrated both approaches)

New files (src/cmd/ module):
- mod.rs: Module declarations (10 modules, excluding safety/trash/gemini for PR 1)
- hook.rs: Shared hook decision logic (21 tests, 3 safety tests removed for PR 2)
- claude_hook.rs: Claude Code JSON protocol handler (18 tests)
- lexer.rs: Quote-aware tokenizer (28 tests)
- analysis.rs: Chain parsing and shellism detection (10 tests)
- builtins.rs: cd/export/pwd/echo/true/false (8 tests)
- exec.rs: Command executor with recursion guard (22 tests, safety dispatch removed for PR 2)
- filters.rs: Output filter registry (5 tests)
- predicates.rs: Context predicates (4 tests)
- test_helpers.rs: Test utilities

Modified files:
- src/main.rs: Added Commands::Run, Commands::Hook, HookCommands enum, routing
- src/init.rs: Changed patch_settings_json to use rtk hook claude binary command
- hooks/rtk-rewrite.sh: Replaced 204-line bash script with 4-line shim (exec rtk hook claude)
- Cargo.toml: Added which = 7 for PATH resolution
- INSTALL.md: Added Windows installation section

Windows support:
- exec.rs:175-176: cfg!(windows) selects cmd /C vs sh -c for shell passthrough
- predicates.rs:26: USERPROFILE fallback for Windows home directory
- No bash, node, or bun dependency - rtk hook claude is a compiled Rust binary

Tests: All 541 tests pass
heAdz0r added a commit to heAdz0r/rtk that referenced this pull request Feb 28, 2026
Upstream 0.22.2 sync (all previously missing fixes verified applied):
- fix(lint): propagate linter exit code (rtk-ai#207) — CI false-green fix
- feat: add rtk wc command for compact word/line/byte counts (rtk-ai#175)
- fix(playwright): JSON parser (specs layer) + binary resolution (rtk-ai#215)
- fix(grep): propagate rg exit codes 1/2 (rtk-ai#227)
- fix(git): branch creation not swallowed by list mode (rtk-ai#194)
- fix(git): support multiple -m flags in git commit (rtk-ai#202)
- fix(grep): BRE \| translation + strip -r flag (rtk-ai#206)
- fix(gh): smart markdown body filter for issue/pr view (rtk-ai#214)
- fix(gh): gh run view --log-failed flag passthrough (rtk-ai#159)
- feat(docker): docker compose support (rtk-ai#110)
- feat: hook audit mode (rtk-ai#151)
- feat: tee raw output to file (rtk-ai#134)

Version bump: 0.21.1-fork.19 → 0.22.2-fork.1

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: tee full output to file for LLM re-read without re-run

4 participants