Skip to content

feat: TUI deploy and launch pickers, filtering, unified artifact view#89

Merged
N4M3Z merged 22 commits into
mainfrom
p2e-tui-ux
Jul 13, 2026
Merged

feat: TUI deploy and launch pickers, filtering, unified artifact view#89
N4M3Z merged 22 commits into
mainfrom
p2e-tui-ux

Conversation

@N4M3Z

@N4M3Z N4M3Z commented Jul 13, 2026

Copy link
Copy Markdown
Owner

Problem

The TUI shows module and artifact state but offers no way to act on it: no deploy or launch from inside the app, no filtering in long lists, an inert Overview, and inconsistent detail views between artifact kinds. #88 carried this work but merged into the p2d-polish branch after #83 had already squashed into main, so none of it reached main.

Approach

Deploy-to-target and harness-launch pickers (including single-artifact deploy via a slug-safe --only filter and persistent targets in ~/.config/forge), in-panel filtering with / and problems-only with !, an enterable Overview that jumps to status and kind views, one unified artifact detail with numbered tabs across skills, ADRs, and companions, digits scoped to detail tabs with letter shortcuts for sections, tuicr-style word wrap and diff hunk navigation with per-line commenting, clickable commits, and git plus jj views. The deploy path is rebased over #86's per-kind target roots: corrupt-manifest refusal and ensure_destination_within now apply per kind root.

Test plan

  • cargo fmt --check
  • cargo clippy --all-features --all-targets -- -D warnings
  • cargo test --all-features (671 passed)
  • Snapshot render via forge tui --snapshot on the rebased tip

🤖 Generated with Claude Code

N4M3Z added 22 commits July 13, 2026 04:19
- forge tui --snapshot renders one frame headless (width/section/drill/row/tab)
- list rows drop the redundant kind; middle column sizes to full row content
- vendored zero-margin glamour style so previews sit flush to the pane border
- glow output is not re-wrapped by the paragraph, keeping tables aligned
- per-artifact version line: branch or jj bookmark, worktree state, last commit
- m opens the tuicr comment prompt from Preview/Diff/etc by switching to Code
- footer hint row is context-sensitive when the detail pane is focused
- toasts clear on the next keypress instead of masking the hints forever
- ArtifactView carries source_path; vcs matching prefers it over the deploy
  key so monorepo layouts resolve the right file
- porcelain -z parsing: verbatim paths, unambiguous renames
- ahead/behind falls back to the resolved branch upstream and origin/<branch>
  when HEAD is detached (jj colocated)
- glow style file lands via write-then-rename, safe across processes
- click focuses panes, selects sections and list rows, switches detail tabs;
  wheel scrolls the viewport under the cursor and never moves selection
- code and glow-preview tabs render only the visible line window, so large
  files scroll at full speed instead of re-cloning every line per frame
- fenced code blocks in previews highlight through syntect (the Code tab
  engine); glow renders the prose around them
Prose segments hand glow the full reference-definition list, so links keep
resolving when their definition lives past a code fence.
- code-tab scroll clamps to the last line, not the last page, so every
  visible line can become current and take a comment
- the code window wraps its visible slice: long lines stay readable
- border and blank-row clicks focus a pane but never select
- fences respect CommonMark: four-column indents are literals, and a block
  closes only on a fence at least as long as its opener
- the fullscreen zoom renders through the same pipeline as the detail pane:
  glow preview, highlighted code, colored diff; digits switch tabs while open
- ADR detail shows the whole document through the markdown renderer instead
  of a truncated summary paragraph
- the Diff tab shows the source file's uncommitted changes, pager-colored;
  Provenance appends the adoption sidecar highlighted as YAML
- repository detail gains local path, branch/jj state, recent commits, and
  o/O to open gitui or jjui in the repo (TUI suspends and resumes)
- every detail tab renders from a cache keyed by target, tab, and width;
  per-frame rebuilds were the main source of input lag
