Carry the v4 language into the diff overlay and the commit detail view:
0.5px hairlines at 8% ink, 26px row pills with a 6px radius, the rem type
ladder from right_panel.rs, neutral chips instead of accent washes, the
shared git_badge for status letters, and tabular figures on counts.
Layout, spacing, type and colour only; no behaviour or i18n changes.
- Rows pad 8px inside lists inset 12px, so text sits on a 20px column in
every tab and hover fills start 12px in with a 6px radius. Headings,
empty states and the Ports line move to the same column.
- Tab labels 18px apart; the panel row's chrome tiles are 26px, 4px
apart, 12px from the edge. Default panel width 280.
- Info: label column floor keeps values at x=88; Ports add tile 22px.
- Changes: 8px top gap on macOS, pinned block on 14px edges with the
branch at 22, 12px sync glyph, 8px group chevron, 10px status cell,
1px between rows.
- History: compact gutter for single-lane pages, filtered rows on the
text column, 10px row gap, 24px age floor, header on 20px insets,
4/12 padding when expanded (heights re-counted in commits).
- Files: search well at 12px with an 11px glyph, 10px before the tree,
16px indent step, 16px bottom padding.
- Default Light/Dark take warm neutrals (#fcfcfb/#1c1c1e, #18181a/#ececed);
Git added/modified seeds follow v4 green and amber.
- The left rail gets its own tinted fill again (Neutrals.rail, 3% toward
the ink) with its own surface ladder; the right panel keeps the content
fill. Captions and hairlines are floored on the rail too.
- Title bar is 48px; the bar over the terminal centres the active tab's
title in caption ink when tabs live in the rail.
- Rail header: 26px new-tab and collapse tiles, then the workspace chip
and search field (28px, 7px radius).
- Groups sit 16px apart under a 22px caption heading with
'branch · +a −d' in tabular numerals.
- Rows are 30px (42px with a branch line), 16px avatars, medium weight
when current, branch cut from the front, and a trailing 5px status dot
(blinks while working, hollow while waiting, unread count as a pill).
- docs/design-system.md updated.
- Pinned block keeps 8/10/14 rhythm; branch name medium, 26px sync tile.
- Commit message box rests at 56px with a 7px radius.
- Split commit control: inverted neutral fill when committable, faint
fill otherwise; 6px radius and an inset 0.5px seam.
- Change groups sit 16px apart under 22px sentence-case medium headers;
file names take width first and directories right-align, eliding
from the start.
- History: 32px header, 26px rows inset with rounded hover, 1px lines
and 7px beads (HEAD filled, others hollow), neutral inks on a
single-lane page, age column always shown, faint HEAD pill.
- Card: 112px from the top, 12px corners, 48px search row with an esc
keycap, 420px body split 340px / preview, 40px footer.
- Workspace rows are 52px: a 26px initial disc carrying the link state as
a ringed dot (live green, faint when offline, amber while connecting,
red on failure), a medium name with its stable number, a machine ·
path · time line, and the tab count over the state word.
- Preview rows are 44px with the sidebar's 18px brand disc, an all-muted
branch · diff line, a Current label and a 5px dot that blinks with the
sidebar while an agent is working.
- Footer: ghost New workspace button and keycap hints for navigate, open
and new window; the unused click-for-new-window string is dropped.
- Tab row: 12.5/16rem word tabs 22px in and 18px apart, the current one in
body ink at medium weight; no hover pill, no underline bar, no hairline
under the row.
- Info: Session, Processes and Ports are spaced 16px apart with no rules;
28px medium muted headings, 28px Session rows on a 76px label floor with
values in body ink, 26px process rows with a tree elbow for children, and
an explicit empty line for Ports.
- Files: the search sits in a 28px filled well; tree rows are 26px with a
disclosure chevron column, ignored entries dim their icon instead of
going italic, and a folder's change dot is 5px.
- docs/design-system.md updated to match.
The README now opens on an animated WebP of the one-minute tour (GitHub
won't play an mp4 inline), linking the full-quality mp4. The docs home
page autoplays the mp4 in the hero slot. The old hero screenshot and the
separate tour poster block are gone.
Every placeholder frame in docs/ now shows a real capture of the current
build: 20 screenshots plus two short looping clips (prompt editor, pane
drag). The README and the docs home page link a one-minute tour covering
agent status across repos, one agent driving another through the CLI,
the prompt editor, diffs, pane dragging, and sessions surviving a quit.
A working agent's dot now alternates every 600ms between its colour and
a paler, still opaque, blend of it over the dot's ring, so a column of
tabs shows at a glance which agents are still going.
It rides the existing half-second home-cursor tick rather than an
animation: two repaints a second while some tab has a working agent,
and none once no agent is working (the dot settles back on its full
colour with one last frame).
On Windows and Linux the tabs sit under a full-width title bar, and a
second 40px band left them well down from the window's top. The row is
now the tab's hover pill plus 2px either side.
Settings used to cover the workspace it was opened from, hiding the
terminal a setting was being tried on. It now opens a separate window.
- The state and page stay on the workspace's Tty7App; a thin
SettingsWindow view borrows it to draw, observes it to repaint, and
sets its own rem size. The state is built against the new window, so
its inputs and subscriptions belong to it.
- Opening again raises the window instead of closing it. Esc, Cmd-W and
the close button go through close_settings_checked, so unsaved forms
and theme drafts still prompt; closing hands focus back to the
workspace window. The window goes when its owner is released.
- open_settings_then / close_settings_then run follow-ups in the right
window: loading an SSH form happens in the settings window, and
Connect opens its tab in the workspace window.
- Window opacity, blur and backdrop are pushed to every window, since
they are now changed from a window that is not the workspace.
- Tests keep the in-window overlay so they can drive settings through
their single test window.
Folded, the history section is the last line in the window and sat flush
against the bottom edge, inside the window's rounded corner. Pad it 2px
above and 4px below; the expanded section is unchanged, so its
commits-per-height pin still holds.
The v5 restyle turned the tab rows, the search field and the workspace
switcher into full pills, which read too round at this density. Put
back CARD_RADIUS on the rows, rounded_lg on the search field and
rounded_md on the switcher (and its rename field), keeping the 28px
row height. PILL_RADIUS has no users left and goes with them.
The workspace switcher painted its picked row a hard-coded #1768CF with
white text, in the workspace list, the tab list and the New Workspace
host dropdown. It bypassed the theme and was the loudest block on
screen. Use the popover's neutral selected step and keep each row's own
inks, so a taken-over warning still reads as one.
- Rails share the window fill and are separated by a hairline only;
the current tab is a neutral selected step plus a semibold title
instead of the blue navigation wash (the unused role is removed).
- Default Light theme takes ink #0F1419 and accent #1F6BF0; the caret
follows the accent.
- Sidebar: 28px pill rows with 18px avatars (two-line rows keep card
corners), pill search field and workspace switcher, group headings
in body ink with the chevron shown only when folded.
- Right panel: word tabs (Info / Changes / Files) with an underline
bar on a closing hairline. The Changes count is dropped before any
label is cut, and the panel floor grows with the measured labels so
the chrome tiles are never pushed off the edge.
- Headings are no longer uppercased; popovers use a 10px radius.
- docs/design-system.md updated to match.
On macOS the panel toggle and app menu tiles sat at the end of the terminal
column's strip whenever the detail panel was closed, including when a docked
diff or file column stood to its right, leaving them in the middle of the
window beside the document's header. Hide them while a document is docked and
stop reserving their width for the tab chips.
Three things went wrong with a Files panel rooted on a distro's \\wsl$
share:
- A drop brought a `name:Zone.Identifier` file along with every
downloaded file. fs::copy is CopyFileEx on Windows, which copies the
NTFS alternate data streams, and the share has no streams to keep one
in, so it lands as a file of its own. A copy onto a WSL share now
moves the contents only; one onto NTFS still goes through fs::copy
and keeps the mark.
- A file removed from the shell in the distro stayed in the tree. The
share accepts a ReadDirectoryChangesW and never reports a change, so
the watch looked healthy and was deaf. Directories on a WSL share are
now watched by a notify PollWatcher every 2s instead, made the first
time one is needed.
- Right-clicking a row did not select it, so nothing marked the row the
menu was about. A right click now selects the row without opening it.
Dropping a RemoteWatch sent WatchClose with a blocking call, and the last
handle is usually let go on the UI thread: from Tty7App::render via
scm_sync_watchers, and from scm_watch_opened when an open lands after its
subscription moved on. Every window froze for a round trip each time, up
to WatchClose's 5 s deadline on a quiet link. Sampling a live instance
caught ~1.1 s of such stalls in 10 s.
- ControlClient::post sends a request without registering for its reply;
the reader already drops replies nobody is waiting for.
- RemoteWatch::drop posts WatchClose instead of calling it.
- pane_workspace_for built the full SSH spec, keychain lookups included,
only to strip the secrets again. It now builds it from NoCredentials,
which takes the securityd trips off pane_liveness::sweep.
Claude-Session: https://claude.ai/code/session_01YX786Hyr4ivijWxv66zVkf
The reader parsed each batch — and a relink's whole replay, up to 8 MB —
in one hold of the grid lock, and every UI-thread handler that touches
the grid queues on it. Feed the emulator in MAX_LOCKED_FEED slices, the
same bound Alacritty's reader uses.
Claude-Session: https://claude.ai/code/session_01YX786Hyr4ivijWxv66zVkf
The interactive cursor-agent TUI fires beforeSubmitPrompt and stop; only
print mode (-p) lacks them. Mapping postToolUse to prompt-submit froze the
activity counter (opportunistic git refresh, agents --changed), shortened
turn timing and hid tool-less turns. Map it to tool-complete instead.
A portable ZIP install whose folder has both the .tty7-portable marker
and a data\ folder next to tty7-app.exe now uses <exe dir>\data as its
config directory, so settings, sessions, scrollback and the daemon's
socket travel with the program. --config-dir and TTY7_CONFIG_DIR still
win. The folder is an explicit opt-in because the marker has shipped in
every portable ZIP since the in-app updater arrived: keying on it alone
would move existing users onto an empty directory at their next update.
The portable directory is not the machine's config dir, so a portable
copy never adopts the installed tty7's legacy tree. An updater test pins
that data\ is not a managed root and survives an in-place update.
SelectWorkspace1-9 and the Window menu numbered workspaces by most
recent use, so switching to one moved it to slot 1 and reshuffled the
rest. Number them by the order this client first had them instead
(the append-only views list), skipping synced remote references until
they are opened; opening one moves it to the end so it takes the next
free number. The switcher keeps its MRU list and shows each row's
number.
With a long prompt the inline editor started at the prompt's end column,
leaving e.g. 24 of 143 columns for the first row of input. When fewer than
max(20, cols/3) columns remain (and the prompt is at least as wide as what
it left, so a new row actually gains room), the input overlay now starts at
column 0 of the row below the prompt.
The start position is decided by one pure fn, input_start(), and fed to
everything that lays out the input: the overlay rows and overflow shift,
click-to-index mapping, vertical caret movement, the rendered bar, the
completion menu anchor and the IME candidate anchor.
Add a macOS-only `font_thicken` key (default true) and a Settings row
under Appearance > Terminal text. When off, AppleFontSmoothing is pinned
to 0 in this process's NSArgumentDomain before gpui's text system first
reads it, so glyphs render at the face's own weight. The volatile domain
is in-memory only: nothing is persisted and no other app is affected.
gpui caches the preference in a OnceLock, so a change applies after a
restart; no gpui fork change is needed.