The command-line tool requires Cullapse Pro. The binary ships
in every install, but every subcommand except version
and doctor exits with code 4 until a Pro
entitlement is detected. See pricing.
Install
The binary lives at
Cullapse.app/Contents/Resources/cullapse. The fastest
way to add it to your shell is from inside the app: Edit →
Install Cullapse CLI…. The sheet shows the resolved path
and a ln -s command you can paste into Terminal.
The Mac App Store sandbox prevents Cullapse from writing into
/usr/local/bin on your behalf. Terminal handles that
part of the install, the same way VS Code installs its
code command. The binary itself is already
notarized.
$ sudo ln -s \
/Applications/Cullapse.app/Contents/Resources/cullapse \
/usr/local/bin/cullapse
Verify with cullapse --version. Accounts you have
added in the GUI are visible to the CLI without further setup,
because the two share the same keychain access group.
Automation philosophy
The CLI is held to two rules. First, every action that mutates a
mailbox supports --dry-run and exits zero when the
dry run is satisfied. Second, the CLI honors the same VIP and
transactional protections as the GUI, and the same buffered-undo
window applies — there is no “bypass safety rails” flag.
Output is line-oriented and grep-friendly. JSON output is
available with --format json for downstream tooling.
The CLI does not paginate, does not colorize when piped, and
returns useful exit codes (see § exit codes).
Commands
cullapse accounts listList configured accounts and their connection state. Shared with the GUI.
cullapse accounts add <email>Add a new account interactively. Prompts for IMAP host, port, and password.
cullapse senders [--min-count N] [--read-rate P] [--vip|--no-vip] [--format tsv|json|text]Show one row per sender for the selected account and folder. Filter by minimum message count, read-rate threshold, or VIP status.
cullapse subjects [--cluster] [--since DATE]List subject groups. --cluster uses the same normalization the GUI uses to merge near-duplicates.
cullapse fetch [--account NAME] [--folder NAME]Refresh headers for the selected account and folder. Idempotent. Honors server rate limits.
cullapse archive --from ADDR | --query EXPR [--dry-run]Archive matching messages to the account's archive folder. Always print affected counts before committing.
cullapse delete --from ADDR | --query EXPR [--dry-run]Delete matching messages. Subject to the same VIP and transactional protections as the GUI. Refuses to run on more than 5,000 messages without an explicit --yes-bulk.
cullapse move --to FOLDER --from ADDR | --query EXPR [--dry-run]Move messages between folders.
cullapse unsubscribe --from ADDR [--method http|mailto]Perform a List-Unsubscribe action. With http, issues the one-click POST. With mailto, opens the URL in your default mail handler — Cullapse does not send mail.
cullapse rules listPrint active rules and the order in which they evaluate.
cullapse rules run [--dry-run]Evaluate every rule against the current cache and apply the resulting actions through the buffered pipeline.
cullapse export --what categories|rules|vips [--format json|tsv]Dump local state to stdout for backup or transfer to another machine.
cullapse licensePrint the current license tier (free or pro) and the platform marker.
The --query expression
A small, header-only query language. Supported terms:
from:, to:, subject:,
list:, folder:, before:DATE,
after:DATE, read:true|false,
replied:true|false, size:>NB,
category:NAME. Combine with AND,
OR, and parentheses. Quote any term containing spaces.
cullapse archive --query 'list:weekly-digest AND before:2026-01-01'
Example workflows
Quarterly cleanup, scripted
#!/usr/bin/env zsh
set -euo pipefail
# refresh, then archive any digest older than 90 days
cullapse fetch --account personal
cullapse archive --account personal \
--query 'category:newsletter AND before:90d' \
--dry-run
read "?Apply? (y/N) " confirm
[[ "$confirm" == "y" ]] || exit 0
cullapse archive --account personal \
--query 'category:newsletter AND before:90d'
Nightly digest of new high-volume senders
# crontab -e
0 6 * * * /usr/local/bin/cullapse senders \
--account work --min-count 10 --new-since 24h \
--format tsv | mail -s "new senders" you@example.com
Review before commit
cullapse rules run --dry-run --format json > /tmp/plan.json
jq '.actions | group_by(.kind) | map({kind: .[0].kind, count: length})' /tmp/plan.json
Exit codes
0— success1— generic error2— usage error (bad arguments)3— IMAP connection failure4— Pro license required5— refused: action would affect more rows than the safety threshold6— destructive action aborted by VIP protection7— provider rate limit hit; retry later
Safety rails
A script that runs cullapse delete in a loop can
remove a large amount of mail in a short period. The CLI is the
same engine the GUI uses, with the same protections, but it has
no human in the loop to catch a typo in a query. Run new
scripts with --dry-run first, and store backups of
anything you cannot afford to lose.
- Every destructive verb prints a count and pauses for the configured undo window before committing. The window is the same one Settings uses.
- Operations above 5,000 messages require
--yes-bulk. - VIPs and transactional senders are protected unless you set
--allow-vipand--allow-transactional, both of which are recorded in the log. - The CLI refuses to run on a Cullapse version that is more than 90 days behind the latest, to keep IMAP behavior in sync with what the GUI ships.
License and redistribution
The CLI is part of the Cullapse application and is licensed under the same terms as the GUI. See EULA §4. You may invoke the CLI from your own scripts on the device where Cullapse is installed. You may not redistribute the binary separately from the application bundle or embed it in other software.