rapadura PHP Com Rapadura
On this page

Recipes: WordPress

By the end of this page you have an event site on WordPress with real content, a menu, a footer, a site icon, images and a co-organizer, all from the terminal or through your agent. The commands were tested on the production multisite with a subsite administrator account, same as yours.

How it works, in one line: rapadura wp <site> -- <wp-cli command>. Everything after -- goes to wp-cli, already pinned to your site and your user. What is allowed is in WordPress sites.

1. Create the site

shell
rapadura wp create php-sobral-2026 --blueprint event --title "PHP Sobral 2026" --email you@example.com
output
PHP Sobral 2026 is live at https://php-sobral-2026.rapadura.net (WordPress, blueprint event).
site: https://php-sobral-2026.rapadura.net
  wp-admin: https://php-sobral-2026.rapadura.net/wp-admin/
  REST: https://php-sobral-2026.rapadura.net/wp-json/wp/v2/
  WordPress login: yourlogin
  application password (shown once): xxxx xxxx xxxx xxxx xxxx xxxx
  note: Shown once. It signs your agent in to the WordPress REST API as you (HTTP basic auth). Application passwords belong to your WordPress account, not to one site: it works on every site of the network where you have a role, and has no permissions anywhere else. Keep it like a token; revoke it in wp-admin › Users › Profile if it leaks.
  next: Edit content with wp-cli: rapadura wp php-sobral-2026.rapadura.net -- post list --post_type=page
  next: Or use the REST API at https://php-sobral-2026.rapadura.net/wp-json/wp/v2/ with HTTP basic auth: yourlogin and the application password.
  next: To log into https://php-sobral-2026.rapadura.net/wp-admin/ in a browser, set a password with: rapadura wp password php-sobral-2026.rapadura.net

Keep the application password: it is shown once and it is what gives access to the REST API (step 8). Lost it? rapadura wp credentials php-sobral-2026 mints another. --email is only needed the first time.

Blueprints: blank (empty), event (home, schedule, speakers, venue, registration), meetup (next meetup, past editions, give a talk) and course (about, syllabus, enroll). rapadura wp blueprints lists them. The blueprint pages are in Portuguese, with placeholder text.

Ask your agent
Create a WordPress site on rapadura called php-sobral-2026 with the event blueprint and the title "PHP Sobral 2026". Keep the application password in this session only, never in a file, and tell me the address and the wp-admin link.

2. See what came with it

shell
rapadura wp php-sobral-2026 -- post list --post_type=page --fields=ID,post_title,post_name
output
ID	post_title	post_name
6	Local	local
7	Inscrições	inscricoes
5	Palestrantes	palestrantes
4	Programação	programacao
3	Início	inicio

The blueprint pages come with placeholder text. The blueprint has also set up the top menu (step 5) and the footer (step 6), and deleted the "Sample Page" and "Hello world!" post WordPress puts on every new site.

The blank blueprint does none of this: the site stays as WordPress made it. To delete the two samples on a blank site:

shell
rapadura wp php-sobral-2026 -- post delete 2 1 --force

3. Replace a page's content with your own file

Write the content on your computer. With block markup (<!-- wp:... -->) the editor opens each part as an editable block; plain HTML works too, as a "Classic" block.

HTML
<!-- programacao.html -->
<!-- wp:heading -->
<h2 class="wp-block-heading">Saturday, November 14</h2>
<!-- /wp:heading -->

<!-- wp:table -->
<figure class="wp-block-table"><table><tbody>
<tr><td>09:00</td><td>Check-in</td></tr>
<tr><td>09:30</td><td>Opening</td></tr>
<tr><td>10:00</td><td>PHP 8.5 in practice</td></tr>
</tbody></table></figure>
<!-- /wp:table -->
shell
ID=$(rapadura wp php-sobral-2026 -- post list --post_type=page --name=programacao --field=ID)
rapadura wp php-sobral-2026 -- post update "$ID" --post_content="$(cat programacao.html)"
output
Success: Updated post 4.

The content travels inside the command, hence the $(cat ...). Passing the file name (post update 4 programacao.html) does not work: wp-cli runs on the server and would look for the file there, and rapadura refuses it. For very large pages (above roughly 100 KB), use the REST API (step 9).

4. Create a new page

shell
rapadura wp php-sobral-2026 -- post create --post_type=page --post_status=publish \
  --post_title="Sponsors" --post_name=sponsors \
  --post_content="<!-- wp:paragraph --><p>Want to support us? Write to contato@phpcomrapadura.org.</p><!-- /wp:paragraph -->" \
  --porcelain
output
11

