1package config
2
3import (
4 "slices"
5 "strings"
6
7 "github.com/charmbracelet/crush/internal/fur/provider"
8)
9
10const (
11 appName = "crush"
12 defaultDataDirectory = ".crush"
13 defaultLogLevel = "info"
14)
15
16var defaultContextPaths = []string{
17 ".github/copilot-instructions.md",
18 ".cursorrules",
19 ".cursor/rules/",
20 "CLAUDE.md",
21 "CLAUDE.local.md",
22 "GEMINI.md",
23 "gemini.md",
24 "crush.md",
25 "crush.local.md",
26 "Crush.md",
27 "Crush.local.md",
28 "CRUSH.md",
29 "CRUSH.local.md",
30}
31
32type SelectedModel struct {
33 // The model id as used by the provider API.
34 // Required.
35 Model string `json:"model"`
36 // The model provider, same as the key/id used in the providers config.
37 // Required.
38 Provider string `json:"provider"`
39
40 // Only used by models that use the openai provider and need this set.
41 ReasoningEffort string `json:"reasoning_effort,omitempty"`
42
43 // Overrides the default model configuration.
44 MaxTokens int64 `json:"max_tokens,omitempty"`
45
46 // Used by anthropic models that can reason to indicate if the model should think.
47 Think bool `json:"think,omitempty"`
48}
49
50type ProviderConfig struct {
51 // The provider's API endpoint.
52 BaseURL string `json:"base_url,omitempty"`
53 // The provider type, e.g. "openai", "anthropic", etc. if empty it defaults to openai.
54 Type provider.Type `json:"type,omitempty"`
55 // The provider's API key.
56 APIKey string `json:"api_key,omitempty"`
57 // Marks the provider as disabled.
58 Disable bool `json:"disable,omitempty"`
59
60 // Extra headers to send with each request to the provider.
61 ExtraHeaders map[string]string
62
63 // Used to pass extra parameters to the provider.
64 ExtraParams map[string]string `json:"-"`
65
66 // The provider models
67 Models []provider.Model `json:"models,omitempty"`
68}
69
70type MCPType string
71
72const (
73 MCPStdio MCPType = "stdio"
74 MCPSse MCPType = "sse"
75 MCPHttp MCPType = "http"
76)
77
78type MCPConfig struct {
79 Command string `json:"command,omitempty" `
80 Env []string `json:"env,omitempty"`
81 Args []string `json:"args,omitempty"`
82 Type MCPType `json:"type"`
83 URL string `json:"url,omitempty"`
84
85 // TODO: maybe make it possible to get the value from the env
86 Headers map[string]string `json:"headers,omitempty"`
87}
88
89type LSPConfig struct {
90 Disabled bool `json:"enabled,omitempty"`
91 Command string `json:"command"`
92 Args []string `json:"args,omitempty"`
93 Options any `json:"options,omitempty"`
94}
95
96type TUIOptions struct {
97 CompactMode bool `json:"compact_mode,omitempty"`
98 // Here we can add themes later or any TUI related options
99}
100
101type Options struct {
102 ContextPaths []string `json:"context_paths,omitempty"`
103 TUI *TUIOptions `json:"tui,omitempty"`
104 Debug bool `json:"debug,omitempty"`
105 DebugLSP bool `json:"debug_lsp,omitempty"`
106 DisableAutoSummarize bool `json:"disable_auto_summarize,omitempty"`
107 // Relative to the cwd
108 DataDirectory string `json:"data_directory,omitempty"`
109}
110
111type MCPs map[string]MCPConfig
112
113type MCP struct {
114 Name string `json:"name"`
115 MCP MCPConfig `json:"mcp"`
116}
117
118func (m MCPs) Sorted() []MCP {
119 sorted := make([]MCP, 0, len(m))
120 for k, v := range m {
121 sorted = append(sorted, MCP{
122 Name: k,
123 MCP: v,
124 })
125 }
126 slices.SortFunc(sorted, func(a, b MCP) int {
127 return strings.Compare(a.Name, b.Name)
128 })
129 return sorted
130}
131
132type LSPs map[string]LSPConfig
133
134type LSP struct {
135 Name string `json:"name"`
136 LSP LSPConfig `json:"lsp"`
137}
138
139func (l LSPs) Sorted() []LSP {
140 sorted := make([]LSP, 0, len(l))
141 for k, v := range l {
142 sorted = append(sorted, LSP{
143 Name: k,
144 LSP: v,
145 })
146 }
147 slices.SortFunc(sorted, func(a, b LSP) int {
148 return strings.Compare(a.Name, b.Name)
149 })
150 return sorted
151}
152
153// Config holds the configuration for crush.
154type Config struct {
155 // We currently only support large/small as values here.
156 Models map[string]SelectedModel `json:"models,omitempty"`
157
158 // The providers that are configured
159 Providers map[string]ProviderConfig `json:"providers,omitempty"`
160
161 MCP MCPs `json:"mcp,omitempty"`
162
163 LSP LSPs `json:"lsp,omitempty"`
164
165 Options *Options `json:"options,omitempty"`
166
167 // Internal
168 workingDir string `json:"-"`
169}
170
171func (c *Config) WorkingDir() string {
172 return c.workingDir
173}