I kept hitting the same two options for mailcow admin and migrations: click through the UI, or hand-roll curl against the API. So I wrote a proper CLI for it, GPL-3 like mailcow itself: elcamino/mailcowctl
mailcowctl is a single Go binary — think kubectl or gh, but for a mailcow instance — that talks to the REST API. No Python, no container wrapper.

# one binary, a profile per instance
mailcowctl --profile prod domain list
mailcowctl --profile prod mailbox create me@example.org --name "Me" --quota 3072 --password-stdin
mailcowctl --profile prod alias create info@example.org --goto me@example.org
# the migration-shaped stuff
mailcowctl --profile prod syncjob list
mailcowctl --profile prod dkim get example.org --dns
mailcowctl --profile prod filter get 12 -o json > sieve-12.json
# everything speaks JSON for scripting
mailcowctl --profile prod domain list -o json
Beyond basic CRUD: migration
Domains, mailboxes and aliases are the obvious part. The bit this community probably cares more about is that it also covers the migration-adjacent resources, so moving mail into mailcow or between instances stops being a manual slog:
syncjob — mailcow’s built-in imapsync jobs, the mechanism that pulls mail content off the old server
dkim — get/add/duplicate/delete keys (private keys are never returned by the API, so migration means regenerating + updating DNS TXT, which --dns prints for you)
apppass — app passwords
filter — sieve filters; filter get -o json exports the full script for re-creation on the new box
policy — per-domain anti-spam allow/block lists
Plus routing/relay maps (transport, bcc, recipient, tlspolicy, relayhost, fwdhost, resource) and quarantine ops (list, release, learn-ham, delete).
Who it’s for
- Anyone automating mailbox/alias provisioning who wants proper exit codes and
-o json instead of scraping the UI
- Anyone migrating an existing setup into mailcow, or between two mailcow servers
- Multi-instance operators — profiles are first-class, so keeping a primary and a secondary in parity stops being copy-paste
What it deliberately is not
Not a TUI, and not a mailcow installer/lifecycle manager — that stays with docker compose and the helper scripts. This only talks to the API of an already-running instance.
Honest caveats
It’s only as complete as the API underneath it. DKIM private keys and app-password secrets can’t be exported (you recreate them), there’s no run-now API for syncjobs, and a few resources have no edit endpoint so they’re create/delete only. Passwords are never echoed — supply them via --password-stdin or --password-env. And the usual prerequisite: the API key is IP allow-listed (API_ALLOW_FROM in mailcow.conf), and write commands need a read-write key.
Install
go install github.com/elcamino/mailcowctl@latest
Release binaries (currently v0.1.2) are on the releases page. Source, issues, contributions: elcamino/mailcowctl — GPL-3.0-or-later.
Bug reports and edge cases very welcome, especially around the API’s quirks — HTTP 200 even on logical failures, and inconsistent JSON typing (booleans come back as strings in places, ints in others) — and the quarantine item-id encoding, which I’d confirm against a single disposable item before any bulk use.
Cheers,
Tobias