WordPress Automation — manage posts, pages, and users via the REST API
Project description
WPA — WordPress Automation
CLI tool for WordPress automation — manage posts, pages, users, media, comments, and taxonomy terms via the REST API.
Install
pip install wpa
Or install from source:
git clone https://github.com/cadentdev/wpa.git
cd wpa
pip install -e .
Create a site config
wpa site add
This prompts for your WordPress URL, username, application password (hidden), and optional admin path. Configs are stored at ~/.config/wpa/<site-name>/.env with 600 permissions.
WordPress Application Password
- Log into wp-admin → Users → Your Profile
- Scroll to "Application Passwords"
- Enter name: "WPA CLI", click "Add New Application Password"
- Copy the generated password (use it during
--new-sitesetup)
Usage
Manage posts
# List posts (with filtering)
wpa post list --site mysite
wpa post list --site mysite --status draft --author 1
wpa post list --site mysite --category 5 --tag 12
wpa post list --site mysite --search "announcement" --orderby date --order desc
# Get a single post
wpa post get 42 --site mysite
# Create a post
wpa post create --site mysite --title "My Post" --content "<p>Hello</p>" --status draft
# Update a post
wpa post update 42 --site mysite --title "Updated Title" --status publish
# Delete a post (moves to trash; use --force to permanently delete)
wpa post delete 42 --site mysite
wpa post delete 42 --site mysite --force
Manage pages
# List pages
wpa page list --site mysite
wpa page list --site mysite --status publish --parent 10
# Get a single page
wpa page get 42 --site mysite
# Create a page from markdown file
wpa page create --site mysite pages/about.md
# Create a page from flags
wpa page create --site mysite --title "About" --content "<p>About us</p>"
# Publish shortcut (equivalent to wpa page create with markdown)
wpa publish pages/your-page.md --site mysite
# Update a page
wpa page update 42 --site mysite --title "New Title" --parent 10
# Delete a page
wpa page delete 42 --site mysite
Manage users
# List all users
wpa user list --site mysite
# List users as JSON, specific fields only
wpa user list --site mysite --format json --fields id,username,email,roles
# Export users to TSV
wpa user list --site mysite --format tsv > users.tsv
# Filter by role or search term
wpa user list --site mysite --role editor
wpa user list --site mysite --search "jane"
# Get a single user
wpa user get 42 --site mysite
# Create a user
wpa user create --site mysite --username jdoe --email jdoe@example.com --role author
# Update a user
wpa user update 42 --site mysite --email newemail@example.com --role editor
# Set a user's role (shortcut for update --role)
wpa user set-role 42 editor --site mysite
# Delete a user (reassign their posts to user 1)
wpa user delete 42 --site mysite --reassign 1
Manage media
# List media items
wpa media list --site mysite
wpa media list --site mysite --media-type image --per-page 50
# List media as JSON, specific fields only
wpa media list --site mysite --format json --fields id,title,source_url,media_type
# Get a single media item
wpa media get 123 --site mysite
# Import (upload) a local file as a WordPress media item
wpa media import /path/to/photo.jpg --site mysite
wpa media import /path/to/photo.jpg --site mysite --title "Cover photo" --alt-text "Team at launch"
# Delete a media item (moves to trash; use --force to permanently delete)
wpa media delete 123 --site mysite
wpa media delete 123 --site mysite --force
Output formats: table (default), json, csv, tsv. Use --fields to select columns (available: id, username, email, first_name, last_name, display_name, roles, registered, url).
Manage comments
# List comments (default shows approved only; filter by status, post, author)
wpa comment list --site mysite
wpa comment list --site mysite --status hold
wpa comment list --site mysite --post 42 --status approved
wpa comment list --site mysite --author-email "reviewer@example.com"
# Get a single comment
wpa comment get 123 --site mysite
# Create a comment
wpa comment create --site mysite --post 42 --content "<p>Thanks for posting!</p>" \
--author-name "Reviewer" --author-email "reviewer@example.com"
# Update comment content or metadata
wpa comment update 123 --site mysite --content "<p>Edited.</p>"
# Moderation shortcuts (wp-cli parity)
wpa comment approve 123 --site mysite
wpa comment unapprove 123 --site mysite # move back to "hold"
wpa comment spam 123 --site mysite
wpa comment unspam 123 --site mysite # restore from spam to approved
wpa comment trash 123 --site mysite # soft delete
# Hard delete (moves to trash by default; --force skips trash)
wpa comment delete 123 --site mysite
wpa comment delete 123 --site mysite --force
Manage taxonomy terms (categories, tags, custom)
# Categories via the alias (pre-sets --taxonomy=category)
wpa category list --site mysite
wpa category list --site mysite --search "news"
wpa category create --site mysite --name "Announcements" --description "Site announcements"
wpa category update 7 --site mysite --description "Major site announcements"
wpa category delete 7 --site mysite # always permanent; terms cannot be trashed
# Tags via the alias (pre-sets --taxonomy=post_tag)
wpa tag list --site mysite
wpa tag create --site mysite --name "wordpress" --description "Posts about WordPress"
wpa tag delete 12 --site mysite
# Generic term interface for built-in or custom taxonomies
wpa term list --site mysite --taxonomy category
wpa term list --site mysite --taxonomy post_tag
wpa term list --site mysite --taxonomy genre # custom taxonomy
wpa term get 7 --site mysite --taxonomy category
wpa term create --site mysite --taxonomy post_tag --name "api"
wpa term update 7 --site mysite --taxonomy category --name "Big Announcements"
wpa term delete 7 --site mysite --taxonomy category
Note on delete: The WordPress REST API does not support trashing taxonomy terms, so wpa term delete (and the category / tag aliases) always performs a permanent delete. There is no --force flag — force is implicit.
Output options
All list commands support these output modifiers:
# Output only IDs
wpa post list --site mysite --ids
# Output only the count
wpa post list --site mysite --count
# Output a single field per result
wpa post list --site mysite --field title
# Select specific columns
wpa user list --site mysite --fields id,username,email
# Debug mode (print HTTP request/response details)
wpa post list --site mysite --debug
Site management
wpa site add
wpa site list
wpa --version
Multi-site behavior
| Configs | --site flag |
Behavior |
|---|---|---|
| 0 | No | Prompts to create a new config |
| 1 | No | Uses the single config automatically |
| 2+ | No | Prompts to select from list |
| Any | Yes | Uses the named config (error if not found) |
Markdown file format
---
title: "Your Page Title"
slug: "your-page-slug"
status: draft
---
Page content in markdown here...
title(required): Page titleslug(optional): URL slugstatus(optional):draft(default),publish,pending, orprivate
Site config format
Each site config is stored at ~/.config/wpa/<name>/.env:
WP_SITE_URL=https://example.com
WP_USER=your-username
WP_APP_PASSWORD=xxxx xxxx xxxx xxxx
WP_ADMIN_PATH=wp-admin
WP_ADMIN_PATHis optional (defaults towp-admin). Override it if your site uses a custom admin URL.- The
XDG_CONFIG_HOMEenvironment variable is respected if set.
Migration from repo-root .env
If you have an existing .env in the repo root and no XDG configs, the tool will offer to migrate it on first run.
Safety and Security
- Default status is always
draft— never publishes unless frontmatter explicitly says otherwise - HTTPS enforced for public addresses — rejects
http://for public URLs; allows HTTP for private/LAN addresses (RFC 1918, localhost,.lan/.local/.test/.internalTLDs) with a warning - Credentials in XDG config — stored outside the repo at
~/.config/wpa/with 600 permissions - Password input hidden — uses
getpassduring interactive setup - Status validation — rejects typos and invalid values in frontmatter
- Site name validation — only alphanumeric characters and hyphens allowed
- Connection error handling — timeouts and network failures produce clear messages, not tracebacks
Development
pip install -e '.[dev]'
pytest --cov=wpa --cov-report=term-missing
Links
- Product Requirements Document — Vision, design principles, command structure, and implementation roadmap
- Getting Started — REST API setup, Wordfence notes, staging guide
- Release Notes
- Contributing
- WP-CLI Command Inventory — Complete catalog of WP-CLI 2.12.0 commands used as the template for WPA planning
- WP-CLI REST API Mapping Matrix — Feasibility classification of every WP-CLI command against the REST API
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file wpa-0.8.0.tar.gz.
File metadata
- Download URL: wpa-0.8.0.tar.gz
- Upload date:
- Size: 53.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ac585b3b36ad5c5f0c94d2c47750ac2f830377ffdbf697d78c48292cfbe5ed2b
|
|
| MD5 |
b2ce7e88730f34d3240617b00e43779e
|
|
| BLAKE2b-256 |
7f99fbc41fe059bc7ccebf5886cefeba0ee76ca4eefd9cce0771f60b21ec7968
|
File details
Details for the file wpa-0.8.0-py3-none-any.whl.
File metadata
- Download URL: wpa-0.8.0-py3-none-any.whl
- Upload date:
- Size: 36.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
106c24d5372737266f322969b529dde1115a56a57934e9e2d158d37a69d950b2
|
|
| MD5 |
0ffc8d77aabaed3949aa320697dc6208
|
|
| BLAKE2b-256 |
350d973bf6d0263e78b113df29a1d7787cf63a648e306860ad9046f947ab31cc
|