Skip to content

Latest commit

 

History

167 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

hey-cli

⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣠⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⡿⠏⠻⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣶⣶⣤⠀⠀⠀⣿⠃⠀⠀⠘⣿⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⠉⠹⣷⣄⠀⣿⡀⠀⠀⠀⠈⢿⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣶⣶⣶⣶⣶⠀⠀⠀⠀⠀⠀⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⡀⠀⠀⠀⠀⢠⣶⣶⣶⣶⣶⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⠀⠀⣿⡆⠀⠘⣿⣦⣿⡇⠀⠀⠀⠀⠘⣿⡆⠀⠀⢀⣀⣀⣀⡀⠀⠸⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⠀⠀⠀⠀⣾⣿⣿⣿⣿⠃⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⣾⡿⣷⣄⢻⣧⠀⠀⠈⢿⣿⣷⡆⠀⠀⠀⠀⢸⣿⣠⣶⠿⠛⠛⠛⣿⣆⠀⢹⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⡏⠉⠉⠉⠉⠉⠉⠙⠻⣿⣿⣿⣿⣆⠀⠀⣸⣿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⣿⡇⠘⢿⣾⣿⡆⠀⠀⠈⢿⣿⣧⠀⠀⠀⠀⠀⣿⣿⠁⠀⠀⠀⠀⢸⣿⠀⠀⣿⣿⣿⣿⣄⣀⣀⣀⣀⣠⣿⣿⣿⣿⣿⣧⣀⣀⣀⣀⡀⠀⠀⠀⢹⣿⣿⣿⣿⡄⢰⣿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⢸⣷⠀⠀⠻⣿⣿⡄⠀⠀⠈⢿⣿⡆⠀⠀⠀⢸⣿⣿⠀⠀⠀⠀⠀⢸⣿⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⢻⣿⣿⣿⣷⣿⣿⣿⣿⠏⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣇⠀⠀⠘⢿⣷⡀⠀⠀⠘⠻⣿⡀⠀⠀⣿⡏⣿⡇⠀⠀⠀⠀⢸⣿⠀⢀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⢻⣿⣿⣿⣿⣿⣿⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⣾⡿⢿⣾⣿⣆⠀⠀⠈⢻⣷⡀⠀⠀⠀⠉⠀⠀⢀⣿⠃⢹⣧⠀⠀⠀⠀⣿⡇⠀⢸⣿⣿⣿⣿⠁⠀⠀⠀⠀⠈⣿⣿⣿⣿⣿⡏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⢹⣧⠀⠙⢿⣿⣆⠀⠀⠀⠹⠷⠀⠀⠀⠀⠀⠀⢸⣿⠀⢸⣿⠀⠀⠀⢸⣿⠀⠀⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣽⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⢿⣧⠀⠀⠙⢿⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⠀⢸⣿⠀⠀⢀⣿⠇⠀⢸⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠈⢻⣷⡀⠀⠀⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣧⣾⡏⠀⠀⣼⡟⠀⠀⠸⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⢻⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⢿⣦⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠻⣷⣦⣄⣀⡀⠀⣀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⠛⠛⠻⠟⠛⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀

A CLI and TUI for HEY.

Read and send emails, manage boxes, calendars, todos, habits, time tracking, and journal entries — all from your terminal.

Install

macOS / Linux / WSL2

curl -fsSL https://hey.com/install-cli | bash

Windows (PowerShell)

irm https://hey.com/install-cli.ps1 | iex

On Windows 11 with Smart App Control, see Troubleshooting if the install is blocked.

Both scripts download the release for your platform, verify its SHA-256 checksum, and — when cosign is installed — verify the release's keyless Sigstore signature (cosign v3 as-is, v2.6+ with --new-bundle-format=true; older versions skip signature verification with a warning). Set HEY_VERSION to pin a release and HEY_BIN_DIR to choose the install directory.

Other installation methods

Homebrew (macOS / Linux):

brew install --cask basecamp/tap/hey

Arch Linux / Omarchy (AUR):

yay -S hey-cli

Linux (deb/rpm/apk):

