changelog
What's new in each release of crystl.
2.188.0
- Vigil watches your fan-outs now, out of the box. When a manager and every worker it spawned go quiet at once, crystl nudges the manager and tells you if that doesn't move it — no setup required. Turn it off or tune how many nudges it sends before carding you in Settings → Agents → defaults.
- The Library is its own settings page. Global and project-level rules, skills, and plugins now live under one Library section instead of being scattered — each one says what scope it's in, and plugins get their own tab instead of being counted in with everything else.
- Key scan is a real settings page. Review the patterns crystl checks before a commit, switch any of them off, and teach it a key format your team uses that isn't on the built-in list.
- "add to gem" is a real picker. Adding a file to a project now shows every open gem to choose from, and asks before overwriting one that already has it.
2.187.0
- Auto-approve is off · in gem · all. The same three behaviours, renamed for what they actually do — "in gem" means the agent reads anything, changes only files inside that gem, runs git that can't lose work, and asks before anything else. Your existing settings carry over untouched, and both the old and new spellings work on the command line.
- A gem's approval mode is now a ceiling. A permission mode declared inside a project — an agent file's frontmatter, for instance — can narrow what gets auto-approved, but can no longer widen it. A file in your repo can't grant an agent more than you did.
- Groundwork for the phone. The conversation syncs incrementally rather than re-sending the whole transcript, which cuts the data a phone uses while watching an agent work by about 95%.
2.186.1
- Terminal text holds together when something scales it. A window that overlaps a display of a different scale gets re-rendered at that scale for screenshots, screen recording, sharing and mirroring, and moving a window between displays does the same for a moment. crystl now blends the terminal surface through those, instead of sampling it a point at a time and dropping rows out of the letters.
2.185.1
- The workbench drawer opens cleanly on a full board. Sliding it out could leave the terminal drawing its text over itself for a moment, on gems with plenty of tasks; the board is now ready before the drawer starts moving, so the terminal is left alone while it does.
2.185.0
- A shard that cannot run now says so. crystl tells you what is in the way: out of quota, a credential only a person can fix, or no agent left. It reads the same in
crystl status,crystl shards, on the shard row and tooltip, and on your phone, where these all used to read "idle". - Each kind carries what to do about it: wait until the retry time, go and unblock it, fetch a human, or respawn it. A rate-limited worker shows when it comes back, when its screen said when.
crystl wait blockedblocks until a worker is blocked, so an orchestrator can stop polling. Narrow it with--class input|time|credential|deadto wait for one kind. A worker already blocked when you start waiting is reported straight away.- A monthly spend limit reads as a credential block rather than a wait. Nothing about it lifts on a clock, so backing off would park a worker until somebody noticed by hand.
- A rate-limited shard no longer reads as stale, and a quest hero blocked on a credential no longer gets nudged through the night. The quest master hears what is actually in the way instead of "stuck".
- Your phone shows the block on the shard row and what it can answer, so an approval still stands out behind a quota wait.
- Switching gems is quick again on a big workbench. crystl used to read and parse the gem's WORKBENCH.md on the main thread on every switch, which is what made a large board pause the window. Opening the drawer no longer waits on that parse either.
- Workbench edits hold when an agent writes the board at the same moment. A tick or an edit made while crystl was re-reading the file could be dropped and then written back over.
- The terminal keeps its shape when the workbench drawer opens. It briefly drew text over itself while the grid caught up with the narrower pane.
- On your phone, opening a notification takes you to the shard it came from.
2.184.0
- Endpoints created with
crystl endpoint setare now callable by name and change nothing else, matching how the settings form has always behaved. Pass--enablewhen you want one to be the ambient default for plainclaude,codex, aider, opencode or goose. Endpoints you already configured keep the setting they have. crystl endpoint listmarks which endpoints are ambient defaults, andcrystl endpoint setsays so when a call leaves one that way, with the command to turn it off.- Enabling an Anthropic-format endpoint that runs on your own machine now tells you what that means for plain
claude: it uses that endpoint's key, and only the models that endpoint serves. - The settings toggle's own description now names the same thing, so the choice reads the same from either place.
2.183.0
- open models are now agents you can type. an endpoint called
glmgives youclaude@glm— type it in any shard and Claude Code runs on that model, while plainclaudekeeps running hosted Claude in the same shard. add--size smallto pick which of the endpoint's models you get - adding an endpoint fills in its callable agent for you, so a new provider is ready to use as soon as you save it
crystl endpoint list,setandremoveput the whole providers & keys form in the terminal, so your agent can look up which API format a provider speaks and set it up for you. free on every plan, and keys are read from stdin rather than the command line- the endpoint panel is two columns now: what the endpoint is on the left, what it runs on the right
- agents installed in your home directory launch correctly in worker shards again — an nvm or npx shim, a mise or asdf wrapper, or a plain alias in your shell config is now kept and used instead of being replaced
- an
sshortmuxalias no longer stops a new shard from starting its work crystl shard close <name>andcrystl shard rename <name>take the name directly,crystl docs search "…"works, andcrystl copykeeps working from a shell whose gem has since closed
2.182.3
- fixes the last launch crash from this weekend's packaging bug — the /fanout provisioner now loads its template the same safe way as everything else
- if crystl still won't open, download this version fresh from crystl.dev/download/latest; from here on updates apply normally again
2.182.2
- fixes a remaining launch crash on Macs restoring an existing session — the terminal renderer now loads its resources from inside the app, like everything else since 2.182.1
- releases are now smoke-tested as packaged apps before they ship, so this class of crash gets caught on the build machine
2.182.1
- fixes a launch crash that affected fresh installs and updates of the last few versions on some Macs — resources now load from inside the app itself
- everything from 2.182.0 rides along: tap-to-talk dictation on the Mac, card pushes to your phone, dismiss-all that clears the phone inbox too, and sturdier bridge errors
2.182.0
- tap-to-talk dictation comes to the Mac: a mic button in the chat composer turns speech into draft text, and anything you type mid-dictation stays put
crystl cardnotifications now reach your phone as push banners, and schedules gain a phone-reminder option- dismiss-all on the desktop now clears your phone inbox too, including notifications the desktop kept quiet while you were watching that shard — those now fold into the summary strip instead of hiding
- the phone inbox gets needs-you and notifications sections with swipe dismissal and card deep links
- gems keep their identity across a relaunch (session restore and formations both), so phone links and schedules stay pointed at the right gem
- push banners name the gem, never its directory path
- bridge errors are clearer: malformed query parameters answer a proper 400, refusals carry the structured error body everywhere, and a common token mistake gets a helpful hint
- the CLI refuses ambiguous gem or shard names instead of guessing, and listings no longer truncate long names
- release and build tooling got stricter guards behind the scenes
2.181.0
- Two open projects with the same folder name no longer confuse
--gem— commands list the matches and let you pick by id instead of silently using the first. crystl workbench check,start, andunchecknow confirm the task's real state on the shared board, so multiple agents working one list stay accurate.crystl history metricsadds anunattributedrow so the table matches its own total, and shows a dash where token counts were never recorded instead of a zero.crystl hero listand other listings no longer clip long names mid-word.
2.180.0
- Quest and gauntlet fan-outs no longer move your selection — new hero shards appear in the bar while you stay on your own shard.
- Antigravity shards keep the first typed letter.
- Codex shards are recognized as codex even when their prompt mentions another agent.
- A hero pin that is a complete command launches its own agent, and a project-local hero without a pin now follows your agent setup.
- Saved API keys: after an update, the keys page explains what needs authorizing and offers a one-click unlock — and a denied prompt can no longer hide or overwrite your stored keys.
- Agent-to-agent messages no longer mangle
@namementions, while@filereferences keep working everywhere. - Quest launch messages name exactly the shards they create, and the setup preview matches.
2.179.0
model@endpointworks everywhere a model can be written, including inside a command's own--modelflag.- Built-in heroes now follow your agent setup: their size picks the model from your own configuration instead of a preset id.
- Typing an agent's own
command@endpointspelling into a size field is caught with a hint that shows the accepted forms. - Quest launch messages now name exactly the shards they create, and the setup panel preview matches.
- Restarting right after closing a shard no longer brings it back.
- No more Keychain prompts at startup after an update — Crystl asks only when you use a keyed feature.
2.178.0
- Collapsed sections stay collapsed. Each gem remembers which ones you closed, and they survive switching gems and restarting the app.
- The + section input now appears directly under the button, instead of at the bottom of the board where you couldn't see it.
- Approvals stack in arrival order, so a new one lands where you expect it.
- The agent activity card stays put when approvals pile up, and the floating card stack scrolls properly when there are more cards than room.
- Heroes summon on the right model when your default agent isn't Claude. Previously a hero could hand a Claude model name to codex.
- A model endpoint that hasn't been told its context window now says so when you start a shard there, along with where to set it — the setting that lets crystl warn you before a long session runs past a small endpoint's limit.
- When you pick a model size that isn't mapped for your agent, crystl tells you it used the agent's own model instead of silently ignoring the size.
- Fixed a crash that could occur when a terminal view reported an extreme window size.
2.177.1
- Your exact start command now wins. When the command you configured already names a model, summoning a hero at a size keeps that command as you wrote it — including choices sitting beside it like
--effort high. crystl agent profile set --model-via '-m {model}'works the way every message spells it. A template starting with a dash used to read as a missing value, so only the--model-via=form went through.- Sizes saved for a custom agent now say when they need a MODEL VIA to do anything, at the moment you save them rather than at the launch that quietly ran the agent's own default.
- A size value that contradicts its agent row is refused with the reason instead of being kept as a model id.
- Settings reads your saved API keys without raising a keychain prompt, and says so when the keychain is locked rather than showing your keys as empty.
2.177.0
- Set small, standard, and large agent profiles to either a model id or a complete start command. Exact paths, environment assignments, arguments, model choices, and effort settings are preserved across shard, hero, quest, remote, and orchestrated launches.
- Create one-click agent facets from model endpoints while adding or editing them. crystl places the launcher in an available bar slot without treating assigned buttons as a limit on saved facets.
- Clarify agent launch fields throughout Settings and keep endpoint model suggestions clear of the Save and Add Agent controls.
- Stop endpoint metadata saves and background reachability probes from triggering unexpected macOS Keychain password prompts.
2.176.0
- Launch any configured agent consistently across shards, heroes, quests, restore, resurrect, schedules, and orchestrated workflows.
- Preserve exact custom-agent commands—including executable paths, arguments, quoted values, and leading environment assignments—when sessions are saved and restored.
- Configure model delivery for custom agents with MODEL VIA in Settings or
crystl agent profile set --model-via, with exact-command profiles inheriting native-agent defaults when appropriate. - Route local and hosted model endpoints through the same launch planner while keeping endpoint credentials out of command text, logs, history, and persisted launch identity.
- Start saved endpoint workers with a true one-click launcher facet; existing incomplete launchers upgrade automatically and use the new robot icon, which is also available for gems.
2.168.1
- Settings → general shows the command's status, with a banner when it needs attention
crystl doctorand bug reports with diagnostics now work out of the box for everyone- History indexing on very large, busy sessions is dramatically faster — first look in under a second, follow-ups in milliseconds
- Shard attribution no longer rescans session folders it has already answered for
- Storage clears run in the background and report honestly when they finish
- Collapsed blocks that aren't tool output no longer pretend to be expandable
- Codex shards waiting on a hook approval now show as awaiting input instead of idle
- Last release's what's-new card retired — upgraders get this release's news, not that one's
2.168.0
- Durable references — every transcript row has an identity that is either correct or clearly refused, never silently wrong
- Fast on big sessions — index requests on large, active conversations answer in milliseconds instead of re-reading the whole transcript
- Filters —
--index --tool Bash,--status error, and friends - Storage — Settings → Storage shows the timeline database size with a one-click compact; also
crystl history compact - Large existing histories finish indexing quietly in the background over the first few minutes after updating
- Typing stays smooth while agents stream — the rail's working glow and tile updates no longer compete with your keystrokes
- Click-to-expand tool output is steadier: full output or an honest "waiting" note, never a silent collapse — and things that aren't tool output no longer pretend to be expandable
- Codex shards remember their hook approval across updates — one trust prompt, ever
2.164.0
- Quests now prevent duplicate parties after relaunch and recover cleanly when hero shards remain after ending.
- End & close handles parties of any size, identifies any hero shards that still need closing, and keeps remote replacement terminals rooted in the repository.
- Quest Master now uses launch-specific greetings, and its read-only raw terminal has moved into the quest actions menu.
- Worktree protection now resolves remote symlinks on the host and hardens discard ownership and remote transport trust checks.
2.163.0
- Quest levels now finish reliably, preserve each party member's final outcome, and show completed status with the correct level numbers.
- Isolated shards now block destructive worktree escapes before tool execution, including Codex sessions using automatic approval modes.
- Questline, settings, and agent guidance now use consistent vocabulary and clearer capability guidance.
2.160.0
- wrote to the gem's main checkout — the change is in *no* branch. It will
- wrote into another shard's worktree — the change lands in a different
- wrote outside its worktree — home dotfiles, system paths, global installs,
2.158.0
- Questlines from crystl.dev. Settings → quest → questlines has a library you can browse, plus sync from crystl.dev to pull the whole catalog down at once. Six questlines to start: onboarding tour, refactor arc, release gauntlet, security sweep, test coverage climb, and vocabulary drift. Imported questlines sit alongside the built-in ones and can be duplicated and edited like any other.
- Convert a local JSON questline to markdown in place, so an older saved questline can be edited as a document.
- Notifications use the name you see. A renamed shard, a hero, or a court seat now appears in notification cards and approval panels by its display name instead of its underlying crystal name.
- Imported and synced heroes appear immediately — no app restart.
- Facet slots show how full they are (N/8) at a glance.
- Quest settings has tabs — quest and questlines — matching the tabbed layout in general, agents and library.
- A rejected-credentials sync now says your membership needs upgrading rather than reporting a generic failure, and bulk questline sync is gated the same way individual imports always were.
2.157.0
- Codex sessions no longer lose their scrollback history unexpectedly on a resize — a clear-screen sequence Codex sends during its own redraw was being treated the same as an intentional clear.
crystl notifyand/sendare more reliable under load: notify retries automatically on a dropped response instead of failing silently, and no longer double-delivers if a retry lands after all; a sent message now submits by default instead of sometimes sitting unsent in the prompt.- Bridge commands (gems, workbench, merge, and more) fail fast with a clear, retryable error instead of hanging when the app is busy under heavy multi-shard load.
- The
crystlCLI starts noticeably snappier — a networking check it used to make on every single command has been skipped since it never applied to this app anyway. - The approval-mode setting is now Tool Approvals (modes: *ask every time / smart / auto*) — it was easy to confuse with Claude Code's own "manual mode," which means something different (edits, not tool permissions).
- Quest's Party Size control is now Model Size — it always chose which model tier your heroes launch at, not how many of them show up.
2.155.1
- "Initialize git repository" is back on for a new gem in an ordinary folder. 2.155.0 turned it off everywhere, which left new gems as non-git folders: the first isolated shard was refused, and the auto-filled git remote never applied. It is now on by default, and off only when the folder sits inside a repo you already have — which was the case it was meant to cover.
crystl uninstallreverses everything crystl wrote outside its own app folder: Claude, Codex and Antigravity hook wiring, the CLI symlink, the bridge token, and optionally the CLI primer in your gems' agent docs. Runcrystl uninstall --dry-runfirst to see exactly what would change. It never touches your work — gems, worktrees,crystl/*branches and saved API keys are listed and left alone. Free on every tier.- Turning the Codex integration off no longer disturbs a running session. Previously it removed the hook script that live sessions still called, so every tool call failed until you restarted Codex. The hook is now disabled in place instead.
- The CLI primer can be removed. Turning the setting off stops writing new ones, and the primer already written into a project's agent docs can be taken back out — those files live in your repos, so removal is always an explicit, confirmed action.
- Antigravity works better. Transcripts are read from agy's own JSONL log instead of reverse-engineered from its database, so turns and timestamps are accurate. Hooks with a turn-finished signal are available (off by default),
crystl doctorreports installed agent CLI versions, and the model list uses agy's current ids. - Schedules are free up to 3 on desktop, CLI and phone. Existing schedules beyond the limit keep running.
- The folder picker opens with nothing selected, so the button offers the folder you are looking at rather than jumping into the first child. Files are no longer selectable, and the pointing-hand cursor holds across a whole file path in the terminal instead of flickering.
- Settings tidied. The library page uses the same tab style as the rest of settings, captions sit with the control they describe, and a control's description no longer floats halfway to the next setting.
- Creating a gem inside a crystl worktree now warns first — that folder gets deleted along with the worktree, taking the gem with it.
2.155.0
- Creating a new gem now keeps Git initialization off by default. The remote field appears only after opting in.
- Gems created inside a larger repository now default to shared shards. Creating a standalone nested repository is an explicit secondary action with a separate-history warning.
- Documentation now maps app, gem, and shard settings and accurately describes both three-dot menus.
2.154.0
- Settings → general is four tabs — appearance, terminal, gems, startup — instead of one long two-column page, and it remembers the tab you were on.
- Agents collapses from seven sidebar entries to four. A single agents page carries defaults, claude, codex and system prompts; schedules, MCP servers and API keys stay on their own. Every "open settings" link in the app lands on the right tab.
- The file library uses the same underline tabs, so settings has one tab style throughout.
- The folder picker finds a projects directory you already have —
~/Projects,~/Developer,~/dev,~/code,~/src,~/repos,~/work— instead of creating~/Projectson your behalf. It creates nothing. - The picker's button says what it will do: open here for the folder you're browsing, open selected for a highlighted one, go up on the parent row. Choosing the folder you're standing in was always possible; now it's visible.
- Creating a gem inside a bigger git repo warns at creation and offers git init here, rather than letting you find out later when an isolated shard is refused. Shared shards work there either way, so it only warns.
- That refusal now comes with a git init here button, and clearer wording about using a shared shard instead.
- Hovering a file path keeps the pointing-hand cursor across the whole path instead of flickering.
- The chat dock no longer shows Claude Code's internal bookkeeping — background-task notifications and context injections — as messages you wrote.
- cavrn is named as the recommended renderer in settings, with the xterm fallback moved below the settings you actually adjust.
2.153.0
- Collapsed tool-output rows in the default GPU terminal now say click to expand. Click one to open that exact Claude Code or Codex call beside the terminal without sending anything to the agent.
- Tool calls in the chat dock expand inline to their full input and output, with a one-click copy button. Long-running calls stay live until their result arrives, while completed calls that printed nothing are labeled honestly.
- Tool-call matching now handles deep scrollback, repeated calls, rapid clicks, dock closes, and transcript changes without opening the wrong row or freezing another result. When a match is ambiguous, crystl opens the dock without guessing.
- Prompt navigation in the GPU terminal now lands on the command line and returns cleanly to the live tail.
- Startup setup and error messages no longer block the app's main thread with modal dialogs.
2.152.0
crystl sendnow waits its turn. A line you're part-way through typing and a send arriving from the CLI or your phone can no longer end up glued together as one prompt — the send waits, or tells the caller to retry.- Sends also stop being blocked by input that isn't there any more: a draft you backspaced away, or a keypress a full-screen app swallowed, no longer wedges every later send.
- New
crystl send --waitconfirms a dispatch actually landed as a user turn in the agent's transcript, so an orchestrator knows its instruction arrived. - The chat dock stays inside its own column instead of drawing over the gem list on a narrow window.
- The chat dock now works for SSH remote shards — it used to open empty and stay that way.
- The shard bar's "+" waits a beat before dropping the creation column, so a quick click for a new shard isn't interrupted by it.
- VoiceOver now reads settings toggles as checkboxes and shard pills as buttons, with space-bar activation and a focus ring. First pass — more of the interface to come.
- The out-of-date demo is no longer offered from General Settings.
2.151.0
- Improve Quest planning: keep Save available after launch, restore quests without a Quest Master, add a raw-terminal escape hatch, and let the Quest Master use a chosen agent plus free-text model.
- Harden Quest level-close and unblock scripts so they use the signed bundled implementation, time out whole process groups, and cannot leave grandchildren running.
- Keep watched-shard questions and notifications out of global panels while preserving accurate shard attribution everywhere else.
- Make merged-but-not-fully-cleaned-up shards report their real state, including whether the worktree remains available.
- Tighten shard-bar layout and creation controls so pills use the available width and fast pointer movement stays deterministic.
- Fix prompt detection and screenshot-hover preview lifecycle regressions.
- Save Claude's default permission mode in the setting Claude actually reads.
- Harden the macOS app by removing unnecessary executable-memory and library-validation exceptions.
2.150.0
- emoji render properly in the terminal again — including flags, skin tones, and multi-part emoji like 👨💻
- crystl remembers your window size and position between launches
- a new window opens taller, and the bars around the terminal give back space they were holding — noticeably more rows to work in
- screenshot thumbnails are smaller, and hovering one shows it large without shifting the terminal
- long snippets in the copy bar stay readable — text now stops before the copy button instead of running underneath it
- the shard bar's creation icons drop down in a column on hover, so they no longer reserve width the shards could be using
- shard pills sit a little tighter
- split a pane and you can summon a hero into it, alongside a new or isolated shard
- the split button now reads "close split" while you're split, and lights up so you can see it's on
- collapsing the gems sidebar with the workbench open no longer flashes the shards behind it
2.149.0
- macOS gives an app launched from the Dock a limit of 256 open files. A busy crystl session — a pty per shard, file watchers, the bridge, SSH connections — uses more than that, and past the limit things fail in scattered ways: shards fail to start, watchers stop noticing changes, the bridge stops answering. crystl now raises its own limit at launch.
- This never showed up in development, because launching from a terminal inherits a much higher limit. If you've had a long session go strange in ways that cleared up after a restart, this is a likely cause — and it may also be behind the rare crash some people see after many hours.
- Starting a quest in your home folder now tells you why instead of reporting success for a quest that never started. Open the project's own folder as a gem and start it there.
CRYSTL_NOWnow refreshes in non-interactive shells too, so a script reading it gets the current time rather than a stale one.
2.148.0
- A shard keeps showing its agent for as long as the agent is actually running. Previously the agent/status fields were driven by hook events and faded about a second and a half after each one — so a shard whose agent was mid-thought, the longest part of a turn, reported no agent at all. Presence now follows the running process, and the working time you see counts real working time rather than time since the last event.
- This matters most for orchestration: a tool reading
crystl status --jsonto decide whether a worker is alive no longer sees a healthy, generating agent as absent. - Open in Crystl now appears in Finder's Services menu when you right-click a folder. The service had been declared for a long time but was never registered in a way macOS would surface.
crystl://links work in released builds. The URL scheme was declared only in development builds, so the handler in shipped copies had nothing to register it.- crystl's application bundle now carries the standard metadata macOS expects. Among other things, this is a candidate fix for a rare crash some people see after long sessions, reported inside the system's recent-items code — if you have been hitting that, we would like to know whether it stops.
- When you pin the bridge with
CRYSTL_BRIDGE_PORT/CRYSTL_TOKEN_FILE, an unusable pin now reports the problem instead of quietly connecting to a different bridge. Absolute paths are accepted alongside plain filenames.
2.147.1
- Scrolling the shard strip with a mouse works. With many shards open, a mouse wheel moved the strip by about a pixel per click — near enough to nothing that the shards past the edge looked unreachable. A trackpad was unaffected, which is why this went unnoticed. A wheel click now moves the strip a useful distance.
- Arrows appear at the ends of the strip when it overflows, on whichever side has more shards. Clicking one moves to the next or previous shard and brings it into view.
- Their tooltips name the keyboard shortcuts —
⌘⌃]and⌘⌃[— which step through every shard, including the tenth and beyond.
2.147.0
- The file menu in the markdown editor has a + new file action. Type a path relative to the gem —
notes.md,docs/api.md,docs/design/routing.md— and any missing folders are created along the way..mdis added if you leave it off. - New files land where the editor can find them again: the gem root, or under
docs,doc,notes, orwiki. Anywhere else and the file would be created but never appear in the list, so those paths are declined with a note about where it can go. - A gem with no markdown yet says so and points at the action, instead of showing an empty menu.
- An existing file is never overwritten — the editor opens it instead.
crystl doctor --fullcounts bucket scans accurately and labels them honestly, and its transcript census names the gem without including its path — so it's safe to attach to a bug report.- tmux shard identity refreshes correctly when tmux runs on a named socket with clustered flags (
tmux -2Lwork).
2.146.1
- Remote shards keep their conversation history on hosts with an unusual
stat,find, or directory permissions. The faster single-round-trip listing added in 2.146.0 now checks its own result and falls back to the older per-file listing when a host can't run it, instead of reading as an empty project. crystl doctor --fullreports bucket scans accurately. It was counting every conversation lookup, so a healthy machine looked like it was constantly searching; it now counts only the searches that mean something is wrong, and says so when there are none.- tmux shard identity refreshes the gem name as well. A naming overlap meant the gem could stay stale on a long-running tmux server.
2.146.0
- Reading a shard's conversation over SSH used to make one round trip per past session in the project — a project with a hundred sessions meant a hundred round trips, every refresh. It's now a single round trip. Measured on a local test host: 6.8s → 0.07s for a 100-session project, and the gap widens the further away the host is.
- The shard-identity fix from 2.145.0 now applies to agents running in tmux on a remote host, not just locally. Approvals from different panes stay separate, and hooks, transcripts, and history land on the right shard.
- The identity refresh also now works when tmux runs on a named socket (
tmux -L …), which previously skipped it. crystl doctor --fullreports how often crystl had to fall back to scanning a project's past sessions, and how many sessions each open gem has. Together they show at a glance whether shard attribution is healthy — and if it isn't, what it's costing.
2.145.0
- Shards keep their own identity inside tmux. A tmux server remembers the environment of whichever shard first started it, so panes could report a different — often long-gone — shard. crystl now keeps that identity fresh for new panes and for the next command in existing ones.
- The practical win: two agents in tmux panes no longer cancel each other's approval prompts. They looked like the same session to crystl, so one agent's request could quietly dismiss another's. Hook attribution, transcripts, and history now land on the right shard too.
- Panes attached from a terminal outside crystl keep working as before.
- Reading a shard's conversation no longer scans every past session in the project first. On a project with a long history that scan ran on nearly every refresh; it's now reserved for the history panel, which is the only place that needs it.
- A conversation that grows while crystl is reading it now stays cached instead of being re-read from the start next time — the case that matters most, since it's the transcript of whatever agent is actively working.
crystl doctor --fullnow separates "this transcript doesn't exist" from "crystl re-read a large file". They were counted together, which made healthy machines look busy.
2.144.1
- When you scroll a shard that's running tmux, vim, or Codex, crystl now explains it with a notification card rather than writing into the app's screen. The note tells you the wheel belongs to that app (in tmux,
set -g mouse onscrolls it) and reminds you the shard's earlier output is searchable the whole time withCmd+Shift+F.
2.144.0
- A party that works past its last authored level now waits quietly for the Quest Master instead of cycling. Author the next level and it picks straight up.
- Delegating with
quest_taskreaches heroes on a remote host — the assignment lands in their terminal, same as a handoff. - Vanished heroes recover on remote quests too: crystl reaches the quest host itself and closes the level so the party moves on, with no Healer needed in the party.
- "Continue quest" resolves the right party when your quest lives in a subdirectory of the gem.
--freshkeeps a plan the Quest Master just authored. Starting over from scratch is--fresh --emergent.- Task and handoff messages reach their recipient whatever the wording — a title that mentions
@allno longer holds one back. - An unblock that arrives during a busy stretch is held and delivered rather than dropped, and you get a card when one is deferred.
- Questlines with spaces in their names launch and delete cleanly.
- Ending a quest tells you if any verb couldn't be retired, rather than reporting a clean finish.
- Host-closes name each affected hero, and their per-quest limit now carries across a continue.
- Scrolling holds your place through a resize.
- Scrolling inside a fullscreen app (Codex, vim, tmux) now explains itself — you'll see the one-line note about enabling mouse mode instead of a wheel that seems to do nothing.
- Resizes reach the engine once instead of twice, which keeps redraw bookkeeping tidy on long-lived shards.
- Closing a shard releases its claims on unfinished tasks, so they're free for the next worker.
crystl workbench open --column backlog|progress|doneopens the panel on the column you mean.- Schedules can be created and edited from the phone.
- Sent messages settle correctly when a conversation switches underneath them.
2.143.0
- quest handoffs now land directly with the hero taking over — including heroes on SSH remotes — so the party picks work up right away
- the whole party gets notified when a questline wraps up, pauses between levels, or is called off
- a hero whose shard closes mid-stall no longer leaves its level waiting — the host wraps it up and the quest moves on
- new staged compose panel: every report opens for your review before anything is sent, with clear hints about who sees your email and where the report goes
- sharing to slack is your choice, with a direct-email option right up top
crystl doctor --fulladds a health snapshot (memory, caches, store sizes) — also available to agents atGET /api/v1/health- a threshold watchdog leaves perf breadcrumbs in crystl.log so slowdowns are easier to pin down
- license page: a mistyped key can now be cleared in place, and the activate button works reliably again
- Commenting on a non-task line tells you instead of silently doing nothing, and "+ section" is now a tidy link below the tabs
- session restore is smarter about transcripts that never existed — no more resuming into a blank session
2.142.0
- begin quest always starts clean — starting a new quest archives the previous chat aside automatically, so yesterday's conversation never bleeds into today's party. Picking up where you left off is the explicit "continue last quest" button.
- saved questlines get a delete — tidy up your questline library from Settings → storage, the CLI, or the bridge.
- quest end is dependable — ending a quest archives everything in one final step, and a quest running across SSH hosts ends everywhere or nowhere; if a host is unreachable, nothing is touched and you can simply retry.
- snappier chat with big fan-outs — the transcript cache now keeps your busiest conversation hot, so the chat dock stays responsive while a fleet of workers streams.
- collapsing the sidebar no longer pushes the copy and screenshot bars out of place
- the workbench/markdown title no longer truncates on a narrow panel
- clearing quest data from storage renders the page in place instead of into the settings sidebar
- the quest panel always shows its own quest's activity and levels, even after switching gems
- the quest loader's shine sweeps gently instead of parking over the phrase
2.141.0
- Heroes can now reach the quest master. A new
quest_unblocklets a hero say the party can't proceed — a member is gone, stuck, or out of context, or the plan itself needs rewriting. The quest master answers by amending the plan or telling you. It's an unblocker, not an advisor: heroes still decide their own work. - A level no longer hangs when a hero's shard disappears. If a shard is closed or crashes while its level is still pending, crystl now closes that level for you so the party can advance, and says so in the quest chat. It waits a minute first, so an accidental close is still undoable with
crystl resurrect. - Editing a questline no longer interrupts the party. Level edits show up in the quest chat as a record, but they no longer land in every hero's terminal — so refining a plan doesn't cost the whole party a turn each time.
- The quest master's own description now covers this, so it understands the role wherever it's summoned.
- The archive nudge is a quiet "archive done tasks" link rather than a button competing with your board.
- Dim titles in the top band ("gems", "· shards", "· workbench") no longer look heavier than the gem name beside them.
- The bridge now refuses to start rather than fall back to a weaker auth token if secure random generation ever fails, and no longer reuses older weak tokens. If you're on one, you'll get a fresh token on next launch.
- Terminal command history and the shard timeline both confine their writes to your project directories.
- Tightened validation on text arriving from a hero before it reaches the quest master.
2.140.0
- Entering a license key works again. Paste your key, click activate, and it goes through. If you're a Guild member who couldn't get a key to take, this is the one — no need to do anything but update.
- A rejected key can now be corrected in place. Previously the field held onto the old key, so retries kept submitting it.
- The Claude page now shows the effort level and default mode you actually have saved, instead of always displaying "high" and "plan".
- Reopening an isolated shard on an existing branch now tells you when that branch has fallen behind your base branch, so an agent doesn't quietly start working on stale code.
- Closing a shard on the xterm.js surface now releases its memory properly. If you use that surface and noticed things getting heavier over a long session, this should help.
- Command history writes are now confined to your project directories.
- Tightened validation on the SSH bridge address, and the SSH settings endpoint is now gated like every other setting that changes state.
- The developer-build licensing path is compile-time only and no longer present in shipped builds.
2.139.0
- Transparency slider always works — dragging it on a solid background switches you to glass (keeping your tint) and applies immediately; the grab area is far more forgiving too.
- Quieter shard bar — creation buttons slide out from the + on hover and tuck away after; pills fade at the strip edges instead of hard-clipping; the first pill sits on the shared left line.
- Finishing touches: more breathing room in the title row; chat/quest/branches match the tab text with even spacing; + section and the turns pill sit level with their rows.
2.138.0
- Quest loading line matches the spark's blue, with a subtle shine sweep.
- Facet bar sits closer to the status row.
- The terminal, its chrome, and the gems column all share clean left rails.
2.137.0
- Quest activity tab uses the full panel height with tidier edge fades.
- Workbench rows no longer stack hover highlights while scrolling.
2.136.0
- quests self-start: a freshly launched questline announces Level 1 to the whole party, so a headless start gets moving without a first message from you
- sealed-quest heroes seat faster: worktrees inherit the gem's external-imports consent, and a fresh party gets a two-minute grace period before any stall reminders
- planned questlines complete cleanly at their last level; an open-ended arc that runs past its authored levels now shows "awaiting next level" instead of a phantom next stage
- conversation timeline reliability: a version bookkeeping mismatch that could quietly pause history search and metrics now heals itself on the next launch
2.135.1
- the workbench markdown picker finds more of your docs: doc/notes/wiki folders, per-package READMEs and design docs, the live quest plan, and saved questline templates — always with the full path shown
- the quest master can retract a queued level with the new
quest_level remove(freely while planning; a running quest keeps its current and cleared levels protected) - quest window housekeeping: the plan doc syncs only when something actually changed
- the first-run agent card sizes to its text instead of clipping when several agents are installed
2.135.0
- continue quest actually continues: the Quest menu item and a one-click "continue last quest" button in the begin-quest panel relaunch your last party with its chat and questline intact
- sealed quests resume sealed: crystl remembers whether the last quest ran open or sealed and relaunches in the same mode (the quest master's proposal still wins when it stages one)
- stalled heroes get an automatic reminder straight in their terminal; the quest master only steps in when one stays stuck, reviewing the level brief and reporting to you
- begin-quest panel cleanup: the PREVIOUS CHAT pills are gone (carrying the chat forward is the default; "archive chat" lives in the quest window menu)
- The rename-shard and quest-master model prompts wouldn't accept typing
2.134.0
- quest master planning grows up: the quest master authors the plan doc live in your workbench editor, offers to help pick the party, and stages the begin-quest panel (heroes + sealed/open) so launch is one click
- save a plan as a questline template: new "save as template" button in the planning tab, plus a questline dropdown in the begin-quest panel for launching saved arcs
- quest plans now carry into fresh launches, so the levels tab shows the whole arc — progress bar, per-level barrier counts, and per-hero "level 3 in progress / complete" rows
- a quest-flavored loading strip while agents work: looting corpses, guzzling ale, casting fireball (again)
- quest window polish: the ready glow on "begin quest" sweeps briefly then settles calm, composer buttons share one style, and the window anchors to the quest button
- plan editing is smoother: the plan doc and quest state stay in lockstep — your edits fold in, authored levels render out
- keyboard shard navigation and approvals refinements: hidden quest master shards stay out of the rotation, and answering one approval leaves the rest showing
- Stale history-database recovery backups are cleaned up automatically
2.133.1
- The agent's status line / spinner could smear stale text across the top rows of the terminal while the copy bar (or another bottom bar) was open during a long task — you'd see fragments like "Boo…" welded onto earlier lines until you closed the bar. The renderer now repaints cleanly once the bar settles, so the top rows stay correct.
2.133.0
- Worktrees panel. The shard bar's branches button now opens a "<gem> worktrees" panel that shows all your isolated work at a glance. ACTIVE lists the isolated shards running now — each row shows what it's doing (its task), the agent and model driving it, how long since it last did anything, and its commit count; click a row to jump to that shard. PARKED lists branches you've set aside, each with its commits, dirty state, and last-commit age, and gives you reattach, merge, and discard right there (discard confirms first). The list scrolls when it gets long.
- Name isolated shards when you create them. Right-click the isolated-shard (⎇) button to name a new shard and its branch up front, so the git branch is meaningful from the start. Optional — leave it blank and crystl auto-names it as before.
- Markdown editor in the workbench. Switch the workbench panel to raw markdown mode to edit any of the gem's
.mdfiles, with syntax highlighting, smart list continuation (Enter continues a list, double-Enter ends it), and find/replace. A searchable file picker lets you jump between docs. Agents can surface a file for you withcrystl markdown show <path>. - Copy code and diffs from an agent's output. Hover a code block or a unified diff an agent printed in the terminal and a menu appears to copy it cleanly.
- Your isolated-branch work is safer. The whole worktree recovery path was hardened: crystl now only deletes a branch or worktree when it's certain nothing is lost. Uncommitted changes and commits are always preserved unless you explicitly discard, a worktree whose agent is still running is never touched, and anything crystl can't positively verify is left parked rather than removed.
- Resizable workbench and gem sidebar. Drag either column's edge to widen it; the window stays put.
- Gems moved to the sidebar for good. The old tabs-on-top layout is retired — gems live in the sidebar, which is cleaner and avoids the stacked-tab rough edges.
- Workbench polish. New sections add at the top instead of the bottom, the task list is less cluttered, and the pull-tab and divider line are aligned and gapped cleanly.
- Several worktree recovery edge cases: recovering the first isolated shard's identity on restore, commit counting, and keeping worktrees when a status check can't run.
- The code/diff detector missed blocks an agent had indented.
- The markdown highlighter could stall while typing in large files.
- Terminal hover stopped re-running detection on the same row repeatedly.
2.132.3
- Command blocks. Hover a finished shell command and a menu appears to copy the command, its output, or both — output comes back clean, with soft-wrapped lines rejoined and no prompt bleed. You can also collapse a command's output, re-run it, and jump between commands from the View menu. On by default; turn it off in settings if you prefer.
- A rare crash that could take down the app when multiple terminals rendered clickable hyperlinks at the same time. It was a data race on a shared link table, now serialized, so heavy sessions with many shards stay stable.
2.132.2
- Opening a project that's already open no longer snaps your view to a different one. A background or scheduled task re-opening a project can't yank you out of the gem you're working in anymore.
- Shards keep their names and restore correctly across app restarts. Previously a shard you hadn't opened before quitting could come back mis-named and fail to restore, and the drift got worse each restart.
- Fixed (security): the Enter-to-approve shortcut no longer auto-allows a pending approval from a different, similarly-named project. Approving in one project can't accidentally approve a tool call in a sibling like crystl vs crystl-web.
- Your agent's permission allowlist is now honored in every project you open. Crystl trusts the workspace on launch, so you no longer get the "this workspace has not been trusted" warning or lose your saved auto-allows.
- After you answer a permission prompt, Crystl nudges the agent to repaint, clearing a status-line garble Claude Code can leave behind. This is a mitigation for an upstream Claude Code rendering issue, controllable via the inkReprintNudgeOnDecide setting.
2.132.0
- Workbench is now a kanban board: slide between Backlog, In Progress and Done, and drag cards to change status.
- Sections are first-class group headers — collapse them like an accordion to cut clutter, and they group your tasks within each column.
- Cards get a full edit form: title, a scrollable description, an append-only comment thread, and a button to schedule an agent for the task right from the card.
- Your agents can now add task comments from the CLI and bridge, so a worker can leave notes on the board.
- Tasks carry stable ids, with archive/heal for done items and a warning when a board grows too long.
- Shard-bar pills gain rich tooltips with a hover marquee for long names.
- Agents are version-aware: they proactively check the changelog and suggest updating when you're behind.
crystl docsis now a discovery tool — it surfaces page URLs so your agent can point you straight at the right doc.- Notifications skip the card for the shard you're already watching.
- Faster status updates for parked workers, so a paused fan-out surfaces sooner.
2.130.1
- Resolve bundled resources on universal (release DMG) builds
2.130.0
crystl screenshots— a read-only CLI command that surfaces your recent macOS screenshots as paths your agent can open with its image tool. Say "view the screenshot I just took," "the 5 I just took," or "the app screenshot from yesterday" and the agent resolves it to files. Local (no bridge, works with the app closed) and free on every tier.- Faster keystroke echo when typing into your agent. Crystl was holding screen updates behind its streaming ghost-frame protection while you typed, adding latency to each character. It now recognizes your own keystrokes and paints their echo immediately, while streaming output stays protected.
- Restored streaming ghost-frame protection that a change in 2.129.1 had weakened during an agent's output.
2.129.0
- faster terminal rendering: the Prism engine now re-draws only the rows that actually changed and reuses cached rows the backend left untouched, so cursor-heavy output like progress bars, live logs, and TUIs costs noticeably less CPU. on by default, and verified byte-identical against the full-redraw path
- the workbench done-check is a brighter icy-blue that reads clearly on dark glass, and the checkbox repaints the instant you toggle it
- approval panels: a bounded reconcile timer sweeps away orphaned panels, so a stray approval can't linger on screen after it's resolved
2.128.0
- fixes a dirty git status from quest state: crystl now guarantees the
.crystl/.gitignoreon gem open, so quest runtime files can never show up as uncommitted changes — existing projects self-heal the moment you open them - toggles across settings are rounded rectangles now, matching the app's other controls instead of iOS-style pills
- internal hardening: the terminal's frame-damage optimization gained a regression net that verifies every rendered frame against a full rebuild, and the scrollback publish cadence is safety-clamped
2.127.0
- notification bell in the rail: a bell above the +/folder buttons toggles all floating cards out of the way for small screens; a badge carries the count (red when something needs you), and the whole stack collapses except the always-on agent activity panel
- crystl speaks through cards now: messages that used to print into the terminal (merge results, restore failures) would splice into an agent's live prompt — they now surface as notification cards instead, with failures headlined in red, and only print in the terminal when no agent owns the screen
- rail polish: bell, +, and folder share one look with hover states and tooltips, and their icons now match in brightness
- agent activity panel: more headroom above the title and more breathing room between shards
- notification sound plays on arrival even when cards are hidden, so a muted bell still chimes if you enabled sound
2.126.0
- facet submit works everywhere: submit-action facet inserts now press a real Enter, so the snippet actually runs in Claude's composer (and Codex, and plain shells) instead of landing with a stray blank line
- terminal snappier under heavy output: snapshot rebuilds are 69% cheaper, and the refresh cadence scales with your scrollback size so big buffers can't starve input handling
- scrollback up to 10,000 rows: a new preset for day-long sessions (measured linear cost; the 2,000 default is unchanged)
- agent activity polish: more breathing room between shards and the agent · model label sits next to the shard name
- Cursor blink can no longer stick off after a TUI resets mid-session; ghost-frame healing now covers scroll and resize repaints too
2.125.0
- spinner ghosts fixed: Claude's status-line rewrites could leave spliced, stale fragments on screen that only a resize cleared. the terminal now holds frames during rewrite bursts and self-heals if one slips through
- background shades: pick from 7 dark presets (graphite, black, navy, forest, oxblood, plum, espresso) with a glass or solid finish in Settings → general; every window and panel follows the choice live
- quest chat renders markdown: party and side-quest bubbles now format instead of showing raw markers
- quest scrollback: quest party members get their own scrollback default (1,000 rows), configurable in Settings → quest, so launching a full party stays light on memory
- memory telemetry: crystl status now shows app and per-shard memory plus system pressure, so orchestrating agents can check before fanning out
- crystl scrollback clear: agents can free a shard's retained scrollback on demand (same as Cmd+K), free on every tier
- faster startup: session restore no longer parses the same transcripts in parallel and resolves Claude sessions directly, fixing multi-GB memory spikes at launch
- smoother under load: the terminal builds each frame's projection once per present, and the tab bar and sidebar repaint only the parts that pulse
- Codex shards keep their identity across lazy restores; background tints stay accurate at low opacity
2.124.2
- Notification cards could appear blank and get stuck on screen after Crystl ran for a while (especially overnight with many pending) — the leftover panels are now cleared correctly.
- Choose your terminal scrollback size in Settings → General → Terminal Rendering (500 / 1,000 / 2,000 / 5,000 rows) — lower it to use less memory. Your agent's messages and the commands you run stay in history search (⌘⇧F) regardless.
- Set scrollback per shard when launching from the CLI —
crystl shard create --scrollback <N>— handy for keeping big fan-outs light on memory. - The agent activity panel is cleaner and easier to read — full shard and model names, aligned rows, a highlight on the focused shard, and no more cut-off status.
- Shard tabs show more of each name before truncating.
- More reliable isolated-shard branch handling when a shard keeps working after its branch was merged.
2.124.1
- Resizing the window while an agent was streaming could leave stale table fragments or ghost rows on screen that nothing repainted — resize now clears them, and scrolled-out history reveals correctly again after clearing the screen or scrollback.
2.124.0
- A visible terminal could freeze mid-stream when you clicked away to another app — windows now keep repainting while unfocused and only lower rendering priority in the background, so you can watch an agent work while doing something else.
- A rare crash on very tall terminal output (Metal texture limit) — oversized frames now clip instead of crashing.
- Tables, diffs, and other structured agent output no longer scatter or re-wrap when you resize the window — scrollback is width-immutable by default (a setting restores prose reflow for plain shells).
- Hidden and backgrounded shards no longer spend CPU rendering off-screen, and drop to lower-priority scheduling when the app isn't focused — noticeably lighter energy use over long, multi-shard sessions.
2.123.0
- Typing latency: keystroke echo is now roughly 40% faster. The terminal presents damage at 60Hz with hardened scheduling, so your typing keeps up during heavy agent output instead of lagging behind it.
- Fixed a rare blank-terminal hang that could happen after a resize or font change when there was no recent output.
- Fixed a data race in the terminal engine's synchronized-output handling.
- Hardened the GPU frame path: it no longer reuses an in-use surface or treats a GPU error as success, preventing rare visual corruption under heavy load.
- Reduced worst-case memory retention in the terminal's damage tracking.
2.122.0
- Deny destructive git state changes
- Inspect shell command strings
- Move rollout parsing off bridge route queue
- Bound Codex rollout and transcript parsing
- Document 2.117 session-age CPU root cause
- Retain uncovered Prism shadow damage
- Close self-destruction bypasses
- Stabilize no-agent scan classification
- Fix renamed worktree branch status counts
- Migrate timeline to unique session ownership
- Enforce one timeline owner per session
- Fix timeline agent and shard attribution
- Hard-deny shard self-destruction
- Inject guardrails for every agent
- Fix merge source branch resolution
- Instrument Prism damage scoping
- Prevent duplicate Claude resumes on restore
- Add Prism main-thread render benchmark
- Scan until agent classification
- Cache Prism table detection by content
2.121.3
- Back off the full process scan while idle
- Reset GlyphCache atlases to 64x64 on purge
- Break BacklogStore onExternalChange retain cycle
- Take the 20Hz agent-glow off the full-redraw path
2.121.2
- Move the last main-thread git off-main (.currentBranch + panel/scan)
- Force dark appearance so the search field isn't white-on-white
- Resolve the accurate default branch off the main thread
- Address code-review findings on the shard-bar + /gems perf fixes
- Cache + off-main the /gems default-branch git spawn
- Stop repainting the whole panel on every pulse tick
2.121.1
- Close a reprint burst that in-place churn holds open
2.121.0
- Isolated shards install npm deps reproducibly. Worktrees now provision with
npm ci(locked versions, matching main/CI) and no longer start with a dirtypackage-lock.json. An out-of-sync lock now fails loudly instead of silently installing different versions. crystl wait doneworks with renamed workers. Waiting on a shard by its display label (or crystal name) now matches its done signal instead of timing out.- Workbench writes stay in the calling shard's project.
crystl workbenchcommands run from inside a shard default to that shard's own gem — no more silent cross-project task bleed — and warn when a write targets a different gem.
2.120.0
- Keeps terminals responsive during heavy agent output by enabling Crystl's off-main Cavrn engine by default.
- Adds scheduled-agent controls to the mobile app, including viewing, pausing, resuming, and cancelling schedules.
2.119.0
- Fixed runaway CPU and memory use during long, file-heavy multi-agent sessions.
- Made growing transcript updates incremental so chatty heroes no longer repeatedly read, parse, or copy their complete histories.
- Kept timeline token metrics accurate when Claude repeats message metadata across transcript updates.
2.118.0
- Add a complete Scheduled Automations interface for creating, editing, pausing, resuming, and monitoring scheduled agent work.
- Improve schedule cards and notifications with names, agent selection, launch status, and clearer one-time and recurring behavior.
- Reorganize and polish Settings navigation, including reliable scrolling in compact windows and a read-only settings CLI/API.
- Show each shard's agent in Crystl Rail gem flyouts, alongside its live status.
2.117.0
- Schedule fresh agent shards for one-time, daily, or weekday runs, with time-zone-aware recurrence and agent, model, approval, and isolation controls.
- Workbench and resurrect CLI commands now honor
--gem, preventing reads and writes from silently targeting the selected gem instead. - Schedule creation now warns when the target gem has no agent configuration that can be resolved at run time.
- Sidebar chat, quest, and branches controls stay aligned with the gem title when isolated shards show pending-commit badges.
2.116.0
- Restored agents now lazy-load by default, activating when you visit their shard; choose automatic, lazy, or no resume in General settings.
- Formation restores follow the same resume policy while preserving active quest continuity, hero relaunches, and shard lineage.
- Timeline recovery now rebuilds only after confirmed SQLite corruption and preserves the complete database, WAL, and SHM set for diagnosis.
- Agent defaults now have their own Settings page, keeping agent-specific controls together and easier to find.
- Terminal rendering does less repeated snapshot and environment work during heavy output.
2.115.0
- Quest heroes now merge into their intended integration branch even when the main checkout is on another branch, with matching local and SSH behavior.
- Remote isolated and hero shards validate explicit base refs before creation and preserve generated sealed-quest targets.
- Clearing quest chat rebuilds Crystl-managed party rosters without losing the active party, while preserving hand-edited rosters.
- Timeline history preserves complete user and assistant turns while keeping tool output bounded.
- The branch picker remains stable while filtering and cleans itself up reliably when dismissed.
2.114.0
- Teach quest_level add in the quest-levels prompt section
- Env contract test asserted escaped source text, not the built script
- Compile environment contract test
- Expose Crystl environment contract
- Expose Crystl environment contract
- Fold errored runs into the rail attention badge with a "!" cue
- Roster labels a finished agent by its last kind, not "none"
- Clear a stale run outcome when a fresh agent is detected
- Per-gem popover is screen-aware and scrolls a large roster
- Clear the run outcome on every working transition, not just the hook
- Keep finished agents in the roster so their outcome is visible
- Clearing quest chat leaves scroll/channel artifacts behind
- Test the run-outcome → idle status mapping
- Tint failure notification cards red
- Roster shows run outcome: done ✓ / errored ✗ instead of bland idle
- Record agent run outcome (success/error) on the session
- Rename the "agents" panel header to "agent activity"
2.113.0
- Per-gem popover clears the rail edge
- Compact per-gem roster popover on re-clicking a gem
- Rail bubble stays centered, shorter tooltips, no reclick-roster
- Rail bubble tooltip garbage + over-large hover grow
- Agent roster scroll bar flash — update row text in place
- Rail bubble hover + tooltip driven by the tile, not the bubble
- Agent roster footer names the metric as tokens
- Agent roster scroll bar no longer flashes on every refresh
- Rail count bubbles get tooltips + a subtle hover grow
- Agent roster — model closer to shard name, wider status column
- Restore the thin window edge border at the true corner radius
- Group shard creation actions in File menu
- Align quest hero colors and context accounting
- Reduce Prism terminal stress overhead
- Approvals win screen budget; overflow "show" cycles them into view
- Per-column overflow footer so top-mode columns don't clobber each other
- Keep floating panels within screen budget
- Remove the window frost rim; native corner is clean
- Window frost rim is a uniform stroke, not a corner-pooling glow
- Window frost corners match the edges (concentric outer clip)
- Add gem and shard actions to main menus
- File-menu save/open formation
- User copy must not hit the OSC 52 prompt; 'allow once' must re-prompt
- OSC 8 fix must not narrow plain-path click-to-open (Prism regression)
- Ship OSC 8 + title-sanitize fixes; hold report suppression for decision
- Harden terminal escape handling
- Gate terminal OSC 52 clipboard writes
- Fix orphaned panels when animate-out completion is dropped
- Retire the rail settings flyout
- Default Approval moves to Settings → General
- Add "pause auto-approvals" to the app menu
- Attention badge tallies awaiting-input shards with pending approvals
- Idle badge: gem-colored, bottom-left; roster footer shows token burn
- Rail tiles show an idle-agent count badge
- Roster shows the model beside the agent name on the main row line
- Roster panel uses a fixed height with an always-scrollable list
- Roster stats line leads with the detected model
- Roster rows show context tokens, output burn, and estimated turns left
- Roster panel snaps into place on first show instead of flying across
- Selected gem tile click opens the agent roster scrolled to that gem
- Add agent roster panel (fleet view) toggled from the rail settings icon
- Branches button counts branches without the merge arrow
- Revival is an explicit mode, not inferred from restoredID
- Collision reroute is revival-only; reattach and exhaustion hardened
- Quest hero seats resolve gem-name collisions before seating
- Mid-flight name reservation still refuses, revival reroute stays
- Prevent shard name collisions during revival
- Shard menu left-aligns and truncates long branch refs
- Badge underline accent only on unselected pills
- Ahead badge anchors to the label's left edge
2.112.0
- Shards now always start at the gem root, and crystl says so: creating a shard while you're cd'd elsewhere prints a one-line hint in the new shard. Right-click (or control-click) the shard buttons to open the new shard where you are instead; the File menu carries the same actions, including a new Cmd+Ctrl+Shift+T for isolated shards.
- The isolated-shard button now lives in the shard bar next to +, with the same right-click support (option-clicking + is retired). Isolated "shard here" opens at the matching subpath inside the new worktree.
- See what's waiting to merge: isolated shards with unmerged commits show a small up-arrow count under their tab, and merge/rebase actions now name the branch, target, and commit count. The isolation dropdown is replaced by a "branches" button that appears only when parked branches from closed shards exist.
- Start an agent in a nested git repo and crystl offers to open it as its own gem — a dismissible suggestion, never automatic.
- Directory tracking is fixed under the current renderer and updates the moment you cd, which also repairs click-to-open for relative paths in terminal output.
- When creating an isolated shard auto-closes your gem's untouched default shard, the new shard now says so.
- An isolated shard can no longer land outside its worktree through a directory symlink, and suggestion cards respect the notifications switch and "dismiss all".
2.111.2
- Voice dictation works in shards: Crystl now ships the microphone entitlement and permission prompt that macOS requires, so agent voice input (like Claude Code's /voice) asks for microphone access on first use instead of silently recording nothing.
- The same fix applied across the board: agents and tools running in your shards can now request camera, contacts, calendar, reminders, photos, location, Bluetooth, speech recognition, and AppleScript automation access through the standard macOS permission prompts. Nothing is granted automatically — each capability asks on first use.
- Local network access is properly declared for phone pairing on macOS Sequoia.
2.111.1
- Quest reliability overhaul: quest status, claims, summaries, and handoffs now update under a shared lock with atomic writes, so parallel heroes can no longer clobber each other's state or lose ownership during compaction.
- Remote (SSH) quests: quest state replicates to the remote host atomically and survives sync races, preserving quest progress across reconnects.
- Quest verbs no longer fail with "argument list too long" on large task or state files — state is passed by path instead of through the environment.
- Party files stay lean: shared heroes no longer multiply their full instructions into party.json, and existing bloated files are healed automatically.
- Quest scripts self-heal from a shared master copy if a shard's local copy goes missing or is only partially installed.
2.111.0
- Exec bits on _quest_core.py, _quest_helper.sh, quest_claim
- Install _quest_core.py alongside quest_msg's helper; pin new handoff entry form
- Versioned quest-scripts master with atomic 'current' symlink
- Restore quest_claim exec bit lost in the E2BIG sweep
- Install master quest scripts only after the single-instance guard
- Quest verbs self-heal from a shared master copy on PATH
- Quest verbs read tasks/claims/status JSON by path, not env (E2BIG)
- Quest_level reads state/questline JSON by path, not env (E2BIG)
2.110.0
- Terminal stays responsive under heavy output floods: agent output now feeds the renderer in bounded slices with real backpressure, and scrollback composes incrementally instead of rebuilding from scratch on every write. Reading a busy shard's screen (app, phone, or CLI) now answers instantly during floods that previously froze it, and flood memory use dropped roughly 4x.
- Turns pill overhaul: token usage is attributed to shards by session id (no more cross-shard mix-ups), the pill and chart survive app restarts by rebuilding from the shard timeline, usage math is compaction-aware, and "turns left" is measured to the point where your agent actually compacts.
- Codex parity for turns and history: Codex sessions now feed the shard timeline (so they show up in history search and usage metrics), turn history restores for Codex shards after a restart, and Codex uses its own compaction threshold.
- New Codex models: GPT-5.6 Sol, Terra, and Luna with their full 1.05M context windows; the Codex default is now gpt-5.6-sol.
- Spinner and status rows no longer double or ghost under heavy streaming.
- Reopening a remote worktree shard now cleans up the leftover default shard as intended.
2.109.0
- Advance detectors sample at committed geometry — fix three sampling races
- Claude-sim samples until DONE-CSIM and the churn spans the sweep
- Reveal-mask hold escape — a stuck mask drops after 1s instead of blanking the pane
- TerminalCoreBackendBox forwards setOutOfBandEventHandler — sync-timeout flush now publishes in-app
- License file self-heal + deletion logging + XCTest mutation backstop
- Gate Prism presents while a DEC 2026 sync frame is open — spinner no longer doubles mid-rewrite
2.108.0
- Shard creation waits for shell startup readiness before agent launch
- search palette: native traffic-light close; custom ✕ was buried under the backing view
- search palette: Esc closes from anywhere + visible ✕ (field report: unclosable)
- Agent-driven search reveal — crystl history show opens the palette pre-filled
- Kind filter constrains in SQL, before ORDER/LIMIT (codex review)
- Add global timeline search palette
- storage page: outcome-first copy — say what you lose and keep, not the mechanism
- storage page: caches in a right column so a long gem list can't bury them
- Add storage settings page
- session store: tri-state host locality — sshHost can no longer go sticky (codex review)
- Ingest remote shard transcripts into timeline
- Isolated-worktree commands scope to the owning gem
- Invalid gem scope 404s; time-clear can't resurrect or corrupt FTS (codex review)
- turns pill: corner-pinned to the workbench edge, shard-tinted, severity fill
- Timeline Phase 3 — search/metrics/clear routes + CLI + ingest triggers
- Shard-timeline store — SQLite Phase 2 (spine of the timeline model)
2.107.0
- wait done: --idle-fallback requires --timeout (codex review)
- Typed worker done signal — notify --done/--blocked + crystl wait done
- quest markers: anchor @task/@done to line start (codex review)
- F2 inline @task markers built (bfa5ba74)
- Inline @task/@done chat markers create and close quest tasks (F2)
- F2 agreed design — inline @task chat markers, level-stamped not level-scoped
2.106.0
- Default-agent sentinel survives hero edit/duplicate and local hero files
- heroes page: default-agent hero cards show role only, no model tier
- default-agent ask: mention per-hero agent overrides in the copy
- default-agent ask: dropdown picker with custom… -> Settings and cancel
- default-agent ask: drop precedence mechanics from the dialog copy
- default-agent ask: only fire on a real quest-button click
- default-agent ask: all quest-selectable agents, fires unconditionally
- Pass Claude tier aliases through instead of expanding to pinned ids
- hero sync: absent agent ingests as the default sentinel, not a claude pin
- Heroes resolve their agent at summon instead of pinning Claude
- Check off remote agent-launch hardcode (fixed in f8f53606)
- Remote auto-start shard resolves its agent instead of hardcoding claude
- Sweep launched mobile track and shipped items
- Quest_level start/force-complete read party.json by path, not env (E2BIG)
2.105.0
- Work protection: closing a shard or gem with uncommitted changes now keeps the worktree intact and asks before anything is lost, and merges refuse to discard untracked files — local and SSH
- Fixed "allow all" acting on pending questions and fanout-worker approvals that had no visible card
- Fixed Cmd+click opening a file once per stacked shard
- Smart approvals now ask before destructive git commands like restore, stash, and branch -D
- Smoother under load: chat dock transcript reads, merges, and remote shard closes no longer block the UI, and quitting waits for in-flight SSH cleanup
- Quest messages with quotes or special characters no longer drop silently
- Crystl events/wait can no longer miss frames, and busy polling can't starve approval taps
- Dismiss-all count, opacity on every panel, rail tiles on quick close/reopen, and several slow memory leaks
2.104.0
- Redesigned the quest chat composer: the message box is now a multiline composer that matches the chat dock (Enter sends, Shift+Enter for a newline), with an insert button.
- The insert button offers quick party prompts (post status, regroup, wind down) that drop into the composer so you can tweak them before sending. Edit or add your own in Settings, Quest, Facet Inserts.
- The app now fades in gently on launch instead of the old zoom.
- Simplified settings page titles (dropped the redundant "settings" suffix).
- Fixed the wind-down questline telling heroes to run a command that was renamed, so it advances levels correctly again.
2.103.0
- Quest levels: heroes now coordinate through shared checkpoints. Each hero marks a level complete, and the last to arrive advances the whole party, no orchestrator required. A new Levels tab in the quest chamber shows progress.
- Fixed a slowdown where Crystl could climb to 100% CPU after days of running, caused by unbounded terminal scrollback plus repeated full re-reads of large agent transcripts. Scrollback is now capped and transcript reads are incremental.
- Fixed resumed quest heroes not finding quest_msg after a restart, so they reconnect with their team correctly instead of falling back to a manual workaround.
- Startup no longer auto-resumes a pathologically large agent conversation, which could stall a shard on launch.
- Quest chamber polish: the chat, activity, and levels tabs are restyled to match shard tabs, and the quest actions (export, archive chat, end quest) moved into a hamburger menu.
- The session-restore options are reworded and nested, so it is clear which one reopens your gems and shards versus which one resumes each agent's conversation.
- Smaller quest party files, isolated shards now work in freshly git-initialized gems, and assorted quest_level command fixes.
2.102.0
- The welcome tour now covers the copy bar and quest heroes/parties, and links straight to the iPhone companion app.
- Welcome tour cards auto-size to their text, so longer tips are never clipped.
- Quest commands (quest_msg, quest_heartbeat, and friends) no longer come up missing when starting a fresh quest right after updating Crystl.
2.101.0
- Configurable integration targets: point a gem's isolated shards and sealed quests at any branch (a release or feature line), not just main. Set a global default in Settings → Worktrees, override it per gem in the gem's worktrees tab, or use the new
crystl worktree targetCLI. Merges go to the target, and isolated shards now fork from it too. - Heads-up: isolated shards now fork from the gem's integration target (the repository default branch by default) instead of your current checkout. Set a gem's target to "current branch" to keep the old behavior.
- Fixed the frozen "thinking" spinner: a self-healing repaint watchdog ends the occasional stacked or frozen spinner during long agent streams, so you no longer have to scroll to unstick it.
- Cleaner table redraws on resize: better dedup of stale table copies.
- A real Settings screen with a default-view preference and a quest-tab toggle, shard detail now opens at the latest message, plus pairing-screen polish.
- A large batch of gem-settings panel fixes: the new worktrees tab, panel positioning, scroll behavior, and spacing.
2.100.2
- Tables no longer shatter on window resize: stale table frames, border skeletons, empty-cell frames, wrapped-cell fragments, and mixed-width rows are all cleaned from scrollback after narrow-to-wide drags
- Table rows that only ever existed at one width are preserved intact rather than deleted, so no content is ever lost during cleanup
2.100.1
- Hero editor hints hug their fields
- Hero editor fits laptop screens; AGENT hint no longer overlaps MODEL label
- Path browser can ascend to filesystem root — network mounts reachable
- Height-only grows never arm the reveal mask
- Height-only grow masks only the revealed top band; copy bar dips 20px into bottom chrome
- Copy bar carves the terminal content area instead of resizing the window
2.100.0
- Rapid double shard create no longer routes two agents into one worktree
- Deferred resize — grid + winsize commit once on settle
- Env-gated /debug-rows route — structured scrollback dump (glue instrumentation)
- Adopt stale-overhang invalidation + presenter mismatch contract (core c63fa97)
- ~40-column floors for window + split panes; document the winsize contract
- Adopt deep-centered hanging indent (terminal-core efb9e8b)
- Adopt hanging-indent reflow (terminal-core 7e083c0); promote narrow-reflow guard
2.99.0
- Deliver party messages to the quest's gem, not selectedProject
- Sealed heroes' replies landed in a worktree-local bus nobody watches
2.98.2
- Rename shards without losing their identity. Shards now have stable internal IDs plus editable display names, so you can keep human-friendly labels without breaking session restore, history, formations, CLI targeting, or mobile prompts.
- More reliable shard targeting. Bridge and CLI commands resolve stable IDs first, then unique display labels, and reject ambiguous duplicate names instead of silently routing to the wrong shard.
- Side quests stay connected to the right agents. Side-quest routing now uses hidden stable route names while showing the readable shard labels in the picker and turns panel.
- History and restore polish. Reopened shards keep their original session identity, worker lineage resolves by stable shard ID, and the history viewer shows current custom shard names where possible while preserving older original names.
- Agent safety fixes. Option+Deny now asks before aborting a whole session, Codex permission decisions use the required nested payload shape, resume prompts are agent-neutral, and PTY sizing is reasserted after spawn so TUIs do not start squished.
2.98.1
- Security hardening for license validation. Tightened how Guild membership is enforced so it can't be bypassed in shipped builds. Recommended update for everyone.
2.98.0
- Antigravity is now a first-class agent. Google's
agy(the Gemini CLI's successor) can be picked for heroes and quest parties with full model + persona support, and launches with the right binary. It replaces the sunset Gemini CLI in the agent picker. - Resurrect brings back Codex and Antigravity conversations, not just Claude. Reopen a recently-closed shard (Cmd+Shift+T) and it resumes the actual session —
codex resume/agy --conversation— instead of starting the agent fresh. - History and resurrect now track each shard by instance. Two shards that share a crystal name no longer show or resume each other's conversation — each resolves to its own session exactly.
- More reliable agent transcripts. Fixed a case where launching crystl from inside another agent session could stop shard agents from saving their history, which broke history, resurrect, and resume.
2.97.1
- Chat dock fixes — reliably shows the conversation now (fixed a session-resolution bug that could leave it empty), no longer ghosts over the terminal after opening Settings, and has a close ✕ in the top-right.
crystl historyshows token & model metadata — each turn carries its model + token usage + duration, with a session summary (tokens, tool calls, models, active time) on top;--jsonemits the full metadata. Useful for judging an agent's cost and context.- Drag-to-scroll selection — dragging a text selection past the top or bottom edge now auto-scrolls and extends it.
- Everyone lands on cavrn — anyone stranded on the retired SwiftTerm renderer is moved to cavrn's Metal GPU terminal, with the announcement card and a "learn more" link to the docs.
- Fresh-start launch — hold Option while opening Crystl to start with no restored gems.
- Copy-table ⋯ — now detects box-drawing tables and anchors just to the right of the table.
2.97.0
- Remove crystl block command + agent instructions
- Revert desktop chat-view reuse (empty-dock regression)
- Pin box-drawing tables through the hover-copy hit mapping
- Hover-⋯ copy: scan viewport with unified TableDetector
- Detect box-drawing tables via a shared TableDetector core
- Render the VM's stable-id entries in the conversation list
- Stable-id conversation entries + no-op refetch skip for the phone
- Pin chat view reuse with DEBUG measure/build counters
- Reuse worker-thread bubbles + cache measured sizes in ChatThreadView
- Reuse chat dock row views across streaming updates
- Add ChatListDiffer: pure prefix diff for chat view reuse
- Bump terminal-core pin to 494214f (live tables clip, not scatter, on narrow)
- Bump terminal-core pin to 0acfa47 (markdown table rows clip, not scatter, on narrow)
- Add detected-table hover ⋯ copy (raw / CSV / JSON) on the Prism surface
- Add CrystlKit markdown-table detector + DetectedTable model
- Detected-table copy + mobile render (parse what Claude draws)
- Bump terminal-core pin to 0646633 (passive blocks — let Claude draw)
- Prism harness: block scenario asserts the passive drawn-inline model
- Prism adapter: keep block regions in frames, region-based hover lookup
- crystl block: emit the full drawn fallback everywhere, drop c=1
- Spec PIVOT 2: let Claude draw — blocks passive, hover ⋯ as backup
- Block anchor hover ⋯ actions menu (copy as markdown/tsv/json + view)
- Bump terminal-core pin to c9bf51e (reflow root-cause fixes)
- Bump terminal-core pin to b442e50 (synthetic box-drawing glyphs)
- Spec pivot: blocks as hover ⋯ copy/download/share, not auto-open viewer
- Bump terminal-core pin to 530d57d (compact anchor persists across repaints)
- Update anchor byte expectations for the c=1 compact param
- Pin terminal-core 625a65a (accordion compact projection) + accordion viewer
- Update block CLI snippet copy for the accordion viewer model
- Accordion block viewer: one-row anchor + native viewer panel
- Quiet native block fallback: anchor row + spacer footprint
- Bump terminal-core pin to e1a8f4f
- Bump terminal-core pin to b546555 (tmux-anchored narrow reflow)
- Bump terminal-core pin to 0694602 (run/row-sequence reprint dedup)
- Bump terminal-core pin to ae73c59 (selection row-range clamp crash fix)
- Bump terminal-core pin to 57e3a03 (streamed-reprint dedup)
- Bump terminal-core pin to a70b6b9 (resize-reprint frame dedup)
- Bump terminal-core pin to 1561660 (in-place TUI replay around closed blocks)
- Bump terminal-core pin to f5e06ca (frozen-scrollback block-tag fix)
- Keep top-clipped block regions native in Prism scrolled viewport
- Bump terminal-core pin to 36778ac (top-clipped block rowOffset fix)
- Bump terminal-core pin to 5ba8791 (soft-wrapped table fallback residue fix)
- Fix xterm resize during async writes
- Add glass background SGR rewriter for near-black badge backgrounds
- Trim CLAUDE.md: tighten Agent Support intro + obsolete SwiftTerm aside
- Trim CLAUDE.md: collapse Typography token enumeration
- Trim CLAUDE.md: condense the file map to non-obvious entry points
- Trim CLAUDE.md: move glass-readability runbook to swiftterm-notes.md
- Trim CLAUDE.md: move Bridge API endpoint catalog to docs/bridge-api.md
- Fix Prism showing stale content after a shard shrinks below its content height then grows back (#55)
- Bump terminal-core pin to df3bc8d1 (Prism table-fallback-residue fix) (#53)
- Fix Prism live-resize cadence
- Reconcile settings cleanup with cavrn-default flip
- Bump terminal-core pin to ba95ae5 (block persistence + chrome extent + CRLF capture fix)
- One-time "say hello to cavrn" card for existing users
- Simplify TERMINAL RENDERING to cavrn default + xterm fallback
- Make cavrn (Prism) the default terminal surface
- Clean up terminal rendering settings
- Pin PTY == engine == layout width in the harness past launch
- Seat hidden stacked shards when the workbench drawer opens
2.96.2
- Fixed tables and wrapped lines getting permanently mangled when the window is narrowed while an agent is still streaming output. The row under the cursor was being cut short during the resize and never recovered; it now reflows like every other line, so mid-stream resizes are safe.
2.96.1
- Fixed a quest party starting with helper scripts installed for only one hero. When you launched a party, only one hero got its quest_* toolkit (quest_msg, quest_heartbeat, quest_task, quest_summary, quest_handoff, quest_claim) — the other heroes were left without them, and their PATH could point at an unrelated project. Every hero in the party now gets its full toolkit provisioned into the correct per-shard folder.
2.96.0
- Fixed quest agents going silent after you clear the chat history. Clearing chat used to move the quest helper scripts (quest_msg, quest_heartbeat, and the rest) out from under running quest shards, so agents could no longer post to the party until they rebuilt the scripts themselves. crystl now reinstalls them the moment you clear, so the party bus keeps working.
- 'crystl sidequest start' can now pair shards across different gems. '--gem' is optional, and each endpoint can name its own gem as '<gem>/<shard>', for example: crystl sidequest start --a web/garnet --b app/citrine. A bare shard name with no --gem resolves across every open gem.
2.95.0
- Gem settings now opens right next to the gem you clicked, and you can drag the panel anywhere.
- Gem settings scrolls internally when it gets tall instead of running off the bottom of the screen, on both the identity and agents tabs. The enable toggles on the right no longer get clipped.
- The side quest shard picker now lists every open shard on both sides, including plain shells, with a count so you can always find and scroll to the one you want.
2.94.1
- Fixed an occasional black frame when opening or switching terminal tabs — a safety timer now clears the overlay if the terminal's redraw acknowledgement is delayed.
2.94.0
- Lead-color dots — a worker spawned by an anointed orchestrator shows a small dot in its lead's crystal color, so you can see at a glance which orchestrator a worker belongs to and group siblings by color.
- Orchestrator visibility — the bridge/API and CLI now surface which shard is the orchestrator and, for a worker, its lead's name (
isOrchestrator/leadName). - Side-quest CLI —
crystl sidequest start/end/statusplus bridge routes, so you can spin up and track a focused side conversation from the terminal or phone. - Hover-only close — the shard-bar close × now appears only on the pill you're hovering, keeping the bar uncluttered.
- Restored Codex shards keep their agent — a Codex shard no longer comes back as Claude after a restart.
- Thinking-doubling / overlap — the terminal now refits when bottom chrome changes its height, fixing stacked spinner frames and separator rules drawn through text during heavy agent churn.
- Retired the auto-start-Claude setting (a default agent launched in every new shard); new shards start at your own shell.
2.93.0
- Agents are now time-aware: every shard gets the current time (CRYSTL_NOW), and the workbench and quest streams timestamp when items and messages happen
- crystl shards / status now show how long each agent has been working or idle and when it last produced output — so an orchestrator can spot a stuck fan-out worker at a glance
- More readable dimmed and secondary terminal text on the glass background
2.92.4
- Improved readability of dimmed and secondary terminal text on the glass background
2.92.3
- Much faster startup with many shards — the shard you're looking at loads first, and background terminals no longer pile up in memory
- Fixed faded grey typed input in the terminal — it now renders clearly readable
- Claim a task by adding @name to its line — shows a coloured pill you can clear with a click
- Cleaner spacing between active task cards
2.92.2
- Switching back to a shard no longer flashes blank — its last screen shows instantly while the live terminal catches up
- Fixed the terminal occasionally not repainting after the copy bar opens
2.92.1
- Fixed terminal text overlapping or garbling when opening the workbench drawer or chat dock
- Fixed the workbench board rendering garbled when its file used Windows-style line endings
- The workbench drawer now auto-opens only when items are added, not on edits or check-offs
2.92.0
- Lift dim text to readable contrast in xterm shards
- Refit xterm terminal when the backlog drawer toggles
- Send newline on Shift+Enter in xterm shards
- Stack side-quest picker columns vertically
- Filter side-quest picker to agent shards
2.91.1
- Improved remote shard readiness checks so SSH-backed sessions wait for the correct shell state before continuing.
- Tightened bridge routing, transcript handling, and clean-port test coverage for safer release validation.
- Fixed bottom dock layout clamping and refreshed several CLI/doctor/resurrect paths.
2.91.0
- Added
crystl gauntletto launch a release-readiness crew with two Seekers, one Monk, and one Scribe. - Solo hero shards now accept opening tasks with
--prompt/--task, includingcrystl shard create --hero ... --prompt .... - Updated the agent-facing CLI docs so spawned agents know how to use gauntlet and hero task prompts.
2.90.1
- Fixed screenshot and copy bars overlapping or staying offset after chat, sidebar, and backlog layout changes.
- Fixed xterm terminal colors so Claude and ANSI-colored output render consistently with SwiftTerm.
- Prevented inherited no-color tooling settings from making new Claude sessions render without color.
2.90.0
- New
crystl doctorcommand checks CLI install, bridge connectivity, and hook wiring before debugging approval or notification issues. - New
crystl resurrectcommand can list and restore recently closed local shards from the command line. - Expanded CLI automation for Workbench tasks, event streams, wait conditions, AskUser prompts, and SSH bridge routing.
- Improved remote SSH support for Codex shards, including notification and hook routing.
- Hardened shard resurrection so closed shards recover more reliably with their name, color, isolation state, and agent session.
2.89.0
- xterm is now the default terminal renderer, with SwiftTerm still available as a fallback.
- Terminal rendering settings now clearly separate xterm WebGL from SwiftTerm Metal GPU rendering.
- Added a terminal font picker for installed monospaced fonts, including Nerd Fonts installed through Font Book.
- Added a terminal renderer benchmark harness for comparing SwiftTerm Metal, SwiftTerm CoreText, xterm canvas, and xterm WebGL.
2.88.1
- Side quest: the shard picker now shows each shard's full name and colors it by its crystal, so you can tell exactly which two shards you're connecting. Long names scroll into view on hover.
- Fixed the command-line-tool description getting clipped behind the install status.
2.88.0
- New default terminal engine: a faster, more reliable xterm.js renderer that fixes the resize glyph-scatter and redraw glitches.
- Your existing shards are unaffected. New shards use the new engine automatically.
- Prefer the old engine? Flip back to SwiftTerm anytime in Settings > General > Terminal Engine.
- Plus 30+ terminal improvements under the hood: clipboard and paste hardening, click-to-open, file and image drop, split-pane focus, crash recovery, and hibernation for hidden shards.
2.87.0
- Approval, question, and notification panels no longer steal focus to a background agent. Your typing stays where you are, even during fan-out.
- The side-quest panel now shows its shard picker (it was being cut off).
- The turns button no longer overlaps the working directory path or long URLs.
- Push-based orchestration. Fanned-out worker shards notify their orchestrator the moment they finish or get blocked, so the lead never has to poll.
2.86.1
- Fixed the castle marker so it only appears after the anoint briefing is actually delivered to an agent.
- Cleared legacy false-positive anoint state on restart so plain shards do not keep the castle icon.
2.86.0
- Multi-agent chat (Phase 2): click a worker in the chat dock's workers tab to read its full lead↔worker thread inline.
- Anoint an orchestrator: the new "anoint" button (crown) sets a shard up to coordinate workers; it fires the briefing straight into the agent and confirms inline.
- Orchestrator shards now wear a castle marker, and the workers tab shows live worker status — both survive an app restart (worker lineage now persists).
- The start panel always fits on screen (the start button can no longer hide below the Dock), with a "local heroes" disclosure and a draggable panel.
- A clearer inline "continue / start fresh" resume choice replaces the old second window, and the misplaced non-quest shard restore is gone.
- The "end quest" dialog now guides the decision — it shows each sealed hero's branch state and offers "end & keep" vs "end & close", with the explanation tracking the button you hover.
- The pulsing quest-recall tile in the rail now comes back after an app restart instead of disappearing.
- Security & reliability hardening: stricter shell-escaping on shard cwd, quest hook input validation, image-upload path confinement, decision validation on the legacy bridge route, and honest failure reporting when an API key can't be saved to the Keychain.
2.85.1
- Fixed a memory leak — closing a shard or gem now frees the agent's memory. Previously an agent process could survive close and accumulate over a long work session.
- Agents can no longer override your gem's approval setting. If you set a gem to auto-approve, a fanned-out worker won't silently re-introduce the prompts you opted out of.
- The shard bar no longer fights your scroll — with many shards open, a "thinking" shard no longer snaps the bar back to itself, so off-screen shards stay reachable.
- Custom-named shards always get a color instead of an occasional colorless label.
crystl wait awaiting|idle— block until a fanned-out worker parks on a prompt or finishes its turn (for agent orchestration). The chat workers tab now reads "● W/N active".
2.85.0
- New — multi-agent orchestration view in the chat dock. When an agent fans out workers (
crystl shard create), the chat dock (Cmd+Y) surfaces them in a workers tab: a live, recency-sorted roster (status · activity · unread) with filters. Zero workers = exactly today's 1:1 chat, so it only appears when you fan out. - Workers no longer stall invisibly.
crystl shardsandcrystl statusnow flag a worker parked on an in-terminal approval prompt with⏸ awaiting input(and over the live event stream) — a blocked fan-out worker is visible instead of silently stuck. - Fixed: the chat dock could show the wrong worker's conversation when several non-isolated agents ran in one project — each shard now resolves to its own session.
- Fixed: chat answers could lose chunks — a big reply followed immediately by a tool call no longer drops text from the dock.
- CLI:
crystl closenow works on gem names with spaces, and reopening an already-open gem focuses it instead of duplicating the tab. - Quest hygiene: per-shard quest helper directories are cleaned up on close instead of piling up.
2.84.1
- Fixed a regression from 2.84.0 where resuming a normal (non-quest) session could inject a stray "re-read the recent quest chat" prompt. Resume now only adds the quest continuation prompt for actual quest heroes.
2.84.0
- Fixed a freeze where Crystl could hang for up to a minute. The agent process scan and git-repo checks no longer run on the main thread, so heavy sessions stay responsive.
- Fixed resuming a quest. Reopening a quest now restarts each hero's Claude session with a continuation prompt instead of failing to come back.
- Fixed Return not always submitting in the chat dock. Typed messages now reliably send (bracketed-paste + retried Enter), including multi-line.
- Fixed the chat dock dropping an agent's answer (it would flash in then vanish on the working→idle edge), plus a related case where one shard's conversation could linger after switching shards.
- Hardened the gem-sidebar layout so the terminal stays correctly sized below the shards bar, split panes included.
2.83.0
- A new insert button brings your facet prompts straight into the chat composer, grouped by slot in a compact, scrollable list. Pick one to stage it for editing, or have it send right away.
- A typing indicator now shows while your agent is working, matching the phone.
- More reliable agent spawning: a first prompt that contains apostrophes or quotes no longer breaks a new shard's launch.
- The turns-left indicator now sits centered under the terminal and no longer overlaps long file paths or URLs.
2.82.0
- Heroes now come from crystl.dev. Fresh installs ship with the 15 core preset heroes (no download), and Settings → Heroes → "sync from crystl.dev" pulls the full roster on demand. crystl.dev is the source of truth; each hero carries its agent and model.
- New "end quest" button right in the quest panel header — end a running quest in one click (heroes return to normal solo shards). Also available as
crystl quest endand over the bridge. - Quest party roster only shows actual heroes now. A regular shard that happened to be open in the gem no longer gets pulled into the party.
- Hero file claims moved to the Activity feed. The roster stays clean (name, role, context health, status); who-locked-which-file now reads as activity.
- Clicking a DM channel or party member while on the Activity tab now switches you back to chat so you actually see the conversation.
- Add items to a specific section with a per-section "+ item" button (always visible). Section titles type in caps to match how they render. The panel title is larger so it outranks section headers.
- Quest panel buttons unified to a single bordered "turns button" style with consistent corners; "open quest" stays a pill.
2.81.0
- Pin the chat composer to the bottom of the dock column
- Start the copy bar right of the chat dock column
- Keep the chat composer fixed when the screenshot bar toggles
- Make rendered links clickable in the chat dock
- Keep the turns button clear of the cwd path label
- Syntax-tint fenced code blocks in the chat dock
- Render horizontal rules in the chat-dock markdown
- Render blockquotes in the chat-dock markdown
- Accept image drops into the chat-dock composer
- Add a gap between the screenshot bar and the chat composer
- Render markdown in chat messages instead of raw text
- Seat chat dock in the terminal content band so the composer clears the screenshot bar
- Coalesce re-entrant drawer rebuild to stop doubled rows
- Clear working state on StopFailure, not just Stop
- Never steal focus on programmatic shard create
- Submit the composer on Return via keyDown
- Correct shell quoting in quest_msg helper guard
- Abort quest_msg if _quest_helper.sh missing; copy helper before producer
- Drive the chat dock off real-time events, not a 2s poll
2.80.5
- Make the composer reliably grab the caret
2.80.4
- Show checkmark on the View-menu toggle-chat item
- Tear down chat dock when its shard/gem closes out from under it
- Re-target chat dock synchronously on shard/gem switch
- Close stale background default shard on remote isolated create
- Quest tile renders white and shimmers while the quest is live
- Desktop chat-mode dock for agent conversations
2.80.3
- Inset the pinned creation cluster from the window edge
- Let the panel go behind other windows (drop floating level)
- Shorten message input to the chat column, not full window width
- Clamp party roster scroll region above the input bar
- Stop quest/isolation labels collapsing in sidebar (stacked) mode
- Keep Isolation/quest labels from collapsing at high shard counts
- Scroll party roster so large parties don't spill off-screen
2.80.2
- Make Quest popup draggable by its top bar
- Use defaultBranch for advisory diff refs
- Refuse remote isolated restore on worktree-create failure
- Surface branch-reattach failure distinctly from generic failure
- ShellEscape the local quest temp-file path
- PATH floor so launchd/Finder launches can spawn a shell
- Confine POST /gems open-path to $HOME
- Insert
--before host in ssh terminal-send sites - Refuse merge/rebase when primary checkout is off the default branch
- Insert
--before ssh host in every RemoteSession argv - Reassert token file mode 0600 on every rewrite
- Never degrade a failed isolated create onto the primary checkout
- Validate OSC 7771 ssh host/control-path before storing
- Constant-time bearer-token compare
- Add scripts/verify.sh — one-command renderer/engine gate
- SwiftTermEngine adapter + TerminalRenderHooks (sole backend)
- Define TerminalEngine protocol + EngineCursor (CrystlKit)
- Read-only DEC mode 2026 sync instrumentation (gated)
- Schedule a draw on sync-frame edges so the widened dirty range is consumed
2.80.1
- Show pointing-hand cursor over the Copy button
- Wordmark → brand serif logo lockup (splash + pairing)
- Self-reconcile the orchestrate prompt so improvements reach all users
2.80.0
- Update app icon to the new gradient-crystal mark
- Free the iPhone app over LAN; keep "from anywhere" Guild (Apple 3.1.1)
- Default bug-report reply email to the licensed account
- Persist gem/shard layout on every change so restore survives crashes
- Full-rebuild on shard re-show (belt-and-suspenders)
- Tighten hidden-shard guard (drop alpha clause, add re-show repaint)
- Don't draw hidden/stacked shards (Metal bleed through glass)
- Apply Crystl renderer patches as source
- SwiftTerm v1.12.0 source in-tree (pristine upstream)
- Crystl render --dump-cells — offline bytes→grid dump
- Headless bytes→grid render seam for the agent-first harness
- Vary injected CLI snippet intro by build identity
2.79.0
- Draw the handle brighten in the view itself
- Pull-tab signal is a slow brighten, not a faint sweep
- Make pull-tab shimmer sweep vertically
- Arm the file watch before the workbench file exists
- Prevent pull-tab shimmer from double-stacking
- Close orphaned default shard on background isolated create
- White quest tile that pulses + shines while agents work
- Don't steal focus on background/CLI shard creation
- Shimmer the pull-tab handle when an agent adds items
- Make the quest chat window closable
- Replace confusing goal placeholder with system-voice orientation
2.78.0
- Default to Claude Code's classic renderer in Crystl
- Raise scrollback to 2000 lines
- Align question text's left edge with the header
- Stop the layout pass from restretching the panel to 360pt
- Auto-dismiss question/notification cards a beat after "show"
- Don't let a stale questAgents entry override the live hero
- Make the agent field a plain text box that reliably saves
- Inject persona for custom quest-party agents + agent-field hint
- Open-ended agents for heroes and quest roles
- Accept any CLI as a custom spawn agent
- Require movement before a library row starts a drag
- Skip the bare-shell guard on remote shards
- Don't touch existing users' bar when seeding orchestrate
- Guard orchestrate against a bare-shell paste
- Orchestrate-specific upsell instead of the generic Guild pitch
- Drag-reorder slots & library, primary treatment, view button
- Add Guild-gated orchestrate facet
2.77.3
- Stop the focus-report storm that froze focus-reporting TUIs
- Open links async so click-to-open can't strand keyboard focus
2.77.2
- Don't carry a text selection across tabs
- Revert "fix(copy-bar): make only the active tab chip read as selected"
- Make only the active tab chip read as selected
- Keep selected text readable with a tinted selection
- Use overlay scrollers so text isn't wrapped short by the scroller gutter
- Show a pointing-hand cursor over the Copy button
- Reclaim terminal focus on click so the caret isn't stranded
- Stop a background TUI shard from stealing the window's scroll
2.77.1
- Route a background-gem push to that gem, not the foreground bar
- Auto-hide the scroller so it stops overlapping the Copy button
- Make the copy bar per gem instead of window-global
- Don't report a TUI's dim ghost-suggestion as typed input
- Give the copy button a solid background
- Hand keyboard focus back to the terminal on Esc
2.77.0
- Auto-close a delegated task when its summary lands
- Collapse chat/tasks/summaries into Chat + Activity
- Keep the quest window from vanishing + always-recallable chat
- Keep sidebar health bars up across transient agent-detection misses
- Show the active party name in the quest window header
- Move file-claim noise out of chat into the sidebar
- Stop blanking hero roles in the chat sidebar
2.76.2
- Make crystl copy free on every tier
- Editable docked copy bar with shard-colored tabs
- Crystl party list/create/delete
- Reveal hero stat card on click, not hover
- Committable named party templates via "create local party"
- Flip dropdown above the bar when it would fall off-screen
2.76.1
- Show custom heroes in the solo summon picker
2.76.0
- A party new to a directory starts on a clean chat
- Only prompt "continue?" when relaunching the party that owns the chat
- Dedup-proof the add-member dropdown + drop picker diagnostics
- Party popup deduped duplicate-titled parties, breaking selection
- Select popup after add-to-hierarchy + prune orphan party files
- Defer party-popup relayout so the selection commits
- Move "edit parties" out of the party popup
- Name shards after the real hero + repaint chooser popup title
- Launch the party the user selected (capture rendered selection)
- New party starts empty + header reads "new party"
- Make + add member dropdown exclude by identity, not label
- Show a party member's real hero name, not its label's catalog match
- Constrain YOUR CHARACTER bar to one column width
- Move YOUR CHARACTER to Heroes page + fix roster overlap
- Unclip continue-quest button + always show selected party
- Preserve typed party name + dedup by identity in editor
- Stable hero identity on party members + local parties
2.75.10
- Fixed a crash while a Quest is running. The app could hard-crash (and take the window down) when a quest party was active — the quest panel's color lookup choked on a duplicate member name. It now tolerates duplicates safely.
- Quest messages no longer leak between projects. If you switched to another gem while a quest was still running in the first, that party's chat could get injected into the wrong project's shards. Quest delivery now stays scoped to the gem the quest is actually running in.
2.75.9
- Quest announcements post once, not N times.
quest_announcenow drops a single line in #quest and pokes each hero's terminal once, instead of fanning out a copy per teammate — roughly half the chat noise gone, and broadcasts reliably reach everyone. - The party narrates what it's doing. Claims, task hand-offs, and summaries now show up as compact lines in the #quest chat, so you can follow (and jump into) the coordination without reading every agent's prose.
- Live hero health + roles. Quest heroes now report their real role and context level even with the chat panel closed, so the health view and auto-recovery have live data instead of blanks.
- The party you pick is the party you get. A custom hero you made by duplicating a built-in no longer sneaks into a party by sharing the original's role — party membership stays exactly what you selected.
- Fixed a crash from tooltips. A use-after-free when tooltips were shown could crash the app; tooltip owners are now retained correctly.
- Cleaner hero migration. Stopped a one-time migration from cloning built-in heroes as stray "(custom)" duplicates.
2.75.8
- Refuse to start a quest rooted at the home directory
- Size the editor panel so the save button is on it
- Persist heroMode across show()'s internal dismiss
- Persist --status from quest_heartbeat
2.75.7
- Persist quest-bus membership so chat survives restart
- Keep the editor's save button on-screen
2.75.6
- Show quest-party shard costumes in hover card + profile modal
- Re-resolve party members against live catalog at launch
- Point Sparkle zip enclosure at the download proxy
2.75.5
- Ship Sparkle updates as a zip, not the DMG
- Hover mini card + expand to full profile modal
- Restore hero costume on last-session relaunch
2.75.4
- Blank the chat topic line instead of a bare #quest label
- Allow standalone self-summary without --task-id
2.75.3
- Stop quest heroes inheriting the selected shard's cwd
- Bind staggered summon to target gem by identity
2.75.2
- Show gem icon in quest chat header + fix pill label
- Validate + lowercase hero names at save
- Materialize hero shards when party uses custom heroes
2.75.1
- Kill multi-agent terminal text overlap via per-row content hash
2.75.0
- In-app create/edit for local heroes + LOCAL column polish
- Read charter from hand-authored .crystl/heroes JSON
- Persist hero charter through party.json round-trip
- Author charters for the built-in hero catalog
- Scaffolded Charter field in the hero editor
- Inject hero charter into quest + solo system prompts
- Add QuestRole.charter field
- Align columns, color names, dupe, LOCAL header/subheaders
- Custom heroes selectable + resolvable in quest parties
- One-time migration of flat overrides into custom heroes
- Dedicated Heroes settings page + slim the Quest page
- Stop writing flat override dicts for built-in edits + library import
- Duplicate-&-edit built-ins into named custom heroes
- Fold global custom heroes into catalog + /heroes with precedence
- CustomHeroStore global CRUD + dupe guard
- Add CustomHero record + LocalHero avatarId
- Find bar lands on the topmost match; note count is a hint
- Collapse split to a single Cmd+D toggle; drop dead pane items
- Cmd+F find in scrollback
- Cmd+Opt+1/2/3 facet-slot hotkeys
- Gem/shard/pane navigation + Cmd+K clear
- Add crystl shard close
- Gate the per-chunk dirty kick during mode 2026 sync frames
- Write MCP-trust flag into isolated worktrees so agents don't re-prompt
2.74.0
- Launch the first hero by session identity, not name lookup
- Honor the project's persisted active party for CLI quest start
- Honor --model when summoning a solo hero shard
2.73.1
- Apply global hero customizations to solo summon
2.73.0
- Solo hero shards — summon a catalog specialist on its own
- Keep manual selection alive during streamed output
- Cmd+click to open any file path or URL
2.72.0
- Drop free-tier count caps — unlimited gems, shards, facets
- Monospace the sidebar group headers
- Inclusive, shorter page description
- Swap settings columns — library left, slot buttons right
- "Your prompts" → "Your facets"; subcopy names prompts + commands
2.71.0
- Translucent overlay scroller to match the glass panel
- Anchor to the default sidebar + add a workbench step
- Rename "backlog" to "workbench" (user/agent-facing, back-compatible)
2.70.0
- Add license + connect iphone to the app menu
- Sync push opt-in with the real system permission
- Suppress the push banner for the shard you're viewing
- Apply notification deep link on cold launch / after pairing
- Gate phone pairing behind Guild, show upgrade prompt
- Richer quest party in demo mode (3 heroes, multi-hero thread)
- Make the push opt-in card specific about phone notifications
- Make email the expected default on bug reports
- Tell agents to offer a reply email on bug reports
- Fast-poll the transcript while the agent is working
- Broadcast working/idle on hook edges so phone dots track all agents
- Lowercase the crystl wordmark in the app menu copy
- Suppress "live updates lost" banner in demo mode
- Lock the app to portrait
- Tell agents to interview + investigate before filing a bug report
2.69.0
- Quest button going dead after the setup panel is dismissed
- Stop the ping burst when reopening a quest with history
- In-panel "start fresh?" launch step with a back button
- Keep setup panel open when editing in a child panel
- Relaunch each hero's agent when resuming a quest
2.68.0
- Click-to-reveal description + sane new-item focus flow
2.67.0
- Add fanout worker protocol to PromptTemplates + settings page
- Draggable gem reorder + marquee fix
2.66.0
- Move default spawn agent to top of left column + layout fixes
- Wrap the default-agent description + clearer title/copy
2.65.0
- Hand focus back to the terminal after committing an edit
- Hover states for the + new / + item / + section pills + backlog handle
- Show which conversation you're in + color the DM list
2.64.0
- Keep the sender color when a message is clicked
- Polish the chat sidebar — hover, channel order, DM hint
- Keep the intro logo out of hero DM channels
2.63.0
- Extend the drawer to the full right column
- Scroll the CRYSTL QUEST logo with the message flow
- Rebuild terminal rows after a sidebar-mode toggle resize
- Stop the screenshot bar sliding under the open drawer
- Re-hide gem header when flipping out of Settings in tab-bar mode
2.62.0
- Launch agents on a task via
shard create --agent/--prompt - Bind remote access on the flag alone, not the async license
- Detect tunnel-port conflicts and add
crystl ssh bridge-address - Apply per-hero model at quest start instead of clobbering it
- Add settings toggle for the SSH preflight diagnostic
- Warn in-terminal when remote agent notifications can't reach Crystl
- Inject CLI/backlog snippet when picker reconfigures a gem in place
- Guild upsell on the mobile settings toggles
- Full-gate remote access on Guild license
- Advertise quest, fs, open/close, askuser, facet in the CLI snippet
- Autoscroll long gem titles on hover
2.61.0
- More breathing room above the CHAT HISTORY section
- CHAT HISTORY header + explanation in setup panel
- Roomier clear/start-fresh confirm with header + explanation
- Preserve party roster across archive, don't lose definitions
- Crystl quest start CLI command
- POST /quest/start bridge route to launch a party headlessly
- Crystl quest clear CLI + POST /quest/clear bridge route
- Continue/start-fresh launch prompt + manual clear button
- Archive-not-delete primitive for clearing chat history
2.60.0
- Claude's chat speaker tag in its brand orange
- Chat tracks the agent's reply live, not on a 18s lag
- Quest logo caption text style, fanfare off-main, accurate comment
- /quest returns no messages when the quest is inactive
- Push quest end on shard/gem close, not just explicit endQuest
- Refresh gems only on quest membership change, not per message
- Match desktop quest hero colors (was 3 purples)
- Refresh the phone when a quest ends (stale conversation)
- Tile the quest logo pixels + typewriter font on awaits screen
- CRYSTL QUEST logo on the quest tab's "awaits" screen (was swords)
- Phone registers a desktop-launched quest immediately (was ~8s)
- Quest logo as a fit-to-width default screen, not a clipped flash
- CRYSTL QUEST intro overlay on quest-chat open
- Port the synthesized quest fanfare to iOS
- Restore the launch intro (logo + fanfare) — join was posted too early
- Persistent per-hero colors in the quest chat (match desktop)
- Resolve Claude transcript by the file it's writing, not argv/mapping
- Submit injected quest paste with a separate, delayed double-Enter
- Delta-aware screen refresh in the shard VM (Phase 3)
- Row-delta screen responses via ?base= (Phase 3)
- Screen row-delta DTO + pure apply (Phase 3)
- Push-driven shard refresh, drop the fast 1.5s screen poll
- Emit unified, sequenced shard_update (screen + transcript)
- Shard_update event DTO, gap helper, and stream/VM wiring
- Resolve Claude transcript from argv, in front of the mapping
- Expose a shard agent's process argv (AgentMonitor.agentArgs)
- Terminal tab polls fast again (was lagging ~18s after the SSE work)
- Don't serve the previous Claude session right after a summon
- Brighten + "agent" badge on backlog tasks an agent touched
- "+ item" opens the editor — add title + description in one step
- Backlog section header rename + delete via context menu
- Backlog section rename + delete plumbing
- Backlog section rename + delete routes
- Delete a section header on desktop (tasks survive)
- "+ section" no longer discards its draft instantly (desktop)
- /send writes Enter twice so a busy TUI doesn't drop it
- Mobile sticky "+ item / + section" add bar
- Desktop sticky "+ item / + section" add bar
- Bridge POST /backlog/section route
- CrystlKit empty-section path (addBacklogSection)
- Inline "+ section" affordance + click-to-rename headers
- BacklogStore.renameSection(at:to:)
- "+ section" button on the drawer instead of typing ##
- Create sections from the desktop drawer (## syntax)
- Tap a backlog task to edit its title + description
- Backlog tab to parity — multi-line detail, 3-state cycle, section picker
- Keyboard no longer covers the backlog add-task field
- Fall back to newest session when Claude's mapped one is a phantom
- Pull-to-refresh re-dials the connection, not just re-fetches
- Backlog as a 3rd tab — content API + live editable list
- Pin hookless agent sessions per shard so shared-cwd shards don't collide
- Up-front Guild affordance — disable mutating controls when !canMutate
- Push agent_status_changed over SSE; fold status into screen/transcript
2.59.0
- Group sidebar nav under section headers
- Agent-change badge + longer flash
- Settings on/off + auto-open on new items
- Crystl backlog open/close/toggle
- Flash on detail edits, indent grip, align open count
- [~] in-progress task state + change-flash
- Retry transient relay failures with backoff
- Clarify crystl docs id-vs-search header comment
- Match window background, side/down carrots, drag-to-reorder
- Crystl-aware agents — crystl docs + crystl report
- Crystl facet — manage facet inserts + bar slots
2.58.0
- Create CLAUDE.md + AGENTS.md when a project has no agent doc
- Tell agents about the backlog + history; broaden agent coverage
- Editable per-gem backlog in a right-edge slide-out drawer
- Run command inserts via Claude bash mode (! prefix)
- Tag inserts as cmd or prmt, show pill in bar dropdown
- Re-dial the tunnel on system wake and network changes
- Add heartbeat ping/pong to detect dead tunnels
- Don't let a transient hello_err kill the tunnel forever
2.57.0
- Lead the heroes column with a Hero System / hero stats key entry
- Honor local heroes' explicit
heroname with collision handling - Local-heroes picker + guardrail tagging in setup panel (Phase 2)
- Project-local guardrail heroes from .crystl/heroes/
- Per-gem auto-approve picker writes the dir the bridge reads
2.56.0
- White labels for Codex plugin/skill rows (were black)
- Gap between troubleshooting blurb and the copy button
- Tighten captions under the field + button on Remote page
- Drop redundant toggle blurb; 'your Mac's bridge'
- Restructure Remote page — neutral lead, troubleshooting section, help icon placement
- Lead the Remote page with its use case
- Clearer remote-install button + copied flash
- Dedicated Remote page; move SSH out of Claude
- Resume uses the hero's configured agent, not hardcoded claude
- Keep quest verbs on PATH when an agent session resumes
- Clearer dropdown affordance on facet pills
2.55.0
- Isolated shards are now hard-blocked from editing files outside their own worktree — an agent in an isolated shard can no longer accidentally modify the main checkout
- More reliable hooks: approval prompts and side-quest messages now authenticate correctly over the local unix socket (no more silent 403s)
2.54.0
- Include bridge port on the unix-socket message path
- Send bearer token on the unix-socket hook path
- Hero editor model is free-text for every agent, not a Claude-only dropdown
- Quest open panel shows each hero's agent + an edit pencil; drop 'Requires Claude Code'
- Codex turn metrics — parse rollout JSONL for the turns panel
- Turns panel recognizes Fable (1M) and stops mislabeling unknown models as Sonnet
2.53.0
- Never symlink tracked config files into worktrees
- One agent-badge convention across all agents in panel headlines
- Badge non-Claude agents in panel headlines next to the shard name
- Summon keeps hero-editor agent choice over party-blob default
- Agent-aware resume gate + quest fallbacks
- Quest launch path resolves the hero's agent via AgentLaunchSpec
- Agent picker in quest hero editor
- Per-hero agent field on QuestRole + questAgents persistence
- AgentLaunchSpec — per-agent quest launch table keyed by AgentKind
- Codex hook adapter — approval panels + notifications via codex hooks
- Thread agent identity through bridge + panel headlines
- Add optional agent identity field to PendingRequest + HookNotification
- Antigravity CLI transcript backend — SQLite + protobuf walk
- Detect Google Antigravity CLI (agy)
- Codex/gemini session view + waiting-prompt detection
- Session view is the default for every shard
- Task cancellation is benign, not 'Network error: cancelled'
- Line-drawn Lucide tab icons for approvals + questions
- Welcome screen fits whole — auto content-width fit in session embed
- Flip the session-store split — Crystl takes the new filename
- Identity-split Stone vs Crystl session mappings
- Splash glow stays on the track, ping-pongs instead of snapping
- Splash progress glow in brand icy blue (accent), not peach
- SessionStart hook remaps shard→session immediately
- Session view lands at the bottom, capped to the last 200 rows
- Persistent CI signing identity via repo secrets
- Archive with the cloud Distribution cert, not per-run dev certs
- Session view shows live terminal until the conversation starts
- Agent-working pulse on gems page
- Auto-trust pre-existing project MCP servers on gem open
- Detect agent stalled on hook-less TUI prompts, notify + push
- Splash progress — slow blush glow instead of orange dot
- Reset relay route memory on foreground
- Pair-device relay toggle + AppDelegate RelayClient wiring
- RelayClient — WS tunnel, loopback replay, reconnect
- MacId + macSecret identity provisioning
- Swift frame codec for the relay wire contract
- Persist relay endpoint with the pairing
- LAN→relay per-request fallback with session route memory
- Pairing payload v2 — relay + mac_id
- Route-aware endpoint requests
- Tap-to-talk mic button in the send bar
- Branded launch splash — glowing crystal, serif wordmark, progress line
- Terminal pinch-zoom + fit double-tap; agent-less shards open on terminal
2.52.0
- Report-bug link in the Help menu
- Match the open-button shine to the quest button
- Loop the open-button shine until the user moves on
- Shimmer the open button to cue a selected folder
2.51.2
- Treat checksum-less party.json as managed, not frozen
2.51.1
- Restore DMs channel list opacity so it renders when shown
2.51.0
- Fade gem rows at scroll edges instead of a shadow overlay
- Keep AskUserQuestion panels until answered
- Glow halo on the unconfigured folder icon
- Recursive folder search, path typing, and open button
2.50.0
- Recolor letter-icon preview when the color changes
- Make the PROJECT DIRECTORY field typeable
- Stop gated-quest warning from overlapping the requires note
- Quest panel reads party roster from resolver
- Warn when a hand-edited party.json is undecodable
- Never regenerate a hand-edited party.json
- Resolve party roster from user-owned party.json
- Decode v2 party.json into QuestParty
- Managed party.json writer + ownership checksum
- Load saved hero stats on editor reopen
- Strip OSC 7 file:// URI from session cwd
2.49.0
- API transcript handler uses per-agent TranscriptSource
- Drive the navigator panel through TranscriptSource
- RemoteFileAccess SSH backend for transcript sources
- Gemini session resolution (registry + legacy hash)
- Gemini chat parser (user/gemini → events)
- Recognize Google Gemini CLI as an AgentKind
- Codex session resolution by session_meta cwd
- Codex rollout parser (response_item → events)
- TranscriptSource protocol + factory + ClaudeTranscriptSource
- Add TranscriptFileAccess protocol + LocalFileAccess
- Auto-publish appcast to crystl-web + deploy
2.48.0
- Default to sidebar mode + redesigned two-row header
- Empty/remote rail states, remove dead picker/scrollback code
- Search field + results across the gem's sessions
- Auto-open the active shard's session
- Highlight the rail moment matching scroll position
- Moment↔scroll index and jump-to-moment in the right pane
- Rail moments state with back navigation
- Rail session-list state (replaces scrollback list)
- Clamp the panel on-screen so the larger 660x520 panel stays visible
- Add background gem-wide search driver
- Add per-session unified search (conversation + tools)
- Add moment extraction for the navigator rail
- Hide picker rule on Scrollback, picker tooltips, row hover
- Taller panel, top-align scrollback, clickable rows
- Stop main-thread freeze when opening the history panel
- Validate transcript sessionId to block path traversal
- Empty-states (remote/Codex), picker visibility, polish
- Add Conversation + Tools transcript tabs with session picker
- Convert HistoryPanel to tabbed shell with Scrollback tab + clear control
- Append session-log record on each save
- Add append-only claude-session-log for shard tagging
- Add SessionHistory.clearOlderThan(days:)
- Add SessionHistory.clearAll for scrollback cleanup
- Add crystl history CLI command
- Fetch remote transcripts over SSH for the transcript route
- Serve GET /gems/:id/shards/:sid/transcript (local)
- Add TranscriptRow/TranscriptResponse wire types
- Load + list transcripts from a bucket dir
- Parse flat JSONL transcript with tool pairing
- Derive per-tool summary one-liners
- Add transcript bucket-path encoding
- Add TranscriptEvent model for Claude transcript parsing
2.47.2
- Log the two silent /hook drop points (401 + external-session filter)
2.47.1
- Log when a notification is dropped by the per-type enabled gate
2.47.0
- Tolerate create-dmg AppleScript styling failure
- Target the bridge that spawned the shard, not the newest token file
- Make crystl approve/deny report whether a request resolved
- Detect uncommitted worktree work instead of silent nothingToMerge
- Make smart auto-approve in-scope work (F3)
2.46.1
- Stop bar at sidebar divider + fade overflow edges
2.46.0
- Insist workers report DONE/BLOCKED as a required final action
- Gate control commands behind Guild (read-free, control-gated)
- Suppress approval/notification panels for orchestrator-managed workers
- Decode crystl pending without snake_case conversion
- Pre-trust the canonical (symlink-resolved) worktree path
- /fanout orchestration command + auto-provisioning on launch
- Pre-trust worker worktree so it runs unattended
- Reject malformed quest_msg without polluting the channel
- Clarify context-window step copy
- Add project optimizer step opening the ⋮ menu
- Retarget gem settings step at the ⋮ menu
- Pin CRYSTL_QUEST_ROOT so --approval+--quest workers write to gem root
- Reject remote isolated shards instead of mis-merging locally
- --quest installs fanout comms channel at shard spawn
- Crystl merge command for isolated shards
- --approval at shard spawn
- Scope log dir by AppIdentity.name so Stone stops writing into Crystl's
2.45.0
- Add optimize item to gem ⋮ menu
- Optimizer header shows large gem name + icon
2.44.0
- Mirror gem ⋮ menu + hover close on sidebar gem rows
- Gem-tab ⋮ menu (history/settings/approval); remove GemToolbar pill
- add TabControlGeometry helper for gem-tab hover controls
2.43.0
- Address pre-ship review (resize-safe disable, hover band-gate, observer cleanup)
- Settings icon uses a native tooltip instead of a clipped hover label
- Move settings icon inward so its hover label isn't clipped
- refine sidebar: align SHARDS with shard text, label footer + new gem
- Don't reveal the tab bar over the sidebar after leaving settings
- refine settings: more space below APPEARANCE/BEHAVIOR headers
- refine settings: more header space, independent columns, squarer diagrams
- Two-column general settings + sidebar-mode illustration
- Larger gem sidebar rows (14pt names, 18px icons)
- refine sidebar: align SHARDS with GEMS, wider bar, larger gems, more gutter
- Stacked two-row shards bar in sidebar mode
- Optional stacked two-row layout for SessionBarView
- refine sidebar layout: terminal gutter + shards bar aligned with gems header
- refine gem sidebar: drop redundant open-folder button, improve spacing
- Add sidebar-mode settings toggle
- Sync gem sidebar from updateTabBar
- Wire gem sidebar into window layout with window growth
- GemSidebarView vertical scrollable gem list
- GemRowView for sidebar gem list
- Sidebar-mode window geometry helper
2.42.6
- Submit injected paste under kitty mode without report-all-keys
2.42.5
- The context button shows the live turns-left count again. The recent rework had reduced it to a plain "turns" label; the "~N turns left" estimate is back on the button (auto-sized so large counts don't clip) and updates each turn.
2.42.4
- Drag-to-select now auto-scrolls. Pull the cursor to the top or bottom edge while selecting and the terminal scrolls so you can select more than a screenful. Holding at the edge keeps scrolling, releasing stops it.
- Fixed scrollback getting stuck in some sessions. When an app enabled mouse reporting it was eating the scroll wheel even in the normal buffer, so you couldn't scroll back through output. The wheel is now only handed to full-screen apps (tmux/vim); otherwise it scrolls your history.
- "Agent finished" notifications show by default. Subagent completions are now treated the same as the main agent finishing, instead of being off until you opted in.
- Fixed notifications overlapping the Crystal Rail. After dragging the rail from a side to the top, floating notifications now re-align below it without needing to be dismissed first.
2.42.3
- Notifications now come through for Claude running over SSH. Idle prompts and questions from a remote session were being silently dropped, and only locally-run agents surfaced panels. Remote sessions now raise the same idle, question, and subagent notifications as local ones, while non-crystl agents in other local terminals stay filtered out.
2.42.2
- Auto-approve now follows the project you're working in. When a shard worked inside a project nested under a broader gem (e.g. a home-folder gem), the gem's approval mode could shadow the project's, so a project set to "all" still prompted for every tool. Approval mode is now resolved from the working directory first, and the rail's approval picker reflects the mode that's actually in effect.
2.42.1
- Formations keep your gem names again. Renaming a gem in Gem Settings now sticks when you save it into a formation. Previously the gem came back with its folder name instead of the name you gave it. (Formations saved before this fix need one re-save to pick the names back up.)
2.42.0
- Context "turns left" estimate fixed for large-window models. It now reads the real context window for newer models (e.g. Opus 4.8's 1M window) instead of assuming 200K, so the countdown is realistic instead of hitting 0 about five times too early.
- The context button is always available. It appears as soon as an agent is running (labeled "turns" with a subtle button border) and opens even before the first turn lands so you can still see the fixed-cost breakdown.
- Redesigned the context panel header. A larger "token usage · gem · shard" title with the gem's icon inline, and the model and window size on the line below.
- The per-turn cost list scrolls. Setups with lots of plugins and skills no longer push the panel off-screen; the column headers and total stay pinned.
- Plugin and skill rows are clearly clickable. They highlight on hover and pop their menu on a click anywhere along the row.
2.41.0
- Subagents are identified in panels. Each gets a stable dwarf name, a pickaxe glyph, and a "sub · <role>" line on both approval cards and notifications, so parallel subagent activity is easy to tell apart.
- Notifications stack. A deck-style peek instead of being dropped once more than four arrive.
- Redesigned the Gem Settings / New Gem panel into Identity and Agents tabs, never runs off-screen, with a ROOT FILES drawer and consistent spacing.
- Codex plugins & skills moved to the Codex settings page (they're global, not per-gem); the gem panel now links there.
- New-gem "initialize git" and remote URL moved to the Identity tab.
- Fixed Crystal Rail badge clipping.
2.40.0
- Master ENABLE toggles in Gem Settings. The plugin, skill, and MCP sections each get a top-level enable toggle.
- Fixed a stray "Butt" label leaking onto icon-only buttons (the NSButton default title).
- Update-check ping includes license plan (free / pro) so anonymous free devices are labeled.
2.39.0
- Plugin recommendation catalog grew from 5 to 23. The optimizer now recognizes 18 more Claude Code plugins when their detection signal fires, covering databases / backends (Firebase, MongoDB, Neon, PlanetScale, Convex, Appwrite), auth (Auth0, WorkOS), frontend / framework (Expo, Apollo GraphQL, Sanity, Shopify, Mintlify), email / messaging (Resend, Twilio), observability (PostHog, Datadog), and Netlify for deploys. Detection is the same shape as before: manifest file (
firebase.json,netlify.toml,convex.json, etc.) or apackage.jsondep prefix (@neondatabase/,mongoose,@auth0/, etc.). When a match fires and the plugin isn't installed, the optimizer's setup section shows+ install <plugin>; one click types/plugin install <id>into the gem's selected shard.
2.38.0
- Optimizer recommends Claude Code plugins. Open the optimizer in a Vercel / Supabase / Cloudflare / Sentry / Stripe project (detected via
vercel.json,wrangler.toml,@vercel/*/@supabase/*/@sentry/*/stripedeps, etc.) and the setup section shows a one-click+ install <plugin>row. Clicking it types/plugin install <id>into the gem's selected shard, then watches~/.claude/plugins/installed_plugins.jsonfor 30s and auto-rescans so the gap disappears once install completes. If the plugin is already installed but disabled for that gem (via the context-load panel right-click), you get+ re-enable <plugin>instead, one click strips the disable entry from.claude/settings.json. The catalog ships asResources/plugin-recommendations.jsonso adding new plugins is a JSON commit, no Swift edit. - Astro project detection. Projects with an
astro.config.mjs(or.ts/.js) now get an "Astro project" profile in the optimizer instead of falling back to generic Node.js with linter / logging nudges. - Optimizer setup checks are scoped clearly. The setup-tab rows now read "No X in this directory" so it's obvious the optimizer grades the gem's onboarding, not your global Claude config. The misnamed "Claude skills" check (which was actually testing
.claude/commands/) is now correctly labeled "slash commands," and a real.claude/skills/check was added alongside it. - Gem Settings: Claude/Codex label parity. Claude accordion sections now read "INCLUDE CLAUDE SKILLS?" / "INCLUDE CLAUDE PLUGINS?" matching the Codex labels, less ambiguous in mixed-agent gems.
- Context-load panel refreshes in place. Disabling or re-enabling a plugin/skill from the turns panel now updates the strikethrough row and totals immediately. Previously you had to close and reopen the panel to see the change.
2.37.0
- crystl CLI. A
crystlcommand-line tool ships inside the app bundle. Install via Help → install command line tool… (one admin prompt, symlinks/usr/local/bin/crystl) or from Settings → General → Command Line Tool. From any terminal:crystl gems,crystl shards --gem <name>,crystl screen,crystl send,crystl pending,crystl approve/deny. Full reference at crystl.dev/docs/cli. - New CLI commands.
crystl shard create --gem <name> [--isolated] [-c "<cmd>"]spawns a sibling shard so orchestrator agents can fan out parallel work.crystl eventsstreams the bridge's SSE event log as JSON lines, pipe-friendly with jq.crystl wait pendingblocks until a permission request appears, built on SSE, no polling. - Agents discover the CLI automatically. Each gem's
CLAUDE.mdandAGENTS.mdget a short marker-bracketedCrystl CLIsection upserted on open, so any agent inside a crystl shard knows it can coordinate with sibling shards. Idempotent (re-runs upsert in place), only touches files that already exist, gated by a General settings toggle. - CLI fixes from first round of testing.
crystl opennow reportsPath does not exist/Path is not a directoryinstead of a generic failure.crystl closeaccepts gem name (was UUID-only despite the help text).crystl screentrims trailing NULs sogrepstops silently exiting 1 on the output.crystl sendappends\rby default so commands submit in shells and TUIs (Claude Code, vim); use--no-enterto opt out.
2.36.37
- Stale panels auto-dismiss. Ask-user, approval, and notification cards now disappear when the agent moves on, rather than sitting orphaned until you click. New rules cover
SessionEnd(drops everything pending for that session),PostToolUsematching an open approval (the tool already ran), a shard restarting its agent (different Claudesession_idfor the same shard UUID), and the big one, any follow-up hook for a session with an open question proves the agent moved past it without your panel's answer. The 5-minute hard timeout stays as a backstop. - Notification cards finally auto-dismiss. The dismiss timer slot existed but was never populated, so informational cards stacked indefinitely. Now they fade after 8 seconds by default, question cards still persist until you click Answer or Dismiss. Tunable via the
notificationAutoDismissSecondsUserDefault (set to 0 to disable). - CrystalRail polish. The tile strip now scrolls when it exceeds 80% of the screen instead of overflowing off the edge. Fixed the top of the rail disappearing after closing a gem from the middle of the strip.
2.36.36
- General settings polish. The
allow notifications from other terminalstoggle now carries a caption explaining what it does ("allows crystl rail to display agent notifications from other terminals"), and the toggle label gains a leading verb so the action is unambiguous. Fixes layout overlap in Settings → General: theSESSION RESTOREsection header no longer collides with therestore last session on startuptoggle pill, and the GPU rendering / external-notifications subcopy hints no longer crowd the toggle below them.
2.36.35
- Notification isolation for other terminals. Claude invocations running outside crystl (Terminal.app, iTerm, Warp, Ghostty, tmux, a cron job, anything) no longer surface in crystl's rail by default. New
notifications from other terminalstoggle in Settings → General flips the behavior back on per machine. SSH-tunneled and Tailscale/LAN sessions are unaffected and keep working regardless of the toggle, since remote Claude can't supply crystl's session env vars. Also fixes a clobbering bug when two builds were installed side by side: the shared~/.claude/crystl-hook.shwould route hooks to whichever installed last; each build's spawned shells now stamp the bridge port, socket, and token-file path into env so the script reaches the right bridge.
2.36.34
- Tab and context-bar polish. Long gem-tab titles no longer crash into the close
×: the glyph is 10% smaller and sits 8px from the tab's right edge (was 12), with a real 6px gap before the text clip. The~N turns leftindicator in the status bar now brightens fromalpha 0.5to1.0on hover so its clickability is obvious instead of reading as a static label. The welcome tour adds a 13th step explaining the context-window indicator and what it points to. The real button only appears after three turns, so the tour materialises a mock at the same position during the step.
2.36.33
- See and shrink the plugin / skill context load per gem. The
~N turns leftpanel now itemizes every installed Claude Code plugin and user-level skill alongside CLAUDE.md / AGENTS.md / .mcp.json. Each row shows lines, tokens, and % of window. Left-click any plugin or skill row to disable it for the active gem, for all gems, or (for Codex) globally; disabled rows render grayed with a strikethrough and a one-click re-enable action. Claude disables write.claude/settings.jsonand inject/reload-pluginsinto the active shard so changes apply mid-session; Codex disables write~/.codex/config.tomlwith a "restart codex to apply" note since Codex has no per-project scope. Plugin and skill checkboxes also appear in the New Gem and Gem Settings panel as collapsibleINCLUDE PLUGINS?/INCLUDE SKILLS?sections, plusINCLUDE CODEX PLUGINS? (global, restart codex)for Codex. New gems with a recognized stack (Vercel, Shopify, Cloudflare, Supabase, Sentry, Swift) get an opt-in dialog proposing which plugins to enable / disable. Bug fix: the turns-remaining button now appears reliably after three turns even when agent detection is mid-cycle.
2.36.32
- Welcome tour: 12 steps, follows the window, replays from Help. The first-run tour now covers isolated shards, quest / side quest, the screenshots bar (it opens automatically during its step), and ends on a centered farewell with a one-click join slack CTA. Bubbles attach as child windows so they track parent moves through drag, fullscreen, and screen-to-screen jumps. Chevrons now land on the actual control they describe (the
+, the isolation dropdown, the quest button, the facet pills) instead of the wide bar’s midpoint. Crystal rail step mentions drag-to-dock on the left, right, or top edge. App settings step calls out the trio that actually matters: API keys, MCP servers, and CLAUDE.md / AGENTS.md editing. New Help → show welcome tour menu item replays it on demand.
2.36.31
- Notifications: timestamps on the headline. Notification cards now show when they were created,
diamond notification - just nowfor fresh cards, switching to absolute time (diamond notification - 7:35pm) at the 60-second mark via a one-shot per-panel timer. Lets you tell at a glance whether a long-lived notification is current or stale instead of having to dismiss-and-wait-for-the-next-one. - Shards: stop nagging on every shared shard in home-rooted gems. The home-directory warning was firing on every shared-shard creation, not just isolated attempts, far too noisy for users who intentionally have a home gem. Isolated shards in home still refuse loudly (they’d scatter worktrees under
~/.crystl/), but shared shards now create silently.
2.36.30
- Invisible-text-on-glass: defensive widening on PTY data. The known “text gone, drag-select makes it appear and stay” signature recurred. Classic renderer-side bug where SwiftTerm’s per-row dirty marking missed a buffer update under heavy Claude Code output, so the renderer’s row cache kept serving stale bytes. Selection works because
selectionChangedwidensmetalDirtyRangeto the full visible range. Mirrored that widening into the existingdataReceivedkick via a newcrystlMarkVisibleDirty()patched onto SwiftTerm. Every PTY chunk now guarantees the next Metal draw rebuilds visible rows from current buffer bytes. Belt-and-suspenders on top of themetalDirtyRangeunion patch: that one fixes writer-vs-writer clobbering; this one defends against writers that miss rows entirely.
2.36.29
- Syntax-highlighted type tokens readable on glass. Claude Code’s Monokai Extended theme emits lone
\e[2m...\e[22mfor both ghost-text hints AND code-block type tokens (UInt8, ArraySlice, etc). The SGR rewriter was injecting gray-120 as the lone-dim substitute, visible enough for input-bar placeholders, but invisible-dark on glass for code-block types that use the same bytes. Bumped to gray-180 so both render visible-but-distinctly-dim relative to typed input (which lifts to white). - Renderer fg luminance floor catches tinted greys. The SwiftTerm-side floor only lifted pure greys (channel diff < 30) to white, lightly-tinted muted syntax-theme colors at diff 40 to 70 slipped past and rendered invisibly. Widened to diff < 80; saturated theme accents (diff > 100) still pass through unchanged.
- Tab bar: clear gap between × close and + add buttons. With
tabSpacing=2, the “+” was rendering essentially flush against the trailing tab’s “×”. Bumped the “+” offset so there’s a 10px clear gap. - Session bar: inset quest/isolation buttons 28px from right edge. The right-edge inset was 14px, crowding the close-window chrome. Centralised the margin in a constant and bumped to 28.
- Crystal Rail: settings diamond back inside the glass capsule. The May 6 wrapper restructure (which correctly stopped alpha cascading from dimming tile icons) inadvertently floated the settings diamond above the rail with a visible gap. Returned just the settings icon to glass, tiles still sit outside glass so their alpha doesn’t cascade.
2.36.28
- Alpha floor: three small text/icon sites lifted from 0.4 → 0.5. crystl’s text alpha floor is “no text in the app should be less than white alpha 0.5”. Three sites still violated it: the QuestPanel subtitle (the · separator and gem name), the DirectoryPicker file icon color, and the TemplateLibraryPanel label badge. Visual polish only, minor brightening of subtle UI affordances against the dark glass background.
2.36.27
- Quest prompt restructured: comms rule first, explicit negative, concrete example. Real-quest feedback from a ranger shard that replied to the user with plain text instead of going through
quest_msg. Asked the shard what would have made the rule stick, then applied its three suggestions verbatim: (1) moved the comms rule to the top (was buried mid-block after recon instructions); (2) added an explicit negative (was “use quest_msg”, now “NEVER respond to the user with plain text” with the consequence (“plain-text replies are invisible to the user”); (3) added a 4-step concrete example of what a first response should look like, because examples beat descriptions when there are 20 competing rules. Also broke the wall-of-text into section headers so the model can scan structure rather than parsing one long paragraph.
2.36.26
- “No conversation found” on startup, actually fixed this time. The v2.36.24 check rejected resumes when Claude Code had deleted the conversation file entirely, but missed the case where the file exists in a *different* cwd’s project bucket. That’s what was happening on most affected sessions: a shard was originally
cd’d into one directory when its Claude session was saved (say~/Nextcloud/promptreviews), then the gem’s resolved cwd changed (back to~). The conversation file lives in the original cwd’s bucket butclaude --resume <id>from the new cwd only looks in the new cwd’s bucket. crystl now encodes the path the same way Claude Code does (each/→-) and checks the one specific bucket the autorun script will actually run from. Mismatch → no autorun written → clean prompt.
2.36.25
- Quest messages now actually reach the agents when multiple gems share a path prefix.
bestProject(for:)had a longest-wins tiebreak that picked the wrong gem when two gems both overlapped the query cwd, specifically when one gem was AT the cwd and another was nested deeper. Quest delivery then iterated the deeper gem’s sessions, found no quest shards (the quest was in the shallower gem), and silently skipped the message. Symptom: chat panel UI showed your typed message, but agents never received it. Fix: prefer exact match first, then deepest-cwd-contained, then SHALLOWEST-gem-inside-cwd so a gem AT the cwd wins. Also tightens prefix comparisons to require the path separator so/Users/chrisdoesn’t spuriously match/Users/chrissomething.
2.36.24
- No more “No conversation found with session ID” error on startup. When crystl restores a shard via session resurrection, it writes
.crystl/autorun-<shard>.shcontainingclaude --resume <id>, which the shell sources at prompt start. If Claude Code has deleted the conversation file in the meantime (rotation, cleanup, sync drift), the resume command printed a red error to the terminal on every startup until the user did something. Now crystl checks that the conversation file actually exists at~/.claude/projects/*/<id>.jsonlbefore writing the autorun, no file means no autorun, which means a clean prompt. The saved session ID is left in.crystl/claude-sessions.jsonso a later restoration (backup, sync) will resume cleanly on the next startup.
2.36.23
- Fresh “begin quest” summon now actually opens the chat panel. Same class of bug as the v2.36.19 resume fix, and previously masked the same way. The fresh-summon path had a timing race:
injectQuestWrapper(which sethasQuestContext = true) was scheduled for +0.8s after shard creation, but the chat-panel open ran at +0.2s. The chat-open path checkshasQuestContextto decide whether to construct the panel and silently no-opped because the wrapper hadn’t fired yet. Fix: sethasQuestContextsynchronously when the shard is created. The flag represents intent (“this is a quest shard”), not “the wrapper scripts are installed.” Reproducible on a 1-hero party; party size didn’t affect the race. - QuestReportGenerator: empty-string check instead of nil-coalesce. Compile-time warning cleanup,
session.detectedModelIdis non-optional so?? “unknown”was dead code. Switched to.isEmptywhich correctly expresses the “fall back when no model detected” intent.
2.36.22
- Shard label readability: luminance floor + dropped onyx. Some shard pills had crystal colors dark enough to be hard to read on the glass background: lapis, ruby, garnet, cobalt, and tanzanite were the worst offenders. New
NSColor.shardReadable()helper applies a perceived-luminance floor (BT.709 Y ≥ 0.55) at the draw site, multiplicatively scaling channels to preserve hue while lifting darks. Onyx removed from the crystal rotation: it was grey-dark by design and just converged to a generic medium grey after the floor. New auto-allocate order: diamond → opal → jade → lapis → topaz → pearl → amber → quartz → ruby → garnet → emerald → cobalt → peridot → zircon → amethyst → tanzanite → carnelian → turquoise → morganite (19 names). Existingcrystl/onyxworktree branches on disk still appear in the Isolation dropdown as orphans and can be reopened.
2.36.21
- PTY hot-path: cached UserDefaults reads + MTKView subview reference.
dataReceivedfires per chunk of bytes from the agent, 50 to 200×/sec under Claude output. The two diagnostic kill switches (crystlDisableSGRRewriter,crystlDebugBytes) now read once at first reference instead of per chunk, and the MTKView subview is resolved lazily once and cached instead of walked + class-name-substring-matched per chunk. Both flags now require an app restart to take effect. - Pulse animations: shared 20Hz clock, cached questEnabled, alpha-at-draw. Three independent per-view
Timer.scheduledTimers consolidated into one sharedAgentPulseClock, previously 11+ independent timers under a multi-gem multi-shard quest. Bonus: all pulsing surfaces now lock-step instead of drifting in/out. CachedquestEnabledinSessionBarView. Fixed a silent bug where the pulse alpha on shard-bar icons was being dropped before reaching the screen (visible behavior change: thegit-branchandswordsicons now actually pulse / hover-brighten). - UI hot path: async git scans, memoized window title, async file gather. The local
GitWorktree.orphanedBranchescall inrefreshOrphanedWorktreesmoved off main (panel-open path kept synchronous so the badge count is correct on first frame).ChamberSetupPanel’s orphan scan cached so typing in the path field doesn’t re-rungit for-each-refper keystroke.uploadV2StateToRemoteHosts’s file-gather phase moved into the async block.updateWindowTitle()memoized to early-bail on no-op title rebuilds. - Lifecycle cleanups.
DirectoryPicker’s NotificationCenter observer now removed before re-assignment and in deinit. Previously a re-shown picker leaked the prior observer which then fired on every settings keypress (visible as settings UI sluggishness).AppDelegate’s Enter-key NSEvent monitor token now stored + removed at app termination. ThreeAppDelegate+Formationsusleeppolling loops replaced with chainedDispatchQueue.asyncAfter, which no longer pins worker threads at startup with big formations.
2.36.20
- Subprocess deadlock when git or ssh output exceeds 64 KB.
GitWorktree.run,RemoteSession.run, andQuestReportGenerator.collectFilesChangedall calledreadDataToEndOfFile()AFTERwaitUntilExit(). macOS pipe buffers cap at ~64 KB, once a subprocess emitted more than that, the child blocked writing to the pipe while the parent blocked waiting for the child to exit. Classic deadlock; crystl would hang and the parent’s file descriptors leaked until force-quit. Triggered bygit diff --stat HEADon a big-changelist repo,git logon long history, ssh command output past 64 KB. Fixed all three sites with concurrent pipe drains viaDispatchGroupbeforewaitUntilExit. - Title hook: dropped the process-tree scan and heavy state writes. Companion fix to v2.36.18’s orphan-scan-off-title work. Every OSC title update from the agent was still triggering
agentMonitor?.scanNow()(a fullsysctl(KERN_PROC_ALL)walk) andupdateAgentUI()’s file I/O (status.json, per-shard quest writers, healer alert scan, remote SSH upload). None of that data changes because of a title string, it changes on bridge hooks. SplitupdateAgentUIinto a cheap UI-sync version and a newrefreshAgentState()for the heavy work; bridge hook handlers now call the heavy version explicitly while the title hot path stays cheap.
2.36.19
- Quest “resume” button now actually opens the chat and delivers messages to agents. After a crystl restart, clicking the green resume (N shards) button in the quest setup panel would re-attach the worktrees but the chat panel never appeared. Once the chat was opened by other means and a message was typed, the message appeared in the panel UI but never reached the agent terminals. Root cause:
resummonShardscalledopenExistingWorktree(which creates plain isolated shards) but never installed the quest wrapper, so the resumed shards lackedhasQuestContext, which the chat-open path and the message-delivery path both gate on. Wrapper installation now runs on resume at the same cadence as on initial party summon.
2.36.18
- Typing lag during Claude activity fixed. The terminal-title hook was spawning 3 to 5
gitsubprocesses on every OSC title update from the agent. Claude Code emits title updates many times per second while “thinking”, so the main thread was starved of keyboard input the entire time the git scan ran.setTerminalTitleclosure dropped from 43.5% to 3.1% of main-thread time after the fix; the cascade also cutCA::Transaction::commitfrom 61.9% to 45.6% and view backing-layer display from 49.7% to 27.6% (fewer spurious git scans = fewer cascading UI invalidations). Orphan-branch scan now happens only on events that can actually change the orphan set: gem switch, shard create/close/merge, and right before the isolation dropdown opens. - Welcome banner now dismisses on your next command. First-launch banner wipes itself when you run anything in the shell, no more lingering banner under your prompt. Hooks into the shell’s preexec via OSC 7770.
- Fixed a regression where holding the delete key could leave stale glyphs on screen. The forced-repaint kick on PTY data had been removed in a recent change based on an A/B that showed “no regression”, but the test was conducted while another bug was incidentally refreshing the terminal layer as a side effect. Once that bug was fixed (above), the latent invisible-text regression surfaced. Kick restored.
2.36.17
- Cwd-drift warnings when a shard wanders outside its gem. A user who
cd’s from inside gem A into project B’s directory sees their shell happily working in B, but crystl-level features (isolated shards, quest, project settings, MCP) stay anchored to gem A’s directory. Silently. Same class of foot-gun as the home-rooted-gem issue earlier this week. Two complementary nudges: a one-time terminal hint fires when drift is first detected (yellow ⚠ banner explaining the situation and recommending “+” to make a new gem for the wandered-into folder, gated so it fires at most once per user), and a persistent status-bar indicator shows a yellow ⚠ + yellow-tinted cwd text on the project label whenever the active shard is outside the gem’s project tree (reverts to plain text the moment the shard cd’s back inside). Remote shards skip both checks; the auto-home gem also skips.
2.36.16
- Welcome banner now actually appears for users with restored sessions. In v2.36.15 the banner was wired into
addProject, which fires once per restored gem during session restoration. The flag-set on the first call locked subsequent calls out, AND the banner was being fed into the first restored gem’s shard (hidden behind the other tabs, since restoration ends with the LAST gem selected). Moved the trigger into a post-restoration hook at +2.5s after launch. It reads the currently-selected session and feeds the banner there, so it lands in the tab the user is actually looking at on first launch of any new version.
2.36.15
- Onboarding nudges for the gem/shard mental model. crystl’s default first-launch state is an “unconfigured” gem at
$HOMEwith a single diamond shard. Previously nothing told users this was special, so they treated crystl like any other terminal and missed the central concept. Three small additions: (1) a one-time coloured welcome banner is fed into the first shard’s output explaining gems vs shards and pointing at the status-bar folder icon; (2) the folder icon next to the project label pulses gently while the gem is unconfigured, so the eye catches it (stops on click or when the gem becomes configured); (3) tooltips on both “+” buttons,new gem (project folder)on the top row,new shard (terminal session in this gem)on the shard row.
2.36.14
- Gem title no longer follows the active shard’s cwd.
hostCurrentDirectoryUpdate(which fires on every OSC 7 the shell emits, typically once per prompt) was rewritingproject.titleto the basename of the shard’s cwd whenever the gem didn’t have a custom name. That turned the gem identifier into a breadcrumb of “wherever I lastcd’d to”, so a shard wandering into~or auto-cd-ing into a worktree path would silently relabel the entire gem. The gem title is now a stable property set at init time and only changes on explicit user edit. Side effects (window subtitle, session cwd tracking, tab observers) still update on OSC 7 as before.
2.36.13
- Isolated shards refused when the gem is rooted at
$HOME. Some usersgit inittheir home directory (for dotfile management or otherwise). Creating an isolated shard on a home-rooted gem madeGitWorktree.createcorrectly produce~/.crystl/worktrees/<name>, but that pollutes the home git repo withcrystl/*branches and scatters shard cwds across the user’s entire home tree. Isolated shards on a home-rooted gem now fail fast with an explanatory error pointing the user at creating a gem for their actual project directory. - Loud yellow warning when any new shard is created on a home-rooted gem (isolated or shared). Home is almost always a misconfiguration regardless of shard type, so surface it instead of letting users discover it via downstream weirdness.
2.36.12
- Cursor is now visible whether GPU rendering is on or off. The Metal renderer already had a patch forcing the cursor to stay drawn regardless of Claude’s
\e[?25l(cursor-hide) spam during status-line redraws. The CoreText renderer didn’t,terminal.cursorHidden = truewould remove the caret view from its superview entirely, so users with GPU rendering disabled in General settings were typing into an invisible-cursor box while Claude was running. Mirrored the override into the CoreText path so the caret stays mounted regardless of what the terminal asks for. - GPU rendering toggle now states the restart requirement.
useMetalRendereris read once when a terminal session is initialized, so flipping it on a running shard has no effect, easy to misread as a broken toggle. Added a caption under it.
2.36.11
- Side quest tab no longer shows the PROJECT DIRECTORY picker or the gem-name row. Side quest connects two arbitrary shards across any gems and is directory-agnostic, it doesn’t operate inside a single directory. The picker was a leftover from the quest-tab layout and implied (incorrectly) that side quest was scoped to the launching gem’s directory. Both sections are now suppressed when the side-quest tab is active, and the panel shrinks to match.
2.36.10
- The quest setup panel’s PROJECT DIRECTORY picker now actually controls where the quest runs. Previously the picker accepted edits and looked editable, but for local quests every consumer downstream (shard cwd, isolated worktree base, party.json write, wizard join message, chat panel message reads, file watcher, context analyzer, v2 hook routing) anchored back at the gem’s own directory. So agents launched in the picked dir but the panel kept reading from the gem’s empty
.crystl/quests/, making quest features appear inert. Now a singleeffectiveQuestRootthreads through every read; the picker dir is the authoritative quest location. Persists to the gem’s.crystl/project.jsonso the anchor survives across app restarts. Open quests cd shards into the picked dir; isolated quests put worktrees under the picked dir’s git repo. - The redundant gem-name row in the panel header is gone when there’s nothing custom to show. A gem at
~with no custom name was rendering “chris” above a path field that read “~”, the same identifier twice. Now the row only renders when the gem’s title differs from its directory’s basename (i.e. a custom name was set). The path picker is the single source of truth. release.shnow tags locally and installs to~/Applicationsat the end. Local builds were stamping stale version strings intoInfo.plistbecause they read fromgit describeand the release tag only existed on the remote aftergh release create. Nowrelease.shcreates the tag locally before building, and copies the freshly-signed + notarized app into~/Applications/Crystl.appat the end so the installed version always matches what was just released.
2.36.9
- Quest setup panel header no longer overlaps itself. The gem icon and project name row was rendering inside the setup tab bar’s vertical range, causing the “side quest” tab label to collide with the project name (most visible when the project name was long like
promptreviews-web). Two builders in the panel layout used mismatched y-coordinate conventions (“decrement before placing” vs “place at y, advance after”); the gap step after the tab bar didn’t account for the gem row’s upward visual extent. Added the missing 17px so the row clears the tab bar cleanly. - Side-quest shard picker now shows the shard name on long project entries. The picker drew row text without a truncation paragraph style, so entries like
promptreviews-web / diamondclipped at the column’s right edge, hiding the shard name, which is the part users actually pick by. Switched to middle-truncation so both the project prefix (for context) and the shard suffix (for selection) survive on long entries.
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) A build could ship without the SwiftTerm fg luminance floor patch, falling 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, so white becomes grey-155. The floor patch is now applied on every build. (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.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.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 to 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. - Side-by-side builds no longer share config files: both 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. A second build now uses its own config directory. 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 reliability, 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 reliability: 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: two builds no longer interfere when running simultaneously
2.19.7
- Reliable 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