Skip to content

Releases: hoangperry/herminal

herminal v0.4.2 — named workspaces

Choose a tag to compare

@hoangperry hoangperry released this 02 Jun 20:25

Closes the v0.4 Sessions milestone: Claude session browser → session restore → named workspaces.

Named workspaces

Save a tab + split layout under a name, reopen it any time. Like iTerm2's window arrangements.

  • Window → Save Workspace As… (⌃⌘S, or the ⌘⇧P palette) — name the current layout.
  • Window → Open Workspace ▸ — pick any saved layout to restore it. The submenu rebuilds each time it opens, so new saves show up immediately. Hold Option on an entry to delete it.
  • Same safe policy as session restore: layout + each pane's directory come back as plain shells; commands (ssh / claude) are not replayed.

The Sessions milestone, complete

Version Feature
v0.4.0 Claude session browser (⌘⇧C) — resume past conversations
v0.4.1 Session restore — reopen last layout on launch
v0.4.2 Named workspaces — save & reopen layouts on demand

All built on OSC 7 working-directory tracking.

Install

curl -LO https://github.com/hoangperry/herminal/releases/download/v0.4.2/herminal-v0.4.2.dmg
open herminal-v0.4.2.dmg

Signed + notarized + stapled. 79/79 tests pass.

herminal v0.4.1 — session restore

Choose a tag to compare

@hoangperry hoangperry released this 02 Jun 20:09

v0.4 milestone slice 2. Quit with a layout, get it back on launch.

Session restore

herminal now remembers your tab + split layout and reopens it next launch — each pane a plain shell in its last working directory. No more rebuilding your workspace every morning.

  • Persists to ~/Library/Application Support/herminal/workspace.json on quit + on every structural change (add/close/split tab).
  • Settings → "Restore tabs & panes on launch" (default on). Off → fresh single tab, snapshot cleared.

