Configuration
PABLO reads two kinds of YAML files: one global ~/.pablo/config.yaml with your defaults, and one file per project in ~/.pablo/projects/. A project can override any default, key by key.
Global defaults#
~/.pablo/config.yaml is created by the installer from examples/config.yaml. It holds the keys every project inherits, plus a few that only exist globally.
default_model: opencode-go/glm-5.3-flash
pr_description_locale: en
sync:
strategy: rebase
auto_apply: false
interval_minutes: 720
state_polling:
interval_minutes: 10
review:
bot_whitelist: []
ci:
ignore_checks: ["approval"]
# agent_runtime: claude-code # global only, default opencode (or copilot)
# agent_backend: openchamber # global only, default orca
# default_model_by_type: # global only
# work: anthropic/claude-opus-4Keys a project inherits#
When a project omits one of these keys, the global value applies; when the global file omits it too, the built-in default does.
| Key | Built-in default | Meaning |
|---|---|---|
default_model | required somewhere | Model for agents (see below) |
pr_description_locale | required somewhere | Language of the pull request descriptions /pablo-commit-and-pr writes |
branch_prefix | none | Prefix added to every branch name, verbatim (write the slash yourself, e.g. pablo/) |
sync.strategy | rebase | rebase or merge |
sync.auto_apply | false | false: sync only reports |
sync.interval_minutes | 30 | How often branches are synced |
state_polling.interval_minutes | 10 | How often pull requests are checked |
main_update.enabled | true | Keep the main checkout up to date |
main_update.interval_minutes | 60 | How often |
testing.enabled | true | Whether the project has a QA step |
review.bot_whitelist | [] | Bot accounts whose reviews count |
ci.ignore_checks | [] | Checks to leave out of CI |
If default_model or pr_description_locale isn't set anywhere (and, for the model, no default_model_by_type entry matches), loading the project fails with an error.
Global-only keys#
agent_runtimeopencode(default),claude-codeorcopilot: the program that runs the agents. Also settable with thePABLO_AGENT_RUNTIMEenvironment variable. It changes the command the doctor requires (opencode,claudeorcopilot), what the installer generates and links, and which model idsdefault_modelaccepts. A first install setsclaude-codefor you when it finds Claude Code but no OpenCode. It setscopilotwhen it finds Copilot CLI but neither OpenCode nor Claude Code. See Run the agents with Claude Code and with GitHub Copilot CLI.agent_backendorca(default) oropenchamber. Also settable with thePABLO_AGENT_BACKENDenvironment variable. Withopenchamber, the doctor checks theopenchambercommand instead oforca. A first install sets it for you when it finds OpenChamber but no Orca. OpenChamber only runs OpenCode: withagent_runtime: claude-codeorcopilotit is refused. See Agent backends.default_model_by_type- A model per project type; see below.
Choose the agent model#
The model is resolved when an agent is launched, and passed to the backend as --model. The first one found wins:
- the project's own
default_model; - the entry for the project's type in
default_model_by_type; - the global
default_model; - as a last resort, the model written in the generated agent file.
# ~/.pablo/config.yaml — expensive models only on work projects
default_model_by_type:
work: anthropic/claude-opus-4
open-source: litellm/glm-5.3-flash
personal: opencode-go/glm-5.3-flashKeys must be project types (work, open-source, personal); an unknown key is an error.
The format depends on agent_runtime. OpenCode takes a provider/model id, as above. Claude Code takes an alias (sonnet, opus, haiku) or a full model id such as claude-sonnet-5-5; a provider/model id is refused with an error when the project loads. Copilot takes its own dotted model ids, such as claude-sonnet-5.5 or gpt-5.3-codex; a provider/model id or a Claude Code name (sonnet, claude-sonnet-5-5) is refused, with the dotted form suggested. Under Claude Code and Copilot the generated agents carry no model, so step 4 never applies.
Run the agents with Claude Code#
PABLO runs its agents with OpenCode by default. To use Claude Code instead, set it in ~/.pablo/config.yaml, then regenerate and relink:
agent_runtime: claude-code
default_model: sonnetcurl -fsSL https://getpablo.dev/installer | bash -s -- --runtime claude-code
# generates ~/.pablo/claude/agents.json, links the agents and the command
# (from a clone: ./bin/install.sh --runtime claude-code)
pablo system:doctor # checks claude and the generated files- Global only. Every project uses the same runtime; there is no per-project setting.
- Orca or headless. Agents run as
claude -p, in an Orca terminal or headless, exactly where OpenCode would run. OpenChamber is not supported: it drives its own OpenCode server.pablo system:doctorreports the combination as an error and the dispatcher refuses to run with it; switch toagent_backend: orcaor back toagent_runtime: opencode. - Your account and quota. Agents run with your own Claude Code login. With a Pro or Max subscription they share its usage limits with your interactive sessions, so keep an eye on them with busy projects.
- Your settings, not your MCP servers. Agents load your Claude Code settings and hooks (Orca's, RTK's) but none of your MCP servers (
--strict-mcp-config). - Sessions you can resume. Each run gets a session id chosen by PABLO;
claude --resume <id>in the worktree reopens it.
How the agent permissions translate is on Agents; what gets installed where is on Installation.
Run the agents with GitHub Copilot CLI#
To use GitHub Copilot CLI instead, set it in ~/.pablo/config.yaml (or export PABLO_AGENT_RUNTIME=copilot), then regenerate and relink:
agent_runtime: copilot
default_model: claude-sonnet-5.5curl -fsSL https://getpablo.dev/installer | bash -s -- --runtime copilot
# renders copilot/ and links the agents and skills into ~/.copilot/
# (from a clone: ./bin/install.sh --runtime copilot)
pablo system:doctor # checks copilot and the generated files- Global only. Every project uses the same runtime.
- Orca or headless. Agents run as
copilot -p, in an Orca terminal or headless, like the other runtimes. OpenChamber is not supported, as with Claude Code: the doctor reports it and the dispatcher refuses to run. - Copilot model ids. Dotted ids such as
claude-sonnet-5.5orgpt-5.3-codex. Aprovider/modelid (bring-your-own-model ids aren't supported) or a Claude Code name (sonnet,claude-sonnet-5-5) is refused when the project loads, with the dotted form suggested. - Your instructions, not your MCP servers. Agents load your custom instructions and hooks, but see only the built-in tools PABLO lists, and Copilot's built-in MCP servers are off.
- Sessions you can resume. Each run gets a UUID chosen by PABLO;
copilot --resume=<id>in the worktree reopens it.
How the agent permissions translate is on Agents; what gets installed where is on Installation.
Project files#
One YAML file per project in ~/.pablo/projects/, any file name. Create one with pablo project:new or by hand. Every key:
name: wallet-kit # required, unique
type: open-source # required: work | open-source | personal
repo:
path: ~/dev/wallet-kit # required: the main checkout
primary_branch: main # required
primary_remote: upstream # optional, default "origin": the remote sync and new
# branches use, e.g. when origin is your fork
worktrees_root: ~/dev/wallet-kit-worktrees
# optional, default ~/.pablo/worktrees/<repo folder name>/
issue_tracker:
provider: github # required: github | jira | linear
identity: your-login # required: whose issues are "assigned to me"
# (informational for Jira, which uses your acli login)
project_key: WK # required. Jira/Linear: the issue key prefix.
# GitHub: the branch prefix (GitHub has no keys)
site: acme.atlassian.net # Jira only, optional: the Atlassian site for links
repo: acme/upstream # GitHub only, optional: where issues and pull requests
# live, when you work on a fork
confluence:
space: PIM # Jira only, optional: where agents look for docs
sync:
strategy: rebase # rebase | merge
auto_apply: false
interval_minutes: 30
state_polling:
interval_minutes: 10
main_update:
enabled: true
interval_minutes: 60
testing:
enabled: true # false: no QA step, approval is final
failure_signal: qa-failed # GitHub: a pull request label. Jira/Linear: an issue status.
# Without it, testing-failed never triggers by itself.
review:
bot_whitelist: ["copilot-pull-request-reviewer[bot]"]
ci:
ignore_checks: ["approval"]
startup_script: ~/scripts/pablo-setup.sh
# optional: bash script run once per task, next to
# task-analyst, in its own terminal
default_model: opencode-go/glm-5.3-flash
pr_description_locale: en
branch_prefix: pablo/ci.ignore_checks#
A list of words. Any check whose name, workflow or context contains one of them is left out when PABLO decides whether CI is red or green. Use it for checks that never finish on their own, such as CircleCI manual approval gates, which stay pending (or “action required”) forever and would otherwise keep the task in draft. It's deliberately simple: a substring match.
Startup script#
startup_script runs once per task when it starts, in parallel with task-analyst, in its own terminal that stays open as a shell afterwards, so you can see its output. Use it to install dependencies or prepare the worktree. It's launched in the background and never blocks pablo task:start. It may run again if PABLO relaunches a launch that never started, so keep it safe to re-run.
Branch names#
Branches PABLO creates follow a fixed pattern, lowercased:
[branch_prefix][project-key]-[issue-id]- Jira and Linear: the issue's key, so
PIM-123becomespim-123. - GitHub: the project's
issue_tracker.project_keyand the issue number:project_key: WKand issue #45 givewk-45. - Prompt tasks: the project key and a short slug of the prompt, such as
wk-fix-callback-verification. If the prompt mentions a Jira or Linear key from one of your projects, that issue's name is used instead. - No title is added: the name is only those parts.
- Duplicates: if the name is already taken, PABLO tries
-2,-3, … until one is free. It never reuses or overwrites a branch.
With branch_prefix: pablo/, the issue above gives pablo/pim-123.
Environment variables#
| Variable | Default | Effect |
|---|---|---|
PABLO_AGENT_RUNTIME | — | Overrides agent_runtime |
PABLO_AGENT_BACKEND | — | Overrides agent_backend |
PABLO_CLAUDE_DIR | ~/.pablo/claude | Where the Claude Code agents.json is generated and read |
CLAUDE_CONFIG_DIR | ~/.claude | Claude Code's own directory: where the command and skill are linked, and where run transcripts are read for analytics |
COPILOT_HOME | ~/.copilot | Copilot's own directory: where the agents and skills are linked, and where session state is read |
PABLO_STATE_DIR, PABLO_PROJECTS_DIR, PABLO_STAMPS_DIR, PABLO_LOGS_DIR, PABLO_AGENTS_DIR, PABLO_ANALYTICS_DIR | under ~/.pablo/ | Move a part of PABLO's data elsewhere |
PABLO_CONFIG | ~/.pablo/config.yaml | Where the installer writes the global config |
PABLO_ENV | dev | Symfony environment. Leave it: in prod the cache is never refreshed, so a git pull would keep running old code |
PABLO_SECRET | a fixed local string | Signs dashboard requests; irrelevant for a local-only dashboard |