Commit log

f6b8592 feat: prepare alibaba migration to `/messages` (#3067)

Click to expand commit body
Add code to handle thinking for Alibaba via `/messages`, while still
keeping the code for `/chat/completions`. This way, it keeps working
before and after the migration on Catwalk.

Andrey Nering created

9e1c9d5 chore(deps): update fantasy

Andrey Nering created

ffaeec1 fix: avoid startup crash if unable to find default models (#3066)

Click to expand commit body
This can happen on edge cases when a models was removed from a provider
on Catwalk on Hyper.

Use the first model in the list instead crashing. This is not critical
to justify preventing Crush to start.

Andrey Nering created

154a323 chore(deps): bump the all group with 9 updates (#3061)

dependabot[bot] created

aeda508 chore(legal): @cak3ninja has signed the CLA

Charm created

3570ea6 chore: auto-update files

Charm created

81170ce refactor(config): replace reload booleans with reloadMu mutex

Click to expand commit body
Replace autoReloadDisabled and reloadInProgress boolean guards with a
sync.Mutex (reloadMu) to serialize ReloadFromDisk calls. autoReload
uses TryLock to skip redundant reloads when one is already in progress,
handling both concurrent auto-reloads after parallel writes and
re-entrant calls from configureProviders during a reload.

The autoReload comment now honestly documents the lost-update window:
if a write completes after the in-progress reload has already read the
config file, that change won't appear in memory until the next reload.
Callers needing guaranteed freshness should call ReloadFromDisk.

The load.go RemoveConfigField comment is corrected to explain that
Providers.Del keeps in-memory state consistent, not reload magic.

Also fixes an aliasing bug where append could mutate the package-level
defaultContextPaths slice by cloning it before prepending.

Kieran Klukas created

5b5f7b6 fix(config): sort SetConfigFields keys, remove redundant MkdirAll, rename test

Click to expand commit body
- Sort keys in SetConfigFields before applying sjson.Set for
  deterministic output regardless of map iteration order.
- Remove duplicate os.MkdirAll from atomicWrite (already done in
  lockConfig).
- Rename concurrent test to _concurrentInProcess to accurately reflect
  that it only exercises the in-process mutex, not the cross-process
  flock.

Kieran Klukas created

c83418d fix(oauth): stop fabricating token lifetime when expires_in is missing

Click to expand commit body
SetExpiresAt no longer silently defaults to 3600s when ExpiresIn is
zero or negative. If ExpiresAt was already set by the provider (some
return exp directly), it is preserved. Otherwise the token is marked
as immediately expired (ExpiresAt=0) so callers are forced to refresh
rather than operating with a guessed lifetime.

Also modernizes IsExpired to use max() for the buffer calculation.

Kieran Klukas created

9019775 fix(agent): centralize 401 retry logic and fix notify-on-success bug

Click to expand commit body
Add runWithUnauthorizedRetry helper that encapsulates the "run → 401
→ refresh credentials → retry" pattern. Migrate all three call sites
(runMessage, Summarize, sub-agent) to use it, preventing the retry
logic from drifting between callers.

Fix a bug in runMessage where the re-authenticate notification fired
unconditionally whenever the original error was a 401, even if the
retry succeeded. Now the notification only fires when the error is
still unauthorized after the retry attempt.

Kieran Klukas created

3cd88ac fix(agent): add 401 retry and reauth notification to sub-agent runs

Click to expand commit body
Sub-agents (agent tool, agentic fetch) had no retry logic on 401.
After moving the reauth notification from agent to coordinator,
sub-agent 401s would silently fail with no recovery or user prompt.

Add retry-after-unauthorized matching Run/Summarize, and publish
TypeReAuthenticate if the retry also fails so the user isn't left
with a dead agent and a confusing tool error.

Kieran Klukas created

d87a632 fix(oauth): harden IsExpired with minimum buffer and ExpiresIn guard

Click to expand commit body
Add 30-second minimum refresh buffer so short-lived tokens always have
a meaningful proactive refresh window. Guard against ExpiresIn=0 in
SetExpiresAt by defaulting to 3600s with a warning, preventing tokens
from being dead on arrival.

Kieran Klukas created

7ce0936 refactor(lock): add canonical internal/lock package, migrate db and cmd callers

Click to expand commit body
Introduce internal/lock as the single file-locking helper for Crush,
replacing the duplicated flock implementations in internal/db and
internal/cmd.

- lock.File(ctx, path) blocks until ctx cancels or lock acquired
  (context-aware deadline replaces hardcoded 5s timeout)
- lock.TryFile(path) returns ErrContended immediately if held
- Migrate internal/db.acquireDataDirLock to lock.TryFile
- Migrate internal/cmd.spawnAndWaitReady to lock.File(cmd.Context(), ...)
  (now respects Ctrl+C during spawn wait)
- Delete internal/db/datadirlock_{unix,windows}.go
- Delete internal/cmd/spawnlock_{other,windows}.go
- Add tests: acquire/release, contention, deadline, cancellation,
  concurrent mutual exclusion

Config store uses lock.File with a 5s context deadline, preserving
existing behavior while gaining context cancellation support.

Kieran Klukas created

23157b6 fix(agent): move reauth notification from agent to coordinator

Click to expand commit body
The agent was publishing TypeReAuthenticate immediately on 401, before
the coordinator had a chance to retry with a refreshed token. This
caused premature reauth popups even when the retry would succeed.

Move the notification to the coordinator so it only fires after
retryAfterUnauthorized fails.

Kieran Klukas created

d60a394 chore(legal): @ardi1s has signed the CLA

Charm created

cd592e8 v0.74.1

Andrey Nering created

c2be8cb fix: set non-interactive env vars in shell to prevent editor hangs (#3025)

Click to expand commit body
Sets TERM=xterm-256color, GIT_EDITOR=false, EDITOR=false, VISUAL=false,
JJ_EDITOR=false, JJ_PAGER=cat, PAGER=cat, GIT_PAGER=cat for all shell
executions.These are always applied regardless of the caller's environment
to prevent commands from spawning editors or pagers and hanging on a
nonexistent TTY.

Co-authored-by: Kieran Klukas <kieran@dunkirk.sh>

Tai Groot and Kieran Klukas created

b7f4ad6 fix(opencode): fix qwen3.7-max on opencode (#3040)

Click to expand commit body
* Closes #3027

This model only work on the Anthropic Messages API.

Andrey Nering created

a4181d6 fix(scrollbar): fix track position calculation

Andrey Nering created

0ee6c5b chore(legal): @xulongzhe has signed the CLA

Charm created

e14d47a fix(noninteractive): crush run reliability in client/server mode

Click to expand commit body
This fixes premature exits during tool use, hangs after certain
tool-calling stops, and issues when continuing into a session that is
already busy.

Co-Authored-By: Charm Crush <crush@charm.land>

Christian Rocha and Charm Crush created

7cd9f5b chore(deps): update charmtone (new colors, name updates) (#3034)

Christian Rocha created

5377b08 v0.74.0

Andrey Nering created

3780279 chore: auto-update files

Charm created

179a6f3 chore: fix(bedrock): apply region if given for aws config as well

Click to expand commit body
* https://github.com/charmbracelet/fantasy/pull/255

Andrey Nering created

57ae2b4 fix(bedrock): improve detection of pre-existing aws credentials

Andrey Nering created

36f0976 fix(bedrock): load aws credentials for bedrock europe

Click to expand commit body
* Follow-up of #3016

Andrey Nering created

82d57e5 fix(copilot): add additional responses models

Kieran Klukas created

7d92731 fix(server): one client's cancel should not send a 500 to others

Click to expand commit body
When two clients share a session, one client canceling the in flight
turn could return a 500 to the other client whose request was still
open. This makes a canceled run behave as a normal completion.
Cancelations still reach every subscribed client.

Co-Authored-By: Charm Crush <crush@charm.land>

Christian Rocha and Charm Crush created

b20b232 chore: gofumpt

Christian Rocha created

ed870ec fix(client): prevent event subscription panic on cancellation

Click to expand commit body
Co-Authored-By: Charm Crush <crush@charm.land>

Christian Rocha and Charm Crush created

d14f3b1 feat(tools): add diff view for denied tools

Kieran Klukas created

c8d0244 fix(ui): properly render model name in summarize

Kieran Klukas created

5e05c50 Merge pull request #3010 from charmbracelet/multi-client

Click to expand commit body
feat(server): multiplayer

Christian Rocha created

cc78648 Merge remote-tracking branch 'origin/main' into multi-client

Christian Rocha created

3f9bb5e chore: auto-update files

Charm created

3fa7d3f feat(notifications): migrate disabled and add picker

Kieran Klukas created

e7f5c68 feat(notifications): add configurable backend and bell support

Kieran Klukas created

6da5c95 feat: support notifications for ssh terminal

nghiant created

2bb5256 fix(server): release pooled DB on test shutdown so Windows can clean temp dir

Christian Rocha created

02b64cf v0.73.0

Andrey Nering created

4280f09 ci(labeler): add missing permission

Andrey Nering created

c6f8413 ci(labeler): do not use custom token

Andrey Nering created

ae20f1f feat: add aws bedrock europe (#3016)

Andrey Nering created

1db7629 fix(ui): improve model changed notification (#3015)

Click to expand commit body
* Capitalize "small" or "large" work (first word)
* Show model display name if available, and only fallback to model ID

Andrey Nering created

a1e4a7c fix(backend): fix data race in tests using captureDebugLogs

Click to expand commit body
The captureDebugLogs function was using a plain bytes.Buffer which is
not safe for concurrent access. When app.New spawns goroutines that log
asynchronously (e.g., mcp.Initialize), the test would read from the
buffer while goroutines were still writing to it, causing a data race.

This change introduces a syncBuffer type that wraps bytes.Buffer with
a mutex, making it safe for concurrent reads and writes.

Christian Rocha created

e530b1f Merge branch 'main' into multi-client

Christian Rocha created

61e4055 v0.72.0

Andrey Nering created

8ad3f5b feat(ui): show notification when toggling yolo mode (#3008)

Click to expand commit body
Display "Yolo mode enabled/disabled" via ReportInfo so the user gets
immediate visual feedback after pressing ctrl+y.

Assisted-by: Crush:claude-opus-4-6

Tai Groot created

2b941aa feat(ui): add ctrl+y keybinding to toggle yolo mode

Click to expand commit body
💘 Generated with Crush

Assisted-by: Crush:qwen3.7-max

Andrey Nering created