---
name: HEY
slug: hey
category: Automation
description: HEY lets you read, search, and send HEY email, and manage contacts, boxes, labels, collections, calendars, todos, habits, time tracking, and journal entries. Use it for any HEY-related question or action.
github: "https://github.com/basecamp/hey-cli/tree/main/skills/hey"
language: Go
stars: 256
forks: 36
install: "npx degit https://github.com/basecamp/hey-cli/tree/main/skills/hey ~/.claude/skills/hey"
installs_to: ~/.claude/skills/hey
source_path: skills/hey/SKILL.md
collection_size: 1
category_size: 1648
added: 2026-09-02T05:20:38.900Z
last_synced: 2026-09-02T05:20:38.900Z
canonical_url: "https://dirskills.com/skills/hey"
---

# HEY

HEY lets you read, search, and send HEY email, and manage contacts, boxes, labels, collections, calendars, todos, habits, time tracking, and journal entries. Use it for any HEY-related question or action.

**Install:**

```bash
npx degit https://github.com/basecamp/hey-cli/tree/main/skills/hey ~/.claude/skills/hey
```

## README

# /hey - HEY Email Workflow Command

CLI for HEY: mailboxes, labels, collections, email threads, contacts, replies, compose, calendars, todos, habits, time tracking, and journal entries.

## Agent Invariants

**MUST follow these rules:**

1. **Choose the right structured output** — use `--jq '<expression>'` to filter or extract fields and `--json` for the full response. Never pipe to an external `jq`; `--jq` is built in and implies `--json`.
2. **Reuse stored authentication** — run the requested data command; it uses stored credentials and refreshes expiring OAuth tokens automatically. If it returns an auth error, report the task as blocked. Use `hey auth status --json` when an explicit authentication check is needed. Never run `hey auth login` unattended; use it only for interactive recovery with the user present.
3. **HTML output** is available via `--html` for commands that return HTML content
4. **Linked mail accounts share one login** — use `hey account list --json`, then `--account <id|all>` when a task must target one account
5. **Local HEY configuration requires human trust** — never run `hey config trust-local` without the user's explicit approval

## Output Filtering

`--jq` filters the full JSON success envelope, so result data is under `.data`. String results print as plain text; objects and arrays print as formatted JSON. Use `--quiet --jq` when the expression should run against result data directly. Errors retain their complete structured envelope. Commands with dedicated raw output (`auth token`, `completion`, `skill`, `tui`, and `--version`) reject `--jq`.

```bash
hey box list --jq '.data[] | {id, name}'
hey search "quarterly planning" --jq '.data[].id'
hey box list --quiet --jq '.[].name'
```

An empty result is an empty array rather than `null`, so `.data[]` is safe to run against a
listing that found nothing.

For the two commonest shapes there is no need for an expression at all: `--ids-only` prints
one ID per line and `--count` prints a bare number, both on stdout with any pagination
notice on stderr. Both need list data, so they work on `hey box list`, `hey box view`,
`hey label list`, `hey label view`, `hey collection list`, `hey collection view`, `hey workflow list`,
`hey workflow view`, `hey clip list`, `hey snippet list`, `hey draft list`, `hey search`,
`hey contact list`, `hey screener list`, `hey screener history`, `hey calendar list`,
`hey event list`, `hey event day`, `hey event week`, `hey todo list`, `hey habit list`,
`hey timetrack list`, `hey journal list` and `hey attachment list`. On `hey box view` they count and list its postings, not the box itself.

## Quick Reference

