hookdeck-cli 1.0.4 → 1.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.
Files changed (3) hide show
  1. package/README.md +238 -76
  2. package/bin/hookdeck +0 -0
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -99,6 +99,7 @@ hookdeck login
99
99
  ```
100
100
 
101
101
  If you are in an environment without a browser (e.g., a TTY-only terminal), you can use the `--interactive` (or `-i`) flag to log in by pasting your API key:
102
+
102
103
  ```sh
103
104
  hookdeck login --interactive
104
105
  ```
@@ -110,17 +111,43 @@ hookdeck login --interactive
110
111
  Start a session to forward your events to an HTTP server.
111
112
 
112
113
  ```sh
113
- hookdeck listen <port-or-URL> <source-alias?> <connection-query?> [--path?]
114
+ hookdeck listen <port-or-URL> <source-alias?> <connection-query?> [--path?] [--output?]
114
115
  ```
115
116
 
116
117
  Hookdeck works by routing events received for a given `source` (i.e., Shopify, Github, etc.) to its defined `destination` by connecting them with a `connection` to a `destination`. The CLI allows you to receive events for any given connection and forward them to your localhost at the specified port or any valid URL.
117
118
 
118
119
  Each `source` is assigned an Event URL, which you can use to receive events. When starting with a fresh account, the CLI will prompt you to create your first source. Each CLI process can listen to one source at a time.
119
120
 
120
- Contrary to ngrok, **Hookdeck does not allow to append a path to your event URL**. Instead, the routing is done within Hookdeck configuration. This means you will also be prompted to specify your `destination` path, and you can have as many as you want per `source`.
121
-
122
121
  > The `port-or-URL` param is mandatory, events will be forwarded to http://localhost:$PORT/$DESTINATION_PATH when inputing a valid port or your provided URL.
123
122
 
123
+ #### Interactive Mode
124
+
125
+ The default interactive mode uses a full-screen TUI (Terminal User Interface) with an alternative screen buffer, meaning your terminal history is preserved when you exit. The interface includes:
126
+
127
+ - **Connection Header**: Shows your sources, webhook URLs, and connection routing
128
+ - Auto-collapses when the first event arrives to save space
129
+ - Toggle with `i` to expand/collapse connection details
130
+ - **Event List**: Scrollable history of all received events (up to 1000 events)
131
+ - Auto-scrolls to show latest events as they arrive
132
+ - Manual navigation pauses auto-scrolling
133
+ - **Status Bar**: Shows event details and available keyboard shortcuts
134
+ - **Event Details View**: Full request/response inspection with headers and body
135
+
136
+ #### Interactive Keyboard Shortcuts
137
+
138
+ While in interactive mode, you can use the following keyboard shortcuts:
139
+
140
+ - `↑` / `↓` or `k` / `j` - Navigate between events (select different events)
141
+ - `i` - Toggle connection information (expand/collapse connection details)
142
+ - `r` - Retry the selected event
143
+ - `o` - Open the selected event in the Hookdeck dashboard
144
+ - `d` - Show detailed request/response information for the selected event (press `d` or `ESC` to close)
145
+ - When details view is open: `↑` / `↓` scroll through content, `PgUp` / `PgDown` for page navigation
146
+ - `q` - Quit the application (terminal state is restored)
147
+ - `Ctrl+C` - Also quits the application
148
+
149
+ The selected event is indicated by a `>` character at the beginning of the line. All actions (retry, open, details) work on the currently selected event, not just the latest one. These shortcuts are displayed in the status bar at the bottom of the screen.
150
+
124
151
  #### Listen to all your connections for a given source
125
152
 
126
153
  The second param, `source-alias` is used to select a specific source to listen on. By default, the CLI will start listening on all eligible connections for that source.
@@ -128,18 +155,24 @@ The second param, `source-alias` is used to select a specific source to listen o
128
155
  ```sh
129
156
  $ hookdeck listen 3000 shopify
130
157
 
