The config file (config.yaml)
What config.yaml is still for (server installs and developers), what wins over it, and the settings that only it holds.
Everything you set yourself is in the app, and the app keeps your choices in your settings file, settings.json. You never need config.yaml for that. It stays for the install itself (server installs, Docker, a copy built from the source code) and for developers: ports, paths, ChatPilot's own servers, and the internal defaults nobody needs to change.
Where it is
Mac and Linux: ~/.config/chatpilot/config.yaml; Windows: %APPDATA%\chatpilot\config.yaml; in Docker: the config volume. chatpilot --config PATH run uses another file.
- A first start without the file (
chatpilot run, the service, the installer, Docker) writes a short one: the owner's Telegram id (filled in by the first-start page in the browser), the quiet hours to start with, and a commented list of the install settings below. uv run chatpilot init(developers) copies the fullconfig.example.yamlinstead, with every setting explained line by line.
After you change it: uv run chatpilot service restart (Docker: restart the container).
What wins
- The panel and
settings.json. A setting that has a card in the app is read fromsettings.jsonfirst. A key there that isnullfollowsconfig.yaml; Back to config.yaml's choice on a card sets it back tonull. config.yaml. Everything else: the install settings below, and the internal defaults.- The built-in default for anything neither file names.
So a line in config.yaml for a setting that has a card is only the starting value of a new install; once someone changes it on the card, the card's value counts.
Install settings
These have no card in the app on purpose: they describe the install, not how you work. The list is generated from src/chatpilot/settingsmap.py (uv run python -m chatpilot.settingsmap --manual); a section ending in … means every setting in it.
| Setting | What it is |
|---|---|
data_dir | Where the data lives; a move to another computer goes through a backup |
admin.… | Panel port, bind address, hosts, proxies, sign-in mode of the install |
email[].oauth_client_id | An own OAuth client (developers) |
google_oauth_client | An own Google OAuth client instead of ChatPilot's (developers) |
llm.claude_path | Path of the claude program |
llm.codex_path | Path of the codex program |
llm.gemini_path | Path of the gemini program |
voice.whisper_bin | Path of whisper.cpp |
voice.model | Path of the whisper model |
voice.ffmpeg | Path of ffmpeg |
tickets.app_repo | ChatPilot's own repository for app reports |
profiles.packs | Folders with extra profile packs |
support.url | ChatPilot's support server |
licence.url | ChatPilot's licence server |
github.… | ChatPilot's GitHub app for reports (developers) |
github_questions.tracker_url | The tracker's MCP server |
update.releases_url | ChatPilot's release feed |
cleanup.ollama_url | The local model server cleanup uses |
config.example.yaml explains each one with the lines to copy in.
Internal defaults
Timeouts, poll intervals, size limits, the model and effort per step and the like have a default that suits every install and no card. A developer can still set them in config.yaml (the example has them all). The full list of settings, with where each one is set in the app or that it is internal, is docs/settings_inventory.md in the repository.
A new setting
Every setting in Config (src/chatpilot/config.py) needs a line in settingsmap.WHERE: panel with where the app sets it, internal, or install. tests/test_settingsmap.py fails for a setting without one, so nothing new lands in config.yaml without saying where a user sets it. A new install setting appears in the table above once you regenerate it.
Checked against ChatPilot 0.1.0b1. Report a problem with this page