How to Update Private WordPress Plugins from GitHub

If you write plugins for clients, or keep your own private toolkit, you’ve hit this problem: WordPress only offers one-click updates for plugins from WordPress.org. Everything else means downloading a ZIP, logging into each site and uploading it again. This guide explains how plugin updates actually work and how to get the same Update now button for private plugins, with GitHub as the source.

How WordPress checks for updates

Twice a day, WordPress sends the list of installed plugins and their versions to api.wordpress.org and gets back which ones have a newer version and where to download it. The result is stored in the update_plugins site transient.

Plugins that aren’t on WordPress.org can take part in the same process: they hook into that transient (pre_set_site_transient_update_plugins) and add their own answer, “version 1.2.0 is available at this ZIP URL”. WordPress then shows the normal update notice, and Update now installs it like any other plugin. That piece of code is called an updater.

The DIY route

You need two things:

  1. An update source that returns the latest version number, the download URL and (ideally) the changelog.
  2. An updater inside the plugin that asks that source and injects the answer into WordPress’s update transient.

With GitHub as the source, a common pattern is to tag a release (v1.2.0), build the plugin ZIP in a GitHub Action, attach it to the release, and have the updater read GitHub’s “latest release” API. It works, but you’re maintaining the update logic yourself, including private-repository tokens, rate limits, changelogs and the “View details” screen.

The self-hosted route with Hoster

Hoster turns one WordPress site into an update server for your plugins and themes.

  1. Create a download for your plugin in Hoster (a name, version, required and tested WordPress versions, author info and changelog).
  2. Add the updater to your plugin: an update file inside an inc/ folder, which Hoster uses to deliver updates to every site running that plugin.
  3. Connect GitHub (optional): add your GitHub user and repository, and Hoster fetches the latest release ZIP and version number automatically. Public and private repositories both work.
  4. Release an update: raise the version number, write the changelog and publish the release (or upload a new ZIP). Every site with the plugin sees the update notice and the changelog, and updates with one click.

A typical plugin structure:

my-plugin/
├── my-plugin.php
├── assets/
│   └── style.css
└── inc/
    └── update.php

A GitHub release workflow

To make releases hands-off, keep only source files in Git (add node_modules/ and .DS_Store to .gitignore) and let a GitHub Action build and publish the release when you push a tag:

git tag v1.2.0
git push origin v1.2.0

The workflow packages the plugin as a ZIP and attaches it to the release; Hoster picks up the new version from there.

Why not just use WordPress.org?

WordPress.org is great for public plugins, but it has rules: code review, restrictions on what you can include and load from external services, and it’s public by definition. Client-specific plugins, premium plugins and internal tools don’t belong there. Self-hosting keeps them private and under your control.

Your own plugin update server

Your own plugin update server

Hoster ships updates for private and client plugins from your WordPress site, with GitHub releases and one-click updates.