Skip to main content

github

Emulated GitHub REST API for local development and testing. Use when the user needs to interact with GitHub API endpoints locally, test GitHub integrations, emulate repos/issues/PRs, set up GitHub OAuth flows, configure GitHub Apps, test webhooks, or work with actions/checks without hitting the real GitHub API. Triggers include "GitHub API", "emulate GitHub", "mock GitHub", "test GitHub OAuth", "GitHub App JWT", "local GitHub", or any task requiring a local GitHub API.

Quellinformationen

Repository
vercel-labs/emulate
Letzte Quellaktivität
14. Oktober 2026 um 16:00
Erkannte Sprache von SKILL.md
Englisch
Sterne
1.893
Forks
138

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
github
description
Emulated GitHub REST API for local development and testing. Use when the user needs to interact with GitHub API endpoints locally, test GitHub integrations, emulate repos/issues/PRs, set up GitHub OAuth flows, configure GitHub Apps, test webhooks, or work with actions/checks without hitting the real GitHub API. Triggers include "GitHub API", "emulate GitHub", "mock GitHub", "test GitHub OAuth", "GitHub App JWT", "local GitHub", or any task requiring a local GitHub API.
allowed-tools
Bash(npx emulate:*), Bash(curl:*)
# GitHub API Emulator Fully stateful GitHub REST API emulation. Creates, updates, and deletes persist in memory and affect related entities. ## Start Local listeners bind to `127.0.0.1` by default. For access from containers or other machines, pass `--host 0.0.0.0` to the CLI or `hostname: '0.0.0.0'` to `createEmulator`. Configure `--base-url` or `baseUrl` for advertised URLs reachable by those clients. ```bash # GitHub only npx emulate --service github # Default port # http://localhost:4001 ``` Or programmatically: ```typescript import { createEmulator } from 'emulate' const github = await createEmulator({ service: 'github', port: 4001 }) // github.url === 'http://localhost:4001' ``` For a programmatic GitHub App, omit `private_key` and read the generated RSA key from the instance: ```typescript const github = await createEmulator({ service: 'github', port: 4001, seed: { github: { users: [{ login: 'octocat' }], apps: [{ app_id: 12345, slug: 'my-github-app', name: 'My GitHub App', installations: [{ installation_id: 100, account: 'octocat' }], }], }, }, }) const privateKey = github.generatedSecrets.find( secret => secret.kind === 'github.app_private_key' && secret.id === '12345', )?.value ``` The key remains stable across `github.reset()`. Explicit keys are not included in `generatedSecrets`. The Next.js and Nuxt adapters also generate omitted keys. Retain the returned handler and call its server-only `generatedSecrets()` method. With persistence configured, the identity survives cold starts. Keep snapshots private because they contain the signing key, and require custom persistence backends to implement atomic `initialize()` semantics. For the CLI, omit `private_key` only when requesting a private delivery file: ```bash npx emulate start --service github --seed emulate.config.yaml \ --generated-secrets-file .emulate-secrets.json ``` The destination must not exist. emulate removes inherited ACLs, verifies effective owner-only access, and publishes complete JSON before any listener or portless alias starts. Handled startup failures remove the invocation-owned artifact. A hard termination can leave a complete artifact that must be removed manually after confirming no invocation is using it. Read `generatedSecrets` from the artifact, then keep the file out of source control. Linux requires `setfacl` and `getfacl` from the `acl` package. The flag fails closed when access controls cannot be verified and is not supported on Windows. Without `--generated-secrets-file`, CLI seed files still require `private_key`. ## Auth Pass tokens as `Authorization: Bearer <token>` or `Authorization: token <token>`. ```bash curl http://localhost:4001/user \ -H "Authorization: Bearer test_token_admin" ``` Public repo endpoints work without auth. Private repos and write operations require a valid token. When no token is provided, requests fall back to the first seeded user. Installation access tokens act as the configured GitHub App bot for repository writes. Repository ownership, selected repository access, and requested App permissions remain enforced. Pull request merges require `contents: write` on the base repository. Pull request branch updates require `pull_requests: write` on the pull request repository and `contents: write` on the head repository. ### GitHub App JWT Configure apps in the seed config with an explicit, valid private key when using the CLI without generated secrets. Sign a JWT with `{ iss: "<app_id>" }` using RS256. The emulator verifies the signature and resolves the app. ```yaml github: apps: - app_id: 12345 slug: my-github-app name: My GitHub App permissions: contents: read issues: write events: [push, pull_request] webhook_url: http://localhost:8080/github/webhook webhook_secret: my-webhook-secret description: My CI/CD bot installations: - installation_id: 100 account: my-org repository_selection: all permissions: contents: read events: [push] repositories: [my-org/org-repo] ``` This example intentionally omits `private_key` for programmatic and adapter usage, where the emulator generates an RSA key and exposes it through `generatedSecrets`. For CLI usage, request a private delivery file with `--generated-secrets-file <path>` or provide your own valid key. Without that flag, CLI seed files require `private_key`; do not use a placeholder PEM. ## Pointing Your App at the Emulator ### Environment Variable ```bash GITHUB_EMULATOR_URL=http://localhost:4001 ``` ### Octokit ```typescript import { Octokit } from '@octokit/rest' const octokit = new Octokit({ baseUrl: process.env.GITHUB_EMULATOR_URL ?? 'https://api.github.com', auth: 'test_token_admin', }) ``` ### OAuth URL Mapping | Real GitHub URL | Emulator URL | |-----------------|-------------| | `https://github.com/login/oauth/authorize` | `$GITHUB_EMULATOR_URL/login/oauth/authorize` | | `https://github.com/login/oauth/access_token` | `$GITHUB_EMULATOR_URL/login/oauth/access_token` | | `https://api.github.com/user` | `$GITHUB_EMULATOR_URL/user` | ### Auth.js / NextAuth.js ```typescript import GitHub from '@auth/core/providers/github' GitHub({ clientId: process.env.GITHUB_CLIENT_ID, clientSecret: process.env.GITHUB_CLIENT_SECRET, authorization: { url: `${process.env.GITHUB_EMULATOR_URL}/login/oauth/authorize`, }, token: { url: `${process.env.GITHUB_EMULATOR_URL}/login/oauth/access_token`, }, userinfo: { url: `${process.env.GITHUB_EMULATOR_URL}/user`, }, }) ``` ## Seed Config ```yaml tokens: test_token_admin: login: admin scopes: [repo, user, admin:org, admin:repo_hook] github: users: - login: octocat name: The Octocat email: octocat@github.com bio: I am the Octocat company: GitHub location: San Francisco blog: https://github.blog twitter_username: github site_admin: false orgs: - login: my-org name: My Organization description: A test organization email: org@example.com members: - login: octocat role: admin repos: - owner: octocat name: hello-world description: My first repository language: JavaScript topics: [hello, world] default_branch: main private: false - owner: my-org name: org-repo description: An organization repository language: TypeScript oauth_apps: - client_id: Iv1.abc123 client_secret: secret_abc123 name: My Web App redirect_uris: - http://localhost:3000/api/auth/callback/github ``` Organization `members` are optional. Each entry references a seeded user by `login`; `role` defaults to `member`, and `admin` maps to the organization administrator role. Unknown users are ignored. Seeded memberships use the synthetic `members` team and grant private organization repository access. Repos are auto-initialized with a commit, branch, and README unless `auto_init: false` is set. ## Pagination All list endpoints support `page` and `per_page` query params with `Link` headers: ```bash curl "http://localhost:4001/repos/octocat/hello-world/issues?page=1&per_page=10" \ -H "Authorization: Bearer $TOKEN" ``` ## API Endpoints ### Users ```bash # Authenticated user curl http://localhost:4001/user -H "Authorization: Bearer $TOKEN" # Update profile curl -X PATCH http://localhost:4001/user \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"bio": "Hello!"}' # Get user by username curl http://localhost:4001/users/octocat # List users curl http://localhost:4001/users # User repos / orgs / followers / following curl http://localhost:4001/users/octocat/repos curl http://localhost:4001/users/octocat/orgs curl http://localhost:4001/users/octocat/followers curl http://localhost:4001/users/octocat/following # User hovercard curl http://localhost:4001/users/octocat/hovercard # User emails curl http://localhost:4001/user/emails -H "Authorization: Bearer $TOKEN" ``` ### Repositories ```bash # Get repo curl http://localhost:4001/repos/octocat/hello-world # Get repo by numeric ID curl http://localhost:4001/repositories/1 # Create user repo curl -X POST http://localhost:4001/user/repos \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"name": "new-repo", "private": false}' # Create org repo curl -X POST http://localhost:4001/orgs/my-org/repos \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"name": "org-project"}' # Update repo curl -X PATCH http://localhost:4001/repos/octocat/hello-world \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"description": "Updated description"}' # Delete repo (cascades issues, PRs, etc.) curl -X DELETE http://localhost:4001/repos/octocat/hello-world \ -H "Authorization: Bearer $TOKEN" # Topics, languages, contributors, forks, collaborators, tags, transfer ``` ### Contents & Commit History ```bash # Read a file or list a directory at a branch, tag, or commit curl "http://localhost:4001/repos/octocat/hello-world/contents/README.md?ref=main" # Request raw bytes from a file Contents or README response with GitHub's raw media type curl "http://localhost:4001/repos/octocat/hello-world/contents/README.md?ref=main" \ -H "Accept: application/vnd.github.raw+json" # Download raw file content from the URL advertised by contents and commit responses curl http://localhost:4001/octocat/hello-world/raw/main/README.md # Create or update a file and commit the change curl -X PUT http://localhost:4001/repos/octocat/hello-world/contents/notes.txt \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"message": "Update notes", "content": "aGVsbG8K"}' # List commits, get a commit with file stats, or compare refs curl http://localhost:4001/repos/octocat/hello-world/commits curl http://localhost:4001/repos/octocat/hello-world/commits/main curl http://localhost:4001/repos/octocat/hello-world/compare/v1.0.0...main ``` ### Issues ```bash # List issues (filter by state, labels, assignee, milestone, creator, since) curl "http://localhost:4001/repos/octocat/hello-world/issues?state=open&labels=bug" # Create issue curl -X POST http://localhost:4001/repos/octocat/hello-world/issues \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"title": "Bug report", "body": "Details here", "labels": ["bug"]}' # Get / update / lock / unlock / timeline / events / assignees ``` ### Pull Requests ```bash # List PRs curl "http://localhost:4001/repos/octocat/hello-world/pulls?state=open" # Create PR curl -X POST http://localhost:4001/repos/octocat/hello-world/pulls \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"title": "Feature", "head": "feature-branch", "base": "main"}' # Merge PR (enforces branch protection) curl -X PUT http://localhost:4001/repos/octocat/hello-world/pulls/1/merge \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"merge_method": "squash"}' # Commits, files, requested reviewers, update branch ``` ### Comments ```bash # Issue comments: full CRUD curl http://localhost:4001/repos/octocat/hello-world/issues/1/comments curl -X POST http://localhost:4001/repos/octocat/hello-world/issues/1/comments \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"body": "Looks good!"}' # Comment by ID (cross-resource) curl http://localhost:4001/repos/octocat/hello-world/issues/comments/1 # PR review comments curl http://localhost:4001/repos/octocat/hello-world/pulls/1/comments # Commit comments curl http://localhost:4001/repos/octocat/hello-world/commits/abc123/comments # Repo-wide comment listings curl http://localhost:4001/repos/octocat/hello-world/issues/comments curl http://localhost:4001/repos/octocat/hello-world/pulls/comments curl http://localhost:4001/repos/octocat/hello-world/comments ``` ### Reviews ```bash # List / create / get / update / submit / dismiss reviews curl http://localhost:4001/repos/octocat/hello-world/pulls/1/reviews curl -X POST http://localhost:4001/repos/octocat/hello-world/pulls/1/reviews \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen