summon-open 1.0.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 ADDED
@@ -0,0 +1,654 @@
1
+ <div align="center">
2
+
3
+ ```
4
+
5
+ ___ _ _ _ __ ___ _ __ ___ ___ _ __
6
+ / __| | | | '_ ` _ \| '_ ` _ \ / _ \| '_ \
7
+ \__ \ |_| | | | | | | | | | | | (_) | | | |
8
+ |___/\__,_|_| |_| |_|_| |_| |_|\___/|_| |_|
9
+
10
+ ```
11
+
12
+ **Open URLs, files, folders, and apps from one cross-platform command.**
13
+
14
+ Bookmarks, search, clipboard, reveal-in-file-manager, dry-run, multiple targets, and stdin — all in a tool small enough to forget it's there. No more remembering `xdg-open` vs `start` vs `open`.
15
+
16
+ [![npm version](https://img.shields.io/npm/v/summon-open.svg)](https://www.npmjs.com/package/summon-open)
17
+ [![node](https://img.shields.io/node/v/summon-open.svg)](https://nodejs.org)
18
+ [![license](https://img.shields.io/npm/l/summon-open.svg)](license)
19
+ [![CI](https://github.com/Aditya060806/summon/actions/workflows/main.yml/badge.svg)](https://github.com/Aditya060806/summon/actions)
20
+
21
+ </div>
22
+
23
+ <!--
24
+ DEMO: drop a terminal recording here for maximum impact.
25
+ Record with https://github.com/charmbracelet/vhs or https://asciinema.org
26
+ then reference it, e.g.:
27
+ <div align="center"><img src="media/demo.gif" alt="summon demo" width="700"></div>
28
+ -->
29
+
30
+ ```console
31
+ $ summon github.com # scheme added automatically
32
+ $ summon report.pdf photo.png notes.txt # open several things at once
33
+ $ summon @docs # open a saved bookmark
34
+ $ summon -s "how to center a div" # search the web
35
+ $ summon report.pdf --reveal # highlight it in your file manager
36
+ $ cat diagram.png | summon # pipe raw bytes straight in
37
+ ```
38
+
39
+ ---
40
+
41
+ ## Table of Contents
42
+
43
+ - [Why summon](#why-summon)
44
+ - [Features](#features)
45
+ - [Install](#install)
46
+ - [Quick start](#quick-start)
47
+ - [Cheatsheet](#cheatsheet)
48
+ - [Usage](#usage)
49
+ - [Options](#options)
50
+ - [Features in depth](#features-in-depth)
51
+ - [Multiple targets](#multiple-targets)
52
+ - [Smart URL normalization](#smart-url-normalization)
53
+ - [Bookmarks](#bookmarks)
54
+ - [Web search](#web-search)
55
+ - [Clipboard](#clipboard)
56
+ - [Reveal in file manager](#reveal-in-file-manager)
57
+ - [Recent & interactive picker](#recent--interactive-picker)
58
+ - [Dry run](#dry-run)
59
+ - [Choosing the app](#choosing-the-app)
60
+ - [Stdin](#stdin)
61
+ - [Recipes](#recipes)
62
+ - [Configuration](#configuration)
63
+ - [Shell completions](#shell-completions)
64
+ - [How it works](#how-it-works)
65
+ - [Comparison](#comparison)
66
+ - [Feature matrix](#feature-matrix)
67
+ - [Same task, side by side](#same-task-side-by-side)
68
+ - [Efficiency](#efficiency)
69
+ - [Exit codes](#exit-codes)
70
+ - [Platform support](#platform-support)
71
+ - [Supported stdin file types](#supported-stdin-file-types)
72
+ - [FAQ & troubleshooting](#faq--troubleshooting)
73
+ - [Related](#related)
74
+ - [Author](#author)
75
+ - [License](#license)
76
+
77
+ ---
78
+
79
+ ## Why summon
80
+
81
+ Every operating system has its own way to "open the default thing":
82
+
83
+ | OS | Native command |
84
+ | --- | --- |
85
+ | macOS | `open` |
86
+ | Windows | `start` |
87
+ | Linux | `xdg-open` |
88
+
89
+ Writing a script that works everywhere means branching on the platform, escaping arguments differently, and handling edge cases like piped input. `summon` collapses all of that into a single, predictable command — then adds the quality-of-life features the native tools never had.
90
+
91
+ ```sh
92
+ # Instead of this…
93
+ case "$(uname)" in
94
+ Darwin) open "$url" ;;
95
+ Linux) xdg-open "$url" ;;
96
+ *) start "$url" ;;
97
+ esac
98
+
99
+ # …just write this
100
+ summon "$url"
101
+ ```
102
+
103
+ ## Features
104
+
105
+ - **Cross-platform** — identical behavior on macOS, Windows, and Linux (Android via Termux too).
106
+ - **Opens anything** — URLs, files, folders, and executables.
107
+ - **Multiple targets** — `summon a.pdf b.png https://x.com` opens them all.
108
+ - **Smart URL normalization** — `summon github.com` just works; the `https://` is added for you.
109
+ - **Bookmarks** — save aliases (`summon @docs`) and turn `summon` into a daily driver.
110
+ - **Web search** — `summon -s "query"` opens a search with your configured engine.
111
+ - **Clipboard mode** — `summon -c` opens whatever URL/path you just copied.
112
+ - **Reveal** — `summon -r file` highlights it in Finder/Explorer/your file manager.
113
+ - **Recent + interactive picker** — re-open recent items or pick from a menu.
114
+ - **Dry run** — `--dry-run` prints exactly what would happen without doing it.
115
+ - **Pick the app** — force a specific app and pass it arguments.
116
+ - **Pipe-friendly** — stream data over stdin; the file type is auto-detected.
117
+ - **Friendly errors + exit codes** — scripts can branch on what went wrong.
118
+
119
+ ## Install
120
+
121
+ Requires **Node.js 20 or newer**.
122
+
123
+ ```sh
124
+ npm install --global summon-open
125
+ ```
126
+
127
+ This installs the `summon` command. Or run it once without installing:
128
+
129
+ ```sh
130
+ npx summon-open https://github.com
131
+ ```
132
+
133
+ <details>
134
+ <summary>Other install channels</summary>
135
+
136
+ Homebrew and Scoop manifests are planned. In the meantime, `npm`/`npx` work on every platform. If you maintain a package repo and want to help, contributions are welcome.
137
+
138
+ </details>
139
+
140
+ ## Quick start
141
+
142
+ ```sh
143
+ # Open a URL in your default browser
144
+ summon https://github.com
145
+
146
+ # Bare domains work too — https:// is added automatically
147
+ summon github.com
148
+
149
+ # Open a file, a folder, and a URL at once
150
+ summon report.pdf ./project https://news.ycombinator.com
151
+
152
+ # Open a URL in a specific browser with flags
153
+ summon https://github.com -- 'google chrome' --incognito
154
+
155
+ # Save and reuse bookmarks
156
+ summon https://docs.example.com --save docs
157
+ summon @docs
158
+
159
+ # Search the web
160
+ summon -s "rust async traits"
161
+
162
+ # Open whatever URL is on your clipboard
163
+ summon --clipboard
164
+
165
+ # Reveal a file in your file manager
166
+ summon report.pdf --reveal
167
+
168
+ # See what would happen, without doing it
169
+ summon github.com --dry-run
170
+
171
+ # Pipe data in and let summon detect the type
172
+ cat photo.png | summon
173
+ echo '<h1>Unicorns!</h1>' | summon --extension=html
174
+ ```
175
+
176
+ ## Cheatsheet
177
+
178
+ The whole tool at a glance — task on the left, command on the right.
179
+
180
+ | I want to… | Command |
181
+ | --- | --- |
182
+ | Open a URL | `summon https://example.com` |
183
+ | Open a bare domain | `summon example.com` |
184
+ | Open a file | `summon report.pdf` |
185
+ | Open a folder | `summon .` |
186
+ | Open several things | `summon a.pdf b.png https://x.com` |
187
+ | Open in a specific app | `summon url -- firefox` |
188
+ | Open with app flags | `summon url -- 'google chrome' --incognito` |
189
+ | Save a bookmark | `summon https://docs.example.com --save docs` |
190
+ | Open a bookmark | `summon @docs` |
191
+ | List bookmarks | `summon --bookmarks` |
192
+ | Remove a bookmark | `summon --remove-bookmark docs` |
193
+ | Search the web | `summon -s "query here"` |
194
+ | Open clipboard URL | `summon -c` |
195
+ | Reveal in file manager | `summon report.pdf -r` |
196
+ | Re-open something recent | `summon --recent` |
197
+ | Preview without opening | `summon url --dry-run` |
198
+ | Wait for the app to close | `summon file --wait` |
199
+ | Open piped data | `cat photo.png \| summon` |
200
+ | Open piped text as HTML | `echo '<h1>Hi</h1>' \| summon --extension=html` |
201
+
202
+ ## Usage
203
+
204
+ ```
205
+ $ summon --help
206
+
207
+ Usage
208
+ $ summon <file|url|@bookmark> … [options] [-- <app> [args]]
209
+ $ cat <file> | summon [--extension] [options] [-- <app> [args]]
210
+
211
+ Options
212
+ --wait, -w Wait for the app to exit
213
+ --background Do not bring the app to the foreground (macOS only)
214
+ --extension File extension for when stdin file type cannot be detected
215
+ --dry-run, -n Print what would be opened without opening it
216
+ --search, -s Treat the input as a search query
217
+ --clipboard, -c Open the URL/path currently on the clipboard
218
+ --reveal, -r Reveal the file/folder in your file manager
219
+ --recent Pick from recently opened items
220
+ --save <name> Save the given target as a bookmark (does not open)
221
+ --remove-bookmark Remove a saved bookmark by name
222
+ --bookmarks List saved bookmarks
223
+
224
+ Examples
225
+ $ summon https://sindresorhus.com
226
+ $ summon github.com
227
+ $ summon report.pdf photo.png notes.txt
228
+ $ summon https://github.com -- 'google chrome' --incognito
229
+ $ summon @docs
230
+ $ summon https://docs.example.com --save docs
231
+ $ summon -s "rust async traits"
232
+ $ echo '<h1>Hi</h1>' | summon --extension=html
233
+ $ summon report.pdf --reveal
234
+ $ summon --recent
235
+ ```
236
+
237
+ ## Options
238
+
239
+ | Flag | Short | Type | Default | Description |
240
+ | --- | --- | --- | --- | --- |
241
+ | `--wait` | `-w` | boolean | `false` | Wait for the opened app to exit before returning. Great for using `summon` as a `$EDITOR`. |
242
+ | `--background` | | boolean | `false` | Open without bringing the app to the foreground. **macOS only.** |
243
+ | `--extension` | | string | auto | Extension to use for piped stdin when the type can't be auto-detected. |
244
+ | `--dry-run` | `-n` | boolean | `false` | Print what would be opened without launching anything. |
245
+ | `--search` | `-s` | boolean | `false` | Treat the input as a web search query. |
246
+ | `--clipboard` | `-c` | boolean | `false` | Open the URL/path currently on the clipboard. |
247
+ | `--reveal` | `-r` | boolean | `false` | Reveal/highlight the file or folder in the file manager. |
248
+ | `--recent` | | boolean | `false` | Interactively pick from recently opened items. |
249
+ | `--save <name>` | | string | | Save the given target as a bookmark. Does not open it. |
250
+ | `--remove-bookmark <name>` | | string | | Remove a saved bookmark. |
251
+ | `--bookmarks` | | boolean | `false` | List saved bookmarks. |
252
+ | `-- <app> [args]` | | — | — | Everything after `--` selects a specific app and forwards arguments to it. |
253
+
254
+ ## Features in depth
255
+
256
+ ### Multiple targets
257
+
258
+ Pass as many files/URLs/bookmarks as you like — they're opened in order:
259
+
260
+ ```sh
261
+ summon index.html styles.css https://caniuse.com
262
+ ```
263
+
264
+ ### Smart URL normalization
265
+
266
+ If an argument looks like a bare domain (and isn't an existing file), `summon` adds `https://` for you:
267
+
268
+ ```sh
269
+ summon github.com # → https://github.com
270
+ summon localhost:3000 # → https://localhost:3000
271
+ ```
272
+
273
+ Existing files always win. `summon report.pdf` opens the file if it exists; names ending in a known file extension are treated as files, not domains.
274
+
275
+ ### Bookmarks
276
+
277
+ Save frequently used targets and open them by alias:
278
+
279
+ ```sh
280
+ summon https://github.com/Aditya060806/summon --save repo
281
+ summon @repo # explicit alias form
282
+ summon repo # bare form also works
283
+ summon --bookmarks # list them
284
+ summon --remove-bookmark repo
285
+ ```
286
+
287
+ Bookmarks live in your [config file](#configuration) and can also be edited by hand.
288
+
289
+ ### Web search
290
+
291
+ ```sh
292
+ summon -s "how to exit vim"
293
+ ```
294
+
295
+ The engine is configurable — see [Configuration](#configuration). The default is Google.
296
+
297
+ ### Clipboard
298
+
299
+ Copy a URL or path anywhere, then:
300
+
301
+ ```sh
302
+ summon --clipboard
303
+ ```
304
+
305
+ Multiple whitespace-separated entries on the clipboard are each opened.
306
+
307
+ > On Linux this uses `xsel`/`xclip`/`wl-clipboard` under the hood (install one if clipboard access fails on a headless machine).
308
+
309
+ ### Reveal in file manager
310
+
311
+ Instead of opening a file, highlight it where it lives:
312
+
313
+ ```sh
314
+ summon report.pdf --reveal
315
+ ```
316
+
317
+ - **macOS** — `open -R` (selects the file in Finder)
318
+ - **Windows** — `explorer /select,` (selects the file in Explorer)
319
+ - **Linux/other** — opens the containing folder
320
+
321
+ ### Recent & interactive picker
322
+
323
+ `summon` remembers what you open. Re-open something recent:
324
+
325
+ ```sh
326
+ summon --recent
327
+ ```
328
+
329
+ Run `summon` with no arguments in a terminal and it shows an interactive menu of your bookmarks and recent items.
330
+
331
+ ### Dry run
332
+
333
+ Preview actions without side effects — perfect for scripts and for building trust:
334
+
335
+ ```sh
336
+ $ summon github.com report.pdf --dry-run
337
+ [dry-run] open: https://github.com
338
+ [dry-run] open: report.pdf
339
+ ```
340
+
341
+ ### Choosing the app
342
+
343
+ Everything after `--` becomes the app and its arguments:
344
+
345
+ ```sh
346
+ summon https://example.com -- firefox
347
+ summon https://example.com -- 'google chrome' --incognito
348
+ ```
349
+
350
+ ### Stdin
351
+
352
+ Pipe data in and `summon` detects the format from the raw bytes, writes a temp file, and opens it:
353
+
354
+ ```sh
355
+ cat unicorn.png | summon
356
+ echo '{"hi":true}' | summon --extension=json
357
+ ```
358
+
359
+ ## Recipes
360
+
361
+ Real-world ways people wire `summon` into their day.
362
+
363
+ **Use it as your Git editor** (waits until you close the file):
364
+
365
+ ```sh
366
+ git config --global core.editor "summon --wait"
367
+ ```
368
+
369
+ **Open the current directory in your file manager:**
370
+
371
+ ```sh
372
+ summon .
373
+ ```
374
+
375
+ **Open a build artifact as soon as it's ready:**
376
+
377
+ ```sh
378
+ npm run build && summon dist/index.html
379
+ ```
380
+
381
+ **Preview a generated report from a script, or pipe it straight in:**
382
+
383
+ ```sh
384
+ node make-report.js > out.html && summon out.html
385
+ node make-report.js | summon --extension=html
386
+ ```
387
+
388
+ **Open every changed file from your last commit:**
389
+
390
+ ```sh
391
+ git diff --name-only HEAD~1 | xargs summon
392
+ ```
393
+
394
+ **Quick project bookmarks:**
395
+
396
+ ```sh
397
+ summon https://github.com/Aditya060806/summon --save repo
398
+ summon https://github.com/Aditya060806/summon/issues --save issues
399
+ summon @issues
400
+ ```
401
+
402
+ **Search from the terminal without leaving your flow:**
403
+
404
+ ```sh
405
+ summon -s "mdn array flatMap"
406
+ ```
407
+
408
+ **Open a link you just copied from a chat/email:**
409
+
410
+ ```sh
411
+ summon --clipboard
412
+ ```
413
+
414
+ **Dry-run in CI to assert what a script would open** (no GUI needed):
415
+
416
+ ```sh
417
+ summon "$ARTIFACT_URL" --dry-run # prints the target, exits 0
418
+ ```
419
+
420
+ ## Configuration
421
+
422
+ `summon` stores its config and history in a per-user directory:
423
+
424
+ | Platform | Location |
425
+ | --- | --- |
426
+ | Linux/macOS | `$XDG_CONFIG_HOME/summon` or `~/.config/summon` |
427
+ | Windows | `%APPDATA%\summon` |
428
+
429
+ You can override it with the `SUMMON_CONFIG_DIR` environment variable (also handy for testing).
430
+
431
+ **`config.json`**
432
+
433
+ ```json
434
+ {
435
+ "bookmarks": {
436
+ "docs": "https://docs.example.com",
437
+ "repo": "https://github.com/Aditya060806/summon"
438
+ },
439
+ "searchEngine": "https://www.google.com/search?q=%s"
440
+ }
441
+ ```
442
+
443
+ - `bookmarks` — map of alias → target. Managed via `--save` / `--remove-bookmark`, or edited by hand.
444
+ - `searchEngine` — a URL template where `%s` is replaced by the URL-encoded query. Examples:
445
+ - DuckDuckGo: `https://duckduckgo.com/?q=%s`
446
+ - Brave: `https://search.brave.com/search?q=%s`
447
+
448
+ **`history.json`** stores your most recently opened targets (capped, de-duplicated) and powers `--recent`.
449
+
450
+ ## Shell completions
451
+
452
+ Completion scripts live in the [`completions/`](completions) folder.
453
+
454
+ **Bash** — add to `~/.bashrc`:
455
+
456
+ ```sh
457
+ source /path/to/summon/completions/summon.bash
458
+ ```
459
+
460
+ **Zsh** — put `summon.zsh` on your `$fpath` as `_summon`, or source it from `~/.zshrc`:
461
+
462
+ ```sh
463
+ source /path/to/summon/completions/summon.zsh
464
+ ```
465
+
466
+ **Fish** — copy to your completions dir:
467
+
468
+ ```sh
469
+ cp /path/to/summon/completions/summon.fish ~/.config/fish/completions/
470
+ ```
471
+
472
+ **PowerShell** — add to your `$PROFILE`:
473
+
474
+ ```powershell
475
+ . /path/to/summon/completions/summon.ps1
476
+ ```
477
+
478
+ Completions include all flags and dynamically complete your saved bookmark names.
479
+
480
+ ## How it works
481
+
482
+ `summon` is a small, dependable layer on top of the battle-tested [`open`](https://github.com/sindresorhus/open) library.
483
+
484
+ ```
485
+ ┌──────────────────────────┐
486
+ │ summon <inputs> │
487
+ └────────────┬─────────────┘
488
+
489
+ management flag? │ (--bookmarks / --save / --remove-bookmark)
490
+ ┌───────────────────┴───────────────────┐
491
+ YES NO
492
+ │ │
493
+ read/write config.json what are we opening?
494
+ then exit ┌───────────────┼───────────────┐
495
+ clipboard search inputs / stdin
496
+ │ │ │
497
+ read clipboard build search URL expand bookmarks
498
+ └───────────────┴───────────────┘
499
+
500
+ for each target: expand @bookmark → classify
501
+
502
+ ┌───────────────────────────┼───────────────────────────┐
503
+ exists on disk? is a URL? looks like domain?
504
+ │ file │ url │ add https://
505
+ └───────────────────────────┼───────────────────────────┘
506
+
507
+ --dry-run? print · --reveal? highlight
508
+
509
+ open(target, {wait, background, app})
510
+
511
+ OS default handler (macOS open · Windows start · Linux xdg-open)
512
+ ```
513
+
514
+ For piped input, `summon` buffers stdin, sniffs the file type from the leading bytes with [`file-type`](https://github.com/sindresorhus/file-type), writes one temp file via [`tempy`](https://github.com/sindresorhus/tempy), and opens that.
515
+
516
+ ## Comparison
517
+
518
+ ### Feature matrix
519
+
520
+ How `summon` stacks up against common alternatives:
521
+
522
+ | Capability | **summon** | `xdg-open` | `open` (macOS) | `start` (Windows) | shell `case` script |
523
+ | --- | :---: | :---: | :---: | :---: | :---: |
524
+ | Works on macOS / Windows / Linux | ✅ | ❌ | macOS only | Win only | ⚠️ manual |
525
+ | One identical command everywhere | ✅ | ❌ | ❌ | ❌ | ❌ |
526
+ | Open a URL / file / folder | ✅ | ✅ | ✅ | ✅ | ⚠️ |
527
+ | Multiple targets in one call | ✅ | ⚠️ | ⚠️ | ❌ | ⚠️ |
528
+ | Auto `https://` for bare domains | ✅ | ❌ | ❌ | ❌ | ❌ |
529
+ | Bookmarks / aliases | ✅ | ❌ | ❌ | ❌ | ❌ |
530
+ | Web search shortcut | ✅ | ❌ | ❌ | ❌ | ❌ |
531
+ | Open from clipboard | ✅ | ❌ | ❌ | ❌ | ❌ |
532
+ | Reveal in file manager | ✅ | ❌ | ⚠️ `-R` | ⚠️ | ❌ |
533
+ | Recent / interactive picker | ✅ | ❌ | ❌ | ❌ | ❌ |
534
+ | Dry-run preview | ✅ | ❌ | ❌ | ❌ | ❌ |
535
+ | Read from stdin (pipe) + type detect | ✅ | ❌ | ❌ | ❌ | ❌ |
536
+ | Choose a specific app + pass args | ✅ | ❌ | ⚠️ `-a` | ⚠️ | ⚠️ |
537
+ | Wait for app to exit | ✅ | ❌ | ⚠️ `-W` | ❌ | ❌ |
538
+ | Friendly errors + typed exit codes | ✅ | ❌ | ❌ | ❌ | ⚠️ |
539
+
540
+ ✅ built-in · ⚠️ partial / manual / platform-specific · ❌ not available
541
+
542
+ ### Same task, side by side
543
+
544
+ The value shows up most when you compare the actual commands for the same job.
545
+
546
+ | Task | summon | Native / DIY |
547
+ | --- | --- | --- |
548
+ | Open a URL, any OS | `summon https://x.com` | `open …` / `start …` / `xdg-open …` (pick per OS) |
549
+ | Open a bare domain | `summon x.com` | `open https://x.com` (must add scheme yourself) |
550
+ | Open 3 files at once | `summon a b c` | `open a; open b; open c` (or a loop) |
551
+ | URL in Chrome incognito | `summon x.com -- 'google chrome' --incognito` | `open -a "Google Chrome" --args --incognito x.com` (macOS-only syntax) |
552
+ | Reveal a file | `summon f -r` | `open -R f` / `explorer /select,f` / — |
553
+ | Search the web | `summon -s "query"` | build the search URL by hand, then open it |
554
+ | Open clipboard URL (macOS) | `summon -c` | `open "$(pbpaste)"` |
555
+ | Open clipboard URL (Linux) | `summon -c` | `xdg-open "$(xclip -o -selection clipboard)"` |
556
+ | Preview without launching | `summon x.com --dry-run` | no native equivalent |
557
+ | Pipe + auto-detect type | `cat f \| summon` | no native equivalent |
558
+
559
+ ## Efficiency
560
+
561
+ `summon` is designed to add as little overhead as possible on top of the native OS handler.
562
+
563
+ - **Direct opens do no disk I/O of their own.** For `summon <file|url>` there's no buffering and no temp file — it parses arguments and delegates straight to the OS.
564
+ - **Stdin is streamed, then written once.** Piped data is consumed as a stream and written to exactly one temp file; no intermediate copies.
565
+ - **Detection reads only the header.** File-type detection inspects the leading bytes, so it stays fast even for large inputs.
566
+ - **Config reads are lazy and tiny.** Bookmarks/history are small JSON files read only when needed; a corrupt file falls back to defaults instead of crashing.
567
+
568
+ | Path | Extra memory | Extra disk writes |
569
+ | --- | --- | --- |
570
+ | `summon <url>` / `<file>` | negligible | none |
571
+ | `summon @bookmark` / `-s query` | negligible | 1 small history write |
572
+ | `… \| summon` | ~size of piped data | 1 temp file (+ history write) |
573
+
574
+ > These describe the tool's architecture and relative overhead, not benchmarked timings — actual launch latency is dominated by the target app and the OS.
575
+
576
+ ### Benchmark it yourself
577
+
578
+ Want real numbers on your machine? Use `--dry-run` to measure `summon`'s own overhead without launching (and juggling) GUI apps, ideally with [hyperfine](https://github.com/sharkdp/hyperfine):
579
+
580
+ ```sh
581
+ # summon's own overhead (parse + resolve + classify, no app launch)
582
+ hyperfine --warmup 3 'summon https://example.com --dry-run'
583
+
584
+ # compare against a bare Node startup baseline
585
+ hyperfine --warmup 3 'node -e ""'
586
+ ```
587
+
588
+ The gap between those two is essentially all of `summon`. Most of the wall-clock time you feel when actually opening something is the target application starting up, which no launcher can avoid.
589
+
590
+ ## Exit codes
591
+
592
+ | Code | Meaning |
593
+ | --- | --- |
594
+ | `0` | Success (or nothing selected in a picker) |
595
+ | `1` | Generic/unexpected error |
596
+ | `2` | File or path not found |
597
+ | `3` | Unknown bookmark |
598
+ | `4` | Bad usage (empty clipboard, missing query/target, nothing to open) |
599
+
600
+ ## Platform support
601
+
602
+ | Platform | Underlying mechanism | Notes |
603
+ | --- | --- | --- |
604
+ | macOS | `open` | `--wait`, `--background`, and `--reveal` fully supported |
605
+ | Windows | `start` / `explorer` | `--background` is a no-op (macOS-only) |
606
+ | Linux | `xdg-open` + desktop tools | `--reveal` opens the containing folder |
607
+ | Android (Termux) | `termux-open` | via the `open` library |
608
+
609
+ Node.js **20+** is required.
610
+
611
+ ## Supported stdin file types
612
+
613
+ When you pipe data in, `summon` sniffs the format from the raw bytes and picks a matching extension automatically — covering **100+ formats**:
614
+
615
+ - **Images** — PNG, JPEG, GIF, WebP, AVIF, HEIC, TIFF, BMP, ICO
616
+ - **Video** — MP4, MKV, WebM, MOV, AVI
617
+ - **Audio** — MP3, FLAC, WAV, OGG, AAC, M4A
618
+ - **Documents** — PDF
619
+ - **Archives** — ZIP, GZIP, TAR, 7z, RAR, XZ, ZSTD
620
+ - …and many more.
621
+
622
+ See the full list in the [`file-type` supported formats](https://github.com/sindresorhus/file-type#supported-file-types). If a format can't be detected (e.g. plain text), pass `--extension`.
623
+
624
+ ## FAQ & troubleshooting
625
+
626
+ **`summon` opens nothing / errors on Linux.**
627
+ Ensure a desktop environment and `xdg-utils` are installed (`sudo apt install xdg-utils`).
628
+
629
+ **Clipboard mode fails on a headless Linux box.**
630
+ Install a clipboard backend such as `xclip`, `xsel`, or `wl-clipboard`.
631
+
632
+ **Piped text opens as `.txt` even though it's something else.**
633
+ Plain text has no magic bytes to detect. Use `--extension` to force the type.
634
+
635
+ **How do I use `summon` as my Git editor?**
636
+
637
+ ```sh
638
+ git config --global core.editor "summon --wait"
639
+ ```
640
+
641
+ **A non-existent `report.pdf` didn't open a website — good?**
642
+ Yes. Names ending in a known file extension are treated as files, so typos give a clear "not found" (exit code 2) instead of launching a browser.
643
+
644
+ ## Related
645
+
646
+ - [open](https://github.com/sindresorhus/open) — the programmatic API that powers this CLI.
647
+
648
+ ## Author
649
+
650
+ Built by **Aditya Pandey**.
651
+
652
+ ## License
653
+
654
+ [MIT](license) © Aditya Pandey