- Docs
- Troy Client
- How Troy Client Works
How Troy Client Works
You don't need to understand the technical details to use Troy Client — it just works. But if you're curious (or troubleshooting), here's what happens under the hood.
The Basic Flow
When WordPress checks for plugin updates (which it does automatically, or when you click "Check for updates"), Troy Client kicks in:
- Scans your plugins for headers that mark them as Troy-enabled.
- Groups plugins by server to minimize network requests.
- Queries each server for available updates.
- Merges the responses into WordPress's native update data.
Updates then appear in your normal WordPress dashboard, just like any other plugin update.
Troy Plugin Detection
Plugin developers add a simple header to their plugin's main file:
/**
* Plugin Name: My Plugin
* Version: 1.3.0
* Troy: repo.example.org
*/
That Troy: repo.example.org line is all it takes. Troy Client sees this header and fetches updates for this plugin from repo.example.org.
Works alongside WordPress.org:
Troy headers are inert metadata that WordPress.org ignores. The same plugin file can be published on both WordPress.org and a Troy Server — sites with Troy Client get updates from the Troy Server, sites without get updates from WordPress.org.
Privacy: What Gets Sent
Troy Client protects your privacy. Each update check sends one POST request per Troy Server, containing only the plugins hosted on that server. Here's the full payload:
Request body (JSON):
- Active Troy plugin slugs and versions.
- Inactive Troy plugin slugs and versions.
- Your WordPress, PHP, and Troy Client versions.
- Your site's installed language codes (site locale + all installed languages).
- Translation file metadata for the Troy plugins (header fields like revision date — not the translations themselves).
- A release channel preference (
tagorbeta).
HTTP headers:
X-Troy-Client-Id— a random anonymous identifier (see below).User-Agent—Troy Client/{version}.
No domain name, no email address, no personal information.
Why include inactive plugins?:
Inactive plugins are a known attack vector — an unpatched file in your plugins/ folder is vulnerable even when deactivated. Including them in the update check lets the Troy Server send back patches for those plugins too, so you get the fix as soon as the developer releases one.
The Anonymous ID
Troy Client generates a random identifier for your site. It looks like this (69 characters):
2927-b6f579671882b3aff8cfc4fea490be6bbbc1a351a610a10e273788f011252ae8
The number before the dash is the epoch — a weekly counter that's been ticking since January 1, 1970 (Unix time divided by one week). The current epoch is . The remaining 64 hex characters are random, with no connection to your domain, your server, or anything identifiable.
The ID exists so the server can count unique sites, not just requests. A busy site might check every 10 minutes; a dormant one might check once a week. Without a stable identifier, those two sites would look like 1,008 installs instead of 2. The ID rotates every week when the epoch increments, so no long-term tracking is possible. Two Troy Servers could technically cross-reference the ID during the same week, but Troy Server purges raw IDs after the epoch is fully processed — only aggregate counts (like "142 active installs") are kept.
Think of it like a library card with no name on it — the library knows how many people borrowed a book, but not who they are.
WordPress.org Never Sees Troy Plugins
When WordPress checks for updates, Troy Client strips all Troy-enabled plugins from the request before it reaches WordPress.org. This means:
- WordPress.org never learns which Troy plugins you have installed.
- Your plugin list stays private from centralized directories.
- Only the specific Troy Server for each plugin receives that plugin's information.
This is proactive filtering — not an override after the fact. Troy plugin data never reaches WordPress.org.
Caching
To avoid redundant network traffic, Troy Client caches responses for 10 minutes. This means:
- If you just checked for updates, checking again immediately won't make a new request.
- After 10 minutes, the next check will contact the server again.
Cache Size Optimization
The cache is capped at 333KB of serialized data — enough for 400+ plugins worth of update metadata. Detail responses (the full plugin readme retrieved when you click "View details") are larger, but those are only cached on demand.
If you need to force a fresh check, you can clear the cache (see Troubleshooting).
Plugin Dependencies
Some plugins depend on other plugins. Plugin developers can declare dependencies with a header:
/**
* Plugin Name: My Plugin
* Version: 1.3.0
* Troy: repo.example.org
* Troy Dependencies: helper-plugin, another-plugin <other-repo.example.org>
*/
Troy Client ensures those dependencies are available and up to date.
Security
All communication with Troy Servers happens over HTTPS, which encrypts data in transit. Troy Client refuses to connect to non-secure servers.
Requests also time out after 7 seconds — if a server is down or slow, your site won't stall waiting for a response.
Next Steps
- Having issues? Check Troubleshooting.
- New to Troy? Start with the Introduction.
