Environment variables
Model endpoints
| Variable | Purpose |
|---|---|
OPENAI_BASE_URL |
Planner API base (default http://localhost:8080) |
OPENAI_API_KEY |
Planner API key |
OPENAI_MODEL |
Planner model id |
NINJA_SUBAGENT_BASE_URL |
Default subagent base |
NINJA_SUBAGENT_API_KEY |
Default subagent key |
NINJA_SUBAGENT_MODEL |
Default subagent model |
Prefer NINJA_SUBAGENT_* for workers. (Legacy subagent_* names exist only as config.json keys, not env vars.)
Tool / integration keys
| Variable | Purpose |
|---|---|
NINJA_SERPER_API_KEY |
Web search (preferred) |
SERPER_API_KEY |
Web search (fallback) |
Install / update (optional)
| Variable | Purpose |
|---|---|
NINJA_VERSION |
Pin version when using install.sh |
NINJA_CDN_BASE |
Force install/update CDN origin (default https://ninja-cli.btaskee.work) |
NINJA_NO_UPDATE_CHECK |
Set to 1 to disable the interactive startup update prompt and headless cache refresh (same as "update_check": false). Does not block ninja update. |
The update check is a plain GET of latest.json — no query parameters or identifying payload.
Precedence
Non-empty environment variables override the general config.json fields (openai_*, ninja_subagent_*) for that shell.
OPENAI_MODEL=other-model ninja
Target-specific config beats env: a planner block, subagent_roles.<role> entry, or plan_panel entry always wins over these variables. ninja doctor warns when an env var shadows a config field and shows where each resolved value came from.
Pinning the planner
To stop OPENAI_* from silently overriding your saved planner, put endpoint fields under planner in config.json (not only under openai_*):
{
"planner": {
"base_url": "https://api.example.com/v1",
"api_key": "REPLACE_PLANNER_KEY",
"model": "planner-model"
}
}
That block outranks OPENAI_*. Details and the full ladder: config.json → Pinning the planner and Configure models → Pinning the planner.