The Buttondown CLI (Command Line Interface) is a powerful tool that lets you manage your newsletter content from your local machine. It enables workflows like editing newsletters in your preferred text editor, backing up your content, and syncing media files.
Installation
Install the CLI globally using npm:
Or use it with npx without installing:
What You Can Do
The CLI provides several capabilities:
- Work offline with your newsletter content
- Edit in your favorite editor using Markdown
- Version control your newsletters with Git or other tools
- Sync content bidirectionally between your computer and Buttondown
- Manage media files like images and attachments
- Automate workflows with scripts
Getting Started
1. Authentication
Before using the CLI, you need to authenticate with your Buttondown API key:
You'll be prompted to enter your API key, which you can find in your Buttondown settings.
2. Pull your content
To download your newsletters from Buttondown:
This creates a ./buttondown directory with all your content.
3. Create or edit newsletters
Create a new draft:
Then edit the created Markdown file with your preferred editor.
4. Push your changes
When you're ready to save your changes back to Buttondown:
Important: buttondown push doesn't publish emails with the status: draft field, which is the default status for new emails. See the Publishing Behavior section below for details on how to actually send your emails.
Publishing Behavior
When you run buttondown push, it syncs your content to Buttondown maintaining the status in the frontmatter. Here's how publishing works:
Status Field Controls Publishing
The status field in your email's frontmatter determines what happens:
| Status | Description |
|---|---|
draft | Email remains a draft when pushed |
scheduled | Email will be sent at the specified publish_date |
about_to_send | Email is queued and will be sent very soon (typically within a few minutes) |
sent | Email has already been sent -- editing these will change their body in the archives |
More information on statuses is available in the API reference.
Directory Structure
The CLI creates this structure in your local folder:
Directory Structure
Newsletter Format
Each newsletter is stored as a Markdown file with YAML frontmatter:
Email Fields Reference
Required Fields
When creating emails via the CLI, only one field is truly required:
| Field | Type | Description | Required When |
|---|---|---|---|
subject | string | The email subject line | Always required for API creation |
title | string | Used by CLI create command (becomes subject) | Required for buttondown create command |
Optional Fields
All other fields are optional and have sensible defaults:
| Field | Type | Default | Description |
|---|---|---|---|
body | string | "" | Email content (HTML or Markdown) |
status | string | "about_to_send" | Email status |
email_type | string | "public" | Email visibility type |
slug | string | null | URL-friendly identifier |
description | string | "" | Human-readable description |
image | string | "" | Primary image URL |
publish_date | datetime | null | Scheduled publish date |
attachments | array<UUID> | [] | List of attachment IDs |
metadata | object | {} | Custom metadata fields |
canonical_url | string | "" | Original content URL |
secondary_id | integer | null | Informal issue number |
filters | object | FilterGroup() | Subscriber filtering rules |
commenting_mode | string | "enabled" | Comment settings |
related_email_ids | array<string> | [] | Related email IDs |
featured | boolean | false | Archive highlighting |
Email Type Values
| Value | Description |
|---|---|
public | Visible to all subscribers and in archives |
private | Only visible to subscribers |
premium | Only visible to paid subscribers |
free | Only visible to free subscribers |
churned | Only visible to churned subscribers |
archival | For imported/archived content |
Email Status Values
| Value | Description |
|---|---|
draft | Email is being composed |
about_to_send | Email is ready to send |
scheduled | Email is scheduled for future |
in_flight | Email is currently sending |
sent | Email has been sent |
paused | Sending was paused |
imported | Email was imported from external source |
Validation Rules
Subject Line
- Maximum length: 1000 characters
- XSS validation: Subject is validated against XSS attacks
- Required: Cannot be empty when creating via API
Body Content
- Format: Accepts HTML or Markdown
- Null characters: Not allowed in body content
- XSS validation: Body is validated against XSS attacks
- Default: Empty string if not provided
Slug
- Format: Must be URL-safe (validated with Django's
validate_slug) - Maximum length: 100 characters
- Uniqueness: Must be unique within the newsletter
- Auto-generation: Generated from subject if not provided
Common Email Examples
Creating a Newsletter Issue
Scheduling an Email
Premium Content
Common Workflows
Working with Existing Content
Editing and Publishing Workflow
Adding Images
- Add images to the
media/directory - Reference them in your Markdown:
- When you
buttondown push, the CLI uploads the images and updates the URLs
Backing Up Your Content
Consider adding this to a scheduled task for regular backups.
Advanced Usage
Working with Multiple Newsletters
You can work with different newsletters using different directories:
Using with Git
Automating with Scripts
Create a script like publish.sh:
Make it executable with chmod +x publish.sh
Available Commands
| Command | Description |
|---|---|
buttondown login | Authenticate with Buttondown |
buttondown logout | Clear stored credentials |
buttondown pull | Download content from Buttondown |
buttondown push | Upload content to Buttondown |
buttondown create | Create a new draft email locally |
Troubleshooting
API Key Issues
If you encounter authentication errors:
Sync Conflicts
If you've modified the same email both locally and on Buttondown:
- Back up your local changes:
cp -r ./buttondown ./buttondown-backup - Pull fresh content:
buttondown pull --force - Manually merge the differences
- Push the resolved content:
buttondown push
Common Error Messages
The CLI provides specific error messages for common issues:
- Missing title:
Error: --title is required for the create command - Invalid format:
Skipping [file]: Invalid format (missing frontmatter) - Upload failures:
Failed to upload image [filename]: [error message] - API errors:
Failed to create email: [error details]
Getting Help
For more information, contact Buttondown support.