v0.67.0

charmbracelet/crushv0.67.0May 11, 2026by github-actions[bot]

AI Summary

Major shell improvements with hooks now using built-in shell interpreter, shell expansion in config values, big file handling fixes, and updated Assisted-by commit header format.

Key Highlights

  • Hooks use built-in shell interpreter (better Windows support)
  • Shell expansion in config values (e.g., $(vault kv get secret))
  • Fixed big file reads and context window issues
  • Updated Assisted-by header to Linux kernel convention
  • Touch tool for creating empty files
  • Better image file detection by content not extension

New Features

  • Built-in shell interpreter for hooks
  • Shell expansion in config values
  • touch tool for empty files

Full Release Notes

# Busy Monday

We had a busy Monday mergin' all sorts of additions and small fixes. Thanks for using Crush, thanks for your contributions, and read on for all the details.

## Hooks now use the built-in shell interpreter

By default, Hooks will now use the built-in shell interpreter instead of the one from the system. This particularly improves support for Windows, where `bash` isn't always available. It's also great for general portability as you can ensure that Bash behaves the same across systems, including environments where Bash isn't available. Of course, if the script has a shebang, we'll still respect that and run on the specified tool.

Curious about Hooks in Crush? [Check out the docs.](https://github.com/charmbracelet/crush/blob/main/docs/hooks/README.md)

## Bring back shell expansion in config values

Speaking of shell, we fixed a regression with shell expansion in config values. So now you can do things like:

```json
"api_key": "$(vault kv get my/secret/token)"
```

The bonus here is that we're also using the embedded shell interpreter, so all the Bash-like things you expect to work here will.

> [!NOTE]
> If you're wondering how are we do all this awesome Bash stuff, it's with [mvdan/sh](https://github.com/mvdan/sh) from @mvdan. It's an absolutely solid project.

## Fixed: big file reads and updates

Crush has a size limit on certain operations to avoid the whole context window getting filled up rendering a session useless. There were some bugs around this which we fixed, tool-to-tool. So now, if your project is a single huge `index.php`, file Crush should be able to work it out just fine.

Special thanks to @taoeffect for working on this.

## Assisted-by, now in the style of the Linux Kernel 

The AI community is still figuring it out patterns and conventions, and we're adjusting as things go. We adjusted the `Assisted-by` trailer on Git commit messages to follow [the current convention of the Linux kernel](https://docs.kernel.org/process/coding-assistants.html#attribution) which seems to be where people are settling at the moment.

For those following along, it was:

```
Assisted-by: {modelName} via Crush <crush@charm.land>
```

And now it’s:

```
Assisted-by: Crush:{modelID}
```


## Smaller things

* Fixed expanding/collapsing thinking blocks with the keyboard.
* More reliable detection of image files attachment. Misrenamed your `.png` as `.jpg`? No problem, Crush will now look for the content instead of the extension.
* We adopted the `write` tool to allow the model to create empty files (thanks @vorticalbox).
* LSPs should now work better on Windows (thanks @sven2718).

Hope you crush your week!
The Charm™ team


## Changelog
### New!
* dbd40d82dccf4f6c13e67f37e9bb889a38fd1d39: feat(config): resolve MCP args and thread resolver through env/headers/args (@meowgorithm)
* f71645753fb8429356354b1354a58c439580d9bc: feat(config): resolve MCP url through shell expansion (@meowgorithm)
* 3b3f992f059643fa07612e5c143623e6986f338c: feat(hooks): propagate CRUSH/AGENT env vars to builtin shell (@meowgorithm)
* 22d6f44e0f4409c64e602841e6d90a485eb91053: feat(hooks): run via shell.Run instead of sh -c (@meowgorithm)
* 711d3a384f27bdf4548579292f8ae80d34e5e30f: feat(shell): add ExpandValue for config value shell expansion (@meowgorithm)
* 2e8e5365a2d20cc75c93b6e064efecf2edf4a1e7: feat(shell): shebang/binary/in-process dispatch handler (@meowgorithm)
* 010ca2f5bf4f0d039b6fe086f195838374582bd6: feat: add touch tool for empty files (@vorticalbox)
### Fixed
* 9d3466885813791119e6d3bf72460eb0b623f894: fix(agent): release activeRequests before publishing TypeAgentFinished (@sven2718)
* 61a9fcedcbaea1bceb66a2ad70cfeb66d60c8579: fix(config): individual errors on json parse (@taciturnaxolotl)
* 78088cd25c6803234a59aab46f50c8882a6e77f1: fix(lsp): update powernap with fix for lsps windows (#2862) (@andreynering)
* da262be6374f90da2f889cb8edcafe85ace85038: fix(schema): fix schema descriptions being cut off (@taciturnaxolotl)
* c9fd6be3e3720fccdc2e2afad55dcf504141cc52: fix(shell): convert path to posix path in tests (@taciturnaxolotl)
* af002dca8ef30c30d6f894dbbb8532e53e5ea326: fix(shell): ctx-aware jq builtin (@meowgorithm)
* 32410e29a464f7a4c5e0aa27046ee9a725fcb4ec: fix(shell): fix build error post-refactor (@meowgorithm)
* 2235a49d0dc5433e1d7015f90f10aa4d65864383: fix: limit view size checks to returned content (#2785) (@taoeffect)
* 24da509486e374024e9a03d27aab26bfdeef9cc8: fix: properly follow the `Assisted-by` header spec (#2871) (@andreynering)
### Docs
* d745ff590a6945c2d47bae67b304ad01a9f10dbc: docs(README): add note about shell expansion in MCP config (@meowgorithm)
* 1d42341dc89ce897280360612d345fdc26a776fc: docs(hooks): clarify relative paths (@taciturnaxolotl)
* 5dacf9e40568e6f027ff2964c49617ddd25d75bb: docs(hooks): document new embedded shell model (@meowgorithm)
* 06f43507a3254ef30f09674003000f42e6c22b0b: docs(skill): document shell expansion in crush-config skill (@meowgorithm)
* bcce66238bfe697f6ff8aef71197d8e4b19f426e: docs: document lenient shell expansion and security model (@meowgorithm)
* 45f7484b495a6ec4e155d38a82a9935bdb11d8a5: docs: update resolver godoc to match lenient default (@meowgorithm)
### Other stuff
* 3b0d5de2b831f76b9a03533142aad48c0a5bfc76: chore: auto-update files (@charmcli)
* b7607a0bdb6822c227d4e443889cfce57083292d: chore: auto-update files (@charmcli)
* 302f4ecf357152659b645a823613eff61dfb29cc: chore: modernize errors.As to errors.AsType (@meowgorithm)
* f23e9982cc216751e509e15b9a147477070478bb: config: fail provider header expansion loudly and drop empty values (@meowgorithm)
* f9134777c941001444eb57ecc81bfcb49c6366f5: config: remove unused environment variable resolver (@meowgorithm)
* 0da13d76995011ec0ba85bf19d444710f04fdf88: fix(tools/touch): gate outside-workingDir paths via permission prompt (@vorticalbox)
* ac79e5bb0343722d4403607ff6bc6072e6e61081: fix(tools/view): detect image mime type; don't rely on extension (#2757) (@meowgorithm)
* d7d25cf89fe2613851aa083267ccb0e4389f05a1: fix(ui/chat): make keyboard expand work for assistant thinking blocks (#2791) (@meowgorithm)
* 1f83559440dda9ef8654c1fe3cc8e48f98c143dd: lsp: expand shell variables in args and env (@meowgorithm)
* 9af81e357b90ee2ec569d1c3f536bce7c96cfcf3: merge: resolve conflicts with main (@taciturnaxolotl)
* c1352663ccbb330ea518feb45f53b2afee26aa56: refactor(config): make Resolved{Env,Headers} pure and error-returning (@meowgorithm)
* 5dc30cfac53a4db94cc0f81b0d8d8879afd72196: refactor(config): resolve shell vars via shell.ExpandValue (@meowgorithm)
* f6ef43e9de46e6cf04a44a901389806a57e61b3e: refactor(shell): extract stateless run entrypoint (@meowgorithm)
* 7da38da0b09f58ccbc623beb616ce2db80ad70e6: refactor(tools): remove touch tool; allow empty write content (@vorticalbox)
* abacef933667599de956fc9493166bf9f92c56f6: shell: switch config value expansion to lenient by default (@meowgorithm)

---

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

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

```bash
wget 'https://github.com/charmbracelet/crush/releases/download/v0.67.0/checksums.txt'
wget 'https://github.com/charmbracelet/crush/releases/download/v0.67.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).