Skip to content

Commit 57e6edb

Browse files
author
dev-sw-1
committed
Support loading config from XDG_CONFIG paths
1 parent f8aa803 commit 57e6edb

File tree

5 files changed

+68
-14
lines changed

5 files changed

+68
-14
lines changed

aider/args.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -791,8 +791,8 @@ def get_parser(default_config_files, git_root):
791791
is_config_file=True,
792792
metavar="CONFIG_FILE",
793793
help=(
794-
"Specify the config file (default: search for .aider.conf.yml in git root, cwd"
795-
" or home directory)"
794+
"Specify the config file (default: search for .aider.conf.yml in git root, cwd, home"
795+
" dir, and for conf.yml in ~/.config/aider)"
796796
),
797797
).complete = shtab.FILE
798798
# This is a duplicate of the argument in the preparser and is a no-op by this time of

aider/args_formatter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ def _format_text(self, text):
9393
##########################################################
9494
# Sample .aider.conf.yml
9595
# This file lists *all* the valid configuration entries.
96-
# Place in your home dir, or at the root of your git repo.
96+
# Place in your home dir, git repo root, or $XDG_CONFIG_HOME/aider/conf.yml.
9797
##########################################################
9898
9999
# Note: You can only put OpenAI and Anthropic API keys in the YAML

aider/main.py

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,17 @@ def parse_lint_cmds(lint_cmds, io):
305305
def generate_search_path_list(default_file, git_root, command_line_file):
306306
files = []
307307
files.append(Path.home() / default_file) # homedir
308+
309+
xdg_config_home = os.environ.get("XDG_CONFIG_HOME")
310+
if not xdg_config_home:
311+
xdg_config_home = Path.home() / ".config"
312+
else:
313+
xdg_config_home = Path(xdg_config_home)
314+
xdg_aider_dir = xdg_config_home / "aider"
315+
files.append(xdg_aider_dir / default_file)
316+
if default_file.startswith("."):
317+
files.append(xdg_aider_dir / default_file[1:])
318+
308319
if git_root:
309320
files.append(Path(git_root) / default_file) # git root
310321
files.append(default_file)
@@ -465,15 +476,35 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
465476

466477
default_config_files = []
467478
try:
468-
default_config_files += [conf_fname.resolve()] # CWD
479+
default_config_files.append(conf_fname.resolve()) # CWD
469480
except OSError:
470481
pass
471482

472483
if git_root:
473484
git_conf = Path(git_root) / conf_fname # git root
474485
if git_conf not in default_config_files:
475486
default_config_files.append(git_conf)
476-
default_config_files.append(Path.home() / conf_fname) # homedir
487+
488+
xdg_config_home = os.environ.get("XDG_CONFIG_HOME")
489+
if not xdg_config_home:
490+
xdg_config_home = Path.home() / ".config"
491+
else:
492+
xdg_config_home = Path(xdg_config_home)
493+
xdg_aider_dir = xdg_config_home / "aider"
494+
495+
# Non-dotted version, higher precedence
496+
xdg_conf_no_dot = xdg_aider_dir / "conf.yml"
497+
if xdg_conf_no_dot not in default_config_files:
498+
default_config_files.append(xdg_conf_no_dot)
499+
500+
# Dotted version
501+
xdg_conf_dot = xdg_aider_dir / conf_fname
502+
if xdg_conf_dot not in default_config_files:
503+
default_config_files.append(xdg_conf_dot)
504+
505+
home_conf = Path.home() / conf_fname
506+
if home_conf not in default_config_files:
507+
default_config_files.append(home_conf) # homedir
477508
default_config_files = list(map(str, default_config_files))
478509

479510
parser = get_parser(default_config_files, git_root)

aider/website/docs/config/aider_conf.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@ description: How to configure aider with a YAML config file.
66

77
# YAML config file
88

9-
Most of aider's options can be set in an `.aider.conf.yml` file.
10-
Aider will look for a this file in these locations:
9+
Most of aider's options can be set in a YAML config file.
10+
Aider will look for config files in these locations:
1111

