Add --project flag to config set, config get, and config list CLI commands, enabling per-project configuration overrides stored under [project."<name>"] TOML tables in the global config file. Project-scoped resolution slots between environment variable and global levels in the ConfigService resolution chain. config list --project shows only overrides for the named project with source annotations. Implementation: - ConfigService: add set_project_value() and get_project_overrides() methods for TOML-backed project-scoped persistence and retrieval - CLI config commands: wire --project flag through set, get, and list subcommands; project-scoped list filters to overrides only - Database persistence: project-scoped config stored as alternative backend for projects not using TOML - Documentation: update docs/reference/config_resolution.md with project-scopable key lists, CLI examples, precedence diagram, and non-scopable key rejection behavior Tests: - Behave: 12 BDD scenarios in features/config_project_scope.feature covering set/get/list, precedence over global defaults, and non-scopable key rejection - Robot: 5 integration smoke tests in robot/config_project_scope.robot for end-to-end project-scoped round-trip verification - ASV: benchmarks/config_project_scope_bench.py measuring resolution overhead with project scope active All nox quality gates pass: lint, typecheck, unit_tests (7522 scenarios), integration_tests (Config Project Scope suite passed), and coverage at 98% line rate (threshold 97%). Closes #259
7.0 KiB
Configuration Resolution
CleverAgents resolves every configuration value through a 5-level precedence
chain. The first level that supplies a non-None value wins.
Resolution Order
| Priority | Source | Example |
|---|---|---|
| 1 (highest) | CLI flag | --format json, --data-dir /tmp |
| 2 | Environment variable | CLEVERAGENTS_CORE_LOG_LEVEL=WARNING |
| 3 | Project-scoped config | [project."myapp"] table in TOML |
| 4 | Global config file | ~/.cleveragents/config.toml |
| 5 (lowest) | Built-in default | Hardcoded in key registry |
$ export CLEVERAGENTS_CORE_LOG_LEVEL=WARNING
$ agents config set core.log_level DEBUG # writes to global config
$ agents config get core.log_level
# -> WARNING (env var at priority 2 beats global config at priority 4)
Key Format
Keys use hierarchical dot-separated names. The segment before the first dot is the group; everything after it is the key name within that group.
core.log.level
plan.budget.per-plan
provider.openai.api-key
Environment variable mapping follows the pattern
CLEVERAGENTS_<GROUP>_<KEY> with dots and hyphens replaced by underscores and
all characters uppercased:
core.log.level→CLEVERAGENTS_CORE_LOG_LEVELplan.budget.per-plan→CLEVERAGENTS_PLAN_BUDGET_PER_PLAN
Exception: provider.* credential keys use standard provider env vars
(see Provider Credentials).
Configuration Groups
| Group | Keys | Scope | Description |
|---|---|---|---|
core.* |
14 | Mixed | Core system settings — logging, data dirs, database, runtime env |
server.* |
4 | Global only | Server mode — bind host, port, TLS, workers |
actor.* |
5 | Mixed | Actor defaults — timeout, retry, concurrency |
plan.* |
8 | Mixed | Plan execution — budget, retries, auto-apply, timeout |
sandbox.* |
5 | Mixed | Sandbox and checkpointing — strategy, cleanup, max age |
index.* |
12 | Mixed | Code intelligence and indexing — backend, embedding model, dimensions |
context.* |
43 | All project-scopable | Context tier defaults — token limits, file caps, inclusion rules |
provider.* |
11 | Global only | LLM provider credentials and model defaults |
skills.* |
1 | Project-scopable | Agent Skills discovery paths |
Total: 103 registered keys.
Project-Scopable Keys
Keys marked as project-scopable can be overridden per-project in the
[project."<name>"] TOML table. When a project name is active, the resolver
checks this table at priority 3 before falling back to the global value.
Fully project-scopable groups:
context.*— all 43 keys
Partially project-scopable groups:
core.*—automation-profileplan.*—concurrency,max-child-depth,budget.per-plansandbox.*—strategy,checkpoint.enabledskills.*—agent_skills_paths
Never project-scopable:
server.*— applies globally to the running processprovider.*— credentials are always globalactor.*— actor defaults are globalindex.*— index backends are global
Setting project overrides
Use the --project flag on config set to store a value under the
project-scoped TOML table:
agents config set core.automation-profile manual --project my-project
agents config set plan.concurrency 16 --project my-project
Reading project-scoped values
When --project is provided, the resolver checks the project table at
priority 3 between environment variables and the global config file:
agents config get core.automation-profile --project my-project
Listing project overrides only
config list --project <name> shows only the keys that have been
explicitly overridden for that project — not the full resolved view:
agents config list --project my-project
Non-scopable key rejection
Attempting to set a non-project-scopable key (e.g. core.data-dir) via
--project raises an error:
$ agents config set core.data-dir /tmp --project my-project
Error: Key 'core.data-dir' is not project-scopable.
CLI Commands
agents config set
agents config set <key> <value> [--project <name>]
Writes a value to the global config file (or to the project-scoped table when
--project is supplied). The value is coerced to the key's registered type.
agents config get
agents config get <key> [--verbose] [--project <name>]
| Flag | Effect |
|---|---|
--verbose |
Print the full resolution chain showing every level |
--project |
Resolve as if inside the named project |
Verbose output example:
$ agents config get core.log.level --verbose
Key: core.log.level
Value: INFO
Source: default
Resolution chain (highest → lowest):
cli_flag → (not set)
env_var → (not set) [CLEVERAGENTS_CORE_LOG_LEVEL]
project → (not set)
global → (not set) [~/.cleveragents/config.toml]
default → INFO ← active
agents config list
agents config list [pattern] [--filter-values] [--show-secrets] [--project <name>]
| Flag | Effect |
|---|---|
pattern |
Glob filter on key names (e.g. core.*, plan.budget.*) |
--filter-values |
Only show keys whose resolved value differs from the default |
--show-secrets |
Unmask secret values (provider keys are masked by default) |
--project |
Resolve values in the context of the named project |
TOML File Format
~/.cleveragents/config.toml:
[core]
log_level = "DEBUG"
data_dir = "/var/lib/cleveragents"
[plan]
auto_apply = true
max_retries = 5
[sandbox]
strategy = "container"
[index]
enabled = true
backend = "faiss"
embedding_model = "text-embedding-3-small"
# Project-scoped overrides
[project."myapp"]
core.log_level = "WARNING"
plan.auto_apply = false
context.max_tokens = 64000
[project."data-pipeline"]
plan.budget.per_plan = 2.50
sandbox.strategy = "git_worktree"
Parent directories are created automatically on the first write.
Provider Credentials
Provider keys use standard provider environment variable names, not the
CLEVERAGENTS_* convention. This avoids requiring users to duplicate
credentials under a project-specific prefix.
| Key | Environment Variable |
|---|---|
provider.openai.api-key |
OPENAI_API_KEY |
provider.anthropic.api-key |
ANTHROPIC_API_KEY |
provider.google.api-key |
GOOGLE_API_KEY |
provider.azure.api-key |
AZURE_OPENAI_API_KEY |
provider.default-provider |
CLEVERAGENTS_PROVIDER_DEFAULT_PROVIDER |
provider.default-model |
CLEVERAGENTS_PROVIDER_DEFAULT_MODEL |
provider.temperature |
CLEVERAGENTS_PROVIDER_TEMPERATURE |
Provider credential values are masked in config list output by default.
Use --show-secrets to reveal them.
Validation
- Unknown keys produce an actionable error listing valid keys.
- Type mismatches raise
TypeErrorwith the expected type and actual value. - Boolean coercion accepts
true/false,1/0,yes/no(case-insensitive).