Config in config.toml via daemon (Get/Set/ConfigChanged), low-churn CSS-var
theme switching (Dark/Light + accent), terminal font, default shell, and
daemon status with Stop/Restart.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- FAVORITES section at the top collects pinned workspaces (removed from their
group listing); a star toggle on each row pins/unpins via setWorkspaceMeta.
- Drag-to-reorder within a section using raw pointer events (HTML5 DnD is
unreliable in the macOS WKWebView), with a drop-line indicator; on drop the
section's `order` is reassigned sequentially and persisted. Cross-section
drops are ignored (group membership unchanged).
- Trash icon on row hover opens a ConfirmDelete modal that shows the live
terminal count and warns before terminating them, then calls close_workspace
and re-points the active workspace.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a `pinned` bool to the workspace model, threaded through proto
(Workspace + WorkspaceView + SetWorkspaceMeta), the registry, the
set_workspace_meta handler, persistence, the CLI mapping, and the Tauri
bridge. serde(default) keeps existing state.json compatible (pinned=false).
Backs the sidebar Favorites section.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Search fixes:
- TerminalView sets allowProposedApi (the search addon's match decorations
use registerMarker/registerDecoration); without it findNext threw before
firing results, so the counter was stuck at 0/0.
- The search bar now renders inside the panel it targets (in the header)
instead of a global top-right overlay, so it's obvious which panel is
searched.
- Search is anchored to the panel it was opened on (searchSurfaceId) and no
longer follows focus — opening it in one panel and switching away no longer
shows it open elsewhere.
Prompt duplication:
- The focus border was 1px when unfocused, 2px when focused; with border-box
that resized the content on every focus switch, firing ResizeObserver -> fit
-> PTY SIGWINCH and making zsh/powerlevel10k reprint its prompt. The border
is now a constant 2px, color-only on focus.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A new surface spawned its shell immediately at the default 80x24, so the
shell (e.g. zsh + powerlevel10k) printed its first prompt before the GUI
fit-resized the panel. The post-print resize reflowed the grid, leaving the
prompt invisible until Enter and shifted by a line.
The surface actor now defers the child spawn: it waits for the first Resize
(spawning at that geometry) or, for headless/CLI surfaces that never attach a
GUI, falls back to the spec geometry after 250ms. Attaches received before
the spawn get an empty-grid snapshot plus a live subscription; pre-spawn
input is buffered and replayed. Adds two deterministic tests via `stty size`.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- LayoutEngine: fix splitter resize (track pointer 1:1 via delta-from-start)
and add panel drag-to-reorder using raw pointer events with drop indicators
- TerminalView: auto-fit xterm to container via FitAddon + ResizeObserver
- App/TopBar: toggleable sidebar; persist sidebar/events collapse in
localStorage; bell icon opens the activity log
- Wizard: new-workspace modal now grabs focus and handles keyboard
- deps: add @xterm/addon-fit
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a config.rs module that loads optional ~/.spacesh/config.toml and a
default_shell() resolver: SPACESH_SHELL env -> config.toml default_shell ->
login shell from the passwd DB -> $SHELL -> /bin/sh. The passwd lookup
matters under launchd where $SHELL is absent. All plain-panel spawn sites in
server.rs now use the resolver. Adds toml + libc deps.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The dock showed a black square because tauri.conf.json had no bundle.icon
block and icons/ held only tiny placeholders with no .icns. Add an SVG
source logo (terminal prompt + split workspace panes), generate the full
icon set via `tauri icon` (icon.icns/.ico + all PNG/iOS/Android sizes), and
wire bundle.icon so the daemon embeds and macOS renders it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Search only ran on Enter; typing merely reset the counter to 0/0, so a
visible term showed no matches until the user pressed Enter. run() now takes
an optional query override and onChange fires it on every keystroke for
search-as-you-type, while Enter/Shift+Enter still navigate matches.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
lock_is_exclusive_within_process acquired the global ~/.spacesh/daemon.lock,
so it flaked whenever a real daemon was running. Add a SPACESH_LOCK env
override to lock_path() and point the test at a private temp file under a
serial() guard, making the suite deterministic regardless of a live daemon.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Wire Cmd::SetZoom through Tauri bridge (set_zoom command), add zoomed
field to WorkspaceView, short-circuit LayoutEngine to render only the
zoomed panel full-grid, and toggle Maximize2/Minimize2 in panel header.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Source Event Center from daemon event_log (seed + live event/events_read push).
Unread/Errors tabs filter real EventRecord flags; bell shows numeric unread badge;
clicking an entry calls focusSurface + markEventsRead(ids). notify.ts param widened
to string so exit kind type-checks without breaking existing NOTIFY_STATES guard.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wire Cmd::EventLog and Cmd::MarkRead to the live EventLog (replacing
NOT_IMPLEMENTED stubs). Cmd::Focus now calls mark_read for the surface,
persists the updated snapshot, and broadcasts Evt::EventsRead.
Add integration tests: event_log_query_and_mark_read and
focus_marks_surface_events_read.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add event_log.rs with EventLog (capped VecDeque, monotonic ids, mark_read,
snapshot/restore) and EventLogState. Register mod in main.rs. Stub
Cmd::EventLog and Cmd::MarkRead arms in server.rs to keep the exhaustive
match compiling; full wiring follows in Task 4.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The app is its own cargo workspace, so in 'tauri dev' the app binary lives
in app/src-tauri/target/ and spaceshd is NOT a sibling — lazy-start failed
and the .expect() crashed the window. Now: find_daemon tries SPACESHD_BIN,
sibling, repo-root target/{debug,release}, then PATH; bridge honors
SPACESH_SOCK like the daemon/CLI; setup logs instead of panicking.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>