changelog
What's new in each release of Crystl.
2.36.8
- SGR rewriter no longer eats CPU on heavy output. The byte-level rewriter that protects against invisible-text-on-glass had been running on every single PTY byte since v2.36.0, copying each one individually into a fresh output array and scanning for escape sequences as it went. For interactive typing that’s free, but for streamed output (build logs, agent token streaming, file dumps) it was a measurable CPU tax that compounded with the App Nap suppression added in 2.36.4 to give a general “Crystl is sluggish” feel. Two optimisations cut the cost to near-zero on the common case: a fast-path early return when the slice contains no ESC bytes at all (skips the entire walk and allocation entirely — this catches the vast majority of plain-text payload), and bulk-copying plain-text runs between CSI boundaries instead of per-byte appends. Correctness pinned by 19 SGR rewriter tests including two new ones for the fast path.
2.36.7
- Typed text now appears as you type inside Claude Code — not only after you hit Enter. Long-running symptom: characters you typed into Claude’s input box would be completely invisible until submit, at which point they’d all appear at once. Drag-selecting over the “empty” region revealed the bytes were there in the terminal buffer all along — the GPU just wasn’t painting them. SwiftTerm’s 60fps repaint throttle plus its dirty-row tracking can drop typed-input row paints under Claude’s rapid status-line redraw bursts, and the upstream race is the same on both the Metal and CoreText paths. Workaround: force a repaint after every PTY data chunk we receive. Bypasses SwiftTerm’s display queue entirely for the typing case. Marginal extra CPU under heavy output bursts, free for interactive typing.
- Glass readability: ghost-text grey vs typed-input white now properly distinguished. The renderer-level luminance floor was lifting everything near-grayscale below 235 to pure white, which destroyed Claude’s dim hint placeholder text (it should stay dim grey). The byte-level rewriter also had a “muted agent output → grey-170” tier that itself rendered as light grey on glass — the exact “light grey” complaint we were trying to kill. Fix threads the dim attribute from the SGR stream all the way through to the renderer: the rewriter keeps the dim flag in the output (was stripping it), drops the grey-170 tier entirely (everything it rewrites is now white), and the floor short-circuits on dim to preserve the rewriter’s intentional grey-120 ghost-text substitute. Result: typed input renders crisp white, ghost text renders dim grey, muted agent output renders white, saturated colours pass through untouched.
2.36.6
- Typed text actually renders as white now — the long-standing “everything looks translucent grey” bug is finally root-caused and fixed. Weeks of patches at the SGR-rewriting, luminance-floor, dim-attribute, and alpha-blending layers were all chasing a symptom downstream of the real problem. The actual cause: SwiftTerm’s Metal renderer rasterizes glyphs into a Core Text bitmap with macOS font smoothing enabled (
setShouldSmoothFonts(true)). Font smoothing is calibrated for dark-text-on-light-bg and bakes a luminance reduction directly into every glyph in the atlas. On Crystl’s transparent glass background, that baked-in reduction made light text look uniformly grey regardless of what colour the agent emitted, what colour the shader received, or what we layered upstream. The grey was already in the atlas before anything else got a chance to touch it. Fix: smoothing off in the rasterizer; glyphs go into the atlas at full luminance and read as crisp white on glass.
2.36.5
- Typed input no longer turns light grey on later turns within a session. First message looked right, then somewhere around turn three your white input would render as grey for no apparent reason — same bytes, same agent, different colour. Two compounding causes. (1) Stone was missing the SwiftTerm fg luminance floor patch entirely, so it fell back to SwiftTerm's
dimmedColor(towards: bg)which blends the foreground 50% toward the input box bg=(55,55,55) whenever the dim flag is set — white becomes grey-155. Stone's build now applies the same floor patch as Crystl. (2) The floor'sdim + bright → grey-120branch was actively harmful: the byte-level rewriter already substitutes explicit grey-120 for lone\e[2mghost-text, so any bright+dim pair reaching the renderer-level floor was a stuck SwiftTerm dim flag, and dimming bright text in that case produced exactly the user-visible bug. Removed the branch. Bright fg now always passes through regardless of dim state.
2.36.4
- Backgrounded terminals keep painting in real time. Previously, if you clicked away to another app while Claude was working, the terminal screen would freeze in place — bytes still arrived on the PTY read queue and updated the buffer in memory, but the queued display-refresh blocks didn't fire often enough to repaint. When you came back, the screen would snap forward in one jump to wherever Claude was now (often already finished), giving a "frozen but secretly working" experience. Cause: macOS App Nap throttling Crystl's main run loop while another app was focused. Fix:
ProcessInfo.beginActivityfor the app's lifetime, same pattern Terminal.app and iTerm2 use. System sleep behaviour is unchanged.
2.36.3
- Typed input renders uniformly readable on glass — for real this time. The byte-level SGR rewriter was a losing battle against every variant agents emit; sequences split mid-word kept producing visible dim/bright transitions. The fix moves the floor to the SwiftTerm render layer: every painted glyph now goes through a luminance floor, so any near-grayscale dark foreground is lifted to readable at paint time — regardless of what bytes the agent sent or how they split across slices. Policy: dim + dark-near-gray → crisp white (typed input); dim + bright → grey-120 (ghost-text); no-dim + dark-near-gray → grey-170 (muted agent text); saturated colors pass through unchanged. The contract is pinned by a unit test suite that fails to compile if a SwiftTerm bump drops the patch.
2.36.2
- Cursor no longer disappears in shards running Claude Code. CC emits
\e[?25l(hide cursor) constantly during status-line redraws, and on stock SwiftTerm the Metal renderer skipped drawing the cursor for that frame — between redraws it never recovered, so the cursor visibly vanished. The cursor is now always drawn, regardless of CC's hide signal. The patch is now applied at build time viabuild.sh/build-stone.shinstead of being a stray uncommitted edit, so it survives any clean SwiftTerm re-resolution. - Patch — typed input now renders uniformly white instead of half-white-half-grey. v2.36.1 made some typed text crisp white but missed a redraw path where Claude Code splits the typed-input fingerprint across two SGR sequences (
\e[2mfirst, then\e[38;5;239mlater). The rewriter now tracks the dim attribute cumulatively across sequences, so the second SGR's near-grayscale dark fg is correctly classified as typed input and rewritten to full white — even at line-wrap boundaries where the split most often shows up. Also resolves the related "completely invisible character" cases.
2.36.1
- Patch — typed input now renders crisp white instead of muted grey. Claude Code wraps every typed character in a dim attribute plus a near-grayscale dark foreground; on the glass background that combination renders near-invisible without the SGR rewriter, and the rewriter's previous policy brightened it only as far as grey-170. The new policy detects the typed-input fingerprint (dim + near-grayscale dark fg) and rewrites the foreground to full white. Muted agent text (dark-gray fg without dim) still rewrites to grey-170 so it stays visually distinct, and the lone-dim ghost-text hint stays at grey-120.
2.36.0
- You'll know when an agent crashes inside an isolated shard. Previously when Claude (or any agent process) exited on its own inside an isolated shard, Crystl silently auto-closed it and you were left wondering whether your work was saved. Now a non-blocking notification fires: “agent in {crystal name} exited — branch crystl/{name} kept with N commit(s)” (or “branch removed (no work to save)” if nothing was committed; appends “+ uncommitted changes” if you had untracked work). The user-driven close path with the merge prompt is unchanged.
- Every save button now flashes “saved” before dismissing. The pattern shipped in v2.35.0 for APIKeys and Facets settings is now extended via a shared helper to IconPicker, ClaudeTemplateEditor, StarterEditor, QuestPartyEditor, and QuestRoleEditor panels. Brief title flip + crystlAccent brighten + 1s dismiss everywhere a save closes a panel.
- Smarter resumption-burst suppression. The 30-second fingerprint rate-limit from v2.34.1 was imprecise — legitimate Stop hooks within the window could be suppressed and the resume storm could leak through if message text differed. The principled fix: when Crystl auto-runs
claude --resumefor a session, it marks a 5-second window during which Stop hooks for that exact session ID are dropped at intake. The 30s fingerprint window stays as a safety net. Tunable viadefaults write com.crystl.app resumptionWindowSeconds -int 5. - Three more panel-monitor leak fixes. NewProjectPanel, HistoryPanel, and IconPickerPanel each now have a
deinitthat removes their global click monitors / NotificationCenter observers as a belt-and-suspenders fallback for misseddismiss()calls. - 57 button corner radii normalized. Off-spec
cornerRadius = 6sites bumped to the speccornerRadius = 8across 28 files (FacetBar, HistoryPanel, StarterEditorPanel, FileMaps, AgentFiles, Editor, Library, Helpers, DenialPanels, SettingsView, drag-drop rows, etc.). Small visual nits adding up to a more consistent feel. - All 6 audit hard-ceiling violators are now split. v2.35.0 covered four; this release finishes the job with AgentBlockLibraryPanel (686 → 350 + 4 extension files, with the Tier 3 9pt chip fix applied in flight) and AgentFileEditorPanel (635 → 346 + 4 extension files). Pure reorganization, no behavior change.
- +20 unit tests (378 → 398). New regression nets for the agent-exit message helper (7 tests) and the resumption-window suppression (13 tests on session-id windowing).
2.35.0
- Active gem highlights brighter on the rail. The previous selected vs unselected delta was dominated by the border; bg fill and icon alpha barely differed. Bumped selected bg alpha 0.25 → 0.42 and border alpha 0.6 → 0.9 so the active gem reads at a glance, and softened the inactive icon dim so they stay legible alongside it.
- Rail icons stay readable at low opacity. The transparency slider's
glass.alphaValuewas cascading to every tile, button, and icon — at the most-translucent end (alpha 0.2) tile icons dropped to ~13% effective alpha and were nearly invisible. Restructured so the glass blur sits at the back as a sibling of the interactive views, not their parent. Only the blur fades; tiles and icons stay at full alpha regardless of slider position. - Bridge token persists across Crystl restarts. Every Crystl restart used to write a fresh random token to
~/.crystl-bridge-token, which broke every SSH-tunneled shell because shell-init captures the token via env at spawn time. Now the existing token is reused (validated as 32- or 64-char hex; corrupt files regenerate cleanly). Tailscale and SSH-relay users no longer get 401s in every existing shell after a Crystl restart. - Three more c9a3799-pattern panel races fixed. Same shape as the v2.34.0 fix: synchronously clearing
setupPanelinsidedismiss()chains dropped the strong reference beforeanimatePanelOut'sonDismisscould fire. Three additional sites covered (RailSettings toggle, RailSettings open path, AppDelegateonWillShowPanel). - New
--no-installflag forbuild.shandbuild-stone.sh. Compile-only build that skips overwriting~/Applications/Crystl.app. Agents building from worktrees should use this — avoids the “Crystl won't open” failure mode where the installed app'sBundle.modulepath was baked to a worktree that later got cleaned up. - +77 unit tests (301 → 378). New regression nets for
shellEscape(security-critical, was untested), MCPConfig merge (user-managed.mcp.jsonentries must survive sync), LicenseManager edge cases (.expired→.freetier), APIKeyStore Keychain round-trip (constructor-injected service name so tests can't pollute the real Keychain), and OSC 7770 parser (extracted into a pure function). - All 6 audit hard-ceiling violators split. ChamberSetupPanel, AgentFileEditorPanel+BlockView, FileLibrarySettingsPage, NewProjectPanel, AgentBlockLibraryPanel, AgentFileEditorPanel — all now under 400 lines, with the workhorse logic in
+Suffix.swiftextension files. Pure reorganization, no behavior change. Plus a Tier 3 UI hygiene pass across ~20 files (alpha-floor lifts, sub-10pt font bumps, ~50 inlineNSFontcalls migrated to Typography tokens,isHidden = true→layer.opacity = 0on glass-overlapping views).
2.34.1
- Patch — startup notification spam fixed. Restarting Crystl with restored Claude sessions used to cause a flood of identical “command completed” panels. Root cause:
claude --resumere-fires Stop hooks for every prior assistant turn in the transcript, and Crystl had no rate-limit on identical events at intake. v2.33.0's dismissal-suppression only kicked in after the user dismissed one — by then the burst had already stacked up. This patch adds a 30-second rate-limit on identical event fingerprints (same session, hook type, and message prefix), so the burst collapses into a single panel. Also catches tool loops firing the same Stop repeatedly, and any other source of bursty identical hooks.
2.34.0
- Worktree integrity hardening. Five fixes covering the audit's Tier 2 worktree cluster: replaced symlinks (e.g.
npm installoverwriting.claude/) are detected on session start and moved aside with a.crystl-replaced-{timestamp}suffix instead of letting per-shard config leak to main; the crystal-name validator is now actually enforced at every entry point that accepts a user/external name; the shard prompt body in autorun.sh is single-quote-escaped so a malicious branch name can't execute attacker-chosen shell; the crystal-name allocator considers allcrystl/*branches as occupied (not just orphans-with-work) so stale empty branches don't get silentlybranch -D'd; and remote SSH disconnect during close now preserves state so the orphan can be cleaned up on reconnect. - Two more c9a3799-pattern panel races fixed. Same shape as the gem-settings stuck-after-save bug:
openGemFromPickerandshowQuickModePickerwere clearing the panel's strong reference synchronously beforeanimatePanelOut'sonDismisscould fire. Now rely on the callback after the animation completes. - Terminal NSEvent monitor leak plugged.
removeScrollForwarding()was defined but never called — each session close left four global event monitors registered forever. Now called from the close paths and from a newdeiniton the terminal-view subclass. - Three
asyncAfterstrong-capture bugs fixed. The 0.3–0.5s asyncAfter blocks inopenSSHURL,showGemSettings, andsetGemApprovalModekept closed sessions alive just to feed a banner to a now-orphanedterminalView. Now[weak session]with a guard. - SGR rewriter hardening. The
pendingCSIbuffer is capped at 4 KiB so a malformed CSI from a buggy or hostile emitter (ESC[with no terminating final byte) can't OOM the process; on overflow the bytes flush to output as raw and the buffer resets. CSI parameter / intermediate / final phases are now walked explicitly per ECMA-48. build.shhard-fails when SwiftTerm sed patches can't apply. Previously a SwiftTerm refactor that renamedsnappedWidth/metalDirtyRange/ etc. would silently leave builds shipping unpatched code, regressing the “invisible text on glass” bug class. Now the build aborts loudly so the regression can't ship.
2.33.0
- Bridge security hardening. The in-process bridge that handles Claude Code's permission hooks now requires bearer authentication on all endpoints (previously loopback was exempt, which let any local process or DNS-rebinding browser POST decisions). Adds a strict
Hostheader check that rejects rebound hostnames and any request carryingOriginorReferer; opt-inbridgeRemoteAccessfor Tailscale / VPN / port-forwarding setups. Caps request bodies at 1 MiB with a 413 response before any body is buffered. Pairs each fix with a regression test in CI so the same drift can't slip back in. - Worktree data-loss prevention. Three close-time data-loss scenarios fixed: (1)
commitsAheadnow uses a stored fork point so worktrees with real commits don't silently report zero-ahead and get deleted when the project is on a feature branch; (2) untracked files in a worktree count as work to preserve, so agent-created files that were nevergit added are no longer force-removed on close; (3) corrupt-worktree recovery refuses to destroy a branch that has commits, so a transient lock file or permission flap can't trigger a silentgit branch -D. - scp upload paths shell-escaped. Remote file uploads via SSH now use a
cat | ssh ... > $(escaped path)pipe instead of rawscp host:path, so a remote path containing;or backticks can't execute on the remote host. - Dismissed notifications stay dismissed for 10 minutes. Identical events (same session, same hook type, same message prefix) are suppressed within the window. Protects against
claude --resumereplaying transcript hooks on session restore, pathological tool-loop floods, and any other source of bursty repeats. After 10 minutes a fresh occurrence re-fires normally. - SSH integration test harness + GitHub Actions CI. A sandboxed
sshdon127.0.0.1:2222backs end-to-end remote-session tests; CI runs both unit and SSH suites on macOS for every push. 31 new bridge regression tests cover the audit-touched paths so future security fixes can ship without breaking SSH features.
2.32.0
- Tool output and typed input render bright again on glass — 2.30.0 introduced a darker rewrite path for any SGR carrying the dim attribute, to keep Claude Code's ghost-text placeholder visually distinct from typed text. But Claude emits its tool output, git output summaries, and even your typed input as
dim + near-grayscale-dark fg, so all of that ended up rendered at gray-120 (visibly dull on glass). The dim-darken now applies only to the ghost-text case (lone\e[2m…\e[22mwith no explicit fg). Anything with an explicit fg rewrites to bright gray-170 as before.
2.31.0
- Gem settings panel closes again after save — clicking save in gem settings flashed the green “saved” state but then left the panel stuck on screen. The X, Escape, and click-outside were all silently dead. The onSubmit callback was clearing the panel's strong reference synchronously, so the panel deallocated before the post-save dismiss timer could fire — AppKit kept the window on screen with all its targets dangling. The strong reference now lives until
animatePanelOutactually completes.
2.30.0
- Claude Code ghost-text reads dimmer than typed text again — the placeholder hint (e.g. Try "write a test for <filepath>") was rendering at the same brightness as what you actually typed. The SGR rewriter that fixes invisible-text-on-glass was stripping the dim attribute entirely, including the lone
\e[2m…\e[22mblocks Claude uses for the ghost-text placeholder. Now dim-attributed text rewrites to a darker gray than regular grayscale text, and a lone dim sequence substitutes an explicit darker fg so the hint survives even when no fg color is set in the source SGR.
2.29.0
- Quest wrapper installs only when you summon a party — previously every non-diamond shard got the quest verbs and
claude()wrapper installed at creation time, even if you weren't running quest. On session restore the +0.8s inject lost the race toclaude --resumeand the bootstrap text (source /tmp/crystl-quest-…) ended up in Claude's input box. Now the wrapper is installed only when a quest party is actually summoned. Side quests already worked this way; nothing changes there. - Crystl and Stone no longer share config files — both apps were reading and writing
~/.config/crystl/for last-session, formations, facets, MCP catalog, file library, agent blocks, claude/starter templates, and bridge settings, so quitting one and launching the other restored the wrong workspace and overwrote the other's saved state. Stone now lives under~/.config/stone/. License key and hero-image cache stay shared (one Guild membership covers both, and the cache is just a CDN download).
2.28.0
- Readable input on glass — fixes invisible text when typing into Claude Code. The agent's input prompt was emitting 256-color and truecolor SGR codes that bypassed the 16-color palette floor and rendered as near-black on the transparent background — you'd type a sentence and only see it after pressing return. Crystl now intercepts the PTY byte stream, parses CSI sequences, and rewrites near-grayscale dark foregrounds to a readable light gray. Saturated colors (red, blue, green) are preserved at any luminance.
2.27.0
- Close all gems — new
File → close all gemsaction for a one-click "start fresh". A single confirm dialog lists every running agent and unmerged isolated-shard branch across all open gems; on accept, the saved-session pointer is cleared so the next launch is empty, and a single fresh unconfigured gem replaces what was closed. Menu item disables itself when the only open gem is already fresh.
2.26.0
- End Quest — new
File → end questaction stands the party of agents down. A[quest ended]banner is bracketed-pasted into each shard, then every quest verb (quest_msg,quest_heartbeat,quest_task,quest_summary,quest_handoff,quest_announce,quest_claim,quest_note) is rewritten to a stub returning{"ok":false,"error":"quest_ended"}so already-running agents learn to stop reporting through their normal feedback channel. Works for local + remote (SSH) shards. The menu item is disabled when no shard is in a quest.
2.25.0
- Side Quest panel matches Quest UX — hero sidebar with crystal-color dots, name + gem, and a context lifebar;
— X joined the side quest —rows on open; CRT-fadecrystl side questlogo splash; cleaner header with identity moved to the sidebar; messages bottom-anchored like Quest. - Side-quest agents follow the protocol — the start banner now declares the rule explicitly: reply only by running
sidequest_msgvia the Bash tool, never as plain chat. Each routed message also carries a per-message reply reminder so the protocol stays in working context turn over turn.
2.24.0
- Glass-readable terminal palette — install all 16 ANSI colors with values tuned for the transparent background, eliminating dark/black text in TUI apps like Claude Code
2.23.0
- crystl://ssh URL scheme — open remote SSH sessions from other apps or scripts with
open "crystl://ssh/user@host/path"
2.22.0
- crystl:// URL scheme — open any project from other apps or scripts with
open "crystl:///path/to/project"
2.21.0
- Quest message injection — messages sent from the quest chat panel now correctly submit in Claude Code's terminal; fixes text appearing in the input buffer but never executing (Kitty keyboard protocol + bracketed paste)
2.20.0
- Quest message delivery — fixed
quest_announceandquest_taskwriting to an unwatched path; messages now reliably appear in the quest panel - SSH quest messages —
quest_msgnow resolves its log path at runtime so remote agents write to the correct location - Quest message persistence — messages sent while Crystl is closed are replayed on next open via a cursor file
- Quest panel colors — agent names in the Tasks and Summaries tabs now render in their crystal colors
- Live summary feed — new summaries append in real-time when the Summaries tab is visible
- SSH hook reliability — quest verbs retry hook delivery 3 times with a warning on total failure
- Quest setup — tilde in project path field now expands correctly before git repo checks
2.19.76
- Gem settings close button — moved to top-right corner, removed invisible title bar that blocked clicks
2.19.74
- Scriptability API — local HTTP API (
/api/v1/) for programmatic control of gems, shards, permissions, and terminal content - crystl CLI — 11 commands:
status,gems,open,close,shards,send,screen,pending,approve,deny,token - SSE event stream — real-time notifications and permission request events at
/api/v1/events - Security — bearer token auth on all API routes, remote
/senddisabled by default
2.19.73
- Click-to-open fix — clicking file paths in Claude Code output now opens correctly instead of showing error -50
- Relative path resolution — relative paths resolved against session working directory, not app process directory
- SSH file click — file:// links over SSH download via SCP then open locally
2.19.72
- StopFailure notifications — glass panel appears on API errors: rate limit, auth expired, billing, server error, max tokens
- PermissionDenied panels — auto mode denials now show a retry/dismiss panel instead of failing silently
2.19.71
- Session resurrection — restores gems, shards, and Claude sessions on startup with zero clicks
- SSH session restore — SSH shards auto-reconnect, cd to remote directory, and resume Claude sessions
- Settings toggles — restore last session and resume Claude sessions toggles in General settings
2.19.69
- SSH hook fix — fixes permission auto-reject on SSH sessions caused by duplicate hook entries accumulating across builds
- Bridge failsafe — when bridge is unreachable, Claude Code now falls through to CLI prompt instead of silently rejecting
2.19.66
- Option+drag to select text — in tmux/vim, hold Option while dragging for native text selection, then Cmd+C to copy. Matches iTerm2/Alacritty/Kitty convention.
- OSC 52 clipboard bridging — tmux can now copy selection to system clipboard via escape sequences
- tmux drag forwarding — mouse drag events forwarded to tmux for click-drag selection highlighting
- One-time hints — brand blue hints for Option+drag and mouse mode on first use
2.19.63
- tmux scroll support — scroll events forwarded to tmux when mouse mode is on; one-time hint when it's off
- Drag to reorder gems — drag tab bar tabs with insertion indicator, rail tiles stay in sync
- 32 preset colors — doubled color palette with deep, rich, and earth tones; scrollable horizontally
- New gem panel reorder — identity at top, setup at bottom; consistent 16px header spacing
- Image drag — shows [image #] via native paste; window re-focuses after drag
- Bare URL detection — clicking domain.com/path opens browser instead of erroring
2.19.62
- Drag to reorder gems — drag tab bar tabs to rearrange project order, rail tiles stay in sync
- Image drag — dragging images into the terminal now shows [image #] instead of raw file paths
- Bare URL detection — clicking URLs like ads.google.com/path opens the browser instead of erroring
- SSH freeze fix — gem settings no longer blocks the main thread on stale SSH connections
- Close button fix — gem settings close button works reliably, brightens on hover
2.19.59
- Ecosystem-colored tags — block tags colored by platform: Swift orange, TypeScript blue, React cyan, Python green, and more
- Inline categories — category label next to block title instead of stacking vertically
- Tag-aware search — editor block search now matches tags and categories
- New block dialog — category dropdown + clickable tag chips for swift, macos, typescript, etc.
- Context load: lines — LINES column in token usage panel showing file line counts
- Optimizer animation — staggered fade-in on load and re-analyze
- 10 Swift/macOS rules — new library blocks for Swift development
2.19.58
- Save feedback — save buttons flash "saved" with bright green confirmation before reverting
- Explore tab — optimizer "map" renamed to "explore" with folder-open icon; "+" buttons on directories to add saved files
- Library hints — "?" buttons on library blocks show the explanation text in the preview area
- Agent block library — larger panel, proper search field styling, more preview space
- Blank rule removed — rule/skill menus no longer offer a useless blank heading option
- Gem panel fix — title text no longer clips descenders on "g" in "gem settings"
2.19.57
- Rule/skill picker — add rule and add skill show a menu of available blocks with content previews
- Drag to zones — dragging blocks from the library into the RULES or SKILLS zone sets the correct block type
- Source mode — raw markdown editor has a proper rounded input area
- Editor zones — rules/skills zones only appear when directories exist on disk
- SSH directory picker — cd command now sent to remote shell
- New gem layout — starter bundle section moved below icons, above MCP
2.19.55
- Add to project — library templates have a project picker to deploy files to any open gem
- Simple file editor — lightweight glass editor for .claudeignore, settings.json, and other non-block files
- Blank new files — new file templates start empty; starter kits keep the scaffold
- Custom filenames — templates can target any path, not just predefined agent file types
2.19.54
- 17 new optimizer checks — testing commands, code conventions, stack detection, verification gate, commit discipline, stale paths, cross-file consistency, gitignore misconfig, hooks, and permissions
- Weighted scoring — content quality weighted 3x higher than setup; AGENTS.md only penalizes multi-agent projects
- Copy for agent — export button writes optimization-report.md and copies a prompt to clipboard for pasting into Claude or Codex
- Bundle starters — new gems get .claudeignore and .claude/settings.json scaffolds automatically
- New blocks — Verification Gate, Commit Discipline, and Tool Restrictions available in the block library
- SSH gem settings fix — agent file checks now hit the remote filesystem instead of the local home directory
2.19.52
- Project Optimizer over SSH — health scores, gap detection, file creation, and the map/files views all read and write through the SSH connection
- File Library rules over SSH — .claude/rules/ listing, creation, editing, and deletion now work for remote projects
- File Maps panel over SSH — rule listing, file editing, add-file, and add-rule all SSH-aware
- Accurate context load for SSH — burn rate now correctly accounts for CLAUDE.md and AGENTS.md on remote hosts
- Gem settings CLAUDE.md detection — correctly detects existing CLAUDE.md on SSH projects
2.19.51
- SSH agent editor — agent files can now be opened, edited, and saved on SSH remote projects; rules and skills load and save correctly over SSH
- ProjectFilesystem — new internal abstraction routes all file operations to either the local filesystem or SSH, eliminating local-only guards throughout the app
- SSH agent files grid — gem settings now shows the correct agent files for remote projects
2.19.50
- Tabbed agent editor — tabs match the terminal gem tab style: separator line, active background, × close, + add, same fonts and spacing
- Close to delete — closing a tab permanently removes the agent file from disk (with confirmation)
- Add menu — pick any known agent type or enter a custom filename (cursor.md, aider.md, etc.)
- Auto-detect — AGENTS.md, GEMINI.md, .cursorrules, .windsurfrules, .github/copilot-instructions.md open automatically as tabs
- Gem settings grid — agent files shown as a clean two-column grid, no false positives from unrelated .md files
2.19.46
- Rules divider — blue zone in the CLAUDE.md block editor; blocks below become individual .claude/rules/*.md files
- Skills divider — purple zone below rules; blocks become .claude/commands/*.md slash commands
- Drag across zones — move content between CLAUDE.md, rules, and skills by dragging blocks across dividers
- Auto-load — existing rule and skill files load into their zones when opening a project's CLAUDE.md
- PLANS.md — new file type for OpenAI Codex execution plan templates
2.19.45
- GEMINI.md support — create and manage Google Gemini CLI instruction files
- Optimizer line count — flags CLAUDE.md over 200 lines with suggestion to split into rules
- Map view add file — "+ add file" button opens file chooser panel from any directory
- Map view add rule — "+ add rule" button with name and path-scope dialog in .claude/rules/
2.19.44
- File chooser panel — glass panel with icons and descriptions for creating project files (CLAUDE.md, AGENTS.md, codex.md, .cursorrules, and more)
- CLAUDE.md w/rules — recommended option that creates CLAUDE.md + .claude/rules/ directory together; badge in the chooser
- Claude rules tab — manage .claude/rules/*.md files in File Library settings with name and path-scoping support
- Line count bar — CLAUDE.md editor footer shows live line count; turns yellow at 150, red over 200
- Codex.md templates — dropdown in New Gem panel for selecting codex.md templates
- Separate skill sections — Claude Skills and Codex Skills as distinct sections in New Gem panel
2.19.41
- Optimizer SSH guard — "optimize" button is now hidden for SSH gems; the analyzer reads local filesystem only and would scan the wrong directory for remote sessions
2.19.40
- SSH show button fix — approval panel "show" now correctly navigates to the originating shard for port-forwarded SSH sessions (connections without user@host format)
2.19.39
- Formations fix — project names now restore correctly for SSH gems; port-forwarded sessions were silently dropping names on save
2.19.38
- Skills import fix — importing from the skills library now installs files directly to
~/.claude/commands/; previously nothing was written to disk - Section header UX — block editor section rows are now inline-editable (no more double-panel expand)
- File Maps: hide non-existent instruction files; add library shortcut at bottom
- Gem settings panel: refactored, adds optimizer shortcut in edit mode
2.19.37
- Remove File Maps window — per-project agent setup coming as part of gem settings
2.19.36
- File maps fix — panel title no longer overlaps traffic light buttons
2.19.35
- Rename "crystl codex" to "crystl library" throughout
2.19.34
- File Library — new settings page with a block-based CLAUDE.md editor, Claude skills manager (
.claude/commands/), and Codex skills manager (~/.agents/skills/) - Block editor — compose instruction files from reusable blocks; drag to reorder, inline heading edit, save any section to your block library
- Guild: browse 200+ blocks & skills — import agent blocks (rules + workflows), Claude skills, Codex skills, and file templates directly from the crystl.dev library
- 7 instruction file types — expanded support for CLAUDE.md, CLAUDE.local.md, AGENTS.md, codex.md, .cursorrules, copilot-instructions.md, .windsurfrules with type-specific scaffolds
- File Maps panel — browse agent config files across all your projects from the Window menu
- Image drag-drop fix — drop now only intercepts in remote (SSH) sessions; local sessions pass through to Claude Code natively
2.19.33
- Remote session fix — gem settings save no longer sends
cd+clearto the terminal when connected via SSH or running a process - Facet bar redesign — unified segments with inline dropdown triangles, diamond settings icon with hover glow
2.19.32
- Context Map — new settings page for viewing agent config files across all projects. Drillable subdirectories, color‑coded type badges (Claude, Codex, Cursor, Aider, Copilot, Windsurf), coverage bars, discovered projects, and tracked files reference
- SSH config alias fix — bare hostnames like
ssh myserverare now correctly detected for image paste, drag‑and‑drop, and remote features - Quest settings rearranged — user character is a compact bar on the left, heroes moved to right column
- DM unread indicators — dot on DM channel pills, badge on dms toggle, distinct two‑note DM sound
- Gem settings accordions — collapsible PROJECT FILES, SKILLS, MCP sections with Lucide chevrons
- Renamed starter files → agent files
2.19.31
- SSH host parsing fix — port‑forwarded connections (
-L,-R,-D) no longer misdetect the forwarding spec as the hostname. Fixes SCP uploads, drag‑and‑drop, and remote features for port‑forwarded SSH - Paste fallback — if SCP fails, the local file path is pasted instead of silently dropping
- DM unread indicators — unread dot on DM channel pills, badge on “dms” toggle button
- DM sound — two‑note ascending ping, distinct from the main chat tick
2.19.30
- File logger — Crystl now writes to
~/Library/Logs/Crystl/crystl.logwith 5 MB rotation. Bridge and paste diagnostics logged for easy debugging
2.19.29
- Hardened image/file paste — checks 6 pasteboard types for cross‑macOS‑version robustness, adds NSImage fallback for non‑standard clipboard managers, and diagnostic logging for SSH upload debugging
2.19.28
- Quest report export — export button in the quest panel generates a timestamped Markdown report with party roster, message counts (main + DM), token usage per shard, user prompts, git diff, and chat log
- SSH image/file paste — Cmd+V of images and files now uploads via SCP for remote sessions, matching drag‑and‑drop behavior
2.19.27
- Smart image/file paste — Cmd+V of files from Finder pastes full shell‑escaped paths instead of bare filenames. Cmd+V of screenshot image data saves to a temp PNG and pastes the path. Regular text paste is unchanged
- Retooled demo — the in‑app demo now showcases all panel types in sequence: permission panel, question notification, and multi‑question series with architecture questions
2.19.26
- Collapsible accordion sections — PROJECT FILES, SKILLS, and INCLUDE MCP in gem settings are now collapsible with Lucide chevron disclosure icons. Sections default to collapsed for a compact panel. Insert buttons use brand blue with hover state
2.19.25
- Marquee scroll — hovering a gem tab with a truncated name scrolls the text left to reveal the full name
- External notifications dropped — notification hooks from Claude Code running outside Crystl are now silently ignored, preventing spurious “Claude is waiting for your input” panels
2.19.24
- Scrollable tab & shard bars — gem tabs and shard pills now scroll horizontally when they overflow. The + and split buttons follow naturally after the last item, pinning to the right edge only when overflow occurs. Quest and isolation buttons stay visible
- Quest join sound fix — the “join” chime no longer plays when adding shards outside of an active quest session
2.19.23
- Screenshot bar — a thumbnail strip at the bottom of the window showing your recent screenshots (powered by Spotlight). Drag a thumbnail into the terminal to paste the file path, or double‑click to open. Toggle via View > screenshot bar (⇧⌘S). Visibility persists across restarts
- View menu fix — removed duplicate “increase font size” entry
2.19.22
- Quest directory fix — all four quest modes (local/remote × open/sealed) now use the directory shown in the setup panel. Quest setup defaults to your current working directory instead of the gem root
- SSH cwd tracking — remote shells emit OSC 7772 via precmd hooks (zsh + bash) so Crystl always knows the remote working directory. Replaces the broken
pwd‑over‑new‑channel approach - SSH exit detection — disconnecting from SSH clears remote state so quest setup correctly switches back to local mode
- Local directory picker — quest setup now has a browse button for local projects, using the existing glass directory picker
- Join messages — remote quest shards now show “has joined your party” in chat, with dedup guard to prevent double posts
2.19.21
- Quest v2 Phase 2 — SSH remote parity complete: all v2 verbs install on remote shards, hooks mirror state back to Crystl, local state is uploaded to remotes, and remote shards get v2 prompts. New ambient feed UI adds tasks, summaries, and per‑shard progress tabs to the quest panel
- SSH panel routing fix — all panel types (notification, approval, denial, ask‑user) now use shard‑aware project matching so SSH gems sharing the same local path route to the correct project
- Tasks tab fix — JSON key mismatch (
task_idvsid) caused silent decode failure and empty tasks tab - Shard pulse — working shards now pulse more visibly (0.3‑1.0 range); selected shard’s underline breathes when its agent is active
- Context health bar fix — dev mode synthetic data no longer corrupts real agent metrics
2.19.20
- New gem name fix — clicking “+” in the tab bar no longer inherits the name, icon, and color from a previous gem's config at
~/.crystl/project.json - SSH formation loading — the
cdinto saved remote directory now waits for the actual SSH connection (OSC 7771 signal) instead of a blind 1.5‑second timer, so slow networks and password prompts no longer lose the command - Multi‑SSH shard fix — shard restoration now tracks project indices directly instead of path matching, fixing wrong‑project targeting when multiple SSH gems share the same local path
2.19.19
- Crash fix — Crystl could crash with a
SIGABRTinSessionBarView.drawwhen CoreText'sTAttributes::ApplyFontencountered a nil value while processing SF Mono's variable‑font feature dictionary. The two shard‑label fonts are now cached as static stored properties and pre‑fetched before the draw loop, preventing any race between first‑load and the 20 Hz pulse timer - Quest verbs — added
quest_claimandquest_announceverbs; improved prompt quality and question detection accuracy
2.19.18
- Quest inter‑shard communication fix — the status‑file hint pointed agents at
.crystl/quest/v2/messages.jsonlbutquest_msgwrites to.crystl/quest/messages.jsonl, so agents always saw an empty file and couldn't read each other's messages. Fixed the path so agents can now read the shared quest log - No more duplicate messages — the file watcher was re‑writing messages it read from disk back into the JSONL file with a new UUID, doubling every entry. Now passes
fromFile: truethrough the protocol so file‑sourced messages skip the write‑back - quest_msg confirmation output —
quest_msgnow prints{"ok":true,"id":"..."}on success, matching the v2 verb convention so agents can verify delivery - Recon‑first quest protocol — agents are now instructed to read
messages.jsonland survey the repo before writing any code, preventing incompatible tech‑stack decisions. Key decisions (architecture, framework choice) are posted immediately so teammates can align - Click‑to‑open refactor — replaced custom mouse‑event click‑to‑open with SwiftTerm's native link system
- Notification shard resolution — notification hooks now resolve the correct shard via cached
session_id
2.19.17
- Per‑shard identity fix — message sender attribution, working/ready state, and context health metrics were all routing to the wrong shard when
CRYSTL_SHARDwas inherited into crystl's own environment (e.g. launching Crystl from inside another Crystl tab). Fixed with two‑layer defense at the env‑inheritance layer so it can't regress silently - Context health bar rebased on usable budget — the bar used to count Claude Code's fixed startup cost (system prompt, tool definitions, walked‑up CLAUDE.md files) against the shard's budget, so it could drop to yellow on the very first turn with no work having happened. Now uses the first recorded turn as a baseline and measures only real per‑turn work accumulation.
turnsRemainingalso estimated against usable budget - Question detection false‑positives — the trailing‑decoration strip was chewing past closing code fences and JSON terminators into embedded
?characters inside string literals, lighting up “has a question” cards on turns where the agent wasn't asking anything. Now scoped to the last non‑empty line of the message so structural delimiters can't trigger
2.19.16
- Quest v2 operational verbs — four new shell commands for shard‑to‑shard coordination.
quest_heartbeatwrites live status + current task + optional blocker.quest_taskdelegates async work to another shard with ownership tracking.quest_summarycheckpoints progress on a task without handing off.quest_handoffhands off the full task with decisions / blockers / next steps, optionally auto‑assigned. Each verb ships as a bash script installed into every local shard'sbin‑<shard>/at session start and returns structured JSON with exit codes for scripting - Structured quest state files — new
.crystl/quest/v2/layout with per‑shardprogress/,status/,tasks.json, and an append‑onlysummaries.jsonl. Crystl writescontext_pctinto each shard's progress file from hook metrics, so teammates cancatthe files for live situational awareness without replaying the chat - Healer context‑watching — shards with the Healer role now get a system‑prompt addendum that tells them to read the progress files during their own turns and nudge any shard below 20% context toward a handoff. Pure prompt‑driven, only fires when a healer is actually in the party — no background daemon
- party.json migration — the quest‑related UserDefaults keys (party composition, per‑shard role overrides, user character sheet) now dual‑write to a single
party.jsonfile under each project's.crystl/quest/v2/. First‑run bootstrap handles the migration from UserDefaults; a corrupt file regenerates from UserDefaults automatically - System Prompts page — new read‑only cards for the quest v2 operational verbs, the healer addendum, and a local/remote split on the status‑file hint so remote SSH shards no longer get pointers to files that don't exist on the remote host
- Settings subtitle slot — the System Prompts page copy now wraps cleanly under the page title instead of being jammed into the page body
2.19.15
- Fix: false‑positive “has a question” cards — the Stop‑hook question detector was matching any
?in the trailing 60 characters, so it lit up on turns that contained a markdown link query string (?foo=barinside a URL), a ternary in a code fence, or a rhetorical aside. It now requires the final meaningful character (after stripping trailing whitespace + markdown decoration) to be?, and routing + display share the same helper so they can’t disagree. Regression coverage added - Quest rename — commander → user across the quest panel, a new read‑only System Prompts settings page, and
PromptTemplatesextraction for the quest prompt assembly
2.19.14
- Session‑ID panel routing — floating approval, ask, notification, and process‑finished cards now route show buttons back to the originating shard by its UUID. Survives shard renames and empty‑cwd edge cases that previously stranded the old cwd/name matching
- Hook‑activity grace window — the agent monitor no longer flips shards to idle while Claude is mid‑stream. Non‑Stop hooks extend a 45 s grace window during which CPU‑based idle detection is suppressed, so streaming LLM turns stay marked working
- Turn‑start hooks —
PreToolUseandUserPromptSubmitare now installed alongside the existing hook set, so the shard pulse animation lights up the instant a turn starts rather than waiting for the first tool to finish. Projects missing these hooks are auto‑upgraded on next launch - Terminal font shortcuts — ⌘+ / ⌘− / ⌘0 to increase, decrease, or reset the terminal font. Persisted across launches and applied live to every open session
- Join Crystl Slack — Help menu now has direct links to join and sign in to the Crystl Slack community
- Quest panel live relayout — swapping parties in the quest setup popup rebuilds the panel in place without flickering the anchor, and a close button lets you bail without clicking outside
- Tab / shard label legibility — tab labels bumped to 12 pt and shard labels to 11 pt for crisper rendering at the monospaced sizes the UI actually uses
2.19.13
- Question notifications work over SSH — Stop hooks from SSH shards now get the same “has a question” cards as local shards. Previously SSH sessions only got the 60 s-delayed idle fallback because the remote transcript file was unreachable from the local bridge
- Remote augment script — the shell-integration installs a tiny
~/.claude/crystl-augment.pyon each remote host and pipes Stop payloads through it before posting to the bridge. The augment parses the transcript JSONL in place and injectslast_assistant_message, so the local bridge sees the same shape whether the session is local or remote - Safe on error — non-Stop hooks pass through untouched and any augment error falls back to the original payload, so a broken transcript can't break the hook chain
2.19.12
- Shard-aware “show” buttons — approval, ask-user, notification, and process-finished cards now remember which shard raised them, so clicking show takes you to the exact session instead of just the project tab
- Question notifications — when Claude ends a turn with a question, a green “has a question” card appears with side-by-side dismiss / answer buttons. Answer focuses the shard and clears the card in one click
- Transcript-driven Stop hook — the last assistant message is now parsed out of the transcript JSONL, since Claude Code's Stop payload omits
last_assistant_messageby default - Question toggle override — Stop-with-“?” bypasses the Stop notification toggle, so turning off generic “Claude finished” cards still lets explicit questions through
- Question dedup — Claude Code's idle
Notificationhook is deduped against the Stop hook via a 120-second per-session window. One event, one card
2.19.11
- Hero health bars — hero health bars in the quest panel now actually reflect context usage. Previously every shard stayed at 100% because session metrics were being attributed to the wrong shard
- Context load button — the "turns left" button now appears after 3 Claude turns as intended. Same root cause: turn metrics were landing on the wrong session, so the visible shard's count stayed at 0
- Shard-routed metrics — the
X-Crystl-Shardhook header is now threaded through session-metrics and hook-activity callbacks, so sessions match by name instead of the ambiguous cwd fallback - Dev-mode fix —
CRYSTL_DEVsynthetic context data now actually injects (was gated on a turn counter that never advanced)
2.19.10
- Quest DM delivery —
quest_msg "shard" "text"now actually delivers the message to the target shard's terminal instead of only creating a side-channel in the UI - Quest party editor — prevented adding the same crystal twice when building a quest party
- AskUserQuestion routing — questions from Claude Code now route to the input panel instead of getting auto-approved into a phantom empty answer
- Bridge binds loopback by default — the hook bridge no longer listens on all interfaces out of the box; Tailscale/VPN users can opt in via
bridgeRemoteAccess - Keychain-backed API keys —
ANTHROPIC_API_KEY,OPENAI_API_KEY,GEMINI_API_KEY, andOPENROUTER_API_KEYare stored in macOS Keychain, never on disk in plaintext - Hardened license validation — tighter checks in
LicenseManagerto prevent tampering - MCP import validation — imported MCP server configs are validated before being written to
.mcp.json - Command history + remote session hardening — shell integration, worktree setup, and SSH bridges no longer shell-interpolate untrusted input
- Worktree robustness — detached-HEAD detection, accurate dirty-state checks, and better error messages when
git worktreeoperations fail - Bridge server fixes — timer scheduling order, FileHandle guard, and approval-panel cache no longer race on startup
- UI consistency pass — typography tokens across the app, text alpha floor enforced (no more disappearing labels on translucent glass), consistent corner radii, and live-reactive window opacity
2.19.9
- Correct shard in notifications — stale
CRYSTL_SHARDenv vars from orphaned Claude Code processes no longer mislabel which shard needs attention; the hook header is validated against the project's current sessions - Instant library imports — prompts, heroes, templates, and skills imported from the library panels appear in settings immediately instead of requiring a page switch
- Facets: no duplication — prompts live in exactly one place — the slot OR the library list, never both
- Facets: edit in slot — click a prompt in a slot to edit it; the × now dismisses back to the library (delete only happens on the library side)
- Facets: glass dropdown — triangle dropdowns on facet pills now use the Crystl glass aesthetic instead of the default gray menu
2.19.8
- Remote git worktrees — create isolated shards on remote servers via SSH with full merge/rebase/close lifecycle
- Shard directory inheritance — new shards inherit SSH session and working directory from the current shard
- Formation SSH restore — formations save and restore SSH host, remote working directory, icon, and color per gem
- Remote orphaned branches — Isolation panel shows remote branches for reopening
- Fixed remote notifications — removed invalid hook types that broke Claude Code hook validation on remote machines
- Fixed paste highlight — pasted text no longer shows as black-on-black in the terminal
- Per-gem approval — auto-approval now works correctly for SSH and worktree sessions
- Dual-build isolation — Crystl and Stone no longer interfere when running simultaneously
2.19.7
- Robust formations — backup before save, auto-restore from backup on corrupt data, error dialogs for missing paths instead of silent failures
- Path normalization — formation paths resolve symlinks, expand tildes, and strip trailing slashes for reliable matching
- Overwrite & rename safety — warns before overwriting an existing formation, prevents duplicate names on rename
- SSH auto-tunnel on by default — new users get the SSH reverse tunnel without needing to find the setting
2.19.6
- Formation SSH auto-reconnect — formations save SSH hosts per gem and shard, auto-reconnect on load with a single confirmation prompt
2.19.5
- Full SSH feature parity — session history, command logs, context load, starter files, and quest prompts all sync to remote over SSH
- Question detection fix — long messages no longer lose the trailing ? that triggers question notifications
- Security hardening — sanitized hero names, auth on unknown connections, restricted file permissions on remote config
2.19.4
- SSH session tracking — notifications and approval panels show the correct project even with many remote SSH sessions open
- Party dropdown roles — hero list shows role names alongside character names
- Custom hero creator — single-panel creation with name, role, personality, instructions, stats, and model (Guild)
2.19.3
- Quest over SSH — quest messages now relay through the bridge on remote sessions
- Reliable shard names — notifications always show the correct shard context, even with subdirectory paths or before agent detection
- International keyboards — auto-detects Nordic, German, French, and other layouts; disables Option-as-Meta so @, €, {, } work out of the box
2.19.2
- SSH notifications for Tailscale/VPN — hook relay now auto-detects remote client IP, bypassing broken SSH port forwarding on Tailscale SSH and VPN setups
- Bridge address override — optional field in Settings > Claude for manual bridge address configuration
2.19.1
- Imported heroes visible — heroes imported from the Hero Library now appear in the YOUR HEROES list, party editor, and add-member dropdown
- Hero portraits — portrait images now download for all heroes, not just built-in catalog entries
2.19.0
- Custom API keys — add arbitrary env vars for any AI provider (Mistral, Groq, xAI, etc.) from the API Keys settings page
- Code quality overhaul — split ChamberSettingsPage into 5 files, fixed 22 review issues including thread safety, observer leaks, accessibility labels, and Typography token adoption
- UI polish — roll dice button with hover state, improved stat stepper arrows, settings spacing fixes across general, claude, and quest pages
- Scribe hero — new Documentation specialist hero in the quest catalog
- Notification fixes — notifications no longer misattribute to the wrong project, shard colors scoped correctly
- License key display — long keys are truncated to a short preview after pasting
2.18.1
- Close warnings — warns before closing shards, gems, or quitting when processes are still running; worktree merge dialogs now also show running process info
- Dock badge — pending approval count shown on the dock icon with bounce on new requests
- Formation shard saving — formations can optionally save open shard state (crystal names, isolation) and restore them on load
2.18.0
- Starter files in gem panels — new gem panel shows CLAUDE.md checkbox+dropdown, separate INCLUDE FILES and SKILLS sections with per-file control
- Edit mode project files — gem settings shows exists/insert status for configured starters; insert buttons write files immediately without affecting save
- Skills section —
.claude/commands/starters are split into their own SKILLS section in both new gem and edit mode - Skills Library — browse and import skills from the skills library in starter settings
- Panel coordination — rail panels (new gem, open picker, gem settings) dismiss each other when opening
- Library upgrade prompts — template, hero, and prompt library panels show Guild upgrade prompt on auth errors
2.16.0
- Token usage panel — per-shard bar chart showing input tokens per turn with projected future turns and burn rate
- Turns remaining — estimated turns left before hitting the context window ceiling, shown in the status bar
- Per-turn cost breakdown — table showing conversation growth and fixed costs (CLAUDE.md, settings) consumed each turn
- Model detection — reads the model ID from Claude Code transcripts for accurate context window sizing
- Quest sidebar turns — each agent in the quest sidebar shows estimated turns remaining; click to open their chart
- JSON export — writes
.crystl/context-load.jsonfor healer and agent consumption
2.15.0
- Quest: multi-agent coordination — summon a party of Claude Code agents with an IRC-style chat panel for real-time coordination
- Party templates — 10 hero archetypes (wizard, ranger, rogue, healer, etc.) with customizable roles, personalities, and RPG stats
- Per-hero model picker — choose Opus, Sonnet, or Haiku per role with smart defaults (Opus for research, Haiku for QA)
- Sealed quest mode — each hero works on its own git branch via worktrees, eliminating file conflicts between agents
- Context health bars — monitor each agent’s remaining context window in the quest sidebar
- DM channels — direct message individual agents via @mentions
- Commander profile — your own character sheet that shapes how agents interact with you
- Hero system reference — stat band chart in settings explains how STR/INT/WIS/DEX affect agent behavior
- Parallel message delivery replaces slow sequential queue
- File locking on quest message log prevents corruption from concurrent agents
- Quest setup panel with radio buttons, risk badges, and git repo detection
2.14.5
- Marquee scroll on hover — truncated text in approval and notification panels auto-scrolls when you hover to reveal the full content
- Shard crystal colors — notification headlines use the shard’s actual crystal color instead of generic tint
- Approval panels stay visible — timeout extended from 60 seconds to 5 minutes so panels don’t disappear before you act
- Duplicate permission notifications suppressed when approval panels are already showing
2.14.4
- Personified shard notifications — approval panels show “diamond wants to edit a file” instead of bare tool names like “Bash”
- Shard identity in notifications — notification headlines use the shard name (“diamond has a question”) instead of “Claude”
- Cleaner notification stack — redundant “needs your permission” notification cards no longer appear alongside approval panels
- Centralized Typography system with semantic font tokens across all panels and settings
2.14.3
- Full Disk Access prompt — guides new users to grant FDA on first launch, preventing repeated macOS permission dialogs
- Codesigned dev builds — build.sh now signs with hardened runtime to match release builds
- Fix duplicate shard names — auto-naming skips crystal names already used by active sessions or existing worktrees
- Fix worktree reopen — reopening an already-open worktree switches to it instead of creating a duplicate
- Dismiss settings flyout when opening gem settings panel and vice versa
2.14.2
- Per-project approval mode — set Manual/Smart/Auto Approve per gem
- Click selected rail tile to open Gem Settings panel
- Fix icon category tab clicks in scrolled positions
- Global approval flyout: renamed header, divider before Pause All
- Terminal readout when approval mode changes
2.14.1
- Clickable links — URLs in terminal output underline on hover and open in browser on click (no Cmd key needed)
- Arrow cursor — cursor changes from I-beam to arrow when hovering over clickable URLs or file paths
- Lowercase labels — History, Settings, and Isolation buttons now use lowercase styling
- Removed broken glow/shimmer effects and non-functional shard rename
2.14.0
- Gem toolbar capsule — History and Settings buttons grouped in a frosted glass pill with the project’s Lucide icon alongside
- Connected facet pills — facet action buttons share a single connected pill with hairline dividers
- Facet label truncation — segment width capped at 120px with ellipsis for long labels
- Nature & Animals icon categories — split into separate categories in the icon picker; added snowflake, waves, and wind icons
- Scrollable icon category tabs — all categories reachable via horizontal scroll
2.13.8
- Multi-question AskUser panels — prev/next dot navigation in a single panel; answers preserved when navigating back and forth
- Always-visible cursor — cursor stays visible while Claude Code runs, matching Warp behavior
- Sound settings — separate sound pickers for Denied and Question panels in Settings > General > Sounds
- Panel consistency — all panels now show project icon, name, shard name, and Show button with standardized spacing
- SSH hook timeout bumped to 3s for more reliable remote notifications
- PermissionDenied hook added to remote setup command
2.13.7
- SSH file relay — drag/drop or paste images into SSH terminals; files are SCP’d to the remote automatically via ControlMaster
- Remote click-to-open — clicking file paths in SSH sessions downloads the file via SCP and opens it locally
- Remote gem config — CLAUDE.md, starter files, and .mcp.json are written to the remote filesystem when configuring SSH gems
- Bridge relay endpoints —
/relay/image,/relay/open,/relay/clipboardfor remote-to-local communication - AskUserQuestion panels — now show full question text with numbered options for multi-question format
- Fix answer passthrough so Claude Code receives multi-question selections correctly
- Auto-sizing panel height based on question content
2.13.6
- Auto SSH relay — when Auto-tunnel is enabled, Crystl automatically installs Claude Code hooks on the remote machine via SSH RemoteCommand (no more manual paste)
- PermissionDenied panels — when auto mode denies a tool, an orange floating card appears with Retry/Dismiss buttons
- AskUserQuestion panels — Claude's questions appear in a floating glass panel with scrollable text and an input field
- Styled DMG installer — proper drag-to-install layout with icon positioning
- Both new panel types toggleable in Settings → Claude → Notifications
2.13.5
- Top-mounted Crystal Rail — the rail can now sit at the top of the screen as a horizontal bar with tiles laid out left-to-right
- Drag-to-snap — grab the rail and drag it to any screen edge (left, right, or top) to reposition instantly
- Two-column panel layout — in top mode, notifications stack to the left of the bar and approvals to the right
- Rail Position setting updated with three options: Left, Right, Top
- Fixed icon picker ignoring right-side rail position
2.13.3
- SSH tunnel support — toggle in Settings → Claude auto-forwards port 19280 so approval panels work on remote machines via SSH
- Remote hook setup — "Copy Remote Setup Command" button installs Claude Code hooks on remote machines with one paste
- Paste visibility fix — pasted text is now readable on dark backgrounds (disabled zsh paste highlight, remapped ANSI black)
- Cursor restore — auto-restores cursor after Claude Code's spinner; Cmd+Shift+R for manual reset
- SSH hint — one-time yellow tip when you first run
sshwithout the tunnel enabled - No more Node.js — the bridge is now a native Swift HTTP server running inside the app. Zero external dependencies.
- Instant approval panels — direct callbacks instead of HTTP polling, no more latency
- Auto-configure Claude Code hooks — hooks are written to
~/.claude/settings.jsonon first launch - Facet Inserts — configurable pill buttons below the terminal that send text to your session on click (Settings → Facet Inserts)
- Prompt Library — Guild members can browse 70+ prompts from crystl.dev and import them as facet inserts
- Standalone Prompt Browser — Window → Prompt Library opens a separate browsing window with search and category filtering
- Universal binary — runs natively on both Intel and Apple Silicon Macs
- Proper code signing — inside-out signing with entitlements, notarization stapled to .app
- Single-instance enforcement — prevents duplicate windows and approval panel races
- Claude settings — Effort Level and Default Mode now properly saved
- Consistent glass opacity on all panels (Isolation, History)
- Non-zsh shell notice for fish/bash users
- Old Node.js bridge automatically cleaned up on upgrade
2.11.0
- Isolation panel — glass dropdown in the shard bar for worktree management: create, reopen, merge, and rebase isolated shards from one place
- Reopen worktrees — orphaned
crystl/*branches with commits or uncommitted changes appear in the Isolation panel for one-click reattachment - Worktree safety — existing intact worktrees are reused on reopen instead of being force-removed, preserving uncommitted changes
- Removed redundant status bar worktree button
- Fixed focus restoration after Isolation panel dismiss and merge error dialogs
2.10.0
- Isolation panel — new glass dropdown in the shard bar for worktree management: create, reopen, merge, and rebase isolated shards from one place
- Reopen worktrees — orphaned
crystl/*branches with commits or uncommitted changes appear in the Isolation panel for one-click reattachment - Merge-on-close prompt — closing an isolated shard with commits now asks: Merge to Main, Keep Branch, or Discard
- Gem close protection — closing a gem with unmerged worktree branches prompts to keep or discard all branches
- Agent guardrails — worktree agents are explicitly instructed not to merge, cherry-pick, or rebase to main; Crystl handles branch integration
- Worktree safety — existing intact worktrees are reused on reopen instead of being force-removed, preserving uncommitted changes
- Directory picker search fix — search field now accepts keyboard input and mouse clicks
- Bridge status redesign — replaced green dot with contextual "Bridge disconnected" warning button with troubleshooting popover
- Isolated shard fix — fixed zsh parse error when
claudeis aliased in the user's shell
2.9.0
- Bridge health check — one-time alert on launch if Node.js is missing or bridge can't connect, with clear instructions
- Bridge status indicator — warning appears in status bar when bridge is disconnected with clickable troubleshooting
- Code signing and notarization — releases are now signed with a Developer ID certificate and notarized by Apple
2.8.0
- Shard context for Claude Code — isolated shards inject branch name, worktree awareness, and parallel agent guidance into Claude Code's system prompt
2.7.0
- Worktree auto-setup — isolated shards auto-detect package managers (16 supported), install dependencies, and symlink .env files
- Custom setup commands via
setupCommandin.crystl/project.json - CLAUDE.md templates — pick from saved presets when creating a gem
- Template management in Settings → Starter Files
- UI fixes for Gem Settings panel spacing and path field
2.6.0
- CLAUDE.md template system — store multiple presets, pick from dropdown in New Gem panel
- Edit mode detection — Gem Settings shows whether a CLAUDE.md exists with option to insert
- Editor panel polish: spacing, text centering, focus ring, opacity sync
2.5.1
- History grouped by date — entries organized under Today, Yesterday, and older dates
- Auto-save fix — overwrites a single active file per shard instead of creating duplicates
2.5.0
- Session history — terminal output saved automatically when shards close. Browse, view, or delete from the History button. Auto-saves every 5 minutes.
- Shard close buttons — small × on shard pills for quick closing
- Stale branch recovery — orphaned worktree branches auto-detected and reattached or cleaned up
- Crystal Rail syncs icon and color when switching directories
2.4.0
- Session history — terminal output saved on shard close and app quit
- Shard close buttons — × visible when 2+ shards exist
- Stale branch recovery — branches with commits reattached, empty ones cleaned up
2.3.0
- Free tier expansion — isolated shards, API keys, and MCP server configuration now available to all users
- Shard limit increased from 3 to 5 per gem on free tier
2.2.0
- Worktree merge-to-main — rebase + fast-forward flow from status bar or right-click menu
- Warns about concurrent schema/migration changes in sibling worktrees
- No more Keychain prompts — API keys and license stored in
~/.config/crystl/with secure permissions
2.1.0
- Metal GPU rendering — hardware-accelerated terminal with automatic CoreText fallback
- Icon picker — fixed scroll behavior, category tabs stay fixed above scrollable grid
- Git-branch icons for isolated shards
- Directory picker close button
- Notification settings with descriptions for each type
2.0.0
First public release of Crystl.
- Gem-based project organization
- Parallel shards (sessions) per gem
- Split view
- Conversation history
- Crystal Rail sidebar
- Guild membership with license activation
- Sparkle auto-updates