Releases: americanjeff/changestab
Release list
v0.3.0
Changes view: the message, per-commit divergent selection, smarter diffs
The selected change's full message
- New read-only
descendpoint (jjlog -G -T description, gitlog -1 --format=%B; trailing newlines stripped; rev validated, backend failures and non-VCS workspaces degrade to empty). - The files pane shows the fetched message for the current selection — any non-empty one, subject included — in a strip above "Files changed". Plain text, no markdown.
- The client fetches per selection, commit-id keyed (a divergent change's two rows resolve to their own commits), per-view cached, cleared by the reload; degrades to no strip on failure or a dead session.
Per-commit selection of divergent changes
- A divergent (branched) change's rows share one change id — selecting one row used to highlight all of the change's rows and clicking a sibling was a no-op. Selection identity (the row's data attribute, the snapshot fetch rev, the desc rev, the agent ref tokens) is now the commit id (git rows have no commit id — their id is the sha), so each divergent row selects and reviews its own commit. The
/Nchange offset stays display-only. - A one-time migration remaps a saved change-id rev to that row's commit id (first match = the newest, offset 0) so a reviewed change survives the upgrade instead of silently degrading to the worktree.
Diff display: whitespace handling + better row pairing
- An "ignore whitespace" toggle in the pane head (re-fetches with jj
-w/ git--ignore-all-space; the binary byte cache is kept across the toggle). - Moved or whitespace-only mod rows now pair with their own copy — whitespace-normalized line matching with a positional fallback for the leftovers, capped at 100k row-pairs per block — and render dimmed with a tooltip ("moved line" / "whitespace-only change") instead of as full red/green false changes.
- The git backend diffs with
--histogramalignment (anchors on rare lines first — better alignment when a block repeats, at myers-like speed; requires git ≥ 2.33). jj exposes no algorithm flag. - A file whose changes vanish under ignore-whitespace (zero hunks) gets a "no changes" note instead of a blank pane.
Housekeeping
- e2e re-verified against dsh 0.2.0-rc.2: both hashed CSS-module classes and the workspace-picker / composer labels still resolve — zero selector changes.
v0.2.0
v0.2.0 — a changes view, not a file browser
changestab pivots from a file browser to a read-only Changes view: a jj/git change tree, each change's changed files, and diffs — nothing else. The tab, the package, and the plugin row are all renamed from filestab to changestab.
The view
- Pivot to changes-and-diffs: the tab is now "Changes" and shows CHANGED FILES and DIFFS only. The nav pane is a change tree (jj or git): the working copy is the top row, rendered by the very same row code as the commits (diamond glyph, its own change id in jj's shortest(8) form, "Editing" in place of the author date, head bookmark/tag pills, description with the commit rows'
(empty)/(no description set)conventions); commits stack below with solid/hollow/red-slash glyphs, bookmark+tag pills, and relative author dates (the host fetches the last 50; the log pane scrolls the rest). Selecting a row lists that change's files, directory-grouped with the directories expanded by default, each file carrying its status badge (A/M/D/R/C/U). The preview pane is diff-only — side-by-side or unified depending on pane width — and the change list, the badges, and the open diff update live. - Split panes: the nav column divides into the change log (top, its own scroll region) and the changed-files list (bottom) with a movable horizontal divider between — drag to resize, double-click for the default height; the log's height persists per session.
- Change-log auto-load: the log pane no longer stops at the first 50 commits — scrolling it toward the bottom fetches the next page (50 at a time, via a new host
logendpoint) and appends the older commits in the same jj-log order, with a quiet pulsing note at the end while a page is in flight. A short or empty page ends the log; there is no "load less". A fresh listing that moves the history drops the appended pages and re-pages from the new top. - Root row: a jj log now terminates at its root commit — the all-z root renders as the final row with a localized "root" label in the date slot (in place of the root's epoch author date) and a blank description (the
(empty)marker would be noise for the log's floor), so the history ends at a visible floor the graph's line lands on and stops, instead of running off the bottom edge. Git has no synthetic root, so its log still ends at the parentless commit.
The graph
- jj-log-style lanes: the change list draws the history as a jj-log-style lane graph — the working copy is the first node, and parents, merges, and siblings each get their lane; a parent outside the window (elided under the fold, or on a not-yet-loaded page) runs its line out of the bottom edge — except at the root (the log's floor), where a dangling line is clipped so it cannot run off past the root. The vertical lane lines run continuously from node to node: a lane that passes through a row (or a node with both an incoming edge and a parent) spans the row's full height, so a straight history renders as one unbroken line instead of stopping at each node.
- Node characters: the graph's node symbols are jj's own log glyphs, host-supplied per commit from its
builtin_log_nodetemplate —@working copy (accent, bold),◆immutable (bold),×conflicted (red, bold),○normal (dim) — the CLI's characters rendered as text, styled after the CLI's node label colors. The worktree row carries@the wayjj logdoes; git rows and stale listings keep○. - jj-style change ids: commit rows render the id in jj's
shortest(8)form, the significant (unique) prefix highlighted and the rest dimmed (jj rows; git rows show the plain short sha), the full id in the tooltip. - Branching and divergence: rows and graph edges key on the COMMIT id (a divergent change has several commits sharing one change id, which can't identify a row), so a fork or merge renders its siblings on separate lanes. Divergent and hidden commits get jj's commit labels —
(hidden)(dim, takes render precedence) /(divergent)(red) /(conflict)(red) — and the change id grows jj's bold/Nchange offset (xyz/0,xyz/1, newest first). Selection, the snapshot fetch, and the agent ref token stay keyed on the CHANGE id, so both rows of a divergent change select the same change, asjjdoes. - Branch visibility: the change list now shows jj's own default
jj logscope (builtin_log() ~ @) instead of the worktree's ancestry alone — a branch that forked off and never re-joins the worktree's path (a sibling of an ancestor) now renders on its own lane, matching what the terminaljj logshows.
Interaction
- Click-to-ref: clicking a diff line shows the exact
@path:lineref in the head row (drag a range of lines for a selection ref carrying the selected text), with copy and add-to-chat buttons. The head row's "Open in Files" button hands the viewed file to the built-in file viewer (a stock file tab in the right column) — plain viewing belongs there. - Session recovery: when the host reports a dead session (a server restart), the view now retries automatically a few times (1.5s / 3s / 6s) — a restarted server cold-resolves the session by id — and only then shows the terminal notice; the ⟳ button remains the manual escape hatch.
- Stable nav: selecting a change no longer reloads the nav: the worktree listing and the snapshot listing (the selected commit's files) are kept apart, so the change list stays mounted and judder-free across selections.
- Stock row metrics: changed-file rows wear the stock file browser's exact row metrics (13px/1.5 primary text,
5px 10pxrow padding, 6px gap, radius-md, 18px per nesting level) — the status badge takes the stock row's 16px icon slot, so the name column lines up with a stock tree. - Non-VCS workspaces render an empty state with the handoff to the built-in file browser instead of a tree.
Removed
Every content preview mode (markdown/mermaid, sandboxed HTML, images, raw source and its character-click ref), the full workspace file tree, the commit-review dropdown, the in-pane jj roll/describe/drop actions, the external (out-of-workspace) file section, and "open locally". The view no longer reads file contents — only diffs.
Rename
filestab → changestab: the package, dsh plugin row, and tab kind all take the new name to match the view (a changes-and-diffs tree, not a file browser). Reinstall under the new name (dsh plugin --profile web add changestab); deploy.sh's one-time migration drops the old filestab link. The display title is now "Changestab".
v0.1.7
v0.1.7
Filestab sits next to the built-in file browser
- The right column shows both guide capsules — "Files" (built-in) and "Filestab" — and both page tabs can be open side by side, with filestab's selection independent of the built-in viewer.
- File opens (chat file chips, "Files changed" rows, the stock tree) route to the built-in file viewer; filestab remains the VCS-aware workspace viewer (expandable tree, diff, rev browsing, live updates).
- Claiming those opens for filestab is an available option: re-register the type to take
dsh-resource://file/**on the extension band.
Fix
- Restored pane state (the expanded set in localStorage) is normalized on load, and the live-update tick dedupes its targets — the tick's positional listing mapping stays aligned, so a re-opened pane shows the workspace root contents immediately.
v0.1.6
v0.1.6
The Files view updates live while it's open, and you can point the agent at an exact spot in a file.
- Live file updates — the file list, the change marks, and the open preview now update while the view is open: edits by the agent or on disk appear within a few seconds, no reload or re-selection. A file the agent changes updates its preview and its row marker on its own, right after the edit lands.
- Precise refs — click a character in the raw view and the head row morphs from the file path into the exact
@path:line:coltoken, with copy and add-to-chat buttons; the agent can then change exactly that spot. Clicking the rendered markdown preview resolves to the source line too (a code fence or plain paragraph gives the exact:line:col). - jj unadded marker — in jj workspaces a new file shows the unadded (U) marker, matching git's
??(jj has no staging area — a worktree add is the unadded state). - Selection opens as content — selecting a file opens it as its content (preview for markdown, raw view otherwise), never as a diff; an explicit Diff pick is soft-sticky for the session.
v0.1.5
The Files view moves into the dsh 0.1.5 right column, gains an External section for files outside the workspace, and the diff view picks up a set of fixes.
Right column (dsh 0.1.5)
- filestab now serves the right sidebar's files slot: the column opens straight onto one filestab view — no more built-in per-file tabs, no more conversation-area Files tab.
- File chips in the conversation select their file in that view and scroll to the mentioned line.
- The file list collapses/restores as a state-pair toggle:
»in the list header,«in the view bar while collapsed — and the list is preserved when a file is opened from a chip. - The viewed file's name appears at the top of the preview pane in every mode.
External section
- Pin any file outside the workspace by absolute path — via the footer's "Open file…" or a file chip whose workspace resolution fails. Pinned files persist per session and preview in the same pane (view/preview only).
Diff view
- Side-by-side falls back to unified below ~66 reference columns.
- Working-copy and last-commit image diffs render the old|new images.
- A text file whose content merely contains git diff marker strings no longer reports as binary.
- Containment is lexical: a symlink inside the workspace reads through to its target.
Coarse changelog: CHANGELOG.md · Built and e2e-pinned against dsh 0.1.5-rc.2.
v0.1.4
v0.1.4
Restores filestab on dsh 0.1.5.
What changed for users
- The Files tab — main area, a sibling of the Chat and Trajectory tabs — works again on dsh 0.1.5. On 0.1.5 the tab mounted but stayed empty: dsh's
connection.rpc.handlecustom-channel registration is broken in web deployments (the route effect readswebServeroff a plain, inject-gated context and throws, so no route ever lands), and every browse request got a 405.
How
- The browse route (
/filez-browse) now registers directly on thewebServerservice, mirroring the built-in/apiroute: the same trusted-hostrequestRejectionfence, the sameclient-request/server-responseenvelope, plus a request-body cap. The route refuses to mount if the fence is missing. - The end-to-end suite (real headless browser against a scratch dsh instance) is re-pinned to dsh 0.1.5-rc.2: the 0.1.5 landing / workspace-picker / composer flows, the token-bearing browser URL, and the conversation view tabs.
Verified
- All 8 unit suites green (containment, magic, filesystem, host, jj, git, client), including new fence-401 / malformed-400 / over-cap-413 route-transport assertions.
- End-to-end suite against dsh 0.1.5-rc.2: 63 assertions green across all journeys (J1, J1.2, J2, J3, J4, J5, J6, J18, J19) in both a jj workspace and a plain workspace.
v0.1.3
What's new
- Files view: pane-edge rail for the collapsed file list (BUG-011). Collapsing the list now leaves a slim raised rail at the pane edge — the panel glyph at top with a hairline right border — so a restored collapsed session reads as "collapsed" instead of "the tree vanished". Click, Enter, or Space on the rail to expand. The header toggle now shows only while expanded: one affordance per state.
- Markdown preview links open in a new tab (BUG-012). Clicking a link in the rendered markdown preview no longer navigates the dsh web GUI to the referenced page and replaces the session; preview anchors now carry
target="_blank" rel="noopener noreferrer".
Update
dsh plugin --profile web add filestabThe tarball below is the official npm registry artifact for filestab@0.1.3.
v0.1.2
New
- @path section refs: selecting a file in the Files view references it by path — from the selection toolbar, the right-click context menu, or "add to chat".
- Open locally: new action opens the viewed file on the local desktop (loopback-only, via dsh's own
host.openPath). - Copy path: new action copies the file's absolute path.
- File row meta: file rows now show size and relative last-modified time.
Fixed
- Intra-line diff spans (BUG-010): a changed phrase no longer fragments into word islands separated by plain spaces — the whitespace inside a changed phrase is highlighted with the phrase, matching how git's word diff and diff-highlight render the same change.
- Heavily rewritten lines no longer churn into fragmented del/add spans; the flat row tint takes over (BUG-004).
- The collapsed file list is now easier to notice, and returning to a session no longer makes the tab look broken (BUG-007).
- A deleted folder shows a friendly note and the Files view returns to the workspace root, instead of a raw
internal: not-found(BUG-009).
Note: host-side behavior requires a dsh-web restart to take effect.
v0.1.1
v0.1.1
Fixed
- Files view now supports cold (persisted, not-live) sessions.
- Nested jj/git repos no longer appear in worktree listings.
Housekeeping
- Dropped the machine-local
.npmrcthat was accidentally included in the initial snapshot. - Added a coarse
CHANGELOG.md(per-release, one section each) with a pointer from both READMEs.
v0.1.0
Read-only Files tab for the dsh web GUI.
- Browse the session workspace with live jj / git change tracking
- Side-by-side diffs, history snapshot mode
- In-harness previews: Markdown (mermaid), syntax-highlighted source, sandboxed HTML, images/PDF
Install: dsh plugin --profile web add filestab (npm) — see README.
Built from tag v0.1.0 (the flat initial commit); npm package filestab@0.1.0
(shasum b69e3fa20d3440f69aabb339f22a1cc7fcc20d1a).