vercel-labs-skills
The CLI for the open agent skills ecosystem. Supports OpenCode, Claude Code, Codex, Cursor, and 75 more.
Local drop-in replacement services for CI and no-network sandboxes. Fully stateful, production-fidelity API emulation. Not mocks.
$ npx -y skills add vercel-labs/emulate --agent claude-code
What's inside
Local drop-in replacement services for CI and no-network sandboxes. Fully stateful, production-fidelity API emulation. Not mocks.
npx emulate
All services start with sensible defaults. No config file needed:
http://localhost:4000http://localhost:4001http://localhost:4002http://localhost:4003http://localhost:4004http://localhost:4005http://localhost:4006http://localhost:4007http://localhost:4008http://localhost:4009http://localhost:4010http://localhost:4011http://localhost:4012http://localhost:4013Stripe webhooks configured with a secret include a Stripe-Signature header signed over the timestamp and raw request body.
Resend POST /emails and POST /emails/batch support 24-hour Idempotency-Key replay, returning the original email IDs without duplicate emails or webhooks.
# Start all services (zero-config)
npx emulate
# Start specific services
npx emulate --service vercel,github
# Custom port
npx emulate --port 3000
# Use a seed config file
npx emulate --seed config.yaml
# Generate omitted service secrets into a private file
npx emulate start --seed config.yaml --generated-secrets-file .emulate-secrets.json
# Generate a starter config
npx emulate init
# Generate config for a specific service
npx emulate init --service vercel
# List available services
npx emulate list
| Flag | Default | Description |
|---|---|---|
-p, --port | 4000 | Base port (auto-increments per service) |
-s, --service | all | Comma-separated services to enable |
--seed | auto-detect | Path to seed config (YAML or JSON) |
--base-url | none | Override advertised base URL (supports {service} template) |
--portless | off | Serve over HTTPS via portless (auto-registers aliases) |
--generated-secrets-file | none | Generate omitted service secrets and write them to a new owner-only JSON file |
The port can also be set via EMULATE_PORT or PORT environment variables.
portless gives emulators trusted HTTPS URLs with auto-generated certs and no browser warnings.
# Start the portless proxy (first time only)
portless proxy start
# Start emulate with portless integration
npx emulate start --portless
Each service registers as a portless alias and gets a named HTTPS URL:
github https://github.emulate.localhost
google https://google.emulate.localhost
slack https://slack.emulate.localhost
If portless is not installed, emulate will prompt to install it (npm i -g portless).
The --portless flag overwrites any existing portless aliases matching *.emulate. Aliases are removed automatically when emulate shuts down.
For a custom base URL without portless (any reverse proxy), use --base-url or the EMULATE_BASE_URL env var:
npx emulate start --base-url "https://{service}.myproxy.test"
The PORTLESS_URL env var is automatically set by the portless CLI wrapper when running a command through it (e.g. portless github.emulate emulate start), typically to a value like https://{service}.emulate.localhost. It supports {service} interpolation, just like --base-url and EMULATE_BASE_URL. When no explicit baseUrl is provided, it is used as a fallback.
Per-service overrides are also supported in the seed config (these take highest priority over all other base URL sources):
github:
baseUrl: https://github.emulate.localhost
npm install emulate
Each call to createEmulator starts a single service:
import { createEmulator } from 'emulate'
const github = await createEmulator({ service: 'github', port: 4001 })
const vercel = await createEmulator({ service: 'vercel', port: 4002 })
github.url // 'http://localhost:4001'
vercel.url // 'http://localhost:4002'
await github.close()
await vercel.close()
When a GitHub App omits private_key, createEmulator generates an RSA-2048 PKCS#1 key for that emulator instance:
const github = await createEmulator({
service: 'github',
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
Generated keys remain stable across reset() calls and appear only in generatedSecrets. Explicitly configured keys are never returned there. A new createEmulator call generates a new key.
The CLI can also generate omitted GitHub App keys when a delivery file is requested:
npx emulate start --service github --seed 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 opening listeners or configuring portless. Handled startup failures remove the invocation-owned artifact so the command can be retried immediately. A hard termination such as SIGKILL can leave a complete published artifact that must be removed manually after confirming no invocation is using it. Only generated secrets are included. Explicitly configured keys are never copied into the artifact. 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 keep requiring private_key.
// vitest.setup.ts
import { createEmulator, type Emulator } from 'emulate'
let github: Emulator
let vercel: Emulator
beforeAll(async () => {
;[github, vercel] = await Promise.all([
createEmulator({ service: 'github', port: 4001 }),
createEmulator({ service: 'vercel', port: 4002 }),
])
process.env.GITHUB_EMULATOR_URL = github.url
process.env.VERCEL_EMULATOR_URL = vercel.url
})
afterEach(() => { github.reset(); vercel.reset() })
afterAll(() => Promise.all([github.close(), vercel.close()]))
| Option | Default | Description |
|---|---|---|
service | (required) | Service name: 'vercel', 'github', 'google', 'slack', 'apple', 'microsoft', 'okta', 'aws', 'resend', 'stripe', 'mongoatlas', 'clerk', 'linear', or 'twilio' |
port | 4000 | Port for the HTTP server |
seed | none | Inline seed data (same shape as YAML config) |
baseUrl | none | Override advertised base URL. Per-service baseUrl in seed config takes highest priority, then this option, then EMULATE_BASE_URL env var (supports {service}), then PORTLESS_URL (supports {service}, automatically set by the portless CLI wrapper), then http://localhost:<port>. |
| Method | Description |
|---|---|
url | Base URL of the running server |
generatedSecrets | Readonly secrets generated while preparing seed data |
reset() | Wipe the store and replay seed data |
close() | Shut down the HTTP server, returns a Promise |
Configuration is optional. The CLI auto-detects config files in this order: emulate.config.yaml / .yml, emulate.config.json, service-emulator.config.yaml / .yml, service-emulator.config.json. Or pass --seed <file> explicitly. Run npx emulate init to generate a starter file.
The CLI for the open agent skills ecosystem. Supports OpenCode, Claude Code, Codex, Cursor, and 75 more.
Give coding agents access to any package's source code.
Comprehensive Vercel ecosystem plugin — relational knowledge graph, skills for every major product, specialized agents, and Vercel conventions. Turns any AI agent into a Vercel expert.
FAQ
emulate is a Claude Code plugin with 14 hand-picked skills for development work, indexed on Flowy. Install it with the command on its page. It includes apple, aws, emulate. Its skills do not fire on their own yet. Request auto-invocation to have Flowy route them as you prompt. Free and open source.
Is this plugin yours?
Claim it with GitHubSubmit a pluginPromote it