Skip to content

Repository files navigation

mailchimp-cli

A comprehensive Rust CLI for MailChimp marketing automation, designed for scripting and AI agent integration. JSON-first output with TSV fallback for human readability.

Features

  • Full campaign lifecycle — create, content, test, schedule, send, and report
  • Audience management — lists, members, tags, segments, batch operations
  • Template browsing — list templates and export HTML
  • Campaign analytics — opens, clicks, growth reports
  • OAuth2 authentication — browser-based login with multi-account support
  • Secure token storage — system keyring (macOS Keychain, Linux Secret Service) with file fallback
  • Structured output — JSON/NDJSON (default) and TSV (--plain) for easy parsing
  • Shell completions — Bash, Zsh, Fish, PowerShell
  • AI agent skill — ships with a Claude Code / Codex skill for natural language access

Installation

Requires Rust (edition 2024).

Quick install

The install script builds the binary, copies it to ~/.local/bin, and installs the AI agent skill to any detected agents (Claude Code, Codex):

./install.sh

Manual install

# Build
cargo build --release
# Install binary
mkdir -p ~/.local/bin
cp ./target/release/mailchimp ~/.local/bin/mailchimp
# Install Claude Code skill (optional)
mkdir -p ~/.claude/skills/mailchimp
ln -sf "$(pwd)/skills/mailchimp/SKILL.md"~/.claude/skills/mailchimp/SKILL.md
ln -sfn "$(pwd)/skills/mailchimp/docs"~/.claude/skills/mailchimp/docs

Make sure ~/.local/bin is in your PATH:

export PATH="$HOME/.local/bin:$PATH"

Quick Start

# Authenticate (opens browser for OAuth)
mailchimp auth login
# Or use a token directly
mailchimp --token mc-XXXXXXXX audiences list
# List your audiences
mailchimp audiences list
# List subscribers
mailchimp members list <audience_id># Create and send a campaign
mailchimp campaigns create --audience <aud_id> --subject "Newsletter"
mailchimp campaigns content <campaign_id> --html-file email.html
mailchimp campaigns test<campaign_id>"you@example.com"
mailchimp campaigns send <campaign_id>

Commands

Auth

mailchimp auth login # OAuth browser flow
mailchimp auth logout# Remove credentials
mailchimp auth accounts # List authenticated accounts
mailchimp auth switch us19 # Switch default account
mailchimp auth status # Current auth state

Audiences (alias: a)

mailchimp audiences list # All audiences
mailchimp audiences list --sort-members # Sort by subscriber count
mailchimp audiences info <id># Audience details
mailchimp audiences info '#My Audience'# Lookup by name

Members (alias: m)

mailchimp members list <aud> --status subscribed --limit 100
mailchimp members add <aud> user@example.com --merge-fields '{"FNAME":"Jo"}'
mailchimp members update <aud> user@example.com --status unsubscribed
mailchimp members remove <aud> user@example.com --force
mailchimp members unsubscribe <aud> user@example.com
mailchimp members search "john" --audience <aud>

Tags (alias: t)

mailchimp tags list <aud># All tags with counts
mailchimp tags add <aud> user@example.com "vip,beta"
mailchimp tags remove <aud> user@example.com "beta"
mailchimp tags members <aud>"vip"# Members with tag

Segments (alias: seg)

mailchimp segments list <aud>
mailchimp segments info <aud><segment_id>
mailchimp segments members <aud><segment_id>
mailchimp segments create <aud> --name "Active" --conditions '<json>'
mailchimp segments update <aud><seg_id> --name "New Name"
mailchimp segments delete <aud><seg_id> --force

Campaigns (alias: c)

mailchimp campaigns list --status sent --sort-sent
mailchimp campaigns info <id>
mailchimp campaigns create --audience <aud> --subject "Newsletter"
mailchimp campaigns content <id> --html-file email.html
mailchimp campaigns test<id>"test@example.com"
mailchimp campaigns schedule <id> --time "tomorrow at 10am"
mailchimp campaigns unschedule <id>
mailchimp campaigns send <id> --force
mailchimp campaigns delete <id> --force

Templates

mailchimp templates list --type user --sort-recent
mailchimp templates info <id>
mailchimp templates info <id> --html-only # Raw HTML to stdout
mailchimp templates info <id> --output tpl.html # Save HTML to file

Reports (alias: r)

mailchimp reports campaign <id># Full campaign stats
mailchimp reports clicks <id># Click details
mailchimp reports opens <id> --limit 100 # Open details
mailchimp reports growth <aud> --period month --months 12

Shell Completions

# Add to ~/.bashrc or ~/.zshrceval"$(mailchimp completions bash)"eval"$(mailchimp completions zsh)"# Or save to file
mailchimp completions fish >~/.config/fish/completions/mailchimp.fish

Output Modes

By default, output is JSON (single objects) or NDJSON (one JSON object per line for lists). Use --plain for TSV with a header row:

# JSON (default)
mailchimp audiences list
# TSV output
mailchimp audiences list --plain

Common patterns

