Building Email CLIs in a Sandbox Without Root: Seven Field Reports

Building Email CLIs in a Sandbox Without Root: Seven Field Reports

Broodnet Team
Broodnet Team April 21, 2026

In this Email Cli Field Test Series

  1. 1. What AI Agents Need From an Email CLI
  2. 2. Ranking 7 Email CLIs for AI Agents in 2026
  3. 3. Building Email CLIs in a Sandbox Without Root: Seven Field Reports

Part 3 of 3 in our 2026 field test of terminal email clients for AI agents. If you want the framing, start with Part 1. If you want the ranking, Part 2 has it. This piece is the install diary: one section per tool, focused on what the environment made harder than it should have been.

What we were actually testing

For every tool, we attempted the same loop: install, configure against a real Broodnet mailbox over IMAP and SMTP, list the inbox, open a message, send a self-test, read it back, try an external-recipient send to see how any policy layer behaved, then clean up the test messages.

The environment was Ubuntu 24.04 under WSL2 with no sudo. That matters more than it sounds like it should. Any tool whose documented install path begins with apt install suddenly has to survive a fallback path built out of apt download, dpkg-deb -x, manual library wiring, and whatever else gets you from “package exists” to “binary runs.”

That constraint is why this article exists. In an environment with root, several of these stories collapse to a single line. In a sandboxed agent runtime, a CI runner without privilege, or a locked-down laptop setup, the fallback path looks like the real path.

In a constrained environment, the install path is part of the product.

We also timed representative commands with /usr/bin/time -v where the tool completed a real round trip. When the loop could not be completed cleanly, that was itself a finding.

Building email CLIs in a sandbox without root

Broodnet CLI

The smoothest install in the set, which also makes it the least dramatic section of the article.

This section describes the 0.2.x line of Broodnet CLI, which is what we tested during this evaluation. Future versions may change the install story, command surface, and feature set.

npm install -g @broodnet/cli

No compile step. No native dependency chase. The binary ends up on PATH.

Auth works cleanly through an environment variable, which is the path we recommend for agent integrations:

export BROODNET_TOKEN="<your-token>"
BROODNET_TOKEN=$BROODNET_TOKEN broodnet mail inbox --json

There is also a broodnet login --token=<your-token> flow that writes a config file, but in a read-only or ephemeral environment the env-var path is usually the better answer anyway. No state on disk, no first-run wizard, secrets injected the same way you inject every other secret in CI.

If the sandbox does not allow global installs, we can still use npx:

  npx @broodnet/cli mail inbox --json

The core loop worked: list, open, send on stdin, read back, delete. The JSON envelope stayed consistent across the commands that matter, and policy rejections were clear in a machine-readable way. The tradeoff is scope: in the 0.2.x line we tested, Broodnet CLI is focused on the core workflow and does not yet expose folder support or plus-addressing style tag patterns such as something+tag@....

Himalaya

The second-smoothest install, and the strongest general-purpose alternative.

curl -sSL https://raw.githubusercontent.com/pimalaya/himalaya/master/install.sh | \
  PREFIX=$HOME/.local sh

That is the good part. The config is where Himalaya stops feeling agent-first.

It wants a hand-written TOML file with separate account, IMAP, and SMTP sections. A representative setup looks like this:

[accounts.broodnet]
email = "agent@broodnet.com"
default = true

[accounts.broodnet.backend]
type = "imap"
host = "mail.broodnet.com"
port = 993
encryption = "tls"
login = "agent@broodnet.com"
auth.type = "password"
auth.cmd = "printf %s \"$BROODNET_TOKEN\""

[accounts.broodnet.message.send.backend]
type = "smtp"
host = "mail.broodnet.com"
port = 465
encryption = "tls"
login = "agent@broodnet.com"
auth.type = "password"
auth.cmd = "printf %s \"$BROODNET_TOKEN\""

Three separate sections for one account, plus an indirection for credentials. Workable, not free.

The loop itself worked cleanly. List folders, list envelopes, read messages, send a self-test, read it back. The catch is output shape: -o json does not mean one schema across commands.

Himalaya installs like a modern CLI. It configures like an older mail client.

NeoMutt

This is where the no-root constraint starts to matter.

On a normal machine, NeoMutt is a straightforward package-manager install. In our sandbox, it had to be assembled through a manual dpkg-deb -x chain plus a shared-library wrapper so the binary could find what it needed at runtime.

Once that was in place, the send path was genuinely good:

echo "neomutt batch-send self-test" | \
  neomutt -F ~/.config/neomutt/neomuttrc \
  -s "neomutt batch self-test" \
  agent@broodnet.com

That worked. The message arrived. The envelope looked correct. NeoMutt even tells you one useful caveat directly: batch mode does not automatically file to Sent.