131
- 👉 Inspect and replay events: https://dashboard.hookdeck.com/cli/events
158
+ ●── HOOKDECK CLI ──●
159
+
160
+ Listening on 1 source • 2 connections • [i] Collapse
132
161
 
133
162
  Shopify Source
134
- 🔌 Event URL: https://events.hookdeck.com/e/src_DAjaFWyyZXsFdZrTOKpuHnOH
163
+ │ Requests to https://events.hookdeck.com/e/src_DAjaFWyyZXsFdZrTOKpuHnOH
164
+ ├─ Forwards to → http://localhost:3000/webhooks/shopify/inventory (Inventory Service)
165
+ └─ Forwards to → http://localhost:3000/webhooks/shopify/orders (Orders Service)
135
166
 
136
- Connections
137
- Inventory Service forwarding to /webhooks/shopify/inventory
138
- Orders Service forwarding to /webhooks/shopify/orders
167
+ 💡 Open dashboard to inspect, retry & bookmark events: https://dashboard.hookdeck.com/events/cli?team_id=...
139
168
 
169
+ Events • [↑↓] Navigate ──────────────────────────────────────────────────────────
140
170
 
141
- Getting ready...
171
+ 2025-10-12 14:32:15 [200] POST http://localhost:3000/webhooks/shopify/orders (23ms) → https://dashboard.hookdeck.com/events/evt_...
172
+ > 2025-10-12 14:32:18 [200] POST http://localhost:3000/webhooks/shopify/inventory (45ms) → https://dashboard.hookdeck.com/events/evt_...
142
173
 
174
+ ───────────────────────────────────────────────────────────────────────────────
175
+ > ✓ Last event succeeded with status 200 | [r] Retry • [o] Open in dashboard • [d] Show data
143
176
  ```
144
177
 
145
178
  #### Listen to multiple sources
@@ -149,20 +182,32 @@ Orders Service forwarding to /webhooks/shopify/orders
149
182
  ```sh
150
183
  $ hookdeck listen 3000 '*'
151
184
 
152
- 👉 Inspect and replay events: https://dashboard.hookdeck.com/cli/events
185
+ ●── HOOKDECK CLI ──●
186
+
187
+ Listening on 3 sources • 3 connections • [i] Collapse
188
+
189
+ stripe
190
+ │ Requests to → https://events.hookdeck.com/e/src_DAjaFWyyZXsFdZrTOKpuHn01
191
+ └─ Forwards to → http://localhost:3000/webhooks/stripe (cli-stripe)
192
+
193
+ shopify
194
+ │ Requests to → https://events.hookdeck.com/e/src_DAjaFWyyZXsFdZrTOKpuHn02
195
+ └─ Forwards to → http://localhost:3000/webhooks/shopify (cli-shopify)
153
196
 
154
- Sources
155
- 🔌 stripe URL: https://events.hookdeck.com/e/src_DAjaFWyyZXsFdZrTOKpuHn01
156
- 🔌 shopify URL: https://events.hookdeck.com/e/src_DAjaFWyyZXsFdZrTOKpuHn02
157
- 🔌 twilio URL: https://events.hookdeck.com/e/src_DAjaFWyyZXsFdZrTOKpuHn03
197
+ twilio
198
+ │ Requests to https://events.hookdeck.com/e/src_DAjaFWyyZXsFdZrTOKpuHn03
199
+ └─ Forwards to → http://localhost:3000/webhooks/twilio (cli-twilio)
158
200
 
159
- Connections
160
- stripe -> cli-stripe forwarding to /webhooks/stripe
161
- shopify -> cli-shopify forwarding to /webhooks/shopify
162
- twilio -> cli-twilio forwarding to /webhooks/twilio
201
+ 💡 Open dashboard to inspect, retry & bookmark events: https://dashboard.hookdeck.com/events/cli?team_id=...
163
202
 
164
- Getting ready...
203
+ Events [↑↓] Navigate ──────────────────────────────────────────────────────────
165
204
 