12-
- Your home directory.
13-
- The root of your git repo.
14-
- The current directory.
12+
- Your home directory (`~/.aider.conf.yml`).
13+
- Your XDG config home in `$XDG_CONFIG_HOME/aider/`. Aider will look for `conf.yml` and `.aider.conf.yml`. If `$XDG_CONFIG_HOME` is not set, it defaults to `~/.config`.
14+
- The root of your git repo (`.aider.conf.yml`).
15+
- The current directory (`.aider.conf.yml`).
1516

16-
If the files above exist, they will be loaded in that order. Files loaded last will take priority.
17+
If the files above exist, they will be loaded in that order. Settings from files loaded later take priority.
1718

1819
You can also specify the `--config <filename>` parameter, which will only load the one config file.
1920

tests/basic/test_main.py

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -533,8 +533,18 @@ def test_yaml_config_file_loading(self):
533533
cwd_config = cwd / ".aider.conf.yml"
534534
named_config = git_dir / "named.aider.conf.yml"
535535

536+
# Create XDG config files
537+
xdg_config_home = fake_home / ".config"
538+
os.environ["XDG_CONFIG_HOME"] = str(xdg_config_home)
539+
xdg_aider_dir = xdg_config_home / "aider"
540+
xdg_aider_dir.mkdir(parents=True)
541+
xdg_config_dot = xdg_aider_dir / ".aider.conf.yml"
542+
xdg_config_no_dot = xdg_aider_dir / "conf.yml"
543+
536544
cwd_config.write_text("model: gpt-4-32k\nmap-tokens: 4096\n")
537545
git_config.write_text("model: gpt-4\nmap-tokens: 2048\n")
546+
xdg_config_no_dot.write_text("model: xdg-no-dot\nmap-tokens: 600\n")
547+
xdg_config_dot.write_text("model: xdg-dot\nmap-tokens: 500\n")
538548
home_config.write_text("model: gpt-3.5-turbo\nmap-tokens: 1024\n")
539549
named_config.write_text("model: gpt-4-1106-preview\nmap-tokens: 8192\n")
540550

@@ -555,8 +565,6 @@ def test_yaml_config_file_loading(self):
555565
# Test loading from current working directory
556566
main(["--yes", "--exit"], input=DummyInput(), output=DummyOutput())
557567
_, kwargs = MockCoder.call_args
558-
print("kwargs:", kwargs) # Add this line for debugging
559-
self.assertIn("main_model", kwargs, "main_model key not found in kwargs")
560568
self.assertEqual(kwargs["main_model"].name, "gpt-4-32k")
561569
self.assertEqual(kwargs["map_tokens"], 4096)
562570

@@ -567,10 +575,24 @@ def test_yaml_config_file_loading(self):
567575
self.assertEqual(kwargs["main_model"].name, "gpt-4")
568576
self.assertEqual(kwargs["map_tokens"], 2048)
569577

570-
# Test loading from home directory
578+
# Test loading from XDG (no dot)
571579
git_config.unlink()
572580
main(["--yes", "--exit"], input=DummyInput(), output=DummyOutput())
573581
_, kwargs = MockCoder.call_args
582+
self.assertEqual(kwargs["main_model"].name, "xdg-no-dot")
583+
self.assertEqual(kwargs["map_tokens"], 600)
584+
585+
# Test loading from XDG (dot)
586+
xdg_config_no_dot.unlink()
587+
main(["--yes", "--exit"], input=DummyInput(), output=DummyOutput())
588+
_, kwargs = MockCoder.call_args
589+
self.assertEqual(kwargs["main_model"].name, "xdg-dot")
590+
self.assertEqual(kwargs["map_tokens"], 500)
591+
592+
# Test loading from home directory
593+
xdg_config_dot.unlink()
594+
main(["--yes", "--exit"], input=DummyInput(), output=DummyOutput())
595+
_, kwargs = MockCoder.call_args
574596
self.assertEqual(kwargs["main_model"].name, "gpt-3.5-turbo")
575597
self.assertEqual(kwargs["map_tokens"], 1024)
576598

0 commit comments

Comments
 (0)