feat: TUI deploy and launch pickers, filtering, unified artifact view#89
Merged
Conversation
- 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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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-polishbranch 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
--onlyfilter 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 andensure_destination_withinnow apply per kind root.Test plan
cargo fmt --checkcargo clippy --all-features --all-targets -- -D warningscargo test --all-features(671 passed)forge tui --snapshoton the rebased tip🤖 Generated with Claude Code