Skip to content

Command Reference

Complete command reference for the webhooks.cc CLI, including authentication, endpoint management, tunneling, replay, the agent sandbox, and updates.

Updated Nov 2026

All available commands for the whk CLI.

Run whk with no arguments to launch the interactive TUI, or use the subcommands below for scriptable, plain-text output.

whk (interactive)

Launch the interactive TUI. Provides a menu-driven interface for all CLI features with real-time request streaming, color-coded methods, and a request detail viewer.

whk
FlagDescription
--noguiDisable the TUI and print help instead (also: WHK_NOGUI=1)

Global flags

These work with every subcommand.

FlagDescription
--jsonPrint JSON instead of plain text, where the command supports it
--api-urlUse another API base URL (also: WHK_API_URL)
--webhook-urlUse another webhook receiver URL (also: WHK_WEBHOOK_URL)
--no-colorDisable colored output

auth login

Log in to webhooks.cc. Opens your browser to verify a device code. Credentials are stored at ~/.config/whk/token.json.

whk auth login

auth logout

Remove stored credentials from your machine.

whk auth logout

auth status

Show current authentication status and email. When you are not logged in but an agent's account connection is saved (see sandbox connect), it says the CLI acts through that connection; with --json the answer carries "via": "agent" instead of "via": "login".

whk auth status

create

Create a new endpoint. An optional name can be provided; the slug is auto-generated. It prints the endpoint's webhook URL and its email address ({slug}@mailhooks.cc, see Email Capture).

whk create [name]
FlagDescription
--ephemeral, -eCreate the endpoint as ephemeral (it expires)
--expires-inExpiry duration (e.g., 12h, 7d)
--mock-statusMock response status code (100-599)
--mock-bodyMock response body; placeholders such as {{ json.id }} are filled in per request
--mock-headerMock response header (repeatable, format: Key:Value)
--signing-providerProvider for automatic signature verification (e.g., stripe, github)
--signing-secretSigning secret (encrypted server-side, never stored locally; also: WHK_SIGNING_SECRET)
whk create my-stripe --signing-provider stripe --signing-secret whsec_...

list

List your endpoints and those shared with you through teams, with slug, name, team, and URL. Your favourites come first, marked with a star; the rest follow in slug order. With --json the answer is the API's { "owned": [...], "shared": [...] }, each endpoint carrying favorite.

whk list
whk list --team Payments
FlagDescription
--teamOnly endpoints tied to this team (id or name): shared with you from it, or yours that are shared with it

get

Show an endpoint's details: webhook URL, email address, name, mock response, and whether it is one of your favourites.

whk get <slug>

update-endpoint

Change an endpoint's name or mock response.

whk update-endpoint <slug> --mock-status 202 --mock-body '{"ok":true}'
FlagDescription
--nameNew display name
--mock-statusMock response status code
--mock-bodyMock response body (placeholders are filled in)
--mock-headerMock response header (repeatable, format: Key:Value)
--clear-mockRemove the mock response

favorite

Mark an endpoint as a favourite, or remove it again with unfavorite. Favourites come first in whk list, in the interactive TUI's endpoint lists, and in the dashboard's endpoint switcher. A favourite is yours alone: you can favourite an endpoint shared with you through a team without changing it for anyone else. Both commands are idempotent, and favourite and unfavourite work as aliases. They need an account, not an agent sandbox.

whk favorite <slug>
whk unfavorite <slug>

With --json they print { "slug": "<slug>", "favorite": true } (or false).

delete

Delete an endpoint. Prompts for confirmation unless --force is set.

whk delete <slug>
FlagDescription
--force, -fSkip the confirmation prompt

tunnel

Forward webhooks to a local port, optionally with a path (whk tunnel 8080/api/webhooks). Creates a new endpoint unless --endpoint is set. Captured emails are posted too, as webhooks.cc's email JSON or in a mail provider's shape (emails).

