Plugin Registry
The plugin registry is a JSON manifest hosted at github.com/TableProApp/plugins. TablePro fetches it to populate Settings > Plugins > Browse and to handle auto-install when a user selects a database type with no loaded driver.
The registry file (plugins.json):
{
"schemaVersion": 1,
"plugins": [
// ... plugin entries
]
}
Entry Fields
| Field | Type | Required | Description |
|---|
id | string | Yes | Bundle identifier (e.g., com.TablePro.OracleDriver) |
name | string | Yes | Display name |
version | string | Yes | Semantic version |
summary | string | Yes | One-line description |
author | object | Yes | { "name": "...", "url": "..." } |
homepage | string | No | Project URL |
category | string | Yes | database-driver, export-format, import-format, theme, other |
databaseTypeIds | [string] | No | Maps to DatabaseType.pluginTypeId. Used for auto-install. |
downloadURL | string | No* | Direct URL to .zip |
sha256 | string | No* | SHA-256 hex of ZIP |
binaries | [object] | No | Per-arch entries with architecture (arm64 or x86_64), downloadURL, and sha256. See example below. |
minAppVersion | string | No | Minimum TablePro version |
minPluginKitVersion | int | No | Minimum PluginKit version (currently 2) |
iconName | string | No | SF Symbol name |
isVerified | bool | Yes | Verified by TablePro team |
Either downloadURL/sha256 (flat fields) or the binaries array is required. When binaries is present, the app picks the matching architecture. Flat fields act as fallback for older app versions.
Example Entry
A complete entry for the Oracle driver plugin:
{
"id": "com.TablePro.OracleDriver",
"name": "Oracle Driver",
"version": "1.0.0",
"summary": "Oracle Database 12c+ driver via OracleNIO",
"author": { "name": "TablePro", "url": "https://tablepro.app" },
"homepage": "https://docs.tablepro.app/databases/oracle",
"category": "database-driver",
"databaseTypeIds": ["Oracle"],
"binaries": [
{ "architecture": "arm64", "downloadURL": "https://github.com/TableProApp/TablePro/releases/download/plugin-oracle-v1.0.0/OracleDriver-arm64.zip", "sha256": "<sha256>" },
{ "architecture": "x86_64", "downloadURL": "https://github.com/TableProApp/TablePro/releases/download/plugin-oracle-v1.0.0/OracleDriver-x86_64.zip", "sha256": "<sha256>" }
],
"minAppVersion": "0.17.0",
"minPluginKitVersion": 2,
"iconName": "server.rack",
"isVerified": true
}
databaseTypeIds Mapping
The databaseTypeIds field tells the app which registry plugin to install when a user picks a database type that has no loaded driver.
| DatabaseType | pluginTypeId |
|---|
| MySQL, MariaDB | "MySQL" |
| PostgreSQL, Redshift, CockroachDB | "PostgreSQL" |
| SQLite | "SQLite" |
| MongoDB | "MongoDB" |
| Redis | "Redis" |
| SQL Server | "SQL Server" |
| Oracle | "Oracle" |
| ClickHouse | "ClickHouse" |
Publishing a Plugin
Tag the commit and push:
git tag plugin-oracle-v1.0.0 && git push --tags
CI builds both architectures, signs the bundles, creates a GitHub release, and updates the registry manifest. The app fetches the updated manifest on the next Browse visit.
Auto-Install Flow
User selects a database type with no loaded driver
App fetches registry, finds plugin by databaseTypeIds
Downloads ZIP, verifies SHA-256
Extracts bundle, verifies code signature, loads plugin
Plugin Compatibility
Every plugin binary declares the PluginKit version it was built against (pluginKitVersion). The app declares two values in PluginManager.swift:
currentPluginKitVersion: the version the running app ships.
minimumCompatiblePluginKitVersion: the oldest version the app still loads.
TableProPluginKit is built with Swift Library Evolution, so a plugin built against any version in [minimum, current] loads under the app and the runtime fills in any newer requirement from its default. The app accepts that whole range instead of an exact match.
When you change PluginKit:
- Additive change (a new requirement with a default, a new field on a non-frozen type): leave both versions alone. Installed plugins keep loading; the registry needs no re-publish.
- Breaking change (a removed or changed requirement, a frozen-layout change, a requirement without a default): raise
currentPluginKitVersion and minimumCompatiblePluginKitVersion together, then run scripts/release-all-plugins.sh <newVersion> so the registry carries binaries for the new version before the app ships.
The registry serves the newest binary whose pluginKitVersion is in the app’s range, so an additive bump is served by the existing binaries with no re-publish. After a breaking bump, scripts/check-registry-readiness.py --floor <min> --current <current> (run by the app release workflow) fails the release until every database driver has a compatible binary, so the app never ships ahead of its plugins.
If a connection’s driver is installed but its binary predates a breaking bump, opening the connection refreshes the registry and updates the driver in the background, then proceeds. The app does not block on this; if a compatible binary is not published yet, the connection reports that it is updating and retries on its own (on a timer and when the network returns), so no quit and reopen is needed.
The manifest is served through jsDelivr (cdn.jsdelivr.net/gh/TableProApp/plugins@main/plugins.json) and purged on each publish, so a new binary is visible within seconds rather than waiting out a CDN cache.
Drivers that most users reach for are bundled inside the app and ship in lockstep, so they never depend on the registry. Reserve registry-only distribution for the long tail, where a short, non-blocking update on first connect is acceptable.
Theme Distribution
Themes use the same manifest format with category: "theme". Key differences from driver plugins:
- Pure JSON data, no executable code
- No code signing required
- No
.tableplugin bundle
- ZIP contains
.json files (valid ThemeDefinition)
- Installed to
~/Library/Application Support/TablePro/Themes/Registry/
- Theme packs (multiple themes in one ZIP) are supported
Example entry:
{
"id": "com.example.monokai-theme",
"name": "Monokai Theme",
"version": "1.0.0",
"summary": "Classic Monokai color scheme for TablePro",
"author": { "name": "Theme Author" },
"category": "theme",
"downloadURL": "https://example.com/monokai-theme.zip",
"sha256": "<sha256-of-zip>",
"iconName": "paintpalette",
"isVerified": false
}
Custom Registry URL
For enterprise or private registries:
# Set custom URL
defaults write com.TablePro com.TablePro.customRegistryURL "https://your-registry.example.com/plugins.json"
# Revert to default
defaults delete com.TablePro com.TablePro.customRegistryURL
The app invalidates its ETag cache when the registry URL changes, forcing a fresh fetch on the next Browse visit.