Resolve race condition by implementing a package-level cache for skill discovery states. Add ~/.agents/skills/ and ~/.claude/skills/ as global skill scan paths.
Each frame the chat list is turned into a string with ANSI color codes
that we then have to parse back into cells before drawing. When the
chat list output is the same as the previous frame, we now reuse the
cells we already produced and skip the parsing step.
Co-Authored-By: Charm Crush <crush@charm.land>
The chat list now remembers what each item rendered last frame and
reuses it when nothing about that item has changed. Once a message
turn is fully done, its rendered output is reused verbatim on every
subsequent frame for as long as it stays unchanged. Resizing the
window, focusing or selecting an item, dragging a selection over it,
toggling a thinking block, and any other state change still triggers
a fresh render. The visible output is identical to before; the work
to produce it is much less.
Co-Authored-By: Charm Crush <crush@charm.land>
When a reasoning block is expanded, show only the most recent few hundred
lines by default with a hint that more lines are hidden, instead of
rendering the entire thing. Clicking again shows the full block.
This keeps the UI responsive when models produce very long reasoning.
Co-Authored-By: Charm Crush <crush@charm.land>
The assistant message type's toggle-expand method returned no value,
so it silently failed to satisfy the expandable interface and the
keyboard expand path skipped assistant thinking blocks. Expansion
only worked via the mouse, which called the concrete method directly.
Fixing the signature exposed a second bug: the mouse path then
toggled twice per click (once inside the item, once via the generic
interface path), netting no change. The item now just reports
whether the click hit the thinking box; the generic path does the
toggle, gated on that flag so clicks elsewhere do nothing.
Adds a runtime regression test plus a compile-time interface
assertion so this can't silently come back.
Co-authored-by: Crush <crush@charm.land>
The theme prep overhaul in 755f6fa made the main markdown renderer and
thinking block markdown renderer heavier, which exasperated a gap in
perf. Basically every token chunk would clear would clear the per-item
render cache and force a re-render.
This update memoizes renderers with markdown and should generally
give us a nice increase in perf compared to what we had before the theme
rendering.
- Display loaded/errored skills in sidebar and landing page
- Use pubsub event to carry skill states directly to UI, avoiding
global mutable state
- Subscribe to skills discovery events via broker, consistent with
MCP/LSP patterns
- Rename State to DiscoveryState for clarity
Fix LSP UI display broken in v0.55.0. The UI was still subscribing
to workspace.LSPEvent after the event type was moved to the app
package, causing LSP status to never update in the UI.
Changes:
- internal/ui/model/ui.go: Subscribe to app.LSPEvent; use app.GetLSPStates()
- internal/ui/model/lsp.go: Use app.LSPClientInfo type for LSPInfo embedding
and sorting (fields are identical to workspace.LSPClientInfo)
Fixescharmbracelet/crush#2560
When Hyper returns a 401, publish a TypeReAuthenticate notification so the
UI opens the OAuth dialog. Also fix coordinator.isUnauthorized to recognize
hyper.ErrUnauthorized for auto-refresh.
💘 Generated with Crush
Assisted-by: Z.ai: GLM 5.1 via Crush <crush@charm.land>
- Add DialogID field to file picker command in commands.go
- Add FilePickerID case handler in openDialog function
- Remove TODO comment and complete implementation