We manage our client WordPress sites using Claude Code: publishing blog posts, deploying custom code snippets, uploading media, editing page content, and more, all from the terminal. No browser, no wp-admin clicking, no copy-pasting between tabs.
This guide focuses on the REST API approach, which handles most WordPress tasks. If you need deeper access (editing theme/plugin files or running WP-CLI), you can extend this setup by giving Claude Code SFTP access. But for everyday site management, the REST API approach is simpler and cleaner.
The core idea: WordPress has a built-in REST API. Claude Code has tools to run shell commands, read/write files, and fetch URLs. Connect the two with an application password and Claude Code can do almost anything you’d do in wp-admin, via script, on demand, fast.
The setup has three parts:
- Application passwords for API authentication
- A JSON file listing your sites and credentials
- A CLAUDE.md file teaching Claude Code how to work with your sites
Step 1: Create an Application Password
WordPress has supported application passwords natively since version 5.6. They let you authenticate REST API requests without exposing your main login credentials.
- Go to Users > Profile in wp-admin
- Scroll to Application Passwords
- Enter a name (e.g., “Claude Code”) and click Add New Application Password
- Copy the generated password (you won’t see it again)
The password will look something like aBcD eFgH iJkL mNoP qRsT uVwX (spaces included, which is normal).
Claude can now authenticate API requests with HTTP Basic Auth:
curl -u "username:aBcD eFgH iJkL mNoP qRsT uVwX" \
https://yoursite.com/wp-json/wp/v2/posts
I recommend creating a dedicated user account (e.g., api@yourcompany.com) specifically for API access rather than using your personal account.
Step 2: Create a Sites JSON File
Create a wordpress-sites.json file in your project directory. This gives Claude Code structured access to all your site details in one place.
{
"sites": [
{
"name": "My Site",
"url": "https://www.example.com/",
"credentials": {
"username": "api@yourcompany.com",
"application_password": "xxxx xxxx xxxx xxxx xxxx xxxx"
},
"theme": "Twenty Twenty-Five",
"builder": "Gutenberg",
"hosting": "SomeHostingCompany"
},
{
"name": "Client Site",
"url": "https://www.clientsite.com/",
"credentials": {
"username": "api@yourcompany.com",
"application_password": "yyyy yyyy yyyy yyyy yyyy yyyy"
},
"theme": "Kadence",
"builder": "Kadence Blocks",
"hosting": "SomeHostingCompany",
"custom_post_types": [
{
"name": "Projects",
"slug": "project",
"taxonomies": ["project-category"]
}
],
"notes": "Career posts use h3 headings for sections."
}
]
}
A few tips on what to include:
name: A human-friendly label so you can say “publish to Client Site” and Claude Code knows which one you mean.themeandbuilder: Helps Claude Code generate compatible markup (Kadence blocks vs vanilla Gutenberg, for example).custom_post_types: If your site has CPTs, list them with their slugs and taxonomies so Claude Code can interact with them via the API.notes: Per-site instructions: image handling preferences, author IDs, content conventions, anything Claude Code should know when working with that specific site.
Important: Add wordpress-sites.json to your .gitignore if your repo is public. These are real credentials.
Step 3: Write Your CLAUDE.md
The CLAUDE.md file is where you teach Claude Code how to work with your WordPress sites. Place it in your project root. Claude Code reads it automatically at the start of every conversation.
Here’s a starter template based on what we’ve learned managing sites in production:
# WordPress Site Management
WordPress site credentials and details are stored in `wordpress-sites.json`.
## WordPress API Requests
When sending JSON with special characters (quotes, em-dashes, apostrophes)
to the WordPress REST API, avoid using bash HEREDOCs as they cause quoting
issues. Instead:
1. Write the JSON to a temporary file using the Write tool
2. Use `curl -d @filename` to read from the file
3. Delete the temp file after the request completes
## Publishing Blog Posts
When publishing blog posts, do not include the featured image in the post
body. The theme automatically displays the featured image above the post
content, so including it in the body causes it to appear twice.
The CLAUDE.md is where you encode all the lessons you learn over time. Here are some real examples from our setup:
Handling Special Characters in API Requests
We learned that sending post content with curly quotes, em-dashes, or apostrophes through bash heredocs causes escaping nightmares. The fix: write the JSON payload to a temp file and use curl -d @file. This instruction in CLAUDE.md saved us from hitting this issue repeatedly.
Plugin-Specific Instructions
If you use plugins with REST API endpoints, document their quirks. For example, we use the Fluent Snippets plugin for deploying custom PHP/CSS/JS to sites. Its API has non-obvious behavior: snippets are always created as drafts regardless of the status you send, so you need a separate API call to publish them. That kind of knowledge belongs in CLAUDE.md.
Cache Purging
If your site uses a caching plugin, include the purge command so Claude Code clears the cache after making changes:
## Cache Purging
After deploying snippets or making frontend changes, purge the cache:
curl -u "user:pass" "https://site.com/?breeze_purge=1&breeze_action=breeze_purge_all"
Content Structure Conventions
If your sites follow specific content patterns, document them. We include Gutenberg block markup templates so Claude Code generates correctly structured content:
## Building with Gutenberg
Wrap all content in the Section pattern:
<!-- wp:group {"tagName":"section",...} -->
<!-- wp:group {"metadata":{"name":"Section inner container"}} -->
[CONTENT]
<!-- /wp:group -->
<!-- /wp:group -->
What You Can Actually Do
Once this is set up, you can do things like:
- “Publish this blog post to Client Site”: Claude takes your client’s exported Google Doc as Gutenberg blocks, uploads it via the REST API, and gives you the live URL.
- “Add a CSS snippet to hide the sidebar on mobile”: Claude Code creates the snippet via the plugin API, publishes it, and purges the cache.
- “Create a new project post with this content and assign it to the Residential category”: handles custom post types and taxonomies.
- “Upload this image, resize it to 1200px, convert to WebP, and set it as the featured image for the latest post”: image processing with Pillow, then upload via the media API.
- “Update the homepage hero text”: fetches the current page content, modifies it, and pushes the update.
All without opening a browser.
The Workflow in Practice
A typical interaction looks like this:
You: Publish this blog post to Shawn's site.
Use this photo as the featured image. [attaches image]
Claude Code:
1. Reads wordpress-sites.json to get Shawn's site credentials
2. Resizes the image to 1200px wide, converts to WebP
3. Uploads the image via /wp-json/wp/v2/media
4. Writes the post content as Gutenberg blocks
5. Creates the post via /wp-json/wp/v2/posts with the featured image set
6. Returns the live URL
Since these tasks run in the background, Claude Code notification sounds let you step away and hear the moment Claude finishes or needs your approval.
Claude Code gets better at this over time, not because of memory, but because your CLAUDE.md accumulates the lessons. Every time you hit a quirk (escaping issues, plugin API gotchas, content formatting rules), you add it to CLAUDE.md and never hit it again.
Security Considerations
- Application passwords can be revoked at any time from the WordPress user profile. If a password is compromised, revoke it and generate a new one.
- Keep
wordpress-sites.jsonout of version control if your repo is public. Use.gitignore. - Use a dedicated API user with only the roles/capabilities needed. Don’t use an admin account if you only need to publish posts.
- Claude Code’s permission system lets you control what commands it can run. You can pre-approve specific curl patterns (e.g.,
Bash(curl:*)) or require approval for each request.
Getting Started Checklist
- Install Claude Code (
npm install -g @anthropic-ai/claude-code) - Create an application password in WordPress for a dedicated API user
- Create
wordpress-sites.jsonwith your site details - Create a
CLAUDE.mdwith API usage instructions - Add
wordpress-sites.jsonto.gitignore - Start Claude Code in your project directory and try: “List the recent posts on [site name]”
That’s it. You now have a WordPress management setup that runs entirely from your terminal. As you use it, keep adding to your CLAUDE.md. That file is what makes the whole system work.