| Task | Command |
|------|---------|
| List linked mail accounts | `hey account list --json` |
| Set default mail account | `hey account use <id\|all>` |
| Run once for one account | `hey --account <id> box list --json` |
| Review trusted local settings | `hey config trusted-locals --json` |
| Trust this repository's settings | `hey config trust-local` (requires explicit user approval) |
| List mailboxes | `hey box list --json` |
| List emails in a box | `hey box view imbox --json` |
| List labels | `hey label list --json` |
| List emails with a label | `hey label view <label_id> --all --json` |
| Add a label to a thread | `hey label add <id> --to <label_id>` |
| Create and add a label | `hey label create "Travel receipts" <id>` |
| Remove labels | `hey label remove <id> --from <label_id\|all>` |
| List collections | `hey collection list --json` |
| List collection threads | `hey collection view <collection_id> --all --json` |
| Create a collection | `hey collection create "Kitchen remodel"` |
| Update a collection | `hey collection update <collection_id> --name "Kitchen renovation"` |
| Add a thread to a collection | `hey collection add <topic_id> --to <collection_id>` |
| Remove a thread from a collection | `hey collection remove <topic_id> --from <collection_id>` |
| List workflows | `hey workflow list --json` |
| View workflow stages | `hey workflow view <workflow_id> --json` |
| List clips | `hey clip list --json` |
| List snippets | `hey snippet list --json` |
| Search email | `hey search "quarterly planning" --json` |
| List search filters | `hey search filters --json` |
| List contacts | `hey contact list --json` |
| View contact | `hey contact show <id> --json` |
| Add contact | `hey contact add --name "Jane Doe" --email jane@example.com` |
| Edit contact | `hey contact update <id> --name "Jane Dawson"` |
| Hide contact | `hey contact hide <id>` |
| Show contact again | `hey contact show-again <id>` |
| Bundle a contact's mail | `hey contact bundle <id>` |
| List a contact's mail separately | `hey contact unbundle <id>` |
| Read private contact note | `hey contact note show <id> --json` |
| Set private contact note | `hey contact note set <id> "Prefers email"` |
| Delete private contact note | `hey contact note delete <id>` |
| Read email thread | `hey thread read <topic_id> --json` |
| Get a sharing link | `hey share <thread_id>` |
| Turn off a sharing link | `hey unshare <thread_id>` |
| Reply to email | `hey reply <topic_id> -m "Friday works for me."` |
| Forward email | `hey forward <topic_id> --to alice@example.com -m "For your review"` |
| Compose email | `hey compose --to alice@example.com --subject "Lunch plans" -m "Are you free Friday?"` |
| Compose with CC/BCC | `hey compose --to alice@example.com --cc bob@example.com --bcc carol@example.org --subject "Kitchen remodel timeline"` |
| List drafts | `hey draft list --json` (`--all`/`--page` follow the cursor) |
| Draft an email for human review | `hey compose --to alice@example.com --subject "Lunch plans" -m "Free Friday?" --draft` |
| Draft a reply for human review | `hey reply <topic_id> -m "Drafting this." --draft` |
| Read a draft back | `hey draft show <draft_id> --json` |
| Change a draft | `hey draft edit <draft_id> --to alice@example.com --subject "New subject"` |
| Send a draft | `hey draft send <draft_id>` |
| Trash drafts | `hey draft delete <draft_id>...` |
| Who is waiting in The Screener | `hey screener list --json` (clearance IDs) |
| Number waiting | `hey screener list --count` |
| Let a sender through | `hey screener approve <clearance_id>` |
| Turn a sender away | `hey screener deny <clearance_id>` |
| Who was already screened | `hey screener history --json` |
| Preview a bulk reply | `hey bulk-reply preview <id> <id> --json` |
| Send a bulk reply | `hey bulk-reply send <id> <id> -m "Thanks for the update."` |
| Recall a bulk reply | `hey bulk-reply undo <delivery_id>` |
| List calendars | `hey calendar list --json` |
| List calendar events | `hey event list --json` |
| Today's schedule, recurrences expanded | `hey event day --json` |
| Add a calendar event | `hey event add "Design review" --starts-on 2026-09-02 --start-time 14:00` |
| List todos | `hey todo list --json` |
| Add todo | `hey todo add "Draft the quarterly report"` |
| Complete todo | `hey todo complete 123` |
| Uncomplete todo | `hey todo uncomplete 123` |
| Delete todo | `hey todo delete 123` |
| Wait for new mail | `hey watch --box imbox --exit-on-first` |
| Follow every change | `hey watch` |
| Mark as seen | `hey seen 12345` |
| Mark as unseen | `hey unseen 12345` |
| Move email threads | `hey move 12345 --to feed` |
| Remove Reply Later | `hey move 12345 --to imbox` |
| Bubble a thread up now | `hey bubble up 12345 --now` |
| Bubble a thread up on a date | `hey bubble up 12345 --on 2026-09-04` |
| Bubble a thread up this weekend | `hey bubble up 12345 --weekend` |
| List bubbled-up and scheduled threads | `hey bubble list --json` |
| Cancel a bubble-up | `hey bubble pop 12345` |
| Move email threads to Trash | `hey trash 12345` |
| Mark email threads as spam | `hey spam 12345` |
| Ignore email threads | `hey ignore 12345` |
| Stop ignoring email threads | `hey stop-ignoring 12345` |
| List habits | `hey habit list --json` |
| Create habit | `hey habit create "Morning strength training"` |
| Edit habit | `hey habit edit 123 --days mon,wed,fri` |
| Delete habit | `hey habit delete 123` |
| Complete habit | `hey habit complete 123` |
| Uncomplete habit | `hey habit uncomplete 123` |
| Start time tracking | `hey timetrack start` |
| Stop time tracking | `hey timetrack stop` |
| Current timer | `hey timetrack current --json` |
| List time entries | `hey timetrack list --json` |
| Export completed time entries | `hey timetrack export > tracked-time.csv` (`--json` etc. need `--output`) |
| Save a time tracking export | `hey timetrack export --output tracked-time.csv --json` |
| List time track categories | `hey timetrack categories --json` |
| Create time track category | `hey timetrack category create "Client work"` |
| List journal entries | `hey journal list --json` |
| Read journal entry | `hey journal read 2024-03-15 --json` |
| Write journal entry | `hey journal write "Shipped the pagination fix."` (empty content removes the entry) |
| Check auth status | `hey auth status --json` |
| Print bearer token | `hey auth token` (refuses a `--cookie` login) |
| Launch TUI | `hey tui` (Ctrl+A switches linked mail accounts) |