--porcelain prints only the new page's ID, handy for scripts and agents.

5. Top menu

The network's theme is Twenty Twenty-Five, a block theme. Menus made with wp menu do not show up in it: the header uses a navigation block, which reads the site's most recent navigation post.

The blueprint has already created that post, "Menu principal", with a link to every page except the home page, labeled with the page titles in blueprint order. To change items, order or labels, update the post with the whole list, one navigation-link per item:

shell
MENU=$(rapadura wp php-sobral-2026 -- post list --post_type=wp_navigation --field=ID)
rapadura wp php-sobral-2026 -- post update "$MENU" \
  --post_content='<!-- wp:navigation-link {"label":"Schedule","url":"/programacao/"} /--><!-- wp:navigation-link {"label":"Speakers","url":"/palestrantes/"} /--><!-- wp:navigation-link {"label":"Venue","url":"/local/"} /--><!-- wp:navigation-link {"label":"Register","url":"/inscricoes/"} /-->'
output
Success: Updated post 8.

A blank site has no such post yet. Create it with the same content:

shell
rapadura wp php-sobral-2026 -- post create --post_type=wp_navigation --post_status=publish \
  --post_title="Main menu" --post_content='<!-- wp:navigation-link {"label":"Schedule","url":"/programacao/"} /-->' --porcelain

The theme's default footer has sample links (Blog, About, FAQs, Shop...). The blueprint has already replaced it with one line carrying the site title, in Portuguese like the rest of the blueprint: "PHP Sobral 2026 · uma realização da comunidade PHP Com Rapadura". It is your own version of the theme's "footer" part, a wp_template_part post. To change the text, update that post:

shell
ID=$(rapadura wp php-sobral-2026 -- post list --post_type=wp_template_part --name=footer --field=ID)
rapadura wp php-sobral-2026 -- post update "$ID" \
  --post_content='<!-- wp:group {"layout":{"type":"constrained"}} --><div class="wp-block-group"><!-- wp:paragraph {"align":"center"} --><p class="has-text-align-center">PHP Sobral 2026 · organized by the <a href="https://phpcomrapadura.org">PHP Com Rapadura</a> community</p><!-- /wp:paragraph --></div><!-- /wp:group -->'
rapadura wp php-sobral-2026 -- cache flush
output
Success: Updated post 9.
Success: The cache was flushed.

On a blank site the footer is still the theme's. Create your own version and tie it to the theme and to the footer area; without the two post term set lines WordPress ignores the post:

shell
ID=$(rapadura wp php-sobral-2026 -- post create --post_type=wp_template_part --post_status=publish \
  --post_name=footer --post_title=Footer --porcelain \
  --post_content='<!-- wp:group {"layout":{"type":"constrained"}} --><div class="wp-block-group"><!-- wp:paragraph {"align":"center"} --><p class="has-text-align-center">PHP Sobral 2026 · organized by the <a href="https://phpcomrapadura.org">PHP Com Rapadura</a> community</p><!-- /wp:paragraph --></div><!-- /wp:group -->')
rapadura wp php-sobral-2026 -- post term set "$ID" wp_theme twentytwentyfive
rapadura wp php-sobral-2026 -- post term set "$ID" wp_template_part_area footer
rapadura wp php-sobral-2026 -- cache flush

To go back to the theme's original footer, on any site, delete the post (post delete "$ID" --force).

7. Title, tagline and icon

