nudge 0.1.0 a CLI for macOS

Let your AI agent show you things.

curl -fsSL https://nudge.reintelligence.live/install.sh | sh
  • macOS 13+ on Apple Silicon
  • 397 KB
  • Free to use
$ nudge -m "Here's the signup chart you asked for" chart.png
A preview window opens on the Mac. You look, press Download, close it.{"status":"saved","saved":["/Users/me/Downloads/chart.png"]}

$ some-tool --render-png | nudge -m "Latest traffic" -
You glance at it and close the window.{"status":"dismissed","saved":[]}

$ 

How it works

  1. The agent runs nudge

    An AI agent such as Claude Code, or any script, runs nudge -m "why" file… on your Mac. Several files can go in one call.

  2. A window opens on your Mac

    A native preview, with the agent's note on top. You can Download a copy, Save As… somewhere else, or Open it in its default app.

  3. The agent reads the result

    When you close the window, nudge prints one line of JSON: whether you kept a copy, and the absolute path of each one.

For AI agents

Add this to your agent's instructions file or system prompt.

instructions.md
To show the user a file (image, PDF, chart, report, HTML, …), run `nudge`:
- `nudge -m "<one line on why>" <file>...` opens a preview window on their desktop
  and waits until they close it, then prints JSON like
  `{"status":"saved","saved":["/Users/…/Downloads/x.png"]}`.
- Pipe generated content with `<cmd> | nudge --name result.png -`.
- If your shell tool has a timeout, add `--timeout 300`, or use
  `--detach --result-file /tmp/nudge.json` and read that file later.
- status `saved` means they kept a copy; `dismissed` means they closed it.
- Run `nudge --list-sounds` once and add `--open-sound <name>` with the sound that
  fits the moment (e.g. `done`, `need-your-input`).

Features

Any Quick Look format

Images, PDFs, text, code, Markdown, JSON, HTML, video, audio and Office files: anything Quick Look understands.

Save

Save As… picks a place. Download copies into ~/Downloads. Or drag the icon out of the title bar.

Sounds

Name your sound files done.mp3 or need-your-input.mp3, and agents pick the one that fits when a window opens.

Reads stdin

Pipe generated content in with -. nudge detects PNG, JPEG, GIF, WebP, HEIC, PDF, SVG, HTML, JSON and text.

$ curl -s https://example.com/chart.png \
    | nudge -m "Latest traffic" -

Timeout and detach

--timeout closes the window on its own. --detach returns at once, and --result-file collects the outcome later.

$ nudge --detach --timeout 600 \
    --result-file /tmp/r.json build/index.html
{"status":"shown","saved":[],"pid":6272}

Install

$ curl -fsSL https://nudge.reintelligence.live/install.sh | sh
Downloading nudge 0.1.0…
Installed nudge 0.1.0 to ~/.local/bin/nudge.
Added ~/.local/bin to your PATH in ~/.zshrc. Open a new terminal to use it.
Try it:  nudge -m "Hello from nudge"

Installer

  • Checks for macOS 13+ on Apple Silicon.
  • Downloads the latest release and verifies its SHA-256.
  • Installs to ~/.local/bin/nudge, without sudo.
  • Adds ~/.local/bin to your PATH if needed.
Installer optionEffect
NUDGE_INSTALL_DIR=<dir>Install somewhere else
NUDGE_NO_MODIFY_PATH=1Leave your shell profile alone
NUDGE_VERSION=<version>Install a specific version

Uninstall

nudge --uninstall

Usage

nudge [options] <file>..., <command> | nudge [options] - or nudge --message <text>. By default nudge waits until the window closes.

examples
# show a file and wait for the window to close
$ nudge report.pdf

# several files in one window, with a note on top
$ nudge -m "Which logo do you prefer?" logo-a.png logo-b.png logo-c.png

# content from stdin; the type is detected
$ curl -s https://example.com/chart.png | nudge -m "Latest traffic" -

# stdin with an explicit name
$ some-tool --svg | nudge --name diagram.svg -

# just a message, with an OK button
$ nudge -m "The deploy finished."

# return at once; collect the result later
$ nudge --detach --timeout 600 --result-file /tmp/r.json build/index.html
OptionWhat it does
-m, --message <text>Note shown above the preview, e.g. why you're showing it
-t, --title <text>Window title (default: the file name)
-d, --save-dir <dir>Folder Download copies into (default: $NUDGE_SAVE_DIR, else ~/Downloads)
-n, --name <name>File name for stdin content (default: nudge-<time>.<type>, with the type detected from the content)
--timeout <seconds>Close the window automatically after this long
--detachDon't wait: print {"status":"shown","pid":…} and return
--result-file <path>Also write the final JSON result to this file (lets you collect the outcome after --detach)
--open-sound <sound>Play a sound when the window opens: a name from your sounds folder, a macOS sound like Glass, or the path to an audio file. Default: $NUDGE_OPEN_SOUND; none = off
--list-soundsList the sounds you can play by name
--on-topKeep the window above other windows
--updateUpdate nudge to the latest version
--uninstallRemove nudge and the PATH line its installer added
-h, --helpShow the help
-v, --versionShow the version
In the windowKey
Download⌘S
Save As…⇧⌘S
Open in default app⌘O
Previous / next file⌘[ ⌘]
CloseEsc or ⌘W
EnvironmentMeaning
NUDGE_SAVE_DIRFolder Download copies into (default ~/Downloads)
NUDGE_OPEN_SOUNDSound for every window; --open-sound overrides it
NUDGE_SOUNDS_DIRYour sound folder (default ~/.config/nudge/sounds, or $XDG_CONFIG_HOME/nudge/sounds)

Sounds

--open-sound plays a sound when the window opens: a name from your sound folder (~/.config/nudge/sounds), a built-in macOS sound, or the path to an audio file. --open-sound none silences one call.

$ nudge --list-sounds
Sounds in ~/.config/nudge/sounds (play one with --open-sound <name>):
  done
  need-your-input
Built-in: Basso, Blow, Bottle, Frog, Funk, Glass, Hero, Morse, Ping, Pop, Purr, Sosumi, Submarine, Tink

$ nudge --open-sound need-your-input -m "Which option should I go with?" a.pdf b.pdf

# in your shell profile: a sound on every nudge
export NUDGE_OPEN_SOUND=done

Result

When the window closes, nudge prints one line of JSON. With --result-file, the same line also goes to that file.

stdout
{"status":"saved","saved":["/Users/me/Downloads/chart.png"]}
{"status":"dismissed","saved":[]}
{"status":"timeout","saved":[]}
{"status":"interrupted","saved":[]}
{"status":"shown","saved":[],"pid":6272}
statusMeaning
savedYou downloaded or saved at least one copy, then closed the window
dismissedClosed without saving
timeout--timeout ran out
interruptednudge received SIGINT, SIGTERM or SIGHUP
shown--detach: the window is open and nudge returned right away
ExitMeaning
0The window was shown, whatever the person did
1Error: missing file, empty stdin, no desktop session, unplayable --open-sound
2Bad usage
  • saved lists every copy, Download and Save As… alike, as absolute paths. It's kept on timeout and interrupt too.
  • Opening the file in its default app isn't reported; status covers copies only.
  • Errors print no JSON. The message goes to stderr, e.g. nudge: no such file: /nope.png.