> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ancha.io/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> These docs describe the Ancha CLI, npm package @ancha-labs/cli version 0.1.4, and the hosted workspace at app.ancha.io. Coding agents should start at https://docs.ancha.io/coding-agents. Run the CLI as `ancha` after `npm install -g @ancha-labs/cli`, or as `npx -y @ancha-labs/cli@0.1.4` without installing. Pass --json for machine-readable output, or set ANCHA_JSON=1. Every command ends with a `next:` line naming the next command. Exit codes: 0 pass, 1 a check failed or a comparison regressed, 2 usage, config or authentication error, 3 infrastructure error, 4 unimplemented endpoint with --strict.

# GitHub

> A stateful replica of GitHub's REST API: repositories, commits and Git data, file contents, pull requests and reviews, issues and labels, check runs, Actions runs and deployments.

The GitHub replica implements 71 REST endpoints over a real commit graph: branches, commits, trees and file contents change as your agent pushes, opens pull requests and merges. Its key is `github`. It was tested with `@octokit/rest`.

## Connect

| Variable | Value |
| - | - |
| `GITHUB_API_URL` | Base URL of the REST API. |
| `GITHUB_TOKEN` | Fake token. Send it in the `Authorization` header with the `Bearer` or `token` scheme. |
| `GITHUB_WEBHOOK_SECRET` | Signs webhook deliveries in `X-Hub-Signature-256`. Verify against the raw request body. |

```js Node theme={null}
import { Octokit } from '@octokit/rest';
const github = new Octokit({ auth: process.env.GITHUB_TOKEN, baseUrl: process.env.GITHUB_API_URL });
await github.repos.get({ owner: 'acme', repo: 'starter' });
```

```python Python theme={null}
import os
from github import Github, Auth
github = Github(base_url=os.environ['GITHUB_API_URL'].rstrip('/'), auth=Auth.Token(os.environ['GITHUB_TOKEN']))
github.get_repo('acme/starter')
```

These are the snippets `ancha connect github` prints. `acme/starter` is the repository in the starter scene that `ancha init` writes. Worlds use `acme/orders`.

## Endpoints

All 71 endpoints are partial: they implement the common request shapes, and `ancha twins coverage github` lists what each one leaves out. Any other route returns HTTP 501 with GitHub's error shape and `x-ancha-gap: 1`.

### Account and repositories

| Method | Path |
| - | - |
| `GET` | `/user` |
| `GET` | `/user/repos` |
| `GET` | `/orgs/:org/repos` |
| `GET` | `/repos/:owner/:repo` |
| `GET` | `/repos/:owner/:repo/branches` |
| `GET` | `/repos/:owner/:repo/branches/:branch` |

### Commits and Git data

| Method | Path |
| - | - |
| `GET` | `/repos/:owner/:repo/commits` |
| `GET` | `/repos/:owner/:repo/commits/:ref` |
| `GET` | `/repos/:owner/:repo/compare/:base...:head` |
| `GET` | `/repos/:owner/:repo/git/blobs/:sha` |
| `POST` | `/repos/:owner/:repo/git/blobs` |
| `GET` | `/repos/:owner/:repo/git/trees/:sha` |
| `POST` | `/repos/:owner/:repo/git/trees` |
| `GET` | `/repos/:owner/:repo/git/commits/:sha` |
| `POST` | `/repos/:owner/:repo/git/commits` |
| `GET` | `/repos/:owner/:repo/git/ref/:ref` |
| `GET` | `/repos/:owner/:repo/git/matching-refs/:ref?` |
| `POST` | `/repos/:owner/:repo/git/refs` |
| `PATCH` | `/repos/:owner/:repo/git/refs/:ref` |
| `DELETE` | `/repos/:owner/:repo/git/refs/:ref` |

Object SHAs are deterministic identities, not real Git content hashes. Commits are immutable, and new ones take their date from the simulated clock.

### File contents

| Method | Path |
| - | - |
| `GET` | `/repos/:owner/:repo/contents/:path?` |
| `PUT` | `/repos/:owner/:repo/contents/:path` |

A file write creates a commit on an existing branch. Updates need the file's current blob SHA, as on GitHub.

### Pull requests and reviews

