Skip to content

Commit c027b7f

Browse files
authored
Merge pull request #64 from umage-ai/docs/spinner-design
docs: spinner design spec + doc refresh
2 parents cf8020c + abfb23a commit c027b7f

4 files changed

Lines changed: 708 additions & 2 deletions

File tree

CLAUDE.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ dotnet run --project src/CodeShellManager/CodeShellManager.csproj
1414

1515
**Requirements:** .NET 10 SDK, Windows 10/11 (uses ConPTY + WebView2)
1616

17+
### Visual Studio: Hot Reload disabled
18+
19+
`Properties/launchSettings.json` ships with `"hotReloadEnabled": false`, and the csproj sets `<MetadataUpdaterSupport>false</MetadataUpdaterSupport>` in Debug. Both are workarounds for a `System.ExecutionEngineException` that crashes the app on F5 under .NET 10.0.8 + VS 18 — `Microsoft.Extensions.DotNetDeltaApplier.dll` faults during its own startup before any managed code runs. Ctrl+F5 (Start Without Debugging) is unaffected either way. **Remove both when the runtime bug is fixed upstream.**
20+
1721
### Command-line flags
1822

1923
| Flag | Effect |
@@ -36,7 +40,7 @@ PTY (ConPTY) → PseudoTerminal → TerminalBridge → WebView2 (xterm.js)
3640
AlertDetector → SessionViewModel.RaiseAlert()
3741
```
3842

39-
- **PseudoTerminal** (`Terminal/PseudoTerminal.cs`): Windows ConPTY wrapper, P/Invoke only
43+
- **PseudoTerminal** (`Terminal/PseudoTerminal.cs`): Windows ConPTY wrapper, P/Invoke only. Implements `IPseudoTerminal` (`Terminal/IPseudoTerminal.cs`) — the minimum surface needed by `RunInstance` (`DataReceived`, `Exited`, `ExitCode`, `Start`). Tests inject a fake via the `internal RunInstance(item, Func<IPseudoTerminal>)` constructor.
4044
- **TerminalBridge** (`Terminal/TerminalBridge.cs`): Routes bytes between PTY and xterm.js via WebView2 messages. Surfaces accelerator keys (Ctrl-combos, F-keys, Esc) via `_webView.PreviewKeyDown` — the newer WPF WebView2 wrapper forwards accelerators through standard key events rather than a separate `CoreWebView2Controller.AcceleratorKeyPressed`. Bridge re-raises them as `AcceleratorKeyPressed` so `MainWindow.OnBridgeAcceleratorKey` can run global shortcuts even when the terminal has focus.
4145
- **OutputIndexer** (`Terminal/OutputIndexer.cs`): Async channels → SQLite, strips ANSI
4246
- **AlertDetector** (`Services/AlertDetector.cs`): Regex on raw PTY output, fires after 1.5s idle
@@ -249,6 +253,16 @@ Each session gets a collapsible 📝 notepad panel between the terminal toolbar
249253

250254
`AlertDetector.NotifyUserInteracted()` clears alert state on user input.
251255

256+
## Session Spinners
257+
258+
Two overlays cover launch and shutdown so the user sees progress instead of a blank pane.
259+
260+
**Launch overlay (per session)** lives in `Assets/terminal.html` and `Assets/terminal-transparent.html` as a CSS-animated rotating SVG arc with a phase label. Visible by default; `TerminalBridge` posts `setBootState` after `NavigationCompleted` (label = `Starting {cmd}…` for local, `Connecting to {host}…` for SSH; accent = session color) and `bootDone` on the first PTY byte (via `OnPtyData → PostBootDoneIfNeeded`, race-safe via `Interlocked.CompareExchange`). An 8-second fallback timer scheduled in `NavCompleted` also calls `PostBootDoneIfNeeded` so silent sessions and slow SSH handshakes don't lock the user out of the pane.
261+
262+
**Shutdown overlay (app-level)** is a `Grid x:Name="ShutdownOverlay"` on `MainWindow.xaml` with a `Storyboard`-rotated `Path`. `OnClosing` shows it then `await Dispatcher.InvokeAsync(() => {}, DispatcherPriority.Background)` to force a render pass before the existing synchronous session-disposal loop blocks the UI thread.
263+
264+
Full design: `docs/superpowers/specs/2026-05-16-session-spinners-design.md`.
265+
252266
## Search
253267

254268
- All PTY output is stripped of ANSI and indexed to SQLite FTS5 by `OutputIndexer`
@@ -295,6 +309,10 @@ Unit tests cover model logic (`ShellSession`, etc.) and run headless. UI tests r
295309

296310
`ShellSession.BuildSshArgs()` is `internal` — accessible from tests via `[assembly: InternalsVisibleTo("CodeShellManager.Tests")]` in `AssemblyInfo.cs`.
297311

312+
**`IPseudoTerminal` testability seam.** `PseudoTerminal` implements `IPseudoTerminal` (in `Terminal/IPseudoTerminal.cs`), and `RunInstance` / `SessionRunner` both expose an `internal` constructor that accepts a `Func<IPseudoTerminal>` factory. Production code uses the parameterless public ctors which default to `() => new PseudoTerminal()`; tests pass a hand-rolled `FakePseudoTerminal` to exercise the run-command lifecycle (Run, Stop, Dismiss, kill-and-restart, 1MB output-buffer cap) without spawning a real ConPTY child. Keep the interface surface minimal — only what `RunInstance` actually calls (`DataReceived`, `Exited`, `ExitCode`, `Start`).
313+
314+
**SearchService tests** open a fresh file-backed SQLite at `Path.GetTempPath()` per test for isolation. The test class is `IDisposable` and clears the connection pool (`SqliteConnection.ClearAllPools()`) before deleting the file on Windows. Seed `session_history` rows with explicit timestamps rather than `Task.Delay` — Windows' 15.6ms timer granularity makes wall-clock-based ordering flaky on CI.
315+
298316
## Releases
299317

300318
CI/CD is in `.github/workflows/build.yml`. Releases are triggered by pushing a `v*.*.*` tag:

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,19 @@ Built with WPF + [xterm.js](https://xtermjs.org/) + Windows ConPTY for full pseu
1919
## Features
2020

2121
- **Multi-terminal grid** — run up to 18 sessions simultaneously in configurable layouts (1, 2, 3, 4, 6 columns; 2×2, 6×2, 6×3 grids); the active pane is highlighted with a 2px accent ring so it's easy to spot
22+
- **Sidebar groups** — organise sessions into named groups with their own color and filter strip; bulk actions (sleep / close / re-group) operate on the active group
2223
- **Sleep & wake** — 💤 button parks a session: PTY torn down, but the session (and its notes) stays in the sidebar so you can wake it later from where you left off. Great when you have many long-running projects but only need a few live at once.
24+
- **Recently closed** — Ctrl+Shift+T reopens the last-closed session (browser convention); the New Session dialog also lists the last 10 closed sessions for one-click revival
25+
- **Per-session run commands** — define a list of labelled commands per session (Test, Build, Watch…); ▶ runs the default, F5 / Shift+F5 run/stop it, output streams into a side drawer without touching the parent terminal. Optional post-run URL opens in your browser on exit code 0.
2326
- **Full-text search** — all terminal output indexed to SQLite FTS5; instant search across every session, ever
2427
- **Per-project notepad** — collapsible 📝 notes panel on every terminal, auto-saved and searchable
2528
- **Alert detection** — detects when Claude is waiting for input or tool approval; green/orange dot indicators
2629
- **Git status** — shows branch and dirty state in the sidebar per session
2730
- **Session rename** — double-click any session name or click ✏ to rename inline
2831
- **Auto-resume** — automatically resumes the last Claude Code session when restoring on startup (`--resume <id>`); toggleable in Settings
2932
- **SSH remote sessions** — connect to remote hosts using your existing SSH config; sessions persist across restarts
33+
- **Windows Terminal profile import** — opt-in import of profiles from Windows Terminal's `settings.json`; pick a profile in the New Session dialog to stamp its font, color scheme, cursor and padding onto the new terminal
34+
- **Launch & shutdown spinners** — every starting session shows a brief overlay (`Starting <cmd>…` or `Connecting to <host>…`) until the first PTY byte arrives; closing the window shows a "Shutting down…" overlay during session disposal
3035
- **Session history** — clicking a search result from a closed session offers to relaunch it
3136
- **Configurable launch commands** — customise the commands available in the New Session dialog
3237
- **Claude badge** — sessions running `claude` commands get a visual indicator
@@ -86,9 +91,13 @@ dotnet run --project src/CodeShellManager/CodeShellManager.csproj
8691
| Key | Action |
8792
|-----|--------|
8893
| `Ctrl+T` | New session |
94+
| `Ctrl+Shift+T` | Reopen the most-recently-closed session |
95+
| `Ctrl+Alt+T` | Duplicate the active session |
8996
| `Ctrl+W` | Close active session |
9097
| `Ctrl+F` | Toggle search |
91-
| `Ctrl+Tab` | Cycle sessions |
98+
| `Ctrl+Tab` / `Ctrl+Shift+Tab` | Cycle sessions |
99+
| `F5` | Run the active session's default run-command |
100+
| `Shift+F5` | Stop the active session's running run-command |
92101
| `Escape` (in search) | Close search panel |
93102

94103
## Layout Options

0 commit comments

Comments
 (0)