v0.34.0

charmbracelet/crushv0.34.0Jan 21, 2026by github-actions[bot]

AI Summary

This release focuses on improving non-interactive mode (`crush run`) with a new `--model` flag for specifying AI models and providers, plus a `crush models` command to list available models. It also includes bug fixes for the edit tool, automatic terminal tab titles, and a major UI internals overhaul to reduce complexity and improve performance (available behind `CRUSH_NEW_UI=1` feature flag).

Key Highlights

  • New `--model` flag for `crush run` to specify models via `{model}` or `{provider}/{model}` format
  • New `crush models` command to list available AI models
  • Bug fixes for the edit tool (PRs #1921, #1915)
  • Automatic terminal tab title setting as QoL improvement
  • Major UI refactoring with new components including dialogs, sidebar, and file picker (behind `CRUSH_NEW_UI=1` flag)

New Features

  • `crush run --model` flag for specifying AI models in non-interactive mode
  • `crush models` command to list available models
  • Expandable thinking display for assistant messages
  • New UI with dialogs (model selection, session selector, commands, file picker)
  • Completions menu for command suggestions
  • File attachments with image preview support
  • Paste as file functionality
  • GitHub Copilot and Hyper OAuth flow implementations
  • Text highlighting support in lazy list components
  • Optimized list component with focus navigation
  • Status bar with info messages and help toggle
  • Working directory display in window title

Full Release Notes

# Non-interactive 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:

```bash
# 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 fine
```

Wondering what models are available? Check out `crush models`. Works great with `grep`, too.

<p><img width="550" alt="Crush Models" src="https://github.com/user-attachments/assets/a56efd18-39cf-49ea-ad7e-b9213540711d" /></p>

## Better edits and QoL

Not less important, this release include some [bug](https://github.com/charmbracelet/crush/pull/1921) [fixes](https://github.com/charmbracelet/crush/pull/1915) for the edit tool. Also, the [terminal tab title will be set automatically](https://github.com/charmbracelet/crush/pull/1886) 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!
* 4316ef3c2f6b14d242e04d569d99d4fcea829ce8: feat(chat): expandable thinking for assistant (@kujtimiihoxha)
* 27fa971aff9352dc74acf834d2a5ca87800d4f8b: feat(ui): add basic dialog and new UI structure (@aymanbagabas)
* 7d9976252d289b3331376ff1e0aa3d597736d708: feat(ui): add chat and editor models with keybindings (@aymanbagabas)
* 82bc601d267ea1e9b8b1fb2d966a2a965aa52782: feat(ui): add common utils and refactor chat message items and tools (@aymanbagabas)
* 470e6f6de7b40957e080a17f25b879c4296eb329: feat(ui): add initial sidebar component with logo (@aymanbagabas)
* afb546733555e78a5970c544062e72e9c4f4360b: feat(ui): add mouse click handling to lazy list items (@aymanbagabas)
* b71baee343d715660693d430fa5ff420b6f9cfab: feat(ui): add optimized list component with focus navigation (@aymanbagabas)
* 9c001302115b716d9a00c787f9b61be3668d35a4: feat(ui): add text highlighting support to lazylist (@aymanbagabas)
* ca3e06a43cd8bd111952f174b27e945cc6a9e3d3: feat(ui): chat: add navigation and keybindings (@aymanbagabas)
* a5c597bdc26d27025046daaa19b8eecb1d558fc6: feat(ui): copy chat highlighted content to clipboard (@aymanbagabas)
* 5d2c533d9c2cea817506d8a8618c0859b469174b: feat(ui): dialog: add file picker dialog with image preview (@aymanbagabas)
* 517a3613c12513d91d93b59c56aae5204c12b4e6: feat(ui): dialog: wrap navigation from last to first and vice versa (@aymanbagabas)
* 77ecb3924f3378c6a494984ba190a48f99a44a56: feat(ui): filepicker: add image attachment support with preview (@aymanbagabas)
* d4ffb554cd6aaded7fd280d5b3f6aa793cba58a1: feat(ui): filepicker: support kitty graphics in tmux (@aymanbagabas)
* 8ded0befafd9b876220159a753de464a19f6982d: feat(ui): filepicker: support kitty graphics in tmux (#1884) (@aymanbagabas)
* 22040d2c844aaf87b3eae9817447dca2867d60bb: feat(ui): implement tea.Layer Draw for UI model (@aymanbagabas)
* 063398841cb5bcca61d7a6b7d6a08cd8146b26be: feat(ui): initial chat ui implementation (@aymanbagabas)
* cd88520924a23f2258ec25302a7916760335c12d: feat(ui): initial lazy-loaded list implementation (@aymanbagabas)
* 8d7e64fef8dbfdf31aa5bfa8831d7f1b114457e2: feat(ui): invalidate rendered items on focus/blur (@aymanbagabas)
* c0be798cb5dfda1408a87f3a90bf8294aca6601a: feat(ui): list: expose filterable items source type and return values for selection methods (@aymanbagabas)
* 90491b4b8ae5be3605cd92d77418edfd5aa4f3e1: feat(ui): model dialog: implement model selection handling (@aymanbagabas)
* 26145a76b5f82158dc0d3ab7a4a513aed3a8b7e1: feat(ui): model selection dialog (@aymanbagabas)
* f5415908291cbb713943aa5f42b3f9e54a5cfa1c: feat(ui): models dialog: filter by provider and model name (@aymanbagabas)
* c280dd546834d6f54c74ea0484c49fc0c5920caf: feat(ui): models dialog: improve group filtering by ignoring spaces (@aymanbagabas)
* 819c33d24e6753836ddfe137596842316f17bc4f: feat(ui): new session selector dialog (@aymanbagabas)
* 953d181984a5daf537bba6a7c713c343e2e55d6a: feat(ui): optimize ScrollToBottom in lazylist (@aymanbagabas)
* 8783795bcbeedfafd2b58b566a5589d8d6bb8f6f: feat(ui): restructure UI package into subpackages (@aymanbagabas)
* b93a3347acf294d59c338c8bad52d28ca9bce5ba: feat(ui): show working directory in window title (@aymanbagabas)
* d9e67367226436d629078fe392e38bc2d61aefeb: feat(ui): simplify editor and embed into main UI model (@aymanbagabas)
* 17e66163283638c8de1bf73557e9c0766b38062d: feat(ui): status: add status bar with info messages and help toggle (@aymanbagabas)
* 742b4d3543ed4977e2e9c578bac36cc6bcad509e: feat(ui): use the new UI behind a feature flag (@aymanbagabas)
* 3f7de0eaaddd6ada99972a8c84ea74649c6fdb61: feat(ui): wip: add commands dialog to show available commands (@aymanbagabas)
* cd81f945f2a19d0af08c6d9b6db646da3781f19b: feat(ui): wip: basic chat message sending (@aymanbagabas)
* 030c8fc58ea90cdf796827a8eb69b1e9f02cb5c6: feat: allow to send the prompt if its empty but has text attachments (#1809) (@caarlos0)
* b66db250ad9915f6957c79cd8a35c105e0812017: feat: attachments (#1797) (@caarlos0)
* 23e0b06d0054203cf4deb033b18e48037ed99e5d: feat: completions menu (#1781) (@caarlos0)
* 366942352a14d6361e40ef44a470bb051548fa78: feat: crush run --model, and crush models (#1889) (@caarlos0)
* dcd664a4a19a9920fb30048962ba7f0f64839bf9: feat: implement api key input dialog on new ui codebase (#1836) (@andreynering)
* f2f44540f58e3cca3602f11d5bd7c002e3ff3109: feat: implement github copilot oauth flow in the new ui codebase (@andreynering)
* c45b1521640ccc513507ae0815609e7c031941d0: feat: implement hyper oauth flow in the new ui codebase (@andreynering)
* f48a3edc33ca62dd9d6ff5f6a226f12f659ce57a: feat: implement text highlighting in list items (#1536) (@aymanbagabas)
* 4086e2f007ac54f1785535546f0fc0bae47afada: feat: increase paste lines as attachment threshold (#1936) (@caarlos0)
* 7c99274dd8a8cbbd0afadbadfc0ae550854a9c23: feat: open editor in the right position (#1803) (@caarlos0)
* 1e83e6657d52c1a7746a6b9425861de1cf83ff28: feat: paste as file (#1800) (@caarlos0)
### Fixed
* 03beedc2002cb9f909568ec3c32775fca0faf023: fix(chat): do not mark tools with results as canceled (@kujtimiihoxha)
* ff9cbf656f77745a147b285ea1a6311ca1533210: fix(chat): only spin when there is no and no tool calls (@kujtimiihoxha)
* b6185b1d9e8f0c58531c3567750d43f20274489b: fix(chat): race condition (@kujtimiihoxha)
* d5f0987bd52d458f86cdfadec0cad4920bb2ce2a: fix(chat): reset index and paused animations (@kujtimiihoxha)
* c74a5c4d64491606fbeff0eda109b7eae5e4e52c: fix(dialog): commands: execute command handlers properly (@aymanbagabas)
* e38ffc3804b85e5dd70c39063a7a9f553fbdff4b: fix(models): ensure that we show unknown providers on the list (@andreynering)
* b66676c52acc2ae0d151d4f5f819820fd188ddcd: fix(sec): do not output resolved command (#1934) (@caarlos0)
* 098bc8abf07fd8dd0506669376c34e6445a07f10: fix(sessions): select the current session in dialog (@kujtimiihoxha)
* 6b8ca6a7c512daea687c8389657db2a421707c31: fix(ui): accurately calculate help and main height in UI layout (@aymanbagabas)
* 706e359b34d1a498a2569532f0b1006fabb169bc: fix(ui): adjust app and help area margins (@aymanbagabas)
* 675d8515bfa37db9dd270f6d97faa494c650af2f: fix(ui): adjust dialog sizing to account for dynamic title and help heights (@aymanbagabas)
* 84bbd5b7587ad538c0b67f27ad9b48934a149cf5: fix(ui): change UI model receiver to pointer back (@aymanbagabas)
* f0942a72d202fb74ef0666a1b26ac3f1443f1aa2: fix(ui): change pointer receivers to value receivers (@aymanbagabas)
* 6a5746354cd9998fabadf57dc9c9ce0a91023e4c: fix(ui): completions: load files asynchronously (@aymanbagabas)
* 0c8cd47548296e9eaed766d8569411f9d3193f1f: fix(ui): completions: simplify Close method (@aymanbagabas)
* 6c0573915f184d935786ef8ecdfc18571f6dc0d9: fix(ui): completions: simplify completions popup message handling (@aymanbagabas)
* e2a586ca40e3fa0f9c4c3d19ec7f80d54c61057f: fix(ui): correct scrolling up behavior in lazy list (@aymanbagabas)
* 9899424bb063ddb626a6de6df603cfbdcb1118e0: fix(ui): dialog sessions refactor and close commands dialog on select (@aymanbagabas)
* d54a5e7eb11892ecb67e3f8510028d037c4978f9: fix(ui): dialog: align radio buttons with checkboxes (@aymanbagabas)
* f14253f1085fe7d5de9559805cddc6e6710835ab: fix(ui): dialog: clarify session age display (@aymanbagabas)
* 67ac46a526623357497b409f2848a15b5dbee0be: fix(ui): dialog: no need for groupItems map in ModelsList.VisibleItems (@aymanbagabas)
* fedf05910715b0c6349092cd6afbfa68a41c830d: fix(ui): dialog: saveKeyAndContinue should return Action (@aymanbagabas)
* 82eafde6a9ce0b10ea44c3b54ee0ba6b01b9bf4f: fix(ui): dialog: show provider name for recent models (@aymanbagabas)
* 179e17f64604c2facf843199b069d23c08a5155c: fix(ui): dialog: show shortcut/info in list items (@aymanbagabas)
* fb78b802586c10dc40dbdd2602ef62a3c51f08c4: fix(ui): dialogs: ensure returned commands are executed (@aymanbagabas)
* 876048d8b45fdbe0a57c6e0a7db8f5f9da2dac32: fix(ui): do not allow summarizing if agent is busy (@kujtimiihoxha)
* aec65c42f57648ab2d2715fe49851f09647d6271: fix(ui): don't use separate showFullHelp field (@aymanbagabas)
* 065f33999124673c5a9ab6c2e3de6f0393c31520: fix(ui): dry highlighting items in lazylist (@aymanbagabas)
* fa5c593c61775ffb3d14f02b06f784c696cea303: fix(ui): dry up session dialog key bindings (@aymanbagabas)
* c4cdc5dee1ce6c86f9d86b03d8845120f8c804f6: fix(ui): dry up up/down key binding in dialog commands (@aymanbagabas)
* 7b1914262610b73ed6873705402dee5760b32feb: fix(ui): editor: show yolo prompt correctly (@aymanbagabas)
* 749a966f306f81cfa34ed7e56f6f0c4501674711: fix(ui): ensure MCPs are displayed in configured order (@aymanbagabas)
* 9f5284f56cebf49d8a13d5bbfb294c0499bb820d: fix(ui): filepicker: defer image preview until after transmission (@aymanbagabas)
* cb8ddcb99c013dabc7de902e5b8ae74ba16e0abc: fix(ui): filepicker: remove redundant Init method and Action type (@aymanbagabas)
* f97faa180bd3274539158fe14dbc6457af579af5: fix(ui): filepicker: simplify cmd return (@aymanbagabas)
* ded1e6b277bbfac8168dc1f978de3da5f3bc0138: fix(ui): filepicker: simplify tmux kitty image encoding (@aymanbagabas)
* f79c9ce48407073360b55c21c008567d28b56524: fix(ui): fix scrolling up last item (@aymanbagabas)
* 98df293310d9d86cb416647f2f526c1907e4d377: fix(ui): handle model selection in models dialog (@aymanbagabas)
* a52e0306c3603b969daed15a59cc88683fac9e8c: fix(ui): hide cursor when editor is not visible (@aymanbagabas)
* d5b83c0dbbaa228bf3f783495d73e6db84489e2d: fix(ui): implement Highlightable interface for message items (@aymanbagabas)
* 1bb5aa8e0784f68313c07d54188a083b5d009121: fix(ui): improve key handling and keybindings for chat/editor (@aymanbagabas)
* 8e244e651a6d8e662f88e6b640ef3541a319ae62: fix(ui): improve thinking message truncation display (@aymanbagabas)
* 158f7a957cb8438324335c97783805b28ee3b18c: fix(ui): increase paste lines threshold (#1937) (@caarlos0)
* 1c968b8804acb3b5fe30fa1c1d4bfe13ce48fcc4: fix(ui): lint: use consistent receiver names in EditorModel methods (@aymanbagabas)
* 03b18fe755acf77f5e10b9000ed7a2cf605af465: fix(ui): list: countLines should return 1 for empty strings (@aymanbagabas)
* dd9e8ca15c72160f63fb017777a76029d65cbcef: fix(ui): list: move focused logic to render callback (@aymanbagabas)
* 318b2c681bb917a21b9126ef4ed2f2d1cad646f7: fix(ui): list: prevent negative offset in list rendering (@aymanbagabas)
* a1648a8c5f2599c240dfa8b8f5a943032266cb30: fix(ui): list: scroll to bottom after session load (@aymanbagabas)
* 5df46965eb6221b8a524f0c8a3b0d6c5b61f71fb: fix(ui): model dialog: skip non-model items when navigating selection (@aymanbagabas)
* 909244e4706a2408acf625ce38a7c5592c9322aa: fix(ui): models dialog: filter each group separately (@aymanbagabas)
* 60882473c933131a4cd78ed2eb3a4a3ff591c430: fix(ui): move canvas initialization to View method (@aymanbagabas)
* 7b267bc6a68bd8de20e8bbea9c25024e63412731: fix(ui): openEditor and handle pasted files in editor (@aymanbagabas)
* ece936a9bfa80b7ede2d8f09ee9a6c2cb55a6e0d: fix(ui): prevent panic when session is nil (@aymanbagabas)
* b4495455256ca33210e67c76722ec93c985dd694: fix(ui): properly align session item age text (@aymanbagabas)
* e86304d5a6f6d9c0a806ae9e402ee971fcf8ee62: fix(ui): remove redundant check in thinking rendering (@aymanbagabas)
* 1460d7577690c9b0e131442670c82911f6147e2b: fix(ui): scroll down off by one (@aymanbagabas)
* 039f7443e21fb5e4d602a9f8366d7a11264a5725: fix(ui): simplify QuitDialogKeyMap by embedding key bindings directly (@aymanbagabas)
* 01c052473d7c9e95dc7391c188ed8deb34ad3b95: fix(ui): simplify suffix handling in message editor (@aymanbagabas)
* 7bc57e7e1689bf2a284aa3120c7e4e92868a4d09: fix(ui): use Content instead of Layer for main view (@aymanbagabas)
* bea6010aa9d8f025b0c9f97cbfad12674dacda8a: fix(ui): use new lipgloss compositor (@aymanbagabas)
* 4c938aa1f773150fb5119c640e9427d684a1015e: fix: address "verifying..." now showing on side of spinner (@andreynering)
* f27f5460223ea98f91ef41b826218d1de882c3e8: fix: address double vertical margins between sections (@andreynering)
* 6caf8788dcbaa9bf3ee2326abc738dbf428f8f5a: fix: align "authentication successful" on the left (@andreynering)
* 2fa1f4dd56d9edced17df1942973d925a4d6cbb8: fix: correct spelling from marshall to marshal (@meowgorithm)
* 4403170ac0af2eb076d23fa9ed4d85ee667cf98d: fix: correct typo in log message (@meowgorithm)
* f8a9b943e7069b76518c10b7db50694c5dd6345c: fix: ensure that hyper and copilot models show up even if not configured (@andreynering)
* 077706036c3a6dc502d7f5d30f2bc77ad1b4d733: fix: recent models dont go into the schema (#1892) (@caarlos0)
* c4add9e0fa401da01b8d0ea6d1b42d03bc354de1: fix: use cached lsp.DiagnosticCounts (#1814) (@caarlos0)
* 4c223c375378ed805f04692e06f22e84646929a8: fix: use canvas to render UI view (@aymanbagabas)
* 7c21b1f0c06d414f9205beae9bd14834fb36b12f: fix: use strconv.ParseBool (@aymanbagabas)
### Docs
* 292688313b69dd295d57618c73e104d9899ad6fd: docs(readme): remove link to site that is offline (#1926) (@andreynering)
### Other stuff
* f2f63d1dfcd528a8fb64387f38f716cb0ca7378f: Refactor Custom Command Arguments Dialog (#1869) (@kujtimiihoxha)
* 7a2769c0a3b51fb0bfe6988c43208eb272f03d67: Refactor commands (#1847) (@kujtimiihoxha)
* 4379251cfe71ddc892b80d3385a3b0b9e6ba54db: Refactored permissions dialog (#1796) (@kujtimiihoxha)
* 95bae1017e11e4312ef98d78eed21eceb2211087: chore(chat): add some missing docs (@kujtimiihoxha)
* 34741602aab75afb82e3eba797efe6ec6d97aefc: chore(chat): remove empty assistant messages (@kujtimiihoxha)
* 8cea0883824de2cfb0627069333c579ea41648ee: chore(chat): remove unused style (@kujtimiihoxha)
* b0dd9830ad278754699406aff3c44b97d01fb8be: chore(chat): rename funcs (@kujtimiihoxha)
* 14ff2243a2f79c3925bc56247d7234aab1d332cd: chore(chat): small improvements (@kujtimiihoxha)
* b8d39c6abdf3d8ff47b6c0cdb9b0d2fbb62ce1de: chore(chat): some more docs missing (@kujtimiihoxha)
* c6e7e3904aeda3768f871827a23538d950c62c98: chore(prompt): small edits (#1915) (@meowgorithm)
* 9e018b939547b9a953cb5ecba72fcad614b3594e: chore(tools/edit): various fixes (#1921) (@meowgorithm)
* 4e541e1910f3f2d8362259da1b0776f59e6a12c9: chore(ui): add TODO for model API and auth validation (@aymanbagabas)
* 8d5226d29f3929dcbd7c8089e5995c068706fe2f: chore(ui): add comments to internal/ui/model/ui.go (@aymanbagabas)
* ed7ef782eae8e202e606c09e1aecf9635dea9eae: chore(ui): standardize dialog identifiers (@aymanbagabas)
* 4665ad27daeb777fe519f7d8057c4dfea7923e9d: chore(ui): standardize truncation message format (@aymanbagabas)
* 26edcdc405cea27dac32208f060a36d565930c0a: chore: add chat sidebar (#1510) (@kujtimiihoxha)
* e2b071d0cea57829f85270871753af34535e1a25: chore: add log when new UI is enabled (@aymanbagabas)
* 4c540cfccb48ce16b5b4fa53c11e48bc238577b9: chore: fix const type (@caarlos0)
* f4b848b50db54d17cfb162d0b8ba80109ac67d5a: chore: implement missing command and fix summarize (#1882) (@kujtimiihoxha)
* db5c3eb3983e838eec277e959e42c6fa18f4272a: chore: initialize functionality & landing page (@kujtimiihoxha)
* f7a22a80999eb57b0dadc26f230fb5818bc664dd: chore: remove dead (duplicate) code (#1913) (@meowgorithm)
* 36354358f302018ba173bd3f2866580ed228098a: chore: remove redundant zero value initialization (@meowgorithm)
* 1ca8abc0a1f24778c64091b2a0cd96e00a6b03f2: chore: remove unnecessary testing concerns from env.New (@meowgorithm)
* bbce33fb50e8b53e02c0d54453047b5789ea64af: chore: rename isSpinning to spinning (@kujtimiihoxha)
* 2f845cc20e1b01310886a7dcbd440011e80cc8d4: chore: return empty slices instead of nil for safety (@meowgorithm)
* b7c128a33cfa79a8ae45b1865b453c7b9353a3c8: chore: simplify struct initialization to direct return (@meowgorithm)
* 614b0bc970f6b82584d0e9159e57a522e3077d4b: chore: some cleanup (@kujtimiihoxha)
* e16eae1a23ea4849429d0f69f711dd58d3e12638: perf(ui): dialog: preallocate slice for filterable items in ModelsList (@aymanbagabas)
* 2f1feaa17247968b07c722b78fc2cc71ff33d929: refactor(chat): add bash related tools (@kujtimiihoxha)
* df22d89a0ebfa2871dc089abde20dd1b5ab9326c: refactor(chat): add file tools (@kujtimiihoxha)
* 5699a91ad5573613fb72bc8f3dc73a8ae739ccf8: refactor(chat): add search tools (@kujtimiihoxha)
* 462cdf644189170903c3a51c4ee0363263d1d026: refactor(chat): hook up events for tools (@kujtimiihoxha)
* 4f07a5485d11fd11e7216954bebd85cfcd1d4f0c: refactor(chat): implement user message (#1644) (@kujtimiihoxha)
* 0896789b516e50c4a13c2ddc01a02fe4466c4bd8: refactor(chat): initial setup for tool calls (@kujtimiihoxha)
* ed18aac98e9f06cc1ad6aa2bef0f779ff894dc43: refactor(chat): only show animations for items that are visible (@kujtimiihoxha)
* 2cccd515a848a5df0d9dffea3c3f5f037752c07b: refactor(chat): rename GetMessageItems to ExtractMessageItems and GetToolRenderer to ToolRenderer (@aymanbagabas)
* 3d9d4e6a3d2c800d52269b0d234e10df56029a2f: refactor(chat): simple assistant message (@kujtimiihoxha)
* 17de9c79dbd908b2d988a736da74d558ba942c7b: refactor(list): remove item IDs for simpler API (@aymanbagabas)
* 5d6dbc865bbda659517373683c1a7972bbff2d7e: refactor(list): simplify focus and highlight interfaces (@aymanbagabas)
* c4440754e5b532f1669296b3565e346aac1602e5: refactor(ui):  reimplement UI components (#1652) (@aymanbagabas)
* 41b819f5204422eaf842d04454c4a1609ef07ae2: refactor(ui): chat: abstract tool message rendering (@aymanbagabas)
* 6dc2dd8fdcfca657ceb572348c410dc32b1c7e91: refactor(ui): cleanup and remove unused list code (@aymanbagabas)
* 1f0605ae33299a887971130f120dc7fca5cf635f: refactor(ui): dialog: cleanup render logic and use RenderContext (#1871) (@aymanbagabas)
* 7fad242ae375f9d8a7b2b6803cfea700b5e558ce: refactor(ui): dialog: improve command and session dialogs (@aymanbagabas)
* fcd1b83168efee74b3cf34f0b33c0a5f2a2bbf2f: refactor(ui): dialog: message and draw handling (#1822) (@aymanbagabas)
* e24c9c387693b83baa43d4cfc7deaa274a74661b: refactor(ui): dialog: rename Add/Remove to Open/Close (@aymanbagabas)
* eed0b49f8ceee2d23afd1dd3db0ff6ac295cb571: refactor(ui): dialog: unify session and model switching dialogs (@aymanbagabas)
* 18ee5408c46833f1d9328b1e51913e8d2988e97d: refactor(ui): dialog: use Action pattern and lipgloss layers (@aymanbagabas)
* 2dc5d0b02728a411df96c38f41612e01f70eeaf6: refactor(ui): list: remove mouse highlighting state, add render callbacks (@aymanbagabas)
* ba9e4528b292d4ad01e90fda3726829adfd7e14b: refactor(ui): pass app.App to common.Common and access config via common (@aymanbagabas)
* 94de6bc884658ed35797ff0dbca1ed5571af3e14: refactor(ui): remove dirty tracking from LazyList (@aymanbagabas)
* e5932974c5cbc41e1dde2624fc38be3e5d96ab3e: refactor(ui): rename files.go to session.go and update session loading logic (@aymanbagabas)
* b25730d0c30129f642b0ade59e9804bfceab52ad: refactor(ui): rename lazylist package to list and update imports (@aymanbagabas)
* 706e182730c2ea7542c0da0224c72b44c5d0db5d: refactor(ui): reorganize ui components into flat structure (@aymanbagabas)
* efaa956d77b90321e9979b78405f28b1b2d358dd: refactor(ui): rework init and support different layouts (#1463) (@kujtimiihoxha)
* 53d38c08edbabad0edd47d38a9b126d271b8301c: refactor(ui): simplify dialog model and rendering (@aymanbagabas)
* 2f95dcc6a6ce61554e851fc6eab69aa2f91f5c89: refactor(ui): use uiutil for command handling and error reporting (@aymanbagabas)
* c0e3f79756a0f405da72cb0c78ce93e773bee073: refactor: add agent tools and rename simple->compact (@kujtimiihoxha)
* 0decf78c95af8e3acbe6a9e056a179afa0a38c15: refactor: add assistant info item (#1881) (@kujtimiihoxha)
* 67efe867a128a9cea1bcde85b51864445dd8be39: refactor: add more tools (@kujtimiihoxha)
* 19c67f7ffc90d1470a4de5644ac78733f4020a42: refactor: compact mode (#1850) (@kujtimiihoxha)
* ccb1a643e9b0959e19bd0263e493a8b7a8544972: refactor: make oauth dialog generic and move provider logic to interface (@andreynering)
* ead5bf4857f22e583b78c6b26a4caeea38594460: refactor: mcp tool item (#1923) (@kujtimiihoxha)
* 4261dfbf156ae6c82e5e0d534eacd2651bd1f896: refactor: move domain-specific type out of generic pubsub package (@meowgorithm)
* c3e9196ed126e12d675092f02f3ddd4f42f8001b: refactor: pills section (#1916) (@kujtimiihoxha)
* e70d46fce15611861c38eeeb3ad11e42bb9fe28b: refactor: reasoning dialog (#1880) (@kujtimiihoxha)
* 8b5cc439a99cdf71bc8c66b62d4ed4471260585b: refactor: remove duplication on functions to open dialogs (@andreynering)
* 9f7be9d2924780b7b10d70061d46d2b9ff2bc997: refactor: remove init in favor of returning cmd on new (@andreynering)
* 599866a9c499a2227b0b97dd0161cc31b4cea93f: refactor: use `cmp.Or` (@andreynering)

---

<details>
<summary>Verifying the artifacts</summary>

First, download the [`checksums.txt` file](https://github.com/charmbracelet/crush/releases/download/v0.34.0/checksums.txt) and the [`checksums.txt.sigstore.json` file](https://github.com/charmbracelet/crush/releases/download/v0.34.0/checksums.txt.sigstore.json) files, for example, with `wget`:

```bash
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`](https://github.com/sigstore/cosign):

```bash
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.txt
```

If the output is `Verified OK`, you can safely use it to verify the checksums of other artifacts you downloaded from the release using `sha256sum`:

```bash
sha256sum --ignore-missing -c checksums.txt
```

Done! You artifacts are now verified!

</details>

<a href="https://charm.land/"><img alt="The Charm logo" src="https://stuff.charm.sh/charm-banner-next.jpg" width="400"></a>

Thoughts? Questions? We love hearing from you. Feel free to reach out on [X](https://x.com/charmcli), [Discord](https://charm.land/discord), [Slack](https://charm.land/slack), [The Fediverse](https://mastodon.social/@charmcli), [Bluesky](https://bsky.app/profile/charm.land).