# Count subscribers
mailchimp members list <aud> --plain | tail -n +2 | wc -l
# Extract a field with jq
mailchimp audiences info <id>| jq '.member_count'# Export subscriber emails
mailchimp members list <aud> --plain | cut -f1 | tail -n +2

Global Flags

FlagEnv VarDescription
--plainTSV output instead of JSON
-a, --account <prefix>MAILCHIMP_ACCOUNTUse specific account (server prefix, e.g. us19)
--token <token>MAILCHIMP_TOKENAPI token (bypasses keyring)
-v, --verboseVerbose logging to stderr
--helpShow help
--versionShow version

Environment Variables

VariableDescription
MAILCHIMP_TOKENDefault API token (overrides keyring)
MAILCHIMP_ACCOUNTDefault account (server prefix)
MAILCHIMP_TOKEN_STORE_PATHUse file-based token storage instead of keyring
MAILCHIMP_API_BASE_URLOverride API base URL (for testing)
MAILCHIMP_CLIENT_IDOAuth app client ID
MAILCHIMP_CLIENT_SECRETOAuth app client secret

Exit Codes

CodeMeaning
0Success
1General error
2Authentication required
3Invalid arguments
4API error
5Rate limited
6Network error

Destructive Operations

Commands that delete or send require confirmation. Use --force to skip the prompt:

  • members remove — permanent deletion
  • segments delete — removes segment
  • campaigns send — sends to all recipients
  • campaigns delete — removes campaign

Multi-Account Usage

# List all authenticated accounts
mailchimp auth accounts
# Run a command against a specific account
mailchimp -a us19 audiences list
# Set the default account
mailchimp auth switch us19

Guides

Batch Operations

Batch commands process multiple subscribers from CSV files, making per-row API calls with immediate feedback.

CSV format

email,FNAME,LNAME,status,tagsalice@example.com,Alice,Smith,subscribed,"vip,beta"bob@example.com,Bob,Jones,pending,
ColumnRequiredNotes
emailYesValid email address
FNAMENoFirst name merge field
LNAMENoLast name merge field
statusNosubscribed (default), pending, unsubscribed
tagsNoComma-separated, quoted if they contain commas

Commands

# Batch add subscribers from CSV
mailchimp members batch-add <aud> --file subscribers.csv
# Batch update existing subscribers
mailchimp members batch-update <aud> --file updates.csv
# Bulk tag from email list (one email per line)
mailchimp members batch-tag <aud> --emails emails.txt --tags "vip,premium"

Exit codes for batch commands: 0 = all succeeded, 1 = some row errors (partial success), 4 = fatal error (aborted).

Campaign Workflows

Full lifecycle for creating and sending campaigns:

# 1. Create draft
CAMPAIGN_ID=$(mailchimp campaigns create \ --audience abc123 \ --subject "March Newsletter" \ --from-name "Acme Inc" \ --reply-to news@acme.com \ --preview-text "What's new this month..." \| jq -r '.id')# 2. Set content from HTML file
mailchimp campaigns content "$CAMPAIGN_ID" --html-file ./newsletter.html
# 3. Send test
mailchimp campaigns test"$CAMPAIGN_ID""team@acme.com"# 4. Schedule for later
mailchimp campaigns schedule "$CAMPAIGN_ID" --time "tomorrow at 10am"# 5. Check results after sending
mailchimp reports campaign "$CAMPAIGN_ID"

Content sources (exactly one required):

FlagDescription
--html-file PATHHTML from file (most common)
--html TEXTInline HTML string
--plain-text TEXTPlain text content
--template-id IDUse MailChimp template (optional: --template-sections JSON)

Schedule accepts ISO 8601 (2024-12-01T14:00:00Z), datetime (2024-12-01 14:00), or natural language (tomorrow at 10am).

Segments and Conditions

Create segments to target subscriber subsets:

# Active subscribers who signed up this year
mailchimp segments create <aud> \
--name "2024 Signups" \
--conditions '{ "match": "all", "conditions": [ { "condition_type": "DateMerge", "field": "timestamp_opt", "op": "greater", "value": "2024-01-01" } ] }'

Condition JSON structure:

{
"match": "all | any",
"conditions": [
{
"condition_type": "TextMerge | DateMerge | Aim | MemberRating | StaticSegment | ...",
"field": "merge0 | merge1 | timestamp_opt | aim | member_rating | ...",
"op": "is | not | contains | greater | less | open | click | ...",
"value": "..."
}
]
}

Common condition types:

TypeFieldOperations
TextMergemerge0 (email), merge1 (FNAME), merge2 (LNAME)is, not, contains, starts, ends, blank
DateMergetimestamp_optis, not, greater, less, blank
Aimaimopen, click, sent, noopen, noclick
MemberRatingmember_ratinggreater, less, is
StaticSegmentstatic_segmentstatic_is, static_not

Development

# Build
cargo build
# Run tests
cargo test# Lint (must pass clean)
cargo clippy --all-targets --all-features -- -D warnings
# Format check
cargo fmt --check
# Run locally
cargo run -- audiences list --token TOKEN

All three checks (test, clippy, fmt) must pass before submitting changes.

License

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages