Non-interactive mode improvements + more!
How's it going? We've been busy! The main focus of this release is crush run, aka non-interactive mode, but there are some other gems here as well. For more, read on.
Now with more non-interactivity
Crush is really powerful in scripts, CI/CD, and so on, and we're seeing more and more headless Crush usage. On that note, this release adds some improvements to non-interactive mode.
You can can now specify a model with the --model flag, which allows you to specify a model and provider via a {model} or {provider}/{model} format. For example:
# Model arguments are case sensitive
crush run --model "glm-4.7" # Find the first available configured instance of GLM-4.7
crush run --model "openai/gpt-5.2-codex" # Use GPT-5.2-Codex at OpenAI
crush run --model "synthetic/hf:MiniMaxAI/MiniMax-M2.1" # Multiple slashes are totally fineWondering what models are available? Check out crush models. Works great with grep, too.
Better edits and QoL
Not less important, this release include some bug fixes for the edit tool. Also, the terminal tab title will be set automatically as a small QoL improvement brough by our contributor @mhpenta.
Why are there so many commits?
You… might also have noticed there are a boatload of commits in this release. We're overhauling the UI internals to greatly reduce code complexity and improve performance. To try the new version, set CRUSH_NEW_UI=1, and let us know if you have any feedback, bearing in mind that the new UI is still a work in progress.
See ya!
Charm 💘
Changelog
New!
- 4316ef3: feat(chat): expandable thinking for assistant (@kujtimiihoxha)
- 27fa971: feat(ui): add basic dialog and new UI structure (@aymanbagabas)
- 7d99762: feat(ui): add chat and editor models with keybindings (@aymanbagabas)
- 82bc601: feat(ui): add common utils and refactor chat message items and tools (@aymanbagabas)
- 470e6f6: feat(ui): add initial sidebar component with logo (@aymanbagabas)
- afb5467: feat(ui): add mouse click handling to lazy list items (@aymanbagabas)
- b71baee: feat(ui): add optimized list component with focus navigation (@aymanbagabas)
- 9c00130: feat(ui): add text highlighting support to lazylist (@aymanbagabas)
- ca3e06a: feat(ui): chat: add navigation and keybindings (@aymanbagabas)
- a5c597b: feat(ui): copy chat highlighted content to clipboard (@aymanbagabas)
- 5d2c533: feat(ui): dialog: add file picker dialog with image preview (@aymanbagabas)
- 517a361: feat(ui): dialog: wrap navigation from last to first and vice versa (@aymanbagabas)
- 77ecb39: feat(ui): filepicker: add image attachment support with preview (@aymanbagabas)
- d4ffb55: feat(ui): filepicker: support kitty graphics in tmux (@aymanbagabas)
- 8ded0be: feat(ui): filepicker: support kitty graphics in tmux (#1884) (@aymanbagabas)
- 22040d2: feat(ui): implement tea.Layer Draw for UI model (@aymanbagabas)
- 0633988: feat(ui): initial chat ui implementation (@aymanbagabas)
- cd88520: feat(ui): initial lazy-loaded list implementation (@aymanbagabas)
- 8d7e64f: feat(ui): invalidate rendered items on focus/blur (@aymanbagabas)
- c0be798: feat(ui): list: expose filterable items source type and return values for selection methods (@aymanbagabas)
- 90491b4: feat(ui): model dialog: implement model selection handling (@aymanbagabas)
- 26145a7: feat(ui): model selection dialog (@aymanbagabas)
- f541590: feat(ui): models dialog: filter by provider and model name (@aymanbagabas)
- c280dd5: feat(ui): models dialog: improve group filtering by ignoring spaces (@aymanbagabas)
- 819c33d: feat(ui): new session selector dialog (@aymanbagabas)
- 953d181: feat(ui): optimize ScrollToBottom in lazylist (@aymanbagabas)
- 8783795: feat(ui): restructure UI package into subpackages (@aymanbagabas)
- b93a334: feat(ui): show working directory in window title (@aymanbagabas)
- d9e6736: feat(ui): simplify editor and embed into main UI model (@aymanbagabas)
- 17e6616: feat(ui): status: add status bar with info messages and help toggle (@aymanbagabas)
- 742b4d3: feat(ui): use the new UI behind a feature flag (@aymanbagabas)
- 3f7de0e: feat(ui): wip: add commands dialog to show available commands (@aymanbagabas)
- cd81f94: feat(ui): wip: basic chat message sending (@aymanbagabas)
- 030c8fc: feat: allow to send the prompt if its empty but has text attachments (#1809) (@caarlos0)
- b66db25: feat: attachments (#1797) (@caarlos0)
- 23e0b06: feat: completions menu (#1781) (@caarlos0)
- 3669423: feat: crush run --model, and crush models (#1889) (@caarlos0)
- dcd664a: feat: implement api key input dialog on new ui codebase (#1836) (@andreynering)
- f2f4454: feat: implement github copilot oauth flow in the new ui codebase (@andreynering)
- c45b152: feat: implement hyper oauth flow in the new ui codebase (@andreynering)
- f48a3ed: feat: implement text highlighting in list items (#1536) (@aymanbagabas)
- 4086e2f: feat: increase paste lines as attachment threshold (#1936) (@caarlos0)
- 7c99274: feat: open editor in the right position (#1803) (@caarlos0)
- 1e83e66: feat: paste as file (#1800) (@caarlos0)
Fixed
- 03beedc: fix(chat): do not mark tools with results as canceled (@kujtimiihoxha)
- ff9cbf6: fix(chat): only spin when there is no and no tool calls (@kujtimiihoxha)
- b6185b1: fix(chat): race condition (@kujtimiihoxha)
- d5f0987: fix(chat): reset index and paused animations (@kujtimiihoxha)
- c74a5c4: fix(dialog): commands: execute command handlers properly (@aymanbagabas)
- e38ffc3: fix(models): ensure that we show unknown providers on the list (@andreynering)
- b66676c: fix(sec): do not output resolved command (#1934) (@caarlos0)
- 098bc8a: fix(sessions): select the current session in dialog (@kujtimiihoxha)
- 6b8ca6a: fix(ui): accurately calculate help and main height in UI layout (@aymanbagabas)
- 706e359: fix(ui): adjust app and help area margins (@aymanbagabas)
- 675d851: fix(ui): adjust dialog sizing to account for dynamic title and help heights (@aymanbagabas)
- 84bbd5b: fix(ui): change UI model receiver to pointer back (@aymanbagabas)
- f0942a7: fix(ui): change pointer receivers to value receivers (@aymanbagabas)
- 6a57463: fix(ui): completions: load files asynchronously (@aymanbagabas)
- 0c8cd47: fix(ui): completions: simplify Close method (@aymanbagabas)
- 6c05739: fix(ui): completions: simplify completions popup message handling (@aymanbagabas)
- e2a586c: fix(ui): correct scrolling up behavior in lazy list (@aymanbagabas)
- 9899424: fix(ui): dialog sessions refactor and close commands dialog on select (@aymanbagabas)
- d54a5e7: fix(ui): dialog: align radio buttons with checkboxes (@aymanbagabas)
- f14253f: fix(ui): dialog: clarify session age display (@aymanbagabas)
- 67ac46a: fix(ui): dialog: no need for groupItems map in ModelsList.VisibleItems (@aymanbagabas)
- fedf059: fix(ui): dialog: saveKeyAndContinue should return Action (@aymanbagabas)
- 82eafde: fix(ui): dialog: show provider name for recent models (@aymanbagabas)
- 179e17f: fix(ui): dialog: show shortcut/info in list items (@aymanbagabas)
- fb78b80: fix(ui): dialogs: ensure returned commands are executed (@aymanbagabas)
- 876048d: fix(ui): do not allow summarizing if agent is busy (@kujtimiihoxha)
- aec65c4: fix(ui): don't use separate showFullHelp field (@aymanbagabas)
- 065f339: fix(ui): dry highlighting items in lazylist (@aymanbagabas)
- fa5c593: fix(ui): dry up session dialog key bindings (@aymanbagabas)
- c4cdc5d: fix(ui): dry up up/down key binding in dialog commands (@aymanbagabas)
- 7b19142: fix(ui): editor: show yolo prompt correctly (@aymanbagabas)
- 749a966: fix(ui): ensure MCPs are displayed in configured order (@aymanbagabas)
- 9f5284f: fix(ui): filepicker: defer image preview until after transmission (@aymanbagabas)
- cb8ddcb: fix(ui): filepicker: remove redundant Init method and Action type (@aymanbagabas)
- f97faa1: fix(ui): filepicker: simplify cmd return (@aymanbagabas)
- ded1e6b: fix(ui): filepicker: simplify tmux kitty image encoding (@aymanbagabas)
- f79c9ce: fix(ui): fix scrolling up last item (@aymanbagabas)
- 98df293: fix(ui): handle model selection in models dialog (@aymanbagabas)
- a52e030: fix(ui): hide cursor when editor is not visible (@aymanbagabas)
- d5b83c0: fix(ui): implement Highlightable interface for message items (@aymanbagabas)
- 1bb5aa8: fix(ui): improve key handling and keybindings for chat/editor (@aymanbagabas)
- 8e244e6: fix(ui): improve thinking message truncation display (@aymanbagabas)
- 158f7a9: fix(ui): increase paste lines threshold (#1937) (@caarlos0)
- 1c968b8: fix(ui): lint: use consistent receiver names in EditorModel methods (@aymanbagabas)
- 03b18fe: fix(ui): list: countLines should return 1 for empty strings (@aymanbagabas)
- dd9e8ca: fix(ui): list: move focused logic to render callback (@aymanbagabas)
- 318b2c6: fix(ui): list: prevent negative offset in list rendering (@aymanbagabas)
- a1648a8: fix(ui): list: scroll to bottom after session load (@aymanbagabas)
- 5df4696: fix(ui): model dialog: skip non-model items when navigating selection (@aymanbagabas)
- 909244e: fix(ui): models dialog: filter each group separately (@aymanbagabas)
- 6088247: fix(ui): move canvas initialization to View method (@aymanbagabas)
- 7b267bc: fix(ui): openEditor and handle pasted files in editor (@aymanbagabas)
- ece936a: fix(ui): prevent panic when session is nil (@aymanbagabas)
- b449545: fix(ui): properly align session item age text (@aymanbagabas)
- e86304d: fix(ui): remove redundant check in thinking rendering (@aymanbagabas)
- 1460d75: fix(ui): scroll down off by one (@aymanbagabas)
- 039f744: fix(ui): simplify QuitDialogKeyMap by embedding key bindings directly (@aymanbagabas)
- 01c0524: fix(ui): simplify suffix handling in message editor (@aymanbagabas)
- 7bc57e7: fix(ui): use Content instead of Layer for main view (@aymanbagabas)
- bea6010: fix(ui): use new lipgloss compositor (@aymanbagabas)
- 4c938aa: fix: address "verifying..." now showing on side of spinner (@andreynering)
- f27f546: fix: address double vertical margins between sections (@andreynering)
- 6caf878: fix: align "authentication successful" on the left (@andreynering)
- 2fa1f4d: fix: correct spelling from marshall to marshal (@meowgorithm)
- 4403170: fix: correct typo in log message (@meowgorithm)
- f8a9b94: fix: ensure that hyper and copilot models show up even if not configured (@andreynering)
- 0777060: fix: recent models dont go into the schema (#1892) (@caarlos0)
- c4add9e: fix: use cached lsp.DiagnosticCounts (#1814) (@caarlos0)
- 4c223c3: fix: use canvas to render UI view (@aymanbagabas)
- 7c21b1f: fix: use strconv.ParseBool (@aymanbagabas)
Docs
- 2926883: docs(readme): remove link to site that is offline (#1926) (@andreynering)
Other stuff
- f2f63d1: Refactor Custom Command Arguments Dialog (#1869) (@kujtimiihoxha)
- 7a2769c: Refactor commands (#1847) (@kujtimiihoxha)
- 4379251: Refactored permissions dialog (#1796) (@kujtimiihoxha)
- 95bae10: chore(chat): add some missing docs (@kujtimiihoxha)
- 3474160: chore(chat): remove empty assistant messages (@kujtimiihoxha)
- 8cea088: chore(chat): remove unused style (@kujtimiihoxha)
- b0dd983: chore(chat): rename funcs (@kujtimiihoxha)
- 14ff224: chore(chat): small improvements (@kujtimiihoxha)
- b8d39c6: chore(chat): some more docs missing (@kujtimiihoxha)
- c6e7e39: chore(prompt): small edits (#1915) (@meowgorithm)
- 9e018b9: chore(tools/edit): various fixes (#1921) (@meowgorithm)
- 4e541e1: chore(ui): add TODO for model API and auth validation (@aymanbagabas)
- 8d5226d: chore(ui): add comments to internal/ui/model/ui.go (@aymanbagabas)
- ed7ef78: chore(ui): standardize dialog identifiers (@aymanbagabas)
- 4665ad2: chore(ui): standardize truncation message format (@aymanbagabas)
- 26edcdc: chore: add chat sidebar (#1510) (@kujtimiihoxha)
- e2b071d: chore: add log when new UI is enabled (@aymanbagabas)
- 4c540cf: chore: fix const type (@caarlos0)
- f4b848b: chore: implement missing command and fix summarize (#1882) (@kujtimiihoxha)
- db5c3eb: chore: initialize functionality & landing page (@kujtimiihoxha)
- f7a22a8: chore: remove dead (duplicate) code (#1913) (@meowgorithm)
- 3635435: chore: remove redundant zero value initialization (@meowgorithm)
- 1ca8abc: chore: remove unnecessary testing concerns from env.New (@meowgorithm)
- bbce33f: chore: rename isSpinning to spinning (@kujtimiihoxha)
- 2f845cc: chore: return empty slices instead of nil for safety (@meowgorithm)
- b7c128a: chore: simplify struct initialization to direct return (@meowgorithm)
- 614b0bc: chore: some cleanup (@kujtimiihoxha)
- e16eae1: perf(ui): dialog: preallocate slice for filterable items in ModelsList (@aymanbagabas)
- 2f1feaa: refactor(chat): add bash related tools (@kujtimiihoxha)
- df22d89: refactor(chat): add file tools (@kujtimiihoxha)
- 5699a91: refactor(chat): add search tools (@kujtimiihoxha)
- 462cdf6: refactor(chat): hook up events for tools (@kujtimiihoxha)
- 4f07a54: refactor(chat): implement user message (#1644) (@kujtimiihoxha)
- 0896789: refactor(chat): initial setup for tool calls (@kujtimiihoxha)
- ed18aac: refactor(chat): only show animations for items that are visible (@kujtimiihoxha)
- 2cccd51: refactor(chat): rename GetMessageItems to ExtractMessageItems and GetToolRenderer to ToolRenderer (@aymanbagabas)
- 3d9d4e6: refactor(chat): simple assistant message (@kujtimiihoxha)
- 17de9c7: refactor(list): remove item IDs for simpler API (@aymanbagabas)
- 5d6dbc8: refactor(list): simplify focus and highlight interfaces (@aymanbagabas)
- c444075: refactor(ui): reimplement UI components (#1652) (@aymanbagabas)
- 41b819f: refactor(ui): chat: abstract tool message rendering (@aymanbagabas)
- 6dc2dd8: refactor(ui): cleanup and remove unused list code (@aymanbagabas)
- 1f0605a: refactor(ui): dialog: cleanup render logic and use RenderContext (#1871) (@aymanbagabas)
- 7fad242: refactor(ui): dialog: improve command and session dialogs (@aymanbagabas)
- fcd1b83: refactor(ui): dialog: message and draw handling (#1822) (@aymanbagabas)
- e24c9c3: refactor(ui): dialog: rename Add/Remove to Open/Close (@aymanbagabas)
- eed0b49: refactor(ui): dialog: unify session and model switching dialogs (@aymanbagabas)
- 18ee540: refactor(ui): dialog: use Action pattern and lipgloss layers (@aymanbagabas)
- 2dc5d0b: refactor(ui): list: remove mouse highlighting state, add render callbacks (@aymanbagabas)
- ba9e452: refactor(ui): pass app.App to common.Common and access config via common (@aymanbagabas)
- 94de6bc: refactor(ui): remove dirty tracking from LazyList (@aymanbagabas)
- e593297: refactor(ui): rename files.go to session.go and update session loading logic (@aymanbagabas)
- b25730d: refactor(ui): rename lazylist package to list and update imports (@aymanbagabas)
- 706e182: refactor(ui): reorganize ui components into flat structure (@aymanbagabas)
- efaa956: refactor(ui): rework init and support different layouts (#1463) (@kujtimiihoxha)
- 53d38c0: refactor(ui): simplify dialog model and rendering (@aymanbagabas)
- 2f95dcc: refactor(ui): use uiutil for command handling and error reporting (@aymanbagabas)
- c0e3f79: refactor: add agent tools and rename simple->compact (@kujtimiihoxha)
- 0decf78: refactor: add assistant info item (#1881) (@kujtimiihoxha)
- 67efe86: refactor: add more tools (@kujtimiihoxha)
- 19c67f7: refactor: compact mode (#1850) (@kujtimiihoxha)
- ccb1a64: refactor: make oauth dialog generic and move provider logic to interface (@andreynering)
- ead5bf4: refactor: mcp tool item (#1923) (@kujtimiihoxha)
- 4261dfb: refactor: move domain-specific type out of generic pubsub package (@meowgorithm)
- c3e9196: refactor: pills section (#1916) (@kujtimiihoxha)
- e70d46f: refactor: reasoning dialog (#1880) (@kujtimiihoxha)
- 8b5cc43: refactor: remove duplication on functions to open dialogs (@andreynering)
- 9f7be9d: refactor: remove init in favor of returning cmd on new (@andreynering)
- 599866a: refactor: use
cmp.Or(@andreynering)
Verifying the artifacts
First, download the checksums.txt file and the checksums.txt.sigstore.json file files, for example, with wget:
wget 'https://github.com/charmbracelet/crush/releases/download/v0.34.0/checksums.txt'
wget 'https://github.com/charmbracelet/crush/releases/download/v0.34.0/checksums.txt.sigstore.json'Then, verify it using cosign:
cosign verify-blob \
--certificate-identity 'https://github.com/charmbracelet/meta/.github/workflows/goreleaser.yml@refs/heads/main' \
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
--bundle 'checksums.txt.sigstore.json' \
./checksums.txtIf the output is Verified OK, you can safely use it to verify the checksums of other artifacts you downloaded from the release using sha256sum:
sha256sum --ignore-missing -c checksums.txtDone! You artifacts are now verified!
Thoughts? Questions? We love hearing from you. Feel free to reach out on X, Discord, Slack, The Fediverse, Bluesky.
