Configuration and overrides

Puppets ships safe defaults. Each caller keeps its policy beside its code, and Puppets loads that policy only from the repository’s trusted default branch.

Available settings

Setting Default Purpose
version 1 Configuration schema version.
approvalActors required GitHub logins allowed to apply the human trust gate.
maxNewIssues 1 Maximum new Copilot assignments in one run.
maxInFlight 2 Maximum issues in active implementation or review states.
conflictRetries 2 Merge-conflict remediation attempts before human escalation.
reviewRetries 2 Acceptance-review remediation cycles before escalation.
copilotModel "auto" Copilot SDK model used by curation and acceptance review.
claudeModel "" Optional model override for the claude implementation provider. Empty uses that action’s own default.
codexModel "" Optional model override for the codex implementation provider. Empty uses that action’s own default.
staleHours 72 Age at which untouched issues return to the attention summary.
ignoreLabels [] Repository-owned processes Puppets must leave alone.

Ignored processes

ignoreLabels supports repository-owned processes that should coexist with Puppets without entering its generic lifecycle. Ignored issues are excluded from triage, inbox reporting, assignment, and pull-request reconciliation.

Workflow DSL

Puppets compiles a versioned workflow definition before it performs any mutation. The built-in basic workflow declares named stages, handler kinds, outcome branches, labels, and profiles.

Create .puppets/workflow.yml to overlay it. Named stages, profiles, control-label roles, and helper labels merge by identity, so callers do not copy the full workflow. Set metadata.name to give the resolved workflow a repository-specific name in logs and workflow summaries. The file explorer below includes a complete incident-review overlay.

implementation.prompt selects a Markdown prompt by name. Add a matching file such as .puppets/prompts/incident-review.md to replace the framework prompt from the trusted default branch. Prompt files are capped at 20 KB.

The compiler rejects duplicate labels, dangling branches, unsupported DSL versions, unknown approval routes, missing security roles, and malformed profiles. Label names are policy data rather than runtime constants. The opt-out label can be renamed, but an opt-out role must always exist.

Profiles

The default basic profile routes approved work through curation and then implementation. Profiles select issues by labels and can choose an approval branch, implementation prompt, trusted guidance file, and heading. Higher-priority matching profiles win; exactly one profile must be the default.

Implementation providers

profile.implementation.provider selects which agent performs the implementation step for issues matching that profile. It defaults to copilot and is validated against a fixed, code-defined allowlist — copilot, claude, or codex — so a caller overlay can never name an arbitrary GitHub Action, only one of these three built-in behaviors:

implementation:
  provider: claude

copilot (the default) assigns the GitHub Copilot coding agent to the issue directly, as Puppets has always done; it works out of band and Puppets later finds the pull request it opens.

claude and codex run as GitHub Actions steps instead of an assignable bot. Because a reusable workflow’s reconcile.js step cannot itself invoke a uses: step, the reconciler emits a small job descriptor (issue number, branch, provider, and prompt/directive text — never raw issue or PR body content beyond what a human already sees) and a separate implement job in reconcile.yml runs the framework-selected provider action, then deterministically commits, pushes, and opens a draft pull request itself. Neither provider action is trusted to create the pull request on its own; the draft state keeps claude/codex-authored PRs subject to exactly the same CI and acceptance-review gates as a Copilot-authored one before a maintainer sees them out of draft.

This job is entirely skipped — no checkout, no secrets used — for any caller where every matching profile still uses copilot, so adopting providers is opt-in per profile and existing callers are unaffected.

Curation and acceptance review remain Copilot-only. Selecting claude or codex only changes who implements an approved issue; issue triage/curation and the acceptance-review gate before merge still call the Copilot SDK (copilotModel) regardless of implementation.provider. Puppets does not claim Copilot-free operation for a profile that uses another implementation provider.

Secrets and permissions

claude needs secrets.anthropic_api_key or secrets.claude_code_oauth_token (the latter from claude setup-token, for Claude Pro/Max plan users, as an alternative to a metered API key); codex needs secrets.openai_api_key. Wire only the secret(s) your chosen provider(s) need through the caller workflow’s secrets: block (see caller-template.yml), and set the caller’s top-level permissions.contents to write. GitHub validates the reusable workflow’s provider job before evaluating whether it is skipped, so this declared maximum is required for every caller; only Claude and Codex runs actually use it to push branches and open pull requests. A reusable workflow can never receive more access than the caller allows. See Getting started for the full setup and a dry-run test procedure.

Explore the files

config/workflow.yml
Open
Loading workflow definition...

Use prompt replacement for repository conventions, validation commands, generated files, or domain-specific acceptance evidence. Security rules remain in runtime code and cannot be replaced by a prompt.

Prompts referenced by a profile do not need to exist in the framework. A caller may add a new .puppets/prompts/<name>.md file and select it from .puppets/workflow.yml.