Two modules can ship the same relative path; the cache key now includes the
module name so switching between them rebuilds instead of showing stale
content.
- git diff failures and untracked files no longer render as "matches HEAD";
  the exit status is checked and untracked artifacts say so
- a completed rescan rebinds the open zoom to the fresh artifact, or closes
  it when the artifact is gone
- Preview and Diff rebuilds wait for the input queue to drain, so holding
  j/k browses at full speed instead of serializing a subprocess per row
…nest copy

- the list column scrolls: the viewport follows selection changes and the
  wheel scrolls it independently; clicks account for the offset
- glow stdin feeds from a thread, removing the pipe deadlock on large bodies
- comments are keyed by module as well as path, and the tuicr digest names
  the module; y really copies the source path via pbcopy
- a deferred rebuild renders a placeholder instead of another artifact
- rescan keeps the selected row by identity, not index; finishing gitui/jjui
  triggers a rescan; refresh is debounced while a scan runs
- zoom clamps scrolling against wrapped display rows and survives rescans
  with its position; terminal state unwinds if setup fails partway
- per-repo VCS state is scanned once per repo, staleness and VCS agree on
  the source path, and the glow style file is per-user
- dashboard route test fixtures compile under --all-features
… clamps

- Esc walks focus back and quits only from Sections; quitting with unsaved
  comments asks for a second press and points at Y
- finishing gitui/jjui force-restarts the scan, superseding one in flight,
  so the view reflects what the tool changed
- non-windowed detail scroll clamps against wrapped rows and resets when
  the selection changes, so short content never renders as a blank pane
- ADR detail defers rebuilds while keys are queued, like artifacts
- the review digest falls back to a temp file when pbcopy is missing
  instead of vanishing into the alternate screen
- search has an explicit input mode: / focuses and edits the query, Enter
  or Esc returns keys to navigation, and the header shows which mode is on
- the sections column shows the letter shortcuts that actually work for
  Settings/Hooks/Config/Schemas; G jumps to the bottom of the detail pane
…iff hunks

- digits switch sections from any focus; detail tabs cycle with Tab and the
  letters p/c/d/v/f/i/n; the tab bar drops its dead numbers
- status column uses gitui letters (M modified, ? new, ! stale, · clean)
- row detail renders only on the selected row; the list column slims to
  label width and nothing truncates while browsing
- the Overview mode row toggles on Enter and click, not just m
- word wrap preserves the gutter: continuation rows align after line
  numbers and key columns with a ↪ marker (code pane, zoom, frontmatter);
  wrap_plain keeps explicit newlines
- diff gets hunk separators, [ and ] navigation with hunk x/y in the
  footer, and untracked files render their whole body as added lines
- ADRs and skill companions render through the same tabbed artifact view
  as scanned artifacts: preview, code, diff, provenance, frontmatter,
  history — synthesized on demand and cached
- companions appear as indented child rows under their parent skill
- provenance is a structured view: aligned keys, shortened shas, empty
  fields omitted, per-target ✓/✗ badges with per-harness rows
- a rule separates file properties from content in the preview header
- o/O open gitui/jjui from ADR and companion rows too; m starts a comment
  straight from the list; the status bar counts unsaved comments
- the Code tab gains a line cursor decoupled from the viewport: j/k and
  paging move it and the viewport follows only when it exits; the wheel
  scrolls without touching it; m comments the cursor line; g/G jump it
- paging is sized to the pane (PgUp/PgDn, space/b) plus Ctrl-d/Ctrl-u
- re-pressing the active tab key no longer resets the scroll position
- the Detail title shows position n/N; clicking the selected row drills
- Provenance, History, and Companions pre-wrap like the other tabs, so
  scroll clamping is exact everywhere except the rare plain fallback
- diff rows carry an old/new number gutter parsed from hunk headers;
  untracked bodies are numbered too
- the detail cursor works in the Diff tab: j/k and paging move it with the
  viewport following, hunk jumps land it on the header, the row highlights
- m on a diff row comments the mapped new-file source line in place;
  header and deletion rows decline with a toast instead of mis-anchoring
