CLI Configuration
One config, every project: layered, project-aware defaults for the praisonai CLI
The praisonai CLI reads defaults from a layered hierarchy so you can set a model once and have it work everywhere — globally, per project, or per command.
from praisonaiagents import Agent
agent = Agent(name="assistant", instructions="Use project defaults from .praisonai/config.yaml.")
agent.start("What model am I using?")The user sets a default model in config once; every praisonai command in that project picks it up without repeating flags.
Quick Start
- Set a default model
bash praisonai config set agent.model gpt-4o-mini - Run any agent
bash praisonai run "Summarise this README"The model from config is picked automatically — no
--modelflag needed. - Inspect what was resolved
bash praisonai config show --sources
When you praisonai run, CLI defaults flow into the agent automatically:
from praisonaiagents import Agent
# Model, temperature, and tools come from resolved CLI config
agent = Agent(name="assistant", instructions="Be helpful.")
# praisonai run "..." uses agent.model from ~/.praisonai/config.yaml or project configHow It Works
Layers are deep-merged. Lists are concatenated. Scalars are overridden by higher layers.
| Layer | Source | Precedence |
|---|---|---|
| 1 | Built-in defaults | Lowest |
| 2 | Global ~/.praisonai/config.yaml (+ legacy paths) | |
| 3 | Project config (walk-up to git root or $HOME, whichever comes first) | |
| 4 | Environment variables | |
| 5 | CLI flags | Highest |
Project vs Global Config
| Location | Scope | Commit to repo? |
|---|---|---|
~/.praisonai/config.yaml | All projects on this machine | No |
./.praisonai/config.yaml | This project (and subdirectories) | Yes |
./praisonai.yaml / ./praisonai.yml | Canonical project config | Yes |
./praison.yaml / ./praison.yml | Legacy fallback (backward compat, still discovered) | Yes |
./.praison/config.toml | Legacy TOML (backward compat) | Optional † |
† When placed directly at $HOME, .praison/config.toml is loaded once as global: (never as project:).
Walk-up discovery searches, at each directory from cwd up to the git root or $HOME (whichever comes first). At $HOME the legacy .praison/config.toml name is skipped — that file is owned by the global loader:
.praisonai/config.yaml.praisonai/config.ymlpraisonai.yaml/praisonai.yml(canonical project-root config, added in PR #3422)praison.yaml/praison.yml(legacy fallback, discovered for backward compat).praison/config.toml(legacy)
# .praisonai/config.yaml — commit this to your repo
agent:
model: claude-sonnet-4-6
temperature: 0.3
max_tokens: 16000
tools:
- search_web
- read_file# Anywhere inside the repo (including subdirs):
praisonai run "Find recent benchmarks for retrieval-augmented generation"
# Uses claude-sonnet-4-6 automatically — no --model flag neededWalk-up Boundaries
Walk-up stops at the nearer of two boundaries: a .git-marked directory or $HOME.
- The walk stops at the nearer of a
.git-marked directory or$HOME. $HOMEitself is still searched for project configs, so~/.praisonai/config.yamland~/praisonai.yamlremain discoverable.- The legacy
.praison/config.tomlname is skipped only at$HOME— that file belongs to the global loader and is loaded exactly once asglobal:. - A config placed above
$HOME(e.g./Users/praisonai.yamlin a shared-parent layout) no longer wins, because$HOMEis now a hard boundary. - If
$HOMEis unresolvable (Path.home()raises), the walk falls back to filesystem root. - The CLI home root (sessions, traces, logs, cache, model-recency) is now the canonical
~/.praisonai/— the same directorypraisonai setupand the SDK use — unlessPRAISONAI_HOMEoverrides it. A legacy~/.praison/is read-only when it is the sole directory present.
Choose Your Scope
CLI Home Root
The CLI writes everything under one directory — ~/.praisonai/ by default, or wherever PRAISONAI_HOME points. Config, sessions, traces, logs, cache, credentials, .env, and durable state all live together there.
Every user-scoped artefact resolves under the same home root:
| Path | Contents |
|---|---|
<home>/config.toml | User CLI config (written by praisonai config set) |
<home>/config.yaml | User CLI YAML config (written by praisonai setup / praisonai init --global) |
<home>/.env | API keys (0600) |
<home>/credentials.json | Unified credential store (0600) |
<home>/sessions/ | Session state (JSON) |
<home>/traces/ | Execution traces |
<home>/logs/ | Log files |
<home>/cache/ | Disposable caches (model catalogue, etc.) |
<home>/state/ | Durable state (model recency, DLQs, journals, approvals, update-check) |
<home>/skills/ | User-scope skills (see Skill Manage) |
Override with PRAISONAI_HOME
Set PRAISONAI_HOME to re-root every artefact together — config and sessions and traces and logs and cache all move as one.
export PRAISONAI_HOME=/var/lib/praisonai
praisonai config set agent.model gpt-4o-mini
# → writes /var/lib/praisonai/config.toml
# → sessions, traces, logs, cache all now live under /var/lib/praisonai/Tilde is expanded, so PRAISONAI_HOME=~/mycustom resolves the same as PRAISONAI_HOME=$HOME/mycustom.
from praisonaiagents.paths import get_data_dir
# Both the SDK and the CLI resolve the same home root
print(get_data_dir()) # /var/lib/praisonai (or ~/.praisonai by default)Legacy ~/.praison/ — read-only fallback
If an older install still has ~/.praison/config.toml, the CLI keeps reading it until the first write. Any praisonai config set / praisonai config reset seeds from whatever currently resolves, then writes the merged result to ~/.praisonai/config.toml — migrating legacy values forward without ever mutating the legacy file. The SDK honours the legacy directory the same way (with a deprecation warning); praisonai migrate-data moves everything to the canonical root.
Project data directory (.praisonai/)
Project-local CLI state lives in ./.praisonai/ — the same directory the runtime (praisonaiagents.paths) reads from. Everything below goes through a single pair of helpers in cli/configuration/paths.py, derived from the one constant PROJECT_DATA_DIRNAME (itself praisonaiagents.paths.DEFAULT_DIR_NAME), so a new site cannot drift:
get_project_data_path(...)— the canonical write path (<cwd>/.praisonai/<file>).resolve_project_data_path(...)— the read path: returns the canonical file if it exists, else an existing legacy<cwd>/.praison/<file>, else the canonical path.
Files written under ./.praisonai/
These nine (plus one) project-data sites migrated from ./.praison/ (or ~/.praison/) to the canonical ./.praisonai/ in PR #4946. A read-only fallback to .praison/ is preserved so nothing saved earlier is orphaned:
| File / directory | Feature |
|---|---|
thinking.json | Thinking level (praisonai thinking) |
compaction.json | Conversation compaction state |
output.json | Output-style (praisonai output-style) |
| file-history | Interactive input history |
queue.db | Background queue database |
knowledge/<collection> | Knowledge vector-store path (config loader, unified schema, and three retrieval.py sites) |
| skills check | praisonai doctor skills check |
| memory check | praisonai doctor memory check |
Configuration Schema
agent.* defaults
| Key | Type | Default | Notes |
|---|---|---|---|
agent.model | str | None | e.g. gpt-4o-mini, claude-sonnet-4-6 |
agent.provider | str | None | e.g. openai, anthropic |
agent.base_url | str | None | Custom LLM base URL |
agent.tools | list[str] | [] | Default tool names |
agent.toolset | str | None | Named toolset |
agent.default_agent | str | None | Default agent slug |
agent.memory | bool or dict | None | Enable memory or config dict |
agent.stream | bool | True | Stream responses |
agent.temperature | float | 0.7 | LLM temperature. Forwarded to every LLM call (PraisonAI PR #4245) |
agent.max_tokens | int | 16000 | LLM token budget |
mcp.servers.<name>
| Key | Type | Default | Description |
|---|---|---|---|
command | list[str] or str | — | Local (stdio) server launch command. List form preferred. |
args | list[str] | [] | Extra args appended to command. |
env | dict[str, str] | {} | Env vars for the server process. Values containing , are skipped on the command-string path. |
enabled | bool | true | Set false to declare-but-not-wire a server. |
type | "remote" | — | Marks a remote server; skipped by the run command-string path. |
url | str | — | Remote endpoint; presence implies remote. |
permissions.*
| Key | Type | Default | Description | ||
|---|---|---|---|---|---|
default | "allow" \ | "deny" \ | "ask" | — | Fallback action when no rule matches. |
rules | list[{pattern, action}] | [] | Structured rule list. action must be allow, deny, or ask. | ||
<pattern> | "allow" \ | "deny" \ | "ask" | — | Flat shorthand — same shape as --allow/--deny produces. |
instructions
Top-level list of extra instruction/context sources loaded alongside the convention-only AGENTS.md / CLAUDE.md auto-discovery. List values concatenate across the config hierarchy (global → user → project), so a project extends rather than replaces the org-wide list.
| Key | Type | Default | Description |
|---|---|---|---|
instructions | list[str] | [] | File paths, globs (docs/standards/*.md), ~/env-var paths, or http(s):// URLs. See Instruction Sources for source-type behaviour, the SSRF guard, and merge semantics. |
# .praisonai/config.yaml
instructions:
- docs/standards/python.md
- docs/standards/security.md
- https://example.com/rules.mdSame first-class, layerable status as agent., mcp.servers., and permissions.* — also mirrored by the repeatable praisonai run --instructions <path|glob|url> flag.
Example combining all three sections:
# .praisonai/config.yaml
agent:
model: gpt-4o
temperature: 0.3
mcp:
servers:
playwright:
command: ["npx", "-y", "@playwright/mcp"]
permissions:
default: ask
rules:
- { pattern: "bash:git *", action: allow }
- { pattern: "bash:rm *", action: deny }
instructions:
- docs/standards/python.md
- https://example.com/rules.mdSee Single-Source Config for a full guide to using all three sections together. Other top-level sections (output, traces, session) are also valid — see Config CLI reference.
Validation
Configuration is validated against a published JSON Schema. Unknown keys produce actionable warnings with typo suggestions; opt into strict mode to fail fast.
| Mode | Enable via | Behaviour on unknown key |
|---|---|---|
| Warn (default) | — | Logs UserWarning, valid keys still apply |
| Strict (per-call) | --strict-config / ConfigResolver(strict=True) | Raises ValueError |
| Strict (global) | PRAISONAI_STRICT_CONFIG=1 | All resolver calls strict |
Typo example:
Unknown config key 'temprature' in .praisonai/config.yaml (section: agent). Did you mean 'temperature'?The # yaml-language-server: $schema=... line written by praisonai init enables real-time autocomplete and inline errors in VS Code (YAML extension) and other LSP-aware editors against the published schema.
Environment Variables
| Variable | Maps to | Notes |
|---|---|---|
MODEL_NAME | agent.model | |
OPENAI_MODEL_NAME | agent.model | |
PRAISONAI_MODEL | agent.model | |
PRAISONAI_PROVIDER | agent.provider | |
OPENAI_BASE_URL | agent.base_url | |
OPENAI_API_BASE | agent.base_url | |
PRAISONAI_BASE_URL | agent.base_url | |
PRAISONAI_OUTPUT_FORMAT | output.format | |
PRAISONAI_COLOR | output.color | bool: true/1/yes |
PRAISONAI_VERBOSE | output.verbose | bool |
PRAISONAI_QUIET | output.quiet | bool |
PRAISONAI_TELEMETRY | telemetry | bool |
PRAISONAI_BACKGROUND_JOB_STORE | background job durability | Default 1 (on). Set to 0 / false to force get_job_manager() to pure in-memory. See Durable Background Jobs |
Subcommand Reference
| Command | Flags | Behaviour | ||
|---|---|---|---|---|
praisonai config show | `–format yaml\ | json\ | table, –sources/-s` | Prints fully resolved config; with --sources, lists contributing layers |
praisonai config validate [FILE] | --strict-config, --json, optional FILE | Validates schema; warn-by-default, strict opts into raise | ||
praisonai config sources | none | Prints precedence hierarchy and active layers | ||
praisonai config list | `–scope all\ | user\ | project` | Lists resolved values; verbose shows sources |
praisonai config get KEY | dotted path | e.g. agent.model | ||
praisonai config set KEY VALUE | `–scope user\ | project` | Writes YAML (0600 user, 0644 project) | |
praisonai config reset | `–scope user\ | project, -y` | Deletes corresponding config.yaml | |
praisonai config path | `–scope user\ | project` | Shows config file path and existence | |
praisonai config env | --scope, --validate | Registered env vars and validation | ||
praisonai config doctor | none | Configuration diagnostics |
# Verify resolution
praisonai config show --sources
# Shows sources: defaults, project:/path/to/repo/.praisonai/config.yaml, ...Backward Compatibility
Legacy ~/.praison/config.toml
Loaded once as a global: source by the global loader. RAG and model keys are migrated to the new agent. / rag. schema automatically. Project walk-up never re-discovers it at $HOME, so praisonai config sources shows it exactly once with the global: label.
The legacy file is read-only. praisonai config set / praisonai config reset always write to the canonical ~/.praisonai/config.toml, seeding from whatever currently resolves — so a first write migrates any legacy values forward and the legacy file is never mutated after that. The same applies to the whole legacy directory: sessions, traces, logs, and cache now live under the canonical home too.
Legacy ~/.praisonai/.env
Model and provider keys from .env are merged into the resolved config when no YAML is present.
Project .praison/config.toml
Walk-up discovery still finds legacy TOML project configs in subdirectories (e.g. <subdir>/.praison/config.toml) and migrates them on read. The exception is the file at $HOME itself, which is only ever loaded as global: (see above).
Best Practices
Pin model per project
Commit .praisonai/config.yaml to your repo so teammates get the same defaults.
Keep secrets out of YAML
api_key is never serialised; use env vars or praisonai auth.
Use config sources to debug
When behaviour surprises you, praisonai config sources prints exactly which layer won.
Walk-up means subdirectories inherit
Running praisonai from repo/scripts/ finds repo/.praisonai/config.yaml.
Interpolation & Provenance
Any config value can reference ${VAR}, {env:NAME:-default}, or {file:./relative/path} — see Value Interpolation for the directive table and its security rules.
Run praisonai config provenance to see the winning value of each key and the exact layer/file that supplied it — see provenance.
Related
Full subcommand reference for praisonai config
SDK-level agents, tasks, and memory configuration
Runtime SelectionModel-scoped runtime configuration
LLM Endpoint ConfigCustom base URLs and provider routing
Single-Source ConfigModel + MCP + permissions in one file
Editor SupportAutocomplete and inline validation for config.yaml and agents.yaml