# Run GitHub Copilot CLI in GitHub Actions Without PATs or Runaway AI Costs

> Source: <https://dev.to/pwd9000/run-github-copilot-cli-in-github-actions-without-pats-or-runaway-ai-costs-3dpf>
> Published: 2026-07-20 16:02:20+00:00

AI automation in CI has always had two awkward questions: which long-lived token do you give the agent, and how do you stop an unattended run from spending more than expected?

GitHub has now addressed both. Since 2 July 2026, GitHub Copilot CLI can authenticate inside GitHub Actions with the workflow's built-in `GITHUB_TOKEN`

. No personal access token (PAT) is required. Copilot CLI also supports per-session AI credit limits, so a non-interactive run can stop when it reaches the amount you set.

In this tutorial, we will build a manually triggered repository-review workflow that:

`--max-ai-credits`

The result is a useful starting point for repository health checks, CI failure analysis, release preparation, and scheduled engineering reports.

Current status:AI credit session limits are in public preview. The syntax and billing behaviour described here were verified against GitHub's documentation on 20 July 2026.

The finished workflow has a deliberately small trust boundary:

```
Developer selects Run workflow
             |
             v
GitHub Actions creates a short-lived GITHUB_TOKEN
             |
             | contents: read
             | copilot-requests: write
             v
Copilot CLI reviews the ephemeral checkout
             |
             | --max-ai-credits 31, 50, or 100
             v
Markdown report is written to the job summary
             |
             v
Workflow verifies that the checkout is unchanged
```

There is no PAT in repository secrets. The workflow token exists only for the job, and its permissions are declared explicitly. AI credits used in an organisation-owned repository are billed to the organisation.