What it restores (and what it doesn't)

  • ✅ Tab count, split axis, pane ratios, focus, each pane's cwd.
  • ❌ Commands. ssh / claude / arbitrary commands are NOT re-run — those are side-effectful (network connections, LLM resumes) and surprising to fire on every launch. A former ssh pane comes back as a clean local shell.
  • Every restored cwd is validated against the local filesystem; a stale or remote path falls back to home rather than failing.

Pairs with v0.4.0's Claude session browser (⌘⇧C): restore brings back your layout, and the browser one-click-resumes the actual Claude conversations.

Install

curl -LO https://github.com/hoangperry/herminal/releases/download/v0.4.1/herminal-v0.4.1.dmg
open herminal-v0.4.1.dmg

Signed + notarized + stapled. 79/79 tests pass.

herminal v0.4.0 — Claude session browser

Choose a tag to compare

@hoangperry hoangperry released this 01 Jun 18:15

The feature the "terminal for devs living in Claude Code" tagline always promised: reopen any past Claude conversation in one click.

⌘⇧C — Claude session browser

A new left sidebar reads Claude Code's own transcript store (~/.claude/projects/) and lists every project you've run claude in — sorted by last-active, with the real working directory and git branch.

  • Resume opens a tab running claude --resume <id> in the project's cwd — reattaches the exact conversation.
  • Open Shell Here drops a plain shell in that directory.

Read-only — herminal never writes into ~/.claude. Reads only the first 16 KB of each transcript, so even a multi-hundred-MB session file costs two syscalls, not a parse. Paths with hyphens (e.g. andromeda-next) resolve correctly — the cwd is parsed from the transcript body, not the lossy directory slug.

Foundation (reused by future session-restore)

  • OSC 7 cwd tracking — every pane now knows its live working directory.
  • working_directory spawn — tabs can open in a specific dir.

What's next (v0.4 milestone)

This is slice 1. Session restore (snapshot every tab/pane on quit, restore on launch) and named workspaces build on this same foundation.

Install

curl -LO https://github.com/hoangperry/herminal/releases/download/v0.4.0/herminal-v0.4.0.dmg
open herminal-v0.4.0.dmg

Signed + notarized + stapled. 79/79 tests pass.

herminal v0.3.3 — drag-resize splits

Choose a tag to compare

@hoangperry hoangperry released this 31 May 18:19

Final slice of the v0.3 polish wave.

Drag-resize splits

Split panes were locked to an even share. Now a draggable handle sits on the gap between panes — hover it (cursor turns into the resize arrows), drag to rebalance. Closing a pane redistributes the freed space; survivors never shrink below a grabbable sliver.

The v0.3 polish wave, complete

Slice Version What
1 v0.3.0 Vibrancy + content padding + spring animations + right-click menu
2 v0.3.1 Command palette (⌘⇧P) + global hotkey (⌥Space)
3 v0.3.2 Scrollback search (⌘F)
4 v0.3.3 Drag-resize splits

These four shipped against the brutal-honest audit in docs/research/09-polish-audit.md that diagnosed the "không đã" (doesn't feel as good as other terminals) feedback. Root cause: Ferrari engine (libghostty Metal), plastic chassis (default AppKit chrome). Fixed.

Deferred (documented, not forgotten)

Caret blink phase-reset needs a libghostty upstream patch — no host-side cursor API exists. Image rendering, semantic double-click, and a font-picker UI are feature work for a later milestone, not polish.

Install

curl -LO https://github.com/hoangperry/herminal/releases/download/v0.3.3/herminal-v0.3.3.dmg
open herminal-v0.3.3.dmg

Signed + notarized + stapled. 79/79 tests pass.

herminal v0.3.2 — scrollback search (⌘F)

Choose a tag to compare

@hoangperry hoangperry released this 28 May 09:15

Polish-wave slice 3. The headline feature.

⌘F — Find in terminal

Floating search bar appears top-right of the active pane. Type to filter, Enter / ⌘G for next match, ⌘⇧G for previous, Esc to dismiss. Live results — libghostty re-scans on every keystroke and reports match count + selected index.

libghostty does ALL the heavy lifting (scan + highlight in the Metal render); herminal just owns the AppKit overlay.

Closes the headline audit finding

"Terminal mà không search được output để debug là đồ chơi, không phải công cụ." — docs/research/09-polish-audit.md §2 row 1.

Available via

  • ⌘F keyboard shortcut
  • Edit menu → Find in Terminal…
  • ⌘⇧P command palette → "Find"

Install

curl -LO https://github.com/hoangperry/herminal/releases/download/v0.3.2/herminal-v0.3.2.dmg
open herminal-v0.3.2.dmg

Signed + notarized + stapled. 79/79 tests pass.

herminal v0.3.1 — command palette + ⌥Space

Choose a tag to compare

@hoangperry hoangperry released this 28 May 03:10

Polish-wave slice 2. Two "magic feature" items.

⌘⇧P — Command palette

Fuzzy launcher over the workspace. 15 actions indexed (tabs, splits, sidebars, theme, Settings, hotkey window). Search field at top, ↑↓ to navigate, Enter to fire, Esc to dismiss. Adding new menu items only needs a one-liner entry; dispatch travels the responder chain.

⌥Space — Global hotkey

Brings herminal forward from anywhere on macOS, or hides it if already key. Carbon RegisterEventHotKey (no accessibility permission required). If the combo is grabbed by another app, the menu fallback (Window → Show Hotkey Window) still works.

Slice 3 next

Scrollback search ⌘F, drag-resize splits, caret blink reset — each needs a libghostty integration spike first.

Install

curl -LO https://github.com/hoangperry/herminal/releases/download/v0.3.1/herminal-v0.3.1.dmg
open herminal-v0.3.1.dmg

Signed + notarized + stapled.

herminal v0.3.0 — polish wave (slice 1: vibrancy + padding)

Choose a tag to compare

@hoangperry hoangperry released this 28 May 02:37

First slice of the v0.3 polish wave. Addresses the owner's "không đã" feedback (full diagnosis at docs/research/09-polish-audit.md).

This release ships visible chrome only — scrollback search, command palette, and hotkey window land in later slices.

What changed

  • Vibrancy. Workspace wrapped in NSVisualEffectView (.underWindowBackground, .behindWindow). The window now blends with whatever sits behind it instead of reading as a flat hex rectangle.
  • Content padding. 6 px inset between the libghostty Metal surface and the pane chrome. No more text-flush-against-edge cheap feel.
  • Tab inactive opacity. Non-active, non-hovered tabs fade to 62%. Active tab reads as the focus point.
  • Right-click context menu on the terminal — Copy / Paste / Select All. Only fires when libghostty isn't claiming the click (vim mouse mode still wins).
  • Spring tab transitions replacing the old linear .easeOut.

Install

curl -LO https://github.com/hoangperry/herminal/releases/download/v0.3.0/herminal-v0.3.0.dmg
open herminal-v0.3.0.dmg

Signed + notarized + stapled.

Coming in v0.3.x

  • Scrollback search (⌘F)
  • Command palette (⌘⇧P)
  • Drag-resize splits
  • Hotkey/Quake window (⌥Space)
  • Smooth caret + selection alpha

herminal v0.2.5 — I-beam cursor + clickable URLs

Choose a tag to compare

@hoangperry hoangperry released this 27 May 09:46

Fifth audit-pass slice. Two more action_cb cases land:

MOUSE_SHAPE

  • HerminalSurfaceView now defaults to `.iBeam` — a terminal IS a text surface, the default arrow always felt wrong.
  • vim mouse mode → pointing-hand, URL hover → pointing-hand, crosshair / resize / grab / not-allowed mapped (12 shapes total).

OPEN_URL

  • Cmd-click on a URL libghostty detected in terminal output now opens the user's default browser via NSWorkspace.
  • Defensive scheme allow-list: `http`, `https`, `mailto`. `file://` and custom schemes rejected so a hostile shell can't pop Finder on `file:///etc/passwd`.

Five-day audit summary

Version Stub fix
v0.2.1 `read/write_clipboard_cb`
v0.2.2 mouse events → libghostty
v0.2.3 `close_surface_cb`
v0.2.4 SET_TITLE / SET_TAB_TITLE
v0.2.5 MOUSE_SHAPE + OPEN_URL (this release)

Each survived 12+ months. The audit pattern (`grep '_ in }|return false$' Sources/HerminalCore/*.swift`) is now baked into the dogfood-checklist pre-release routine.

Install

```bash
curl -LO https://github.com/hoangperry/herminal/releases/download/v0.2.5/herminal-v0.2.5.dmg
open herminal-v0.2.5.dmg
```

Signed + notarized + stapled.

Requirements

  • macOS 14.0 (Sonoma) or later
  • Apple Silicon (arm64)

herminal v0.2.4 — shell-set tab titles

Choose a tag to compare

@hoangperry hoangperry released this 27 May 08:29

Fourth stub-from-spike fix in the v0.2.0 → v0.2.4 audit window. `GhosttyApp.handleAction` was a one-case switch (only handled `RING_BELL`); SET_TITLE / SET_TAB_TITLE returned false, so OSC 0/2 escapes from vim/htop/starship-style prompts were silently dropped — the tab strip stayed on "herminal" no matter what the shell wrote.

Fix

  • `GhosttyApp.handleAction` routes SET_TITLE + SET_TAB_TITLE through `ghostty_surface_userdata` → `ClipboardOwner` protocol → `surfaceTitleDidChangeNotification`.
  • `WorkspaceView` observes, finds the matching pane by identity, updates `TerminalSession.title`, rebuilds the tab strip.
  • Empty payload falls back to "herminal" (OSC 0 with empty string conventionally clears the title).

Try it

```bash
printf '\033]0;mytab\007'
```
The tab label switches to `mytab`.

Four-day audit pass

Version Stub fix
v0.2.1 `read/write_clipboard_cb` (clipboard moves bytes)
v0.2.2 mouse events → libghostty (drag-select works)
v0.2.3 `close_surface_cb` (`exit` closes the pane)
v0.2.4 SET_TITLE / SET_TAB_TITLE actions (this release)

Each one survived 12+ months because the dogfood checklist never explicitly verified the round-trip end-to-end. The `verify-clipboard.sh` (v0.2.2) and `verify-title.sh` (v0.2.4) regression-guards now catch any future regression on day one.

Install

```bash
curl -LO https://github.com/hoangperry/herminal/releases/download/v0.2.4/herminal-v0.2.4.dmg
open herminal-v0.2.4.dmg
```

Signed + notarized + stapled.

Requirements

  • macOS 14.0 (Sonoma) or later
  • Apple Silicon (arm64)

herminal v0.2.3 — exit closes the pane

Choose a tag to compare

@hoangperry hoangperry released this 27 May 07:43

Third stub-from-spike fix in the v0.2.0 → v0.2.3 audit window. `close_surface_cb` was an empty closure, so when the shell PTY child exited (`exit`, crash, PTY disconnect) the pane locked onto "Process exited" until the user manually ⌘W'd.

Fix

  • `GhosttyApp.closeSurface` posts `surfaceDidCloseNotification` with the surfaceOwner.
  • `WorkspaceView` listens, walks tabs/panes by identity, removes the matching pane.
  • If the closed pane was the last in its tab, the tab is collapsed automatically.
  • Skip the note-confirm prompt — the process exited on its own.

Three-day audit pass

  • v0.2.1 — wired `read_clipboard_cb` + `write_clipboard_cb` to NSPasteboard
  • v0.2.2 — forwarded mouse events to libghostty (selection)
  • v0.2.3 — wired `close_surface_cb` (this release)

Plus the M11 `Scripts/verify-clipboard.sh` regression-guard runs the clipboard round-trip end-to-end every day so the v0.2.0 mistake stays caught.

Install

```bash
curl -LO https://github.com/hoangperry/herminal/releases/download/v0.2.3/herminal-v0.2.3.dmg
open herminal-v0.2.3.dmg
```

Signed + notarized + stapled.

Requirements

  • macOS 14.0 (Sonoma) or later
  • Apple Silicon (arm64)