# Terminal File Viewer Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** File paths in terminal output become clickable; a click opens the file from the project's container in its own OS window with a CodeMirror 6 editor that highlights the target line, live-reloads on a 2 s poll, and saves with hash-based conflict detection. **Architecture:** A pure matcher plus an xterm `ILinkProvider` find paths in the terminal buffer and call one Rust command, `open_file_viewer`, which probes the candidate container paths in a single exec and opens a `file-viewer-` window on a second Vite entry (`viewer.html`). A managed `ViewerRegistry` maps window labels to targets; every viewer command takes `window: tauri::Window` and operates only on its caller's entry, so no viewer command ever accepts a path. Reads use the existing archive-API fetch; polls are one `sha256sum` exec; saves stage bytes in `/tmp` via the existing tar upload and then let a `sh` script running as the container user do the hash check, `chmod --reference` and `mv -f`. **Tech Stack:** Rust (tauri 2.11, bollard 0.18, sha2, base64, uuid), React 19 + TypeScript, @xterm/xterm 5.5, CodeMirror 6 (`@codemirror/*` 6.x, `@lezer/highlight`), Vite 6 multi-page, Vitest + jsdom. **Spec:** `docs/superpowers/specs/2026-09-22-terminal-file-viewer-design.md` — read it first, including "Decisions made during review", which records why each mechanism below is the one chosen. ## Global Constraints - **User-approved decisions are fixed:** one window per click, editable, CodeMirror 6, probe-roots resolution, 2 s polling, no autosave, "Changed on disk" conflict banner, 20-window cap, AppManifest lockdown deferred. - **Design tokens only.** All colour from CSS custom properties in `app/src/index.css` (`--bg-primary`, `--bg-secondary`, `--border-color`, `--text-primary`, `--text-secondary`, `--text-disabled`, `--accent`, `--accent-emphasis`, `--warning`, `--warning-muted`, `--success`, `--radius-control`, `--radius-panel`). Filled buttons use `--accent-emphasis`. Never `focus:outline-none`, never `disabled:opacity-50`. - **Use `components/ui` primitives** (`Button`, `StatusIndicator`) — do not hand-roll replacements. Status is never colour alone. - **Frontend types in `lib/types.ts` must match Rust structs field-for-field** (snake_case both sides). - **Every `#[tauri::command]` goes into `generate_handler![]` in `lib.rs`, one fully-qualified path per line.** The test `every_command_is_registered_exactly_once` (`lib.rs:759`) fails otherwise. - **No viewer command accepts a path or a label argument.** Commands take `window: tauri::Window` and gate on `window.label()`. - **`viewer.html` must not contain an inline `