| Method | Path |
| - | - |
| `GET` | `/repos/:owner/:repo/pulls/:number/reviews` |
| `POST` | `/repos/:owner/:repo/pulls/:number/reviews` |
| `GET` | `/repos/:owner/:repo/pulls/:number/reviews/:id` |
| `GET` | `/repos/:owner/:repo/pulls/comments` |
| `GET` | `/repos/:owner/:repo/pulls/comments/:id` |
| `PATCH` | `/repos/:owner/:repo/pulls/comments/:id` |
| `DELETE` | `/repos/:owner/:repo/pulls/comments/:id` |
| `GET` | `/repos/:owner/:repo/pulls/:number/comments` |
| `POST` | `/repos/:owner/:repo/pulls/:number/comments` |
| `GET` | `/repos/:owner/:repo/pulls` |
| `POST` | `/repos/:owner/:repo/pulls` |
| `GET` | `/repos/:owner/:repo/pulls/:number` |
| `PATCH` | `/repos/:owner/:repo/pulls/:number` |
| `GET` | `/repos/:owner/:repo/pulls/:number/merge` |
| `PUT` | `/repos/:owner/:repo/pulls/:number/merge` |
| `GET` | `/repos/:owner/:repo/pulls/:number/files` |
| `GET` | `/repos/:owner/:repo/pulls/:number/commits` |

Pull requests are between branches of the same repository. A merge makes a two-parent merge commit when the base is an ancestor of the head. A diverged or stale head returns 409, and a closed or draft pull request returns 405. Squash, rebase and cross-repository pull requests are not modeled.

### Issues and comments

| Method | Path |
| - | - |
| `GET` | `/repos/:owner/:repo/issues` |
| `POST` | `/repos/:owner/:repo/issues` |
| `GET` | `/repos/:owner/:repo/issues/comments` |
| `GET` | `/repos/:owner/:repo/issues/comments/:id` |
| `PATCH` | `/repos/:owner/:repo/issues/comments/:id` |
| `DELETE` | `/repos/:owner/:repo/issues/comments/:id` |
| `GET` | `/repos/:owner/:repo/issues/:number` |
| `PATCH` | `/repos/:owner/:repo/issues/:number` |
| `GET` | `/repos/:owner/:repo/issues/:number/comments` |
| `POST` | `/repos/:owner/:repo/issues/:number/comments` |

Issues and pull requests share one numbering sequence. Labels apply on create and update, and the `labels` filter matches issues that carry every listed label, ignoring case. Assignees and milestones are not modeled.

### Labels

| Method | Path |
| - | - |
| `GET` | `/repos/:owner/:repo/labels` |
| `POST` | `/repos/:owner/:repo/labels` |
| `GET` | `/repos/:owner/:repo/labels/:name` |
| `PATCH` | `/repos/:owner/:repo/labels/:name` |
| `DELETE` | `/repos/:owner/:repo/labels/:name` |
| `GET` | `/repos/:owner/:repo/issues/:number/labels` |
| `POST` | `/repos/:owner/:repo/issues/:number/labels` |
| `PUT` | `/repos/:owner/:repo/issues/:number/labels` |
| `DELETE` | `/repos/:owner/:repo/issues/:number/labels` |
| `DELETE` | `/repos/:owner/:repo/issues/:number/labels/:name` |

Repository labels have a name, color and description. Giving an issue a label the repository does not declare creates it, as GitHub does. Names match without regard to case. Label suggestions are a gap.

### Check runs and Actions

| Method | Path |
| - | - |
| `GET` | `/repos/:owner/:repo/commits/:ref/check-runs` |
| `GET` | `/repos/:owner/:repo/check-runs/:id` |
| `GET` | `/repos/:owner/:repo/actions/runs` |
| `GET` | `/repos/:owner/:repo/actions/workflows/:workflow/runs` |
| `GET` | `/repos/:owner/:repo/actions/runs/:id` |
| `POST` | `/repos/:owner/:repo/actions/runs/:id/rerun` |

Check runs are read-only starter data. Actions runs exist only for the simulated pipelines a living world defines; no workflow actually executes.

### Deployments

| Method | Path |
| - | - |
| `GET` | `/repos/:owner/:repo/deployments` |
| `POST` | `/repos/:owner/:repo/deployments` |
| `GET` | `/repos/:owner/:repo/deployments/:id` |
| `GET` | `/repos/:owner/:repo/deployments/:id/statuses` |
| `POST` | `/repos/:owner/:repo/deployments/:id/statuses` |
| `GET` | `/repos/:owner/:repo/deployments/:id/statuses/:statusId` |

A successful deployment status for the `production` environment moves production to that deployment's commit.

## Events

