wp-deploy-without-local — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited wp-deploy-without-local (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
When the only access you have is wp-admin in a browser, here's the playbook for deploying changes.
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 uploadWhen: 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();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 -ForceOr 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.
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.
When: you need to add <script>, <meta>, or PHP snippets without uploading code.
Both are free, install from Plugins → Add New → search. Faster than editing functions.php for one-off injections.
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');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.
When: you DO have a working source (Local, staging, another live install) and want to push the entire site somewhere.
Path:
.wpress.wpress → confirm overwriteFree version limit: 512MB upload. For bigger sites:
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)wp-content/themes/<your-theme> appears in CSS pathscurl -sI https://YOUR-SITE.com/ — confirm 200 OK and check cache headersRealistic limits to know:
Skill maintained at https://github.com/OmarEltak/wp-rescue-kit
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.