## Decision Trees

### Reading Email

```
Want to read email?
├── Which mailbox? → hey box list --json
├── List emails in box? → hey box view <name|id> --json
├── List labels or labeled email? → hey label list --json / hey label view <label_id> --json
├── Add, create, or remove a label? → hey label add|create|remove
├── List collections or collection threads? → hey collection list --json / hey collection view <collection_id> --json
├── Create, update, add to, or remove from a collection? → hey collection create|update|add|remove
├── Search threads and messages? → hey search <query> --json
├── Need available refinements? → hey search filters --json
├── List or view contacts? → hey contact list --json / hey contact show <id> --json
├── Read full thread? → hey thread read <topic_id> --json
├── Get a sharing link? → hey share <thread_id>
├── Turn off the sharing link? → hey unshare <thread_id>
├── Mark as seen? → hey seen <id>
├── Mark as unseen? → hey unseen <id>
├── Move to another box? → hey move <id> --to <box>
├── Remove or unmark Reply Later? → hey move <id> --to imbox
├── Move to Trash? → hey trash <id>
├── Mark as spam? → hey spam <id>
├── Ignore future activity? → hey ignore <id>
├── Stop ignoring? → hey stop-ignoring <id>
├── Who is waiting to be screened? → hey screener list --json
├── Screen a sender in or out? → hey screener approve|deny <clearance_id>
└── Launch interactive UI? → hey tui
```

### Sending Email

