@better-webhook/cli 0.3.1 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,287 +5,624 @@
5
5
  [![License](https://img.shields.io/github/license/endalk200/better-webhook?style=for-the-badge)](https://opensource.org/licenses/MIT)
6
6
  [![Node.js](https://img.shields.io/node/v/@better-webhook/cli?style=for-the-badge&logo=node.js)](https://nodejs.org/)
7
7
 
8
- A powerful CLI tool for webhook development, testing, and management. Capture incoming webhooks, replay them, generate reusable templates, and manage webhook definitions locally.
8
+ A modern CLI tool for webhook development, testing, and debugging. Capture incoming webhooks, replay them against your local server, manage reusable templates, and generate provider-specific signatures automatically.
9
9
 
10
10
  ## Features
11
11
 
12
- **Webhook Management** - Store and execute webhook definitions locally
13
- 🎣 **Live Capture** - Capture incoming webhooks with a local server
14
- 🔄 **Replay** - Replay captured webhooks to any endpoint
15
- 📋 **Templates** - Generate reusable templates from captured requests
16
- 📥 **Download** - Access curated webhook templates from the community
17
- 🎯 **Override** - Override URLs, methods, and headers on the fly
12
+ - 🎣 **Capture** Start a local server to capture incoming webhooks from any provider
13
+ - 🔄 **Replay** Replay captured webhooks to any endpoint with full header preservation
14
+ - 📋 **Templates** Download and run curated webhook templates from the community
15
+ - 🔐 **Signatures** Automatic signature generation for Stripe, GitHub, Shopify, Slack, and more
16
+ - 🌐 **WebSocket** — Real-time capture notifications via WebSocket for dashboard integration
17
+ - 🎯 **Provider Detection** Automatically identifies webhook providers from headers
18
+
19
+ ## Supported Providers
20
+
21
+ | Provider | Signature Algorithm | Auto-Detection |
22
+ | ------------ | ------------------------------- | -------------- |
23
+ | Stripe | HMAC-SHA256 (`t={ts},v1={sig}`) | ✅ |
24
+ | GitHub | HMAC-SHA256 (`sha256={sig}`) | ✅ |
25
+ | Shopify | HMAC-SHA256 (Base64) | ✅ |
26
+ | Slack | HMAC-SHA256 (`v0={sig}`) | ✅ |
27
+ | Twilio | HMAC-SHA1 (Base64) | ✅ |
28
+ | SendGrid | HMAC-SHA256 (Base64) | ✅ |
29
+ | Linear | HMAC-SHA256 (Hex) | ✅ |
30
+ | Clerk (Svix) | HMAC-SHA256 (`v1,{sig}`) | ✅ |
31
+ | Discord | Ed25519 | ✅ |
32
+ | Custom | — | — |
18
33
 
19
34
  ## Installation
20
35
 
21
- ### NPM/YARN/PNPM
22
-
23
36
  ```bash
24
- # Install globally
37
+ # NPM
25
38
  npm install -g @better-webhook/cli
26
- # or use with npx
27
- npx @better-webhook/cli --help
28
39
 
29
- # With yarn
40
+ # Yarn
30
41
  yarn global add @better-webhook/cli
31
42
 
32
- # With pnpm
43
+ # PNPM
33
44
  pnpm add -g @better-webhook/cli
45
+
46
+ # Or use with npx (no installation required)
47
+ npx @better-webhook/cli --help
34
48
  ```
35
49
 
36
50
  ### Verify Installation
37
51
 
38
52
  ```bash
39
- better-webhook --help
53
+ better-webhook --version
54
+ # 2.0.0
40
55
  ```
41
56
 
42
57
  ## Quick Start
43
58
 
44
- ### 1. Manage Webhook Definitions
59
+ ### 1. Capture Webhooks
45
60
 
46
- ```bash
47
- # List available webhook definitions
48
- better-webhook webhooks list
61
+ Start a local server to capture incoming webhooks:
49
62
 
50
- # Download community templates
51
- better-webhook webhooks download stripe-invoice.payment_succeeded
52
- better-webhook webhooks download --all
63
+ ```bash
64
+ # Start capture server on default port 3001
65
+ better-webhook capture
53
66
 
54
- # Run a webhook
55
- better-webhook webhooks run stripe-invoice
56
- better-webhook webhooks run mywebhook --url https://example.com/hook --method POST
67
+ # Use a custom port
68
+ better-webhook capture --port 4000
57
69
  ```
58
70
 
59
- ### 2. Capture Live Webhooks
71
+ Point your webhook provider (Stripe, GitHub, etc.) to `http://localhost:3001` or use a tunneling service like ngrok.
60
72
 
61
- ```bash
62
- # Start capture server (default port 3001)
63
- better-webhook capture
64
- better-webhook capture --port 3000
73
+ ### 2. View & Manage Captures
65
74
 
75
+ ```bash
66
76
  # List captured webhooks
67
- better-webhook capture list
68
- better-webhook capture list --limit 20
77
+ better-webhook captures list
69
78
 
70
- # Generate template from capture
71
- better-webhook capture template abc123 my-template-name
79
+ # Show detailed information about a capture
80
+ better-webhook captures show abc123
81
+
82
+ # Search captures
83
+ better-webhook captures search "github"
84
+
85
+ # Delete a capture
86
+ better-webhook captures delete abc123
72
87
  ```
73
88
 
74
89
  ### 3. Replay Webhooks
75
90
 
91
+ Replay a captured webhook to your local development server:
92
+
76
93
  ```bash
77
- # Replay captured webhook to any endpoint
78
- better-webhook replay abc123 https://example.com/webhook
79
- better-webhook replay abc123 https://test.com/hook --method PUT
94
+ # Interactive mode (select capture and enter URL)
95
+ better-webhook replay
96
+
97
+ # Direct replay
98
+ better-webhook replay abc123 http://localhost:3000/api/webhooks/github
80
99
  ```
81
100
 
82
- ## Commands
101
+ ### 4. Use Templates
102
+
103
+ Download and run curated webhook templates:
104
+
105
+ ```bash
106
+ # List available templates
107
+ better-webhook templates list
83
108
 
84
- ### `better-webhook webhooks`
109
+ # Download a template
110
+ better-webhook templates download github-push
85
111
 
86
- Manage and execute webhook definitions stored in `.webhooks/` directory.
112
+ # Run a template against your endpoint
113
+ better-webhook run github-push --url http://localhost:3000/webhooks/github
114
+ ```
115
+
116
+ ---
87
117
 
88
- | Command | Description | Options |
89
- | -------------------------- | ---------------------------------- | ------------------- |
90
- | `webhooks list` | List available webhook definitions | - |
91
- | `webhooks run <name>` | Execute a webhook definition | `--url`, `--method` |
92
- | `webhooks download [name]` | Download community templates | `--all`, `--force` |
118
+ ## Commands Reference
93
119
 
94
120
  ### `better-webhook capture`
95
121
 
96
- Capture, list, and generate templates from live webhook requests.
122
+ Start a server to capture incoming webhooks. All captured webhooks are saved to `~/.better-webhook/captures/`.
97
123
 
98
- | Command | Description | Options |
99
- | ------------------------------ | ------------------------------ | ----------------------- |
100
- | `capture` | Start webhook capture server | `--port` |
101
- | `capture list` | List captured webhook requests | `--limit` |
102
- | `capture template <id> [name]` | Generate template from capture | `--url`, `--output-dir` |
124
+ ```bash
125
+ better-webhook capture [options]
126
+ ```
103
127
 
104
- ### `better-webhook replay`
128
+ | Option | Description | Default |
129
+ | ------------------- | ----------------- | --------- |
130
+ | `-p, --port <port>` | Port to listen on | `3001` |
131
+ | `-h, --host <host>` | Host to bind to | `0.0.0.0` |
105
132
 
106
- Replay captured webhooks to any endpoint.
133
+ **Features:**
107
134
 
108
- | Command | Description | Options |
109
- | -------------------------------- | ----------------------- | ---------------------- |
110
- | `replay <captureId> <targetUrl>` | Replay captured webhook | `--method`, `--header` |
135
+ - Automatically detects webhook provider from headers
136
+ - Saves full request including headers, body, query params
137
+ - WebSocket server for real-time notifications
138
+ - Returns capture ID in response for easy reference
111
139
 
112
- ## Webhook Definition Format
140
+ **Example:**
113
141
 
114
- Webhook definitions are JSON files that follow this schema:
142
+ ```bash
143
+ better-webhook capture --port 4000 --host localhost
144
+ ```
115
145
 
116
- ```json
117
- {
118
- "url": "https://api.example.com/webhook",
119
- "method": "POST",
120
- "headers": [
121
- { "key": "Authorization", "value": "Bearer token123" },
122
- { "key": "Content-Type", "value": "application/json" }
123
- ],
124
- "body": {
125
- "event": "user.created",
126
- "data": {
127
- "id": "12345",
128
- "email": "user@example.com"
129
- }
130
- }
131
- }
146
+ ---
147
+
148
+ ### `better-webhook captures` (alias: `c`)
149
+
150
+ Manage captured webhooks.
151
+
152
+ #### `captures list` (alias: `ls`)
153
+
154
+ List captured webhooks, sorted by most recent first.
155
+
156
+ ```bash
157
+ better-webhook captures list [options]
158
+ ```
159
+
160
+ | Option | Description | Default |
161
+ | --------------------------- | ----------------------------------------- | ------- |
162
+ | `-l, --limit <limit>` | Maximum captures to show | `20` |
163
+ | `-p, --provider <provider>` | Filter by provider (stripe, github, etc.) | — |
164
+
165
+ #### `captures show <captureId>`
166
+
167
+ Show detailed information about a specific capture.
168
+
169
+ ```bash
170
+ better-webhook captures show <captureId> [options]
171
+ ```
172
+
173
+ | Option | Description |
174
+ | ------------ | ---------------------- |
175
+ | `-b, --body` | Show full body content |
176
+
177
+ **Arguments:**
178
+
179
+ - `<captureId>` — Full or partial capture ID
180
+
181
+ #### `captures search <query>`
182
+
183
+ Search captures by ID, path, method, provider, or filename.
184
+
185
+ ```bash
186
+ better-webhook captures search <query>
187
+ ```
188
+
189
+ #### `captures delete` (alias: `rm`)
190
+
191
+ Delete a specific captured webhook.
192
+
193
+ ```bash
194
+ better-webhook captures delete <captureId> [options]
132
195
  ```
133
196
 
134
- ### Schema Fields
197
+ | Option | Description |
198
+ | ------------- | ------------------------ |
199
+ | `-f, --force` | Skip confirmation prompt |
135
200
 
136
- | Field | Type | Required | Description |
137
- | --------- | ------ | -------- | --------------------------- |
138
- | `url` | string | ✅ | Target webhook URL |
139
- | `method` | string | ❌ | HTTP method (default: POST) |
140
- | `headers` | array | ❌ | Array of header objects |
141
- | `body` | any | ❌ | Request payload |
201
+ #### `captures clean` (alias: `remove-all`)
142
202
 
143
- ## Directory Structure
203
+ Remove all captured webhooks.
144
204
 
205
+ ```bash
206
+ better-webhook captures clean [options]
145
207
  ```
146
- your-project/
147
- ├── .webhooks/ # Webhook definitions
148
- │ ├── stripe-payment.json
149
- │ ├── user-signup.json
150
- │ └── order-complete.json
151
- └── .webhook-captures/ # Captured requests (auto-created)
152
- ├── 2024-01-15T10-30-00_abc123.json
153
- └── 2024-01-15T11-00-00_def456.json
208
+
209
+ | Option | Description |
210
+ | ------------- | ------------------------ |
211
+ | `-f, --force` | Skip confirmation prompt |
212
+
213
+ ---
214
+
215
+ ### `better-webhook templates` (alias: `t`)
216
+
217
+ Manage webhook templates. Templates are fetched from the [better-webhook repository](https://github.com/endalk200/better-webhook/tree/main/templates).
218
+
219
+ #### `templates list` (alias: `ls`)
220
+
221
+ List available remote templates from the repository.
222
+
223
+ ```bash
224
+ better-webhook templates list [options]
154
225
  ```
155
226
 
156
- ## Use Cases
227
+ | Option | Description |
228
+ | --------------------------- | -------------------------------------- |
229
+ | `-p, --provider <provider>` | Filter by provider |
230
+ | `-r, --refresh` | Force refresh the template index cache |
231
+
232
+ #### `templates download` (alias: `get`)
157
233
 
158
- ### Development & Testing
234
+ Download a template to local storage (`~/.better-webhook/templates/`).
159
235
 
160
236
  ```bash
161
- # Test your webhook endpoint during development
162
- better-webhook webhooks run test-payload --url http://localhost:3000/webhook
237
+ better-webhook templates download [templateId] [options]
238
+ ```
163
239
 
164
- # Capture webhooks from external services
165
- better-webhook capture --port 4000
166
- # Point your webhook provider to http://localhost:4000
240
+ | Option | Description |
241
+ | ----------- | -------------------------------- |
242
+ | `-a, --all` | Download all available templates |
243
+
244
+ If no `templateId` is provided, shows an interactive selection menu.
245
+
246
+ #### `templates local`
247
+
248
+ List downloaded local templates.
167
249
 
168
- # Replay captured requests for debugging
169
- better-webhook replay abc123 http://localhost:3000/debug
250
+ ```bash
251
+ better-webhook templates local [options]
170
252
  ```
171
253
 
172
- ### CI/CD & Automation
254
+ | Option | Description |
255
+ | --------------------------- | ------------------ |
256
+ | `-p, --provider <provider>` | Filter by provider |
257
+
258
+ #### `templates search <query>`
259
+
260
+ Search templates by name, provider, or event type.
173
261
 
174
262
  ```bash
175
- # Test webhook endpoints in your pipeline
176
- better-webhook webhooks run deployment-success --url $PROD_WEBHOOK_URL
263
+ better-webhook templates search <query>
264
+ ```
265
+
266
+ #### `templates cache`
267
+
268
+ Manage the template index cache.
269
+
270
+ ```bash
271
+ better-webhook templates cache [options]
272
+ ```
273
+
274
+ | Option | Description |
275
+ | ------------- | ------------------------ |
276
+ | `-c, --clear` | Clear the template cache |
277
+
278
+ #### `templates clean` (alias: `remove-all`)
279
+
280
+ Remove all downloaded templates.
281
+
282
+ ```bash
283
+ better-webhook templates clean [options]
284
+ ```
285
+
286
+ | Option | Description |
287
+ | ------------- | ------------------------ |
288
+ | `-f, --force` | Skip confirmation prompt |
289
+
290
+ ---
291
+
292
+ ### `better-webhook run`
293
+
294
+ Run a webhook template against a target URL. Automatically generates provider-specific signatures when a secret is provided.
295
+
296
+ ```bash
297
+ better-webhook run [templateId] [options]
298
+ ```
299
+
300
+ | Option | Description | Required |
301
+ | ----------------------- | ------------------------------------------ | -------- |
302
+ | `-u, --url <url>` | Target URL to send the webhook to | ✅ |
303
+ | `-s, --secret <secret>` | Secret for signature generation | — |
304
+ | `-H, --header <header>` | Add custom header (format: `key:value`) | — |
305
+ | `-v, --verbose` | Show detailed request/response information | — |
306
+
307
+ **Arguments:**
308
+
309
+ - `[templateId]` — Template ID to run (interactive selection if omitted)
177
310
 
178
- # Capture and replay for integration testing
179
- better-webhook capture --port 8080 &
180
- run_integration_tests
181
- better-webhook capture list
182
- better-webhook replay latest-capture $TEST_ENDPOINT
311
+ **Signature Generation:**
312
+
313
+ When you provide a secret (`--secret`), the CLI automatically generates the correct signature header based on the template's provider. You can also use environment variables (see [Environment Variables](#environment-variables)).
314
+
315
+ **Example:**
316
+
317
+ ```bash
318
+ # Run with inline secret
319
+ better-webhook run github-push \
320
+ --url http://localhost:3000/api/webhooks/github \
321
+ --secret "your-webhook-secret"
322
+
323
+ # Run with custom headers
324
+ better-webhook run github-push \
325
+ --url http://localhost:3000/api/webhooks/github \
326
+ --secret "$GITHUB_WEBHOOK_SECRET" \
327
+ --header "X-Custom-Header:value" \
328
+ --verbose
329
+ ```
330
+
331
+ ---
332
+
333
+ ### `better-webhook replay`
334
+
335
+ Replay a captured webhook to a target URL. Preserves original headers (except connection-related ones) and allows overrides.
336
+
337
+ ```bash
338
+ better-webhook replay [captureId] [targetUrl] [options]
183
339
  ```
184
340
 
185
- ### API Integration
341
+ | Option | Description |
342
+ | ----------------------- | -------------------------------------------- |
343
+ | `-m, --method <method>` | Override HTTP method |
344
+ | `-H, --header <header>` | Add or override header (format: `key:value`) |
345
+ | `-v, --verbose` | Show detailed request/response information |
346
+
347
+ **Arguments:**
348
+
349
+ - `[captureId]` — Capture ID to replay (interactive selection if omitted)
350
+ - `[targetUrl]` — Target URL (prompts if omitted, defaults to original path on localhost:3000)
351
+
352
+ **Example:**
186
353
 
187
354
  ```bash
188
- # Download and customize templates for popular services
189
- better-webhook webhooks download stripe-invoice.payment_succeeded
190
- better-webhook webhooks run stripe-invoice --url https://myapp.com/stripe
355
+ # Interactive mode
356
+ better-webhook replay
357
+
358
+ # Direct replay with options
359
+ better-webhook replay abc123 http://localhost:3000/webhooks \
360
+ --method POST \
361
+ --header "X-Debug:true" \
362
+ --verbose
363
+ ```
364
+
365
+ ---
366
+
367
+ ### `better-webhook dashboard`
368
+
369
+ Start the local **dashboard UI + API + WebSocket** server.
370
+
371
+ By default, this command starts:
191
372
 
192
- # Generate templates from real webhook data
193
- better-webhook capture template abc123 stripe-custom-template
373
+ - **Dashboard UI**: `http://localhost:4000/`
374
+ - **API**: `http://localhost:4000/api/*`
375
+ - **WebSocket**: `ws://localhost:4000/ws`
376
+ - **Capture server** (in-process): `http://localhost:3001/*`
377
+
378
+ ```bash
379
+ better-webhook dashboard [options]
194
380
  ```
195
381
 
196
- ## Examples
382
+ | Option | Description | Default |
383
+ | ------------------------- | ------------------------------- | ----------- |
384
+ | `-p, --port <port>` | Dashboard server port | `4000` |
385
+ | `-h, --host <host>` | Dashboard server host | `localhost` |
386
+ | `--capture-port <port>` | Capture server port | `3001` |
387
+ | `--capture-host <host>` | Capture server host | `0.0.0.0` |
388
+ | `--no-capture` | Do not start capture server | — |
389
+ | `--captures-dir <dir>` | Override captures directory | — |
390
+ | `--templates-dir <dir>` | Override templates base dir | — |
391
+
392
+ **Security note:**
393
+ Keep the dashboard bound to `localhost` unless you trust your network. The API includes endpoints that can send HTTP requests to arbitrary URLs (run/replay).
394
+
395
+ ---
396
+
397
+ ## Environment Variables
398
+
399
+ The CLI automatically reads webhook secrets from environment variables based on the provider:
197
400
 
198
- ### Stripe Payment Webhook
401
+ | Provider | Environment Variable |
402
+ | -------- | ------------------------- |
403
+ | Stripe | `STRIPE_WEBHOOK_SECRET` |
404
+ | GitHub | `GITHUB_WEBHOOK_SECRET` |
405
+ | Shopify | `SHOPIFY_WEBHOOK_SECRET` |
406
+ | Twilio | `TWILIO_WEBHOOK_SECRET` |
407
+ | Slack | `SLACK_WEBHOOK_SECRET` |
408
+ | Linear | `LINEAR_WEBHOOK_SECRET` |
409
+ | Clerk | `CLERK_WEBHOOK_SECRET` |
410
+ | SendGrid | `SENDGRID_WEBHOOK_SECRET` |
411
+ | Discord | `DISCORD_WEBHOOK_SECRET` |
412
+ | Custom | `WEBHOOK_SECRET` |
413
+
414
+ **Usage:**
415
+
416
+ ```bash
417
+ export GITHUB_WEBHOOK_SECRET="your-secret-here"
418
+ better-webhook run github-push --url http://localhost:3000/webhooks/github
419
+ # Secret is automatically used for signature generation
420
+ ```
421
+
422
+ ---
423
+
424
+ ## Storage Locations
425
+
426
+ All CLI data is stored in `~/.better-webhook/`:
427
+
428
+ ```
429
+ ~/.better-webhook/
430
+ ├── captures/ # Captured webhook requests
431
+ │ ├── 2024-01-15_10-30-00_abc12345.json
432
+ │ └── 2024-01-15_11-00-00_def67890.json
433
+ ├── templates/ # Downloaded templates
434
+ │ ├── github/
435
+ │ │ ├── github-push.json
436
+ │ │ └── github-pull_request.json
437
+ │ └── stripe/
438
+ │ └── stripe-invoice.json
439
+ └── templates-cache.json # Template index cache (1 hour TTL)
440
+ ```
441
+
442
+ ---
443
+
444
+ ## Webhook Template Format
445
+
446
+ Templates follow this JSON schema:
199
447
 
200
448
  ```json
201
449
  {
202
- "url": "https://api.myapp.com/webhooks/stripe",
450
+ "url": "https://api.example.com/webhook",
203
451
  "method": "POST",
204
452
  "headers": [
205
- { "key": "Stripe-Signature", "value": "t=1234567890,v1=signature" }
453
+ { "key": "Content-Type", "value": "application/json" },
454
+ { "key": "X-Custom-Header", "value": "custom-value" }
206
455
  ],
207
456
  "body": {
208
- "id": "evt_1234567890",
209
- "object": "event",
210
- "type": "payment_intent.succeeded",
457
+ "event": "user.created",
211
458
  "data": {
212
- "object": {
213
- "id": "pi_1234567890",
214
- "amount": 2000,
215
- "currency": "usd",
216
- "status": "succeeded"
217
- }
459
+ "id": "12345",
460
+ "email": "user@example.com"
218
461
  }
219
- }
462
+ },
463
+ "provider": "custom",
464
+ "event": "user.created",
465
+ "description": "Triggered when a new user is created"
220
466
  }
221
467
  ```
222
468
 
223
- ### GitHub Webhook
469
+ | Field | Type | Required | Description |
470
+ | ------------- | ------ | -------- | --------------------------------------------------- |
471
+ | `url` | string | — | Default target URL (can be overridden with `--url`) |
472
+ | `method` | string | — | HTTP method (default: `POST`) |
473
+ | `headers` | array | — | Array of `{ key, value }` header objects |
474
+ | `body` | any | — | Request payload (object or string) |
475
+ | `provider` | string | — | Provider name for signature generation |
476
+ | `event` | string | — | Event type identifier |
477
+ | `description` | string | — | Human-readable description |
478
+
479
+ ---
480
+
481
+ ## Captured Webhook Format
482
+
483
+ Captured webhooks are stored with full request details:
224
484
 
225
485
  ```json
226
486
  {
227
- "url": "https://api.myapp.com/webhooks/github",
487
+ "id": "550e8400-e29b-41d4-a716-446655440000",
488
+ "timestamp": "2024-01-15T10:30:00.000Z",
228
489
  "method": "POST",
229
- "headers": [
230
- { "key": "X-GitHub-Event", "value": "push" },
231
- { "key": "X-Hub-Signature-256", "value": "sha256=signature" }
232
- ],
233
- "body": {
234
- "ref": "refs/heads/main",
235
- "commits": [
236
- {
237
- "id": "abc123",
238
- "message": "Update README",
239
- "author": {
240
- "name": "Developer",
241
- "email": "dev@example.com"
242
- }
243
- }
244
- ]
245
- }
490
+ "url": "/webhooks/github?action=opened",
491
+ "path": "/webhooks/github",
492
+ "headers": {
493
+ "content-type": "application/json",
494
+ "x-github-event": "push",
495
+ "x-hub-signature-256": "sha256=..."
496
+ },
497
+ "body": { "...parsed JSON..." },
498
+ "rawBody": "{...original string...}",
499
+ "query": { "action": "opened" },
500
+ "provider": "github",
501
+ "contentType": "application/json",
502
+ "contentLength": 1234
246
503
  }
247
504
  ```
248
505
 
249
- ## Error Handling
506
+ ---
250
507
 
251
- The CLI provides detailed error messages and uses appropriate exit codes:
508
+ ## Use Cases
252
509
 
253
- - **0**: Success
254
- - **1**: General error (network, validation, file not found)
510
+ ### Local Development
511
+
512
+ Test your webhook endpoints during development:
255
513
 
256
514
  ```bash
257
- # Validation errors show detailed field information
258
- better-webhook webhooks run invalid-webhook
259
- # Error: Webhook validation failed:
260
- # - url: Required field missing
261
- # - method: Invalid HTTP method "INVALID"
515
+ # Terminal 1: Start your app
516
+ npm run dev
517
+
518
+ # Terminal 2: Capture webhooks
519
+ better-webhook capture --port 4000
262
520
 
263
- # Network errors are clearly reported
264
- better-webhook webhooks run test --url https://invalid-domain.nonexistent
265
- # Error: Request failed: getaddrinfo ENOTFOUND invalid-domain.nonexistent
521
+ # Configure your webhook provider to send to http://localhost:4000
522
+ # (use ngrok for external providers: ngrok http 4000)
523
+
524
+ # Terminal 3: Replay captured webhooks to your app
525
+ better-webhook replay abc123 http://localhost:3000/api/webhooks
266
526
  ```
267
527
 
268
- ## Configuration
528
+ ### Debugging Webhook Issues
269
529
 
270
- ### Environment Variables
530
+ ```bash
531
+ # Capture the problematic webhook
532
+ better-webhook capture
271
533
 
272
- | Variable | Description | Default |
273
- | -------------- | --------------------------------- | ------------------- |
274
- | `WEBHOOKS_DIR` | Directory for webhook definitions | `.webhooks` |
275
- | `CAPTURES_DIR` | Directory for captured webhooks | `.webhook-captures` |
534
+ # Inspect the full request
535
+ better-webhook captures show abc123 --body
276
536
 
277
- ### Global Options
537
+ # Replay to your local server with verbose output
538
+ better-webhook replay abc123 http://localhost:3000/webhooks --verbose
539
+ ```
278
540
 
279
- | Flag | Description |
280
- | ----------- | ------------------------ |
281
- | `--help` | Show help information |
282
- | `--version` | Show version information |
541
+ ### Testing Signature Verification
283
542
 
284
- ## Contributing
543
+ ```bash
544
+ # Run a template with your production secret
545
+ better-webhook run stripe-invoice.payment_succeeded \
546
+ --url http://localhost:3000/api/webhooks/stripe \
547
+ --secret "whsec_your_stripe_secret" \
548
+ --verbose
549
+ ```
285
550
 
286
- We welcome contributions! Please see our [Contributing Guide](https://github.com/endalk200/better-webhook/blob/main/CONTRIBUTING.md) for details.
551
+ ### CI/CD Integration
552
+
553
+ ```bash
554
+ # Test webhook endpoints in your pipeline
555
+ better-webhook templates download github-push
556
+ better-webhook run github-push \
557
+ --url "$TEST_ENDPOINT" \
558
+ --secret "$GITHUB_WEBHOOK_SECRET"
559
+
560
+ # Check exit code
561
+ if [ $? -eq 0 ]; then
562
+ echo "Webhook test passed"
563
+ fi
564
+ ```
565
+
566
+ ---
567
+
568
+ ## WebSocket API
569
+
570
+ The capture server exposes a WebSocket endpoint on the same port for real-time notifications:
571
+
572
+ ```javascript
573
+ const ws = new WebSocket("ws://localhost:3001");
574
+
575
+ ws.onmessage = (event) => {
576
+ const message = JSON.parse(event.data);
577
+
578
+ switch (message.type) {
579
+ case "capture":
580
+ console.log("New capture:", message.payload.capture);
581
+ break;
582
+ case "captures_updated":
583
+ console.log("Captures list:", message.payload.captures);
584
+ break;
585
+ }
586
+ };
587
+ ```
287
588
 
288
- ### Development Setup
589
+ **Message Types:**
590
+
591
+ | Type | Description | Payload |
592
+ | ------------------ | --------------------------- | --------------------- |
593
+ | `capture` | New webhook captured | `{ file, capture }` |
594
+ | `captures_updated` | Initial state on connection | `{ captures, count }` |
595
+
596
+ ---
597
+
598
+ ## Error Handling
599
+
600
+ The CLI uses standard exit codes:
601
+
602
+ | Code | Description |
603
+ | ---- | ------------------------------------------------- |
604
+ | `0` | Success |
605
+ | `1` | Error (validation, network, file not found, etc.) |
606
+
607
+ Detailed error messages are displayed in the terminal:
608
+
609
+ ```bash
610
+ better-webhook run nonexistent-template --url http://localhost:3000
611
+ # ❌ Template not found: nonexistent-template
612
+ # Download it with: better-webhook templates download nonexistent-template
613
+
614
+ better-webhook capture --port 99999
615
+ # Invalid port number
616
+
617
+ better-webhook replay abc123 invalid-url
618
+ # Please enter a valid URL
619
+ ```
620
+
621
+ ---
622
+
623
+ ## Development
624
+
625
+ ### Building from Source
289
626
 
290
627
  ```bash
291
628
  git clone https://github.com/endalk200/better-webhook.git
@@ -294,15 +631,22 @@ pnpm install
294
631
  pnpm --filter @better-webhook/cli build
295
632
  ```
296
633
 
297
- ### Running Tests
634
+ ### Running Locally
298
635
 
299
636
  ```bash
300
- pnpm --filter @better-webhook/cli test
637
+ cd apps/webhook-cli
638
+ pnpm start -- capture --port 3001
301
639
  ```
302
640
 
641
+ ---
642
+
643
+ ## Contributing
644
+
645
+ We welcome contributions! Please see our [Contributing Guide](https://github.com/endalk200/better-webhook/blob/main/CONTRIBUTING.md) for details.
646
+
303
647
  ## Changelog
304
648
 
305
- See [CHANGELOG.md](https://github.com/endalk200/better-webhook/blob/main/apps/webhook-cli/CHANGELOG.md) for version history.
649
+ See [CHANGELOG.md](./CHANGELOG.md) for version history.
306
650
 
307
651
  ## License
308
652
 
@@ -313,8 +657,3 @@ MIT © [Endalk](https://github.com/endalk200)
313
657
  - 🐛 [Report bugs](https://github.com/endalk200/better-webhook/issues)
314
658
  - 💡 [Request features](https://github.com/endalk200/better-webhook/issues)
315
659
  - 📖 [Documentation](https://github.com/endalk200/better-webhook#readme)
316
-
317
- ---
318
-
319
- Made with ❤️ by [Endalk](https://github.com/endalk200)
320
-