Skip to main content

WordPress Automation — manage posts, pages, and users via the REST API

Project description

WPA — WordPress Automation

CI Coverage Python PyPI License: MIT

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

  1. Log into wp-admin → Users → Your Profile
  2. Scroll to "Application Passwords"
  3. Enter name: "WPA CLI", click "Add New Application Password"
  4. Copy the generated password (use it during --new-site setup)

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 title
  • slug (optional): URL slug
  • status (optional): draft (default), publish, pending, or private

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_PATH is optional (defaults to wp-admin). Override it if your site uses a custom admin URL.
  • The XDG_CONFIG_HOME environment 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/.internal TLDs) with a warning
  • Credentials in XDG config — stored outside the repo at ~/.config/wpa/ with 600 permissions
  • Password input hidden — uses getpass during 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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

wpa-0.8.0.tar.gz (53.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

wpa-0.8.0-py3-none-any.whl (36.8 kB view details)

Uploaded Python 3

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

Hashes for wpa-0.8.0.tar.gz
Algorithm Hash digest
SHA256 ac585b3b36ad5c5f0c94d2c47750ac2f830377ffdbf697d78c48292cfbe5ed2b
MD5 b2ce7e88730f34d3240617b00e43779e
BLAKE2b-256 7f99fbc41fe059bc7ccebf5886cefeba0ee76ca4eefd9cce0771f60b21ec7968

See more details on using hashes here.

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

Hashes for wpa-0.8.0-py3-none-any.whl
Algorithm Hash digest
SHA256 106c24d5372737266f322969b529dde1115a56a57934e9e2d158d37a69d950b2
MD5 0ffc8d77aabaed3949aa320697dc6208
BLAKE2b-256 350d973bf6d0263e78b113df29a1d7787cf63a648e306860ad9046f947ab31cc

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page