```
Want to send email?
├── Reply to thread? → hey reply <topic_id> -m "message"
│   ├── Open editor? → hey reply <topic_id> (omit -m to open $EDITOR)
│   └── Attach files? → add --attach ./report.pdf (repeatable)
├── Reply to many threads at once? → hey bulk-reply preview <id>... first, then send
│   └── Sent by mistake? → hey bulk-reply undo <delivery_id> (while the window is open)
├── Forward latest message? → hey forward <topic_id> --to <email>
│   └── Add a note? → add -m "note"
├── Compose new? → hey compose --to <email> --subject "Subject"
│   ├── With body? → hey compose --to <email> --subject "Subject" -m "Body"
│   ├── With files? → add --attach ./report.pdf (repeatable; body is optional)
│   ├── With CC? → add --cc <email>
│   └── With BCC? → add --bcc <email>
├── List files in a thread? → hey attachment list <topic_id> --json
│   └── Save one? → hey attachment save <attachment_id> [--output <path>]
├── Draft instead of sending (human reviews in HEY)? → add --draft to compose or reply; the answer carries the draft id
│   ├── Read it back? → hey draft show <draft_id> --json
│   ├── Change it? → hey draft edit <draft_id> --subject/--to/--cc/--bcc/-m (flags replace; omitted fields are kept)
│   ├── Deliver it? → hey draft send <draft_id> (recipients required)
│   └── Discard it? → hey draft delete <draft_id>
└── Check drafts? → hey draft list --json
```

### Managing Todos

```
Want to manage todos?
├── List todos? → hey todo list --json
├── Add todo? → hey todo add "Task description"
├── Complete? → hey todo complete <id>
├── Uncomplete? → hey todo uncomplete <id>
└── Delete? → hey todo delete <id>
```

## Resource Reference

### Email - Boxes

```bash
hey box list --json                          # List all mailboxes
hey box view imbox --json                    # List emails in Imbox (by name)
hey box view 123 --json                      # List emails in box (by ID)
hey box view imbox --page next-cursor --json # Continue from an earlier listing
```

Box names: `imbox`, `feedbox`, `trailbox`, `asidebox`, `laterbox`, `bubblebox`

**Response format:** `hey box view --json` returns the box itself — `id`, `kind`, `name`, `app_url`, `next_history_url`, `next_page` — with a `postings` array of the email threads in it. Each posting has: `id` (box item ID), `topic_id` (thread ID), `name` (subject), `seen` (read status), `created_at`, `contacts`, `summary`, `app_url`, `visible_entry_count`. Use `id` for `hey seen`, `hey unseen`, `hey move`, `hey label add`, `hey label remove`, `hey trash`, `hey spam`, `hey ignore`, and `hey stop-ignoring`, and `topic_id` for `hey thread read`, `hey reply`, `hey forward`, `hey share` and `hey attachment list`. A box item `id` passed to `hey thread read` answers `not_found`, and so does a `topic_id` passed to `hey move`.

A posting that bundles a contact's mail into one row can **omit `topic_id`**: a bundle names its sender rather than a thread, and its `name` joins the bundled subjects with `•`. A bundle that does carry a `topic_id` opens as that thread — its one unseen thread — and `hey threads` reads it as usual. For a bundle without one, never substitute the box item `id` (`hey threads <id>` answers `not_found`); there is no command that lists the threads inside a bundle, so run `hey contacts unbundle <contact_id>` — the contact is in the posting's `contacts` — to list that sender's mail as separate rows, or direct the user to open the bundle in HEY.

`next_page` is the cursor `--page` takes, and it is the cursor inside `next_history_url` — `--page` accepts either. `--all` reads to the end instead.

`--ids-only` and `--count` work here too, and answer for the postings: one box item ID per line, or how many threads were read.

### Email - Labels

```bash
hey label list --json                         # List labels and stable IDs
hey label view 789 --all --json                # List every thread with a label
hey label add 12345 --to 789                   # Add an existing label
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
```

Label mutations take box item IDs from `hey box view`, `hey label view`, or active `hey search` results. Label IDs come from `hey label list`. `hey label view` returns `next_page` and `total_count`; pass `--page <next_page>` to continue or `--all` to fetch every page. HEY creates a label while adding it to at least one thread, so `label create` requires one or more thread item IDs.

### Email - Collections