205
+ 2025-10-12 14:35:21 [200] POST http://localhost:3000/webhooks/stripe (12ms) → https://dashboard.hookdeck.com/events/evt_...
206
+ 2025-10-12 14:35:44 [200] POST http://localhost:3000/webhooks/shopify (31ms) → https://dashboard.hookdeck.com/events/evt_...
207
+ > 2025-10-12 14:35:52 [200] POST http://localhost:3000/webhooks/twilio (18ms) → https://dashboard.hookdeck.com/events/evt_...
208
+
209
+ ───────────────────────────────────────────────────────────────────────────────
210
+ > ✓ Last event succeeded with status 200 | [r] Retry • [o] Open in dashboard • [d] Show data
166
211
  ```
167
212
 
168
213
  #### Listen to a subset of connections
@@ -172,17 +217,22 @@ The 3rd param, `connection-query` specifies which connection with a CLI destinat
172
217
  ```sh
173
218
  $ hookdeck listen 3000 shopify orders
174
219
 
175
- 👉 Inspect and replay events: https://dashboard.hookdeck.com/cli/events
220
+ ●── HOOKDECK CLI ──●
221
+
222
+ Listening on 1 source • 1 connection • [i] Collapse
176
223
 
177
224
  Shopify Source
178
- 🔌 Event URL: https://events.hookdeck.com/e/src_DAjaFWyyZXsFdZrTOKpuHnOH
225
+ │ Requests to https://events.hookdeck.com/e/src_DAjaFWyyZXsFdZrTOKpuHnOH
226
+ └─ Forwards to → http://localhost:3000/webhooks/shopify/orders (Orders Service)
179
227
 
180
- Connections
181
- Orders Service forwarding to /webhooks/shopify/orders
228
+ 💡 Open dashboard to inspect, retry & bookmark events: https://dashboard.hookdeck.com/events/cli?team_id=...
182
229
 
230
+ Events • [↑↓] Navigate ──────────────────────────────────────────────────────────
183
231
 
184
- Getting ready...
232
+ > 2025-10-12 14:38:09 [200] POST http://localhost:3000/webhooks/shopify/orders (27ms) → https://dashboard.hookdeck.com/events/evt_...
185
233
 
234
+ ───────────────────────────────────────────────────────────────────────────────
235
+ > ✓ Last event succeeded with status 200 | [r] Retry • [o] Open in dashboard • [d] Show data
186
236
  ```
187
237
 
188
238
  #### Changing the path events are forwarded to
@@ -192,19 +242,104 @@ The `--path` flag sets the path to which events are forwarded.
192
242
  ```sh
193
243
  $ hookdeck listen 3000 shopify orders --path /events/shopify/orders
194
244
 
195
- 👉 Inspect and replay events: https://dashboard.hookdeck.com/cli/events
245
+ ●── HOOKDECK CLI ──●
246
+
247
+ Listening on 1 source • 1 connection • [i] Collapse
196
248
 
197
249
  Shopify Source
198
- 🔌 Event URL: https://events.hookdeck.com/e/src_DAjaFWyyZXsFdZrTOKpuHnOH
250
+ │ Requests to https://events.hookdeck.com/e/src_DAjaFWyyZXsFdZrTOKpuHnOH
251
+ └─ Forwards to → http://localhost:3000/events/shopify/orders (Orders Service)
199
252
 
200
- Connections
201
- Orders Service forwarding to /events/shopify/orders
253
+ 💡 Open dashboard to inspect, retry & bookmark events: https://dashboard.hookdeck.com/events/cli?team_id=...
202
254
 
255
+ Events • [↑↓] Navigate ──────────────────────────────────────────────────────────
203
256
 
204
- Getting ready...
257
+ > 2025-10-12 14:40:23 [200] POST http://localhost:3000/events/shopify/orders (19ms) → https://dashboard.hookdeck.com/events/evt_...
205
258
 
