The kill button now sends the unforced DELETE immediately instead of
asking first. Only the daemon's guard refusal raises a prompt, and it is
a real dialog rather than confirm(), so it can offer the override the
daemon already implements.
The API error envelope is decoded into ApiRequestError, keeping the code
and the unsaved-work breakdown so the dialog names what is in the way.
The command fragment named the full command line, so a session spawned
with `claude --dangerously-skip-permissions` spent the whole line on a
flag. Cards now name the program only — its icon in the web client, its
bare name in the TUI — and keep the full command line in the tooltip.
Adds `maestro_protocol::display::command_program`, the Rust counterpart
of the web's `splitCommand`.
The header carried only the brand and a session tally; app actions had
already moved to the sidebar footer. The mobile ☰ it hosted moves to the
pane header (replacing the redundant back arrow) and to the welcome
state, so the session drawer stays reachable without a swipe. The DEV
`?kit` link moves to the sidebar footer.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The bar has nothing to switch between with one tab, so it is pure chrome. It reappears as soon as a second tab exists; spawn already opens its own tab, so the "+" button stays reachable.
Session handles are one word from a single 218-entry list — instruments,
forms, notation and theory, tempo and dynamics — replacing the
adjective-noun pair. A batch is shuffled, so it repeats only once the
wordlist runs out.
Project boxes show the parent directory instead of the full path: the
last segment is already the name line above it. The last command is gone
from the box, and picking a project no longer pre-selects it — the
directory and what runs in it are independent choices. Both changes land
in the TUI picker too, which mirrors the web form's rules.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Spawn and Spawn similar open a draft pane behind the open sidebar on
mobile, so the tap read as dead. Extract the drawer into its own module
and close it on both spawn events as well as a session tap.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Below 860px the layout no longer grows a second navigation surface. The
pane pill strip is gone, the tab bar stays collapsed however many tabs
exist, and opening or spawning takes over the current pane instead of
splitting beside it or opening a tab. The sidebar drawer is the only way
to move between sessions.
The tree itself is untouched, so a desktop-built layout comes back when
the window widens again.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
~ never distinguishes anything from a sibling — nothing else sits
beside it — so it showed as its own header even when it immediately
branched into multiple real projects. Now it folds into each child
instead, at the top only; a real divergence further down still gets
its own header.
Session header used to print the raw command line ("claude"); mirror
the sidebar's icon-for-program treatment so both agree.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Help, theme toggle, and Spawn now live pinned to the bottom of the
sidebar instead of the top-right app header, keeping them next to the
session list they act on.
Focused sidebar rows and multiview panes drew a green border/ring.
Swap to a background tint on the row and the pane titlebar instead,
so focus stays borderless.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Ctrl+Shift+H moves the keyboard between the session list and the pane;
j/k walk the cards, Enter opens, Escape hands the pane back. The walk
skips expanded folder headers and stops on collapsed ones, matching the
TUI.
Line 2 of a session card spelled out its blocked work ("1 uncommitted
file") and its command ("claude"). Both now render as marks: the
breakdown as diff notation, and the command's leading program as its
tool's icon in the web client.
The probe carries the line delta of the tracked changes — staged and
unstaged together, against HEAD — so `git add` never makes the counter
drop. Untracked files stay a file count; counting their lines means
reading every one off disk. A tracked change with no line delta falls
back to `~N` rather than claiming `+0 -0`.
The TUI keeps its command as text: a terminal cannot be assumed to have
a font carrying tool glyphs.
The sidebar row dot, the pane top strip and the mobile pill dot all
painted a hashed per-session colour; the focused pane added an outer
accent glow on top of its ring. Removes the colour concept entirely
along with the glow, leaving the flat accent ring as the only focus mark.
Spawn similar dropped the session's cwd into the free-text directory hatch,
so the project picker showed nothing selected. For a worktree session that
cwd was the daemon-made checkout, and the worktree toggle defaulted on, so
the clone asked for a worktree of a worktree.
It now seeds the picker: the cloned project's box selected, the same
worktree decision, base repo plus '+ new' when the source had a worktree.
A seeded path that matches no project falls back to the raw input showing
that path instead of an empty picker.
`?` toggles a dialog listing every web binding, mirroring the TUI's help
overlay. A `?` button in the header covers pointer-only clients, and the
welcome screen points at the key.
One registry (SHORTCUTS) drives the rendering, so a binding added without
an entry reads as missing. main.ts and the overlay now share one
isTypingTarget guard instead of two copies.
Killing the only session in a tab left an empty tab behind for the operator to close by hand. The pane's tab now goes with it, unless it is the last tab (which stays, emptied).
Removes the retained-worktree store end to end: the daemon's state-dir
store, GET/DELETE /api/worktrees, `maestro worktrees list|reclaim`, the
TUI overlay behind `w`, and the web `#/worktrees` view and header link.
The kill guard stays. A forced kill and a dirty natural exit now leave
the worktree on disk untouched instead of parking it in a store, so
removing one is an ordinary `git worktree remove`. A pristine tree is
still removed on exit. DELETE /api/sessions/:id always answers 204.
The header's debug button also goes; Ctrl+Shift+D and `?hud` still
toggle the HUD.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The worktree step ("+ new" plus the repository's existing worktrees) now
lives inside the collapsed "Advanced options" section in both the web form
and the TUI draft pane, so a plain spawn is command, project, name.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Right-clicking a card opens a custom context menu (rename, spawn similar,
kill). Rename swaps the name for an inline field; Enter commits, Escape and
blur cancel. The tree stops rebuilding while the field is open, so a catalog
delta cannot replace what is being typed into.
Refs #125
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Pressing Spawn while reading a session split that pane in half. It now
opens the draft in its own tab, leaving the current tab untouched.
Scoped to the explicit Spawn affordances (the header button and the
sidebar empty state, both via OPEN_SPAWN_EVENT). "Spawn similar" and the
fast-forward key deliberately keep splitting: both act on the session in
front of you, so a pane beside it is the point. Reusing an empty pane
(#72) is unchanged — that path never split anything.
Closes#100
The sidebar nested a worktree session under the worktree, so a repo grew
a <repo>/worktrees/<branch> folder holding one session of the same name,
and the repo stopped being where you look for the work.
The daemon recorded whatever base_repo the request named, which is the
worktree itself when spawning from inside one; it now records the
resolved main checkout. The web tree groups by that instead of the cwd.
The TUI sidebar is a flat list with no directory grouping, so it needs
no mirror.
Closes#99
Matches the TUI's WorktreeToggle, whose Enter also toggles rather than
submitting — otherwise the two clients would disagree on this one
field despite #97 requiring the same rule everywhere else.
The new-branch name input and the existing-branch picker both had a
literal <label>Branch</label>, on top of "New branch"/"Existing branch"
mode radios — reading the form gave no clue what the field wanted.
Kept the mode radios (they name the choice, not the field) and gave
each field its own label: "New branch name" for the text input,
"Pick a branch" for the select.
A project-box or worktree-choice picker button that isn't yet the
active pick takes the Enter to choose it instead; the next Enter, once
it's active, submits. The project filter resolves to the top filtered
project rather than sending whatever cwd was last set. The raw-cwd
autocomplete's own Enter (accept the highlight) keeps working via
e.defaultPrevented.