… READMEs

- the tab bar shows numbers again and digits follow focus: sections while
  browsing, detail tabs 1-7 when the detail pane or zoom has focus
- glow was silently dropping every color because it saw a pipe instead of
  a terminal; CLICOLOR_FORCE and COLORTERM restore full-color previews
- the glamour style differentiates heading levels, styles quotes, links,
  emphasis, and rules
- repository detail renders the repo README through glow below the header
  and commit log, cached and scrollable like every other detail view
- D on an artifact, companion, ADR, or repository opens a target picker
  (user scope, this project, watched locations); Enter suspends the TUI
  and runs install --source <module> --target <choice> --no-prune, then
  rescans — additive deploy, nothing at the target is pruned
- L suspends into a harness session in the module repo: FORGE_TUI_LAUNCH
  when set, the claude CLI otherwise, forge launch once this binary has it
- external commands generalized to program + args + directory
- install/deploy gain --only <prefix>: deploys just the files under a
  module-relative prefix and never prunes, so adding one artifact to a
  target leaves everything else there untouched
- D on an artifact deploys exactly that artifact (skills carry their
  companions, agents/rules match across provider extensions); on a
  repository row it deploys the whole module — the picker title says which
- the picker ends with an add-target row: type a path (~ expands, must be
  an existing directory), it persists to the watchlist and becomes a
  selectable target immediately
- L opens a harness picker (FORGE_TUI_LAUNCH first when set, then claude,
  codex, gemini, opencode) and suspends into the session in the module repo
- --only matching survives provider renames: keys and prefixes compare
  lowercased with separators dropped, so gemini/opencode slugs still match
- every content write validates its deepest existing ancestor against the
  target base, so a symlinked directory under the target cannot redirect a
  deploy outside it; boundary validation runs before any directory exists
- provenance sidecars copy only alongside content that actually installed;
  a locally-modified skipped file keeps its previous sidecar
- a corrupt target manifest aborts filtered deploys instead of silently
  rewriting the manifest down to the filtered keys; full deploys warn
- the add-target row reports watchlist failures instead of claiming
  success, and persistence no longer prints inside the alternate screen
- open pickers block mouse events from reaching the panes underneath
- custom launch commands split into program and arguments
…nion surface

- digits 1-6 switch the detail tabs from any focus and nothing else; the
  sections column drops its confusing numbers (letters t/h/c/m remain)
- the Companions tab is gone: companions live as child rows in the list
  with the full artifact view
- commit rows in History and repository detail open the commit in the
  default browser on click (https sources)
- repository detail shows recent jj changes beside the git log, with
  change ids and bookmarks
…ns, positions

- / filters the focused list in place (Esc restores, Enter keeps); ! shows
  problems only; the list title names the active mode; the Search section
  keeps its own query input
- the Overview is a launcher: Needs-attention counts open the Search view
  pre-filtered, inventory kinds open their section, and modules open the
  section with the filter set to that module
- the owning module (or variant qualifier) is a dim right-aligned column on
  every row, truncating from the left; Variants disambiguate inline and
  their detail shows the actual variant body
- empty states name the next key (history, gitui, deploy) and empty module
  fields are omitted; hints are purposeful per focused pane; list titles
  carry position x/y
- every section has a letter shortcut, shown as its row prefix
- Overview module rows jump via the Search module filter instead of a
  substring text filter, so similarly named modules and companion rows
  scope correctly
- filter edits and the problems toggle reset the list viewport with the
  selection, keeping the highlight on screen
- the right-aligned detail column measures display width (wide and
  combining characters) and truncates on real column boundaries
- help matches dispatch: / filters the focused list, the dead n binding is
  gone, and tab letters note their Sections-focus exception
@N4M3Z
N4M3Z merged commit 0b4be26 into main Jul 13, 2026
4 checks passed
@N4M3Z N4M3Z mentioned this pull request Jul 13, 2026
4 tasks
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.

1 participant