259
+ ───────────────────────────────────────────────────────────────────────────────
260
+ > ✓ Last event succeeded with status 200 | [r] Retry • [o] Open in dashboard • [d] Show data
206
261
  ```
207
262
 
263
+ #### Controlling output verbosity
264
+
265
+ The `--output` flag controls how events are displayed. This is useful for reducing resource usage in high-throughput scenarios or when running in the background.
266
+
267
+ **Available modes:**
268
+
269
+ - `interactive` (default) - Full-screen TUI with alternative screen buffer, event history, navigation, and keyboard shortcuts. Your terminal history is preserved and restored when you exit.
270
+ - `compact` - Simple one-line logs for all events without interactive features. Events are appended to your terminal history.
271
+ - `quiet` - Only displays fatal connection errors (network failures, timeouts), not HTTP errors
272
+
273
+ All modes display connection information at startup and a connection status message.
274
+
275
+ **Examples:**
276
+
277
+ ```sh
278
+ # Default - full interactive UI with keyboard shortcuts
279
+ $ hookdeck listen 3000 shopify
280
+
281
+ # Simple logging mode - prints all events as one-line logs
282
+ $ hookdeck listen 3000 shopify --output compact
283
+
284
+ # Quiet mode - only shows fatal connection errors
285
+ $ hookdeck listen 3000 shopify --output quiet
286
+ ```
287
+
288
+ **Compact mode output:**
289
+
290
+ ```
291
+ Listening on
292
+ shopify
293
+ └─ Forwards to → http://localhost:3000
294
+
295
+ Connected. Waiting for events...
296
+
297
+ 2025-10-08 15:56:53 [200] POST http://localhost:3000 (45ms) → https://...
298
+ 2025-10-08 15:56:54 [422] POST http://localhost:3000 (12ms) → https://...
299
+ ```
300
+
301
+ **Quiet mode output:**
302
+
303
+ ```
304
+ Listening on
305
+ shopify
306
+ └─ Forwards to → http://localhost:3000
307
+
308
+ Connected. Waiting for events...
309
+
310
+ 2025-10-08 15:56:53 [ERROR] Failed to POST: connection refused
311
+ ```
312
+
313
+ > Note: In `quiet` mode, only fatal errors are shown (connection failures, network unreachable, timeouts). HTTP error responses (4xx, 5xx) are not displayed as they are valid HTTP responses.
314
+
315
+ #### Filtering events
316
+
317
+ The CLI supports filtering events using Hookdeck's filter syntax. Filters allow you to receive only events that match specific conditions, reducing noise and focusing on the events you care about during development.
318
+
319
+ **Filter flags:**
320
+
321
+ - `--filter-body` - Filter events by request body content (JSON)
322
+ - `--filter-headers` - Filter events by request headers (JSON)
323
+ - `--filter-query` - Filter events by query parameters (JSON)
324
+ - `--filter-path` - Filter events by request path (JSON)
325
+
326
+ All filter flags accept JSON using [Hookdeck's filter syntax](https://hookdeck.com/docs/filters). You can use exact matches or operators like `$exist`, `$gte`, `$lte`, `$in`, etc.
327
+
328
+ **Examples:**
329
+
330
+ ```sh
331
+ # Filter events by body content (only events with matching data)
332
+ hookdeck listen 3000 github --filter-body '{"action": "opened"}'
333
+
334
+ # Filter events with multiple conditions
335
+ hookdeck listen 3000 stripe --filter-body '{"type": "charge.succeeded"}' --filter-headers '{"x-stripe-signature": {"$exist": true}}'
336
+
337
+ # Filter using operators
338
+ hookdeck listen 3000 api --filter-body '{"amount": {"$gte": 100}}'
339
+ ```
340
+
341
+ When filters are active, the CLI will display a warning message indicating which filters are applied. Only events matching all specified filter conditions will be forwarded to your local server.
342
+
208
343
  #### Viewing and interacting with your events
209
344
 
210
345
  Event logs for your CLI can be found at [https://dashboard.hookdeck.com/cli/events](https://dashboard.hookdeck.com/cli/events?ref=github-hookdeck-cli). Events can be replayed or saved at any time.
@@ -226,6 +361,7 @@ For local development scenarios, you can instruct the `listen` command to bypass
226
361
  **This is dangerous and should only be used in trusted local development environments for destinations you control.**
227
362
 
228
363
  Example of skipping SSL validation for an HTTPS destination:
364
+
229
365
  ```sh
