From 2b222e3d951d317389f361f8f12be0fbc77267eb Mon Sep 17 00:00:00 2001 From: masroor-ahmad <75073229+masroor-ahmad@users.noreply.github.com> Date: Mon, 1 Dec 2025 18:16:36 +0100 Subject: [PATCH 1/9] fix: remove `max_tokens` minimum requirement to fix json schema issue (#1532) --- internal/config/config.go | 2 +- schema.json | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/config/config.go b/internal/config/config.go index fab908413c691eb6cf7a73ea44c31fdfb722d0b9..464dc14bc8c6d12cdf1db17c681c4faa68a59339 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -73,7 +73,7 @@ type SelectedModel struct { Think bool `json:"think,omitempty" jsonschema:"description=Enable thinking mode for Anthropic models that support reasoning"` // Overrides the default model configuration. - MaxTokens int64 `json:"max_tokens,omitempty" jsonschema:"description=Maximum number of tokens for model responses,minimum=1,maximum=200000,example=4096"` + MaxTokens int64 `json:"max_tokens,omitempty" jsonschema:"description=Maximum number of tokens for model responses,maximum=200000,example=4096"` Temperature *float64 `json:"temperature,omitempty" jsonschema:"description=Sampling temperature,minimum=0,maximum=1,example=0.7"` TopP *float64 `json:"top_p,omitempty" jsonschema:"description=Top-p (nucleus) sampling parameter,minimum=0,maximum=1,example=0.9"` TopK *int64 `json:"top_k,omitempty" jsonschema:"description=Top-k sampling parameter"` diff --git a/schema.json b/schema.json index 41809010df84ba774d734d81403a0cebb1579375..47740b9c18c8d2807c74557ffd9e21b5b6658ceb 100644 --- a/schema.json +++ b/schema.json @@ -555,7 +555,6 @@ "max_tokens": { "type": "integer", "maximum": 200000, - "minimum": 1, "description": "Maximum number of tokens for model responses", "examples": [ 4096 From d898662d3e37b0a88be032da68d914b8ff168ac6 Mon Sep 17 00:00:00 2001 From: Andrey Nering Date: Mon, 1 Dec 2025 17:19:00 -0300 Subject: [PATCH 2/9] feat: add `crush login claude` command (#1537) --- internal/cmd/login.go | 103 ++++++++++++++++++++++++++++++++++++++++++ internal/cmd/root.go | 1 + 2 files changed, 104 insertions(+) create mode 100644 internal/cmd/login.go diff --git a/internal/cmd/login.go b/internal/cmd/login.go new file mode 100644 index 0000000000000000000000000000000000000000..ac6510fdcc120950806e316cf24f653fe8270c43 --- /dev/null +++ b/internal/cmd/login.go @@ -0,0 +1,103 @@ +package cmd + +import ( + "cmp" + "context" + "fmt" + "os" + "os/signal" + "strings" + + "charm.land/lipgloss/v2" + "github.com/charmbracelet/crush/internal/config" + "github.com/charmbracelet/crush/internal/oauth/claude" + "github.com/spf13/cobra" +) + +var loginCmd = &cobra.Command{ + Aliases: []string{"auth"}, + Use: "login [platform]", + Short: "Login Crush to a platform", + Long: `Login Crush to a specified platform. +The platform should be provided as an argument. +Available platforms are: claude.`, + Example: ` +# Authenticate with Claude Code Max +crush login claude + `, + RunE: func(cmd *cobra.Command, args []string) error { + if len(args) > 1 { + return fmt.Errorf("wrong number of arguments") + } + if len(args) == 0 || args[0] == "" { + return cmd.Help() + } + + app, err := setupAppWithProgressBar(cmd) + if err != nil { + return err + } + defer app.Shutdown() + + switch args[0] { + case "anthropic", "claude": + return loginClaude() + default: + return fmt.Errorf("unknown platform: %s", args[0]) + } + }, +} + +func loginClaude() error { + ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill) + go func() { + <-ctx.Done() + cancel() + os.Exit(1) + }() + + verifier, challenge, err := claude.GetChallenge() + if err != nil { + return err + } + url, err := claude.AuthorizeURL(verifier, challenge) + if err != nil { + return err + } + fmt.Println("Open the following URL and follow the instructions to authenticate with Claude Code Max:") + fmt.Println() + fmt.Println(lipgloss.NewStyle().Hyperlink(url, "id=claude").Render(url)) + fmt.Println() + fmt.Println("Press enter to continue...") + if _, err := fmt.Scanln(); err != nil { + return err + } + + fmt.Println("Now paste and code from Anthropic and press enter...") + fmt.Println() + fmt.Print("> ") + var code string + for code == "" { + _, _ = fmt.Scanln(&code) + code = strings.TrimSpace(code) + } + + fmt.Println() + fmt.Println("Exchanging authorization code...") + token, err := claude.ExchangeToken(ctx, code, verifier) + if err != nil { + return err + } + + cfg := config.Get() + if err := cmp.Or( + cfg.SetConfigField("providers.anthropic.api_key", token.AccessToken), + cfg.SetConfigField("providers.anthropic.oauth", token), + ); err != nil { + return err + } + + fmt.Println() + fmt.Println("You're now authenticated with Claude Code Max!") + return nil +} diff --git a/internal/cmd/root.go b/internal/cmd/root.go index e98fd9d3b6bc7fcb59d1db739fd550f31e017b48..e1aed5fe2cfe16cb1c8274752157339306276c7d 100644 --- a/internal/cmd/root.go +++ b/internal/cmd/root.go @@ -43,6 +43,7 @@ func init() { updateProvidersCmd, logsCmd, schemaCmd, + loginCmd, ) } From 53e2277d64a4a4b9898ec3a5580a3ad25b42f299 Mon Sep 17 00:00:00 2001 From: Carlos Alexandro Becker Date: Mon, 1 Dec 2025 19:38:32 -0300 Subject: [PATCH 4/9] ci: fix cosign (#1538) Signed-off-by: Carlos Alexandro Becker --- .goreleaser.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index 1bfc9202745776736b1483f9e697292d9f90386b..0d628df8946ec7df4a8823570b5cb26250831cd0 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -235,11 +235,10 @@ nfpms: signs: - cmd: cosign - certificate: "${artifact}.pem" + signature: "${artifact}.sigstore.json" args: - sign-blob - - "--output-certificate=${certificate}" - - "--output-signature=${signature}" + - "--bundle=${signature}" - "${artifact}" - "--yes" artifacts: checksum From 7272a90ed5f5036b69acd4e800abab26b3ace67e Mon Sep 17 00:00:00 2001 From: Carlos Alexandro Becker Date: Tue, 2 Dec 2025 08:44:27 -0300 Subject: [PATCH 6/9] fix: add ValidArgs and Args to login cmd (#1540) Signed-off-by: Carlos Alexandro Becker --- internal/cmd/login.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/internal/cmd/login.go b/internal/cmd/login.go index ac6510fdcc120950806e316cf24f653fe8270c43..00c155cbfd23a95005da10a60f9ea36ab50cbd7d 100644 --- a/internal/cmd/login.go +++ b/internal/cmd/login.go @@ -25,6 +25,11 @@ Available platforms are: claude.`, # Authenticate with Claude Code Max crush login claude `, + ValidArgs: []cobra.Completion{ + "claude", + "anthropic", + }, + Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { if len(args) > 1 { return fmt.Errorf("wrong number of arguments") From 2c97eb8a5ba3a25d4ebc703cb2ed154b8c7afd42 Mon Sep 17 00:00:00 2001 From: Andrey Nering Date: Wed, 26 Nov 2025 16:40:52 -0300 Subject: [PATCH 7/9] feat: show progress bar on iterm2 and rio --- go.mod | 1 + go.sum | 2 ++ internal/stringext/string.go | 11 +++++++++++ internal/tui/tui.go | 18 +++++++++++++++--- 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f291838eba7bca3a9c25b061f5974a4d7885b6ce..1d1403b4511c79f64657fa3d9d053cc7921e44ac 100644 --- a/go.mod +++ b/go.mod @@ -54,6 +54,7 @@ require ( github.com/stretchr/testify v1.11.1 github.com/tidwall/sjson v1.2.5 github.com/zeebo/xxh3 v1.0.2 + golang.org/x/mod v0.30.0 golang.org/x/sync v0.18.0 golang.org/x/text v0.31.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 diff --git a/go.sum b/go.sum index aaeba2379bc8d66cdbbbed1cfe491372abf9e76c..79efd285e06d69d320f089fe6d6af3f46bbd1106 100644 --- a/go.sum +++ b/go.sum @@ -378,6 +378,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk= +golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= diff --git a/internal/stringext/string.go b/internal/stringext/string.go index 03456db93bc148f7c77e52da3c493c94fa79624f..9383ce1d78b8f0a776fc533526ee961d0123d734 100644 --- a/internal/stringext/string.go +++ b/internal/stringext/string.go @@ -1,6 +1,8 @@ package stringext import ( + "strings" + "golang.org/x/text/cases" "golang.org/x/text/language" ) @@ -8,3 +10,12 @@ import ( func Capitalize(text string) string { return cases.Title(language.English, cases.Compact).String(text) } + +func ContainsAny(str string, args ...string) bool { + for _, arg := range args { + if strings.Contains(str, arg) { + return true + } + } + return false +} diff --git a/internal/tui/tui.go b/internal/tui/tui.go index 2fbd9f612934511d18e5d8c0a35f042ebbb8d82a..45f0ae5ec410e85b3d30d620b4db5c499cff09c3 100644 --- a/internal/tui/tui.go +++ b/internal/tui/tui.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "math/rand" + "regexp" "slices" "strings" "time" @@ -17,6 +18,7 @@ import ( "github.com/charmbracelet/crush/internal/event" "github.com/charmbracelet/crush/internal/permission" "github.com/charmbracelet/crush/internal/pubsub" + "github.com/charmbracelet/crush/internal/stringext" cmpChat "github.com/charmbracelet/crush/internal/tui/components/chat" "github.com/charmbracelet/crush/internal/tui/components/chat/splash" "github.com/charmbracelet/crush/internal/tui/components/completions" @@ -34,6 +36,7 @@ import ( "github.com/charmbracelet/crush/internal/tui/page/chat" "github.com/charmbracelet/crush/internal/tui/styles" "github.com/charmbracelet/crush/internal/tui/util" + "golang.org/x/mod/semver" "golang.org/x/text/cases" "golang.org/x/text/language" ) @@ -120,10 +123,19 @@ func (a *appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { a.sendProgressBar = slices.Contains(msg, "WT_SESSION") } case tea.TerminalVersionMsg: + if a.sendProgressBar { + return a, nil + } termVersion := strings.ToLower(msg.Name) - // Only enable progress bar for the following terminals. - if !a.sendProgressBar { - a.sendProgressBar = strings.Contains(termVersion, "ghostty") + switch { + case stringext.ContainsAny(termVersion, "ghostty", "rio"): + a.sendProgressBar = true + case strings.Contains(termVersion, "iterm2"): + // iTerm2 supports progress bars from version v3.6.6 + matches := regexp.MustCompile(`^iterm2 (\d+\.\d+\.\d+)$`).FindStringSubmatch(termVersion) + if len(matches) == 2 && semver.Compare("v"+matches[1], "v3.6.6") >= 0 { + a.sendProgressBar = true + } } return a, nil case tea.KeyboardEnhancementsMsg: From 59a4b4759e7f9ca79555047ef26f97659d860938 Mon Sep 17 00:00:00 2001 From: Andrey Nering Date: Wed, 26 Nov 2025 16:46:32 -0300 Subject: [PATCH 8/9] refactor: use contains any --- internal/cmd/root.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/internal/cmd/root.go b/internal/cmd/root.go index e1aed5fe2cfe16cb1c8274752157339306276c7d..17c23aeabfd6aaca438d30a0d59cf014c3134f4b 100644 --- a/internal/cmd/root.go +++ b/internal/cmd/root.go @@ -19,6 +19,7 @@ import ( "github.com/charmbracelet/crush/internal/config" "github.com/charmbracelet/crush/internal/db" "github.com/charmbracelet/crush/internal/event" + "github.com/charmbracelet/crush/internal/stringext" termutil "github.com/charmbracelet/crush/internal/term" "github.com/charmbracelet/crush/internal/tui" "github.com/charmbracelet/crush/internal/version" @@ -275,9 +276,5 @@ func shouldQueryTerminalVersion(env uv.Environ) bool { return (!okTermProg && !okSSHTTY) || (!strings.Contains(termProg, "Apple") && !okSSHTTY) || // Terminals that do support XTVERSION. - strings.Contains(termType, "ghostty") || - strings.Contains(termType, "wezterm") || - strings.Contains(termType, "alacritty") || - strings.Contains(termType, "kitty") || - strings.Contains(termType, "rio") + stringext.ContainsAny(termType, "alacritty", "ghostty", "kitty", "rio", "wezterm") } From 431d6fb4e380ac0157020d716d6bef51246386b2 Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Tue, 2 Dec 2025 11:30:13 -0500 Subject: [PATCH 9/9] chore: bump ultraviolet to fix rendering issues with unnecessary cursor movements and erasing line background color --- go.mod | 4 ++-- go.sum | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 1d1403b4511c79f64657fa3d9d053cc7921e44ac..c8a4865334903e3244f1a0198c3683d3d75f6056 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.25.0 require ( charm.land/bubbles/v2 v2.0.0-rc.1 - charm.land/bubbletea/v2 v2.0.0-rc.2.0.20251126220703-2a0096c500a7 + charm.land/bubbletea/v2 v2.0.0-rc.2.0.20251202162339-5fa38b798f16 charm.land/fantasy v0.3.2 charm.land/lipgloss/v2 v2.0.0-beta.3.0.20251119143523-0334bb4562ca charm.land/x/vcr v0.1.1 @@ -21,7 +21,7 @@ require ( github.com/charmbracelet/fang v0.4.4 github.com/charmbracelet/glamour/v2 v2.0.0-20251106195642-800eb8175930 github.com/charmbracelet/log/v2 v2.0.0-20251106192421-eb64aaa963a0 - github.com/charmbracelet/ultraviolet v0.0.0-20251116181749-377898bcce38 + github.com/charmbracelet/ultraviolet v0.0.0-20251202162030-ecc8c1ae4b2b github.com/charmbracelet/x/ansi v0.11.2 github.com/charmbracelet/x/exp/charmtone v0.0.0-20250708181618-a60a724ba6c3 github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f diff --git a/go.sum b/go.sum index 79efd285e06d69d320f089fe6d6af3f46bbd1106..693db05169cf844c0f0926f9abed05f55b3bfeb2 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,8 @@ charm.land/bubbles/v2 v2.0.0-rc.1 h1:EiIFVAc3Zi/yY86td+79mPhHR7AqZ1OxF+6ztpOCRaM charm.land/bubbles/v2 v2.0.0-rc.1/go.mod h1:5AbN6cEd/47gkEf8TgiQ2O3RZ5QxMS14l9W+7F9fPC4= charm.land/bubbletea/v2 v2.0.0-rc.2.0.20251126220703-2a0096c500a7 h1:3qsObfEm0WuACFhe3MSTPX8QByjVcjWkZDO4o2VWFpc= charm.land/bubbletea/v2 v2.0.0-rc.2.0.20251126220703-2a0096c500a7/go.mod h1:IXFmnCnMLTWw/KQ9rEatSYqbAPAYi8kA3Yqwa1SFnLk= +charm.land/bubbletea/v2 v2.0.0-rc.2.0.20251202162339-5fa38b798f16 h1:9iVAss7WF8Ax5QBzmZE77aA08JbOMuDpbEhl/Uvc3Eo= +charm.land/bubbletea/v2 v2.0.0-rc.2.0.20251202162339-5fa38b798f16/go.mod h1:Vsh7/MLC7LQ2Ab8H63SXm6yD/L6o4HDvhdD/IrIRXrU= charm.land/fantasy v0.3.2 h1:yHTsSZ25LcICMRw3xzdz3OkaZtDQch+B5ljJo17HxgU= charm.land/fantasy v0.3.2/go.mod h1:sV8Ns/JTJHOaYOHPgVRDugMheAyxsW/nmdpVGrycYEk= charm.land/lipgloss/v2 v2.0.0-beta.3.0.20251119143523-0334bb4562ca h1:6bVc8OFotCS4sS7HKqxTudP7yn8Y0ODR6df2pdlY/+s= @@ -100,6 +102,8 @@ github.com/charmbracelet/log/v2 v2.0.0-20251106192421-eb64aaa963a0 h1:lxHzxsHd4P github.com/charmbracelet/log/v2 v2.0.0-20251106192421-eb64aaa963a0/go.mod h1:Q7oMtlboDPnnrYiJDXNwdWmJblOmuOnycPKczlVju6I= github.com/charmbracelet/ultraviolet v0.0.0-20251116181749-377898bcce38 h1:7Rs87fbKJoIIxsQS8YKJYGYa0tlsDwwb0twQjV1KB+g= github.com/charmbracelet/ultraviolet v0.0.0-20251116181749-377898bcce38/go.mod h1:6lfcr3MNP+kZR25sF1nQwJFuQnNYBlFy3PGX5rvslXc= +github.com/charmbracelet/ultraviolet v0.0.0-20251202162030-ecc8c1ae4b2b h1:jY1J0PcfetoB1uJ+w8rd86gUFSpKpJJI35gnfpKF5hg= +github.com/charmbracelet/ultraviolet v0.0.0-20251202162030-ecc8c1ae4b2b/go.mod h1:Y6kE2GzHfkyQQVCSL9r2hwokSrIlHGzZG+71+wDYSZI= github.com/charmbracelet/x/ansi v0.11.2 h1:XAG3FSjiVtFvgEgGrNBkCNNYrsucAt8c6bfxHyROLLs= github.com/charmbracelet/x/ansi v0.11.2/go.mod h1:9tY2bzX5SiJCU0iWyskjBeI2BRQfvPqI+J760Mjf+Rg= github.com/charmbracelet/x/exp/charmtone v0.0.0-20250708181618-a60a724ba6c3 h1:1xwHZg6eMZ9Wv5TE1UGub6ARubyOd1Lo5kPUI/6VL50=