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/cli.js +275 -0
- package/completions/summon.bash +37 -0
- package/completions/summon.fish +20 -0
- package/completions/summon.ps1 +30 -0
- package/completions/summon.zsh +38 -0
- package/lib/config.js +127 -0
- package/lib/picker.js +43 -0
- package/lib/resolve.js +198 -0
- package/lib/reveal.js +52 -0
- package/license +9 -0
- package/package.json +77 -0
- package/readme.md +654 -0
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
|
+
[](https://www.npmjs.com/package/summon-open)
|
|
17
|
+
[](https://nodejs.org)
|
|
18
|
+
[](license)
|
|
19
|
+
[](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
|