# Download from https://github.com/basecamp/hey-cli/releases/latest
sudo apt install ./hey-cli_*_linux_amd64.deb                 # Debian/Ubuntu
sudo dnf install ./hey-cli_*_linux_amd64.rpm                 # Fedora/RHEL
sudo apk add --allow-untrusted ./hey-cli_*_linux_amd64.apk   # Alpine

Arm64: substitute arm64 for amd64 in the filename. Verify the SHA-256 checksum from checksums.txt before installing unsigned Alpine packages.

Scoop (Windows):

scoop bucket add basecamp https://github.com/basecamp/homebrew-tap
scoop install hey

Nix:

nix profile install github:basecamp/hey-cli

Go install:

go install github.com/basecamp/hey-cli/cmd/hey@latest

From source (requires Go 1.26+; mise installs the right version):

mise install       # install Go 1.26
make install       # build and install into /usr/local/bin/hey

GitHub Release: download from Releases. Every release ships checksums.txt and a keyless Sigstore signature checksums.txt.bundle, verifiable with:

cosign verify-blob --bundle checksums.txt.bundle \
  --certificate-identity "https://github.com/basecamp/hey-cli/.github/workflows/release.yml@refs/tags/v<VERSION>" \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com checksums.txt

That command is for cosign v3. With cosign v2.6–v2.x add --new-bundle-format=true; older versions cannot verify the bundle.

Upgrading

hey upgrade
hey upgrade 0.2.0-rc.1   # target a specific release, e.g. a prerelease

Upgrading only ever moves forward: a requested version at or below the installed one is a no-op, and package-manager installs always follow their manager's own version (a pinned version is refused there).

What happens depends on how hey was installed:

  • Installer script / tarball (a binary under your home directory, e.g. ~/.local/bin or ~/bin): upgrades in place. hey downloads the release for your platform, verifies its Sigstore signature (the keyless checksums.txt.bundle published by the release pipeline, identity-pinned to the release workflow and tag) and SHA-256 checksum, swaps the executable transactionally, and confirms the installed binary reports the new version. On failure the previous binary is restored; in the worst case — restoration itself fails mid-swap — the error names the preserved backup file next to the binary so you can put it back by hand.
  • Homebrew / Scoop: delegates to brew upgrade --cask basecamp/tap/hey / scoop update hey, then verifies the manager-installed binary actually reports the new version.
  • System packages (apt/dnf/apk, AUR, Nix) and go install builds: never touched. hey upgrade exits nonzero with upgrade guidance for that install method (the exact command where it can be known, e.g. go install or yay -S hey-cli; otherwise which package manager to use).

hey upgrade exits 0 only when there is no update, or the update was applied and confirmed. Every other outcome is a structured failure ("ok": false in JSON) with one of these codes:

Code Meaning
upgrade_required An update exists but hey won't apply it for this install method (or this is not a release build) — the hint carries the right next step
upgrade_incomplete The package manager exited 0 but the binary still reports the old version
upgrade_unverified The upgrade may have worked, but the installed version could not be confirmed
upgrade_failed The update check, download, signature/checksum verification, or executable swap failed — the previous binary remains installed (or the error names the preserved backup if restoration also failed)

hey version prints the installed version; hey version --json adds the commit, build date, Go version and build source (release, go install or dev). hey doctor warns when a newer release is available.

Authentication

# Browser-based OAuth via Launchpad (primary method)
hey auth login

# Or use a pre-generated token
hey auth login --token TOKEN

# Or use a browser session cookie
hey auth login --cookie COOKIE

Tokens refresh automatically on expiry. Credentials are stored in the system keyring (with file fallback at ~/.config/hey-cli/credentials.json).

hey auth status   # check auth status
hey auth token    # print access token for scripting
hey auth refresh  # force token refresh
hey auth logout   # clear credentials

Linked accounts

One HEY login exposes every mail account linked to that identity. List the available filters, persist a default, or select one for a single invocation:

hey accounts list                 # list All Accounts and each linked account
hey accounts use 12345            # persist a linked account as the default mail filter
hey accounts use all              # return to All Accounts
hey --account 12345 boxes         # override the default for one invocation
HEY_ACCOUNT_ID=12345 hey search "quarterly planning"

