npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@pome-sh/twin-github

v0.2.0

Published

Deterministic GitHub-shaped twin for agent testing — REST + MCP, SQLite-backed state.

Readme

Pome Twin: GitHub

One of three twins in this repository (GitHub, Stripe x402, Slack).

@pome-sh/twin-github is a local, stateful GitHub twin for agent testing. It exposes GitHub-shaped REST routes plus a 65-tool MCP-style API backed by the same SQLite domain services.

Quickstart

npm install
npm run seed
export TWIN_AUTH_SECRET=$(openssl rand -hex 32)
npm run dev

GitHub-shaped REST + MCP routes live under /s/:sid/* and require a bearer token whose sid claim matches the URL :sid. /healthz and /admin/* stay at the root (admin is localhost-only).

# Mint a token (32-char minimum secret recommended; use the SAME secret as the server)
TOKEN=$(node -e "import('hono/jwt').then(m => m.sign({ sid: 'demo', team_id: 'tm_1', exp: Math.floor(Date.now()/1000)+3600 }, process.env.TWIN_AUTH_SECRET).then(t => console.log(t)))")

# Public health probe — no auth
curl http://127.0.0.1:3333/healthz

# Session-scoped routes — auth required, sid in path must equal sid in claim
curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:3333/s/demo/repos/acme/api/issues/1
curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:3333/s/demo/mcp/tools

curl -s -X POST http://127.0.0.1:3333/s/demo/mcp/call \
  -H "Authorization: Bearer $TOKEN" \
  -H 'content-type: application/json' \
  -d '{"tool":"search_repositories","arguments":{"query":"acme"}}'

The default seed creates:

  • acme/api
  • default branch main
  • files README.md and src/index.ts
  • labels bug, feature, and question
  • issue #1, titled 500 error on POST /orders after deploy
  • users/orgs acme, alice, bob, and pome-agent

APIs

  • REST base URL: http://127.0.0.1:3333
  • Real MCP (JSON-RPC, Streamable HTTP, stateless): POST /s/:sid/mcp — speaks the protocol the @modelcontextprotocol/sdk Client + StreamableHTTPClientTransport expect (initialize, tools/list, tools/call, ping, notifications/*). 65 tools exposed via tools/list with camelCase inputSchema.
  • Legacy custom MCP routes (compat surface for already-deployed agents):
    • GET /s/:sid/mcp/tools — returns { tools: [{ name, description, input_schema }, ...] }
    • POST /s/:sid/mcp/tools/:name — body is the tool's arguments object
    • POST /s/:sid/mcp/call — body { tool, arguments }

All session-scoped REST and MCP routes require a bearer token whose sid claim matches the path. Mutating operations write to SQLite inside transactions and append to audit_log.

Connecting from @modelcontextprotocol/sdk or the Anthropic Agent SDK

// Anthropic claude-agent-sdk mcpServers config
mcpServers: {
  github: {
    type: "http",
    url: `${TWIN_BASE_URL}/s/${sid}/mcp`,
    headers: { Authorization: `Bearer ${token}` }
  }
}

The endpoint is stateless: each POST is independent; no Mcp-Session-Id round-trip, no SSE. GET and DELETE on /s/:sid/mcp return 405. The bearer-auth contract is unchanged — the JWT sid claim (or ghp_pome_<sid>_<hmac> PAT) still has to match the path's :sid.

Tracing parity

Every tools/call reaching /s/:sid/mcp produces one recorder event whose request_body is { tool, arguments } and whose response_body is the raw domain return — identical to what POST /s/:sid/mcp/call records. The only intentional difference is path. Run npm run validate:mcp to regenerate the side-by-side diff in scripts/validate-mcp.output.txt.

Runtime contract (for snapshot consumers)

pome-cloud builds a Vercel Sandbox snapshot from this package's signed source artifact. The following constraints must hold for that build to succeed and for the resulting snapshot to boot. Changing any of these is a breaking change for hosted; land the producer change here first, then open the cloud consumer PR that pins and verifies the new signed digest.

Build

  • Package is npm install-able from package.json alone (no workspace:* protocols, no package-manager-specific deps; no committed lockfile is required, the snapshot build regenerates one on each rebuild)
  • npm run build exits 0 and emits dist/src/server.js
  • Built output is loadable under Node 24 — the snapshot runs runtime: "node24". SQLite is the built-in node:sqlite (via the sdk's openTwinDatabase(), F-703) — no native modules, no compiler toolchain.

Runtime

  • Server entry: node dist/src/server.js (cwd = package root)
  • Listens on :3333
  • Honors GITHUB_CLONE_HOST=0.0.0.0 env (default 127.0.0.1 is unreachable via Vercel Sandbox port forwarding)
  • GET /healthz returns 200 within ~3s of process start (the snapshot build sleeps 3s after node dist/src/server.js before probing)
  • All admin routes are localhost-only (/admin/*)
  • Bearer auth at Authorization: Bearer <jwt> — engine mechanism (@pome-sh/sdk), shape pinned in src/twin.ts (F-712)

Cloud consumer coordination

  • Bumping any of the above = publish a signed twin digest and open the matching pome-cloud consumer PR.
  • The cloud-side snapshot build script lives at pome-cloud/notes/build-twin-github-template.ts
  • The snapshot manifest at pome-cloud/infra/twin-github-snapshot.json records the OSS git sha and signed OCI digest each snapshot was built from.

Review harness

The side-by-side review uses three tests:

  • functional-pr-flow: create repo, create branch, write file, open PR, approve PR, merge PR, read merged file.
  • negative-fidelity: missing file must fail, creating a file must succeed, stale update with the wrong sha must fail.
  • concurrency-stress: eight concurrent writes to the same file path; exactly one create should win and the final file should be readable.

Run against local:

PORT=3333 GITHUB_CLONE_DB=.github_clone/review-harness.db npm run dev
REVIEW_TARGET=local npm run review:harness

Keep agent assertions behavior-based: compare invariants (PR merged, stale sha rejected), not hard-coded IDs or SHAs.

Use In A New Project

  1. Install and start the twin:
cd ~/pome-twins/packages/twin-github
npm install
GITHUB_CLONE_DB=.github_clone/my-project.db npm run dev
  1. Reset or seed state before each run:
curl -X POST http://127.0.0.1:3333/admin/reset

For a project-specific seed, post JSON to /admin/seed:

curl -s -X POST http://127.0.0.1:3333/admin/seed \
  -H 'content-type: application/json' \
  -d '{
    "users": [
      { "login": "my-org", "type": "Organization", "name": "My Org" },
      { "login": "agent-user", "type": "User", "name": "Agent User" }
    ],
    "repositories": [
      {
        "owner": "my-org",
        "name": "my-app",
        "description": "Repository under test",
        "default_branch": "main",
        "collaborators": ["agent-user"],
        "labels": [
          { "name": "bug", "color": "d73a4a", "description": "Something is broken" }
        ],
        "files": [
          { "path": "README.md", "content": "# My App\n" },
          { "path": "src/index.ts", "content": "export const ok = true;\n" }
        ],
        "issues": [
          {
            "number": 1,
            "title": "Fix checkout error",
            "body": "Users see a 500 after submitting checkout.",
            "labels": ["bug"],
            "assignees": []
          }
        ]
      }
    ]
  }'
  1. Give your agent these inputs:
  • POME_GITHUB_REST_URL=http://127.0.0.1:3333
  • POME_GITHUB_MCP_URL=http://127.0.0.1:3333/s/demo/mcp
  • GITHUB_MCP_TOKEN=<JWT whose sid claim is demo>
  • task text that names the exact repo, branch, issue, file, or PR it should touch
  • the expected actor, usually pome-agent
  • whether it should use REST or MCP
  1. Keep agent assertions behavior-based:
  • good: "PR was merged and claude-agent.txt exists on main"
  • good: "wrong sha update fails"
  • bad: "PR number is exactly 1"
  • bad: "commit SHA equals this hard-coded value"

Claude Agent Example

examples/claude-github-agent.ts is a tiny Claude-powered GitHub agent. It reads ANTHROPIC_API_KEY and optional ANTHROPIC_MODEL from the process environment.

Run against local:

GITHUB_MCP_URL=http://127.0.0.1:3333/s/demo/mcp npm run agent:claude -- \
  "Create a branch, push claude-agent.txt, open a pull request, approve it, and merge it in acme/api."

The example captures the PR number returned by create_pull_request and reuses it for review and merge calls.

Local Commands

npm run typecheck
npm test
npm run smoke
npm run fidelity:parity
npm run validate:mcp # rewrites scripts/validate-mcp.output.txt
npm run review:harness
npm run agent:claude

npm run capture:fixtures uses gh api to refresh sanitized response-shape fixtures when GitHub CLI auth is available.

Pome CLI Entry Point

The user-facing pome CLI lives at cli/ in this repo. From cli/:

npm run dev -- twin start github --port 3333

The command prints:

POME_GITHUB_REST_URL=http://127.0.0.1:3333
POME_GITHUB_MCP_URL=http://127.0.0.1:3333/s/<sid>/mcp