One inbox for everything. void unifies WhatsApp, Telegram, Slack, Gmail, Google Calendar, LinkedIn, GitHub, Hacker News, Google News, and Reddit into a single local-first command-line tool — one inbox, one search index, one set of commands.
It is built for terminals, shell scripts, and AI agents:
- One inbox —
void inboxshows every unprocessed message across all your accounts - Local-first — a background daemon syncs everything into SQLite; reads are instant and work offline
- Full-text search — FTS5 across every message on every service
- Inbox Zero — triage, act, archive; muted noise stays out of sight
- Agent hooks — run Claude Code (or any agent CLI) on new messages or cron schedules
- Remote mode — sync on a home server, drive it from any laptop over plain SSH
Start here: Install · Commands · Connector setup · Configuration · Hooks · Remote store
# macOS (Homebrew) — recommended
brew install MaximeGaudin/tap/void
# macOS (Apple Silicon, direct)
curl -fsSL https://github.com/MaximeGaudin/void/releases/latest/download/void-darwin-arm64.tar.gz | sudo tar xz -C /usr/local/bin
# Linux (x86_64)
curl -fsSL https://github.com/MaximeGaudin/void/releases/latest/download/void-linux-amd64.tar.gz | sudo tar xz -C /usr/local/binmacOS Intel, Linux ARM64, Windows, and build-from-source: see Install.
void setup # interactive wizard — connect WhatsApp, Slack, Gmail, ...
void sync --daemon # start the background sync daemon
void inbox # everything unprocessed, all services
void search "quarterly report" # full-text search across all of it
void reply <id> --message "On it — sending today." # reply from where you are
void archive <id> # done; on to the next oneWhatsApp and Telegram connect by scanning a QR code. Gmail and Calendar ship with built-in OAuth credentials — no Google Cloud project required. Per-service details: Connector setup.
Void follows an Inbox Zero model: every unprocessed message from every service lands in a single inbox, and the goal is to empty it.
- Triage —
void inboxshows all unarchived messages across every connector - Act — reply, react, forward, draft, or just read
- Archive —
void archive <id>marks the item as processed - Done — when
void inboxreturns nothing, you're at Inbox Zero
Noise never reaches the inbox in the first place: void mute (or ignore_conversations in the config) silences groups and channels permanently. void inbox --all reviews what's been archived.
# Send anywhere through one interface
void send --via slack --to "#general" --message "Hello team"
void send --via whatsapp --to "Alice" --message "Running 5 min late"
void send --via telegram --to "Notes" --file ./screenshot.png
# Threads, reactions, edits, scheduled messages
void reply <id> --message "Agreed" --in-thread
void slack react <id> --emoji rocket
void slack schedule --channel "#standup" --message "OOO today" --at "2026-06-12 09:00"
# Bulk-archive an old backlog
void archive --before 2026-05-01 --connector slackvoid gmail search "from:boss newer_than:7d"
void gmail thread <id>
# Drafts only — void never sends email directly
void gmail draft create --reply-to <id> --subject "Re: Q3" --body "LGTM, approved."
# Archive in Gmail by removing the INBOX label, in bulk
void gmail batch-modify <id1> <id2> --remove INBOXDocs: commands
void calendar # today
void calendar week # this week
void calendar --day tomorrow
void calendar create --title "1:1 Alice" --start "2026-06-16T14:00" --meet # ends +30min by default
void calendar availability --attendees alice@x.com,bob@x.com --from 2026-06-15T09:00 --to 2026-06-15T18:00
void calendar respond <id> --status acceptedKeyword-watched stories land in your inbox like any other message:
void hn keywords add "rust,local-first"
void hn min-score 100Keyword- and score-filtered posts from watched subreddits land in your inbox like any other message. Enable commenting during void setup to sync thread comments and reply from the CLI (browser OAuth, stores refresh_token).
void reddit subreddits add "rust,programming"
void reddit keywords add "ai,llm"
void reddit min-score 50
void reddit config
void reply <message-id> --message "Thanks!"Keyword-watched articles from the public Google News RSS feed land in your inbox — one search per keyword, filtered by recency:
void gn keywords add "intelligence artificielle,startup"
void gn when 7d # only articles from the last 7 days
void gn language fr # hl parameter
void gn country FR # gl parameterHooks run an AI agent on new messages or cron schedules — and since the agent can call void itself, it can triage, draft, and notify on your behalf. Docs: Hooks
# Get pinged on Telegram when an important email lands
void hook create --name email-triage --trigger new_message --connector gmail \
--prompt 'New email: {message}. If important and actionable, send me a one-line summary on Telegram (chat "Notes") via void send. Otherwise do nothing.'
# Weekday-morning digest
void hook create --name digest --trigger schedule --cron "0 8 * * mon-fri" \
--prompt-file ~/.config/void/prompts/digest.md --max-turns 10A background daemon keeps a local SQLite database in sync with every connected service. Read commands hit the local database — instant, offline-capable. Write commands call the service APIs directly.
reads (instant, offline) writes (direct API)
void ◄──────────► SQLite (FTS5) ◄────── sync daemon ──────► services
│
WhatsApp │ Telegram │ Slack ──── push (WebSocket / MTProto)
Gmail │ Calendar │ LinkedIn │ GitHub │ HN │ Google News │ Reddit ──── polling
| Crate | Role |
|---|---|
void-core |
Config, database, models, hooks, Connector trait, sync engine |
void-cli |
The void binary: clap commands, output formatting |
void-slack, void-gmail, void-calendar, void-whatsapp, void-telegram, void-hackernews, void-googlenews, void-linkedin, void-github, void-reddit |
One crate per connector |
All data stays on your machine in ~/.local/share/void — no external database, no Docker, no cloud. Layout details: Configuration.
| Local mode (default) | Remote mode | |
|---|---|---|
| Where sync runs | your machine | an always-on server |
| Setup | nothing beyond void setup |
one server + a 4-line client config |
| When your laptop is off | sync and hooks pause | sync and hooks keep running 24/7 |
| Multiple machines | one database per machine | any laptop, over plain SSH |
Local mode is the zero-infrastructure default: daemon, database, and credentials all live on your machine. The only catch is that sync follows your laptop — closed lid means a stale inbox and silent hooks until it wakes.
Remote mode moves the daemon (and your credentials) to a home server or VPS. Your laptop keeps a cached snapshot for instant, offline-capable reads, and proxies writes to the server over plain SSH — no extra service, no open ports beyond SSH.
Details, trade-offs, and migration: Deployment modes · config reference: Remote store
- Install — all platforms, build from source
- Command reference — every command and flag
- Connector setup — credentials and onboarding per service
- Configuration — full
config.tomlschema, data layout - Hooks — LLM automation: triggers, placeholders, agent contract
- Deployment modes — local vs remote sync: trade-offs, architecture, migration
- Remote store — server-side sync over SSH
- Adding a connector — wire in a new service
- Testing — suite layout, conventions, coverage gaps
./scripts/check.sh # fmt + clippy + tests, same as CI
cargo build --releaseContributions welcome — read CONTRIBUTING.md, and Adding a connector is the best place to start. Security reports: SECURITY.md. Release notes: CHANGELOG.md.
Copyright (C) 2026 Maxime Gaudin
Free software under the GNU Affero General Public License v3.0. See LICENSE for the full text.