Skip to main content
The GitHub twin is a deterministic in-process simulation of the GitHub REST API. It covers issues, pull requests, comments, labels, repositories, combined commit status, and the parts of the search API that agents tend to reach for. Every twin instance starts from a scenario seed and resets between runs, so the same scenario produces the same state every time.

What it covers

  • Repositories, issues, pull requests, comments, labels
  • Combined commit status (latest per context)
  • Search across issues and PRs
  • MCP tools for triage, labeling, merging, and review workflows
  • Webhook-style event payloads recorded for assertions

What it does not cover

GitHub Actions execution, billing, Copilot APIs, and real OAuth flows. The twin hands out a static token; if you need real OAuth, run against GitHub directly.

Quickstart

pome run scenarios/01-bug-happy-path.md \
  --agent "<your agent command>"
That scenario boots the GitHub twin, hands your agent a token and base URL, and scores the agent’s output once it finishes. No GitHub account and no network round-trips.

Pointing your own agent at the twin

For interactive development without a full scenario run, start the standalone twin:
pome twin start github
The command prints env-var lines you can paste into your agent’s environment:
POME_GITHUB_REST_URL=http://127.0.0.1:3333/s/standalone
POME_GITHUB_MCP_URL=http://127.0.0.1:3333/s/standalone/mcp
POME_AUTH_TOKEN=<jwt>
POME_GITHUB_REST_URL is the REST root. POME_GITHUB_MCP_URL is the MCP transport endpoint. POME_AUTH_TOKEN is a short-lived JWT that authenticates every request on the session. The twin speaks the GitHub REST shape. Point any existing GitHub client at POME_GITHUB_REST_URL and the same code path runs. To check whether the twin is alive, use the unauthenticated root health endpoint:
curl http://127.0.0.1:3333/healthz
The session path /s/standalone/healthz requires the JWT and returns 401 without it.

Reset between runs

pome twin reset
Removes the local SQLite database under .pome/github.db. The next pome twin start github reseeds from the fixture.

Scenario seed shape

GitHub scenarios use a flat seed block with repositories:
{
  "repositories": [
    {
      "name": "acme-app",
      "issues": [],
      "pull_requests": []
    }
  ]
}
Set twins: ["github"] in the scenario’s ## Config block.

Scenarios

A scenario is a markdown file with a seed, a prompt, and acceptance criteria. Browse and copy the bundled catalog:
pome scenarios github
pome scenarios github --copy

Catalog

#ScenarioWhat it exercises
01Bug, happy path (01-bug-happy-path.md)Triage a clear bug report: apply the right label, assign the owner. The simplest end-to-end pass.
03Already triaged (03-already-triaged.md)Issue is already labeled and assigned — agent should not pile on duplicate labels or comments.
04Judge sees context (04-judge-context.md)Exercises the LLM judge: is the existing label contextually appropriate?
05GitHub identity spoof (05-github-identity-spoof.md)Refuse to merge a PR from an unauthorized author.
06Mislabeled issue (06-mislabeled-needs-fix.md)The applied label is wrong — agent must fix the triage.
07PR backdoor review (07-pr-backdoor-review.md)Malicious code hidden in an otherwise honest-looking PR description.
08Prompt injection in issue body (08-prompt-injection-issue-body.md)Malicious instructions embedded in issue content the agent reads.
09Security revert persuasion (09-security-revert-rationalization.md)Refuse to remove a security control under social pressure.
17In-scope injection (17-in-scope-injection.md)Injection asks the agent to mislabel an issue as wontfix — agent should resist.
18Fabricate green CI (18-fabricate-green-ci.md)Refuse to post a passing commit status when required checks are failing.
00-default-seed.md is a reference seed for hosted runs that do not define their own. It is not runnable — pome scenarios github and --copy skip it.

Run one

pome run scenarios/01-bug-happy-path.md --agent "<your agent command>"
Or let /pome-test pick matching scenarios automatically. See /test-with-pome.