Skip to content

File browser: phased implementation plan #479

@srid

Description

@srid

Phased implementation plan for the file browser feature (#460), informed by the prototype in #475 (which will not be merged — it was an exploratory spike to validate the UX) and Superset's file browser / diff viewer architecture for reference.

Each phase is self-contained with user-visible output. Phases A–F replace the original Phases 1–2, broken into smaller vertical slices.

Phase 0: 3-column layout + live terminal metadata inspector — ✅ #483

  • Refactor App.tsx from 2-column (sidebar + terminal) to 3-column (terminal list | terminal | right panel) using Corvu <Resizable>
  • Right panel is resizable via drag handle, collapsible with Cmd+B + header toggle button
  • useRightPanel.ts singleton managing panel state (open/closed, active view, panel size)
  • RightPanel.tsx shell with view routing via ts-pattern
  • Metadata inspector: live view of the active terminal's full context — complete CWD path, repo root, branch, worktree status, PR details (number, title, CI checks, URL), agent state + model + task progress, foreground process name. All data already flows via onMetadataChange — this is pure rendering, zero new endpoints.
  • Introduces the layout pattern that all subsequent phases plug into

User gets: a persistent workspace context panel alongside their terminal. See the full picture (branch, PR, CI, agent state, CWD) without squinting at the header's one-liner.

Phase 0.5: Right panel multi-tab infrastructure — ✅ #501

  • Nested rightPanel preference object (collapsed, size, tab) with deep-partial patch support
  • RightPanel.tsx tabbed navigation via TABS config array + Dynamic routing
  • Files tab and Git tab: placeholder shells ("Coming soon") for Phases A & E
  • Inspector tab: unchanged
  • Shared Section component extracted from MetadataInspector
  • right-panel/ directory (renamed from inspector/), agentDisplay moved to ui/
  • Server migration 1.7.0 strips old flat fields, sets rightPanel defaults

User gets: tabbed right panel with Inspector, Files, and Git tabs.

Phase A: fs.listDir + lazy directory tree in Files tab

The smallest vertical slice that delivers a real file browser. No search, no peek, no watching — just a tree.

Server:

  • Add fs.listDir to the oRPC contract — input: { terminalId: string, path: string }, output: { entries: { name, isDirectory, path }[] }
  • Server handler: resolve the terminal's CWD/repo root, readdir the requested path, return sorted entries (directories first, then files, alphabetical)
  • Path traversal guard: requested path must be under the terminal's repo root

Client:

  • Add @ark-ui/solid dependency — SolidJS-native tree view with built-in async loadChildren, keyboard navigation, typeahead, and unstyled compound components. Built on Zag.js (same ecosystem as Corvu).
  • Wire RightPanel.tsx tab bar to switch between Inspector / Files (tab markup exists, currently hardcoded)
  • FilesTab.tsx: Ark UI TreeView with loadChildren calling client.fs.listDir, rooted at meta().git?.repoRoot ?? meta().cwd
  • File/folder icons, expand chevrons via BranchIndicator
  • Manual refresh button in the tab header

User gets: browsable, lazy-loaded file tree alongside their terminal.

Phase B: File peek + syntax highlighting

  • fs.readFile endpoint (with size guard — e.g. 2MB limit)
  • Clicking a file in the tree opens an inline read-only preview in the right panel
  • Syntax highlighting via a lazy-loaded library (highlight.js or Shiki)
  • Breadcrumb navigation back to the tree

User gets: click any file to preview its contents with syntax highlighting, without leaving the terminal.

Phase C: Fuzzy file search + Cmd+O

  • fs.search endpoint — server-side fuzzy matching
  • Cmd+O overlay: debounced query → ranked results with match highlighting
  • Selecting a result opens peek view (Phase B)
  • Command palette "Browse files" entry

User gets: fast file finder across the entire repo.

Phase D: Git status in file tree

  • Extend fs.listDir response with per-file git status (or separate fs.gitStatus endpoint parsing git status --porcelain)
  • Color-coded dots/badges on tree items (green = added, blue = modified, red = deleted)
  • Status propagation to parent directories (dot if any descendant is modified)

User gets: at-a-glance view of what's changed in the repo, right in the file tree.

Phase E: Changes tab + diff viewer

  • fs.fileDiff endpoint — returns old/new file contents for a given path and diff category (against-base, staged, unstaged)
  • Right panel Changes tab: lists modified files with status badges (M/A/D)
  • Click file → inline diff view with add/remove coloring
  • Side-by-side vs unified toggle
  • Breadcrumb navigation ("Changes › path/to/file") with smart go-back

User gets: sees exactly what their agent changed, with inline diffs.

Phase F: Live file watching

  • fs.onChange streaming endpoint (oRPC event iterator) using fs.watch with debounce
  • Auto-invalidates tree for changed directories
  • Auto-invalidates search results and diff viewer for changed files
  • This is last because manual refresh works fine, and fs.watch is the hardest to get right (especially flaky on Linux under parallel workers)

User gets: the file tree and diffs stay up-to-date automatically as the agent works.


Prototype PR: #475 — contains the full exploratory spike. Reference for UX decisions and architectural patterns, but the code itself will be rewritten.

Architecture reference: Superset's file browser uses @headless-tree (React) + simple-git + @pierre/diffs for its equivalent features. Kolu's approach uses Ark UI's TreeView (SolidJS-native, same Zag.js ecosystem as Corvu) and defers complexity (watching, search, diffs) to later phases.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions