PABLO
Docs
Documentation home

Getting started

  • What is PABLO?
  • Quickstart
  • Installation
  • Your first project
  • Your first task

Guides

  • Managing tasks
  • Dashboard
  • Analytics
  • Backups & restore
  • Troubleshooting

Concepts

  • How it works
  • Task states
  • Agents
  • Sync & rebase

Reference

  • Commands
  • Configuration
  • Providers
  • Storage

Contributing

  • Development

Concepts

Agents

PABLO ships five agents, run by OpenCode, Claude Code or GitHub Copilot CLI (see agent_runtime). Four read and analyse, and never touch your code; the fifth resolves rebase conflicts. Each one is launched by a specific state, with the right link and the right worktree, so you read results instead of writing prompts.

The agents#

AgentLaunched onWhat it does
task-analystin-progress, once per taskReads the issue (GitHub, Jira or Linear), its parents, linked pull requests and the relevant code, and writes a summary and a grounded action plan. For a prompt task, it applies the same method to your prompt.
ci-analystci-redFetches the failing checks and their logs, ties each failure to the responsible code, and proposes a fix plan. It never changes the pull request.
pr-feedbackrequest-changesReads unresolved review threads, review bodies and comments, and turns them into a fix plan grouped by topic. When it finishes, the pull request goes back to draft.
task-feedbacktesting-failedCompares QA's feedback with what the pull request really ships, classifies each point, and drafts a reply in the language QA used. When it finishes, the pull request goes back to draft.
rebase-conflict-resolvera sync rebase hits a conflictReplays the rebase, resolves every conflict and pushes with --force-with-lease. See below.

Open an agent's session in Orca or OpenChamber to read its result and keep the conversation going: ask questions, push back, refine the plan. A headless Claude Code run reopens with claude --resume <session id> in the worktree, a Copilot one with copilot --resume=<session id>.

The rebase-conflict resolver#

The single deliberate exception to the read-only rule. When an applied sync hits conflicts, git aborts cleanly and PABLO launches this agent headless. It may edit files and run git, because that's its job, but it is denied anything that acts as you in front of other people: no gh pr merge, review, comment, edit, ready or close, no issue commands, no Jira commands. If a conflict needs a human, it stops and pushes nothing. It has no step limit, so it never stops halfway through a rebase.

Everything it does lands in your pull request, which you review before merging. The dashboard's “Last sync” card shows the command to open its session: opencode -s <id>, claude --resume <id> under Claude Code, or copilot --resume=<id> under Copilot (its handle is recorded as copilot:<uuid>, so it can't be mistaken for a Claude Code session).

Read-only, enforced#

The analysis agents can't edit files and can only run read-only commands, by permission rules in their OpenCode frontmatter, not just by instructions in their prompt. Even if a ticket says “just fix it quickly”, they can't. Under Claude Code the same rules are translated and enforced by Claude Code itself (below), and under Copilot by Copilot CLI (below).

yaml
permissions:
  - { action: edit,  resource: "*",          effect: deny }   # edit, write, patch
  - { action: shell, resource: "*",          effect: deny }   # nothing runs by default…
  - { action: shell, resource: "git *",      effect: allow }  # …except git
  - { action: shell, resource: "git push *", effect: deny }   # …but never a push

Every agent also follows shared house rules: use tools sparingly (batched calls, bounded logs and diffs), write in English, never post or edit anything on GitHub without your explicit approval in the session (they draft the text, you post it), and never commit or push.

Context fetched up front#

Every step an agent takes re-reads its whole context, so steps are what cost tokens. Before launching an analyst, PABLO fetches the obvious context with read-only commands and appends it to the prompt (up to about 24,000 characters):

  • task-analyst, task-feedback: the issue's title, details, description and latest 15 comments;
  • ci-analyst: the failing checks (minus ignored ones) and, for up to 3 GitHub Actions jobs, their error lines and the end of their logs;
  • pr-feedback: unresolved threads, review bodies and comments.

It's best-effort: if fetching fails, the agent fetches by itself. It's skipped with Orca, where the prompt travels on a command line.

Step limits#

Analysts have a step budget (30 for task-analyst and ci-analyst, 25 for pr-feedback and task-feedback). On the last step OpenCode removes their tools and forces a written answer. Sending them a new message resets the budget.

Claude Code and Copilot CLI have no per-agent step limit, so there the budget becomes an instruction at the end of the agent's prompt: write the deliverable at the latest on the last step. It is followed, not enforced; the watcher's one-hour timeout stays the hard backstop.

Which model#

The model is picked at launch time, from your configuration: the project's default_model, else the one for the project's type in default_model_by_type, else the global default_model. See Choose the agent model.

The commit command#

/pablo-commit-and-pr commits, pushes, opens a draft pull request and moves the task to draft. It's the only part of PABLO that runs as an agent command (OpenCode, Claude Code, or a skill under Copilot), because writing a good commit message and pull request description is where an agent beats plain code. It never changes your git identity. How to use it: Ship your work.

It's called /pablo-commit-and-pr rather than /commit-and-pr so it can live next to a personal /commit-and-pr command you may already have.

The skill#

The pablo-task skill teaches your other agents one thing: how to create a PABLO task (pablo task:start with an issue link, or --project and a prompt). The installer links it into ~/.config/opencode/skill/, into ~/.claude/skills/ under Claude Code, or into ~/.copilot/skills/ under Copilot.

Under Claude Code#

With agent_runtime: claude-code, the same templates are translated rather than rewritten, so the runtimes always run the same prompts and the same guardrails.

  • Where the agents live. pablo system:generate-agents writes all five into ~/.pablo/claude/agents.json, which every launch passes with --agents. The same agents are also rendered as pablo-<agent>.md files in the git-ignored claude/agents/ and linked into ~/.claude/agents by the installer, so they show up in /agents and the @ picker of your own sessions. Those files only carry tool-level limits: the per-command shell denies (such as git push) are launch flags and apply only to PABLO's own launches.
  • How they launch. claude -p --agents … --agent <name> --model <default_model> --session-id <id> --strict-mcp-config, plus the permission flags below.
  • No permission prompts. The analysts run with --permission-mode dontAsk (anything not allowed is denied), the resolver with acceptEdits.

The permissions map as follows:

OpenCode ruleClaude Code
read, grep, glob, webfetchthe Read, Grep, Glob, WebFetch tools
edit *Edit, Write and NotebookEdit
skill *Skill
shell * allowedBash
shell "git commit*" deniedBash(git commit*) and Bash(rtk git commit*) in --disallowedTools

Whole tools are allowed or denied both in the agent definition and on the command line. Command patterns only go on the command line: in an agent definition, a Bash(…) entry removes the whole Bash tool. Claude Code matches * anywhere, so patterns such as *acli jira workitem edit* keep their meaning.

Why every command pattern is denied twice. If you use RTK, its Claude Code hook rewrites git push into rtk git push before permissions are checked, which slips past a plain Bash(git push*) rule. Each denied pattern is therefore emitted raw and with the rtk prefix; a test checks that no OpenCode deny is missing either form.

The commit command is rendered into claude/commands/ (git-ignored) and linked into ~/.claude/commands/. Its body, the !`…` context injection and $ARGUMENTS work as in OpenCode, and its allowed commands become allowed-tools (raw and rtk forms again). One limit: a Claude Code command can't deny a tool, so “no edits” is an instruction in its hard rules rather than a permission.

Under GitHub Copilot CLI#

With agent_runtime: copilot, the same templates are translated once more, so all three runtimes run the same prompts and the same guardrails.

  • Where the agents live. pablo system:generate-agents renders copilot/agents/pablo-<agent>.agent.md (git-ignored) for the five agents, and the installer links them into ~/.copilot/agents/. Unlike Claude Code, they're deliberately visible, with a pablo- prefix, so you can pick them in your own Copilot sessions too.
  • What an agent file holds. name, description and tools (Copilot aliases: read, search, execute, web, edit), and no model: line: in Copilot an agent file's model would override --model.
  • How they launch. copilot --agent pablo-<agent> --model <default_model> --session-id <uuid> --no-ask-user --no-auto-update --no-color --disable-builtin-mcps --available-tools … --allow-tool … --deny-tool … -p '<prompt>'. --available-tools lists exactly the built-in tools the agent may use (the analysts: view, grep, glob, web_fetch, bash; the resolver: view, bash, edit, create), which also hides your MCP tools; --disable-builtin-mcps turns off Copilot's built-in MCP servers. Your own custom instructions (AGENTS.md…) and hooks still load.

The permissions map as follows:

OpenCode ruleCopilot CLI
read * allowedtool view, --allow-tool read
grep, globtools grep, glob
webfetchtool web_fetch, --allow-all-urls
shell * allowedtool bash, --allow-tool shell
edit * allowedtools edit, create, --allow-tool write
edit * denied--deny-tool write
skill deniedskill left out of the available tools
shell "git push*" denied--deny-tool 'shell(git push)' and 'shell(git push:*)', plus shell(rtk git push) and shell(rtk git push:*)

Copilot matches a command prefix, so leading and trailing * are dropped: *acli jira workitem edit* becomes acli jira workitem edit. A pattern with a * in the middle can't be translated, and generation fails. In Copilot a deny always wins over an allow. The command patterns only exist on PABLO's launches: when you run a pablo-* agent by hand, only the visible tools from its agent file apply.

The step budget works as under Claude Code: no per-agent limit, so it becomes an instruction at the end of the prompt.

Copilot has no !`…` context injection, so the commit command becomes a skill, copilot/skills/pablo-commit-and-pr/SKILL.md, linked into ~/.copilot/skills/. Its context section tells the agent to run those commands first, and disable-model-invocation: true keeps the model from running it on its own: only you typing /pablo-commit-and-pr does. The “no code edits” rule is restated in its hard rules, and --force still works as part of your request.

This runtime was built from Copilot CLI's documentation, without the CLI at hand: loading agents from ~/.copilot/agents during -p, compound commands (a && b) against prefix denies, and skill argument passing are not verified live yet.

Customise the agents#

The agent files are generated, not written by hand. Edit the sources in the repository, then regenerate:

bash
pablo system:generate-agents
  • opencode/agents/*.md.template: one per agent, with its own description and prompt;
  • opencode/agents/shared/analysts.frontmatter.md: the read-only permissions shared by the four analysts;
  • opencode/agents/shared/resolver.frontmatter.md: the resolver's permissions;
  • opencode/agents/shared/housekeeping.body.md: the house rules appended to every agent.

The same sources produce the Claude Code agents.json and command when agent_runtime is claude-code, and the Copilot agent files and skill in copilot/ when it is copilot. Templates pull these in with {{SHARED_FRONTMATTER:<profile>}} and {{SHARED_BODY:<profile>}}, and the task agents get tracker-specific instructions through {{ISSUE_TRACKER_SECTION}} and {{ISSUE_TRACKER_NAMES}}, filled in for the trackers your projects use. Generation runs on install, and again when pablo project:new or pablo project:remove changes the set of trackers. Never edit the generated .md files: they're overwritten.

PreviousTask states NextSync & rebase

Edit this page on GitHub

On this page

  • The agents
  • The rebase-conflict resolver
  • Read-only, enforced
  • Context fetched up front
  • Step limits
  • Which model
  • The commit command
  • The skill
  • Under Claude Code
  • Under GitHub Copilot CLI
  • Customise the agents
PABLO

MIT licensed · made by Baptiste Leduc · GitHub · Docs