Install
Upload it under Plugins → Add New Plugin → Upload Plugin, then activate.
Install straight from GitHub with WP-CLI:
wp plugin install https://github.com/amabdomo/wp-plugins-themes-manager/releases/download/v2.5.5/plugin-theme-manager.zipPlugin & Theme Manager maintains a portable catalog of WordPress plugins and themes. Public remote packages stay metadata-only and download on demand, while packages without a verified public source remain checksum-protected offline archives.
What it does
- Ships with on-demand catalog entries for WooCommerce, Elementor, PRO Elements, and Hello Elementor.
- Adds future packages from WordPress.org, public GitHub repositories, public HTTPS manifests, or local ZIP uploads.
- Keeps WordPress.org, GitHub, and manifest packages on demand without permanently storing their ZIP files.
- Offers Add and Add, install & activate for every intake source.
- Downloads on-demand packages into protected temporary storage, validates them, installs or updates the site, and removes temporary files afterward.
- Installs and activates offline library archives without overwriting an existing installation.
- Checks every remote source only when an administrator clicks Check plugin & theme updates, then shows available installed-package updates in the PT Manager admin-menu badge.
- Captures folder-based installed plugins and themes into canonical offline ZIP archives.
- Exports the manager, catalog metadata, and any explicitly embedded offline archives without navigating away from the admin page.
The manager is intentionally not self-updating. Export the current portable ZIP before manually replacing it.
Storage model
Every catalog entry has one of two storage modes:
- On demand: Source metadata remains in
library-manifest.json. Installation and updates download a temporary verified package and do not increase the manager's persistent size. - Embedded: A verified
<slug>.ziparchive is stored beside the manager for offline installation.
Manual plugin and theme card order is stored per item in library-manifest.json, survives package updates, and travels with the portable export.
Default behavior:
| Source | Storage mode |
|---|---|
| WordPress.org | On demand |
| Public GitHub repository | On demand |
| Public HTTPS manifest | On demand |
| Local ZIP upload | Embedded |
| Installed site package | Verified WordPress.org/GitHub on demand, otherwise embedded |
The generic storage model applies to all future plugins and themes, not only the default catalog.
Default catalog
| Package | Type | Source | Storage |
|---|---|---|---|
| WooCommerce | Plugin | WordPress.org | On demand |
| Elementor | Plugin | WordPress.org | On demand |
| PRO Elements | Plugin | https://github.com/proelements/proelements |
On demand |
| Hello Elementor | Theme | WordPress.org | On demand |
Default entries cannot be removed from the catalog. Their installed site copies can still be activated and updated normally.
Library layout
plugin-theme-manager/
├── bundled-plugins/ Optional embedded <slug>.zip archives
├── bundled-themes/ Optional embedded <slug>.zip archives
├── library-manifest.json Schema-4 catalog, editable source references, storage, and checksums
├── assets/ Admin interface
├── includes/ Manager classes
└── plugin-theme-manager.php
The manifest is authoritative. Do not place arbitrary files in the bundled directories. Use Add or capture so the manager can validate package identity and update the manifest transactionally.
Version 2.5 adds portable WordPress.org source-slug overrides through schema 4. Schema-3 manifests migrate transactionally while preserving every catalog entry and archive. Earlier schema-1 and schema-2 migrations remain supported, including conversion of the default bundled packages to on-demand entries.
Use
- Install and activate Plugin & Theme Manager.
- Open PT Manager in WordPress admin.
- Select a default entry or open Add or capture for another package.
- Choose Install & activate to download an on-demand package or install an embedded archive.
- Click Check plugin & theme updates to refresh every remote source, then use the per-item update action where an update is available.
- Add an installed item to let the manager verify WordPress.org, then an exact GitHub repository declared in its headers, before falling back to an offline ZIP.
- Use Edit source on an installed item or catalog card to set a WordPress.org source slug, exact GitHub repository URL, or HTTPS manifest manually. The package slug remains stable while its portable source reference changes.
- Use Move up and Move down on each plugin or theme card to set its catalog position.
- Open Settings to review storage paths or export the portable manager.
If catalog creation succeeds but installation or activation fails, the catalog entry remains and the interface reports the partial result. Removing a non-default catalog or library entry never deletes its installed site copy.
Package sources
WordPress.org
Enter a plugin or theme slug. The manager stores only catalog metadata. Install and update actions retrieve the current official package into protected temporary storage.
Public GitHub repository
Enter an exact repository URL:
https://github.com/owner/repository
A terminal .git suffix is accepted. SSH URLs, shorthand names, credentials, ports, query strings, fragments, and repository subpaths are rejected. Private repositories and access tokens are not supported.
The manager uses GitHub's latest published, non-draft, non-prerelease release. If no release exists, it uses the default branch. GitHub's generated archive wrapper is removed, but the WordPress package must exist at the repository root.
Package identity and version come from the actual WordPress headers, never from the repository name or release tag. Update checks probe the commit revision first and inspect the archive only when necessary. Validated headers are cached by immutable commit SHA.
Public unauthenticated GitHub API limits apply. Rate-limit responses are shown as source errors rather than triggering unsafe fallback downloads.
Public HTTPS manifest
The manifest response must be JSON with these fields:
{
"slug": "example-plugin",
"type": "plugin",
"name": "Example Plugin",
"version": "2.4.0",
"download_url": "https://downloads.example.com/example-plugin-2.4.0.zip",
"sha256": "optional-lowercase-sha256-of-the-zip"
}
Required fields are slug, type, version, and download_url. The manifest and package URLs must be public HTTPS URLs. If supplied, sha256 must be the source ZIP's 64-character SHA-256 hash. The JSON response must be smaller than 256 KiB.
Local ZIP and installed items
A local ZIP must contain exactly one valid plugin or theme folder and is stored as a balanced-compression embedded archive.
When adding an installed item, the manager first verifies a matching WordPress.org package unless a custom Update URI opts out. It then checks only an exact public GitHub repository URL declared by the package's Update URI, Plugin URI, or Theme URI. Remote archive slug, type, version, and main-file identity are verified before an on-demand entry is registered. Repository names are never guessed. If neither remote source can be verified, the installed files are stored as a protected offline ZIP.
Validation and replacement safety
Before using a downloaded or uploaded package, the manager checks:
- archive traversal paths and symbolic links;
- compressed and expanded size limits;
- archive entry limits;
- a single canonical package root;
- plugin or theme headers, version, slug, and main-file identity;
- supported WordPress/PHP requirements;
- source checksums when supplied;
- embedded archive checksums before listing, installation, synchronization, update, and export.
Updates are staged beside the installed destination. Existing site folders are backed up, replacements are verified, and failures roll back. Active installed packages use WordPress maintenance mode during direct replacement.
Current limits:
- ZIP download/upload or stored archive: 50 MB
- Expanded package data: 250 MB
- ZIP archive entries: 20,000
- Installed capture-tree entries: 20,000
- Portable manifest items: 500
Export
The export includes the manager, schema-4 catalog, and any embedded offline package ZIPs. On-demand entries add only small metadata records. Inner package archives are stored without recompression, while ordinary manager files use fast compression. Development dependencies, tests, wp-env files, operation locks, stages, and backups are excluded.
On a trusted HTTPS admin page, the export streams through WordPress’s authenticated admin-post endpoint into the browser’s direct file-save picker and verifies the received byte count before closing the file. Browsers without the File System Access API use the conventional attachment response. The portable ZIP preserves catalog entries and manual ordering; on-demand entries remain metadata-only unless they were explicitly embedded.
Requirements and limits
- WordPress 5.9 or newer
- PHP 7.4 or newer
- PHP
ZipArchiveextension - Direct WordPress filesystem access for catalog and library mutations
- Single-site WordPress installation
Multisite is read-only: listing and cached update results remain available, while migration, catalog changes, settings changes, and export are blocked.
Root-level single-file plugins are not offered for capture or direct folder replacement because moving them into a folder would change their WordPress identity.
Public source checks and package downloads require outbound HTTPS access. Authenticated/private package endpoints are not supported.
Local development
Static checks:
php -l plugin-theme-manager.php
php -l includes/class-ptm-repository.php
php -l includes/class-ptm-migration.php
php -l includes/class-ptm-github.php
node --check assets/js/admin.js
The integration suite uses @wordpress/env:
npm install
npm run env:start
npm run test:php
npm run env:stop
The minimum supported stack uses .wp-env.wp59.json with WordPress 5.9 and PHP 7.4. Docker Desktop must be installed and running before wp-env starts.
Releases
1 release. Each count is every asset in that release; expand a row for the breakdown.