Wp deploy without local
When you need to deploy WordPress changes (theme files, new plugins, content) but cannot use Local/staging because it's broken, and you don't have SSH/FTP access — only wp-admin in the browser. Covers Theme File Editor, Plugin Upload, Plugin File Editor, and CodeMirror automation tricks. Triggers on "deploy WordPress", "no SSH", "no FTP", "Local is broken", "edit theme via wp-admin", "upload plugin via wp-admin", "Theme File Editor", "Plugin File Editor".From its SKILL.md
npx -y skills add OmarEltak/wp-rescue-kit --skill wp-deploy-without-localAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
8.8 KB, ~2.1k tokens by cl100k_base, as published. Nobody here has run it
WordPress Deployment Without Local, SSH, or FTP
When the only access you have is wp-admin in a browser, here's the playbook for deploying changes.
Decision tree
What are you deploying?
├── Edit existing theme/plugin file
│ └── Theme File Editor / Plugin File Editor (Appearance/Plugins)
├── Add new content (posts, pages, products)
│ └── wp-admin → Posts/Pages, OR custom plugin with activation hooks
├── New plugin (your own code)
│ └── ZIP it → Plugins → Add New → Upload Plugin
├── New theme (your own code)
│ └── ZIP it → Appearance → Themes → Add New → Upload (deactivate active first if same slug)
├── Just need to inject a snippet (analytics, schema, ads.txt)
│ └── "Code Snippets" or "Insert Headers and Footers" plugin
└── Bulk content (hundreds of posts)
└── WP REST API + a script, OR a custom seeder plugin you upload
Tactic 1: Theme File Editor
When: quick edit to functions.php, header.php, footer.php, etc.
Path: wp-admin → Appearance → Theme File Editor
Gotcha: If the editor is missing, your wp-config.php has DISALLOW_FILE_EDIT. Add this temporarily:
// In wp-config.php, comment out or remove:
// define('DISALLOW_FILE_EDIT', true);
(Re-add it after deploy for security.)
CodeMirror trap: Theme File Editor uses CodeMirror. If you're automating via JavaScript, setting textarea.value does NOT update CodeMirror's internal state. The save would write the OLD content.
// WRONG — only updates the underlying textarea, CodeMirror still has old value
document.getElementById('newcontent').value = newContent;
// RIGHT — use CodeMirror's API
const cm = document.querySelector('.CodeMirror').CodeMirror;
cm.setValue(newContent); // sets editor content
cm.save(); // syncs to underlying textarea
document.getElementById('submit').click();
Tactic 2: Plugin Upload (for new plugins)
When: you have a plugin packaged as a .zip.
Path: wp-admin → Plugins → Add New → Upload Plugin → Choose File → Install Now → Activate
Building the ZIP locally:
# Python is installed almost everywhere
python -c "
import os, zipfile
with zipfile.ZipFile('my-plugin.zip', 'w', zipfile.ZIP_DEFLATED) as zf:
for root, dirs, files in os.walk('my-plugin'):
for f in files:
fp = os.path.join(root, f)
zf.write(fp, os.path.relpath(fp, '.'))
"
Or PowerShell on Windows:
Compress-Archive -Path my-plugin -DestinationPath my-plugin.zip -Force
Or zip CLI on macOS/Linux:
zip -r my-plugin.zip my-plugin/
The ZIP must contain a folder with the plugin name, NOT the plugin files at the root.
Tactic 3: Use a content seeder plugin
When: you need to deploy posts, pages, custom post types, terms, options, or any database content.
Don't try to add 50 posts via the wp-admin UI. Build a small plugin that runs on activation:
<?php
/**
* Plugin Name: My Content Seeder
* Description: Activate once to create content.
*/
defined('ABSPATH') || exit;
function my_seed_on_activate() {
// Idempotent: skip if exists
if (get_page_by_path('my-page', OBJECT, 'page')) return;
wp_insert_post([
'post_title' => 'My Page',
'post_name' => 'my-page',
'post_type' => 'page',
'post_status' => 'publish',
'post_content' => 'Content here',
]);
// Set options too
update_option('my_setting', 'value');
}
register_activation_hook(__FILE__, 'my_seed_on_activate');
ZIP it, upload it, activate it — all your content lands in one click. Add a register_deactivation_hook if you want clean uninstall.
Tactic 4: Insert Headers and Footers / Code Snippets
When: you need to add <script>, <meta>, or PHP snippets without uploading code.
- Insert Headers and Footers (by WPBeginner) — UI for adding scripts and meta tags
- Code Snippets (by Code Snippets Pro) — UI for running PHP snippets safely
Both are free, install from Plugins → Add New → search. Faster than editing functions.php for one-off injections.
Tactic 5: Direct DB edits via phpMyAdmin
When: you need to fix corrupt data, change siteurl after a domain change, or manage options that aren't in any UI.
Path: Hosting panel → Databases → phpMyAdmin → run SQL.
Most useful queries:
-- Change site URL after domain migration
UPDATE wp_options SET option_value = 'https://newdomain.com' WHERE option_name = 'siteurl';
UPDATE wp_options SET option_value = 'https://newdomain.com' WHERE option_name = 'home';
-- Find a user by email
SELECT * FROM wp_users WHERE user_email = '[email protected]';
-- Reset admin password (use with caution)
UPDATE wp_users SET user_pass = MD5('NEW_PASSWORD_HERE') WHERE user_login = 'admin';
-- List active plugins
SELECT option_value FROM wp_options WHERE option_name = 'active_plugins';
-- Disable all plugins (recovery from white screen of death)
UPDATE wp_options SET option_value = 'a:0:{}' WHERE option_name = 'active_plugins';
-- Switch active theme
UPDATE wp_options SET option_value = 'twentytwentyfive' WHERE option_name IN ('template', 'stylesheet');
Tactic 6: WordPress REST API (for content automation)
When: you want to script content creation from outside WordPress.
# Auth: create an Application Password (Users → Profile → Application Passwords)
APP_PASS="xxxx xxxx xxxx xxxx"
# Create a post
curl -X POST "https://YOUR-SITE.com/wp-json/wp/v2/posts" \
-u "USERNAME:$APP_PASS" \
-H "Content-Type: application/json" \
-d '{
"title": "Hello from REST",
"content": "Body content here",
"status": "publish"
}'
# List all posts
curl -u "USERNAME:$APP_PASS" "https://YOUR-SITE.com/wp-json/wp/v2/posts?per_page=100"
Application Passwords work with HTTPS and don't require any extra plugin since WP 5.6.
Tactic 7: All-in-One WP Migration
When: you DO have a working source (Local, staging, another live install) and want to push the entire site somewhere.
Path:
- Install plugin on source: Plugins → Add New → search "All-in-One WP Migration" → Install
- Source: Tools → All-in-One WP Migration → Export → File → download
.wpress - Destination: install same plugin → Import → Upload → upload
.wpress→ confirm overwrite - Save permalinks: Settings → Permalinks → Save (no changes, just save)
Free version limit: 512MB upload. For bigger sites:
- Use the "Export to FTP/Dropbox/GDrive" extensions (paid)
- Or split your site (export DB only, copy media via FTP separately)
Order of operations (for a real migration)
1. Backup the destination (always — All-in-One Backup → Create)
2. Edit any environment-specific files (wp-config.php) via Theme File Editor or hosting File Manager
3. Upload + activate plugins (any custom code in plugin form)
4. Upload + switch theme (Appearance → Themes → Add New → Upload Theme)
5. Run Permalinks save (Settings → Permalinks → Save)
6. Flush all caches at hosting and WordPress level
7. Test in incognito (NOT just your logged-in browser)
Verification checklist after deploy
- View source on the homepage and confirm
wp-content/themes/<your-theme>appears in CSS paths - Check the page title matches what you expect
- Test in incognito (cookies bypass cache; only incognito tells you what users see)
- Test on mobile (different cache, different user agent)
- Run
curl -sI https://YOUR-SITE.com/— confirm200 OKand check cache headers - If using a hosting panel CDN, FLUSH IT after deploy
What you cannot do without SSH
Realistic limits to know:
- Run wp-cli — needs shell access. Workaround: install "WP-CLI Login" plugin (interactive) or rely on REST API + custom plugins.
- Edit
wp-config.php— possible via File Manager in hosting panel, but NOT through wp-admin (security restriction). - Bulk file operations on uploads — slow via wp-admin. Use FTP/SFTP if available, or a Media Library bulk plugin.
- Cron jobs (real ones) — wp-cron runs in PHP per request. Real OS-level crons need SSH or hosting panel cron config.
- Server-level config (PHP version, memory limit, max upload size) — usually in hosting panel, not wp-admin.
Skill maintained at https://github.com/OmarEltak/wp-rescue-kit
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.
Gives 0 of the 12 instructions most ship operate skills give in ~2.1k tokens
Counted across 779 of the 1,178 authors here whose files we hold, read 2026-08-07
- Document a rollback plan before deploymentin 41 of 779, across 22 files
- Update the changelogin 21 of 779, across 19 files
- Run the test suitein 20 of 779
- Create an annotated git tagin 20 of 779
- Clean up feature flags after full rolloutin 18 of 779, across 10 files
- Verify deployment health after launchin 18 of 779, across 10 files
- Test both feature flag statesin 17 of 779, across 9 files
- Verify the working tree is cleanin 17 of 779
- Make database migrations backward-compatiblein 16 of 779, across 8 files
- Set up error monitoring before launchin 15 of 779, across 7 files
- Monitor metrics at each rollout stagein 14 of 779, across 5 files
- Create a GitHub releasein 14 of 779
Said here and by no other author read
- package custom plugins or themes into a zip file before upload
- ensure plugin zip files contain a named parent folder
- use CodeMirror API to update and save editor content
- make content seeder functions idempotent
- backup the destination site before changing it
- save permalinks after completing a migration
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.