Skip to content

Commit 6837061

Browse files
committed
feat(cli): add BALATROLLM_CONFIG env var support
Add support for specifying the config file path via BALATROLLM_CONFIG environment variable. This allows users to set the config path in their environment instead of passing it as a CLI argument. - Add _resolve_config_path() function to handle precedence logic - CLI positional argument takes precedence over env var - Update docs/cli.md with usage examples and notes - Add unit tests for the new functionality Closes #57 https://claude.ai/code/session_01665SJCL7QdWY2kiettyqV3
1 parent 3aff5db commit 6837061

3 files changed

Lines changed: 87 additions & 1 deletion

File tree

docs/cli.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,19 @@ This means CLI flags override config file values, which override environment var
2222
| -------- | -------- | ------------------------------- |
2323
| `CONFIG` | No | Path to YAML configuration file |
2424

25+
!!! note "BALATROLLM_CONFIG Environment Variable"
26+
27+
The configuration file path can also be specified via the `BALATROLLM_CONFIG` environment variable:
28+
29+
```bash
30+
export BALATROLLM_CONFIG="config/example.yaml"
31+
balatrollm --model openai/gpt-5
32+
```
33+
34+
This is the **only** `BALATROLLM_*` environment variable that does not have a corresponding CLI flag — the user can simply provide the config file path as a positional argument instead.
35+
36+
**Precedence:** If both the `CONFIG` argument and `BALATROLLM_CONFIG` are provided, the CLI argument takes precedence and `BALATROLLM_CONFIG` is ignored.
37+
2538
## Options
2639

2740
| CLI Flag | Environment Variable | Default | Description |
@@ -59,6 +72,10 @@ balatrollm --model openai/gpt-5
5972
# Run with configuration file
6073
balatrollm config/example.yaml
6174

75+
# Run with configuration file via environment variable
76+
export BALATROLLM_CONFIG="config/example.yaml"
77+
balatrollm --model openai/gpt-5
78+
6279
# Run with config file and override specific options
6380
balatrollm config/example.yaml --model openai/gpt-5 --seed BBBBBBB
6481
```

src/balatrollm/cli.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,15 @@
22

33
import argparse
44
import asyncio
5+
import os
56
import sys
67
from pathlib import Path
78

89
from .config import Config, Task
910

11+
# Environment variable for config file path (special: no corresponding CLI flag)
12+
BALATROLLM_CONFIG_ENV = "BALATROLLM_CONFIG"
13+
1014

1115
def create_parser() -> argparse.ArgumentParser:
1216
"""Create the argument parser."""
@@ -83,14 +87,27 @@ async def execute(config: Config, tasks: list[Task]) -> int:
8387
views_server.stop()
8488

8589

90+
def _resolve_config_path(args_config: Path | None) -> Path | None:
91+
"""Resolve config path: CLI arg takes precedence over BALATROLLM_CONFIG env var."""
92+
if args_config is not None:
93+
return args_config
94+
env_config = os.environ.get(BALATROLLM_CONFIG_ENV)
95+
if env_config:
96+
return Path(env_config)
97+
return None
98+
99+
86100
def main() -> None:
87101
"""Main entry point for balatrollm command."""
88102
parser = create_parser()
89103
args = parser.parse_args()
90104

105+
# Resolve config path: CLI arg > BALATROLLM_CONFIG env var
106+
config_path = _resolve_config_path(args.config)
107+
91108
# Build config with precedence: env < yaml < args
92109
try:
93-
config = Config.load(yaml_path=args.config, args=args)
110+
config = Config.load(yaml_path=config_path, args=args)
94111
config.validate()
95112
except (FileNotFoundError, ValueError) as e:
96113
parser.error(str(e))

tests/unit/test_cli.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
"""Unit tests for the cli module."""
2+
3+
from pathlib import Path
4+
5+
import pytest
6+
7+
from balatrollm.cli import BALATROLLM_CONFIG_ENV, _resolve_config_path
8+
9+
# ============================================================================
10+
# Test _resolve_config_path
11+
# ============================================================================
12+
13+
14+
class TestResolveConfigPath:
15+
"""Tests for _resolve_config_path helper function."""
16+
17+
def test_cli_arg_returns_arg(self) -> None:
18+
"""CLI argument should be returned when provided."""
19+
cli_path = Path("/some/config.yaml")
20+
result = _resolve_config_path(cli_path)
21+
assert result == cli_path
22+
23+
def test_env_var_used_when_no_cli_arg(
24+
self, monkeypatch: pytest.MonkeyPatch
25+
) -> None:
26+
"""BALATROLLM_CONFIG env var should be used when CLI arg is None."""
27+
monkeypatch.setenv(BALATROLLM_CONFIG_ENV, "/env/config.yaml")
28+
result = _resolve_config_path(None)
29+
assert result == Path("/env/config.yaml")
30+
31+
def test_cli_arg_takes_precedence_over_env(
32+
self, monkeypatch: pytest.MonkeyPatch
33+
) -> None:
34+
"""CLI argument should take precedence over BALATROLLM_CONFIG env var."""
35+
monkeypatch.setenv(BALATROLLM_CONFIG_ENV, "/env/config.yaml")
36+
cli_path = Path("/cli/config.yaml")
37+
result = _resolve_config_path(cli_path)
38+
assert result == cli_path
39+
40+
def test_none_when_no_cli_arg_and_no_env(
41+
self, monkeypatch: pytest.MonkeyPatch
42+
) -> None:
43+
"""None should be returned when neither CLI arg nor env var is set."""
44+
monkeypatch.delenv(BALATROLLM_CONFIG_ENV, raising=False)
45+
result = _resolve_config_path(None)
46+
assert result is None
47+
48+
def test_empty_env_var_returns_none(self, monkeypatch: pytest.MonkeyPatch) -> None:
49+
"""Empty BALATROLLM_CONFIG env var should be treated as unset."""
50+
monkeypatch.setenv(BALATROLLM_CONFIG_ENV, "")
51+
result = _resolve_config_path(None)
52+
assert result is None

0 commit comments

Comments
 (0)