Skip to content

Terminal Output Handling Refactor: Persisted Output Pattern #10941

@hannesrudolph

Description

@hannesrudolph

Summary

Refactor how Roo Code captures and relays terminal output to the LLM. Currently, output is compressed and truncated (lossy), which means information is permanently lost. Adopt a "persisted output" pattern inspired by Claude Code where full output is saved to disk and the LLM receives a fixed-size preview.

Problem

Current approach:

  • Output is compressed via RLE, carriage return processing, etc.
  • Then truncated to terminalOutputLineLimit (500) and terminalOutputCharacterLimit (100000)
  • 20% head / 80% tail split means middle content is permanently lost
  • Agent cannot recover truncated content
  • Variable context window cost (unpredictable)

Proposed Solution

Implement an OutputInterceptor that:

  1. Accumulates output up to a threshold (e.g., 4KB)
  2. If threshold exceeded, spills full output to disk artifact
  3. Returns preview (first N bytes) + artifact ID to LLM
  4. Agent can use new read_command_output tool to access full output when needed

Key Architectural Decisions

  1. Storage location: Artifacts stored in task storage directory (globalStoragePath/tasks/<taskId>/command-output/), NOT workspace
  2. Lifecycle: Artifacts tied to conversation history - cleaned up on task completion AND on history rewind/delete
  3. New tool required: read_command_output tool since existing read_file/search_files are workspace-scoped

Storage Architecture

globalStoragePath/tasks/<taskId>/
├── api_conversation_history.json    # Existing
├── ui_messages.json                 # Existing
├── task_metadata.json               # Existing
├── checkpoints/                     # Existing
└── command-output/                  # NEW
    ├── cmd-<executionId-1>.txt
    ├── cmd-<executionId-2>.txt
    └── ...

Settings Changes

Remove

  • terminalOutputLineLimit (slider)
  • terminalOutputCharacterLimit (slider)

Keep

  • terminalCompressProgressBar (checkbox) - still useful for preview quality

Add

  • terminalOutputPreviewSize (dropdown: Small 2KB / Medium 4KB / Large 8KB)
    • Default: Medium (4KB)

Implementation Phases

  1. Phase 1: Types - Add TerminalOutputPreviewSize, PersistedCommandOutput types
  2. Phase 2: OutputInterceptor - Core class for buffering + spilling to disk
  3. Phase 3: ExecuteCommandTool Integration - Wire interceptor into command execution
  4. Phase 4: Lifecycle Management - Cleanup on task completion + history rewind
  5. Phase 5: Settings UI - Remove old sliders, add new dropdown
  6. Phase 6: read_command_output Tool - New tool to access artifacts
  7. Phase 7: Testing - Unit + integration + manual tests
  8. Phase 8: Documentation - Update docs

New Tool: read_command_output

interface ReadCommandOutputParams {
  artifact_id: string      // e.g., "cmd-1706119234567.txt"
  search?: string          // Optional: grep-like search
  offset?: number          // Optional: byte offset
  limit?: number           // Optional: max bytes (default: 32KB)
}

Tool Result Format

When output fits in preview:

Command executed in '/project'. Exit code: 0
Output:
npm install completed successfully.

When output exceeds preview:

Command executed in '/project'. Exit code: 1

Output (47.3KB) persisted. Artifact ID: cmd-1706119234.txt

Preview:
> npm test
FAIL src/integrations/terminal/...
...

Use read_command_output tool to view full output if needed.

Success Criteria

  • Commands producing <4KB output work identically to before (inline)
  • Commands producing >4KB output create artifacts in task storage
  • Agent can successfully use read_command_output on artifacts
  • Artifacts are cleaned up on task completion
  • Artifacts are cleaned up on history rewind/delete
  • Settings UI shows new dropdown, old sliders removed
  • No increase in memory usage for large outputs
  • Context window usage is predictable (preview size)

References

  • Detailed implementation plan: plans/terminal-output-refactor-plan.md
  • Claude Code research: .roo/commands/claude-code-terminal.md
  • Current implementation: src/core/tools/ExecuteCommandTool.ts

Metadata

Metadata

Assignees

No one assigned

    Labels

    EnhancementNew feature or request

    Type

    No type

    Projects

    Status

    Triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions