summon-open
v1.1.2
Published
Open URLs, files, folders, and apps from one cross-platform command — with bookmarks, search, clipboard, reveal, dry-run, and stdin support.
Maintainers
Readme
___ _ _ _ __ ___ _ __ ___ ___ _ __
/ __| | | | '_ ` _ \| '_ ` _ \ / _ \| '_ \
\__ \ |_| | | | | | | | | | | | (_) | | | |
|___/\__,_|_| |_| |_|_| |_| |_|\___/|_| |_|
Open URLs, files, folders, and apps from one cross-platform command.
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.
$ summon github.com # scheme added automatically
$ summon report.pdf photo.png notes.txt # open several things at once
$ summon @docs # open a saved bookmark
$ summon -s "how to center a div" # search the web
$ summon report.pdf --reveal # highlight it in your file manager
$ cat diagram.png | summon # pipe raw bytes straight inTable of Contents
- Why summon
- Features
- Install
- Quick start
- Cheatsheet
- Usage
- Options
- Features in depth
- Recipes
- Configuration
- Shell completions
- How it works
- Comparison
- Efficiency
- Exit codes
- Platform support
- Supported stdin file types
- FAQ & troubleshooting
- Related
- Author
- License
Why summon
Every operating system has its own way to "open the default thing":
| OS | Native command |
| --- | --- |
| macOS | open |
| Windows | start |
| Linux | xdg-open |
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.
# Instead of this…
case "$(uname)" in
Darwin) open "$url" ;;
Linux) xdg-open "$url" ;;
*) start "$url" ;;
esac
# …just write this
summon "$url"Features
- Cross-platform — identical behavior on macOS, Windows, and Linux (Android via Termux too).
- Opens anything — URLs, files, folders, and executables.
- Multiple targets —
summon a.pdf b.png https://x.comopens them all. - Smart URL normalization —
summon github.comjust works; thehttps://is added for you. - Bookmarks — save aliases (
summon @docs) and turnsummoninto a daily driver. - Web search —
summon -s "query"searches with a configurable engine (-e mdn,-e npm, …). - Clipboard mode —
summon -copens whatever URL/path you just copied. - Reveal —
summon -r filehighlights it in Finder/Explorer/your file manager. - Recent + fuzzy picker — re-open recent items or fuzzy-search a menu of bookmarks/history.
- Dry run —
--dry-runprints exactly what would happen without doing it. - Pick the app — force a specific app and pass it arguments.
- Pipe-friendly — stream data over stdin; the file type is auto-detected.
- Friendly errors + exit codes — scripts can branch on what went wrong.
Install
Requires Node.js 20 or newer.
npm install --global summon-openThis installs the summon command. Or run it once without installing:
npx summon-open https://github.comHomebrew (macOS/Linux):
brew install --formula https://raw.githubusercontent.com/Aditya060806/summon/main/dist/homebrew/summon-open.rbScoop (Windows):
scoop install https://raw.githubusercontent.com/Aditya060806/summon/main/dist/scoop/summon-open.jsonBoth channels install the same summon command and depend on Node.js. The manifests live in dist/.
Quick start
# Open a URL in your default browser
summon https://github.com
# Bare domains work too — https:// is added automatically
summon github.com
# Open a file, a folder, and a URL at once
summon report.pdf ./project https://news.ycombinator.com
# Open a URL in a specific browser with flags
summon https://github.com -- 'google chrome' --incognito
# Save and reuse bookmarks
summon https://docs.example.com --save docs
summon @docs
# Search the web
summon -s "rust async traits"
# Open whatever URL is on your clipboard
summon --clipboard
# Reveal a file in your file manager
summon report.pdf --reveal
# See what would happen, without doing it
summon github.com --dry-run
# Pipe data in and let summon detect the type
cat photo.png | summon
echo '<h1>Unicorns!</h1>' | summon --extension=htmlCheatsheet
The whole tool at a glance — task on the left, command on the right.
| I want to… | Command |
| --- | --- |
| Open a URL | summon https://example.com |
| Open a bare domain | summon example.com |
| Open a file | summon report.pdf |
| Open a folder | summon . |
| Open several things | summon a.pdf b.png https://x.com |
| Open in a specific app | summon url -- firefox |
| Open with app flags | summon url -- 'google chrome' --incognito |
| Save a bookmark | summon https://docs.example.com --save docs |
| Open a bookmark | summon @docs |
| List bookmarks | summon --bookmarks |
| Remove a bookmark | summon --remove-bookmark docs |
| Search the web | summon -s "query here" |
| Search with a specific engine | summon -s "flatMap" -e mdn |
| List search engines | summon --engines |
| Open clipboard URL | summon -c |
| Reveal in file manager | summon report.pdf -r |
| Re-open something recent | summon --recent |
| Preview without opening | summon url --dry-run |
| Wait for the app to close | summon file --wait |
| Open piped data | cat photo.png \| summon |
| Open piped text as HTML | echo '<h1>Hi</h1>' \| summon --extension=html |
Usage
$ summon --help
Usage
$ summon <file|url|@bookmark> … [options] [-- <app> [args]]
$ cat <file> | summon [--extension] [options] [-- <app> [args]]
Options
--wait, -w Wait for the app to exit
--background Do not bring the app to the foreground (macOS only)
--extension File extension for when stdin file type cannot be detected
--dry-run, -n Print what would be opened without opening it
--search, -s Treat the input as a search query
--engine, -e Search engine to use with --search (see --engines)
--engines List available search engines
--clipboard, -c Open the URL/path currently on the clipboard
--reveal, -r Reveal the file/folder in your file manager
--recent Pick from recently opened items
--save <name> Save the given target as a bookmark (does not open)
--remove-bookmark Remove a saved bookmark by name
--bookmarks List saved bookmarks
Examples
$ summon https://sindresorhus.com
$ summon github.com # scheme added automatically
$ summon report.pdf photo.png notes.txt
$ summon https://github.com -- 'google chrome' --incognito
$ summon @docs # open a saved bookmark
$ summon https://docs.example.com --save docs
$ summon -s "rust async traits"
$ summon -s "flatMap" -e mdn
$ echo '<h1>Hi</h1>' | summon --extension=html
$ summon report.pdf --reveal
$ summon --recentOptions
| Flag | Short | Type | Default | Description |
| --- | --- | --- | --- | --- |
| --wait | -w | boolean | false | Wait for the opened app to exit before returning. Great for using summon as a $EDITOR. |
| --background | | boolean | false | Open without bringing the app to the foreground. macOS only. |
| --extension | | string | auto | Extension to use for piped stdin when the type can't be auto-detected. |
| --dry-run | -n | boolean | false | Print what would be opened without launching anything. |
| --search | -s | boolean | false | Treat the input as a web search query. |
| --engine <name> | -e | string | config | Search engine to use with --search. See --engines. |
| --engines | | boolean | false | List available search engines (* marks the default). |
| --clipboard | -c | boolean | false | Open the URL/path currently on the clipboard. |
| --reveal | -r | boolean | false | Reveal/highlight the file or folder in the file manager. |
| --recent | | boolean | false | Interactively pick from recently opened items. |
| --save <name> | | string | | Save the given target as a bookmark. Does not open it. |
| --remove-bookmark <name> | | string | | Remove a saved bookmark. |
| --bookmarks | | boolean | false | List saved bookmarks. |
| -- <app> [args] | | — | — | Everything after -- selects a specific app and forwards arguments to it. |
Features in depth
Multiple targets
Pass as many files/URLs/bookmarks as you like — they're opened in order:
summon index.html styles.css https://caniuse.comSmart URL normalization
If an argument looks like a bare domain (and isn't an existing file), summon adds https:// for you:
summon github.com # → https://github.com
summon localhost:3000 # → https://localhost:3000Existing 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.
Bookmarks
Save frequently used targets and open them by alias:
summon https://github.com/Aditya060806/summon --save repo
summon @repo # explicit alias form
summon repo # bare form also works
summon --bookmarks # list them
summon --remove-bookmark repoBookmarks live in your config file and can also be edited by hand.
Web search
summon -s "how to exit vim"Pick an engine per search with --engine/-e, and list what's available with --engines:
summon -s "flatMap" -e mdn
summon -s "left-pad" -e npm
summon --enginesBuilt-in engines include google (default), ddg, bing, brave, npm, gh, mdn, so, yt, and wiki. Add your own or change the default in Configuration.
Clipboard
Copy a URL or path anywhere, then:
summon --clipboardMultiple whitespace-separated entries on the clipboard are each opened.
On Linux this uses
xsel/xclip/wl-clipboardunder the hood (install one if clipboard access fails on a headless machine).
Reveal in file manager
Instead of opening a file, highlight it where it lives:
summon report.pdf --reveal- macOS —
open -R(selects the file in Finder) - Windows —
explorer /select,(selects the file in Explorer) - Linux/other — opens the containing folder
Recent & fuzzy picker
summon remembers what you open. Re-open something recent:
summon --recentRun summon with no arguments in a terminal and it shows an interactive fuzzy picker of your bookmarks and recent items. Just start typing to filter (fuzzy, so ghb matches github), enter a number to select from the visible list, or press Enter on an empty line to cancel. When your filter narrows to a single match, it's selected automatically.
Dry run
Preview actions without side effects — perfect for scripts and for building trust:
$ summon github.com report.pdf --dry-run
[dry-run] open: https://github.com
[dry-run] open: report.pdfChoosing the app
Everything after -- becomes the app and its arguments:
summon https://example.com -- firefox
summon https://example.com -- 'google chrome' --incognitoStdin
Pipe data in and summon detects the format from the raw bytes, writes a temp file, and opens it:
cat unicorn.png | summon
echo '{"hi":true}' | summon --extension=jsonRecipes
Real-world ways people wire summon into their day.
Use it as your Git editor (waits until you close the file):
git config --global core.editor "summon --wait"Open the current directory in your file manager:
summon .Open a build artifact as soon as it's ready:
npm run build && summon dist/index.htmlPreview a generated report from a script, or pipe it straight in:
node make-report.js > out.html && summon out.html
node make-report.js | summon --extension=htmlOpen every changed file from your last commit:
git diff --name-only HEAD~1 | xargs summonQuick project bookmarks:
summon https://github.com/Aditya060806/summon --save repo
summon https://github.com/Aditya060806/summon/issues --save issues
summon @issuesSearch from the terminal without leaving your flow:
summon -s "mdn array flatMap"Open a link you just copied from a chat/email:
summon --clipboardDry-run in CI to assert what a script would open (no GUI needed):
summon "$ARTIFACT_URL" --dry-run # prints the target, exits 0Configuration
summon stores its config and history in a per-user directory:
| Platform | Location |
| --- | --- |
| Linux/macOS | $XDG_CONFIG_HOME/summon or ~/.config/summon |
| Windows | %APPDATA%\summon |
You can override it with the SUMMON_CONFIG_DIR environment variable (also handy for testing).
config.json
{
"bookmarks": {
"docs": "https://docs.example.com",
"repo": "https://github.com/Aditya060806/summon"
},
"defaultSearchEngine": "ddg",
"searchEngines": {
"work": "https://intranet.example.com/search?q=%s",
"scholar": "https://scholar.google.com/scholar?q=%s"
}
}bookmarks— map of alias → target. Managed via--save/--remove-bookmark, or edited by hand.searchEngines— map of engine name → URL template, where%sis replaced by the URL-encoded query. These are merged with the built-ins (google,ddg,bing,brave,npm,gh,mdn,so,yt,wiki), so you can add new ones or override existing ones.defaultSearchEngine— the engine--searchuses when--engineisn't given (default:google).
A legacy single
"searchEngine": "…"string is still honored and appears as thecustomengine.
history.json stores your most recently opened targets (capped, de-duplicated) and powers --recent.
Shell completions
Completion scripts live in the completions/ folder.
Bash — add to ~/.bashrc:
source /path/to/summon/completions/summon.bashZsh — put summon.zsh on your $fpath as _summon, or source it from ~/.zshrc:
source /path/to/summon/completions/summon.zshFish — copy to your completions dir:
cp /path/to/summon/completions/summon.fish ~/.config/fish/completions/PowerShell — add to your $PROFILE:
. /path/to/summon/completions/summon.ps1Completions include all flags and dynamically complete your saved bookmark names.
How it works
summon is a small, dependable layer on top of the battle-tested open library.
┌──────────────────────────┐
│ summon <inputs> │
└────────────┬─────────────┘
│
management flag? │ (--bookmarks / --save / --remove-bookmark)
┌───────────────────┴───────────────────┐
YES NO
│ │
read/write config.json what are we opening?
then exit ┌───────────────┼───────────────┐
clipboard search inputs / stdin
│ │ │
read clipboard build search URL expand bookmarks
└───────────────┴───────────────┘
│
for each target: expand @bookmark → classify
│
┌───────────────────────────┼───────────────────────────┐
exists on disk? is a URL? looks like domain?
│ file │ url │ add https://
└───────────────────────────┼───────────────────────────┘
│
--dry-run? print · --reveal? highlight
│
open(target, {wait, background, app})
│
OS default handler (macOS open · Windows start · Linux xdg-open)For piped input, summon buffers stdin, sniffs the file type from the leading bytes with file-type, writes one temp file via tempy, and opens that.
Comparison
Feature matrix
How summon stacks up against common alternatives:
| Capability | summon | xdg-open | open (macOS) | start (Windows) | shell case script |
| --- | :---: | :---: | :---: | :---: | :---: |
| Works on macOS / Windows / Linux | ✅ | ❌ | macOS only | Win only | ⚠️ manual |
| One identical command everywhere | ✅ | ❌ | ❌ | ❌ | ❌ |
| Open a URL / file / folder | ✅ | ✅ | ✅ | ✅ | ⚠️ |
| Multiple targets in one call | ✅ | ⚠️ | ⚠️ | ❌ | ⚠️ |
| Auto https:// for bare domains | ✅ | ❌ | ❌ | ❌ | ❌ |
| Bookmarks / aliases | ✅ | ❌ | ❌ | ❌ | ❌ |
| Web search shortcut | ✅ | ❌ | ❌ | ❌ | ❌ |
| Configurable search engines | ✅ | ❌ | ❌ | ❌ | ❌ |
| Fuzzy interactive picker | ✅ | ❌ | ❌ | ❌ | ❌ |
| Open from clipboard | ✅ | ❌ | ❌ | ❌ | ❌ |
| Reveal in file manager | ✅ | ❌ | ⚠️ -R | ⚠️ | ❌ |
| Recent / interactive picker | ✅ | ❌ | ❌ | ❌ | ❌ |
| Dry-run preview | ✅ | ❌ | ❌ | ❌ | ❌ |
| Read from stdin (pipe) + type detect | ✅ | ❌ | ❌ | ❌ | ❌ |
| Choose a specific app + pass args | ✅ | ❌ | ⚠️ -a | ⚠️ | ⚠️ |
| Wait for app to exit | ✅ | ❌ | ⚠️ -W | ❌ | ❌ |
| Friendly errors + typed exit codes | ✅ | ❌ | ❌ | ❌ | ⚠️ |
✅ built-in · ⚠️ partial / manual / platform-specific · ❌ not available
Same task, side by side
The value shows up most when you compare the actual commands for the same job.
| Task | summon | Native / DIY |
| --- | --- | --- |
| Open a URL, any OS | summon https://x.com | open … / start … / xdg-open … (pick per OS) |
| Open a bare domain | summon x.com | open https://x.com (must add scheme yourself) |
| Open 3 files at once | summon a b c | open a; open b; open c (or a loop) |
| URL in Chrome incognito | summon x.com -- 'google chrome' --incognito | open -a "Google Chrome" --args --incognito x.com (macOS-only syntax) |
| Reveal a file | summon f -r | open -R f / explorer /select,f / — |
| Search the web | summon -s "query" | build the search URL by hand, then open it |
| Open clipboard URL (macOS) | summon -c | open "$(pbpaste)" |
| Open clipboard URL (Linux) | summon -c | xdg-open "$(xclip -o -selection clipboard)" |
| Preview without launching | summon x.com --dry-run | no native equivalent |
| Pipe + auto-detect type | cat f \| summon | no native equivalent |
vs other npm openers
The npm ecosystem has a few ways to open things. summon builds on the excellent open library (the programmatic API) and starts from open-cli, then adds a workflow layer on top.
| Capability | summon | open-cli | opener | open |
| --- | :---: | :---: | :---: | :---: |
| Ships a CLI command | ✅ | ✅ | ✅ | ❌ (library) |
| Cross-platform | ✅ | ✅ | ✅ | ✅ |
| Open URL / file / folder / app | ✅ | ✅ | ✅ | ✅ (API) |
| Choose app + pass args (-- app …) | ✅ | ✅ | ❌ | ✅ (API) |
| Wait / background | ✅ | ✅ | ❌ | ✅ (API) |
| Stdin + file-type detection | ✅ | ✅ | ❌ | ❌ |
| Multiple targets in one call | ✅ | ❌ | ❌ | ❌ |
| Auto https:// for bare domains | ✅ | ❌ | ❌ | ❌ |
| Bookmarks / aliases | ✅ | ❌ | ❌ | ❌ |
| Web search + configurable engines | ✅ | ❌ | ❌ | ❌ |
| Open from clipboard | ✅ | ❌ | ❌ | ❌ |
| Reveal in file manager | ✅ | ❌ | ❌ | ❌ |
| Recent + fuzzy picker | ✅ | ❌ | ❌ | ❌ |
| Dry-run preview | ✅ | ❌ | ❌ | ❌ |
| Typed exit codes + friendly errors | ✅ | ⚠️ | ⚠️ | n/a |
| Shell completions | ✅ | ❌ | ❌ | n/a |
✅ yes · ⚠️ basic/partial · ❌ no · n/a not applicable
In short: reach for open when you need a programmatic API inside Node code; reach for open-cli or opener for a bare "open this one thing" command; reach for summon when you want that same reliability plus multiple targets, bookmarks, search, clipboard, reveal, a fuzzy picker, and dry-run in day-to-day terminal use.
Efficiency
summon is designed to add as little overhead as possible on top of the native OS handler.
- 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. - Stdin is streamed, then written once. Piped data is consumed as a stream and written to exactly one temp file; no intermediate copies.
- Detection reads only the header. File-type detection inspects the leading bytes, so it stays fast even for large inputs.
- 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.
| Path | Extra memory | Extra disk writes |
| --- | --- | --- |
| summon <url> / <file> | negligible | none |
| summon @bookmark / -s query | negligible | 1 small history write |
| … \| summon | ~size of piped data | 1 temp file (+ history write) |
These describe the tool's architecture and relative overhead, not benchmarked timings — actual launch latency is dominated by the target app and the OS.
Benchmark it yourself
Want real numbers on your machine? Use --dry-run to measure summon's own overhead without launching (and juggling) GUI apps, ideally with hyperfine:
# summon's own overhead (parse + resolve + classify, no app launch)
hyperfine --warmup 3 'summon https://example.com --dry-run'
# compare against a bare Node startup baseline
hyperfine --warmup 3 'node -e ""'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.
Exit codes
| Code | Meaning |
| --- | --- |
| 0 | Success (or nothing selected in a picker) |
| 1 | Generic/unexpected error |
| 2 | File or path not found |
| 3 | Unknown bookmark |
| 4 | Bad usage (empty clipboard, missing query/target, nothing to open) |
Platform support
| Platform | Underlying mechanism | Notes |
| --- | --- | --- |
| macOS | open | --wait, --background, and --reveal fully supported |
| Windows | start / explorer | --background is a no-op (macOS-only) |
| Linux | xdg-open + desktop tools | --reveal opens the containing folder |
| Android (Termux) | termux-open | via the open library |
Node.js 20+ is required.
Supported stdin file types
When you pipe data in, summon sniffs the format from the raw bytes and picks a matching extension automatically — covering 100+ formats:
- Images — PNG, JPEG, GIF, WebP, AVIF, HEIC, TIFF, BMP, ICO
- Video — MP4, MKV, WebM, MOV, AVI
- Audio — MP3, FLAC, WAV, OGG, AAC, M4A
- Documents — PDF
- Archives — ZIP, GZIP, TAR, 7z, RAR, XZ, ZSTD
- …and many more.
See the full list in the file-type supported formats. If a format can't be detected (e.g. plain text), pass --extension.
FAQ & troubleshooting
summon opens nothing / errors on Linux.
Ensure a desktop environment and xdg-utils are installed (sudo apt install xdg-utils).
Clipboard mode fails on a headless Linux box.
Install a clipboard backend such as xclip, xsel, or wl-clipboard.
Piped text opens as .txt even though it's something else.
Plain text has no magic bytes to detect. Use --extension to force the type.
How do I use summon as my Git editor?
git config --global core.editor "summon --wait"A non-existent report.pdf didn't open a website — good?
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.
summon url -- firefox ignores the app on Windows PowerShell.
PowerShell strips the -- token before it reaches the command (this affects all native commands, not just summon). Work around it by running from cmd, invoking the shim explicitly as summon.cmd url -- firefox, or using PowerShell's stop-parsing token: summon --% https://x.com -- firefox. On macOS/Linux shells and via cmd, -- works as documented.
Releasing
Maintainers: releases publish to npm automatically when a version tag is pushed (see .github/workflows/release.yml).
One-time: add an npm automation token as the
NPM_TOKENrepository secret.Cut a release:
npm version patch # or minor / major — bumps package.json and tags git push --follow-tags
The workflow runs the tests, then publishes with npm provenance. See the changelog for release history.
Related
- open — the programmatic API that powers this CLI.
Author
Built by Aditya Pandey.
License
MIT © Aditya Pandey