The default is all. Selection precedence is --account, HEY_ACCOUNT_ID, trusted local .hey/config.json, the global default for the active server, then All Accounts. Global account defaults are stored separately for each server origin, so development and production selections cannot affect one another. Explicit and persisted IDs are validated against the signed-in identity before mail requests, so an unavailable account fails closed.

The first command that would use a repository-local server or account setting asks whether to use it once, always trust its current values, or cancel. Non-interactive and JSON commands fail closed until you explicitly run hey config trust-local from that directory. Changes to the local server or account invalidate trust. Review trust with hey config trusted-locals and remove it with hey config untrust-local.

Compose and contact creation use an individually selected account; replies and forwards use the thread's account. Calendars, todos, habits, time tracking, and journal entries remain identity-wide.

TUI

Run hey tui to launch the interactive terminal UI. Bare hey prints the help. For identities with multiple linked mail accounts, press Ctrl+A to switch between All Accounts and individual email addresses. Switching cancels requests from the previous account and reloads the active section; Calendar and Journal remain identity-wide.

Navigate between Mail, Contacts, Calendar, and Journal. Mail navigation includes HEY boxes followed by your labels. Use n and p to page through a label. Use / to search, Enter to open a thread, r to reply, f to forward, m to move, g to add, create, or remove labels, t to trash, s to mark as spam, - to ignore, and + to stop ignoring. Select threads with Space and press b to preview every bulk-reply recipient before writing and sending one reply to all selected threads. A delayed bulk reply can be recalled with u while HEY's undo window remains open. Search results retain the matching-message summary; use n and p to move between result pages.

Press Ctrl+S from the mail list to open The Screener. When senders are waiting, the mail list says so above the threads. In The Screener, y screens the selected sender in and n screens them out, Tab moves to Screener History and back, [ and ] page through either list, X clears the whole Screener after a confirmation, and Escape or q returns to mail.

Thread attachments always appear with their filename, media type, and size. Use [ and ] to select an attachment, s to save it without replacing an existing file, and o to download and open it in an external application. Attachments never open automatically. Kitty and Ghostty can show inline images. Foot and other terminals use visible text markers.

Press Shift+O to open Contacts. Use Enter to view a contact, a to add, e to edit, n to edit the private note, x twice to delete a note, h to hide, and u to show the most recently hidden contact again. Escape or q goes back.

CLI Commands

Structured data commands support --json for full output and --jq '<expression>' to filter that output without an external jq binary. --jq implies --json and filters the full success envelope; combine it with --quiet to filter result data directly. Errors retain their complete structured envelope. Commands with dedicated raw output (auth token, completion, skill, tui, and --version) reject --jq.

Use --base-url to override the server URL and --account <id|all> to select a linked mail account.

hey boxes --jq '.data[] | {id, name}'
hey boxes --quiet --jq '.[].id'

Email

