Skip to main content

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.

Manifest Format

The registry file (plugins.json):
{
  "schemaVersion": 1,
  "plugins": [
    // ... plugin entries
  ]
}

Entry Fields

FieldTypeRequiredDescription
idstringYesBundle identifier (e.g., com.TablePro.OracleDriver)
namestringYesDisplay name
versionstringYesSemantic version
summarystringYesOne-line description
authorobjectYes{ "name": "...", "url": "..." }
homepagestringNoProject URL
categorystringYesdatabase-driver, export-format, import-format, theme, other
databaseTypeIds[string]NoMaps to DatabaseType.pluginTypeId. Used for auto-install.
downloadURLstringNo*Direct URL to .zip
sha256stringNo*SHA-256 hex of ZIP
binaries[object]NoPer-arch entries with architecture (arm64 or x86_64), downloadURL, and sha256. See example below.
minAppVersionstringNoMinimum TablePro version
minPluginKitVersionintNoMinimum PluginKit version (currently 2)
iconNamestringNoSF Symbol name
isVerifiedboolYesVerified 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.
DatabaseTypepluginTypeId
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

1

User selects a database type with no loaded driver

2

App fetches registry, finds plugin by databaseTypeIds

3

Downloads ZIP, verifies SHA-256

4

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.