whk tunnel <port>
FlagDescription
--endpointUse an existing endpoint instead of creating one
--ephemeral, -eDelete the endpoint when the tunnel exits
--header, -HAdd a custom header to forwarded requests and emails (repeatable, format: Key:Value)
--email-formatShape to post emails in: json (default, webhooks.cc's email JSON), postmark, sendgrid, mailgun or cloudmailin
--email-pathPath to post emails to, appended to the target like a webhook's path (default: the target itself)
--mailgun-signing-keyYour Mailgun HTTP webhook signing key, to sign the form with --email-format mailgun (also: WHK_MAILGUN_SIGNING_KEY)
--no-emailSkip captured emails instead of posting them

When signature verification is configured on the endpoint, tunnel injects verification headers into forwarded requests:

  • X-Signature-Verified: true or false
  • X-Signature-Provider: stripe (the provider name)
  • X-Signature-Error: ... (when verification fails)

Your local server can use these headers to skip its own verification during development.

Warning: These headers are injected by the local tunnel client and are not authenticated. Never trust them in production: any HTTP client can send arbitrary X-Signature-* headers. Always perform your own signature verification in production environments.

listen

Stream incoming requests for an endpoint to the terminal without forwarding them.

whk listen <slug>

When signature verification is configured, listen shows verification status inline:

14:32:01 POST /webhook ✓ stripe  423 B
14:32:05 POST /webhook ✗ stripe  423 B

requests

List, read, search, count, clear, and export captured requests. Run whk requests <command> --help for each command's flags.

whk requests list <slug>          # newest first, --limit (default 25), --since, --cursor
whk requests get <request-id>
whk requests search -q invoice --slug <slug> --from 1h   # across retained requests: --method, --to, --limit, --offset, --order
whk requests count --slug <slug> --method POST           # same filters as search
whk requests clear <slug>         # --before <time or duration>, --force to skip the prompt
whk requests export <slug> --format har -o requests.har  # or --format curl; --limit (default 100), --since

Captured emails are listed with an EMAIL method, the address they arrived at, and their subject:

2026-10-08 16:47:20 EMAIL acme+run-7@mailhooks.cc Confirm your email 1.2 KB

whk requests get on an email shows the sender, recipient, subject, tag, attachments, and text part instead of the raw message. Add --json for the headers and the raw message; the HTML and the sender checks are in the dashboard.

On an endpoint with layouts, it also shows what they found under Parsed: the layout, each field as name: value, the line items as a table in their columns' order (the first 50), and one line per parsed attachment. The TUI's request view shows the same, and --json returns the request's parsed as stored: a very large result is cut to fit the email's JSON (attachment rows and text first, then line items from the end), and parsed.truncated says so.

replay

Replay a captured request to a target URL. Emails cannot be replayed as HTTP requests; to send them to your server, use forwarding.

whk replay <request-id>
FlagDescription
--toTarget URL for replay (default: http://localhost:8080)

send

Send a test webhook to one of your endpoints. The body can be a string or @file.

whk send <slug> -d '{"event":"test"}' -H "Content-Type: application/json"
FlagDescription
--methodHTTP method (default: POST)
--header, -HRequest header (repeatable, format: Key:Value)
--data, -dRequest body, a string or @file (up to 10 MB)

send-to

Send a webhook from your machine to any URL, with the same flags as send.

whk send-to http://localhost:3000/webhooks -d @payload.json

teams

Manage teams: sharing, members, and invites. Wherever a command takes <team>, pass a team id or a team name (case-insensitive). A name that matches several teams is rejected; pass the id instead.

whk teams list                              # your teams: role, seats, members, pooled usage, status
whk teams members <team>                    # members and pending invites
whk teams share <slug> --team <team>        # share an endpoint you own (needs an active team)
whk teams unshare <slug> --team <team>
whk teams invite <team> <email>             # sends an invite email; accepting claims a seat
whk teams invites                           # invites waiting for you
whk teams accept <invite-id>
whk teams decline <invite-id>

Sharing moves the endpoint's requests onto the team's pooled quota. Only the endpoint owner can share or unshare, and only the team owner can invite. Every subcommand supports --json.

usage

Show your plan's request usage and, below it, the pooled quota of every subscribed team you belong to. With --json the team pools are returned in a teams array.

whk usage

sandbox

Webhook capture for AI agents and scripts without an account, and the claim that connects an agent to a human's account (auth.md). Every subcommand runs without prompts and supports --json; progress messages go to stderr and are left out with --json. Errors carry the server's code (sandbox_full, sandbox_endpoint_limit, rate_limited with its Retry-After, invalid_grant, ...) and exit with a non-zero status.

whk sandbox create --json                   # a capture endpoint: slug, url, limits
whk sandbox list                            # endpoints and the remaining budget
whk sandbox get <slug>
whk sandbox delete <slug>                   # frees a slot; the budget is not refunded
whk sandbox requests <slug>                 # newest first, --limit (1-100), --since <ms>
whk sandbox request <request-id>
whk sandbox wait <slug> --timeout 60s       # poll until a request arrives, then print it
whk sandbox status                          # what the credential file holds (never tokens)
whk sandbox connect --email you@example.com # connect the agent to your account
whk sandbox forget --sandbox                # or --claimed, or --all

The first whk sandbox create registers anonymously, which takes a short proof of work (a second or two of CPU). Later commands, and later processes, reuse that registration until it expires. A sandbox holds up to 3 endpoints at a time, 25 captures per endpoint and 100 in all; everything is deleted after 24 hours. Sandbox endpoints answer every capture with a plain 200: no mock responses, forwarding, signature checks or email.

whk sandbox wait counts requests from the last 5 minutes unless --since gives a timestamp in milliseconds. --count <n> (up to 25, what one endpoint can capture) waits for several and prints them as a list.

Connecting an agent to an account

whk sandbox connect --email you@example.com --json
{"status":"pending","registration_id":"...","verification_uri":"https://webhooks.cc/agent/claim?attempt=...","user_code":"123456","expires_at":"2026-10-28T12:15:00.000Z","email":"you@example.com"}
{"status":"claimed","registration_id":"...","email":"you@example.com","scope":"webhooks:read webhooks:write","assertion_expires":"2027-01-26T12:00:00.000Z","client_name":"whk-cli","saved_at":"2026-10-28T12:01:10.000Z"}

The first line is printed at once: hand the link and the 6-digit code to the human, who signs in (or signs up) with that email address and enters the code. The command keeps polling and prints a second line when the human approves (claimed), declines (declined), or the code runs out (expired, after 15 minutes, or timeout when --timeout is shorter); anything but claimed exits with a non-zero status. When a connection is already saved, it prints already_connected and exits without registering again; run whk sandbox forget --claimed first to connect another account.

Once connected, the regular commands (whk list, whk create, whk requests, whk listen, whk tunnel, ...) act for that account whenever no whk auth login session exists; a login always wins. The connection lasts 90 days. When the human disconnects the agent under Account, Connected agents, the next command answers invalid_grant and the connection is removed from the credential file. The sandbox endpoints of an earlier whk sandbox create stay in the sandbox until they expire.

The credential file

Registrations are saved in a file the CLI shares with the MCP server and the SDKs, so a connection the human approved once works from every tool and survives restarts:

PlatformPath
Linux$XDG_CONFIG_HOME/whk/agent.json, else ~/.config/whk/agent.json
macOS~/Library/Application Support/whk/agent.json
Windows%APPDATA%\whk\agent.json

Set WHK_AGENT_FILE to use another path, for example one per CI job. The file is written with mode 0600 and holds identity assertions and short-lived access tokens, so treat it like token.json. Entries are kept per API URL (--api-url, WHK_API_URL), so a local stack never touches production's. whk sandbox status shows what is saved without printing any secret.

update

Update whk to the latest version.

whk update

completions

Print a shell completion script (bash, zsh, fish, elvish or powershell).

whk completions zsh > ~/.zfunc/_whk

--version

Print the CLI version.

whk --version