```bash
hey collection list --json                                 # List collections and stable IDs
hey collection view 321 --all --json                        # List every thread in a collection
hey collection create "Kitchen remodel" --summary "Plans and decisions"
hey collection update 321 --name "Kitchen renovation"
hey collection add 987 --to 321                             # Add a topic ID
hey collection remove 987 --from 321                        # Remove a topic ID
```

Collection IDs come from `hey collection list`. `hey collection view` returns posting `id`, thread `topic_id`, `next_page`, and `total_count`; pass `--page <next_page>` to continue or `--all` to fetch every page. Collection membership commands take `topic_id`. Creating a collection confirms the mutation, and listing collections provides its ID for later commands.

### Email - Search

```bash
hey search "quarterly planning" --json         # Free-text search
hey search --from jane@example.com --date last_30_days --json  # Refined search
hey search --subject invoice --attachment pdfs --all --json    # Search up to 100 pages
hey search filters --json                      # Available box, date, label, and attachment values
```

Search refinements are `--required`, `--any`, `--none`, `--exact`, `--from`, `--to`, `--subject`, `--date`, `--in`, `--label`, and `--attachment`. `--page` selects one result page; `--all` fetches up to 100 pages from that point onward. When the cap is reached, the response notice provides the next `--page` value for continuation.

`--in`, `--date`, `--label` and `--attachment` accept only the values `hey search filters` lists: boxes are `imbox`, `feed`, `papertrail`, `trash`; dates are `last_7_days`, `last_30_days`, `last_90_days` or a four-digit year; attachment kinds are `any`, `images`, `pdfs`, `calendar_invites`, `documents`, `spreadsheets`, `presentations`, `media`, `zip_files`. The kinds are plural — `--attachment pdfs`, not `pdf`. An unrecognized `--in`, `--date` or `--attachment` is refused as a usage error naming the values it accepts, before anything is sent; `--label` is not checked, so read `hey search filters` when unsure of a label.

**Response format:** `data` contains one item per matching thread. Each result has `id` (box item ID for organization actions), `topic_id` (thread ID for `hey thread read`, `hey reply`, and `hey forward`), `subject`, `updated_at`, and `messages` containing the matching message IDs, senders, dates, and summaries. A result can omit `id` when the thread has no active box item.

### Contacts

```bash
hey contact list --json                       # List contacts
hey contact list --page 2 --json              # List another page
hey contact show 12345 --json                 # View details, aliases, and private note
hey contact add --name "Jane Doe" --email jane@example.com
hey contact add --name "Jane Doe" --email jane@example.com --alias jane.doe@example.org
hey contact update 12345 --name "Jane Dawson"
hey contact update 12345 --alias=              # Clear aliases
hey contact hide 12345                         # Hide from lists and autocomplete
hey contact show-again 12345                   # Reverse hiding
hey contact bundle 12345                       # Group this contact's mail into one row
hey contact unbundle 12345                     # List this contact's mail separately
hey contact note show 12345 --json
hey contact note set 12345 "Prefers email"
echo "Multiline private note" | hey contact note set 12345
hey contact note delete 12345
```

`hey contact list` returns contact IDs, names, email addresses, and update timestamps. `hey contact show` adds aliases, screening status, and the private note. Contact updates preserve omitted fields. Supplying `--alias` replaces the complete alias list, and `--alias=` clears it.

HEY hides contacts instead of permanently deleting them. A hidden contact leaves contact lists, autocomplete, and search results while remaining available by ID; `show-again` reverses the action. Bundling groups a contact's mail into one row without merging or deleting the underlying threads; `unbundle` lists those threads separately again. HEY applies bundling when the contact's current delivery setting supports bundles. Contact notes are private and support positional content, `--note`, stdin, or `$EDITOR`. Deleting a note leaves the contact unchanged.

### Email - Threads

```bash
hey thread read <topic_id> --json                 # Read full email thread
hey thread read <topic_id> --html                 # Read with raw HTML content
hey share <thread_id>                         # Get a sharing link
hey unshare <thread_id>                       # Turn off the sharing link
```

`hey thread read` returns every entry in the thread, oldest first. Each entry's `bod