hey boxes                          # list mailboxes
hey box imbox                      # list email threads in a box (by name or ID)
hey labels                          # list labels and their IDs
hey label 789 --all                 # list all email threads with a label
hey label add 12345 --to 789        # add a label to a thread
hey label create "Travel receipts" 12345  # create and add a label
hey label remove 12345 --from 789   # remove one label
hey label remove 12345 --from all   # remove every label
hey search "quarterly planning"    # search threads and matching messages
hey search --from jane@example.com --date last_30_days  # refine a search
hey search filters                 # list available refinement values
hey contacts list                  # list contacts
hey contacts show 12345            # view a contact and private note
hey contacts add --name "Jane Doe" --email jane@example.com
hey contacts update 12345 --name "Jane Dawson"
hey contacts hide 12345            # hide without permanently deleting
hey contacts show-again 12345      # show a hidden contact again
hey contacts bundle 12345          # group this contact's mail into one row
hey contacts unbundle 12345        # list this contact's mail separately
hey contacts note set 12345 "Prefers email"
hey contacts note delete 12345
hey screener list                  # who is waiting to be screened
hey screener list --count          # just the number waiting
hey screener approve 91            # let a sender through
hey screener approve 91 --box "The Feed"  # let them through, into another box
hey screener deny 91 92            # turn several senders away
hey screener deny 91 --spam        # turn them away and mark what they sent as spam
hey screener history               # who has already been screened
hey screener clear                 # empty the queue without deciding
hey threads 123                    # read a full email thread
hey attachments 123                # list files attached to the thread
hey attachments save 456:1         # save a file using its attachment ID
hey reply 123 -m "Thanks!"        # reply to a thread (or omit -m to open $EDITOR)
hey reply 123 -m "Attached." --attach ./diagram.png
hey bulk-reply preview 12345 67890  # inspect threads and exact To/CC/BCC recipients
hey bulk-reply send 12345 67890 -m "Thanks for the update."
hey bulk-reply undo 98765            # recall a delayed bulk reply
hey forward 123 --to alice@example.com -m "For your review"  # forward the latest message
hey compose --to user@example.com --subject "Hello"  # compose a new message
hey compose --to user@example.com --subject "Report" -m "Attached." --attach ./report.pdf
hey compose --to user@example.com --cc bob@example.com --bcc carol@example.org --subject "Hello"  # with CC/BCC
hey drafts                         # list drafts
hey move 12345 --to feed           # move a thread to another box
hey move 12345 67890 --to "paper trail"  # move multiple threads
hey trash 12345                    # move a thread to Trash
hey spam 12345                     # mark a thread as spam
hey ignore 12345                   # ignore future activity on a thread
hey stop-ignoring 12345            # resume attention for a thread

Search accepts free text plus --required, --any, --none, --exact, --from, --to, --subject, --date, --in, --label, and --attachment. Use --page for one page or --all to fetch up to 100 pages; capped searches report the next page for continuation. Search results include topic_id for reading the thread and the matching message summaries. Results with an active box item also include id for organization actions.

Contact updates preserve omitted name, email, and alias fields. Supplying --alias replaces the complete alias list; --alias= clears it. Contact notes accept positional content, --note, stdin, or $EDITOR. HEY hides contacts rather than permanently deleting them; hidden contacts leave lists, autocomplete, and search, and can be shown again by ID. Bundling groups a contact's mail into one row without merging or deleting the underlying threads; unbundling lists those threads separately again. HEY applies bundling when the contact's current delivery setting supports bundles.

The Screener is where first-time senders wait. hey screener list returns clearance IDs — not contact IDs — with the sender and the subject of what they sent, plus topic_id for reading the thread before deciding. --count asks for the number alone, which is a far cheaper request than the queue. Approving delivers everything the sender has waiting; denying hides it. Either is reversible with the opposite command, and hey screener history shows what was already decided. --box and --seen approve one sender at a time; several IDs go through HEY's bulk endpoint, which takes neither. --spam also trains HEY's filter, which is harder to undo than denying. hey screener clear empties the queue without deciding anything — those senders reappear on their next email.

hey bulk-reply preview is read-only and resolves each posting to its latest replyable entry. hey bulk-reply send resolves the selection again, skips threads without a replyable entry, keeps HEY's server-provided name tag, and returns the exact reply count, delivery ID, delayed state, undo URL, and undo command. Posting IDs must be positive and unique. The message can come from -m, stdin, or $EDITOR; --attach is repeatable.

--attach is repeatable on hey compose, hey reply, and hey bulk-reply send, and attachment-only messages are supported. The CLI validates and uploads every file before sending the email. hey attachments <topic_id> returns stable message-and-position IDs such as 456:1; pass an ID to hey attachments save. Saving uses the original filename by default, accepts --output for a file or directory, and preserves existing files unless --force is set.

Organization actions take the id values returned by hey box --json, hey label --json, or hey search --json. Label IDs come from hey labels; hey label returns next_page and total_count, accepts --page <next_page> for continuation, and supports --all for complete traversal. HEY creates a label while adding it to at least one thread, so hey label create requires thread item IDs. Move destinations are Imbox, The Feed, Set Aside, Reply Later, or Paper Trail. Bubble Up requires a scheduled date and is not available through hey move. Trashing a shared thread removes your access instead of deleting it for everyone. Ignored threads remain in their box and can be restored with hey stop-ignoring.

Watching for changes

