Automation Environment Install and Configuration
This page explains how to get the mailagent CLI running inside CI / cron / an agent runner, and how to understand its configuration load order — the latter directly determines “whether the value I set actually took effect.”
Installation
Section titled “Installation”The CLI is installed via pip’s optional-dependencies. From the repository root (with a venv already present), run:
source venv/bin/activatepip install -e ".[cli,dev]"# cli: typer / rich / pyyaml# dev: pytest + jsonschema>=4.18 + referencing (needed for schema validation runs)Verify:
which mailagent # should be <project>/venv/bin/mailagentmailagent --version # prints the version numbermailagent --help # lists the 10 groups + global flagsConfiguration Precedence Chain
Section titled “Configuration Precedence Chain”At startup, the CLI loads configuration in the following order, with later sources overriding earlier ones:
| Precedence | Source | Notes |
|---|---|---|
| 1 (lowest) | ~/.config/mailagent/config.toml | User-level, optional |
| 2 | <project>/.env | The pydantic Config shared with the service |
| 3 | --config PATH | Config file explicitly specified on the CLI |
| 4 | MAILAGENT_* environment variables | e.g. MAILAGENT_CLI_API_KEY |
| 5 (highest) | Command-line flags | --db-path / --api-key, etc. |
Example: mailagent --config x.toml email get 53675 uses the db_path from x.toml rather than from .env.
# db-path override: temporarily point at another database (e.g. the app DB vs the main-repo PM2 DB)mailagent --db-path ~/Library/Application\ Support/mailagent-frontend/data/sync_store.db \ -o json email list --limit 5
# API key override (write command): env beats .env, flag beats envMAILAGENT_CLI_API_KEY=xxx mailagent email flag 53675 --is-readmailagent --api-key xxx email flag 53675 --is-readThe load_cli_config() Factory — Why Configuration Is Guaranteed to Take Effect
Section titled “The load_cli_config() Factory — Why Configuration Is Guaranteed to Take Effect”The CLI does not use a module-level singleton from src.config import config. The reason: pydantic Settings loads .env immediately at import time, which makes the --config flag arrive too late to override it.
The CLI instead uses an explicit factory, load_cli_config(config_path, env_overrides, flag_overrides): it reconstructs a fresh Config instance at every startup following the precedence chain above. This means:
- The
--config/--db-path/--api-keyyou pass are guaranteed to take effect and won’t be overridden by an import-time-locked.env. - Server-side processes (
main.py/ pm2) still use the global singleton and don’t interfere with the CLI path — the CLI is a short-lived process that loads cleanly each time.
MAILAGENT_CLI_API_KEY
Section titled “MAILAGENT_CLI_API_KEY”Write commands require authentication (read commands do not). In an automation environment, inject it via an environment variable — don’t put it on the --api-key command line (which ends up in shell history / the process list):
# CI / cron: inject the env var from the secret storeexport MAILAGENT_CLI_API_KEY="$(cat /run/secrets/mailagent_cli_key)"mailagent email flag 53675 --is-read # automatically uses the key from envThe server-side .env also sets a MAILAGENT_CLI_API_KEY of the same name, and the CLI compares them with hmac.compare_digest. For the full rules (list of read/write commands, --dry-run skipping auth, dev-bypass risk), see Write-Command Authentication Contract.
Shell Completion
Section titled “Shell Completion”mailagent is built on typer and ships shell completion:
# install completion for the current shell (zsh / bash / fish)mailagent --install-completion zsh# or just print the completion script and decide how to source it yourselfmailagent --show-completion zshCompletion covers resources, actions, and flags, and is enumerable — this is exactly the autocomplete dividend that design principle 2, “resource-action consistency,” gives agents.
Common Installation Issues
Section titled “Common Installation Issues”| Symptom | Cause | Fix |
|---|---|---|
mailagent: command not found | venv not activated / PATH doesn’t include venv/bin | source venv/bin/activate or use the absolute path |
Write command reports E_AUTH_FAILED (exit 4) | MAILAGENT_CLI_API_KEY not passed | Inject the env var; see Authentication |
| Read command reports a SQLite permission error | Missing Full Disk Access | Grant FDA to the runner |
admin db-version reports E_SCHEMA_MISMATCH (exit 5) | db_version does not match expected | Run the backend first to apply DB migrations; see Exit Codes |