# Allowed Domains
Source: https://docs.wp-content.io/account/allowed-domains
Each time a WordPress site connects to your account using an API key, its domain is automatically added to the list of allowed domains for the organization linked to that key. This includes local development environments.
## Domain Status
Once a domain has been added, you can manage its status through the dashboard:
* **Active**: The domain is authorized to install and receive updates for your plugins and themes.
* **Disabled**: This acts like a blacklist. The connection with the site will be blocked, and it won’t be able to reconnect, even after deleting or reinstalling the plugin, unless it is manually re-enabled.
* **Deleted**: The domain is removed from the list, but if the site connects again using a valid API key, the domain will be automatically re-added.
This system allows you to keep control over which sites can use your private repositories.
## Requesting Additional Domains
For security reasons, the number of allowed domains per organization may be limited depending on your plan.
If you need to add more domains, please contact us at [support@wp-content.io](mailto:support@wp-content.io). We manually review these requests to ensure the service is not being misused for distributing pirated or malicious content.
# Manage API Keys
Source: https://docs.wp-content.io/account/api-keys
API keys allow your WordPress sites to connect securely to your organization and retrieve update information for your private plugins and themes.
## Overview
When an organization is created, two API Keys are generated named `publisher_key` and `readonly`. Both of the keys are scoped on "themes" and "plugins".
The `readonly` key let you see the list and download your different plugins and themes versions but cannot be used to upload a new artifact.
The `publisher_key` should be kept securely. **Everyone with this key** will be able to perform all actions on your account, including **deleting your data**.
You can revoke a key anytime by deleting it. Be careful, each key are unique so if you delete it, you will have to change the key everywhere you use it.
## Understanding scopes and permissions
There are two scopes available for API Keys : `plugins` and `themes`. For each scope, you can choose to apply permissions gradually:
1. `read` : See list and plugin or theme details
2. `update` : Upload a new artifact and update plugin or theme details
3. `create` : Create a new plugin or theme
4. `delete` : Delete an existing plugin or theme
Only owners and admins can manage API Keys.
**Need more details about scopes and permissions?**
Check out the full list of available scopes and what each permission allows [on this page](/account/users#available-scopes-and-permissions).
# Organizations
Source: https://docs.wp-content.io/account/organizations
You can manage multiple organizations from your account, each acting as a separate workspace for your plugins, themes, collaborators, and API keys.
Each organization is tied to its own subscription.
Plans are flexible and designed to fit individual developers, freelancers, and agencies.
You’ll find full pricing details here: [wp-content.io/pricing](https://wp-content.io/pricing).
Typical use cases for multiple organizations:
* Separate projects or clients
* Different internal teams
* Distinct billing needs
Everything related to deployment, API keys, and domain restrictions is managed per organization.
# Users and permissions
Source: https://docs.wp-content.io/account/users
User management is available on the Agency plan only.
It includes 5 users by default, with the option to add more seats if needed.
Each user can be assigned fine-grained permissions across different scopes like plugins, themes, API keys, billing, and more.
For every scope, you can define specific rights: read, edit, create, or delete.
This makes it easy to collaborate while keeping full control over who can access and manage each part of your organization.
Permissions can be configured at any time from your organization settings.
## Available scopes and permissions
The table below lists all available scopes and the corresponding permissions that can be granted to a user. Each permission defines the level of access the user has for a given resource, such as viewing billing information, managing plugins, or inviting new members.
Use this as a reference to configure user roles and API access appropriately.
| Scope | `Read` | `Update` | `Create` | `Delete` |
| -------------- | -------------------------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------ | ------------------------------------- |
| `organization` | View organization details | Update organization details | | |
| `billing` | View billing information and invoice history | Update billing details or change subscription plan | Subscribe to a paid plan (if not already subscribed) | Cancel the active subscription |
| `api_keys` | View API keys and their permissions | Rename an existing API key | Create a new API key with specific permissions | Revoke (delete) an existing API key |
| `users` | View organization members and their roles | Change a member’s role | Invite a new member to the organization or accept a pending invite | Remove a member from the organization |
| `plugins` | View available plugins and their metadata | Upload a new ZIP version and edit plugin metadata (name, version, readme, etc.) | Add a new plugin to the registry | Delete a plugin from the registry |
| `themes` | View available themes and their metadata | Upload a new ZIP version and edit theme metadata (name, version, readme, etc.) | Add a new theme to the registry | Delete a theme from the registry |
# Introduction
Source: https://docs.wp-content.io/api-reference/introduction
This API allows you to manage the **plugins and themes** of your organization.
It provides a simple and secure way to publish new versions, retrieve metadata, and automate deployments.
To interact with the API, you'll need a valid API key associated with your organization.
Keys can be generated and managed from your dashboard: [https://dashboard.wp-content.io](https://dashboard.wp-content.io)
## Scopes and permissions
The REST API is built on a standard CRUD model. Each permission corresponds to an HTTP method:
| **Method** | **Permission** |
| ---------- | -------------- |
| `GET` | read |
| `POST` | create |
| `PATCH` | update |
| `DELETE` | delete |
## Authentication
All requests must include a valid API key in the request header:
```
X-Api-Key: YOUR_API_KEY
```
You can find and manage your API keys in the **API Keys** section of your dashboard.
# Delete a version
Source: https://docs.wp-content.io/api-reference/plugin-versions/delete-a-version
/api-reference/openapi.yaml delete /plugins/{slug}/versions/{version}
# Get all plugin versions
Source: https://docs.wp-content.io/api-reference/plugin-versions/get-all-plugin-versions
/api-reference/openapi.yaml get /plugins/{slug}/versions
Get versions of plugins with details.
# Get plugin version details
Source: https://docs.wp-content.io/api-reference/plugin-versions/get-plugin-version-details
/api-reference/openapi.yaml get /plugins/{slug}/versions/{version}
Get version detail for a given plugin
# Update plugin version details
Source: https://docs.wp-content.io/api-reference/plugin-versions/update-plugin-version-details
/api-reference/openapi.yaml patch /plugins/{slug}/versions/{version}
Update plugin version details.
You can use this endpoint to change "latest" version of a plugin and add release notes.
# Delete a plugin
Source: https://docs.wp-content.io/api-reference/plugins/delete-a-plugin
/api-reference/openapi.yaml delete /plugins/{slug}
Delete a plugin organization.
# Get plugin details
Source: https://docs.wp-content.io/api-reference/plugins/get-plugin-details
/api-reference/openapi.yaml get /plugins/{slug}
Retrieve detailed information about a plugin from the organization.
# List all plugins
Source: https://docs.wp-content.io/api-reference/plugins/list-all-plugins
/api-reference/openapi.yaml get /plugins
Retrieve the list of plugins published in the organization. The response format is compatible with official Wordpress Repository format.
# Update plugin informations
Source: https://docs.wp-content.io/api-reference/plugins/update-plugin-informations
/api-reference/openapi.yaml patch /plugins/{slug}
# Upload a plugin
Source: https://docs.wp-content.io/api-reference/plugins/upload-a-plugin
/api-reference/openapi.yaml post /plugins
# Profile
Source: https://docs.wp-content.io/api-reference/repository/profile
/api-reference/openapi.yaml get /author
# Repository status
Source: https://docs.wp-content.io/api-reference/repository/repository-status
/api-reference/openapi.yaml get /
# Delete a version
Source: https://docs.wp-content.io/api-reference/theme-versions/delete-a-version
/api-reference/openapi.yaml delete /themes/{slug}/versions/{version}
# Get all plugin versions
Source: https://docs.wp-content.io/api-reference/theme-versions/get-all-plugin-versions
/api-reference/openapi.yaml get /themes/{slug}/versions
Get versions of plugins with details.
# Get theme version details
Source: https://docs.wp-content.io/api-reference/theme-versions/get-theme-version-details
/api-reference/openapi.yaml get /themes/{slug}/versions/{version}
Get version detail for a given plugin
# Update theme version details
Source: https://docs.wp-content.io/api-reference/theme-versions/update-theme-version-details
/api-reference/openapi.yaml patch /themes/{slug}/versions/{version}
Update plugin version details.
You can use this endpoint to change "latest" version of a plugin and add release notes.
# Delete a theme
Source: https://docs.wp-content.io/api-reference/themes/delete-a-theme
/api-reference/openapi.yaml delete /themes/{slug}
Delete a plugin organization.
# Get theme details
Source: https://docs.wp-content.io/api-reference/themes/get-theme-details
/api-reference/openapi.yaml get /themes/{slug}
Retrieve detailed information about a plugin from the organization.
# List all themes
Source: https://docs.wp-content.io/api-reference/themes/list-all-themes
/api-reference/openapi.yaml get /themes
Retrieve the list of plugins published in the organization. The response format is compatible with official Wordpress Repository format.
# Update theme informations
Source: https://docs.wp-content.io/api-reference/themes/update-theme-informations
/api-reference/openapi.yaml patch /themes/{slug}
# Upload a theme
Source: https://docs.wp-content.io/api-reference/themes/upload-a-theme
/api-reference/openapi.yaml post /themes
# Integrate in your CI/CD
Source: https://docs.wp-content.io/cli/automate
Automate your workflow
## Use docker image
The CLI is available in a docker image with PHP 8.2 and composer pre-installed on [Docker hub](https://hub.docker.com/r/wpcontent/wpc-cli). You can use `latest` tag or specify the version.
## Example of CI/CD with Gitlab
Example of .gitlab-ci.yml file to put in your git project :
```yaml .gitlab-ci.yml theme={null}
stages:
- 📦️ build
- 🚀 publish
variables:
GIT_SUBMODULE_STRATEGY: recursive
GIT_SUBMODULE_FORCE_HTTPS: "true"
PLUGIN_SLUG: dummy
WPC_CLI_VERSION: 1.1
WPC_API_KEY: 00000000-0000-0000-0000-000000000000
⛏️ generate zip:
stage: 📦️ build
image: wpcontent/wpc-cli:${WPC_CLI_VERSION}
script:
- composer install --no-dev --optimize-autoloader
- wpc plugin:build --slug=${PLUGIN_SLUG} --output-dir=./ .
artifacts:
paths:
- ./${PLUGIN_SLUG}.zip
🗂️ push to registry:
stage: 🚀 publish
image: wpcontent/wpc-cli:${WPC_CLI_VERSION}
script:
- wpc plugin:push -m "${CI_COMMIT_MESSAGE}" ./${PLUGIN_SLUG}.zip
when: manual
workflow:
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
```
## Use CLI in your Dockerfile
You can grab the latest version by copying from the official repository :
```dockerfile Dockerfile theme={null}
FROM php:8.3-alpine
COPY --from=wpcontent/wpc-cli:latest /usr/local/bin/wpc /usr/local/bin/wpc
# Run any command
RUN wpc plugin:build
```
## Original Dockerfile
If you want to create your own image, you can find original Dockerfile below.
```dockerfile Dockerfile theme={null}
FROM php:8.2-alpine AS build
LABEL Maintainer="Happy Monkey "
# Prepare system
RUN apk update && apk add --no-cache \
gettext \
git \
zip \
libzip-dev \
curl \
sudo \
unzip \
icu-dev \
bzip2-dev \
libpng-dev \
libjpeg-turbo-dev \
freetype-dev \
postgresql-dev \
g++ \
make \
autoconf
# Install PHP extensions
RUN docker-php-ext-install \
pdo_mysql \
pdo_pgsql \
bcmath \
bz2 \
gd \
intl \
zip
# Clean up
RUN rm -rf /var/cache/apk/*
# Install PHP modules
RUN docker-php-ext-configure gd --with-freetype=/usr --with-jpeg=/usr && \
docker-php-ext-install \
bz2 \
zip \
gd \
intl \
bcmath \
opcache \
calendar \
pdo_mysql \
mysqli \
pdo_pgsql \
pgsql
# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Add main command
COPY ./wpc.phar /usr/local/bin/wpc
RUN chmod +x /usr/local/bin/wpc
WORKDIR /app
```
# Installation
Source: https://docs.wp-content.io/cli/install
Manage your organization content from CLI.
## Installation
Download [wpc.phar](https://downloads.wp-content.io/wpc-cli/latest/wpc.phar) using wget or curl. For example:
```bash theme={null}
curl -O https://downloads.wp-content.io/wpc-cli/latest/wpc.phar
```
To be able to type just `wpc`, instead of php wpc.phar, you need to make the file executable and move it to somewhere in your PATH. For example:
```bash theme={null}
chmod +x wpc.phar
sudo mv wpc.phar /usr/local/bin/wpc
```
The CLI needs at least PHP 8.2 and zip extension installed to works.
# Build a plugin archive
Source: https://docs.wp-content.io/cli/plugins/build
wpc plugin:build
Generate a ZIP archive from a plugin folder, with optional metadata override and repository push.
If a `.wpcignore` file is present in the plugin folder, it will be used to exclude files from the archive. See [documentation](/cli/wpcignore) for details.
## Usage
```bash theme={null}
wpc plugin:build [options] [--] []
```
## Arguments
Input directory containing plugin sources (default: current working directory).
## Options
Plugin slug. If omitted, the working directory name will be used.
Output directory for the ZIP archive.
Name of the output ZIP file.
Override one or more plugin headers (e.g. `--header="Version=1.2.3"`).\
Only existing headers in the plugin file will be replaced, new ones will be ignored. Original file will be unchanged.
Push the archive to the configured repository.
[See push documentation](/cli/plugins/push).
Release notes used during push (ignored without push option).
Delete the ZIP file after it has been uploaded (ignored without push option).
## Examples
```bash theme={null}
# Build a zip from current working directory
$ wpc plugin:build
# Build a zip by providing all directories and files name
$ wpc plugin:build --slug=my-plugin --output-dir=build --filename=my-plugin.zip my-plugin
# Build and push a zip with a specific version and with release notes
$ wpc plugin:build --header="Version=1.2.3" --push --m "Add new block"
```
# Generate a plugin manifest
Source: https://docs.wp-content.io/cli/plugins/manifest
wpc plugin:manifest
Extract metadata from a plugin file using WordPress internals and output it as a structured manifest.
## Usage
```bash theme={null}
wpc plugin:manifest [options] [--]
```
## Arguments
Path to the main plugin file (e.g. `my-plugin/my-plugin.php`).
## Options
If set, outputs only the value of the specified property (e.g. `Name`, `Version`, `Author`, etc.).
## Examples
```bash theme={null}
# Display full manifest
$ wpc plugin:manifest my-plugin/my-plugin.php
# Output only the version
$ wpc plugin:manifest my-plugin/my-plugin.php --get=Version
```
# List and inspect plugins
Source: https://docs.wp-content.io/cli/plugins/published
wpc plugin:ls, wpc plugin:info
Retrieve the list of plugins published by your organization, or fetch detailed information about a specific plugin.
## List plugins
Use `wpc plugin:ls` to list plugins available on your account.
### Usage
```bash theme={null}
wpc plugin:ls [options]
```
### Options
Page number to retrieve.
Number of items per page.
### Examples
```bash theme={null}
# Get all plugins from organization
$ wpc plugin:ls
# Provide pagination informations
$ wpc plugin:ls --paged=2 --per-page=5
```
## Get plugin details
Use `wpc plugin:info` to retrieve full information for a plugin from the repository.
### Usage
```bash theme={null}
wpc plugin:info
```
### Arguments
Slug of the plugin on the repository.
### Examples
```bash theme={null}
# Get info from plugin with slug `dummy`
$ wpc plugin:info dummy
```
# Push a plugin archive
Source: https://docs.wp-content.io/cli/plugins/push
wpc plugin:push
Upload a ZIP archive to the configured plugin repository.
## Usage
```bash theme={null}
wpc plugin:push [options] [--]
```
## Arguments
Path to the ZIP file to upload.
## Options
Release notes for this version.
Delete the ZIP file after it has been uploaded.
## Examples
```bash theme={null}
# Push the plugin archive without message
$ wpc plugin:push dist/my-plugin.zip
# Push the plugin archive with a commit message
$ wpc plugin:push --m "🐛 Fix some bugs" dist/my-plugin.zip
# Push the plugin archive and clean previous versions
$ wpc plugin:push --clean dist/my-plugin.zip
```
# Start a new plugin
Source: https://docs.wp-content.io/cli/plugins/start
wpc plugin:start
Create a folder with a minimal plugin file. If no arguments or options are passed to the command, they can be entered interactively.
## Usage
```bash theme={null}
wpc plugin:start [options] [--] [ []]
```
## Arguments
Name of the plugin.
This will be the folder name and the slug of the plugin. If you don’t specify the slug, the name will be used to create one.
## Options
The options allow you to set the information in your plugin’s header ([see the WordPress documentation](https://developer.wordpress.org/plugins/plugin-basics/header-requirements/)).
Plugin URI plugin header
Description plugin header
Version plugin header
Requires at least plugin header
Requires PHP plugin header
Author plugin header
Author URI plugin header
License plugin header
License URI plugin header
Text Domain plugin header
Domain Path plugin header
Network plugin header
Do not ask any interactive question
## Examples
```bash Input theme={null}
$ cd /Users/mkey/Wordpress/wp-content/plugins/
$ wpc plugin:start --author="Happy Monkey" --author-uri="https://mkey.fr" --plugin-version=1.0.0 --no-interaction dummy
Plugin initialized at path : /Users/mkey/Wordpress/wp-content/plugins/dummy
```
```php Output file: dummy/dummy.php theme={null}
```bash Input theme={null}
$ wpc plugin:start
Plugin name:
Would you like to define plugin additional headers ? [N/y]
Plugin URI: <>
Description:
Version: <1.0.1>
Requires at least: <6.0>
Requires PHP: <8.2>
Author:
Author URI:
License: <>
License URI: <>
Text Domain:
Domain Path: <>
Network:<>
Plugin initialized at path : /Users/mkey/Wordpress/wp-content/plugins/dummy
```
```php Output file: dummy/dummy.php theme={null}
# Build a theme archive
Source: https://docs.wp-content.io/cli/themes/build
wpc theme:build
Generate a ZIP archive from a theme folder, with optional metadata override and repository push.
If a `.wpcignore` file is present in the theme folder, it will be used to exclude files from the archive. See [documentation](/cli/wpcignore) for details.
## Usage
```bash theme={null}
wpc theme:build [options] [--] []
```
## Arguments
Input directory containing theme sources (default: current working directory).
## Options
Theme slug. If omitted, the working directory name will be used.
Output directory for the ZIP archive.
Name of the output ZIP file.
Override one or more theme headers (e.g. `--header="Version=1.2.3"`).
Only existing headers in the theme file will be replaced, new ones will be ignored. Original file will be unchanged.
Push the archive to the configured repository.
[See push documentation](/cli/themes/push).
Release notes used during push (ignored without push option).
Delete the ZIP file after it has been uploaded (ignored without push option).
## Examples
```bash theme={null}
# Build a zip from current working directory
$ wpc theme:build
# Build a zip by providing all directories and files name
$ wpc theme:build --slug=my-theme --output-dir=build --filename=my-theme.zip my-theme
# Build and push a zip with a specific version and with release notes
$ wpc theme:build --header="Version=1.2.3" --push --m "Add new block"
```
# Generate a theme manifest
Source: https://docs.wp-content.io/cli/themes/manifest
wpc theme:manifest
Extract metadata from a theme file using WordPress internals and output it as a structured manifest.
## Usage
```bash theme={null}
wpc theme:manifest [options] [--]
```
## Arguments
Path to the stylesheet file (e.g. `my-theme/style.css`).
## Options
If set, outputs only the value of the specified property (e.g. `Name`, `Version`, `Author`, etc.).
## Examples
```bash theme={null}
# Display full manifest
$ wpc theme:manifest my-plugin/style.css
# Output only the version
$ wpc theme:manifest my-plugin/style.css --get=Version
```
# List and inspect themes
Source: https://docs.wp-content.io/cli/themes/published
wpc theme:ls, wpc theme:info
Retrieve the list of themes published by your organization, or fetch detailed information about a specific theme.
## List themes
Use `wpc theme:ls` to list themes available on your account.
### Usage
```bash theme={null}
wpc theme:ls [options]
```
### Options
Page number to retrieve.
Number of items per page.
### Examples
```bash theme={null}
# Get all themes from organization
$ wpc theme:ls
# Provide pagination informations
$ wpc theme:ls --paged=2 --per-page=5
```
## Get theme details
Use `wpc theme:info` to retrieve full information for a theme from the repository.
### Usage
```bash theme={null}
wpc theme:info
```
### Arguments
Slug of the theme on the repository.
### Examples
```bash theme={null}
# Get info from theme with slug `dummy`
$ wpc theme:info dummy
```
# Push a theme archive
Source: https://docs.wp-content.io/cli/themes/push
wpc theme:push
Upload a ZIP archive to the configured theme repository.
## Usage
```bash theme={null}
wpc theme:push [options] [--]
```
## Arguments
Path to the ZIP file to upload.
## Options
Release notes for this version.
Delete the ZIP file after it has been uploaded.
## Examples
```bash theme={null}
# Push the theme archive without message
$ wpc theme:push dist/my-theme.zip
# Push the theme archive with a commit message
$ wpc theme:push --m "🐛 Fix some bugs" dist/my-theme.zip
# Push the theme archive and clean previous versions
$ wpc theme:push --clean dist/my-theme.zip
```
# Start a new theme
Source: https://docs.wp-content.io/cli/themes/start
wpc theme:start
Create a folder with a minimal theme file. If no arguments or options are passed to the command, they can be entered interactively.
## Usage
```bash theme={null}
wpc theme:start [options] [--] [ []]
```
## Arguments
Name of the theme.
This will be the folder name and the slug of the theme. If you don’t specify the slug, the name will be used to create one.
## Options
The options allow you to set the information in your theme’s header ([see the WordPress documentation](https://developer.wordpress.org/themes/basics/main-stylesheet-style-css/)).
Version theme header
Author theme header
Author URI theme header
Theme URI theme header
Description theme header
Requires at least theme header
Requires PHP theme header
License theme header
License URI theme header
Text Domain theme header
Domain Path theme header
Tags theme header
## Interactive mode
If you don't pass any argument or option, the command runs in interactive mode. You’ll be prompted to enter the theme name and can optionally define additional headers.
## Examples
```bash Input theme={null}
$ cd /Users/mkey/Wordpress/wp-content/themes/
$ wpc theme:start --author="Happy Monkey" --author-uri="https://mkey.fr" --theme-version=1.0.0 --no-interaction dummy
Theme initialized at path : /Users/mkey/Wordpress/wp-content/themes/dummy
```
```css Output file: dummy/style.css theme={null}
/**
* Theme Name: dummy
* Description:
* Version: 1.0.0
* Author: Happy Monkey
* Author URI: https://mkey.fr
* Update URI: https://registry.wp-content.io
*
* Generated by WPC-CLI Generator (https://wp-content.io).
*/
```
```bash Input theme={null}
$ wpc theme:start
Theme name:
Would you like to define plugin additional headers ? [N/y]
Plugin URI: <>
Description:
Version: <1.0.1>
Requires at least: <6.0>
Requires PHP: <8.2>
Author:
Author URI:
License: <>
License URI: <>
Text Domain:
Domain Path: <>
Tags: <>
Network:<>
Plugin initialized at path : /Users/mkey/Wordpress/wp-content/plugins/dummy
```
```css Output file: dummy/style.css theme={null}
/**
* Theme Name: dummy
* Description: Lorem ipsum dolor sit amet
* Version: 1.0.1
* Requires at least: 6.0
* Requires PHP: 8.2
* Author: Happy Monkey
* Author URI: https://mkey.fr
* Text Domain: dummy
* Update URI: https://registry.wp-content.io
*
* Generated by WPC-CLI Generator (https://wp-content.io).
*/
```
# Usage
Source: https://docs.wp-content.io/cli/usage
Check installed version
```bash theme={null}
wpc --version
```
Get available commands
```bash theme={null}
wpc list
```
## API Key
Most actions require a valid API key. You can provide an API Key by using the global option or by defining an environment variable.
[Manage API Keys](/account/api-keys).
## Global options
Provide custom repository API url
API Key to use
Response format. Could be `json` or `human`
## Environment variables
You can provide environment variables to override some global options.
```bash theme={null}
export WPC_REPO_URL=https://registry.wp-content.io
export WPC_API_KEY=00000000-0000-0000-0000-000000000000
```
# Ignore files
Source: https://docs.wp-content.io/cli/wpcignore
Exclude files during plugin and theme build process.
The `.wpcignore` file works like a `.gitignore`: it allows you to specify files or directories to exclude during the build process, especially when generating ZIP archives via the CLI.
## Purpose
When executing build commands, the `.wpcignore` file is used to determine which files should be excluded from the final ZIP package. This helps avoid including unnecessary files like version control folders, logs, or local development artifacts.
## Format
The `.wpcignore` file is a plain text file containing one pattern per line. It supports glob patterns, making it easy to match files or folders.
## Example
```gitignore .wpcignore theme={null}
# Exclude Git-related files and folders
.git*
# Exclude all .log files
*.log
# Exclude temporary folders
temp/
```
## Usage
Place the `.wpcignore` file at the root of your project. During the build process, the CLI will automatically use it to determine what should be excluded from the archive.
## Notes
* Patterns are relative to the root of the project.
* Empty lines and lines starting with `#` are treated as comments.
* Be careful not to exclude required files unintentionally.
# External Repositories
Source: https://docs.wp-content.io/guides/external-repositories
Manage external sources for your plugins and themes, and bring private updates directly into the WordPress admin.
This plugin cannot be published on the official WordPress repository, as their guidelines forbid plugins that implement custom update mechanisms.
Once installed, it will behave like any other plugin, and future updates will be delivered directly from wp-content.io.
## Installation
Download the plugin from the official website: [https://wp-content.io/external-repositories](https://wp-content.io/external-repositories).
You’ll get a `.zip` file ready to install.
In your WordPress admin, go to **Plugins > Add New**, click **Upload Plugin**, and select the downloaded ZIP file.
Then click **Install Now**, and activate the plugin once the installation completes.
After activation, you'll be redirected to the plugin settings page.
Paste your API key to connect your site to your organization.
A default **readonly key** was automatically created when you set up your organization.
## Configuration
The screen below allows you to configure external sources for plugin and theme updates.
Each **tab** represents a different source. You can connect multiple registries (for example, several wp-content.io accounts or custom APIs) to the same site.
* **Name**: A unique label for this repository. It can be anything — for example, your organization name.
* **Registry URL**: Choose between the official wp-content.io registry or a custom API endpoint compatible with the same structure ([API Reference](/api-reference)).
* **API Key**: A read-only key is required for security. If `SECURE_AUTH_KEY` is defined in your `wp-config.php`, the key will be encrypted in the database.
* **Supports**: Toggle whether this source should manage plugins, themes, or both.
* **Enabled**: Allows you to temporarily disable a repository. When unchecked, no update checks will be made for that source.
Once connected, the current site's domain is automatically added to your organization's **allowed domains**.
You can revoke access at any time from your [dashboard](https://dashboard.wp-content.io).
## Programmatic Configuration
Starting from version 1.1.2, the External Repositories plugin introduces new hooks that allow you to define repository sources and manage plugin visibility directly via code. This is useful for advanced setups or automated deployments.
### Adding repositories with code
You can define one or more repositories using the `external_repositories` filter. Repositories added this way will not appear in the plugin’s admin interface, but will be active and used for updates.
```php theme={null}
add_filter( 'external_repositories', function( $repositories ) {
$repositories[] = [
'name' => 'ACME', // Must be unique across all repositories
'api_key' => 'your-api-key',
'url' => 'https://registry.wp-content.io/',
'supports_themes' => true,
'supports_plugins' => true,
];
return $repositories;
} );
```
If `url`, `supports_themes`, or `supports_plugins` are not specified, the following defaults are applied:
```php theme={null}
[
'url' => 'https://registry.wp-content.io/',
'supports_themes' => true,
'supports_plugins' => true,
]
```
The name must be unique, even across repositories defined in the plugin settings UI.
### Hiding the plugin from the Plugins screen
If you want to hide the plugin from the standard Plugins screen — for example, to avoid accidental deactivation — you can use the `hide_external_repositories_plugin` filter:
```php theme={null}
add_filter( 'hide_external_repositories_plugin', '__return_true' );
```
### Recommended usage
We recommend placing this configuration code inside a small MU plugin (`wp-content/mu-plugins/custom-repos.php`) to ensure it’s always loaded and easy to share across projects.
# Plugin Setup Guide
Source: https://docs.wp-content.io/guides/plugins
How to prepare your plugin for private updates
## Prerequisites
Before getting started, make sure you're familiar with how WordPress plugins work.
This guide doesn't cover how to build a plugin from scratch, it focuses on adapting an existing one to work with wp-content.io.
## Plugin management
To simplify the deployment of updates and make it as seamless as possible, the plugin’s release is based on the information provided in the plugin’s own file.
You simply need to publish a zip file of your plugin (the folder name inside the zip should match the plugin’s slug). If the slug does not exist in your organization, the plugin will be created; otherwise, a new version will be created.
When you publish an update, the version number need to be unique and greater than the latest version.
## File Header requirement
This is the minimum header of your plugin file :
```php my-plugin/my-plugin.php theme={null}
By default, only "Description" tab is shown and use the short plugin description (from main file header comment).
If you want to customize tabs, you can add some files (in Markdown format) at your plugin root :
| Filename | Corresponding tab |
| ---------- | ----------------- |
| README.md | Description |
| INSTALL.md | Installation |
| FAQ.md | FAQ |
Example of zip structure :
```
my-plugin/
├── my-plugin.php
├── FAQ.md
├── INSTALL.md
└── README.md
```
## Changelog tab
The changelog is automatically generated from your plugin update history.
You can manage your version (add release notes or delete a version) from your [dashboard](https://dashboard.wp-content.io).
# Theme Setup Guide
Source: https://docs.wp-content.io/guides/themes
How to prepare your theme for private updates
## Prerequisites
Before getting started, make sure you're familiar with how WordPress themes work.
This guide doesn't cover how to build a theme from scratch, it focuses on adapting an existing one to work with wp-content.io.
## Theme management
To simplify the deployment of updates and make it as seamless as possible, the theme’s release is based on the information provided in its stylesheet header.
You simply need to publish a zip file of your theme (the folder name inside the zip should match the theme’s slug). If the slug does not exist in your organization, the theme will be created; otherwise, a new version will be created.
When you publish an update, the version number needs to be unique and greater than the latest version.
## File Header requirement
This is the minimum header of your `style.css` file:
```css my-theme/style.css theme={null}
/*
Theme Name: My Theme
Version: 1.0.4
Author: Your company name
Update URI: https://registry.wp-content.io
*/
```
The name, version and author properties will be used to publish your theme data.
The `Update URI` property is mandatory because it tells WordPress to check the wp-content.io registry instead of the official repository.
## Zip structure
Here is an example of minimal theme structure:
```
my-theme/
├── index.php
└── style.css
```
## Enhance your theme details view
The following header shows the available customization options from the `style.css` file:
```css my-theme/style.css theme={null}
/*
Theme Name: My Theme
Theme URI:
Description: Fake theme
Version: 1.0.4
Author: Happy Monkey
Author URI: https://mkey.fr/
Requires at least: 6.4
Requires PHP: 8.1
Update URI: https://registry.wp-content.io
*/
```
If you include a screenshot.png file in your theme, it will be used as the theme preview, but you can also customize it from the dashboard.
## Theme preview
In the official WordPress repository, themes are usually presented with a live preview using a pre-installed demo site.
We’ve made a different choice.
Because we care deeply about the **security and confidentiality** of your code, wp-content.io does not deploy any of your files.
All your archives stay securely hosted on the CDN, without being extracted or exposed.
If you want to provide a live preview, you can define a **Preview URL** in the dashboard.
If no URL is provided, users will instead see the changelog and version history of your theme.
## Child themes
You can upload a child theme based on either:
* a parent theme from the official WordPress repository,
* a private theme managed by any organization (as long as the site is connected to your the organization account).
When installing a child theme, the parent theme will be installed automatically if it’s not already present on the site.
This allows you to safely distribute child themes without requiring any manual setup for the parent.
## Troubleshooting
If you're having trouble uploading your theme, here are some common issues and how to resolve them:
Make sure you're uploading a valid `.zip` file. Other formats like `.rar` or uncompressed folders are not supported.
The maximum allowed file size is 512MB. If your archive is larger, consider optimizing your theme or reducing unused assets.
Your ZIP file must contain a single folder named after your theme's slug. Inside that folder, there must be a `style.css` file that includes the required headers.
```text Example: theme={null}
my-theme/
└── style.css
```
The theme slug may already exist on the official WordPress repository, be in use by another organization, or be restricted (e.g., for premium themes).
Please choose a unique and authorized slug.
Each plan has a limit on the number of themes.
You can also manage your quota or upgrade your plan from your dashboard.
If you're on the Agency plan, you can contact support to request additional slots.
Make sure your `style.css` file includes the required headers: `Theme Name`, `Author`, `Version`, and `Update URI`.
# Introduction
Source: https://docs.wp-content.io/index
Welcome to the official documentation
Start now with [wp-content.io](https://wp-content.io/) and get the same smooth experience as the official WordPress repository, but for your private plugins and themes.
No manual uploads, no repetitive code. Just a clean way to register external sources, deliver updates, and manage custom extensions and themes at scale.
This guide will walk you through everything you need to get started, whether you’re building for a single site or maintaining dozens.
Get an overview of the service.
Check available plans.
Use the command-line tool.
Explore the API reference.
# Quickstart
Source: https://docs.wp-content.io/quickstart
This quickstart guide will help you deploy your plugin or theme in just a few minutes.
Recreate the official WordPress experience for your own plugins and themes with one-click installs and built-in updates, all without writing a single line of code.
## Ready in 3 simple steps
There’s no library to install, no custom logic to write. All WordPress plugins and themes are compatible out of the box.
Just follow these three simple steps to start deploying your code to any WordPress site cleanly, and without effort.
If you haven’t already, [create an account](https://dashboard.wp-content.io/signup) and configure your first organization.
You can start with a free plan, no credit card required.
An organization is your workspace. From there, you can manage your private plugins and themes, browse all published versions, invite collaborators, configure API keys, and define which domains are allowed to receive updates.
To enable updates from an external source, you need to add the Update URI header to your plugin or theme.
For **plugins**, add it to the header of the main .php file:
```php my-plugin/my-plugin.php {6} theme={null}
For **themes**, add it to the style.css file:
```css my-theme/style.css {5} theme={null}
/*
Theme Name: My Theme
Author: Your Name
Version: 1.0.0
Update URI: https://registry.wp-content.io
*/
```
The Author, Version, and Update URI fields are required.
Other headers like Description, Tags, or License are optional, but will be used to enrich the dashboard and update information.
Once this is done, create a ZIP archive of your plugin or theme folder.
You’ll upload it when creating your first release.
To enable updates on your WordPress sites, install the External Repositories plugin.
You can download it for free from [the official webpage](https://wp-content.io/external-repositories).
Once installed and activated, you’ll be redirected to the plugin settings page.
There, you can enter your API key to connect your site to your organization.
When you create an organization, a readonly API key is automatically generated.
You can use this key to allow update checks without exposing write access.
## You’re all set 🎉
Everything is ready, your site is now connected and can receive updates for your private plugins and themes.
You’ll also find a new tab when adding a plugin or a theme from the WordPress admin.
This view lets you browse the items linked to your account and install them in one click.
When you publish a new version, it will appear directly in the WordPress admin, just like any plugin or theme from the official repository.
## Troubleshooting
If you’re not familiar with WordPress headers or run into errors during upload, check the detailed setup guides:
How to prepare your plugin for private updates
How to prepare your theme for private updates