The problem is the read side. There is no equivalent non-interactive inbox surface. You can automate send cleanly, but the moment you want read-plus-send inside one tool, you are back in TUI territory.

NeoMutt is the exception that proves the rule: one clean batch-send surface is enough to make it interesting, but not enough to make it agent-first.

Debian package manager is easy, but the resulting NeoMutt install is not agent-friendly

nmail

The heaviest install in the article, and not by a small margin.

There was no simple Ubuntu package path. The route was source build plus a pile of native dependencies extracted by hand, followed by CMake configuration work that needed manual nudging for things like OpenSSL and Xapian. In a privileged environment this is annoying. In a no-root environment it turns into a full afternoon.

Once running, nmail looked healthy and modern as a human-facing client. The inbox rendered properly. SMTP send through the compose flow worked. The trouble is that all of this still assumes a human at the terminal.

There is no documented non-interactive send path. First-run behavior prompts for credentials in the terminal. You can script around that with tmux send-keys if you really want to, but that is not a serious integration story for agents.

meli

The most interesting build mess in the set.

meli expects a recent Rust toolchain. If you let openssl-sys fall back to vendored OpenSSL, the build stops being “compile the mail client” and becomes “compile an entire crypto stack first.” In our environment, that was enough to turn a straightforward build into a build-system incident.

The fix was to point the build at an extracted OpenSSL prefix and disable vendoring:

OPENSSL_DIR=$HOME/tools/ossl-prefix \
OPENSSL_NO_VENDOR=1 \
  cargo build --bin meli --offline

Then there is m4. meli preprocesses its config through m4 before parsing. If m4 is not on PATH, config validation fails in a way that is not obvious until you know what you are looking for.

The IMAP side was strong. The mailbox loaded correctly. The SMTP tooling proved the backend wiring was alive. What we did not get was a practical non-interactive send path that looked like something you would want to hand to an agent.

meli has an interesting architecture. It also has the kind of provisioning surprises that automation pipelines tend to hate.

aerc

Install was actually pleasant, which only made the automation story more frustrating.

go build produced a working binary on the first try. After that, the problem was not “can this run?” but “how do you drive it without pretending to be a human?”

Our proof-of-send looked like this in spirit:

TERM=tmux-256color tmux new-session -d -s aerc 'aerc'
sleep 3
tmux send-keys -t aerc ':compose' Enter
tmux send-keys -t aerc 'agent@broodnet.com' Tab 'aerc self-test' Enter
tmux send-keys -t aerc 'i' 'body text' Escape ':wq' Enter
tmux send-keys -t aerc ':send' Enter

Yes, it worked. No, that does not make it a good idea.

This is the exact tmux-plus-editor anti-pattern Part 1 warns about. One keybinding change upstream and the whole thing breaks silently.

Alpine

The cleanest user-space install of any tool here — and still the least agent-ready.

One download, one extraction, and it ran. Its command surface is also more scriptable than people remember. It can take a body on stdin, it can compose from the command line, and it can be pointed at an alternate config file cleanly.

The project is actively maintained by a single dev, with development releases shipping into 2026. But none of that maintenance has produced a non-interactive read path, structured output, or env-var auth. Alpine is a human-first TUI that remains a human-first TUI. For agents, the automation surface is what matters, and it is not there.

Time and memory, where it mattered

Two numbers kept coming up:

  • Broodnet CLI 0.2.X on inbox --limit=20 --json: about 1.2s wall time and 112 MB peak RSS
  • Himalaya on envelope list -s 20 -o json: about 0.5s wall time and 13 MB peak RSS

That tracks the runtime story. A Rust binary starts faster and lighter than a Node CLI on the same shape of operation. The more important question is whether those advantages matter more than installation simplicity in the environment you actually have.

Performance signals for email CLIs in a sandbox without root

Closing

The point of running this end-to-end rather than surveying docs was to see where the tools break under automation pressure. The main findings live in Part 2. The secondary finding only shows up when the environment is constrained: the distance between “documented install path” and “runnable binary” varies wildly across these tools, and that variation is not tightly correlated with quality.

Alpine is trivial to extract but entirely human-first. meli is thoughtful and actively developed but asks more from your toolchain than most setup scripts will know about. aerc builds beautifully and then makes you automate an editor. nmail is actively maintained and still gives you no credible non-interactive path. Those are not edge details. For agents, they are the product.

The tooling question is not “does it support IMAP and SMTP?” The tooling question is “what happens when you try to automate the whole thing in a place where you do not control the machine?”

If you want the framing, go back to Part 1. If you want the ranking, Part 2 has it. If you want the war stories, this is the file.

In this Email Cli Field Test Series

  1. 1. What AI Agents Need From an Email CLI
  2. 2. Ranking 7 Email CLIs for AI Agents in 2026
  3. 3. Building Email CLIs in a Sandbox Without Root: Seven Field Reports

Other posts