# Azure OpenAI Source: https://docs.pullfrog.com/azure Run Pullfrog on OpenAI models deployed in your own Azure OpenAI resource. Route Pullfrog's model calls through your own Azure OpenAI resource. Inference bills to your Azure subscription, so Azure credits and commitments apply. Azure OpenAI is bring-your-own-key only. Pullfrog never proxies Azure traffic. ## Setup In the Pullfrog console, pick the **Azure OpenAI** tile on the **Provider** card. Click **Set up** on the tile and fill in the five values from the table below. Pullfrog injects them into every run, so `pullfrog.yml` needs no changes. The Configure Azure OpenAI dialog with its five fields To keep them in the workflow instead, put `AZURE_API_KEY` in a GitHub Actions secret and the rest in the `env:` block of `.github/workflows/pullfrog.yml`: ```yaml theme={null} env: AZURE_RESOURCE_NAME: my-resource AZURE_API_KEY: ${{ secrets.AZURE_API_KEY }} AZURE_DEPLOYMENT: my-deployment AZURE_CONTEXT: "400000" AZURE_MAX_OUTPUT: "128000" ``` ## Variables | Name | Secret | Purpose | | - | - | - | | `AZURE_RESOURCE_NAME` | No | The `` in `https://.openai.azure.com`. | | `AZURE_API_KEY` | Yes | A key for that resource. | | `AZURE_DEPLOYMENT` | No | The deployment's name, which is not always the model's name. | | `AZURE_CONTEXT` | No | Context window of the model behind the deployment, in tokens. | | `AZURE_MAX_OUTPUT` | No | Maximum completion tokens that model accepts. | | `AZURE_USE_CHAT_COMPLETIONS` | No | Optional. Set to `"true"` for a model that predates the Responses API. | The first five are required. The two limits must be positive numbers, so `128k` is rejected. A value set in the workflow wins over a stored one. On an account that pays through [Pullfrog Router](/billing#pullfrog-router), store the values in the Pullfrog console. Pullfrog decides how to fund a run before the runner starts, when GitHub Actions secrets are not visible to it, so a run whose key exists only there falls back to the Router's default model. ### Token limits A deployment name carries no model metadata, so Pullfrog cannot look up the limits and needs you to declare them. Undeclared limits would break two things: * **Completions are capped at 32000 tokens**, and a model with a smaller cap rejects every request. * **Auto-compaction turns off.** Compaction keys off the context limit, so a long session grows until Azure refuses it. Set `AZURE_CONTEXT` to the real window of the deployed model. A low value compacts earlier than needed; a high value delays compaction until Azure refuses the request. ### Reasoning effort The [effort setting](/models#reasoning-effort) does not apply to Azure runs. A deployment name does not identify a model, so Pullfrog sends no effort level and the model's own default applies. ## Deployment name Azure routes on the deployment name, not the model name. Set `AZURE_DEPLOYMENT` to the name given to the deployment, which defaults to the model's name but is often changed: * Deployed `gpt-5` and kept the default name: `AZURE_DEPLOYMENT: gpt-5` * Renamed the deployment `prod-reasoning`: `AZURE_DEPLOYMENT: prod-reasoning` Find the name under **Deployments** in [Microsoft Foundry](https://ai.azure.com), or under **Model deployments** on the resource in the Azure portal. Any OpenAI model the resource has deployed works. Non-OpenAI models on Azure, such as Anthropic, DeepSeek, Llama, Mistral and Phi, are [Foundry Models](https://learn.microsoft.com/en-us/azure/ai-foundry/foundry-models/) served from a different endpoint, which this integration cannot reach. Point [OpenAI-compatible endpoints](/openai-compatible) at the Foundry inference URL for those. ## Routing Pullfrog sends requests to the resource's Responses endpoint, `/openai/v1/responses`, through OpenCode's `azure` provider. GPT-5-family models speak it as deployed. Older deployments such as `gpt-4` and `gpt-35-turbo` speak only Chat Completions; set `AZURE_USE_CHAT_COMPLETIONS: "true"` for them. Pullfrog sends a static key and cannot refresh a Microsoft Entra ID token during a run. If your organization forbids resource keys, put a gateway that does the token exchange in front of the resource, and point [OpenAI-compatible endpoints](/openai-compatible) at the gateway. ## Troubleshooting | Symptom | Fix | | - | - | | `AZURE_DEPLOYMENT env var is required when the model is set to "azure/byok"` | The repository uses Azure OpenAI, but no deployment name is stored or set in the workflow. | | "Azure OpenAI selected but required configuration is missing" | The message names each missing value. Store it in the console or list it in the workflow `env:`; GitHub Actions passes only the secrets the workflow file names. | | HTTP `404` from Azure | `AZURE_RESOURCE_NAME` does not match the endpoint hostname, or `AZURE_DEPLOYMENT` is not a deployment on that resource. A Foundry model also returns `404` here. | | HTTP `401` from Azure | The key belongs to a different resource. Each resource has its own keys. | | An error about the Responses API | The deployment serves a model that predates it. Set `AZURE_USE_CHAT_COMPLETIONS: "true"`. | # Amazon Bedrock Source: https://docs.pullfrog.com/bedrock Run Pullfrog on models hosted in your own AWS account through Amazon Bedrock. Route Pullfrog's model calls through [Amazon Bedrock](https://aws.amazon.com/bedrock/) in your own AWS account. Use it to spend AWS credits or an enterprise AWS commitment, keep inference inside AWS for compliance, or use provisioned throughput you already pay for. Bedrock is bring-your-own-key only. AWS bills inference to your account, and Pullfrog never proxies Bedrock traffic. ## Setup In the Pullfrog console, pick the **Amazon Bedrock** tile on the **Provider** card. Amazon Bedrock picked on the Pullfrog console Provider card Click **Set up** on the tile and save one of these: * A Bedrock API key, created under **API keys** in the [Bedrock console](https://console.aws.amazon.com/bedrock/home#/api-keys). It becomes `AWS_BEARER_TOKEN_BEDROCK`. * An IAM access-key pair whose policy allows `bedrock:InvokeModel` and `bedrock:InvokeModelWithResponseStream`. The Configure Amazon Bedrock dialog with the bearer token and access key fields You can store the credential as a GitHub Actions secret instead and map it in the workflow's `env:` block. Add `AWS_REGION` and `BEDROCK_MODEL_ID` to the `env:` block of `.github/workflows/pullfrog.yml`. Neither is secret. ```yaml theme={null} - name: Run agent uses: pullfrog/pullfrog@v0 with: prompt: ${{ inputs.prompt }} env: AWS_REGION: us-east-1 BEDROCK_MODEL_ID: us.anthropic.claude-opus-5-5 # only when the credential is a GitHub Actions secret AWS_BEARER_TOKEN_BEDROCK: ${{ secrets.AWS_BEARER_TOKEN_BEDROCK }} ``` Anthropic models only: before the first call, submit the one-time use-case form in the [Bedrock console](https://console.aws.amazon.com/bedrock/). Open **Model catalog**, pick an Anthropic model, and complete the form. ## Variables | Name | Secret | Purpose | | - | - | - | | `AWS_BEARER_TOKEN_BEDROCK` | Yes | Bedrock API key. Use this or the access-key pair. | | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` | Yes | IAM access-key pair. | | `AWS_SESSION_TOKEN` | Yes | Optional. Needed only with temporary STS credentials. | | `AWS_REGION` | No | AWS region to call, for example `us-east-1`. | | `BEDROCK_MODEL_ID` | No | Exact Bedrock model ID. Pullfrog runs it as written and never upgrades it. | A credential stored in the console needs no `env:` line, because Pullfrog injects it into every run. A value set in the workflow wins over a stored one. On an account that pays through [Pullfrog Router](/billing#pullfrog-router), store the credential in the Pullfrog console. Pullfrog decides how to fund a run before the runner starts, when GitHub Actions secrets are not visible to it, so a run whose credential exists only there falls back to the Router's default model. ## Model IDs The model menu has a single **Amazon Bedrock** entry; `BEDROCK_MODEL_ID` names the actual model. Copy the ID from the **Programmatic Access** section of the model's card in [Bedrock's model list](https://docs.aws.amazon.com/bedrock/latest/userguide/model-cards.html). For example: ```bash theme={null} us.anthropic.claude-opus-5-5 # Claude Opus 5.5, US cross-region inference profile amazon.nova-pro-v1:0 # Amazon Nova Pro, in-region openai.gpt-oss-120b-1:0 # gpt-oss-120b, in-region ``` Cross-region inference profiles carry a geography prefix such as `us.`, `eu.`, `jp.`, `au.` or `global.`. Pick the prefix that matches `AWS_REGION`, or use the bare in-region ID where the model card lists one. To change models, edit `BEDROCK_MODEL_ID` and commit. ## Routing Pullfrog reads the model ID to choose the agent: * **Anthropic models**, whose ID contains an `anthropic` segment, run on [Claude Code](https://code.claude.com/docs/en/amazon-bedrock). Pullfrog sets `CLAUDE_CODE_USE_BEDROCK=1` for Claude Code. * **Every other model** runs on OpenCode's `amazon-bedrock` provider. An application inference profile ARN routes to OpenCode unless its name contains an `anthropic` segment. For an Anthropic model behind such an ARN, set `PULLFROG_AGENT: claude` in the workflow `env:`. ## Troubleshooting | Symptom | Fix | | - | - | | `BEDROCK_MODEL_ID env var is required when the model is set to "bedrock/byok"` | The repository uses Amazon Bedrock, but the workflow does not set `BEDROCK_MODEL_ID`. Add it to `env:`. | | "Bedrock model selected but required configuration is missing" | The message lists each missing value: the credential, `AWS_REGION`, or `BEDROCK_MODEL_ID`. | | `AccessDeniedException` on an Anthropic model | The account has not submitted the Anthropic use-case form. Submit it in the Bedrock console, then re-run. | | `AccessDeniedException` on another model | The IAM policy behind the access keys lacks `bedrock:InvokeModel` or `bedrock:InvokeModelWithResponseStream` for that model. | | `ValidationException` about the model ID | The ID is not valid in `AWS_REGION`. Check the model card's **Programmatic Access** section and match the geography prefix to the region. A model without on-demand throughput needs its inference profile ID. | # Billing Source: https://docs.pullfrog.com/billing Pullfrog plans and prices, the organization trial, subscribing, and funding model usage through Pullfrog Router. Pullfrog bills two things separately: a plan for private organization repositories and hosted features, and model usage. Both are managed in the **Billing** card of the account console. ## Plans | Plan | For | Price | What it adds | | - | - | - | - | | Free | Every account | \$0 | Unlimited runs on public repositories, and on a personal account's private repositories | | Pro | Personal accounts | \$30/month | [Signed commits](/security#signed-commits), the observability dashboard, [issue indexing](/issue-enrichment#issue-indexing) and [Smart](/models#smart) model selection | | Organization | GitHub organizations | \$30/month per organization | Runs on private repositories, plus everything in Pro | | Enterprise | GitHub Enterprise Cloud organizations | \$80/month per organization | Everything in Organization, plus per-person usage analytics | Organization and Enterprise have no per-seat charge. Public repositories run free on every plan, and a personal account never needs a plan to run. No plan includes model tokens. Pay for those with your own key or subscription, a free model, or [Pullfrog Router](#pullfrog-router) at provider cost with no markup. See [model access](/model-access). Enterprise covers GitHub Enterprise Cloud organizations on `github.com`, and each organization in an enterprise subscribes separately. It does not include GitHub Enterprise Server, isolated GitHub hosts, SSO, compliance certifications, SLAs or on-premises hosting. The observability dashboard at `pullfrog.com/console//analytics` charts model spend, PR reviews and runs by week or month. The observability dashboard with weekly Spend, PR reviews and Runs charts ## Trials ### Organization trial An organization gets a **14-day trial with no card**, starting with its first run on a private repository. Installing the app does not start it, and an organization that only runs on public repositories never needs one. | When | What happens | | - | - | | Day 0 | The first private-repository run starts the trial, with every paid feature included | | Day 14 | The trial ends and a 7-day grace period begins. Private-repository runs continue, and Pullfrog emails the organization. | | Day 18 | Pullfrog emails a reminder, 3 days before the pause | | Day 21 | Private-repository runs pause until the organization subscribes | An organization with 10 or fewer runs when its trial ends gets one more 14-day trial instead of the grace period. During the trial, a run with no working model credential can fall back to an efficient model that Pullfrog pays for; the grace period does not include this. ### Personal model allowance A personal account gets no trial, because it needs no plan to run. It gets a one-time **30-day introductory model allowance** instead, starting when its first repository is set up or its first workflow runs. While the allowance lasts, a run with no usable credential falls back to an efficient model that Pullfrog pays for. The allowance does not unlock Pro features and does not restart when you add a repository or reinstall the app. Buying Pro does not pay for model usage. ## Subscribing and payment Open `pullfrog.com/console/` and use **Upgrade to Pro** in the **Plan and payment** card. On an organization it subscribes to Organization, or to Enterprise on GitHub Enterprise Cloud. Stripe Checkout shows the monthly price, applicable taxes and the first charge date, asks you to accept Pullfrog's Terms, and saves the payment method. An organization that subscribes during its trial keeps its remaining trial days; a personal upgrade is charged at Checkout. A card added only for Pullfrog Router never starts a subscription. | Control | What it does | | - | - | | **Payment method** row | Shows the card brand and last four digits, or **Stripe Link**. Its pencil opens the Stripe Customer Portal to change the card or the billing email. | | **Manage plan** | On a subscribed organization, opens the Stripe Customer Portal to change the plan | | **View billing history** | At the foot of **Plan and payment**: a page listing plan invoices | | **View Router history** | At the foot of the **Pullfrog Router** tab: a page listing Router top-ups and credit grants | The Plan and payment card on a free personal account, with the Upgrade to Pro offer The Router history page with a signup credit grant An existing subscription keeps the price it was bought at. A new subscription after a cancellation uses the current price. On an organization, only GitHub organization owners can see and change billing. Other members, repository admins included, see a message to ask an owner. ## Pullfrog Router Pullfrog Router reaches every major model provider through one billing account, at raw provider cost with no markup. Pullfrog mints a short-lived key for each run, so you manage no provider keys. The **Providers** section of the **Billing** card switches the whole account between two tabs at any time: | Tab | Who pays for model usage | | - | - | | **BYOK** (recommended) | Your provider, through your own [API key](/keys) or [subscription](/model-access#your-existing-subscription) | | **Pullfrog Router** | Your Router credit balance | A provider key stored with Pullfrog is used for the models it covers even on Router. Router runs draw on a prepaid **Router credit balance**. Use **Add payment method** in the **Top up** row to save a card, then **Add credit** for a one-time top-up. Without a card, a positive balance runs DeepSeek Flash only, and runs stop at zero. The Pullfrog Router tab: credit balance, Top up, auto-reload and the monthly spend limit ### Auto-reload Auto-reload is off by default. Turn it on once a card is on file, and Pullfrog charges the card whenever the balance drops below your threshold. With auto-reload off, runs stop when the balance reaches \$0, and the PR comment links to the console to add credit. | Setting | What it does | Range | | - | - | - | | **Auto-reload amount** | Credit added per reload. The balance lands at its current value plus this amount. | $10 to $100,000 | | **Auto-reload threshold** | The balance that triggers a reload | $5 to $10,000 | Each charge adds an estimated card processing fee on top of the credit amount, with no Pullfrog markup: 2.9% + $0.30 for US cards and 4.4% + $0.30 for international cards. ### Monthly spend limit **Monthly spend limit** caps how much auto-reload can charge in one UTC calendar month, resetting at 00:00 UTC on the 1st. The field appears with auto-reload; leave it empty for no limit, or set at least \$10. Manual top-ups don't count toward the limit and are never blocked. Once a limit is set, **Behavior at limit** chooses what happens when the next reload would cross it: | Behavior | What happens | | - | - | | **Hard cap** | Pullfrog refuses the reload and emails you. Runs keep spending the credit already in the wallet; at \$0 they stop until you raise the limit, top up by hand, or the month resets. | | **Alert only** | The reload goes through, and Pullfrog emails you | Auto-reload and the spend limit can also be set from the CLI. See [CLI configuration](/cli-configuration#keys-and-values). ## Open source program Maintainers of public repositories with more than 1,000 stars can apply to [Pullfrog for OSS](https://pullfrog.com/for-oss). Pullfrog covers the model costs of accepted repositories on a funded set of models; see [Pullfrog for OSS](/models#pullfrog-for-oss). # Claude subscription Source: https://docs.pullfrog.com/claude-auth Run Anthropic models on your Claude Pro or Max plan instead of paying for API tokens. Run Pullfrog on the Claude Pro or Max plan you already pay for, with no Anthropic API bill on top. One command stores the token, and every run on an Anthropic model uses it. A Claude subscription covers the Anthropic models: Claude Fable, Claude Opus, Claude Sonnet and Claude Haiku. For other providers, see [Model access](/model-access). ## Setup Run this inside a clone of the repository. The CLI uses the [GitHub CLI](https://cli.github.com) to sign you in, so run `gh auth login` first if you have not. ```bash theme={null} npx pullfrog auth claude ``` The CLI: 1. Opens a Claude sign-in in your browser. Sign in with the account on the Pro or Max plan and approve it. 2. Receives the token `claude setup-token` would print: inference-only, valid for a year, starting with `sk-ant-oat`. Claude Code does not need to be installed. 3. Saves it to Pullfrog's encrypted store. Pullfrog refuses a token that Anthropic rejects. The CLI shows which account signed in. A browser signs in as the account it already holds, so to connect a different one, sign out of Claude in that browser or open the sign-in link in a private window. ### Remote machines The sign-in finishes on `localhost`, so the browser must be on the machine that runs the CLI. Over SSH, or on Linux with no display, the CLI asks for a token instead: run `claude setup-token` from [Claude Code](https://code.claude.com/docs) on any machine with a browser, and paste the token it prints. Pass `--paste-token` to choose this yourself: ```bash theme={null} npx pullfrog auth claude --paste-token ``` The next run on an Anthropic model uses the subscription. Run the command again to add another account or replace one. Each connection is labelled with the last six characters of its token. With several connections, or an `ANTHROPIC_API_KEY` beside them, Pullfrog moves to the next credential when one is rejected or out of quota; see [multiple subscriptions and fallback](/keys#multiple-subscriptions-and-fallback). The Subscriptions row of the Providers section: Claude Pro/Max, ChatGPT (Codex) and Grok ## Scope On an organization repository, the CLI asks where to store the token: | Option | Scope | Who can save it | | - | - | - | | **`` organization** | Every repository in the organization | Organization owner | | **`/` only** | This repository | Repository admin | A personal account has only the account scope, so the CLI does not ask. To skip the prompt or run outside a checkout, pass the scope as a flag: ```bash theme={null} npx pullfrog auth claude --org my-org # organization scope npx pullfrog auth claude --repo my-org/my-repo # one repository ``` ## Credential refresh The token is static and lasts a year. Pullfrog stores no refresh token, so nothing rotates between runs. Run `npx pullfrog auth claude` again when the token expires or you revoke it, and pick the old connection to replace. ## Troubleshooting | Symptom | Fix | | - | - | | The CLI waits after you approve in a browser on another machine | The sign-in returns to `localhost` on the machine that ran it. Cancel, and run `npx pullfrog auth claude --paste-token`. | | `claude: command not found` while using `--paste-token` | Install [Claude Code](https://code.claude.com/docs) on the machine with the browser, then run `claude setup-token` there. | | Run comment: "Your Claude Pro/Max subscription was rejected by its provider" | The token expired or was revoked. Run `npx pullfrog auth claude` and replace the old connection. | | Run comment: "Your Claude subscription has hit its usage limit" | The plan's usage window is spent. Re-trigger after the reset, or add an `ANTHROPIC_API_KEY` so runs continue on the API key until then. | # CLI configuration Source: https://docs.pullfrog.com/cli-configuration Inspect and change repository settings, organization defaults, and stored credentials. The `pullfrog` CLI reads and writes the same settings as the console, from a terminal or a script. Each value shows where it comes from: the repository, the organization default, or Pullfrog's default. ```console theme={null} $ pullfrog config list --repo pullfrog/scratch pullfrog/scratch enabled true [repo] model "openai/gpt-sol" [org] effort 0.5 [default] push "enabled" [repo] shell "restricted" [repo] review.mode "agent" [repo] review.re-review true [repo] issue.mode "links" [repo] # ... $ pullfrog config describe review.mode review.mode behavior when a PR is opened values: none | links | agent unset: not allowed write access: repo write ``` ```bash theme={null} pullfrog config get model pullfrog config set model anthropic/claude-opus pullfrog config unset model ``` ## Install and sign in Install the CLI from npm, or run it with `npx` without installing: ```bash theme={null} npm install --global pullfrog@latest npx pullfrog@latest config list ``` The CLI acts as the GitHub user signed in to the [GitHub CLI](https://cli.github.com). Run `gh auth login` once; the CLI then sends whatever `gh auth token` prints, which is `GH_TOKEN` or `GITHUB_TOKEN` when either is set. The token needs the `repo` and `read:org` scopes, which `gh auth login` requests by default. ## Scope Commands act on the repository in the current directory's GitHub `origin` unless you name a target: ```bash theme={null} pullfrog config get model --repo acme/api pullfrog config set model openai/gpt-sol --org acme pullfrog config set enabled false --repo acme/api ``` The `--repo` option (alias `-R`) selects one repository. The `--org` option selects organization defaults, or a personal account's shared settings. You cannot combine them. Disabling a repository affects that repository only. Re-enabling it does not install a missing workflow; run `pullfrog init` for setup. ## Keys and values ```bash theme={null} pullfrog config keys pullfrog config keys review pullfrog config keys --org acme pullfrog config describe shell ``` The `keys` and `describe` commands work offline and describe what the installed CLI supports, not what you may change. The `list` command shows the source of each value and whether you can write it. | Repository keys | Values | | - | - | | `enabled`, `progress-comments`, `oss`, `signed-commits`, `auto-merge` | `true` or `false` | | `model` | `provider/model`, or unset | | `effort` | Number from `0` to `1`, or unset | | `instructions`, `env-allowlist` | Text, or unset | | `push`, `shell` | `disabled`, `restricted`, `enabled` | | `hooks.setup`, `hooks.post-checkout`, `hooks.pre-push`, `hooks.stop` | Script text, or unset | | `prompts.review`, `prompts.build`, `prompts.plan`, `prompts.address-reviews`, `prompts.fix-ci` | Text, or unset | | `mention.enabled`, `mention.non-collaborators` | `true` or `false` | | `mention.instructions` | Text, or unset | | `review.mode` | `none`, `links`, `agent` | | `review.non-collaborators`, `review.re-review`, `review.approve`, `review.drafts`, `review.own-prs`, `review.status-check`, `review.approval-check` | `true` or `false` | | `issue.mode` | `none`, `links`, `plan`, `build`, `custom` | | `issue.instructions`, `label.instructions` | Text, or unset | | `issue.non-collaborators`, `label.enabled`, `address-reviews.enabled`, `fix-ci.own-prs`, `fix-ci.reviewed-prs` | `true` or `false` | The `hooks.stop` key is accepted and stored, but Pullfrog does not currently run a stop hook. | Organization keys | Values | | - | - | | `model`, `effort`, `instructions` | Same types as the repository keys | | `xrepo.brief` | Text, or unset | | `billing.mode` | `byok`, `router` | | `billing.auto-reload` | `true` or `false` | | `billing.reload-threshold-usd` | Whole USD, `5`โ€“`10000` | | `billing.reload-amount-usd` | Whole USD, `10`โ€“`100000` | | `billing.monthly-limit-usd` | Whole USD, `10`โ€“`1000000`, or unset for unlimited | | `billing.limit-mode` | `hard_cap`, `alert_only` | ### Inherited defaults When a repository has no model or effort of its own, `get` prints the organization default. With neither set, model prints `auto` and effort prints `0.5`. Unsetting a repository value restores inheritance. These are configured defaults, not a prediction of the next run: [flags](/flags), workflow inputs, credentials and funding can all change what runs. Outside collaborators cannot read private organization defaults, so an inherited value shows as unavailable to them. ### Text and scripts ```bash theme={null} pullfrog config set instructions --file instructions.md pullfrog config set hooks.setup --file setup.sh pullfrog config set prompts.review 'Check authorization boundaries.' pullfrog config unset prompts.review ``` Use `--file -` to read from stdin. Each prompt key changes only that prompt. The environment allowlist takes one variable name per line. ### Confirmations These changes ask for confirmation before they are written: * Disabling a repository or its OSS funding. * Widening `push` or `shell`, or adding names to the environment allowlist. * Allowing non-collaborators, or letting reviews approve. * Enabling auto-merge. * Raising automatic charges: switching to Router billing, enabling auto-reload, raising a billing amount, removing the monthly limit, or choosing `alert_only`. Without a terminal, pass `--yes`. Enabling auto-merge also needs `--ack-auto-merge`, or typing `MERGE` at the prompt. A confirmation never grants a permission you lack. ```bash theme={null} pullfrog config set enabled false --repo acme/api --yes pullfrog config set auto-merge true --yes --ack-auto-merge ``` The `oss` key turns an existing funding grant on or off; it does not enroll a repository. Turning a grant on can clear an incompatible model, and the CLI reports it. Signed commits and auto-merge still depend on the plan and on runtime checks. ## Secrets ```bash theme={null} pullfrog secret list pullfrog secret list --org acme pullfrog secret set OPENAI_API_KEY --org acme pullfrog secret set SERVICE_TOKEN --file ./token --repo acme/api pullfrog secret delete SERVICE_TOKEN --repo acme/api --yes ``` These commands manage Pullfrog's secret store, not GitHub Actions secrets. * The list shows names only, including organization secrets a repository inherits. Values are never returned. * A repository secret overrides an organization secret of the same name. Deleting the repository copy exposes the organization value again. * Setting a secret prompts for a masked value, or reads it from `--file PATH` (`-` for stdin). Values are never accepted as arguments. * Several names in one command prompt for each value and save together, which suits custom provider credentials. The `--file` option takes one name at a time. Subscription credentials have their own commands: ```bash theme={null} pullfrog auth codex --org acme pullfrog auth claude --repo acme/api pullfrog auth grok --org acme ``` A repository copy of a subscription credential takes precedence over the organization one. Saving one for an organization therefore stops if any repository has its own copy, prints the `secret delete` command for each, and saves nothing. Run those, then run it again. The `secret set` command refuses these three credentials for the same reason; a plain API key has no such restriction. ## Permissions | Change | Required access | | - | - | | Ordinary repository settings | Repo write | | Push, shell, environment allowlist, signing, auto-merge, OSS funding | Repo admin | | Repository secrets | Repo admin | | Organization defaults and instructions | Org member | | Billing settings and organization secrets | Org owner | On a personal account the owner has the organization-owner permissions. Your GitHub token must also reach the target, and a suspended installation cannot be configured. See [Permissions](/organizations) for the full role table. ## Console ```bash theme={null} pullfrog console pullfrog console --org acme pullfrog console --repo acme/api pullfrog console --no-browser ``` The command prints the console URL and opens it when stdout is a terminal. Use the console for payment methods, subscriptions, advanced trigger overrides, learnings and custom flags. Configuration has no bulk apply, export or JSON output. ## CLI compatibility The API rejects a CLI whose contract version it does not support, before it does anything. Releases that keep the contract keep working; you upgrade only when it changes, and older clients that send no contract version are rejected. To upgrade, run `npm install --global pullfrog@latest`, then restart any running `pullfrog watch` or MCP process. If the latest CLI still reports an incompatibility, the matching server deployment has not finished yet. Retry once it has. # Codex subscription Source: https://docs.pullfrog.com/codex-auth Run OpenAI models on the Codex access in your ChatGPT plan instead of paying for API tokens. Run Pullfrog on the Codex access included in every ChatGPT plan, with no OpenAI API bill on top. One command signs you in and stores the credential. A Codex subscription covers the OpenAI models in the picker, including GPT Astra, GPT Sol, GPT Terra and GPT Luna. For other providers, see [Model access](/model-access). ## Setup Run this inside a clone of the repository. The CLI uses the [GitHub CLI](https://cli.github.com) to sign you in, and the [Codex CLI](https://developers.openai.com/codex/cli) must be on your `PATH`. ```bash theme={null} npx pullfrog auth codex ``` The CLI: 1. Runs `codex login` in a temporary Codex home, so your own `~/.codex/auth.json` is untouched. 2. Codex opens the ChatGPT sign-in in your browser. Sign in and approve it. 3. Refreshes the new credential once, then saves it to Pullfrog's encrypted store. The next run on an OpenAI model uses the subscription. Run the command again to add another ChatGPT account or replace one. With several connections, or an `OPENAI_API_KEY` beside them, Pullfrog moves to the next credential when one is rejected or out of quota; see [multiple subscriptions and fallback](/keys#multiple-subscriptions-and-fallback). ### Remote machines The browser sign-in finishes on `localhost`, so the browser must be on the machine that runs the CLI. Over SSH, or on Linux with no display, the CLI signs in with a one-time code instead: it prints a URL and a code to enter in a browser on any device. Pass `--device-auth` to choose the code yourself: ```bash theme={null} npx pullfrog auth codex --device-auth ``` ChatGPT keeps device-code sign-in behind a setting. Turn it on in [ChatGPT security settings](https://chatgpt.com/#settings/Security) for a personal account. On a Team, Business or Enterprise plan, a workspace owner turns it on in [workspace permissions](https://chatgpt.com/admin/permissions), under **Codex Local**. The Subscriptions row of the Providers section: Claude Pro/Max, ChatGPT (Codex) and Grok ## Scope On an organization repository, the CLI asks where to store the credential: | Option | Scope | Who can save it | | - | - | - | | **`` organization** | Every repository in the organization | Organization owner | | **`/` only** | This repository | Repository admin | A personal account has only the account scope, so the CLI does not ask. To skip the prompt or run outside a checkout, pass the scope as a flag: ```bash theme={null} npx pullfrog auth codex --org my-org # organization scope npx pullfrog auth codex --repo my-org/my-repo # one repository ``` ## Credential refresh ChatGPT access tokens last about ten days, and every refresh replaces the refresh token. Pullfrog keeps the stored copy current on its own: * Before a run, Pullfrog refreshes the stored credential when less than a day is left on it. * After a run, Pullfrog saves any token the run refreshed back to its store. The credential must stay in Pullfrog for this to work. A copy in a GitHub Actions secret cannot be updated after a refresh and stops working. ## Troubleshooting | Symptom | Fix | | - | - | | The browser ends on a `localhost:1455` page that does not load | The browser is on a different machine from the CLI. Run `npx pullfrog auth codex --device-auth`. | | The ChatGPT page refuses the one-time code, or asks you to contact your workspace admin | Device-code sign-in is off. Turn it on in [ChatGPT security settings](https://chatgpt.com/#settings/Security), or have a workspace owner turn it on in [workspace permissions](https://chatgpt.com/admin/permissions), then run the command again. | | CLI: "was already connected here, so no subscription was added" | The browser signed in as a ChatGPT account you had already connected. Sign out of ChatGPT in that browser, or open the sign-in link in a private window, then run the command again. | | CLI error: "codex CLI not found on PATH" | Install the [Codex CLI](https://developers.openai.com/codex/cli). The error message includes the install command for your platform. | | Run comment: "Your ChatGPT subscription was rejected by its provider", or `CODEX_AUTH_JSON was rejected by OpenAI` / `Token refresh failed: 401` in the job log | ChatGPT ended the session behind the credential, for example after a sign-out or an expiry. Run `npx pullfrog auth codex` and replace the old connection. | | Job log: "subscription auth skipped: could not create /var/lib/pullfrog" | Pullfrog keeps the credential in a directory the agent cannot read, and creating it needs passwordless `sudo`. Allow passwordless `sudo` for the runner user, use a GitHub-hosted runner, or add an `OPENAI_API_KEY`. | # Coding tasks Source: https://docs.pullfrog.com/coding-tasks Pullfrog addresses review feedback and fixes failing CI on pull requests, guided by your build instructions. Pullfrog keeps pull requests moving: it applies review feedback and fixes failing CI without anyone re-triggering it. Both are cards in the repository console under **Automations**. ## Auto-address reviews When a person submits a review on a PR that Pullfrog opened, Pullfrog applies the feedback and pushes. The **Address reviews** card turns this on or off, and its **Custom instructions** field guides how Pullfrog handles feedback. The Address reviews card in the repository console Line-level comments, **Fix all**, and **Fix ๐Ÿ‘s** are covered in [Address reviews](/pr-reviews#address-reviews). To request a change on any PR, including one Pullfrog did not open, comment with `@pullfrog` and describe the fix. ## Auto-fix CI failures When a check suite fails on an open PR, Pullfrog reads the failure logs, reproduces the failure with the CI commands, fixes it, and pushes to the PR branch. Pullfrog's comment after fixing a failing test job on a pull request The **Fix CI failures** card has two toggles: | Toggle | Default | Applies to | | - | - | - | | **Fix CI failures on Pullfrog's PRs** | On | PRs that Pullfrog opened | | **Fix CI failures on non-Pullfrog PRs under review** | Off | Every other open PR in the repository | The Fix CI failures card with its two toggles Pullfrog skips a failure in these cases: * **Bot commit.** The failing commit was authored or committed by a bot, such as Dependabot or Renovate. This applies to PRs that Pullfrog did not open. * **Failing base branch.** The latest completed check suite on the PR's base branch did not pass, so the failure is likely not the PR's. * **Recent attempt.** Pullfrog already started a CI fix on the same PR within the last hour. During the run, Pullfrog first confirms that the PR caused the failure. If the cause is unrelated, such as a flaky test, an infrastructure problem, or an existing bug, it makes no change and reports why. The card's **Custom instructions** field applies whenever Pullfrog fixes CI, for example "Do not weaken assertions to make CI pass." ## Build instructions Build instructions guide how Pullfrog writes code when it implements a task: a plan, an issue in Build mode, or an `@pullfrog` request for a change. Edit them in the **Custom instructions** field of the **Build** card under **Automations**. The Build card and its Custom instructions field Keep them short and actionable, for example "run `pnpm test` and `pnpm lint` before pushing," "match the patterns in the file you're editing," or "keep PRs small and move unrelated cleanup to a separate PR." Instructions that apply to every run, not only builds, belong under **Agent โ†’ Standing instructions**. # Comparisons Source: https://docs.pullfrog.com/comparisons How Pullfrog compares with the vendor agent actions for GitHub and with GitHub Copilot cloud agent. Several AI coding agents now run on GitHub. Pullfrog runs the same agent CLIs on your GitHub Actions runner and adds event triggers set in a console, tools built for CI, context that carries from run to run, and a sandboxed shell. | Product | From | Where the agent runs | | - | - | - | | [claude-code-action](https://github.com/anthropics/claude-code-action) | Anthropic | Your Actions runner | | [Codex on GitHub](https://learn.chatgpt.com/docs/third-party/github) | OpenAI | OpenAI's cloud | | [run-gemini-cli](https://github.com/google-github-actions/run-gemini-cli) | Google | Your Actions runner | | [OpenCode GitHub action](https://opencode.ai/docs/github/) | OpenCode | Your Actions runner | | [Copilot cloud agent](https://docs.github.com/en/copilot/concepts/agents/cloud-agent/about-cloud-agent) | GitHub | An ephemeral GitHub-hosted environment | | **Pullfrog** | Pullfrog | Your Actions runner, GitHub-hosted or [self-hosted](/security#self-hosted-runners) | Pullfrog runs Claude Code for Anthropic models and OpenCode for every other provider, with an experimental Codex CLI harness for organizations that opt in ([model resolution](/models#model-resolution)). Copilot also offers Claude and Codex as agents to Copilot Pro+ and Enterprise customers, in [public preview since February 2026](https://github.blog/changelog/2026-02-04-claude-and-codex-are-now-available-in-public-preview-on-github/). ## Models and credentials Anthropic's claude-code-action runs Claude, Codex runs OpenAI models, Google's run-gemini-cli runs Gemini, and Copilot cloud agent picks from [GitHub's model list](https://docs.github.com/en/copilot/how-tos/use-copilot-agents/cloud-agent/changing-the-ai-model). Pullfrog runs any major provider, and each account chooses how to pay: * Your own API key, including Amazon Bedrock, Google Vertex AI, Azure OpenAI, and OpenAI-compatible endpoints * A Claude, ChatGPT, Grok, or Kimi Code subscription you already pay for * Pullfrog Router, one prepaid balance across providers at provider cost with no markup * Free models, with no bill at all See [model access](/model-access) for the four routes. ## Triggers Each automation is a toggle in the repo console. The vendor actions express the same events as workflow filters in YAML, which you write and maintain in each repository. | Event | What Pullfrog does | | - | - | | A `@pullfrog` mention in an issue, PR, or review comment | Answers, plans, or changes code, as asked | | PR opened or marked ready for review | Reviews it | | New commits on a reviewed PR | Re-reviews only the new commits | | Issue opened | Posts quick links, writes a plan, implements it, or follows your instructions; can also label it | | Review submitted on a Pullfrog PR | Applies the feedback and pushes | | CI fails on a Pullfrog PR or a reviewed PR | [Fixes the failure](/coding-tasks#auto-fix-ci-failures) | | Prompt typed in the console | Runs the task | Editing a mention cancels its run and starts a new one with the new text. For a schedule, use the [headless action](/headless-action) with GitHub's own `on: schedule` trigger. ## PR review Pullfrog re-reviews a PR as new commits land, and closes out its own findings once they are fixed. * A re-review reads a `git range-diff` against the last reviewed commit, so its feedback covers only what changed. * Before it reviews, Pullfrog checks its own open findings, replies "Addressed in" with the commit, and resolves each thread the new commits fixed. Threads from human reviewers stay open for those reviewers. * The reviewer can hand open questions to read-only specialist subagents, several in parallel. * **Fix all** and **Fix ๐Ÿ‘s** on a review turn its comments into a commit ([address reviews](/pr-reviews#address-reviews)). * With auto-merge on, an approval hands the PR to GitHub's native auto-merge, so branch protection still decides when it merges ([auto-merge](/pr-reviews)). ## Tools built for CI An agent in CI needs more than the GitHub API. Pullfrog ships these tools in the action, already authenticated: | Tool | What the agent gets | | - | - | | CI logs | An index of the relevant lines from a failed check suite, a curated excerpt, and the full log on disk | | PR checkout | The PR branch checked out, fork pushes configured, and the diff written to a file | | Dependency install | Dependencies install in the background while the agent reads code | | File upload | A public URL for a screenshot or artifact, ready to embed in a comment | | [Browser](/tools#browser) | Headless Chromium for checking a running app and taking screenshots | | Progress comment | One comment, updated in place with the agent's task list | | GitHub | Reviews with inline comments, replies, thread resolution, issues, PRs, and labels | See [Tools](/tools) for the full list. ## Context between runs Each review updates a PR-level snapshot that the next review of that PR reads first. Repo-level learnings collect durable facts about the codebase, and you can edit them in the repo console ([learnings](/learnings)). ## Hooks The **Hooks** card in the repo console runs your scripts at fixed points in a run. They run in the same sandbox and scrubbed environment as the agent's shell. The Hooks card: Repo setup script, Post-checkout script and Pre-push script | Hook | When it runs | | - | - | | Repo setup script | Once, before the agent starts | | Post-checkout script | After every branch checkout | | Pre-push script | Before a push. If it fails, the agent gets the output and can fix the problem; later pushes in the run skip the hook | ## Shell and credential isolation The agent has a real shell, git, and network access, but not your secrets. See [Security](/security) for each layer. * Shell commands run in a Linux namespace sandbox. In Restricted mode, which is always on for public repositories and the default for private ones, a default-deny allowlist keeps secrets in the runner environment out of the shell. * Git authenticates with a one-time code per operation, so the GitHub token never enters the agent's environment. * Review and plan runs cannot push or commit code. * Pushes can be limited to feature branches, or turned off. * Runs from non-collaborators are off by default. When you turn them on, those runs are always capped at Restricted. By comparison, claude-code-action scrubs secrets from subprocesses and adds PID-namespace isolation only when it is set to accept triggers from users without write access ([its security docs](https://github.com/anthropics/claude-code-action/blob/main/docs/security.md)). ## Cross-repository runs With the `--xrepo` flag, one run can read and change several repositories in your organization ([cross-repo](/flags#cross-repo)). Copilot cloud agent works in [one repository per task](https://docs.github.com/en/copilot/concepts/agents/cloud-agent/about-cloud-agent). ## Pricing and license The action is open source under the MIT license at [pullfrog/pullfrog](https://github.com/pullfrog/pullfrog). Personal accounts and public repositories run free, and private repositories in an organization take one flat monthly plan per organization, with no per-seat charge ([billing](/billing)). Active open source projects can apply for [funded models](/models#pullfrog-for-oss). ## GitHub Copilot cloud agent Copilot cloud agent is the closest alternative. It is built into github.com and supports MCP servers, hooks, custom agents, and [automations that start sessions on events or a schedule](https://docs.github.com/en/copilot/how-tos/use-copilot-agents/cloud-agent/start-copilot-sessions). | | Copilot cloud agent | Pullfrog | | - | - | - | | Where it runs | An ephemeral GitHub environment with [restricted internet access](https://docs.github.com/en/copilot/concepts/agents/cloud-agent/risks-and-mitigations) | Your Actions runner, including self-hosted runners | | Models | [GitHub's model list](https://docs.github.com/en/copilot/how-tos/use-copilot-agents/cloud-agent/changing-the-ai-model) | Any provider, with your key, a subscription, Pullfrog Router, or free models | | Price | A [Copilot plan](https://docs.github.com/en/copilot/get-started/plans), per granted seat on Business and Enterprise, plus [one premium request per session](https://docs.github.com/en/copilot/concepts/billing/copilot-requests) times the model's rate | A flat plan per organization for private repositories; models paid separately | | Who can trigger it | [Only users with write access](https://docs.github.com/en/copilot/concepts/agents/cloud-agent/risks-and-mitigations) | Collaborators; non-collaborators if you allow them, capped at Restricted | | Repositories per task | One | Several, with `--xrepo` | | Memory | [Copilot Memory](https://docs.github.com/en/copilot/concepts/agents/copilot-memory), in public preview; entries expire after 28 days unused | PR snapshots and repo learnings you can edit | | Built-in tools | [GitHub and Playwright MCP servers](https://docs.github.com/en/copilot/concepts/agents/cloud-agent/mcp-and-cloud-agent); Playwright reaches only localhost | GitHub tools, CI logs, uploads, a browser, and background dependency install | Copilot is ahead on reach and first-party integration: * Sessions start from [GitHub, GitHub Mobile, IDEs, the GitHub CLI, the REST API, Jira, Slack, Microsoft Teams, Azure Boards, Linear, and Raycast](https://docs.github.com/en/copilot/how-tos/use-copilot-agents/cloud-agent/start-copilot-sessions). Pullfrog starts from GitHub and its console. * Commits are authored by Copilot with the assigning developer as co-author, and workflows on its PRs wait for approval from a user with write access ([risks and mitigations](https://docs.github.com/en/copilot/concepts/agents/cloud-agent/risks-and-mitigations)). * [Copilot code review](https://docs.github.com/en/copilot/how-tos/use-copilot-agents/request-a-code-review/configure-automatic-review) can review every new PR and each new push, set by personal setting or ruleset, under the same subscription. ## Feature matrix | | claude-code-action | Codex on GitHub | run-gemini-cli | OpenCode action | Copilot cloud agent | **Pullfrog** | | - | - | - | - | - | - | - | | Runs on | Your runner | OpenAI's cloud | Your runner | Your runner | GitHub's cloud | **Your runner** | | Models | Claude | OpenAI | Gemini | Any OpenCode provider | GitHub's model list | **Any provider** | | Pays for models with | [Anthropic key or Claude subscription, Bedrock, Vertex AI, Foundry](https://github.com/anthropics/claude-code-action/blob/main/action.yml) | [ChatGPT plan](https://learn.chatgpt.com/docs/pricing) | Gemini API or Vertex AI | Your provider keys | Copilot premium requests | **Your key, a subscription, Pullfrog Router, or free models** | | Triggers configured in | Workflow YAML | Codex settings and `@codex` | Workflow YAML | Workflow YAML | GitHub UI and automations | **Repo console** | | Automatic PR review | With a workflow | Yes | Yes | With a workflow | With Copilot code review | **Yes** | | Context kept between runs | Not documented | Not documented | Not documented | Not documented | Copilot Memory (preview) | **PR snapshots and repo learnings** | | Secrets scrubbed from the shell | Only when non-write users may trigger | Not applicable | Not documented | Not documented | Not documented | **Default-deny allowlist** | | Open source | MIT | No (cloud service) | Apache-2.0 | MIT | No | **MIT** | ## When each option fits * **A vendor action** fits when you use one vendor's models, want an `@mention` or a review step, and are happy to own the workflow YAML for each event. * **Copilot cloud agent** fits when your team already pays for Copilot seats, starts work from IDEs, Slack, Jira, or Linear, and works in one repository per task. * **Pullfrog** fits when you want the agent to react to PRs, reviews, issues, and CI failures without YAML, to choose models and credentials per account, to carry context across runs, or to accept restricted runs from outside contributors. Start with [getting started](/getting-started). # Direct prompting Source: https://docs.pullfrog.com/direct-prompting Start a Pullfrog run from the console prompt box, an @pullfrog mention, or a Quick Links button. Tell Pullfrog what to do, from the console or from any GitHub thread. Each prompt starts a GitHub Actions run in your repository. ## Console prompt box Open a repository in the [Pullfrog console](https://pullfrog.com/console), type a prompt, and send it. Use it for tasks that have no issue or PR yet. A prompt typed into the repository console prompt box ## Mentioning `@pullfrog` Mention `@pullfrog` in an issue comment, a PR comment, or a PR review comment. Pullfrog replies in the same thread. An @pullfrog mention on an issue and Pullfrog's reply in the same thread Mentions are configured in the repository console under **Automations โ†’ Mentions**: * Only repository collaborators can trigger a run by default. On public repositories, **Include mentions from non-collaborators** opens mentions to everyone. * **Custom instructions** on the same card are added to every run a mention starts. The Mentions card in the repository console A mention in the body of a new issue or PR starts a run immediately, with the body as the prompt. It takes the place of the automation that would otherwise run on that issue or PR. ## Quick Links Quick Links are an opt-in comment with one-click buttons on each new issue or PR, so the author decides whether to involve Pullfrog. | Posted on | Buttons | | - | - | | New issues | **Build this**, **Make a plan** | | New PRs | **Review this** | To use them, turn off the **Review PRs** or **Enrich issues** card under **Automations**, then turn on **Post an initial comment with Quick Links instead** on the same card. # Flags Source: https://docs.pullfrog.com/flags Double-dash shortcuts in any Pullfrog instruction that pick the model, effort, and timeout, open cross-repo access, or expand into your own text. Flags are double-dash shortcuts you can put in any instruction Pullfrog reads. Built-in flags change how a run behaves, and custom flags expand into text you define. ``` @pullfrog fix the flaky checkout test --opus --timeout=2h ``` ## Where flags are read Pullfrog assembles each run's instructions from these levels, most general first: 1. **Org standing instructions** โ€” every repository in the organization 2. **Repo standing instructions** โ€” every run in the repository 3. **Mentions instructions** โ€” runs started by an `@pullfrog` mention 4. **The per-run request** โ€” your `@pullfrog` prompt, or the triggering automation's instructions when you did not tag Pullfrog The standing levels are always added to the run. The per-run level is one or the other: when you tag `@pullfrog`, your prompt is the request and the automation's instructions do not apply. Flags resolve when Pullfrog starts a run from a GitHub event. A run started with a raw prompt through the [headless action](/headless-action) skips this resolution; configure it with the action's inputs instead. ## Custom flags (aliases) A custom flag is a text alias: define `--refactor` once, and every occurrence expands in place to its replacement text. Use one for any snippet you repeat, such as a refactoring checklist or a review rubric. Define custom flags at the org level, where every repository can use them, or at the repo level, where a flag shadows an org flag with the same name. A flag name starts with a letter and contains letters, digits, underscores, and hyphens. Names are case-sensitive, so `--refactor` and `--Refactor` are different flags. Aliases expand before built-in flags resolve, so an alias can contain built-in flags: ``` --mini โ†’ --model=anthropic/claude-haiku --ship โ†’ --opus --notimeout ``` With these, `@pullfrog fix the flaky test --ship` runs on Claude Opus with no timeout. Expansion is a single pass: an alias inside an alias's text is not expanded again. ### Creating a flag In a repository's console, open **Agent โ†’ Flags**. For an organization-wide flag, open the organization console and expand **Advanced**. Click **Add flag**, enter the **Flag** name without the dashes (for example `refactor`), and enter the **Replacement text**. The Flags card with a --ship alias above the built-in flags ## Precedence Built-in flags resolve last-occurrence-wins across all levels. Reading org, then repo, then the per-run request, the last value of a flag wins, so a more specific level overrides a more general one: ``` org --timeout=2h repo --timeout=30m user --notimeout โ† wins: this run has no timeout ``` Pullfrog removes built-in flags from the text before the agent sees it. They configure the run; they are not part of the prompt. ## Built-in flags | Flag | Effect | | - | - | | [Model flags](#model) | Pick the model for one run | | [`--timeout`, `--notimeout`](#timeout) | Change or remove the run timeout | | [`--debug`](#debug) | Raise the run's logging | | [`--effort`](#effort) | Set reasoning effort | | [`--xrepo`](#cross-repo) | Let the run reach other repositories in the organization | ### Model A model flag overrides the model for one run. Family flags resolve to the latest version of that model, on the repository's current provider when that provider carries it: | Flag | Model | | - | - | | `--opus` / `--sonnet` / `--haiku` | Claude Opus / Sonnet / Haiku | | `--fable` | Claude Fable (limited availability; needs Anthropic Fable access) | | `--gpt` / `--codex` | GPT Sol | | `--gpt-pro` / `--gpt-mini` | GPT Sol Pro / Luna | | `--sol` / `--terra` / `--luna` | GPT Sol / Terra / Luna | | `--gemini` / `--gemini-flash` | Gemini Pro / Flash | | `--grok` | Grok | | `--kimi` / `--kimi-k3` | Kimi K2 / K3 | | `--deepseek` / `--deepseek-flash` | DeepSeek Pro / Flash | | `--minimax` | MiniMax M2.5 | | `--glm` | GLM | | `--model=` | Any model slug, for example `--model=openrouter/claude-opus` | A model flag in your own `@pullfrog` prompt is an explicit request. If the run cannot serve that model, because no provider key is configured, the OSS subsidy does not fund it, or Pullfrog Router cannot serve it, the run fails before the agent starts with an error that names the fix. A model flag in org, repo, or automation instructions is a standing default, and the run treats it like the repository's own model setting. A `--model=` slug that Pullfrog does not recognize is left in the prompt as plain text. ### Timeout | Flag | Effect | | - | - | | `--timeout=` | Set the run timeout, for example `--timeout=30m` or `--timeout=1h30m` | | `--notimeout` | Remove the timeout | The default is 1 hour. A `timeout` input on the workflow step takes precedence over these flags. ### Debug | Flag | Effect | | - | - | | `--debug` | Raise this run's logging so the workflow log shows what the agent and its harness did | Use it when a run fails with nothing useful in the log. The log then records Pullfrog's debug output and each request to your model provider. The flag changes only what the run logs, never what the agent may do, and applies only to the run you put it on. The workflow input does the same for every run of that workflow: ```yaml theme={null} - uses: pullfrog/pullfrog@v0 with: debug: enabled ``` Debug logs are verbose and visible to anyone who can read your repository's Actions logs. Turn debugging on for the run you are diagnosing, then off again. ### Effort | Flag | Effect | | - | - | | `--effort=` | Set reasoning effort: `low`, `medium`, `high`, `xhigh`, `max`, or a position from `0` to `1` such as `0.75` | Higher effort reasons longer and costs more; lower effort finishes faster. Models name and count their levels differently, so `--effort` sets a position on the running model's own range: `low` is its lowest level and `max` its highest. A level between two of the model's levels rounds down. The repository's [effort setting](/models#reasoning-effort) is the default. Like every built-in flag, `--effort=medium` in repo instructions is a standing default that a per-run `--effort=max` overrides. An alias can wrap it: ``` --deep โ†’ --effort=max ``` ## Cross-repo By default a run works only in the repository that triggered it. The `--xrepo` flag lets one run read, and open PRs in, a bounded set of other repositories in the same organization. | Form | Meaning | | - | - | | `--xrepo` | The 10 most recently active repositories the triggering user can access, always including the triggering repository | | `--xrepo=api,shared` | The named repositories, with no count limit; the owner is implied | | `--no-xrepo` | Cancel a cross-repo default set at a more general level | The triggering user's own GitHub permissions bound every cross-repo run, so a run never touches a repository that person could not already touch: * A repository the user can only read is reference-only: the run can clone and inspect it but not open PRs. * A repository the user can write to accepts branches and pull requests. * A run started by a bot rather than a person gets no cross-repo access. For a cross-repo default in org or repo instructions, prefer the value form, which names exactly the repositories a run may reach. During a cross-repo run, the agent calls `list_repos` to see what is in scope and `checkout_repo` to clone another repository, then passes `repo: ""` to the git and pull-request tools to work in it. Two org-level settings steer cross-repo work: a **Cross-repo brief** that you write to describe how your repositories relate, and **Cross-repo learnings** that Pullfrog maintains over time. See [Cross-repo learnings](/learnings#cross-repo-learnings). # Getting started Source: https://docs.pullfrog.com/getting-started Install the Pullfrog GitHub App, choose how to pay for models, add the workflow, and send a first prompt. A repository needs two things to run Pullfrog: the Pullfrog GitHub App and a `.github/workflows/pullfrog.yml` workflow. The console sets up both. Sign in to the [Pullfrog console](https://pullfrog.com/console) with your GitHub account. Sign in to Pullfrog console with GitHub Install the Pullfrog GitHub App on your personal account or on an organization. You can give it access to every repository or only the ones you pick. Install Pullfrog GitHub App on personal account Install Pullfrog GitHub App on organization The console asks for a billing mode. On an organization, an org owner makes this choice. * **Bring your own key**: a provider API key or an existing subscription, billed by your provider. The console then asks for the provider, its credentials, and a model. * **Pullfrog Router**: every model through Pullfrog's gateway, paid from a balance at provider cost with no markup. By default, Pullfrog picks the model for each run. The Choose billing mode step of console onboarding The Pick a provider and Connect provider steps of console onboarding You can switch later under **Providers** in the console's **Billing** section. [Model access](/model-access) compares the options, including [free models](/model-access#free-models). Pick the repositories to set up. The console commits `.github/workflows/pullfrog.yml` to each repository's default branch, or opens a PR when branch protection blocks the commit. To set up a repository later, open it in the console and click **Add workflow directly** or **Add workflow via PR**. The Add workflow directly and Add workflow via PR options on a repository that needs setup Open the repository in the console and type a prompt, such as "Summarize what this repository does." Press the send button, or `Cmd+Enter` (`Ctrl+Enter` on Windows and Linux). Pullfrog dispatches a GitHub Actions run and opens its logs in a new tab. A prompt typed into the repository console prompt box ## Manual workflow setup To add the workflow yourself, create `.github/workflows/pullfrog.yml` (or `pullfrog.yaml`) on the default branch, then click **Verify manual installation** on the repository's console page. ```yaml theme={null} # PULLFROG ACTION โ€” DO NOT EDIT EXCEPT WHERE INDICATED name: Pullfrog run-name: ${{ inputs.name || github.workflow }} on: workflow_dispatch: inputs: prompt: type: string description: Agent prompt name: type: string description: Run name permissions: contents: read jobs: pullfrog: runs-on: ubuntu-latest permissions: id-token: write contents: read steps: - name: Checkout code uses: actions/checkout@v6 with: fetch-depth: 1 - name: Run agent uses: pullfrog/pullfrog@v0 with: prompt: ${{ inputs.prompt }} ``` The console's version adds an `env:` block that maps provider keys from GitHub Actions secrets. Add one only if you keep keys there; Pullfrog Router and keys stored in Pullfrog need no workflow changes. See [GitHub Actions secrets](/keys#github-actions-secrets). ## Next steps * Set up [PR reviews](/pr-reviews), [issue enrichment](/issue-enrichment), and other automations * Tune [build](/coding-tasks#build-instructions) and [review](/pr-reviews#review-instructions) instructions for your repo * Use the action in your own workflows with [CI integration](/headless-action) ## Uninstall Pullfrog Uninstalling the GitHub App stops every run on that account. 1. Open the installed GitHub Apps for your [personal account](https://github.com/settings/installations), or `https://github.com/organizations//settings/installations` for an organization. 2. Click **Configure** next to Pullfrog. 3. Click **Uninstall** at the bottom of the page. The workflow does nothing without the app, so deleting `pullfrog.yml` is optional. To delete your Pullfrog account and its data, email [support@pullfrog.com](mailto:support@pullfrog.com). # Iterating in GitHub Source: https://docs.pullfrog.com/github Take a change from issue to plan to pull request to review without leaving GitHub. Pullfrog works where your team already does: issues, pull requests, and review threads. A change goes from plan to implementation to review without leaving GitHub. ## Plan Open an issue for the work. By default, Pullfrog [enriches new issues](/issue-enrichment): it checks for duplicates, surfaces related context, and posts a plan for actionable requests from collaborators. On a repository that uses [Quick Links](/direct-prompting#quick-links) instead, the issue gets one-click buttons: Pullfrog quick links on a new issue Click **Make a plan**, and Pullfrog posts an implementation plan as a comment on the issue. Pullfrog plan comment To revise the plan, reply with an `@pullfrog` comment, or edit the plan comment yourself. When the plan is ready, click **Implement plan**. Pullfrog plan comment with implementation controls To skip planning, mention `@pullfrog` in the issue body when you open it. The run starts immediately with the body as the prompt. ## Implement **Implement plan** runs against the current text of the plan comment, so your edits are included. An enrichment reply without a plan offers **Implement a fix**, which starts a build from the issue and its discussion. Either way, Pullfrog creates a branch, makes the change, and opens a PR linked to the issue. Set [issue enrichment](/issue-enrichment) to **Build** to implement every new issue without a planning step. ## Review Pullfrog skips its own PRs in [automatic review](/pr-reviews) unless **Review Pullfrog's own PRs** is on. Mention `@pullfrog` in a comment to request a review. For small fixes, the review carries GitHub suggested changes that you can commit from the thread. To ask for another implementation pass, comment on the PR: PR comment requesting changes For feedback on specific lines, reply in the review thread so the request is anchored to that code: An @pullfrog request in a review thread, and Pullfrog's reply After Pullfrog pushes its changes, ask for a re-review to continue the loop: PR comment requesting re-review Pullfrog's reviews also carry **Fix all** and **Fix ๐Ÿ‘s** buttons that apply a whole review, or only the comments you approve, in one run. See [Address reviews](/pr-reviews#address-reviews). # Grok subscription Source: https://docs.pullfrog.com/grok-auth Run xAI models on your SuperGrok or X Premium subscription instead of paying for API tokens. Run Pullfrog on the SuperGrok or X Premium subscription you already pay for, with no xAI API bill on top. One command signs you in and stores the credential, with no second CLI to install. A Grok subscription covers the xAI models: Grok and Grok 4.3. For other providers, see [Model access](/model-access). ## Setup Run this inside a clone of the repository. The CLI uses the [GitHub CLI](https://cli.github.com) to sign you in. ```bash theme={null} npx pullfrog auth grok ``` The CLI: 1. Requests a device code from xAI, then opens the sign-in URL and shows the code. 2. Waits while you sign in and approve the code. The device-code flow also works over SSH and in containers. 3. Refreshes the new credential once, then saves it to Pullfrog's encrypted store. The next run on an xAI model uses the subscription. Run the command again to add another account or replace one. With several connections, or an `XAI_API_KEY` beside them, Pullfrog moves to the next credential when one is rejected or out of quota; see [multiple subscriptions and fallback](/keys#multiple-subscriptions-and-fallback). The Subscriptions row of the Providers section: Claude Pro/Max, ChatGPT (Codex) and Grok ## Scope On an organization repository, the CLI asks where to store the credential: | Option | Scope | Who can save it | | - | - | - | | **`` organization** | Every repository in the organization | Organization owner | | **`/` only** | This repository | Repository admin | A personal account has only the account scope, so the CLI does not ask. To skip the prompt or run outside a checkout, pass the scope as a flag: ```bash theme={null} npx pullfrog auth grok --org my-org # organization scope npx pullfrog auth grok --repo my-org/my-repo # one repository ``` ## Credential refresh Grok access tokens last about six hours, and xAI replaces the refresh token on every use. Pullfrog keeps the stored copy current on its own: * Before a run, Pullfrog refreshes the stored credential when less than an hour is left on it. * After a run, Pullfrog saves any token the run refreshed back to its store. A credential that goes unused for long enough can lapse at xAI. Run `npx pullfrog auth grok` again to replace it. ## Troubleshooting | Symptom | Fix | | - | - | | CLI error: "Grok sign-in timed out" | The device code expires after a few minutes. Run the command again and approve the code sooner. | | Job log: `GROK_AUTH_JSON was rejected by xAI` | xAI refused the stored refresh token, so Pullfrog skips it and tries the next credential for the model. Run `npx pullfrog auth grok` and replace the old connection. | | Job log: "subscription auth skipped: could not create /var/lib/pullfrog" | Pullfrog keeps the credential in a directory the agent cannot read, and creating it needs passwordless `sudo`. Allow passwordless `sudo` for the runner user, use a GitHub-hosted runner, or add an `XAI_API_KEY`. | # CI integration Source: https://docs.pullfrog.com/headless-action Run a Pullfrog agent as one step in any GitHub Actions workflow and pass its result to the next step. The `pullfrog/pullfrog@v0` action behind every Pullfrog automation also works as a step in your own workflows. Run an agent inside a release, deploy or scheduled job, and hand its output to the steps that follow. PR review, issue enrichment, addressing reviews and fixing CI are built-in features you turn on in the [console](https://pullfrog.com/console). Write a custom workflow only for behavior the console does not cover. A custom workflow fits when you want to: * Run an agent as **one step** in an existing pipeline, such as a release, deploy, nightly job or scheduled audit. * Feed the agent's result into **later steps**: a deploy, a Slack message, a `git tag` or a release body. * Trigger on conditions the automations do not expose, such as specific labels, paths, schedules or manual dispatch inputs. * Keep the orchestration in version control next to your other workflows. ## Inputs Set exactly one of `prompt` or `prompt_file`. Every other input is optional. | Input | Description | | - | - | | `prompt` | The task for the agent. | | `prompt_file` | Path, relative to the workspace, of a file whose contents are the prompt. | | `output_schema` | JSON Schema for the agent's result. See [Capturing agent output](#capturing-agent-output). | | `model` | Model slug, such as `anthropic/claude-opus`, or a models.dev specifier. Overrides the repository setting. | | `effort` | Reasoning effort: `low`, `medium`, `high`, `xhigh`, `max`, or a number from `0` to `1`. Overrides the repository setting. | | `timeout` | Maximum run time, such as `10m` or `1h30m`. Defaults to `1h`. | | `push` | `disabled`, `restricted` or `enabled`. Overrides the repository's [code pushes](/security#code-pushes) setting. | | `shell` | `disabled`, `restricted` or `enabled`. Can only make the repository's [shell setting](/security#shell-environment-scrubbing) stricter. | | `progress_comments` | `disabled` stops live task-list updates to the progress comment. | | `debug` | `enabled` raises the run's log level. | | `cwd` | Working directory for the agent. Defaults to the workspace root. | ## Capturing agent output The action has one output, `result`, for later steps to read. The agent sets it by calling the `set_output` tool with whatever you asked for: a string, a JSON object or a file path. | `output_schema` | Behavior | | - | - | | Omitted | `result` is optional. The agent may set any string or JSON value. | | Set to a JSON Schema | `result` is required and validated against the schema. The step fails if the agent does not set it or the value does not conform. | ## Example: release changelog This release workflow has an agent draft the changelog from the commits since the last tag. The schema makes `result` a typed object, so the release step reads its fields with `fromJSON()`. The version bump, build and publish stay in your workflow. ```yaml theme={null} # .github/workflows/release.yml name: Release on: workflow_dispatch: inputs: version: description: Semver to release required: true jobs: release: runs-on: ubuntu-latest permissions: contents: write # for the release step id-token: write # for Pullfrog steps: - uses: actions/checkout@v6 with: fetch-depth: 0 - name: Draft changelog id: changelog uses: pullfrog/pullfrog@v0 with: prompt: | Read the commits between the latest tag and HEAD (use `git log`). Write a concise, user-facing changelog grouped by Added / Changed / Fixed. Skip internal refactors and chores. Output JSON only โ€” no prose outside the schema. output_schema: | { "type": "object", "required": ["title", "markdown"], "properties": { "title": { "type": "string" }, "markdown": { "type": "string" } } } - name: Build & publish run: pnpm release ${{ inputs.version }} # reads the agent's output as typed fields - name: Create GitHub release uses: softprops/action-gh-release@v2 with: tag_name: v${{ inputs.version }} name: ${{ fromJSON(steps.changelog.outputs.result).title }} body: ${{ fromJSON(steps.changelog.outputs.result).markdown }} ``` ## Required permissions The action mints its own short-lived GitHub App installation tokens through OIDC for everything it does on GitHub: pushing branches, posting comments, creating reviews and updating issues. It does not use your workflow's `GITHUB_TOKEN` for any of it. The action needs only two permissions from your workflow: | Permission | Why | | - | - | | `id-token: write` | Lets the action mint installation tokens through OIDC | | `contents: read` | Lets `actions/checkout` clone the repository | Extra scopes, such as `contents: write` for a step that pushes tags, go to the workflow's `GITHUB_TOKEN` for the other steps in the job; the Pullfrog action does not use them. Set `permissions:` on the job rather than the workflow, so other jobs do not inherit them. ## Run tracking Pullfrog records every run of these workflows from the same OIDC token, so on Pro its token usage, cost and model appear on the console's analytics page as **Uncategorized** runs. Failure emails and run diagnosis cover only the runs Pullfrog dispatches itself. A workflow that runs the action more than once, such as a matrix or one review per model, is still one run. Each Pullfrog step's usage and model count separately, and the run shows the totals. The run's status follows the Pullfrog steps' own results, so a gate job that fails elsewhere in the workflow does not mark the run failed. # Introduction Source: https://docs.pullfrog.com/index Pullfrog runs coding agents inside your GitHub repositories to review pull requests, plan issues, and write code. Pullfrog puts a coding agent to work in your GitHub repositories. It reviews pull requests, plans and triages issues, and writes code when you mention `@pullfrog` in a comment. ## How it works * **The Pullfrog GitHub App** listens to your repository's events, checks who triggered each one, and decides when to start a run. * **A `pullfrog.yml` workflow** in `.github/workflows/` runs the agent on your own GitHub Actions runners, against a checkout of your repository. * **The [console](https://pullfrog.com/console)** holds each repository's settings: the model, which events trigger a run, and your review and coding instructions. Runs start from an `@pullfrog` mention on an issue or PR, from the prompt box in the console, or automatically: on a new PR, a new issue, a review on a Pullfrog PR, or a failing CI check. ## What you get * **Any model.** Pay through [Pullfrog Router](/billing#pullfrog-router) at provider cost with no markup, bring your own API key, or use a Claude, ChatGPT, Grok, Kimi Code, or OpenCode Go subscription you already have. Some models are free. * **Agent-agnostic.** Pullfrog runs Claude Code for Anthropic models and OpenCode for every other provider, with an experimental Codex harness. See [model resolution](/models#model-resolution). * **Scoped credentials.** Each run gets repository-scoped GitHub tokens that Pullfrog revokes when the run ends. Provider keys are stored encrypted in Pullfrog or in your GitHub Actions secrets. * **Free for individuals and open source.** Personal accounts and public repositories run free. Organizations need a plan for private repositories, after a 14-day trial. See [Billing](/billing). * **An open-source action.** The [Pullfrog GitHub Action](https://github.com/pullfrog/pullfrog) is MIT-licensed. ## Explore the docs Install the GitHub App, add the workflow, and send your first prompt. Automatic reviews on new PRs and new commits, and fixes for the comments they leave. Duplicate checks, related issues, and implementation plans on new issues. Pullfrog addresses reviews and fixes failing CI on its own PRs. Free models, Pullfrog Router, your own API key, or an existing subscription. Sandboxing, secret isolation, and short-lived GitHub tokens. Inspect and change settings and stored credentials from the terminal. How Pullfrog compares to vendor agent actions and GitHub Copilot. # Issue enrichment Source: https://docs.pullfrog.com/issue-enrichment Duplicate checks, related context, and implementation plans on every new issue, plus automatic labels. Pullfrog reads every new issue, checks it against the issues you already have, and replies with context or a plan. Enrichment is on by default. Configure it in the repository console under **Automations โ†’ Enrich issues**. ## Enrich new issues Enrichment checks for duplicates, surfaces related issues, and investigates concrete bugs and feature requests. For an actionable request from a collaborator with write access, it posts a concise implementation plan. Other issues get an analysis or a request for the missing information. In Enrich mode, Pullfrog does not change code. A Pullfrog enrichment reply on a new issue: no duplicates found, and an implementation plan with an Implement plan link The **Mode** setting on the card chooses what a new issue triggers: | Mode | Behavior | | - | - | | **Enrich** | Run the default enrichment prompt, or your own prompt in its place | | **Plan** | Analyze the issue and post an implementation plan | | **Build** | Implement the issue and open a PR | The Enrich issues card with the Mode menu open Each run uses the repository's configured model. On public repositories, **Include issues from non-collaborators** controls whether issues from outside contributors are enriched; it is on by default and gives those contributors no other trigger. To let authors decide when to involve Pullfrog, turn off **Enrich issues** and turn on **Post an initial comment with Quick Links instead**. Each new issue then gets **Build this** and **Make a plan** buttons. ### Customize the prompt In Enrich mode, the **Enrichment prompt** field replaces the default prompt. Click **View default prompt**, then **Copy prompt**, paste it into the field, and edit it. Clear the field to go back to the default. In Plan and Build modes, the field is labeled **Custom instructions** and adds to the mode's built-in prompt. The Default issue prompt dialog with its Copy prompt button ### Implement from an issue An enrichment reply carries an **Implement a fix** button, and a plan comment carries **Implement plan**. Either one starts a run that reads the issue discussion, implements the work, and opens a PR. Both buttons require you to sign in to Pullfrog with write access to the repository. ## Issue indexing Issue indexing is a paid-plan feature. See [Billing](/billing). Without a paid plan, enrichment searches the repository's issues by keyword. A paid plan adds retrieval from Pullfrog's background index of your issues. Pullfrog inspects the likely matches before it calls an issue a duplicate, and links a confirmed duplicate instead of writing another plan. Neither search guarantees that every duplicate is found. Pullfrog never closes or labels an issue on similarity alone. That decision stays with a maintainer. Pullfrog builds the index for every set-up repository on every plan, including a backfill of existing issues, so the index is complete on the day you upgrade. Indexing reads issue titles, bodies, and comments, and may read a bounded amount of repository source when an issue references specific files. It never writes to your repository. ## Auto-label issues The **Label issues** card under **Automations** labels each new issue from its title and body, using only labels that already exist in the repository. It is off by default. Its **Custom instructions** field shapes the choice, for example "Prefer specific labels over generic ones. Use at most 3 labels." Pullfrog adding the enhancement and good first issue labels to a new issue The Label issues card in the repository console ## Plan instructions The **Custom instructions** field on the **Plan** card under **Automations** guides how Pullfrog writes implementation plans. It applies when enrichment runs in Plan mode, when someone clicks **Make a plan**, and when an `@pullfrog` mention asks for a plan. The plans that Enrich mode posts follow the enrichment prompt instead. # API keys Source: https://docs.pullfrog.com/keys Store provider API keys with Pullfrog or in GitHub Actions secrets, connect several subscriptions with fallback, and route a provider through your own gateway. Pullfrog runs on your own API key (BYOK, bring your own key) for every [supported provider](/models#supported-providers), and for [providers with no console card](/models#custom-providers) through GitHub Actions secrets. You keep your provider relationship, rate limits and billing, and pay the provider directly at its prices. To run on a Claude, ChatGPT, Grok, Kimi or OpenCode Go plan you already pay for, see [your existing subscription](/model-access#your-existing-subscription). To skip keys entirely, see [Pullfrog Router](/billing#pullfrog-router). ## Key storage | Where | Set it in | Scope | | - | - | - | | [Pullfrog secrets](#pullfrog-secrets) (recommended) | The Pullfrog console | The account, or one repository | | [GitHub Actions secrets](#github-actions-secrets) | GitHub, then the workflow `env:` block | The workflow | You can mix the two per provider. If a key is set in both, the workflow value wins, so a workflow can override a stored key. ### Pullfrog secrets Pullfrog encrypts stored keys at rest, injects them into each run, and never writes them to your repository or workflow files. No workflow edits are needed. 1. Open `pullfrog.com/console/` and find the **Providers** section of the **Billing** card. 2. Select the **BYOK** tab. 3. Click **Set up** on the provider's card and follow its credential instructions. The Providers section of the Billing card on the BYOK tab The **Add secret** modal scopes a secret to the whole account or to one repository: Add secret modal in the Pullfrog console Every repository inherits the account's secrets. A repository secret with the same name overrides the account one for that repository only. On an organization, only owners can open the **Billing** card. Repository admins manage keys for their repository in the **Secrets** section of the repository console, where inherited account secrets appear read-only: Secrets card on the repo console ### GitHub Actions secrets Keep keys in GitHub when you already rotate secrets there. Pullfrog reads them from the workflow `env:` block. 1. Add the secret in GitHub, at the organization (`github.com/organizations//settings/secrets/actions`, **New organization secret**) or the repository (`github.com///settings/secrets/actions`, **New repository secret**). 2. Map it into `pullfrog.yml`: ```diff theme={null} jobs: pullfrog: runs-on: ubuntu-latest steps: - name: Run agent uses: pullfrog/pullfrog@v0 with: prompt: ${{ inputs.prompt }} + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} ``` Any variable in `env:` reaches the agent, so a provider with no console card runs from a GitHub Actions secret too. See [custom providers](/models#custom-providers). ## Cloud providers and custom endpoints These routes are BYOK only and have their own setup pages: | Route | Use it for | | - | - | | [Amazon Bedrock](/bedrock) | Inference through your AWS account, with pinned model IDs | | [Google Vertex AI](/vertex) | Inference through your Google Cloud project, with pinned model IDs | | [Azure OpenAI](/azure) | Your Azure deployments, billed to your Azure subscription | | [OpenAI-compatible endpoints](/openai-compatible) | A LiteLLM proxy, a self-hosted vLLM server, or any gateway that speaks chat completions | ## Multiple subscriptions and fallback Connect several Claude, Codex or Grok subscriptions by running the provider's auth command again. Choose **Add another** to keep the existing connections as fallbacks, or **Replace** to swap one out once the new connection succeeds. The account that signs in decides the result, and the CLI reports it: `added`, `replaced`, or `reconnected` when the sign-in was an account already connected. A browser signs in as the account it already holds, so adding a second account takes a signed-out browser or a private window. ```bash theme={null} npx pullfrog auth claude --org my-org npx pullfrog auth codex --repo my-org/my-repo npx pullfrog auth grok --org my-org ``` Each subscription card lists its connected accounts; Claude connections show the end of the setup token, and Codex and Grok connections show the account email when available. The pencil removes a connection or copies the command to add another. After a run checks a connection, its card shows **Rejected** if the provider refused it, or **Limit reached** with the reset time when the provider gives one. Before the agent starts, Pullfrog tries the credentials for the run's model and provider in this order: 1. Subscriptions: the workflow's, then the repository's, then the account's, then shared personal ones 2. API keys: the workflow's, then the repository's, then the account's Within a scope, the most recently connected subscription goes first. A rejected or exhausted credential moves the run to the next one, so a fallback to an API key can incur API charges. If a provider cannot answer the check, Pullfrog keeps the current credential. Once the agent has started, Pullfrog does not switch credentials or models. Checks for some providers send a small inference request. A passing check does not reserve quota or guarantee the whole run fits within the limit. ### Personal subscriptions on organization repositories The owner of a personal account can share one of its subscriptions with an organization or repository they also manage: ```bash theme={null} npx pullfrog auth list --org my-username npx pullfrog auth share CREDENTIAL_ID --from my-username --repo my-org/my-repo npx pullfrog auth unshare CREDENTIAL_ID --from my-username --repo my-org/my-repo ``` The list prints a binding ID for `auth remove`, a credential ID for `auth share` and `auth unshare`, and each connection's status: **Rejected**, **Limit reached** with its reset time, or `-` when the last check passed. Removing the connection from the personal account revokes its shares. Nothing is shared automatically because someone triggered a run. ## Gateways and proxies Route a provider's requests through your own host, such as a LiteLLM proxy, a corporate egress proxy or an AI gateway, while keeping your normal model selection. Set the base URL under **Set up a proxy or gateway** on the provider's setup card, or in your workflow `env:`: | Provider | Variable | | - | - | | Anthropic | `ANTHROPIC_BASE_URL` | | OpenAI | `OPENAI_BASE_URL` | Put only the host in the base URL; a credential embedded in it is not treated as one. Pullfrog skips its pre-run credential check for a gateway, so a gateway that refuses the credential reports its own error in the run. The Configure Anthropic dialog with Set up a proxy or gateway expanded to ANTHROPIC_BASE_URL Other providers take other routes. [Azure OpenAI](/azure) builds its endpoint from `AZURE_RESOURCE_NAME`, and a gateway with its own model list belongs on [OpenAI-compatible endpoints](/openai-compatible). ### Anthropic Anthropic models run through Claude Code, which honors `ANTHROPIC_BASE_URL` natively and talks to the gateway in Anthropic's own format, so prompt caching and extended thinking survive the hop. ```yaml theme={null} env: ANTHROPIC_BASE_URL: https://gateway.internal.example.com ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} ``` Pick the credential variable by the header your gateway reads. The `ANTHROPIC_API_KEY` variable is sent as `x-api-key`, and `ANTHROPIC_AUTH_TOKEN` as `Authorization: Bearer`. A gateway that reads the other header answers `401`. ```yaml theme={null} env: ANTHROPIC_BASE_URL: https://gateway.internal.example.com ANTHROPIC_AUTH_TOKEN: ${{ secrets.GATEWAY_TOKEN }} ``` This route serves Claude models only. Anthropic [doesn't support routing Claude Code to non-Claude models through a gateway](https://code.claude.com/docs/en/llm-gateway), so use [OpenAI-compatible endpoints](/openai-compatible) for a provider's `/anthropic` endpoint that serves its own models. ### OpenAI The `OPENAI_BASE_URL` variable re-points the OpenAI provider, which speaks the **Responses API** (`POST /v1/responses`). Point it at a gateway that serves that endpoint. ```yaml theme={null} env: OPENAI_BASE_URL: https://gateway.internal.example.com/v1 OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} ``` Most third-party gateways speak the older Chat Completions API (`POST /v1/chat/completions`), which is what "OpenAI-compatible" usually means. For one of those, use [OpenAI-compatible endpoints](/openai-compatible) instead. ## Troubleshooting ### "Missing API key" error in GitHub Actions The agent found no valid key at runtime. Check, in order: 1. The selected model's env var is set in Pullfrog secrets or in a workflow `env:` mapping. 2. The secret name matches the provider's env var exactly: `ANTHROPIC_API_KEY`, not `CLAUDE_API_KEY`. 3. A GitHub secret is mapped in the `env:` block of `pullfrog.yml`. GitHub Actions injects only what the workflow lists. ### "Missing API key" warning in the console The console found no stored key for the selected model. Add one under **Providers** on the **Billing** card, or switch to a model whose key you already have. # Kimi Code Source: https://docs.pullfrog.com/kimi-code Run Kimi models on your Kimi membership quota instead of a Moonshot API balance. Run Pullfrog on the Kimi Code quota in your Kimi membership instead of a separate Moonshot API balance. Mint a key in the Kimi Code console, store it as `KIMI_API_KEY`, and pick a Kimi Code model. ```yaml theme={null} - name: Run agent uses: pullfrog/pullfrog@v0 with: prompt: ${{ inputs.prompt }} model: kimi-for-coding/kimi-k3-256k env: KIMI_API_KEY: ${{ secrets.KIMI_API_KEY }} ``` Kimi Code and the [Moonshot open platform](https://platform.kimi.ai) are separate systems with separate keys, endpoints and billing. A `MOONSHOT_API_KEY` does not work here, and a Kimi Code key does not work on `moonshotai/*` models. ## Setup 1. Create an API key in the [Kimi Code console](https://www.kimi.com/code/console). The console shows it once, and you can hold at most five. 2. Store it as `KIMI_API_KEY`: on the **Kimi Code** card in the [Pullfrog console](https://pullfrog.com/console), or as a GitHub Actions secret mapped into the workflow's `env:` block. 3. Pick a Kimi Code model in the console, or set the `model` input as above. The Configure Kimi Code dialog with the KIMI_API_KEY field ## Models The membership tier decides which models a key can reach. A request for a model outside your plan fails with an error that names the plan it needs. | Model | Context | Plan | | - | - | - | | Kimi K3 256K | 256K | Moderato and above | | Kimi K3 | up to 1M; 256K below Allegretto | Moderato and above | | Kimi K2 | up to 1M | Every tier | | Kimi K2 HighSpeed | 256K | Allegretto and above | Pullfrog recommends Kimi K3 256K. It is the same model as Kimi K3 in a 256K window, at about half the quota per run. Below Allegretto, Kimi K3 also stops at 256K, so on Moderato both give the same results and Kimi K3 uses twice the quota. Kimi K3 and Kimi K2 accept a [reasoning effort](/flags) of low, high or max, and default to high. Kimi K2 HighSpeed has no effort setting. ## Billing A stored `KIMI_API_KEY` counts as your own key: runs on Kimi Code models use your membership quota, not [Pullfrog Router](/billing#pullfrog-router). Pullfrog Router cannot serve these models, so a Kimi Code pick with no key runs on the Router's default model, and the job log names the substitution. ## Troubleshooting | Symptom | Fix | | - | - | | Run comment: "Your Kimi membership doesn't include the model this run asked for" | The plan is below what the model or context window needs. Upgrade at [Kimi membership](https://www.kimi.com/membership/pricing), or switch the repository to Kimi K2, which every tier includes. | | Kimi error: "Invalid Authentication" | The key in `KIMI_API_KEY` is usually a Moonshot open-platform key. Kimi Code keys come only from the [Kimi Code console](https://www.kimi.com/code/console). | | Kimi error: usage limit reached | Kimi Code quota has five-hour, weekly and monthly windows, plus a limit on concurrent requests. Re-trigger after the reset, or store a `MOONSHOT_API_KEY` and pick a `moonshotai/*` model to keep running on pay-as-you-go. | # Learnings Source: https://docs.pullfrog.com/learnings Context Pullfrog carries from one run to the next, at the repository, pull request, and organization level. Pullfrog carries context forward between runs, so each run starts with what earlier runs learned about the repository and the PR. | Kind | Scope | Where to edit it | | - | - | - | | Repo-level learnings | Every run in a repository | Repository console, **Agent โ†’ Learnings** | | PR-level learnings | Runs on one pull request | Not editable; agent context only | | Cross-repo learnings | [Cross-repo (`--xrepo`)](/flags#cross-repo) runs in an organization | Organization console, **Advanced โ†’ Cross-repo learnings** | ## Repo-level learnings Repo-level learnings are durable notes about how a repository works, kept for facts that many future tasks can reuse: * Setup and verification commands, such as the package manager, the lint command, or a targeted test command. * Project conventions, such as where shared utilities live or how components are styled. * Repository gotchas, such as a flaky integration test, a generated file that must not be edited, or a deployment detail that changes how code is validated. * Stable architecture facts, such as which package owns shared runtime logic or where auth decisions are enforced. Pullfrog keeps these notes high-confidence and broadly useful, not a run log. It skips one-off discoveries and guesses, and prunes notes that go stale. You can correct any note in the console, or clear them all. The Learnings card in the repository console ## PR-level learnings PR-level learnings are a rolling summary of one pull request that review and re-review runs read and update: * What the PR changes, and which subsystems, files, or behaviors it affects. * Risks, open questions, and contracts the next review must preserve. * What has been reviewed already, and what changed since the last review. * Earlier feedback that has been addressed or no longer applies. The summary is context for the next run, not a changelog. The review on GitHub carries its own summary for people to read. ## Cross-repo learnings Cross-repo learnings map how an organization's repositories relate, so a [cross-repo](/flags#cross-repo) run does not rediscover the structure each time. Two settings in the organization console, under **Advanced**, hold this knowledge: * **Cross-repo brief** is text you write, and the agent never edits it. State relationships directly: "`api` consumes types from `shared`", "`web` and `mobile` both depend on `design-system`", "run `pnpm -r build` in `platform` before changing downstream repos". * **Cross-repo learnings** are maintained by the agent, like repo-level learnings but for the organization. When the brief leaves the structure unstated, the agent works it out once and records it for later cross-repo runs. The Cross-repo brief and Cross-repo learnings fields in the organization console Keep cross-repo learnings structural: dependency direction, where shared code and types live, and each repository's build and test entry points. Facts about a single repository belong in that repository's own learnings. # Model access Source: https://docs.pullfrog.com/model-access The four ways to pay for the model tokens a Pullfrog run spends, and how to fix a run that fails on credentials or balance. Every Pullfrog run spends model tokens. Run on a free model, fund Pullfrog Router, bring your own API key, or use a subscription you already pay for. | Route | What you pay | Set it up | | - | - | - | | [Free models](#free-models) | Nothing per token | Pick the model and store an `OPENCODE_API_KEY` | | [Pullfrog Router](#pullfrog-router) | A prepaid balance, at provider cost with no markup | Add a card in the console | | [Your own API key](#your-own-api-key) | Your provider bills you directly | Paste the key in the console | | [Your existing subscription](#your-existing-subscription) | Nothing extra | One CLI command, or one key | The **Providers** section of the console's **Billing** card switches the account between **BYOK** (your own keys and subscriptions) and **Pullfrog Router**. A provider key stored with Pullfrog is used for the models it covers even on Router, and free models work under either. Model access is separate from your [plan](/billing#plans). No plan includes model tokens, and paying for tokens does not require a plan. ## Free models These models cost nothing per token. Pick one in the [model selector](/models#selecting-a-model). | Model | Notes | | - | - | | Big Pickle | | | LongCat Preview | Meituan's preview, free for a limited time | | MiMo | | | Muse Spark Contributor | Meta trains on the prompts and completions | | Space Bunny | Stealth preview, free for a limited time | | Step 5 Preview | StepFun's preview, free for a limited time | All six are served by OpenCode Zen, which still authenticates each request. Store an `OPENCODE_API_KEY` the same way as [any other provider key](/keys); a run without one stops at session start with `No provider available`. ## Pullfrog Router Pullfrog Router reaches every major provider through one billing account, at provider cost with no markup. Pullfrog mints a short-lived key for each run, so there are no provider keys to manage. Router runs draw on a prepaid balance and stop when it reaches zero. Add a card in the **Billing** card and turn on auto-reload to keep the balance funded. See [Pullfrog Router](/billing#pullfrog-router) for balance, auto-reload and spend limits. The Providers section of the Billing card on the Pullfrog Router tab ## Your own API key Bring a provider API key and the provider bills you directly, at its own prices. The key must match the repository's model: an OpenAI key cannot run an Anthropic model. Store the key with Pullfrog, at the account or repository level, or keep it in GitHub Actions secrets. See [API keys](/keys) for both, plus [Amazon Bedrock](/bedrock), [Google Vertex AI](/vertex), [Azure OpenAI](/azure) and [OpenAI-compatible endpoints](/openai-compatible). ## Your existing subscription Pullfrog can run on a plan you already pay for instead of API tokens. Claude, ChatGPT and Grok plans connect with one command, run from inside the repository; Kimi and OpenCode Go issue an ordinary key. | Subscription | Connect with | Guide | | - | - | - | | Claude Pro or Max | `npx pullfrog auth claude` | [Claude subscription](/claude-auth) | | ChatGPT (Codex) | `npx pullfrog auth codex` | [Codex subscription](/codex-auth) | | SuperGrok or X Premium | `npx pullfrog auth grok` | [Grok subscription](/grok-auth) | | Kimi membership | A `KIMI_API_KEY` | [Kimi Code](/kimi-code) | | OpenCode Go | An `OPENCODE_API_KEY` | [OpenCode Go](/models#opencode-zen-and-opencode-go) | The Subscriptions row of the Providers section: Claude Pro/Max, ChatGPT (Codex) and Grok Do not put a Claude, Codex or Grok credential into GitHub Actions secrets. The Codex and Grok credentials rotate as they refresh, and a GitHub secret cannot be written at runtime, so a credential stored there stops working when its access token expires: within hours for Grok, days for Codex. The commands above store it with Pullfrog instead. A subscription has usage limits, and runs on it fail until the limit resets. Connect a second account or add an API key for the same provider, and Pullfrog falls back to it. See [multiple subscriptions and fallback](/keys#multiple-subscriptions-and-fallback). ## Troubleshooting a failing run 1. **Does the repository's model match a credential you hold?** A repository set to an OpenAI model needs an OpenAI credential, whichever route you use. Check the model in the repository's console. 2. **On Router, is there a balance or a card on file?** An empty balance with no card stops every Router run. 3. **On BYOK, does the key exist?** It can live at the account, at the repository, or in GitHub Actions secrets. A secret the workflow references but nobody created resolves to an empty value, not an error. 4. **On a subscription, has it hit its usage limit?** Runs resume when the limit resets. 5. **Did GitHub refuse to start the job?** A run with no steps at all points to your GitHub Actions billing, not to Pullfrog. Check your GitHub account's billing settings. # Models Source: https://docs.pullfrog.com/models Pick a model per repository or let Smart pick one per pull request, and see how Pullfrog resolves the model and agent a run uses. Pullfrog model names are rolling aliases, like a `latest` tag on npm. "Claude Opus" resolves to a concrete version at runtime (`anthropic/claude-opus-5-5`), and when a new generation ships the alias moves with it. Your configuration doesn't change. ## Selecting a model Pick a provider and a model in the **Agent** section of the repository [console](https://pullfrog.com/console). Set an organization default in the **Model** section of the org console; every repository inherits it until it picks its own. The Provider and Model cards in the Pullfrog console The **Provider** card shows each provider with the credential that pays for it, or a way to set one up. The **Model** card has two tabs: | Tab | What it does | | - | - | | **Manual** | Pins one model from the provider's menu, with its reasoning effort | | **Smart** | Picks a model from the provider's ladder for each piece of work. See [Smart](#smart). | Models marked **Free** cost nothing per token but still need an `OPENCODE_API_KEY`. See [free models](/model-access#free-models). On [Pullfrog Router](/billing#pullfrog-router) without a card on file, a positive balance runs DeepSeek Flash and every other model is locked. With no balance and no card, Router runs stop. Free models, models you hold a [Pullfrog-stored key](/keys) for, and BYOK accounts are not affected. ## Reasoning effort Under a pinned model, **Reasoning effort** offers the levels that model publishes. Pullfrog stores the setting as a position on the model's range, so it keeps its place when you switch models. Smart sets effort for each run itself. To override effort for a single run, use the [`--effort` flag](/flags#effort). The Model card on Manual with Claude Opus pinned and Reasoning effort set to High ## Smart Smart runs cheap work on a provider's cheapest model and hard work on its frontier model. For pull request reviews, a model Pullfrog pays for reads the diff and picks one of four rungs. | Rung | Work it gets | | - | - | | Minimal | Issue labeling, and reviews with no behavioral change | | Light | New-issue enrichment, and small pull requests that can be checked line by line | | Standard | Mentions, fixes and other tasks, and self-contained pull requests with logic to verify | | Deep | Large pull requests, and changes that reach across many files | Smart is included in the Pro, Organization and Enterprise [plans](/billing#plans) and in an organization's trial. Without one, the **Smart** tab shows a lock, and clicking it explains how Smart works and where to upgrade. A Smart setting saved before Pro lapsed is kept, and the card opens on **Manual**, showing the ladder's Standard rung, which is the model runs use meanwhile. ### Ladders Each provider maps the rungs to its own models. While Smart is on, the **Provider** card lists only the providers in this table. | Provider | Minimal | Light | Standard | Deep | | - | - | - | - | - | | Anthropic | Claude Sonnet | Claude Sonnet | Claude Opus | Claude Opus | | OpenAI | GPT Luna | GPT Terra | GPT Sol | GPT Astra | | Google | Gemini Flash | Gemini Flash | Gemini Pro | Gemini Pro | | DeepSeek | DeepSeek Flash | DeepSeek Flash | DeepSeek Pro | DeepSeek Pro | | xAI | Grok 4.3 | Grok 4.3 | Grok | Grok | | Moonshot AI | Kimi K2 | Kimi K2 | Kimi K3 | Kimi K3 | | OpenRouter | DeepSeek Flash | GPT Luna | GPT Sol | Claude Opus | | OpenCode Zen | GPT Luna | GPT Luna | GPT Sol | Claude Opus | | [Pullfrog Router](/billing#pullfrog-router) | DeepSeek Flash | GPT Luna | GPT Sol | Claude Opus | On Pullfrog Router, Smart runs DeepSeek Flash for everything until a card is on file. A per-run [`--model` flag](/flags#model) overrides Smart, and [Pullfrog for OSS](#pullfrog-for-oss) repositories don't use it. ### Custom instructions Under Smart, **Custom instructions** takes standing guidance for the pick: which paths or kinds of change deserve the top model or more effort, and which can stay on the cheapest rung. Changing the provider clears it. Lockfiles, snapshots, generated files and binary files are already left out when a diff is weighed. Guidance for the review itself belongs in **Standing instructions**. The Smart tab with Custom instructions expanded ## Pullfrog for OSS Repositories in [Pullfrog for OSS](https://pullfrog.com/for-oss) have their model costs covered by Pullfrog, so the picker offers the set we fund: | Model | Notes | | - | - | | **DeepSeek Flash** | Recommended, and the default | | GPT Luna | OpenAI's cost-efficient tier | | MiniMax M2 | | | Muse Spark Contributor | Meta's discounted tier. Meta may train on the prompts and completions. | A model outside this set falls back to the default, and the PR footer says so. The exception is a provider key stored **with Pullfrog**: the run then uses your key and your pick. A key that lives only in GitHub Actions secrets doesn't count, because the server can't see it when it decides. The same rule applies to a per-run [`--model` flag](/flags#model). ## Model resolution When a run starts, Pullfrog takes the first model set in this order: 1. Per-run flag (`--model`) 2. Repository model in the console, or Smart's pick when the repository is set to Smart 3. Workflow input (`model:`) 4. Organization default in the console, or Smart's pick when the default is Smart 5. Auto-select: the best curated model your keys can reach, preferring each provider's top tier 6. OpenCode's own default Specifiers use the [models.dev](https://models.dev) format (`anthropic/claude-opus-5-5`), and Pullfrog's aliases map onto them. The model also decides which agent runs. An Anthropic model with Anthropic credentials runs on Claude Code, and everything else runs on OpenCode. Organizations opted in to the experimental [Codex CLI](https://developers.openai.com/codex/cli) agent run OpenAI models on Codex when a [Codex subscription](/codex-auth) or an `OPENAI_API_KEY` is present. Runs billed through Pullfrog Router or the OSS program always use OpenCode. ## Supported providers | Provider | API key env var | | - | - | | Anthropic | `ANTHROPIC_API_KEY` (or a [Claude subscription](/claude-auth)) | | OpenAI | `OPENAI_API_KEY` (or a [Codex subscription](/codex-auth)) | | Google | `GOOGLE_GENERATIVE_AI_API_KEY` or `GEMINI_API_KEY` | | xAI | `XAI_API_KEY` (or a [Grok subscription](/grok-auth)) | | DeepSeek | `DEEPSEEK_API_KEY` | | Moonshot AI | `MOONSHOT_API_KEY` | | Meta | `META_MODEL_API_KEY`, from the [Meta Model API](https://dev.meta.ai), for Muse Spark | | [Kimi Code](/kimi-code) | `KIMI_API_KEY`, from a Kimi membership rather than a Moonshot API balance | | OpenCode | `OPENCODE_API_KEY`: one key for [Zen and Go](#opencode-zen-and-opencode-go), also required for the free Zen models | | OpenRouter | `OPENROUTER_API_KEY` | | Vercel AI Gateway | `AI_GATEWAY_API_KEY` | | [Amazon Bedrock](/bedrock) | `AWS_BEARER_TOKEN_BEDROCK` (or `AWS_ACCESS_KEY_ID` + `AWS_SECRET_ACCESS_KEY`) + `AWS_REGION` + `BEDROCK_MODEL_ID` | | [Google Vertex AI](/vertex) | `VERTEX_SERVICE_ACCOUNT_JSON` + `GOOGLE_CLOUD_PROJECT` + `VERTEX_LOCATION` + `VERTEX_MODEL_ID` | | [Azure OpenAI](/azure) | `AZURE_RESOURCE_NAME` + `AZURE_API_KEY` + `AZURE_DEPLOYMENT` + `AZURE_CONTEXT` + `AZURE_MAX_OUTPUT` | | [Custom โ€บ OpenAI-compatible](/openai-compatible) | `OPENAI_COMPATIBLE_BASE_URL` + `OPENAI_COMPATIBLE_API_KEY` + `OPENAI_COMPATIBLE_MODEL` + `OPENAI_COMPATIBLE_CONTEXT` + `OPENAI_COMPATIBLE_MAX_OUTPUT` | ## Custom providers The table above lists the providers the console has a card for. Any other provider in the [models.dev](https://models.dev) catalog runs too, through [OpenCode](https://github.com/anomalyco/opencode): Groq, Mistral, Cerebras, Together, Fireworks and the rest switch on as soon as their API key is in the run's environment. Set the account to **BYOK** in the **Providers** section of the **Billing** card first. On Pullfrog Router the server hands the run a Router credential before it starts, and it cannot see a key that lives only in GitHub Actions secrets. Add it as a GitHub Actions secret, under the exact name that provider's [models.dev](https://models.dev) page declares. The specifier must be one models.dev lists; the run checks it against the provider's catalog before starting. Non-secret settings some providers want, such as a region or an endpoint, go straight in `env:`. ```yaml theme={null} - name: Run agent uses: pullfrog/pullfrog@v0 with: prompt: ${{ inputs.prompt }} model: groq/llama-3.3-70b-versatile env: GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }} ``` A model stored for the repository in the console beats the workflow's `model` input, so pick **Custom (set in workflow)**, or **Inherit from org** if your organization has a default. The job log confirms the specifier took: ``` ยป "groq/llama-3.3-70b-versatile" is not a curated alias โ€” passing through as a raw model specifier ``` Use [OpenAI-compatible endpoints](/openai-compatible) instead when your provider isn't in the catalog, when you front several providers behind one gateway, or when you need a model ID the catalog doesn't carry. ## Routers OpenRouter, OpenCode Zen, OpenCode Go and Vercel AI Gateway are providers like any other, with their own aliases (OpenRouter's "Claude Opus" is `openrouter/~anthropic/claude-opus-latest`). To pin an exact version instead of the rolling alias, set the `model` input to the full specifier: ```yaml theme={null} with: model: openrouter/anthropic/claude-sonnet-5 env: OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} ``` ### OpenCode Zen and OpenCode Go [Zen](https://opencode.ai/zen) and [Go](https://opencode.ai/go) are two OpenCode plans behind one credential. Store `OPENCODE_API_KEY` once and both groups appear in the picker. | Plan | Billing | Models | | - | - | - | | **OpenCode Zen** | Pay as you go | Claude, GPT, Gemini, Grok, Kimi, MiniMax, GLM, Qwen, Mistral, MiMo, LongCat, Step, Muse Spark | | **OpenCode Go** | \$10/month, capped usage | GLM, Qwen, Kimi, MiniMax, MiMo, LongCat, Hy3, plus Grok and GPT Luna | Most of the Go catalog is not served on Zen, so the two groups are different menus. DeepSeek and Muse Spark are not on the Go menu. OpenCode gates them on a workspace opt-in that is off by default (China hosting for DeepSeek, data collection for Muse Spark), so a run without it refuses with a link to the setting. Turn the opt-in on in your OpenCode workspace and run them by full specifier, as below. DeepSeek needs no opt-in on any other route. ### Models the picker does not carry The picker is a curated menu. Any other model either endpoint serves runs by its full [models.dev](https://models.dev) specifier: ```yaml theme={null} with: model: opencode-go/mimo-v2-omni env: OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} ``` Set the console model to **Custom (set in workflow)** so a stored pick does not beat the workflow input, as with [custom providers](#custom-providers). # OpenAI-compatible endpoints Source: https://docs.pullfrog.com/openai-compatible Run Pullfrog against any endpoint that speaks the OpenAI Chat Completions API, such as LiteLLM, Cloudflare AI Gateway or vLLM. Route Pullfrog's model calls to any endpoint that speaks the OpenAI Chat Completions API: a [LiteLLM](https://docs.litellm.ai/docs/simple_proxy) proxy, [Cloudflare AI Gateway](https://developers.cloudflare.com/ai-gateway/), [Alibaba DashScope](https://www.alibabacloud.com/help/en/model-studio/), or a self-hosted [vLLM](https://docs.vllm.ai/) server. Use it for a model the catalog does not carry, several providers behind one gateway, or your own inference. A provider listed on [models.dev](https://models.dev) runs from its own API key, with no base URL or token limits to declare; see [custom providers](/models#custom-providers). For Azure OpenAI, use [Azure OpenAI](/azure) instead. OpenAI-compatible endpoints are bring-your-own-key only. Your provider bills inference to your account, and Pullfrog never proxies this traffic. ## Setup In the Pullfrog console, pick the **Custom (OAI)** tile on the **Provider** card. Click **Set up** on the tile and fill in the five values from the table below. Pullfrog injects them into every run, so `pullfrog.yml` needs no changes. Values stored for the organization can be overridden per repository. The Configure Custom (OAI) dialog with its five fields To keep them in the workflow instead, put `OPENAI_COMPATIBLE_API_KEY` in a GitHub Actions secret and the rest in the `env:` block of `.github/workflows/pullfrog.yml`: ```yaml theme={null} env: OPENAI_COMPATIBLE_BASE_URL: https://gateway.ai.cloudflare.com/v1///compat OPENAI_COMPATIBLE_API_KEY: ${{ secrets.OPENAI_COMPATIBLE_API_KEY }} OPENAI_COMPATIBLE_MODEL: workers-ai/@cf/meta/llama-3.1-8b-instruct OPENAI_COMPATIBLE_CONTEXT: "128000" OPENAI_COMPATIBLE_MAX_OUTPUT: "16384" ``` ## Variables | Name | Secret | Purpose | | - | - | - | | `OPENAI_COMPATIBLE_BASE_URL` | No | Base URL of the endpoint, the path that serves `/chat/completions`. | | `OPENAI_COMPATIBLE_API_KEY` | Yes | API key or bearer token for the endpoint. | | `OPENAI_COMPATIBLE_MODEL` | No | Exact model ID the endpoint serves. Pullfrog runs it as written and never upgrades it. | | `OPENAI_COMPATIBLE_CONTEXT` | No | Context window of that model, in tokens. | | `OPENAI_COMPATIBLE_MAX_OUTPUT` | No | Maximum completion tokens that model accepts. | All five are required, and a run without them fails before the agent starts. The two limits must be positive numbers, so `128k` is rejected. A value set in the workflow wins over a stored one. Put the key only in `OPENAI_COMPATIBLE_API_KEY`, never inside the base URL. A base URL set in the workflow is not masked in logs. On an account that pays through [Pullfrog Router](/billing#pullfrog-router), store the values in the Pullfrog console. Pullfrog decides how to fund a run before the runner starts, when GitHub Actions secrets are not visible to it, so a run whose values exist only there falls back to the Router's default model. ### Token limits Your endpoint owns the model catalog, so Pullfrog cannot look up the model's limits and needs you to declare them. Undeclared limits would break two things: * **Completions are capped at 32000 tokens**, and a model with a smaller cap rejects every request. GPT-4o and GPT-4o mini stop at 16384, and many open models at 4096 or 8192. * **Auto-compaction turns off.** Compaction keys off the context limit, so a long session grows until the endpoint refuses it. Set `OPENAI_COMPATIBLE_CONTEXT` to the model's real window. A low value compacts earlier than needed; a high value delays compaction until the endpoint refuses the request. ## Model IDs The model menu has a single **OpenAI-compatible** entry; `OPENAI_COMPATIBLE_MODEL` names the actual model, in your gateway's own format: | Gateway | Model ID format | Example | | - | - | - | | [Cloudflare AI Gateway](https://developers.cloudflare.com/ai-gateway/usage/chat-completion/) | `/` | `workers-ai/@cf/meta/llama-3.1-8b-instruct` | | DashScope | Bare model ID | `qwen3-coder-plus` | | LiteLLM proxy | The `model_name` from the proxy's `model_list` | `claude-opus-internal` | ### LiteLLM A [LiteLLM proxy](https://docs.litellm.ai/docs/simple_proxy) needs no special configuration. Point the base URL at the proxy's `/v1` path and use a [virtual key](https://docs.litellm.ai/docs/proxy/virtual_keys): ```yaml theme={null} env: OPENAI_COMPATIBLE_BASE_URL: https://litellm.internal.example.com/v1 OPENAI_COMPATIBLE_API_KEY: ${{ secrets.LITELLM_VIRTUAL_KEY }} OPENAI_COMPATIBLE_MODEL: claude-opus-internal # model_name from model_list OPENAI_COMPATIBLE_CONTEXT: "200000" OPENAI_COMPATIBLE_MAX_OUTPUT: "32000" ``` LiteLLM's own routing, failover and spend tracking apply as configured. The same setup covers models the proxy serves from self-hosted vLLM or Ollama. ## Routing Pullfrog runs the model on OpenCode, through an [`@ai-sdk/openai-compatible`](https://www.npmjs.com/package/@ai-sdk/openai-compatible) provider pointed at `OPENAI_COMPATIBLE_BASE_URL`. Requests go to `/chat/completions` with your key as the bearer token. ## Troubleshooting | Symptom | Fix | | - | - | | `OPENAI_COMPATIBLE_MODEL env var is required when the model is set to "openai-compatible/byok"` | The repository uses the OpenAI-compatible entry, but no model ID is stored or set in the workflow. | | "OpenAI-compatible model selected but required configuration is missing" | The message names each missing or non-numeric value. | | `max_tokens is too large` | The value of `OPENAI_COMPATIBLE_MAX_OUTPUT` is above what the model accepts. Lower it to the model's real limit. | | HTTP `404` from the endpoint | Pullfrog appends `/chat/completions` to the base URL, so the base URL is usually the path that ends in `/v1`. | # Permissions Source: https://docs.pullfrog.com/organizations Who can see and change what in Pullfrog, based on each person's GitHub role. Pullfrog takes every permission from GitHub. There is no user list, invite step or seat to manage: a teammate signs in with GitHub and sees the organizations and repositories they can already reach. The organization console as an org member, with the Billing card locked ## Roles | GitHub role | What it allows in Pullfrog | | - | - | | Repo read | Open the repo console and view active and past runs. | | Repo write | Trigger runs from the console prompt box. Set the repo up. Edit the **Model**, **Hooks**, **Comments**, **Standing instructions**, **Learnings** and **Flags** cards and every automation. Disable and re-enable Pullfrog on the repo. | | Repo admin | Edit the **Security** card (code pushes, signed commits, shell isolation, environment allowlist) and the **Secrets** card. Turn on **Auto-merge approved PRs** and Pullfrog for OSS. | | Outside collaborator | See only the repos they collaborate on in the organization console, with no organization-wide cards. Their repo role applies in each repo console. | | Org member | Edit the organization **Default model** card and, under **Advanced**, **Standing instructions**, **Cross-repo brief**, **Cross-repo learnings** and **Flags**. View **Analytics** on a paid plan. | | Org owner | Manage **Plan and payment**, **Providers** and **Secrets**: the plan, payment method, Pullfrog Router credit, and account-level provider keys and secrets. View the billing and Router history pages. | Each repo role includes the ones above it, so an admin can do everything a write user can. Organization roles are separate from repo roles: an org member still needs write access to change a repo's settings. On a personal account, the account owner holds every role. ## Notes * **Repo setup.** Adding `pullfrog.yml` needs write access to that repo, not an organization role. The commit is made as you; if the default branch is protected, Pullfrog opens a pull request from `pullfrog[bot]` instead. A private repository in an organization still needs a [plan](/billing) that covers it. * **Locked cards.** A card you cannot edit stays in place with a lock icon and a short message naming who can change it, so links into the console still resolve. The API enforces the same rules, so billing data never reaches a non-owner's browser. The Billing card as a non-owner sees it, with the ask-an-owner message * **Organization-wide reach.** Organization standing instructions and flags apply to every run in every repository of the organization, including [flags](/flags) that set the model or timeout. Any org member can edit them; outside collaborators cannot. * **Org owners.** Pullfrog reads the owner role from GitHub again before billing changes instead of trusting a cached value. GitHub's API calls this role `admin`. # PR reviews Source: https://docs.pullfrog.com/pr-reviews Automatic pull request reviews and re-reviews, one-click fixes for review feedback, approval checks, and auto-merge. Pullfrog reviews every new pull request, re-reviews each push, and implements the changes a review asks for in one click. Configure reviews in the repository console under **Automations โ†’ Review PRs**. ## Auto-review new PRs Pullfrog reviews a PR when it opens, or when a draft is marked ready for review. The first review opens with a summary of the change, followed by inline feedback. For small fixes, an inline comment carries a GitHub suggested change that you can commit from the thread. A Pullfrog review with a summary, the Fix all and Fix ๐Ÿ‘s links, and an inline comment carrying a suggested change The **Review PRs** card holds these options: | Option | Default | Effect | | - | - | - | | **Re-review when new commits are pushed** | On | Review each push incrementally (see [below](#re-review-on-new-commits)) | | **Allow Pullfrog to approve PRs** | Off | Submit approvals and change requests. When off, every review is a comment. | | **Review Pullfrog's own PRs** | Off | Review PRs that Pullfrog opened | | **Include PRs from external contributors** | On | Review PRs from non-collaborators. Public repositories only. | | **Include draft PRs** | Off | Review and re-review draft PRs | | **Include PRs opened by bots** | Off | Review PRs from Dependabot, Renovate, Greenkeeper, Snyk, and `github-actions[bot]`, and changesets release PRs | | **Limit reviews to target branches** | Any branch | Review only PRs into the branches you pick (see [Base branches](#base-branches)) | The Review PRs card with every option GitHub attributes a PR opened by any of your workflows to `github-actions[bot]`, so release PRs from release-please, git-pr-release, or a custom script are skipped until **Include PRs opened by bots** is on. Mention `@pullfrog` in a comment to request a one-off review on any PR. ## Re-review on new commits When new commits land on a PR that Pullfrog already reviewed, it reviews only the new changes. The re-review summarizes what changed since the previous review, so the PR keeps a running record. If a review is still running when more commits arrive, that run covers them and no second run starts. ## Base branches Pullfrog reviews PRs into any branch by default. **Limit reviews to target branches** narrows that to branches you pick from the repository's own list, which shows the default branch first and then the most recently updated ones. A team that merges feature branches into `develop` and cuts release PRs into `main` can pick `develop`. The release PR then goes unreviewed, since its changes were reviewed on the way in. The setting scopes the review on open and the re-review on push. An `@pullfrog` mention, addressing reviews, and fixing CI failures work on a PR into any branch. ## Address reviews Pullfrog implements review feedback in follow-up commits, whether the review came from Pullfrog or from a person. ### Reviews on Pullfrog's PRs When a person submits a review on a PR that Pullfrog opened, Pullfrog applies the requested changes and pushes. The **Address reviews** card under **Automations** turns this on or off; it is on by default. Pullfrog auto-addressing review feedback in a PR thread ### Comment to request a fix On any PR, comment with `@pullfrog` and the change you want. For feedback on specific lines, comment in the review thread so the change is anchored to that code. PR comment requesting changes from Pullfrog ### Fix all and Fix ๐Ÿ‘s A Pullfrog review with inline comments ends with two buttons: * **Fix all** addresses every comment in the review in one run. * **Fix ๐Ÿ‘s** addresses only the comments you reacted to with ๐Ÿ‘, and resolves their threads. Fix all and Fix ๐Ÿ‘s buttons on a Pullfrog review summary Pullfrog fix thumbs-up workflow result With **Allow Pullfrog to approve PRs** on, a fix run that leaves no Pullfrog review thread open ends by approving the PR, with a summary of what changed. A **Fix ๐Ÿ‘s** run that leaves some of Pullfrog's threads open does not approve. Pullfrog can push to a PR from a fork when the author allows edits from maintainers. ## Auto-merge approved PRs With auto-merge on, a PR that Pullfrog approves goes to GitHub's native auto-merge. GitHub merges it once your required status checks pass and any required reviews are in. Pullfrog never merges past a check or review that your branch protection requires. Auto-merge is experimental. It needs all of the following: * **Auto-merge approved PRs** turned on in the **Review PRs** card. Only a repository admin can turn it on, and the console asks you to type `MERGE` to confirm. * **Allow Pullfrog to approve PRs** turned on. * Branch protection on the base branch with at least one required status check. Without it, Pullfrog approves but does not merge. * **Allow auto-merge** turned on in the repository's GitHub settings (**Settings โ†’ General โ†’ Pull Requests**). It is off by default. Auto-merge covers every PR Pullfrog approves, including PRs from contributors and forks. A fork cannot fake a required check, so a contributor's code still has to pass your CI. A person's "Request changes" review blocks the merge until it is resolved. Add a required human reviewer to branch protection if a person must sign off on every merge. The Enable auto-merge on approval dialog, which asks for MERGE to confirm ## Progress comments While a run is in progress, Pullfrog posts a temporary "Leaping into action..." comment, updates it with the agent's task list, and deletes it when the run finishes. A Leaping into action progress comment during a run If another tool reads your PR conversation, such as an LLM-based PR watcher or a bot that mirrors comments, those temporary comments become input it pays for. Turn them off in the repository console under **Agent โ†’ Comments โ†’ Progress comments**. Pullfrog posts the first comment before your workflow starts, so only this setting stops it. The Progress comments toggle on the Comments card The `progress_comments` workflow input suppresses only the live task-list updates: ```yaml theme={null} - uses: pullfrog/pullfrog@v0 with: prompt: ${{ ... }} progress_comments: disabled ``` With the setting off, an automatic review posts nothing until the review itself lands. Output that carries a result is unaffected: | Still posted | Suppressed | | - | - | | PR reviews, inline comments, and review replies | The initial "Leaping into action..." comment | | The final result comment, including its collapsible task list | Live task-list updates during the run | | Plan comments and `@pullfrog` answers | โ€” | | Failure reports, including cancelled and crashed runs | โ€” | ## Status checks Pullfrog dispatches its GitHub Actions runs against your default branch, so the run never appears in a PR's checks list. Two checks put Pullfrog's state on the PR instead. Both are toggles in the **Review PRs** card. | Check | Default | Reports | Console toggle | | - | - | - | - | | `pullfrog` | On | Whether a Pullfrog run is in progress, succeeded, or failed | **Add Pullfrog's run status as a Check on pull requests** | | `pullfrog-approval` | Off | Whether Pullfrog would approve the PR | **Add Pullfrog's approval verdict as a Check on pull requests** | Neither check blocks a merge until you add it to the branch's required status checks in GitHub. The pullfrog check passing in a pull request's merge box ### `pullfrog` The check appears on the PR head as soon as a run is dispatched, before the runner starts, and shows **Pullfrog is running**. When the run ends, it resolves to success, or to failure, cancelled, or timed out with a link to the run logs. ### `pullfrog-approval` The check succeeds when Pullfrog has no outstanding feedback. It fails when Pullfrog requested changes or when any earlier Pullfrog review thread is still unresolved, even if the latest commit introduces no new issue. It is independent of **Allow Pullfrog to approve PRs**, so you can require the check without letting Pullfrog submit approvals. The check attaches to the exact commit Pullfrog reviewed, and only runs that produce a review verdict post it. A new push therefore has no `pullfrog-approval` check until Pullfrog re-reviews it, so a required check keeps the merge blocked until then. A re-review that finds nothing new to review, such as after a merge of the base branch, carries the previous verdict forward to the new head; a previous rejection carries forward after any re-review that submits no review. A run that fails or is cancelled posts no check, which also blocks the merge until the next run reports. The deprecated `status_checks: enabled` workflow input still posts both checks, and the console toggles cannot override it. Remove it from your workflow to let the console settings take full effect. ## Review instructions Review instructions tell Pullfrog what to focus on. Edit them in the **Custom instructions** field at the bottom of the **Review PRs** card. They apply to automatic reviews, re-reviews, and reviews you request with `@pullfrog`. Examples: "always check for missing test coverage," "flag any new dependencies," or a repository-specific style rule. Keep them short and concrete. By default, a review looks for defects โ€” anything that changes what the code does โ€” and puts each one inline at its real severity. It does not go looking for missing tests, stale comments, naming, dead code or rollout plans, and it never flags formatting. If your team wants that feedback, ask for it here, for example "flag new code that has no test" or "check the rollout order of schema changes." # Security Source: https://docs.pullfrog.com/security How Pullfrog keeps secrets, tokens and your repository safe from a prompt-injected agent. Pullfrog gives agents a real shell, git and the GitHub API, and still keeps secrets and credentials out of their reach. Independent layers block the usual prompt-injection goals: reading API keys, stealing tokens and pushing malicious code. | Layer | Protection | | - | - | | [System prompt](#system-prompt) | Tells the agent never to reveal secrets and to refuse malicious requests | | [Untrusted input isolation](#untrusted-input-isolation) | Issue and PR bodies are never inlined into the prompt | | [Secret masking](#secret-masking) | Redacts secrets in GitHub Actions logs | | [Secret isolation](#secret-isolation) | Secrets reach a run only through the workflow or an OIDC-verified request | | [Shell environment scrubbing](#shell-environment-scrubbing) | Only allowlisted environment variables reach shell commands | | [Lifecycle scripts](#lifecycle-scripts) | Setup, post-checkout and pre-push scripts run scrubbed and sandboxed | | [Filesystem sandbox](#filesystem-sandbox) | Hides on-disk credentials and blocks environment injection and git-config tampering | | [Short-lived tokens](#short-lived-tokens) | GitHub tokens are scoped to the repository and revoked after each run | | [Permission checks](#permission-checks) | Runs from people without write access are always restricted | | [Code pushes](#code-pushes) | Repo admins decide where the agent may push | Most of these layers defend against untrusted authors: people who open issues, pull requests and comments without write access. That exposure is largest on public repositories. ## System prompt Every run carries a system prompt that tells the agent not to reveal secrets or commit them, and to refuse any request it suspects is malicious. The prompt marks where the system section ends and the task begins, and the task cannot override the system section. ## Untrusted input isolation Issue and pull request bodies are the main prompt-injection vector, so Pullfrog never inlines them into the prompt. The agent gets the event metadata it needs, such as the title, and fetches the body through a Pullfrog tool. Untrusted text therefore reaches the model as tool output, not as instructions. ## Secret masking Pullfrog registers every secret with GitHub's secret masking, so a secret printed by accident shows as `***` in the Actions log. ## Secret isolation A run gets secrets from two places, and neither one exposes them by default: * **GitHub Actions secrets** reach the action only when your workflow passes them under `env:`. * **Pullfrog secrets**, stored in the console or with the CLI, are encrypted at rest. Pullfrog releases them only to a GitHub Actions run that proves with an OIDC token that it belongs to that repository. A workflow triggered by a pull request from a fork cannot get an OIDC token, so a contributor who edits the workflow in a fork cannot reach these secrets. Both kinds land in the action's own environment, where a workflow variable wins over a Pullfrog secret of the same name. Shell commands see them only as the [shell environment scrubbing](#shell-environment-scrubbing) rules allow. See [API keys](/keys) for how to store and scope secrets. ## Shell environment scrubbing The **Shell isolation** toggle in the repo console's **Security** card decides what environment shell commands get. It works the same way for every agent. The Security card: Code pushes, Signed commits, Shell isolation and Environment allowlist Shell environment scrubbing example | Setting | Console | Shell commands get | | - | - | - | | `restricted` | Shell isolation on (default) | Only the [default allowed variables](#default-allowed-variables) and your [environment allowlist](#environment-allowlist) | | `enabled` | Shell isolation off | The full environment, secrets included | | `disabled` | CLI or workflow input only | No shell at all | Shell isolation is always on for public repositories, and a repo admin can turn it off on a private one. Runs triggered by people without write access are always held to `restricted`, whatever the setting. * The allowlist is default-deny, so `env` or `printenv` cannot reveal an API key. * Variables whose names end in `_TOKEN`, `_KEY`, `_SECRET`, `_PASSWORD` or `_CREDENTIAL` are dropped even under an allowed prefix, so `GITHUB_TOKEN` and `GH_TOKEN` do not pass. Pullfrog's git operations authenticate separately and work without them. * The agent process itself keeps the full environment, because model providers need it. Only shell commands, the exfiltration path, are filtered. * In CI every shell command runs in its own Linux PID namespace, so `cat /proc/$PPID/environ` cannot read the parent's environment. Pullfrog creates the namespace with `unshare`, with passwordless `sudo`, or inside an unprivileged user namespace; see [Self-hosted runners](#self-hosted-runners). * With isolation on, shell commands cannot gain root: `sudo` fails, so a `sudo apt-get install` step needs shell isolation off or a runner image that already has the package. ### Lifecycle scripts Setup, post-checkout and pre-push scripts get the same environment and the same sandbox as shell commands. You write these scripts, but the code they call is not always yours: on a pull request from a fork, a pre-push script of `pnpm test` runs the contributor's tests. * A script that needs a secret needs that variable in the [environment allowlist](#environment-allowlist), or shell isolation turned off. A missing variable is the usual reason a working script starts to fail. * On a runner that cannot provide namespace isolation, Pullfrog skips the script instead of running it unprotected. The run continues, and the agent is told the script did not run. ### Default allowed variables These variables reach shell commands automatically. Every other variable is blocked unless you add it to the [environment allowlist](#environment-allowlist). **Prefix-matched.** Every variable with one of these prefixes passes, except a name that ends in one of the sensitive suffixes above. | Prefix | Description | | - | - | | `GITHUB_*` | GitHub Actions runner metadata and workflow context | | `RUNNER_*` | Runner configuration and paths | | `JAVA_HOME_*` | JDK version paths, for example `JAVA_HOME_17_X64` | | `GOROOT_*` | Go installation paths | **Exact names.** ```text theme={null} CI HOME LANG LOGNAME PATH SHELL SHLVL TERM TMPDIR TZ USER XDG_CONFIG_HOME XDG_RUNTIME_DIR DEBIAN_FRONTEND ``` ```text theme={null} ACCEPT_EULA AGENT_TOOLSDIRECTORY ANDROID_HOME ANDROID_NDK ANDROID_NDK_HOME ANDROID_NDK_LATEST_HOME ANDROID_NDK_ROOT ANDROID_SDK_ROOT ANT_HOME AZURE_EXTENSION_DIR BOOTSTRAP_HASKELL_NONINTERACTIVE CHROME_BIN CHROMEWEBDRIVER CONDA DOTNET_MULTILEVEL_LOOKUP DOTNET_NOLOGO DOTNET_SKIP_FIRST_TIME_EXPERIENCE EDGEWEBDRIVER GECKOWEBDRIVER GHCUP_INSTALL_BASE_PREFIX GRADLE_HOME HOMEBREW_CLEANUP_PERIODIC_FULL_DAYS HOMEBREW_NO_AUTO_UPDATE ImageOS ImageVersion JAVA_HOME NVM_DIR PIPX_BIN_DIR PIPX_HOME PSModulePath SELENIUM_JAR_PATH SGX_AESM_ADDR SWIFT_PATH VCPKG_INSTALLATION_ROOT ``` ### Environment allowlist The **Environment allowlist** field in the **Security** card passes extra variables to shell commands, one name per line. Use it for variables your build needs, such as `DATABASE_URL` or `NPM_TOKEN`, or for tools a prompt should be able to use, such as `GH_TOKEN` for the `gh` CLI. ```text theme={null} DATABASE_URL NPM_TOKEN ``` Listed values reach agent shells in plaintext, so list only variables you are willing to expose to any prompt that runs in the repository. Allowlisting `GITHUB_TOKEN` or `GH_TOKEN` gives shell commands the workflow token's permissions; narrow them with the `permissions:` block in `pullfrog.yml`. ## Filesystem sandbox In CI each shell command also runs in a mount namespace that hides or freezes three kinds of path. This applies whether shell isolation is on or off. | Path | Inside the sandbox | | - | - | | `/var/lib/pullfrog/` | An empty directory. Pullfrog keeps subscription credentials here, such as ChatGPT and Grok sign-ins, and only Pullfrog's own process reads the real files. | | `$RUNNER_TEMP/_runner_file_commands/` | A throwaway directory, so `echo X >> $GITHUB_ENV` cannot inject variables into later workflow steps. | | The repository's `.git` directory | Read-only, so the agent cannot plant a git hook or filter that runs in a later workflow step. Pullfrog's own commits run outside the sandbox and are unaffected. | The agent's built-in file tools have their own rules. They cannot write anywhere under `.git`, including `.git` pointer files in worktree and submodule layouts, and they cannot read `.git/config` or `/var/lib/pullfrog/`. ## Self-hosted runners Pullfrog runs on self-hosted runners. The shell sandbox needs `CAP_SYS_ADMIN`, which runner kinds expose differently: * **VM and bare-metal runners** work with no setup. Pullfrog uses passwordless `sudo` to create the namespace, as it does on GitHub-hosted runners. * **Containerized and Kubernetes runners**, such as [actions-runner-controller](https://github.com/actions/actions-runner-controller), usually have neither `CAP_SYS_ADMIN` nor `sudo`. Pullfrog first creates an unprivileged user namespace, which grants the capability inside that namespace only. A stock runner pod needs no configuration. Subscription credentials need passwordless `sudo` to set up `/var/lib/pullfrog/`. On a runner without it, Pullfrog skips them and uses an API key if one is available. ### What the container fallback guarantees A shell command still cannot read another process's environment variables, reach Pullfrog-managed files, undo the filesystem protections or signal the Pullfrog process. The kernel blocks cross-namespace environment reads on its own. One thing differs: inside a user namespace the container's `/proc` cannot be replaced, so a shell command can see which processes run and their command lines. Pullfrog never puts credentials on a command line. ### When it does not engage The fallback needs a pod that may create user namespaces and a node kernel that permits them. It does not engage in these cases: * **Pod seccomp.** A pod hardened to `seccompProfile: RuntimeDefault`, which the Pod Security Standards `baseline` and `restricted` profiles require, cannot create user namespaces. Stock runner pods are unaffected, because the [ARC chart](https://github.com/actions/actions-runner-controller/blob/master/charts/gha-runner-scale-set/values.yaml) sets no `securityContext` by default. * **Root pod without `CAP_SETFCAP`.** A container that runs as root needs this capability to map user IDs. Pods that run as a non-root user, the ARC default, are unaffected. * **Node kernel.** Most distributions permit unprivileged user namespaces, including Debian, Ubuntu 22.04 and earlier, RHEL 8 and 9, Amazon Linux 2023 and GKE COS. Ubuntu 23.10 and 24.04 restrict them by default (`kernel.apparmor_restrict_unprivileged_userns`), and RHEL and CentOS 7, Bottlerocket and Talos disable them (`user.max_user_namespaces=0`). If no method provides isolation, the run continues without a shell, and the log names these causes. Pullfrog never runs shell commands unsandboxed in CI. ## Short-lived tokens Pullfrog uses GitHub OIDC to get installation tokens that are scoped to the repository and expire on their own. Pullfrog also revokes them at the end of each run. The token is never in the agent's environment or in `.git/config`. Git authenticates through ASKPASS: a localhost helper hands git a code that is valid only for one operation and revokes it when the operation ends. If anything replays a code after that, Pullfrog revokes the GitHub token at once. ## Permission checks Pullfrog checks the GitHub permission of the person who triggered each run. Users with write, maintain or admin access are collaborators; everyone else is a non-collaborator. Repo admins decide which non-collaborator events start a run: | Event from a non-collaborator | Default | | - | - | | Mention | Off | | New pull request (review) | On | | New issue | On | A run triggered by a non-collaborator always uses the `restricted` shell, with a scrubbed environment, however the repository is configured. ## Signed commits Signed commits are available on [paid plans](/billing). With the setting on, Pullfrog creates commits through the GitHub API, and GitHub signs them with its own key. They show as **Verified** and satisfy a "require signed commits" branch protection rule, which otherwise rejects every push from an agent. Turn it on per repository with **Signed commits** in the **Security** card. Pull requests from forks and content tracked by Git LFS fall back to ordinary unsigned commits. ## Code pushes Repo admins set **Code pushes** in the repo console's **Security** card. The setting applies to the whole repository, and an explicit `push:` input in the workflow overrides it. | Setting | Value | The agent can | | - | - | - | | **No code pushes** | `disabled` | Comment and review only. No pushes and no signed commits. | | **Feature branches only** | `restricted` | Push feature branches and create signed commits. No pushes to the default branch, no branch deletion, no tag pushes. | | **Full push access** | `enabled` | Push anywhere GitHub branch protection allows. This is the default. | Whatever the setting, the agent can never delete the default branch. On [cross-repo runs](/flags#cross-repo), it cannot push to the default branch of any repository other than the one that triggered the run. Use GitHub branch protection rules to protect other branches on the server side. These settings control what the agent publishes, not local edits or local commits. They apply to the Pullfrog runtime, and a modified workflow can bypass them. A custom `GH_TOKEN` keeps the permissions its owner granted; Pullfrog does not narrow it. # Tools Source: https://docs.pullfrog.com/tools The GitHub, git, CI and browser tools Pullfrog gives the agent in every run. Every run gets a Pullfrog MCP server with tools for pull requests, reviews, issues, CI logs and git. The tools enforce the repository's [push and shell settings](/security), and some appear only when the run needs them. | Tool | What it does | | - | - | | **Pull requests** | | | `checkout_pr` | Checks out a PR branch, including from a fork, and returns a formatted diff. | | `create_pull_request` | Creates a pull request from the current branch. | | `update_pull_request_body` | Updates the description of an existing pull request. | | `get_pull_request` | Gets PR metadata: title, body, state, branches, author, labels and linked issues. | | **Code reviews** | | | `list_pull_request_reviews` | Lists all reviews on a pull request. | | `get_review_comments` | Gets full review thread context. | | `create_pull_request_review` | Submits a review (comment, approve or request changes) with optional inline comments and suggestions. | | `reply_to_review_comment` | Replies to a review comment thread. | | `resolve_review_thread` | Marks a review thread as resolved. | | **Issues and labels** | | | `create_issue` | Creates an issue with optional labels and assignees. | | `get_issue` | Gets issue metadata and current state. | | `get_issue_comments` | Gets the issue body and all comments. | | `get_issue_events` | Gets timeline events such as cross-references and linked commits. | | `search_issues` | Finds open or closed issues in the repository by keyword. Issue runs only. | | `find_similar_issues` | Finds older issues that may be duplicates. Issue runs with issue indexing, on [paid plans](/billing). | | `create_issue_comment` | Adds a comment to an issue or pull request. | | `edit_issue_comment` | Edits an existing comment. | | `close_current` | Closes the issue or pull request the run was triggered on, with a reason. Only for its author or someone with triage access or above. | | `reopen_current` | Reopens the issue or pull request the run was triggered on, with the same rule. | | `add_labels` | Adds existing labels to an issue or pull request. | | `remove_labels` | Removes labels from an issue or pull request. | | **CI** | | | `get_check_suite_logs` | Gets the logs of a failed check suite, with an index of the relevant lines and an excerpt. | | **Git** | | | `git` | Runs local git commands such as `status`, `diff`, `add` and `commit`. | | `git_fetch` | Fetches refs from the remote. | | `push_branch` | Pushes a branch, subject to the repository's push setting. | | `commit_changes` | Commits working-tree changes straight to the remote as a signed commit. Only when [signed commits](/security#signed-commits) are on. | | `push_tags` | Pushes a tag. Requires full push access. | | `delete_branch` | Deletes a remote branch other than the default branch. Requires full push access. | | `get_commit_info` | Gets commit metadata and a formatted diff. | | **Cross-repo** | | | `list_repos` | Lists the repositories a [cross-repo run](/flags#cross-repo) may use, with each one's access level. | | `checkout_repo` | Clones another repository from that list into a working directory. Read-only repositories cannot be pushed. | | **Shell** | | | `shell` | Runs shell commands in the [sandbox](/security#shell-environment-scrubbing), in the foreground or the background. | | `kill_background` | Stops a background process, such as a dev server. | | `start_dependency_installation` | Starts installing the project's dependencies in the background. | | `await_dependency_installation` | Waits for the dependency installation and returns its result. | | **GitHub CLI** | | | `gh` | Runs the GitHub CLI against this repository. Only when the run was triggered by someone with triage access or above; its token can read code and write issues and pull requests, and cannot push or merge. | | **Utilities** | | | `upload_file` | Uploads a local file, up to 10 MB, and returns a permanent public URL. | | `set_output` | Sets the action's `result` output for later workflow steps. Only in [custom workflows](/headless-action#capturing-agent-output). | ## Browser The agent can drive a headless Chrome browser with [agent-browser](https://github.com/vercel-labs/agent-browser). It starts your app, opens it and checks its own work the way a reviewer would. * Open pages, including a dev server the agent starts in the background with the `shell` tool. * Click, type and fill in forms. * Read the page structure and the console output to debug a UI. * Take screenshots and post them in a comment or PR with `upload_file`. The browser runs through the shell, so a run with the shell disabled has no browser. Pullfrog installs it the first time the agent uses it, so runs that never open a page skip the install. # Versions & pinning Source: https://docs.pullfrog.com/versioning What the action reference in your workflow pins, and how to pin it to a commit SHA. Your workflow references the action with a `uses:` ref, almost always the moving major tag `pullfrog/pullfrog@v0`. That ref pins less than it appears to. ## How the action is versioned The published action is a thin bootstrap. The code behind both of its steps, the agent and the post-run cleanup that saves rotated credentials, comes from npm at `^`. The behavior you care about therefore tracks the latest release in the current version line. The `uses:` ref fixes two things: * The input and output contract, read from the action's `action.yml`. * The npm range the bootstrap resolves: `^` as of the pinned revision. The `pullfrog/pullfrog@v0` tag tracks the latest `v0.x` release. The console writes this ref, and it is the one we recommend. ## Pinning to a commit SHA GitHub's [security hardening guide](https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions) recommends pinning third-party actions to a full commit SHA, because tags can move. Dependabot, [StepSecurity](https://www.stepsecurity.io/) and `pin-github-action` do this for you and keep the version as a comment: ```yaml theme={null} uses: pullfrog/pullfrog@abc123โ€ฆ # v0 ``` A pinned SHA takes both steps from npm the same way the tag does, so the agent and the cleanup step still receive patch releases. Updating the pin is what picks up a new minor version. Dependabot bumps the SHA and the `# v0` comment together: ```yaml theme={null} # .github/dependabot.yml version: 2 updates: - package-ecosystem: github-actions directory: / schedule: interval: weekly ``` ## Choosing a ref | You want | Use | | - | - | | The simplest setup that stays current | `pullfrog/pullfrog@v0` | | SHA pinning for a security policy | A commit SHA, with Dependabot to pick up new minor versions | # Google Vertex AI Source: https://docs.pullfrog.com/vertex Run Pullfrog on models hosted in your own Google Cloud project through Vertex AI. Route Pullfrog's model calls through [Vertex AI](https://cloud.google.com/vertex-ai) in your own Google Cloud project. Use it when your team already buys through Google Cloud, holds Vertex model-access approvals, or wants Google Cloud's audit and billing controls around inference. Vertex AI is bring-your-own-key only. Google Cloud bills inference to your account, and Pullfrog never proxies Vertex traffic. ## Setup In the Pullfrog console, pick the **Google Vertex AI** tile on the **Provider** card. Create a Google Cloud service account with the `roles/aiplatform.user` role and download a JSON key. Click **Set up** on the tile and paste the whole JSON object as `VERTEX_SERVICE_ACCOUNT_JSON`. The Configure Google Vertex AI dialog with the VERTEX_SERVICE_ACCOUNT_JSON field You can store it as a GitHub Actions secret instead and map it in the workflow's `env:` block. Add these to the `env:` block of `.github/workflows/pullfrog.yml`. None of them is secret. ```yaml theme={null} - name: Run agent uses: pullfrog/pullfrog@v0 with: prompt: ${{ inputs.prompt }} env: GOOGLE_CLOUD_PROJECT: my-project VERTEX_LOCATION: global VERTEX_MODEL_ID: # only when the key is a GitHub Actions secret VERTEX_SERVICE_ACCOUNT_JSON: ${{ secrets.VERTEX_SERVICE_ACCOUNT_JSON }} ``` Enable the Vertex AI API (`aiplatform.googleapis.com`) for the project, then enable any gated model in [Model Garden](https://console.cloud.google.com/agent-platform/model-garden). ## Variables | Name | Secret | Purpose | | - | - | - | | `VERTEX_SERVICE_ACCOUNT_JSON` | Yes | The full service-account JSON key, not a file path. | | `GOOGLE_CLOUD_PROJECT` | No | Project ID. Optional when the JSON key has a `project_id`. | | `VERTEX_LOCATION` | No | Vertex location. Use `global` unless data residency needs a regional endpoint. | | `VERTEX_MODEL_ID` | No | Exact Vertex model ID. Pullfrog runs it as written and never upgrades it. | A value stored in the console needs no `env:` line, because Pullfrog injects it into every run. A value set in the workflow wins over a stored one. On an account that pays through [Pullfrog Router](/billing#pullfrog-router), store the service-account key in the Pullfrog console. Pullfrog decides how to fund a run before the runner starts, when GitHub Actions secrets are not visible to it, so a run whose key exists only there falls back to the Router's default model. ## Model IDs The model menu has a single **Google Vertex AI** entry; `VERTEX_MODEL_ID` names the actual model. Use the ID that Model Garden shows for a Claude, Gemini or partner model your project has enabled. To change models, edit `VERTEX_MODEL_ID` and commit. ## Routing Pullfrog reads the model ID to choose the agent: * **Claude models**, whose ID starts with `claude-`, run on [Claude Code](https://code.claude.com/docs/en/google-vertex-ai). Pullfrog sets `CLAUDE_CODE_USE_VERTEX=1` and passes the project and location in Claude Code's own variable names. * **Every other model** runs on OpenCode's `google-vertex` provider. ## Troubleshooting | Symptom | Fix | | - | - | | `VERTEX_MODEL_ID env var is required when the model is set to "vertex/byok"` | The repository uses Google Vertex AI, but the workflow does not set `VERTEX_MODEL_ID`. Add it to `env:`. | | "Google Vertex AI model selected but required configuration is missing" | The message lists each missing value: `VERTEX_SERVICE_ACCOUNT_JSON`, `GOOGLE_CLOUD_PROJECT` (when the key has no `project_id`), `VERTEX_LOCATION`, or `VERTEX_MODEL_ID`. | | Google authentication error | `VERTEX_SERVICE_ACCOUNT_JSON` must hold the JSON object itself, not a file path. Pullfrog writes it to a credentials file on the runner and sets `GOOGLE_APPLICATION_CREDENTIALS` for the agent. | | Permission or model-access error | Check that the service account has `roles/aiplatform.user`, the Vertex AI API is on, and the model is enabled in Model Garden for `VERTEX_LOCATION`. | # Watch a PR Source: https://docs.pullfrog.com/watch Stream a pull request's reviews, comments and checks to your terminal or to a coding agent, without polling GitHub. Pullfrog streams a pull request's activity to your terminal: one structured event per new review, comment, inline review thread, PR state change, or completed check suite. ```bash theme={null} npx pullfrog watch --pr 42 ``` Pullfrog already receives the GitHub webhooks for your repository, so each event reaches you within a second of firing. The stream makes no GitHub API calls of its own; only a periodic access check does, at most once every five minutes. ## Usage Run the command inside your repository, or name the repository: ```bash theme={null} npx pullfrog watch --pr 42 # infers the repo from the origin remote npx pullfrog watch owner/repo --pr 42 ``` Each event is one line of JSON on stdout, so the stream pipes into another process unchanged: ```json theme={null} {"cursor":"11022","repo":"pullfrog/app","pr":1267,"kind":"check","createdAt":"2026-08-28T22:05:55.334Z","data":{"app":"GitHub Actions","status":"completed","headSha":"d9eeb89406c21c91d42bcf1ebcddb72a424df8c2","conclusion":"success"}} ``` Add `--pretty` for human-readable lines. ## Watching from an agent The default command runs until you stop it, which suits a terminal or a harness that reads a long-running process's output. Most coding agents can only call something that returns, so Pullfrog offers two shapes that do. ### `--once` With `--once`, the command waits for the next batch of activity, prints it, and exits. Any agent that can run a shell command can use it as a monitor. ```bash theme={null} npx pullfrog watch --pr 42 --once ``` It waits up to 20 seconds. If nothing happens, it exits 0 with no output, so a loop is repeated calls. Each call saves its position (see [Resuming](#resuming)), so the next call starts where the last one stopped. ### `pullfrog mcp` The MCP server exposes the same wait as a tool named `pr_wait`, which blocks until something happens on the PR and returns it. Register the server once, and the agent can wait on a PR like any other tool call. ```bash Claude Code theme={null} claude mcp add pullfrog -- npx pullfrog mcp ``` ```toml Codex theme={null} # ~/.codex/config.toml [mcp_servers.pullfrog] command = "npx" args = ["pullfrog", "mcp"] tool_timeout_sec = 120 # must exceed the longest pr_wait you ask for ``` ```json opencode theme={null} { "mcp": { "pullfrog": { "type": "local", "command": ["npx", "pullfrog", "mcp"], "enabled": true, // milliseconds, and must exceed the longest pr_wait you ask for "timeout": 120000 } } } ``` The tool takes the PR number, an optional `repo` as `owner/repo`, and an optional `max_wait_seconds` that defaults to 20 and is capped at 50. The call blocks, so the harness's MCP request timeout must be longer than the wait you ask for. The snippets above raise it where the default is too low. ## Options | Flag | Description | | - | - | | `--pr ` | pull request number to watch (required) | | `--once` | wait for one batch of events, print it, and exit | | `--since ` | resume from a cursor instead of the saved position | | `--pretty` | human-readable output instead of JSON lines | | `-h, --help` | show help | ## Event kinds Every line carries a `kind`, the affected `pr`, an ISO `createdAt`, an opaque `cursor`, and a curated `data` object. | Kind | Fires on | | - | - | | `pr` | pull request opened / closed / synchronized / edited / labeled / etc. | | `review` | a review submitted, dismissed, or edited | | `review_comment` | an inline review comment created, edited, or deleted | | `review_thread` | an inline review thread resolved or unresolved | | `comment` | a top-level comment on the PR | | `check` | a check suite completed (carries `status` + `conclusion`) | The `data` object holds enough to decide whether to react: actor, action, state, a truncated body or title, and the `html_url`. Fetch the full detail from that URL when you need it. ## Resuming The stream is cursor-based. The last position is saved per repository and PR under `~/.pullfrog/watch/`, so a restarted watcher or the next `--once` call continues from where the previous one stopped. Pullfrog buffers a PR's events only while a watcher has checked in within the last minute, and keeps buffered events for an hour. Events that arrive while nothing is watching are not delivered later, so keep `--once` calls less than a minute apart. * `--since ` starts from a cursor you name, ignoring the saved one. * `PULLFROG_STATE_DIR` moves the saved positions out of the home directory. A watch that has never run for a PR starts from now rather than replaying history. ## Authentication The command authenticates with your GitHub CLI token and streams events only for repositories that token can read. Pullfrog must be [set up](/getting-started) on the repository. Sign in to the GitHub CLI first: ```bash theme={null} gh auth login ```