JSON on every command ⟶
Add --json and you get parseable, stable schemas. Pipe straight into jq or your model's tool layer. No screen-scraping.
██╗███╗ ██╗██████╗ ██║████╗ ██║██╔══██╗██║██╔██╗ ██║██████╔╝██║██║╚██╗██║██╔══██╗██║██║ ╚████║██████╔╝╚═╝╚═╝ ╚═══╝╚═════╝
The agent inbox.
A tiny Go CLI for IMAP & SMTP — no SDK, no OAuth dance, no TTY.
go install github.com/yuzu-hub/inb@latest
inb setup
inb assumes nothing. Every surface — auth, output, addressing, errors — is shaped for a process that can't click "Allow" in a browser tab, can't read a screenshot of a thread, and shouldn't have to. Six concrete consequences:
Add --json and you get parseable, stable schemas. Pipe straight into jq or your model's tool layer. No screen-scraping.
Credentials live in INB_* environment variables or ~/.inb.env. No OAuth redirect, no browser, no token refresh thread.
Every message is referenced by IMAP UID — stable within a folder, easy to thread through a plan. Agents can re-read their own state.
inb read 421 --max-bytes=8192Marking read twice is fine. Moving to a folder it's already in is fine. The agent doesn't need to remember whether it already did the thing.
inb mark 421 --read0 success, 1 anything went wrong (net, auth, bad flag, missing message), 2 unknown subcommand. Errors go to stderr — loops branch on $?, no prose parsing.
Outside of setup, inb never prompts. Body via --body, --body-file, or stdin. Headless containers, cron jobs, agent sandboxes — all fine.
One static binary, no runtime deps. Or grab a release from GitHub and drop it on $PATH.
The wizard detects your provider (Gmail, Fastmail, iCloud, generic IMAP) and writes ~/.inb.env. Or set env vars directly — agents typically prefer the latter so secrets live in their sandbox, not on disk.
Read your inbox, draft a reply, mark it done — entirely from the shell.
Every command takes --json for machine output and --folder <name>
to scope to a non-INBOX folder. Run inb <cmd> --help for the full flag set.
inb <command> [flags]
list --searchFilename, ContentType, Size) — every other command uses snake_case- for stdin); --attach is repeatable; appends to Sent by default. Footer: configured INB_FOOTER is auto-appended with RFC 3676 sigdash; override per call with --footer/--footer-file/--footer-html, suppress with --no-footerINBOX)HOST, PORT (default 993 if TLS else 143), USER, PASS, TLS=tls|starttls|none (default tls)HOST, PORT (default 587 starttls / 465 tls / 25 none), USER, PASS, TLS=starttls|tls|none (default starttls)send (e.g. 'Alice <alice@example.com>')<br>-wrapped unless INB_FOOTER_HTML is set.~/ prefix.KEY=v, KEY="v" (with \n \r \t escapes), KEY='v' (literal), # comments.Full schema reference, error catalog, provider settings, behavior guarantees → llms.txt (agent-readable, ~600 lines).
None of these need an SDK. They're shell. That's the point — anything that can spawn a subprocess can read and write email.
List + JSON output + jq + your favorite agent runner. The model decides what to archive, what to flag, what needs a reply. Re-running tomorrow is safe — already-marked items don't reappear.
Add a single .claude/commands/email.md that wraps the four commands an agent actually needs. The model invokes them like any other shell tool.
inb reads from stdin for --body=-, so you can stream the model's response straight into a send. No temp files, no shell-escaping of the body.
inb · MIT · made for processes, not people github.com/yuzu-hub/inb · issues · ↑ top