Resolved runtime configuration for planck_headless.
Config is resolved by Skogsra, which reads from three sources in priority order (highest first):
- Environment variables (
PLANCK_*) - Application config —
config :planck, <key>, ... - Hardcoded defaults
Values are cached in persistent terms via preload/0 at application boot;
the application also calls validate!/0 to fail fast on malformed config.
To change a value at runtime, set the application env and call the
Skogsra-generated reload_<key>/0 function.
JSON config files (~/.planck/config.json and .planck/config.json) are
read via JsonBinding as part of Skogsra's binding chain. Keys that appear
in a JSON file override application config but are overridden by env vars.
Env vars
Planner config
| Env var | Config key | Default |
|---|---|---|
PLANCK_DEFAULT_PROVIDER | :default_provider | nil |
PLANCK_DEFAULT_MODEL | :default_model | nil |
PLANCK_SESSIONS_DIR | :sessions_dir | .planck/sessions |
PLANCK_SKILLS_DIRS | :skills_dirs | .planck/skills:~/.planck/skills |
PLANCK_TEAMS_DIRS | :teams_dirs | .planck/teams:~/.planck/teams |
PLANCK_SIDECAR | :sidecar | .planck/sidecar |
*_DIRS env vars take a colon-separated list; paths are expanded at runtime
(~ and relative paths resolved). The :models key has no env var
equivalent — declare models in .planck/config.json or
config :planck, :models, [...].
Provider API keys
API keys are not included in get/0 or the %Config{} struct to avoid
accidental exposure in logs or inspect output. Use the generated getter
functions directly (e.g. Config.anthropic_api_key!/0).
| Env var | Config key | Used for |
|---|---|---|
ANTHROPIC_API_KEY | :anthropic_api_key | Anthropic (Claude) models |
OPENAI_API_KEY | :openai_api_key | OpenAI models |
GOOGLE_API_KEY | :google_api_key | Google (Gemini) models |
Summary
Functions
Anthropic API key.
Anthropic API key.
Colon-separated list of JSON config files to read at boot, in order. Later files override earlier ones. Not read from the JSON files themselves — that would be circular. Defaults to the user-global file followed by the project-local file (project-local wins on collision).
Colon-separated list of JSON config files to read at boot, in order. Later files override earlier ones. Not read from the JSON files themselves — that would be circular. Defaults to the user-global file followed by the project-local file (project-local wins on collision).
Default model id within the default provider (e.g. claude-sonnet-4-6).
Default model id within the default provider (e.g. claude-sonnet-4-6).
Default LLM provider (e.g. anthropic).
Default LLM provider (e.g. anthropic).
Ordered list of .env files to read for API keys.
Global file is read first; project-local file wins on collision.
Not read from the .env files themselves — that would be circular.
Ordered list of .env files to read for API keys.
Global file is read first; project-local file wins on collision.
Not read from the .env files themselves — that would be circular.
Return the fully-resolved config as a %Planck.Headless.Config{} struct.
Google API key.
Google API key.
UI locale (e.g. "en", "es"). Set in .planck/config.json for a
project-specific language or in ~/.planck/config.json for a global
preference. When absent the browser's Accept-Language header is used,
falling back to English.
UI locale (e.g. "en", "es"). Set in .planck/config.json for a
project-specific language or in ~/.planck/config.json for a global
preference. When absent the browser's Accept-Language header is used,
falling back to English.
List of model declarations for local providers (and optional cloud model
overrides). Each entry follows the Planck.AI.Config JSON format. Only
readable from .planck/config.json or application config — no env var
equivalent (the format is too structured for a flat string).
List of model declarations for local providers (and optional cloud model
overrides). Each entry follows the Planck.AI.Config JSON format. Only
readable from .planck/config.json or application config — no env var
equivalent (the format is too structured for a flat string).
OpenAI API key.
OpenAI API key.
Preloads all variables in a namespace if supplied.
Puts the value to Planck.Headless.Config.anthropic_api_key/0. Optionally, receives
the namespace.
Puts the value to Planck.Headless.Config.config_files/0. Optionally, receives
the namespace.
Puts the value to Planck.Headless.Config.default_model/0. Optionally, receives
the namespace.
Puts the value to Planck.Headless.Config.default_provider/0. Optionally, receives
the namespace.
Puts the value to Planck.Headless.Config.env_files/0. Optionally, receives
the namespace.
Puts the value to Planck.Headless.Config.google_api_key/0. Optionally, receives
the namespace.
Puts the value to Planck.Headless.Config.locale/0. Optionally, receives
the namespace.
Puts the value to Planck.Headless.Config.models/0. Optionally, receives
the namespace.
Puts the value to Planck.Headless.Config.openai_api_key/0. Optionally, receives
the namespace.
Puts the value to Planck.Headless.Config.sessions_dir/0. Optionally, receives
the namespace.
Puts the value to Planck.Headless.Config.sidecar/0. Optionally, receives
the namespace.
Puts the value to Planck.Headless.Config.skills_dirs/0. Optionally, receives
the namespace.
Puts the value to Planck.Headless.Config.teams_dirs/0. Optionally, receives
the namespace.
Reloads the value for Planck.Headless.Config.anthropic_api_key/0. Optionally, receives
the namespace for the variable.
Reloads the value for Planck.Headless.Config.config_files/0. Optionally, receives
the namespace for the variable.
Reloads the value for Planck.Headless.Config.default_model/0. Optionally, receives
the namespace for the variable.
Reloads the value for Planck.Headless.Config.default_provider/0. Optionally, receives
the namespace for the variable.
Reloads the value for Planck.Headless.Config.env_files/0. Optionally, receives
the namespace for the variable.
Reloads the value for Planck.Headless.Config.google_api_key/0. Optionally, receives
the namespace for the variable.
Reloads the value for Planck.Headless.Config.locale/0. Optionally, receives
the namespace for the variable.
Reloads the value for Planck.Headless.Config.models/0. Optionally, receives
the namespace for the variable.
Reloads the value for Planck.Headless.Config.openai_api_key/0. Optionally, receives
the namespace for the variable.
Reloads the value for Planck.Headless.Config.sessions_dir/0. Optionally, receives
the namespace for the variable.
Reloads the value for Planck.Headless.Config.sidecar/0. Optionally, receives
the namespace for the variable.
Reloads the value for Planck.Headless.Config.skills_dirs/0. Optionally, receives
the namespace for the variable.
Reloads the value for Planck.Headless.Config.teams_dirs/0. Optionally, receives
the namespace for the variable.
Path to the sessions directory.
Path to the sessions directory.
Path to the sidecar Mix project directory. planck_headless starts the sidecar application from this path when it exists on disk. Set to a non-existent path to disable sidecar startup.
Path to the sidecar Mix project directory. planck_headless starts the sidecar application from this path when it exists on disk. Set to a non-existent path to disable sidecar startup.
Colon-separated list of skill directories.
Colon-separated list of skill directories.
Colon-separated list of team directories.
Colon-separated list of team directories.
Creates a template for OS environment variables given a filename.
Additionally, it can receive a list of options
Validates that all required variables are present.
Returns :ok if they are, {:error, errors} if they are not. errors
will be a list of all errors encountered while getting required variables.
Validates that all required variables are present.
Returns :ok if they are, raises if they're not.
Types
Functions
@spec anthropic_api_key(Skogsra.Env.namespace()) :: {:ok, nil | binary()} | {:error, binary()}
Anthropic API key.
Calling Planck.Headless.Config.anthropic_api_key() will ensure the following:
- Binding order: [:system, :config]
- OS environment variable: "ANTHROPIC_API_KEY"
- Type: :binary
- Default: nil
- Required: false
- Cached: true
@spec anthropic_api_key!(Skogsra.Env.namespace()) :: (nil | binary()) | no_return()
Anthropic API key.
Bang version of Planck.Headless.Config.anthropic_api_key/0 (fails on error). Optionally,
receives the namespace for the variable.
@spec config_files(Skogsra.Env.namespace()) :: {:ok, Planck.Headless.Config.PathList.t()} | {:error, binary()}
Colon-separated list of JSON config files to read at boot, in order. Later files override earlier ones. Not read from the JSON files themselves — that would be circular. Defaults to the user-global file followed by the project-local file (project-local wins on collision).
Calling Planck.Headless.Config.config_files() will ensure the following:
- Binding order: [:system, :config]
- OS environment variable: "PLANCK_CONFIG_FILES"
- Type: Planck.Headless.Config.PathList
- Default: ["~/.planck/config.json", ".planck/config.json"]
- Required: false
- Cached: true
@spec config_files!(Skogsra.Env.namespace()) :: Planck.Headless.Config.PathList.t() | no_return()
Colon-separated list of JSON config files to read at boot, in order. Later files override earlier ones. Not read from the JSON files themselves — that would be circular. Defaults to the user-global file followed by the project-local file (project-local wins on collision).
Bang version of Planck.Headless.Config.config_files/0 (fails on error). Optionally,
receives the namespace for the variable.
@spec default_model(Skogsra.Env.namespace()) :: {:ok, nil | binary()} | {:error, binary()}
Default model id within the default provider (e.g. claude-sonnet-4-6).
Calling Planck.Headless.Config.default_model() will ensure the following:
- Binding order: [:system, :config]
- OS environment variable: "PLANCK_DEFAULT_MODEL"
- Type: :binary
- Default: nil
- Required: false
- Cached: true
@spec default_model!(Skogsra.Env.namespace()) :: (nil | binary()) | no_return()
Default model id within the default provider (e.g. claude-sonnet-4-6).
Bang version of Planck.Headless.Config.default_model/0 (fails on error). Optionally,
receives the namespace for the variable.
@spec default_provider(Skogsra.Env.namespace()) :: {:ok, nil | atom()} | {:error, binary()}
Default LLM provider (e.g. anthropic).
Calling Planck.Headless.Config.default_provider() will ensure the following:
- Binding order: [:system, :config]
- OS environment variable: "PLANCK_DEFAULT_PROVIDER"
- Type: :atom
- Default: nil
- Required: false
- Cached: true
@spec default_provider!(Skogsra.Env.namespace()) :: (nil | atom()) | no_return()
Default LLM provider (e.g. anthropic).
Bang version of Planck.Headless.Config.default_provider/0 (fails on error). Optionally,
receives the namespace for the variable.
@spec env_files(Skogsra.Env.namespace()) :: {:ok, Planck.Headless.Config.PathList.t()} | {:error, binary()}
Ordered list of .env files to read for API keys.
Global file is read first; project-local file wins on collision.
Not read from the .env files themselves — that would be circular.
Calling Planck.Headless.Config.env_files() will ensure the following:
- Binding order: [:system, :config]
- OS environment variable: "PLANCK_ENV_FILES"
- Type: Planck.Headless.Config.PathList
- Default: ["~/.planck/.env", "./.planck/.env"]
- Required: false
- Cached: true
@spec env_files!(Skogsra.Env.namespace()) :: Planck.Headless.Config.PathList.t() | no_return()
Ordered list of .env files to read for API keys.
Global file is read first; project-local file wins on collision.
Not read from the .env files themselves — that would be circular.
Bang version of Planck.Headless.Config.env_files/0 (fails on error). Optionally,
receives the namespace for the variable.
@spec get() :: t()
Return the fully-resolved config as a %Planck.Headless.Config{} struct.
@spec google_api_key(Skogsra.Env.namespace()) :: {:ok, nil | binary()} | {:error, binary()}
Google API key.
Calling Planck.Headless.Config.google_api_key() will ensure the following:
- Binding order: [:system, :config]
- OS environment variable: "GOOGLE_API_KEY"
- Type: :binary
- Default: nil
- Required: false
- Cached: true
@spec google_api_key!(Skogsra.Env.namespace()) :: (nil | binary()) | no_return()
Google API key.
Bang version of Planck.Headless.Config.google_api_key/0 (fails on error). Optionally,
receives the namespace for the variable.
@spec locale(Skogsra.Env.namespace()) :: {:ok, nil | binary()} | {:error, binary()}
UI locale (e.g. "en", "es"). Set in .planck/config.json for a
project-specific language or in ~/.planck/config.json for a global
preference. When absent the browser's Accept-Language header is used,
falling back to English.
Calling Planck.Headless.Config.locale() will ensure the following:
- Binding order: [:system, :config]
- OS environment variable: "PLANCK_LOCALE"
- Type: :binary
- Default: nil
- Required: false
- Cached: true
@spec locale!(Skogsra.Env.namespace()) :: (nil | binary()) | no_return()
UI locale (e.g. "en", "es"). Set in .planck/config.json for a
project-specific language or in ~/.planck/config.json for a global
preference. When absent the browser's Accept-Language header is used,
falling back to English.
Bang version of Planck.Headless.Config.locale/0 (fails on error). Optionally,
receives the namespace for the variable.
@spec models(Skogsra.Env.namespace()) :: {:ok, Planck.Headless.Config.Models.t()} | {:error, binary()}
List of model declarations for local providers (and optional cloud model
overrides). Each entry follows the Planck.AI.Config JSON format. Only
readable from .planck/config.json or application config — no env var
equivalent (the format is too structured for a flat string).
Example (in .planck/config.json):
"models": [
{
"id": "llama3.2",
"provider": "ollama",
"base_url": "http://localhost:11434",
"context_window": 128000,
"default_opts": {"temperature": 0.7, "top_p": 0.9}
},
{
"id": "mistral",
"provider": "llama_cpp",
"base_url": "http://localhost:8080",
"context_window": 32768,
"default_opts": {"temperature": 0.5}
}
]Calling Planck.Headless.Config.models() will ensure the following:
- Binding order: [:system, :config]
- OS environment variable: "PLANCK_MODELS"
- Type: Planck.Headless.Config.Models
- Default: []
- Required: false
- Cached: true
@spec models!(Skogsra.Env.namespace()) :: Planck.Headless.Config.Models.t() | no_return()
List of model declarations for local providers (and optional cloud model
overrides). Each entry follows the Planck.AI.Config JSON format. Only
readable from .planck/config.json or application config — no env var
equivalent (the format is too structured for a flat string).
Example (in .planck/config.json):
"models": [
{
"id": "llama3.2",
"provider": "ollama",
"base_url": "http://localhost:11434",
"context_window": 128000,
"default_opts": {"temperature": 0.7, "top_p": 0.9}
},
{
"id": "mistral",
"provider": "llama_cpp",
"base_url": "http://localhost:8080",
"context_window": 32768,
"default_opts": {"temperature": 0.5}
}
]Bang version of Planck.Headless.Config.models/0 (fails on error). Optionally,
receives the namespace for the variable.
@spec openai_api_key(Skogsra.Env.namespace()) :: {:ok, nil | binary()} | {:error, binary()}
OpenAI API key.
Calling Planck.Headless.Config.openai_api_key() will ensure the following:
- Binding order: [:system, :config]
- OS environment variable: "OPENAI_API_KEY"
- Type: :binary
- Default: nil
- Required: false
- Cached: true
@spec openai_api_key!(Skogsra.Env.namespace()) :: (nil | binary()) | no_return()
OpenAI API key.
Bang version of Planck.Headless.Config.openai_api_key/0 (fails on error). Optionally,
receives the namespace for the variable.
@spec preload(Skogsra.Env.namespace()) :: :ok
Preloads all variables in a namespace if supplied.
@spec put_anthropic_api_key(nil | binary(), Skogsra.Env.namespace()) :: :ok | {:error, binary()}
Puts the value to Planck.Headless.Config.anthropic_api_key/0. Optionally, receives
the namespace.
@spec put_config_files(Planck.Headless.Config.PathList.t(), Skogsra.Env.namespace()) :: :ok | {:error, binary()}
Puts the value to Planck.Headless.Config.config_files/0. Optionally, receives
the namespace.
@spec put_default_model(nil | binary(), Skogsra.Env.namespace()) :: :ok | {:error, binary()}
Puts the value to Planck.Headless.Config.default_model/0. Optionally, receives
the namespace.
@spec put_default_provider(nil | atom(), Skogsra.Env.namespace()) :: :ok | {:error, binary()}
Puts the value to Planck.Headless.Config.default_provider/0. Optionally, receives
the namespace.
@spec put_env_files(Planck.Headless.Config.PathList.t(), Skogsra.Env.namespace()) :: :ok | {:error, binary()}
Puts the value to Planck.Headless.Config.env_files/0. Optionally, receives
the namespace.
@spec put_google_api_key(nil | binary(), Skogsra.Env.namespace()) :: :ok | {:error, binary()}
Puts the value to Planck.Headless.Config.google_api_key/0. Optionally, receives
the namespace.
@spec put_locale(nil | binary(), Skogsra.Env.namespace()) :: :ok | {:error, binary()}
Puts the value to Planck.Headless.Config.locale/0. Optionally, receives
the namespace.
@spec put_models(Planck.Headless.Config.Models.t(), Skogsra.Env.namespace()) :: :ok | {:error, binary()}
Puts the value to Planck.Headless.Config.models/0. Optionally, receives
the namespace.
@spec put_openai_api_key(nil | binary(), Skogsra.Env.namespace()) :: :ok | {:error, binary()}
Puts the value to Planck.Headless.Config.openai_api_key/0. Optionally, receives
the namespace.
@spec put_sessions_dir(binary(), Skogsra.Env.namespace()) :: :ok | {:error, binary()}
Puts the value to Planck.Headless.Config.sessions_dir/0. Optionally, receives
the namespace.
@spec put_sidecar(binary(), Skogsra.Env.namespace()) :: :ok | {:error, binary()}
Puts the value to Planck.Headless.Config.sidecar/0. Optionally, receives
the namespace.
@spec put_skills_dirs(Planck.Headless.Config.PathList.t(), Skogsra.Env.namespace()) :: :ok | {:error, binary()}
Puts the value to Planck.Headless.Config.skills_dirs/0. Optionally, receives
the namespace.
@spec put_teams_dirs(Planck.Headless.Config.PathList.t(), Skogsra.Env.namespace()) :: :ok | {:error, binary()}
Puts the value to Planck.Headless.Config.teams_dirs/0. Optionally, receives
the namespace.
@spec reload_anthropic_api_key(Skogsra.Env.namespace()) :: {:ok, nil | binary()} | {:error, binary()}
Reloads the value for Planck.Headless.Config.anthropic_api_key/0. Optionally, receives
the namespace for the variable.
@spec reload_config_files(Skogsra.Env.namespace()) :: {:ok, Planck.Headless.Config.PathList.t()} | {:error, binary()}
Reloads the value for Planck.Headless.Config.config_files/0. Optionally, receives
the namespace for the variable.
@spec reload_default_model(Skogsra.Env.namespace()) :: {:ok, nil | binary()} | {:error, binary()}
Reloads the value for Planck.Headless.Config.default_model/0. Optionally, receives
the namespace for the variable.
@spec reload_default_provider(Skogsra.Env.namespace()) :: {:ok, nil | atom()} | {:error, binary()}
Reloads the value for Planck.Headless.Config.default_provider/0. Optionally, receives
the namespace for the variable.
@spec reload_env_files(Skogsra.Env.namespace()) :: {:ok, Planck.Headless.Config.PathList.t()} | {:error, binary()}
Reloads the value for Planck.Headless.Config.env_files/0. Optionally, receives
the namespace for the variable.
@spec reload_google_api_key(Skogsra.Env.namespace()) :: {:ok, nil | binary()} | {:error, binary()}
Reloads the value for Planck.Headless.Config.google_api_key/0. Optionally, receives
the namespace for the variable.
@spec reload_locale(Skogsra.Env.namespace()) :: {:ok, nil | binary()} | {:error, binary()}
Reloads the value for Planck.Headless.Config.locale/0. Optionally, receives
the namespace for the variable.
@spec reload_models(Skogsra.Env.namespace()) :: {:ok, Planck.Headless.Config.Models.t()} | {:error, binary()}
Reloads the value for Planck.Headless.Config.models/0. Optionally, receives
the namespace for the variable.
@spec reload_openai_api_key(Skogsra.Env.namespace()) :: {:ok, nil | binary()} | {:error, binary()}
Reloads the value for Planck.Headless.Config.openai_api_key/0. Optionally, receives
the namespace for the variable.
@spec reload_sessions_dir(Skogsra.Env.namespace()) :: {:ok, binary()} | {:error, binary()}
Reloads the value for Planck.Headless.Config.sessions_dir/0. Optionally, receives
the namespace for the variable.
@spec reload_sidecar(Skogsra.Env.namespace()) :: {:ok, binary()} | {:error, binary()}
Reloads the value for Planck.Headless.Config.sidecar/0. Optionally, receives
the namespace for the variable.
@spec reload_skills_dirs(Skogsra.Env.namespace()) :: {:ok, Planck.Headless.Config.PathList.t()} | {:error, binary()}
Reloads the value for Planck.Headless.Config.skills_dirs/0. Optionally, receives
the namespace for the variable.
@spec reload_teams_dirs(Skogsra.Env.namespace()) :: {:ok, Planck.Headless.Config.PathList.t()} | {:error, binary()}
Reloads the value for Planck.Headless.Config.teams_dirs/0. Optionally, receives
the namespace for the variable.
@spec sessions_dir(Skogsra.Env.namespace()) :: {:ok, binary()} | {:error, binary()}
Path to the sessions directory.
Calling Planck.Headless.Config.sessions_dir() will ensure the following:
- Binding order: [:system, :config]
- OS environment variable: "PLANCK_SESSIONS_DIR"
- Type: :binary
- Default: ".planck/sessions"
- Required: false
- Cached: true
@spec sessions_dir!(Skogsra.Env.namespace()) :: binary() | no_return()
Path to the sessions directory.
Bang version of Planck.Headless.Config.sessions_dir/0 (fails on error). Optionally,
receives the namespace for the variable.
@spec sidecar(Skogsra.Env.namespace()) :: {:ok, binary()} | {:error, binary()}
Path to the sidecar Mix project directory. planck_headless starts the sidecar application from this path when it exists on disk. Set to a non-existent path to disable sidecar startup.
Calling Planck.Headless.Config.sidecar() will ensure the following:
- Binding order: [:system, :config]
- OS environment variable: "PLANCK_SIDECAR"
- Type: :binary
- Default: ".planck/sidecar"
- Required: false
- Cached: true
@spec sidecar!(Skogsra.Env.namespace()) :: binary() | no_return()
Path to the sidecar Mix project directory. planck_headless starts the sidecar application from this path when it exists on disk. Set to a non-existent path to disable sidecar startup.
Bang version of Planck.Headless.Config.sidecar/0 (fails on error). Optionally,
receives the namespace for the variable.
@spec skills_dirs(Skogsra.Env.namespace()) :: {:ok, Planck.Headless.Config.PathList.t()} | {:error, binary()}
Colon-separated list of skill directories.
Calling Planck.Headless.Config.skills_dirs() will ensure the following:
- Binding order: [:system, :config]
- OS environment variable: "PLANCK_SKILLS_DIRS"
- Type: Planck.Headless.Config.PathList
- Default: [".planck/skills", "~/.planck/skills"]
- Required: false
- Cached: true
@spec skills_dirs!(Skogsra.Env.namespace()) :: Planck.Headless.Config.PathList.t() | no_return()
Colon-separated list of skill directories.
Bang version of Planck.Headless.Config.skills_dirs/0 (fails on error). Optionally,
receives the namespace for the variable.
@spec teams_dirs(Skogsra.Env.namespace()) :: {:ok, Planck.Headless.Config.PathList.t()} | {:error, binary()}
Colon-separated list of team directories.
Calling Planck.Headless.Config.teams_dirs() will ensure the following:
- Binding order: [:system, :config]
- OS environment variable: "PLANCK_TEAMS_DIRS"
- Type: Planck.Headless.Config.PathList
- Default: [".planck/teams", "~/.planck/teams"]
- Required: false
- Cached: true
@spec teams_dirs!(Skogsra.Env.namespace()) :: Planck.Headless.Config.PathList.t() | no_return()
Colon-separated list of team directories.
Bang version of Planck.Headless.Config.teams_dirs/0 (fails on error). Optionally,
receives the namespace for the variable.
@spec template( Path.t(), keyword() ) :: :ok | {:error, File.posix()}
Creates a template for OS environment variables given a filename.
Additionally, it can receive a list of options:
type: What kind of file it will generate (:elixir,:unix,:windows).namespace: Namespace for the variables.
@spec validate(Skogsra.Env.namespace()) :: :ok | {:error, [binary()]}
Validates that all required variables are present.
Returns :ok if they are, {:error, errors} if they are not. errors
will be a list of all errors encountered while getting required variables.
It is possible to provide a namespace as argument (defaults to nil).
@spec validate!(Skogsra.Env.namespace()) :: :ok | no_return()
Validates that all required variables are present.
Returns :ok if they are, raises if they're not.
It is possible to provide a namespace as argument (defaults to nil).