shell
rapadura wp php-sobral-2026 -- option update blogname "PHP Sobral 2026"
rapadura wp php-sobral-2026 -- option update blogdescription "The PHP meetup of the Ceará backlands"
ICON=$(rapadura wp php-sobral-2026 -- media import https://www.php.net/images/logos/new-php-logo.png --title="Logo" --porcelain)
rapadura wp php-sobral-2026 -- option update site_icon "$ICON"

media import takes http(s) addresses: the server downloads the image. For a file on your computer, use the REST API (next step).

8. Images from your computer (REST API)

With the login and the application password from step 1:

shell
export WP_SITE=https://php-sobral-2026.rapadura.net
export WP_AUTH="yourlogin:xxxx xxxx xxxx xxxx xxxx xxxx"

curl -s -u "$WP_AUTH" \
  -H "Content-Disposition: attachment; filename=palco.png" \
  -H "Content-Type: image/png" \
  --data-binary @palco.png \
  "$WP_SITE/wp-json/wp/v2/media" | jq '{id, source_url}'
output
{
  "id": 15,
  "source_url": "https://php-sobral-2026.rapadura.net/wp-content/uploads/sites/7/2026/10/palco.png"
}

To put the image on a page, use source_url in an image block:

HTML
<!-- wp:image --><figure class="wp-block-image"><img src="https://php-sobral-2026.rapadura.net/wp-content/uploads/sites/7/2026/10/palco.png" alt="The PHP Sobral stage"/></figure><!-- /wp:image -->

Upload space per site is 100 MB.

9. Pages through the REST API

The same application password creates and edits pages. Good for agents that prefer HTTP, and for large content.

shell
# list
curl -s -u "$WP_AUTH" "$WP_SITE/wp-json/wp/v2/pages?per_page=50&_fields=id,slug,title"

# create
curl -s -u "$WP_AUTH" -H "Content-Type: application/json" \
  -d '{"title":"Code of conduct","slug":"conduct","status":"publish","content":"<!-- wp:paragraph --><p>Respect above all.</p><!-- /wp:paragraph -->"}' \
  "$WP_SITE/wp-json/wp/v2/pages" | jq '{id, link}'
output
{
  "id": 16,
  "link": "https://php-sobral-2026.rapadura.net/conduct/"
}
shell
# update page 16
curl -s -u "$WP_AUTH" -H "Content-Type: application/json" \
  -d '{"status":"draft"}' "$WP_SITE/wp-json/wp/v2/pages/16" | jq '{id, status}'

The password belongs to your WordPress account, not to this one site: it works on every site of the network where you have a role (your own sites) and has no permissions anywhere else. The full reference is the WordPress REST API.

10. Bring in a co-organizer

shell
rapadura wp php-sobral-2026 -- user create maria maria@example.com --role=editor
output
Success: Created user 6.
Password: t7Qx2LmV9rBz1sPw4KcE

The password is shown once; send it to the person over a safe channel. The login takes lowercase letters and digits only. Roles: editor (all content), author (their own posts), administrator (the whole site, appearance included). To change it later: user set-role maria author.

11. Draft, unpublish, delete

shell
rapadura wp php-sobral-2026 -- post update 16 --post_status=draft   # offline, kept
rapadura wp php-sobral-2026 -- post delete 16                       # to the trash
rapadura wp php-sobral-2026 -- post delete 16 --force               # gone for good

12. Back up the content

shell
rapadura wp php-sobral-2026 -- export --stdout > php-sobral-2026.xml

Always --stdout: writing the file on the server (--dir) is refused.

The file is a WXR with pages, posts, menus and references to the images. To restore it on another site: activate the importer (plugin activate wordpress-importer) and use Tools › Import in wp-admin.

13. Replace a string across the site

Always with --dry-run first:

shell
rapadura wp php-sobral-2026 -- search-replace "2025" "2026" --dry-run
rapadura wp php-sobral-2026 -- search-replace "2025" "2026"

rapadura always limits search-replace to your site's tables (wp_7_posts, wp_7_options...). The output lists each table and how many replacements it got.

14. For agents: JSON output

With --json before the --, the answer separates output, errors and exit status:

shell
rapadura --json wp php-sobral-2026 -- option get blogname
output
{
  "host": "php-sobral-2026.rapadura.net",
  "args": [
    "option",
    "get",
    "blogname"
  ],
  "stdout": "PHP Sobral 2026\n",
  "stderr": "",
  "exit_code": 0,
  "duration": "1.2s"
}

Over MCP, the wp_cli tool takes the same arguments as a list: ["option", "get", "blogname"].

What you cannot do, and what to do instead

I want to what happens do this
install a plugin or theme refused ask the administrator; today only Twenty Twenty-Five is enabled
media import ./photo.jpg refused: the path would be read on the server REST API (step 8) or a URL
post create page.html refused, same reason --post_content="$(cat page.html)"
wp menu create works, but the theme does not show it a wp_navigation post (step 5)
change my password or credentials user update is refused rapadura wp password / rapadura wp credentials
touch another site or the network refused only your own site is reachable

Ready-made prompts

Ask your agent
On the php-sobral-2026 WordPress site on rapadura, replace the placeholder text of every blueprint page with real content about PHP Sobral 2026 (November 14, Sobral, Ceará). Use WordPress block markup and show me the final list of pages.
Ask your agent
On php-sobral-2026, relabel the top menu in English (Schedule, Speakers, Venue, Register), add a link to the Sponsors page, and change the footer to say "organized by the PHP Com Rapadura community". Check by opening the home page.
Ask your agent
Upload the photos in ./photos to the php-sobral-2026 media library through the REST API, using the application password I will paste, and create a "Gallery" page with all of them.
Ask your agent
Back up the content of php-sobral-2026 to php-sobral-2026.xml and tell me how many pages and images it has.