This tutorial invokes Copilot CLI directly because that makes the authentication, permissions, and cost boundary easy to inspect. GitHub recommends [GitHub Agentic Workflows](https://github.com/github/gh-aw) for most production automation because it adds safeguards designed for unattended agents. We will compare the two approaches later.

You will need:

The session-limit feature requires Copilot CLI `1.0.66`

or later. The workflow installs the latest version so that both `GITHUB_TOKEN`

authentication and `--max-ai-credits`

are available.

No PAT, API key, or custom Actions secret is required.

GitHub defines one AI credit as $0.01 USD. A limit of 50 AI credits therefore represents a nominal session boundary of $0.50 USD.

Session limits are **soft caps**. Copilot only knows the cost of a response after that response completes, so an in-flight response can make the final usage slightly higher than the configured limit. Session limits complement organisation budgets and cost centres; they do not replace them.

GitHub also recommends setting a limit above 30 credits because many model calls cost more than 20 credits. That is why this tutorial offers 31 as the lowest choice rather than using a tiny value that may prevent useful work.

An organisation owner must allow Actions workflows to bill Copilot CLI usage directly to the organisation.

GitHub enables this setting by default when the existing Copilot CLI policy is enabled, but it is worth checking before debugging a failed workflow.

When this policy is active, a workflow can authenticate with `GITHUB_TOKEN`

by declaring one additional permission:

```
permissions:
  contents: read
  copilot-requests: write
```

`contents: read`

lets the checkout action read the repository. `copilot-requests: write`

allows the token to make Copilot requests billed to the organisation. It does not grant write access to repository contents.

Create `.github/workflows/copilot-ci-review.yml`

in the repository you want Copilot to inspect.

```
name: Copilot CLI repository review

on:
  workflow_dispatch:
    inputs:
      max_ai_credits:
        description: Maximum AI credits for this Copilot session
        required: true
        default: '50'
        type: choice
        options:
          - '31'
          - '50'
          - '100'

permissions:
  contents: read
  copilot-requests: write

concurrency:
  group: copilot-ci-review-${{ github.ref }}
  cancel-in-progress: true

jobs:
  review:
    name: Run bounded Copilot review
    runs-on: ubuntu-latest
    timeout-minutes: 10

    steps:
      - name: Check out repository
        uses: actions/checkout@v6

      - name: Install latest Copilot CLI
        run: |
          npm install --global @github/copilot@latest
          copilot --version

      - name: Review repository
        id: copilot
        shell: bash
        env:
          GITHUB_TOKEN: ${{ github.token }}
          MAX_AI_CREDITS: ${{ inputs.max_ai_credits }}
          REPORT_PATH: ${{ runner.temp }}/copilot-review.md
          PROMPT: >-
            Perform a read-only review of this repository at the current commit. Do not modify files. Produce a concise Markdown report containing: likely build and test commands based on repository evidence; the top three reliability or security risks with repository-relative file references; missing or weak automated checks; and three prioritised actions. Do not print secrets, tokens, or environment-variable values.

        run: |
          set -o pipefail
          copilot --yolo -p "$PROMPT" \
            --max-ai-credits "$MAX_AI_CREDITS" \
            | tee "$REPORT_PATH"

      - name: Publish Copilot report
        if: ${{ always() }}
        shell: bash
        env:
          REPORT_PATH: ${{ runner.temp }}/copilot-review.md
        run: |
          if [[ -s "$REPORT_PATH" ]]; then
            cat "$REPORT_PATH" >> "$GITHUB_STEP_SUMMARY"
          else
            echo "## Copilot CLI review" >> "$GITHUB_STEP_SUMMARY"
            echo "No report was produced. Check the workflow log." >> "$GITHUB_STEP_SUMMARY"
          fi

      - name: Verify Copilot made no file changes
        if: ${{ always() }}
        shell: bash
        run: |
          if [[ -n "$(git status --porcelain)" ]]; then
            echo "Copilot changed the checkout unexpectedly:"
            git status --short
            exit 1
          fi
```

You can also find the complete sample in [ code/copilot-ci-review.yml](https://./code/copilot-ci-review.yml).

Let us unpack the controls that matter.

The workflow only runs through `workflow_dispatch`

. That avoids automatically feeding code from untrusted pull requests into an agent with broad local tool access.

The credit limit is a `choice`

rather than free text. Users can select 31, 50, or 100 credits, but cannot inject arbitrary shell content through the workflow input.

This line exposes the job's automatically generated token to Copilot CLI:

```
env:
  GITHUB_TOKEN: ${{ github.token }}
```

The token is created for the workflow job, constrained by the `permissions`

block, and expires when the job ends. There is no secret to rotate and no individual developer identity tied to the automation.

GitHub's direct-invocation example uses `--yolo`

so Copilot does not pause for interactive tool approvals in Actions:

```
copilot --yolo -p "$PROMPT" --max-ai-credits "$MAX_AI_CREDITS"
```

The name is memorable because the risk is real. `--yolo`

gives Copilot broad access to the workflow environment. A prompt saying "do not modify files" is guidance, not a security boundary.

The actual boundaries are the manual trigger, read-only repository permission, ephemeral runner, timeout, credit cap, and final clean-worktree check. Do not add deployment credentials or production secrets to this job.

The report is written to `${{ runner.temp }}`

instead of the repository workspace. This lets the final step use `git status --porcelain`

to detect any tracked or untracked file created by the agent.

The report step uses `if: ${{ always() }}`

. If Copilot reaches the credit limit or exits with an error after producing partial output, the workflow still attempts to publish that output to the job summary.

The workflow combines:

`--max-ai-credits`

, which bounds model usage for the Copilot session`timeout-minutes: 10`

, which bounds total job runtimeThe concurrency group also cancels an older run on the same branch when a replacement starts. This reduces accidental duplicate spend.

Commit the workflow to the repository's default branch, then:

The job should:

`GITHUB_TOKEN`

Open the completed run and select **Summary**. A successful result will resemble:

```
## Repository review

### Likely build and test commands

- `npm ci`
- `npm test`
- `npm run lint`

### Reliability or security risks

1. The deployment workflow uses a floating third-party action version...
2. Integration tests do not cover the authentication failure path...
3. Dependency updates are not automated...

### Prioritised actions

1. Pin external actions to reviewed commit SHAs.
2. Add an authentication failure integration test.
3. Enable grouped dependency update pull requests.
```

The exact findings will depend on the repository and model. Treat the report as triage input, not as proof that the repository is secure or production-ready.

Run the workflow again and select **31** AI credits. A sufficiently complex repository review may reach the limit before completing.

When a non-interactive session reaches its limit, Copilot stops cleanly and the command ends. Because the cap is soft, a response already in progress completes first and may take the final total slightly above 31 credits.

Do not rely on forcing the limit as a deterministic test. Model selection, token usage, and repository complexity all affect consumption. The repeatable checks are:

`--max-ai-credits`

receiving the selected valueUser-level budgets are not considered when Actions usage is billed directly to the organisation because the activity is not attributed to an individual user.

Direct Copilot CLI execution is powerful, but it needs the same threat modelling as any other privileged CI automation.

| Risk | Control in this tutorial | Production recommendation |
|---|---|---|
| Long-lived credential theft | Uses job-scoped `GITHUB_TOKEN`
|
Do not replace it with a PAT unless there is a documented requirement |
| Repository modification |
`contents: read` and clean-worktree check |
Keep write operations in a separate reviewed job |
| Untrusted pull request content | Manual trigger only | Never run this pattern on forked PRs with sensitive credentials |
| Unbounded model usage | Selectable `--max-ai-credits` value |
Add organisation budgets, alerts, and cost-centre attribution |
| Runaway execution | Ten-minute timeout and concurrency cancellation | Tune the timeout to the smallest useful value |
| Secret disclosure | No extra secrets and prompt forbids printing environment values | Keep deployment secrets out of the job entirely |
| Unsafe agent output | Human reads the job summary | Never execute commands copied from the report automatically |
| Dependency drift | CLI version is printed in the log | Pin a tested CLI version after validating new releases |

For high-assurance environments, pin `actions/checkout`

to a reviewed full commit SHA rather than a moving major-version tag. You can also pin `@github/copilot`

after testing a specific release that supports both token authentication and session limits.

Remember that repository content can contain prompt-injection instructions. Read-only GitHub permissions stop a compromised prompt from pushing code, but the agent can still read files available in the checkout and interact with its local runner environment. Keep the environment intentionally sparse.

GitHub's documentation recommends Agentic Workflows for most automation scenarios. Direct CLI invocation still has a useful place when you need to add one bounded reasoning step to an existing workflow.

| Consideration | Direct Copilot CLI step | GitHub Agentic Workflows |
|---|---|---|
| Definition | Standard Actions YAML | Natural-language Markdown compiled to Actions YAML |
| Existing workflow integration | Straightforward | Better suited to agent-first workflows |
| Authentication |
`GITHUB_TOKEN` with `copilot-requests: write`
|
`GITHUB_TOKEN` by default |
| Guardrails | You design them | Includes agent-focused integrity, firewall, safe-output, and threat-detection controls |
| Best fit | A bounded task inside an established pipeline | Issue triage, reporting, compliance, and change-producing autonomous workflows |

Use the direct pattern when you understand and control the prompt, trigger, tools, and environment. Start with Agentic Workflows when the agent will process untrusted content, propose repository changes, or operate across a broader part of the software delivery lifecycle.

Once the basic workflow is working, the same pattern can support several read-only DevOps tasks:

Download test results or build logs as artifacts, then ask Copilot to identify the likely failure chain and recommend the next diagnostic action. Avoid passing raw secrets or environment dumps into the prompt.

Ask Copilot to inspect changelogs, dependency updates, migrations, tests, and deployment definitions, then produce a checklist for a human release owner.

Ask Copilot to review Terraform, Bicep, Kubernetes, or workflow files for risky defaults, missing validation, and likely operational gaps. Keep cloud credentials out of the job and do not let the report apply changes automatically.

Replace `workflow_dispatch`

with a trusted `schedule`

trigger after the prompt and cost profile are stable. Keep concurrency, timeout, permissions, and AI credit limits in place.

Use this checklist before adopting the workflow more broadly:

`contents: read`

and `copilot-requests: write`

.`1.0.66`

or later.For a stronger validation, temporarily add a harmless tracked test file to the prompt's requested output. The clean-worktree step should detect the change and fail. Remove that test immediately afterwards; the production prompt should remain read-only.

Check all three layers:

`copilot-requests: write`

.`GITHUB_TOKEN: ${{ github.token }}`

is present on the Copilot step.Also confirm that the repository belongs to the organisation whose policy and billing you configured.

`--max-ai-credits`

is unknown
The installed CLI is too old. Session limits require Copilot CLI `1.0.66`

or later. Check the version printed by the installation step and reinstall the latest package:

```
npm install --global @github/copilot@latest
copilot --version
```

This can happen because the session limit is a soft cap. A model response already in progress is allowed to finish. Use the session limit together with organisation budgets and spending limits.

That is intentional. `if: ${{ always() }}`

preserves partial output and writes a diagnostic message when no report exists. The overall job still retains the Copilot step's failure state.

Inspect the `git status --short`

output. The prompt may have caused Copilot to create or edit a file despite the read-only instruction. Tighten the task, remove unnecessary tools or credentials, and consider moving the use case to Agentic Workflows before enabling it again.

Running an AI agent in CI no longer needs to mean storing a developer's PAT or accepting an open-ended model bill. GitHub Actions can issue Copilot CLI a short-lived, narrowly scoped `GITHUB_TOKEN`

, while `--max-ai-credits`

gives every run an explicit session boundary.

The important lesson is that authentication and cost controls are only part of the design. The trigger, repository permissions, runner contents, timeout, prompt, output handling, and human approval path all determine whether the automation is trustworthy.

Start with a manually triggered, read-only report like this one. Measure its output and cost, keep the environment free of sensitive credentials, and only expand its authority when the workflow has earned it.

Like, share, follow me on: 🐙 [GitHub](https://github.com/Pwd9000-ML) | 🐧 [X](https://x.com/pwd9000) | 👾 [LinkedIn](https://www.linkedin.com/in/marcel-pwd9000/)

Date: 20-07-2026