Changes emit GitHub webhook events, signed with `GITHUB_WEBHOOK_SECRET`: pushes and branch updates emit `push`, pull request changes and merges emit `pull_request`, comments emit `issue_comment`, issues emit `issues` with the actions `opened`, `edited`, `closed`, `reopened`, `labeled` and `unlabeled`, and deployment statuses emit `deployment_status`. Agents receive them through the trial event feed or by HTTP. See [ancha.yaml](https://docs.ancha.io/reference/ancha-yaml.md).

## Starter data

The `github-starter` dataset holds three private repositories of the organization `acme`.

| Ref | Record |
| - | - |
| `$github_bot` | User `ancha` ("Ancha assistant"). The token authenticates as this user. |
| `$github_ben`, `$github_greg`, `$github_rachel`, `$github_victor` | Users `ben` (Ben Carter), `greg` (Greg Wilson), `rachel` (Rachel Moore) and `victor` (Victor Lane). |
| `$github_orders` | Repository `acme/orders`, default branch `main`: the Orders API. |
| `$github_web` | Repository `acme/web`: the dashboard app. |
| `$github_sync` | Repository `acme/warehouse-sync`: copies customer warehouse tables into Acme. |

### acme/orders

| Ref | Record |
| - | - |
| `$github_pagination`, `$github_node24`, `$github_idempotency`, `$github_retries` | Four merged commits on `main`, from 50 hours to 8 hours before start: pagination for `GET /orders`, the Node 24 upgrade, idempotency keys for order creation, and webhook retries with backoff. |
| `$github_healthy` | Commit "Pin worker concurrency to 32 after the rollback" on `main`, 2 hours before start, with `config/runtime.ts`, `README.md` and `docs/runbook.md`. Production points here. |
| `$github_docs` | Commit "Document deployment checks" on branch `runbook-update`. Its "Documentation checks" check run succeeded. |
| `$github_rate_limit` | Commit "Rate-limit order creation per API key" on branch `rate-limit-orders`, 40 minutes before start. Its CI check run succeeded. |
| `$github_runbook_pr` | Draft pull request #12, "Clarify recovery checks in the Orders runbook", from `runbook-update` into `main`. |
| `$github_rate_limit_pr` | Open pull request #11, "Rate-limit order creation per API key", from `rate-limit-orders`. |
| `$github_pagination_pr`, `$github_node24_pr`, `$github_idempotency_pr`, `$github_retries_pr` | Merged pull requests #3, #5, #8 and #10 for the four merged commits. |
| `$github_export_issue` | Open issue #13, "Explain delayed CSV exports", with one comment from Ben. |
| `$github_cancel_issue`, `$github_states_issue` | Open issues #6, "Return 409 when an order is cancelled twice", and #9, "Document the order states". |
| `$github_cents_issue`, `$github_page_issue`, `$github_timeout_issue`, `$github_rollup_issue` | Closed issues #1, #2, #4 and #7, each fixed by one of the merged pull requests. |

### acme/web and acme/warehouse-sync

| Ref | Record |
| - | - |
| `$github_web_main` | Commit "Release 2026.10.29" on `main` of `acme/web`. Production points here. |
| `$github_web_schedule`, `$github_web_schedule_pr` | Commit "Add the report schedule page" on branch `report-schedules`, and its open pull request #3. |
| `$github_web_dark`, `$github_web_tooltips` | Open issue #1, "Dark mode for dashboards", and closed issue #2, "Chart tooltips overflow on mobile". |
| `$github_sync_main` | Commit "Stream large tables in batches" on `main` of `acme/warehouse-sync`. Production points here. |
| `$github_sync_retry`, `$github_sync_stall` | Open issue #1, "Retry Snowflake connections on 503", and closed issue #2, "Sync stalls on tables over 50M rows". |

The starter scene that `ancha init` writes uses a different, smaller repository, `acme/starter`.

## Checks

| Check | Example |
| - | - |
| `github.file_at` | `{ github.file_at: [$github_orders, main, docs/runbook.md], contains: "health check" }` |
| `github.pull` | `{ github.pull: { pull: $github_runbook_pr, merged: true } }` |
| `github.production` | `{ github.production: { repo: $github_orders, commit: $github_docs } }` |
| `github.issue` | `{ github.issue: { repo: $github_orders, body_contains: [CSV, export], labels: [bug], state: open, count: 1 } }` |

The second element of `github.file_at` is a branch name, a commit ref, `default` or `production`. `contains` and `equals` compare exact bytes and are case-sensitive. To check that the agent opened an issue, use a `github.issue` state check, or a trace check such as `{ called: "POST /repos/acme/orders/issues" }`. See [Checks reference](https://docs.ancha.io/reference/checks.md#github).

## Limits

* No branch protection, permissions model, assignees, milestones or releases.
* No real Actions execution, jobs, artifacts or logs.
* Annotated tags, symlinks and submodules are not modeled.


## Related topics

- [Test file (scene.yaml)](https://docs.ancha.io/reference/test-file.md)
- [Checks reference](https://docs.ancha.io/reference/checks.md)
- [Worlds](https://docs.ancha.io/concepts/worlds.md)
- [CI](https://docs.ancha.io/cloud/ci.md)
- [ancha world gen](https://docs.ancha.io/cli/world-gen.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.