hey watch                               # follow every box, a line of JSON per change
hey watch --box imbox --events added    # only new postings in the Imbox
hey watch --box imbox --exit-on-first   # block until something lands, then exit
hey watch --since 2026-08-18T09:00:00Z  # catch up from a time first, then follow
hey watch --run-async 'notify-send "New mail in $HEY_BOX_KIND"'
hey watch --run-sync ./triage.sh        # one at a time, waiting for each

Runs until interrupted, printing changes as they happen, one line each:

{"change":"added","at":"2026-08-18T09:14:22.031Z","box":{"id":24088,"kind":"imbox","name":"Imbox"},"posting_id":98765,"thread_id":54321,"posting":{}}

A change can drive a command instead of being printed, and there's a choice to make between two behaviours — pass one or the other, not both. --run-async spawns the command per change and moves on, so a slow one never holds up the watch and two can overlap. --run-sync waits for each and runs them in order, so they never overlap and a slow one delays the next.

Both hand the JSON to the command on its stdin, and the same fields as HEY_CHANGE, HEY_AT, HEY_BOX_ID, HEY_BOX_KIND, HEY_BOX_NAME, HEY_POSTING_ID and HEY_THREAD_ID. Both also take over stdout, so the JSON isn't printed as well.

Calendars

hey calendars                      # list calendars
hey recordings 1 --starts-on 2026-01-01 --ends-on 2026-01-31  # list events in a calendar

Todos

hey todo list                      # list todos
hey todo add "Buy milk"            # create a todo
hey todo complete 1                # mark done
hey todo uncomplete 1              # mark undone
hey todo delete 1                  # delete

Habits

hey habit complete 1               # mark habit done (today or --date YYYY-MM-DD)
hey habit uncomplete 1             # undo habit completion

Time tracking

hey timetrack start                # start tracking
hey timetrack stop                 # stop tracking
hey timetrack current              # show active track
hey timetrack list                 # list all tracks

Journal

hey journal list                   # list entries
hey journal read                   # read today's entry (or pass YYYY-MM-DD)
hey journal write "..."            # write today's entry (or omit content for $EDITOR)

Agent Skill

hey-cli ships with an embedded agent skill so your agent can interact with HEY on your behalf.

hey skill install   # install the skill globally for your agent

Troubleshooting

hey doctor           # Check CLI health and diagnose issues
hey version --json   # Installed version, commit, build date and build source
hey upgrade          # Upgrade to the latest release (see Upgrading)

Windows: Smart App Control and SmartScreen

To check whether your installed binary is signed:

Get-AuthenticodeSignature (Get-Command hey).Source

Smart App Control (Windows 11) blocks unsigned executables no matter where they were downloaded from, and it has no per-app exceptions — this applies to the PowerShell installer, Scoop installs, and manual downloads alike. If it blocks an unsigned hey.exe, two options:

  1. Use WSL2 (preferred). Install the Linux build inside WSL2 — Smart App Control doesn't apply there and your Windows security setup is untouched: wsl --install, then inside the WSL terminal: curl -fsSL https://hey.com/install-cli | bash
  2. Turn Smart App Control off (Windows Security → App & browser control → Smart App Control settings) and leave it off while using the unsigned build. Because there are no per-app exceptions, turning it back on re-blocks hey.exe on its next run — only re-enable after upgrading to a signed build. Windows 11 with the March/April 2026 updates can re-enable Smart App Control from Windows Security without a reset; on older builds re-enabling requires resetting Windows, so prefer WSL2 there.

SmartScreen (without Smart App Control) may warn on first run of an unrecognized executable — choose "More info" → "Run anyway" if you downloaded the release from this repository.

Development

make build      # build binary
make test       # run tests
make coverage   # run cross-package coverage and enforce the 70.8% floor
make lint       # run golangci-lint
make clean      # remove build artifacts

make coverage writes coverage.out, coverage.func.txt, and coverage.packages.txt, then prints a concise package summary and the lowest-covered functions.

License

This project is licensed under the MIT License. See LICENSE.md for details.

About

HEY CLI and Agent Skills

Topics

Resources

Contributing

Security policy

Stars

120 stars

Watchers

2 watching

Forks

Releases

Used by

Contributors

Languages