@@ -11,6 +11,7 @@ import (
1111
1212 "github.com/charmbracelet/crush/internal/llm/models"
1313 "github.com/charmbracelet/crush/internal/logging"
14+ "github.com/spf13/afero"
1415 "github.com/spf13/viper"
1516)
1617
@@ -201,21 +202,62 @@ func Load(workingDir string, debug bool) (*Config, error) {
201202 return cfg, nil
202203}
203204
205+type configFinder struct {
206+ appName string
207+ dotPrefix bool
208+ paths []string
209+}
210+
211+func (f configFinder) Find(fsys afero.Fs) ([]string, error) {
212+ var configFiles []string
213+ configName := fmt.Sprintf("%s.json", f.appName)
214+ if f.dotPrefix {
215+ configName = fmt.Sprintf(".%s.json", f.appName)
216+ }
217+ paths := []string{}
218+ for _, p := range f.paths {
219+ if p == "" {
220+ continue
221+ }
222+ paths = append(paths, os.ExpandEnv(p))
223+ }
224+
225+ for _, path := range paths {
226+ if path == "" {
227+ continue
228+ }
229+
230+ configPath := filepath.Join(path, configName)
231+ if exists, err := afero.Exists(fsys, configPath); err == nil && exists {
232+ configFiles = append(configFiles, configPath)
233+ }
234+ }
235+ return configFiles, nil
236+}
237+
204238// configureViper sets up viper's configuration paths and environment variables.
205239func configureViper() {
206− viper.SetConfigName(fmt.Sprintf(".%s", appName))
207240 viper.SetConfigType("json")
208241
209− // Unix-style paths
210− viper.AddConfigPath("$HOME")
211− viper.AddConfigPath(fmt.Sprintf("$XDG_CONFIG_HOME/%s", appName))
212− viper.AddConfigPath(fmt.Sprintf("$HOME/.config/%s", appName))
213−
214− // Windows-style paths
215− viper.AddConfigPath(fmt.Sprintf("$USERPROFILE"))
216− viper.AddConfigPath(fmt.Sprintf("$APPDATA/%s", appName))
217− viper.AddConfigPath(fmt.Sprintf("$LOCALAPPDATA/%s", appName))
218−
242+ // Create the three finders
243+ windowsFinder := configFinder{appName: appName, dotPrefix: false, paths: []string{
244+ "$USERPROFILE",
245+ fmt.Sprintf("$APPDATA/%s", appName),
246+ fmt.Sprintf("$LOCALAPPDATA/%s", appName),
247+ }}
248+
249+ unixFinder := configFinder{appName: appName, dotPrefix: false, paths: []string{
250+ "$HOME",
251+ fmt.Sprintf("$XDG_CONFIG_HOME/%s", appName),
252+ fmt.Sprintf("$HOME/.config/%s", appName),
253+ }}
254+
255+ localFinder := configFinder{appName: appName, dotPrefix: true, paths: []string{
256+ ".",
257+ }}
258+
259+ // Use all finders with viper
260+ viper.SetOptions(viper.WithFinder(viper.Finders(windowsFinder, unixFinder, localFinder)))
219261 viper.SetEnvPrefix(strings.ToUpper(appName))
220262 viper.AutomaticEnv()
221263}