230
366
  hookdeck listen --insecure https://<your-ssl-url-or-url:port>/ <source-alias?> <connection-query?>
231
367
  ```
@@ -256,17 +392,22 @@ Done! The Hookdeck CLI is configured in project MyProject
256
392
 
257
393
  $ hookdeck listen 3000 shopify orders
258
394
 
259
- 👉 Inspect and replay events: https://dashboard.hookdeck.com/cli/events
395
+ ●── HOOKDECK CLI ──●
396
+
397
+ Listening on 1 source • 1 connection • [i] Collapse
260
398
 
261
399
  Shopify Source
262
- 🔌 Event URL: https://events.hookdeck.com/e/src_DAjaFWyyZXsFdZrTOKpuHnOH
400
+ │ Requests to https://events.hookdeck.com/e/src_DAjaFWyyZXsFdZrTOKpuHnOH
401
+ └─ Forwards to → http://localhost:3000/webhooks/shopify/orders (Orders Service)
263
402
 
264
- Connections
265
- Inventory Service forwarding to /webhooks/shopify/inventory
403
+ 💡 Open dashboard to inspect, retry & bookmark events: https://dashboard.hookdeck.com/events/cli?team_id=...
266
404
 
405
+ Events • [↑↓] Navigate ──────────────────────────────────────────────────────────
267
406
 
268
- Getting ready...
407
+ > 2025-10-12 14:42:55 [200] POST http://localhost:3000/webhooks/shopify/orders (34ms) → https://dashboard.hookdeck.com/events/evt_...
269
408
 
409
+ ───────────────────────────────────────────────────────────────────────────────
410
+ > ✓ Last event succeeded with status 200 | [r] Retry • [o] Open in dashboard • [d] Show data
270
411
  ```
271
412
 
272
413
  ### Manage active project
@@ -296,38 +437,41 @@ hookdeck project use [<organization_name> [<project_name>]]
296
437
 
297
438
  **Behavior:**
298
439
 
299
- - **`hookdeck project use`** (no arguments):
300
- An interactive prompt will guide you through selecting your organization and then the project within that organization.
301
- ```sh
302
- $ hookdeck project use
303
- Use the arrow keys to navigate: ↓ ↑ → ←
304
- ? Select Organization:
305
- My Org
306
- Another Org
307
- ...
308
- ? Select Project (Another Org):
309
- Project X
310
- Project Y
311
- Selecting project Project Y
312
- Successfully set active project to: [Another Org] Project Y
313
- ```
314
-
315
- - **`hookdeck project use <organization_name>`** (one argument):
316
- Filters projects by the specified `<organization_name>`.
317
- - If multiple projects exist under that organization, you'll be prompted to choose one.
318
- - If only one project exists, it will be selected automatically.
319
- ```sh
320
- $ hookdeck project use "My Org"
321
- # (If multiple projects, prompts to select. If one, auto-selects)
322
- Successfully set active project to: [My Org] Default Project
323
- ```
324
-
325
- - **`hookdeck project use <organization_name> <project_name>`** (two arguments):
326
- Directly selects the project `<project_name>` under the organization `<organization_name>`.
327
- ```sh
328
- $ hookdeck project use "My Corp" "API Staging"
329
- Successfully set active project to: [My Corp] API Staging
330
- ```
440
+ - **`hookdeck project use`** (no arguments):
441
+ An interactive prompt will guide you through selecting your organization and then the project within that organization.
442
+
443
+ ```sh
444
+ $ hookdeck project use
445
+ Use the arrow keys to navigate: ↓ ↑ → ←
446
+ ? Select Organization:
447
+ My Org
448
+ ▸ Another Org
449
+ ...
450
+ ? Select Project (Another Org):
451
+ Project X
452
+ Project Y
453
+ Selecting project Project Y
454
+ Successfully set active project to: [Another Org] Project Y
455
+ ```
456
+
457
+ - **`hookdeck project use <organization_name>`** (one argument):
458
+ Filters projects by the specified `<organization_name>`.
459
+
460
+ - If multiple projects exist under that organization, you'll be prompted to choose one.
461
+ - If only one project exists, it will be selected automatically.
462
+
463
+ ```sh
464
+ $ hookdeck project use "My Org"
465
+ # (If multiple projects, prompts to select. If one, auto-selects)
466
+ Successfully set active project to: [My Org] Default Project
467
+ ```
468
+
469
+ - **`hookdeck project use <organization_name> <project_name>`** (two arguments):
470
+ Directly selects the project `<project_name>` under the organization `<organization_name>`.
471
+ ```sh
472
+ $ hookdeck project use "My Corp" "API Staging"
473
+ Successfully set active project to: [My Corp] API Staging
474
+ ```
331
475
 
332
476
  Upon successful selection, you will generally see a confirmation message like:
333
477
  `Successfully set active project to: [<organization_name>] <project_name>`
@@ -340,9 +484,9 @@ The Hookdeck CLI uses configuration files to store the your keys, project settin
340
484
 
341
485
  The CLI will look for the configuration file in the following order:
342
486
 
343
- 1. The `--config` flag, which allows you to specify a custom configuration file name and path per command.
344
- 2. The local directory `.hookdeck/config.toml`.
345
- 3. The default global configuration file location.
487
+ 1. The `--config` flag, which allows you to specify a custom configuration file name and path per command.
488
+ 2. The local directory `.hookdeck/config.toml`.
489
+ 3. The default global configuration file location.
346
490
 
347
491
  ### Default configuration Location
348
492
 
@@ -415,13 +559,13 @@ hookdeck listen 3030 webhooks -p prod
415
559
 
416
560
  The following flags can be used with any command:
417
561
 
418
- * `--api-key`: Your API key to use for the command.
419
- * `--color`: Turn on/off color output (on, off, auto).
420
- * `--config`: Path to a specific configuration file.
421
- * `--device-name`: A unique name for your device.
422
- * `--insecure`: Allow invalid TLS certificates.
423
- * `--log-level`: Set the logging level (debug, info, warn, error).
424
- * `--profile` or `-p`: Use a specific configuration profile.
562
+ - `--api-key`: Your API key to use for the command.
563
+ - `--color`: Turn on/off color output (on, off, auto).
564
+ - `--config`: Path to a specific configuration file.
565
+ - `--device-name`: A unique name for your device.
566
+ - `--insecure`: Allow invalid TLS certificates.
567
+ - `--log-level`: Set the logging level (debug, info, warn, error).
568
+ - `--profile` or `-p`: Use a specific configuration profile.
425
569
 
426
570
  There are also some hidden flags that are mainly used for development and debugging:
427
571
 
@@ -430,6 +574,24 @@ There are also some hidden flags that are mainly used for development and debugg
430
574
  * `--console-base`: Sets the web console base URL.
431
575
  * `--ws-base`: Sets the Websocket base URL.
432
576
 
577
+ ## Troubleshooting
578
+
579
+ ### Homebrew: Binary Already Exists Error
580
+
581
+ If you previously installed Hookdeck via the Homebrew formula and are upgrading to the cask version, you may see:
582
+
583
+ ```
584
+ Warning: It seems there is already a Binary at '/opt/homebrew/bin/hookdeck'
585
+ from formula hookdeck; skipping link.
586
+ ```
587
+
588
+ To resolve this, uninstall the old formula version first, then install the cask:
589
+
590
+ ```sh
591
+ brew uninstall hookdeck
592
+ brew install --cask hookdeck/hookdeck/hookdeck
593
+ ```
594
+
433
595
 
434
596
  ## Developing
435
597
 
package/bin/hookdeck CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hookdeck-cli",
3
- "version": "1.0.4",
3
+ "version": "1.1.0",
4
4
  "description": "Hookdeck CLI",
5
5
  "repository": {
6
6
  "type": "git",