Publishing
I publish the platform packages as restricted-access packages to the npm registry under the @opentabs-dev org. The process is mostly automated, but there are enough moving parts that I wrote it all down. Here's the full workflow.
Packages
Seven platform packages are published. The dependency order matters — get it wrong and downstream packages reference versions that don't exist yet:
| Order | Package | Depends on |
|---|---|---|
| 1 | @opentabs-dev/shared | — |
| 2 | @opentabs-dev/browser-extension | shared |
| 3 | @opentabs-dev/mcp-server | shared |
| 4 | @opentabs-dev/plugin-sdk | shared |
| 5 | @opentabs-dev/plugin-tools | plugin-sdk, shared |
| 6 | @opentabs-dev/cli | mcp-server, browser-extension, plugin-sdk, plugin-tools, shared |
| 7 | @opentabs-dev/create-plugin | cli |
All seven packages are published to npm. browser-extension and mcp-server are additionally bundled with the CLI — opentabs start uses the bundled MCP server and auto-installs the bundled browser extension to ~/.opentabs/extension/.
npm Authentication (One-Time Setup)
Create a granular access token at npmjs.com/settings/tokens/create:
- Permissions: Read and Write
- Packages:
@opentabs-dev/* - Bypass 2FA: Enabled
Save the token to ~/.npmrc:
echo '//registry.npmjs.org/:_authToken=<YOUR_TOKEN>' > ~/.npmrcVerify it works:
npm whoamiPublishing a Release
I automated the entire publish workflow in a single script. It handles everything in one shot:
npx tsx scripts/publish.ts 0.0.17The script:
- Verifies npm authentication via
npm whoami - Bumps
"version"in all sevenplatform/*/package.jsonfiles - Deletes the lockfile, runs
npm install, and runsnpm run build:forceto sync lockfile and rebuild with the new versions - Publishes in dependency order:
shared→browser-extension→mcp-server→plugin-sdk→plugin-tools→cli→create-plugin - Updates plugin
@opentabs-dev/*dependencies to^versionand rebuilds each plugin - Generates a changelog from
git logsince the previous tag - Creates a release commit and tag (
v<version>)
Six packages use "publishConfig": { "access": "restricted" } explicitly. browser-extension omits publishConfig but is still restricted — npm defaults to restricted access for scoped packages. Only authenticated npm users with access to the @opentabs-dev scope can install them.
After Publishing
After a release, every plugin that depends on @opentabs-dev/* packages needs its dependencies updated. This is the tedious part:
cd plugins/slack
# Update @opentabs-dev/* versions in package.json
npm install
npm run buildThe opentabs-plugin build command embeds the installed SDK version as sdkVersion in dist/tools.json. The MCP server checks this at discovery time — if a plugin was built with a newer SDK than the server, it is rejected with a clear rebuild message.
Version Compatibility
The MCP server checks that plugins weren't built with a newer SDK than it understands. It uses major.minor comparison:
- A plugin's major.minor must be less than or equal to the server's major.minor
- Patch differences are always fine
- Plugins without
sdkVersionintools.json(predating this feature) load with a warning
In practice, this means patch releases are painless — existing plugins keep working without rebuilding. A minor or major bump (e.g., 0.0.x → 0.1.0) requires plugins to rebuild with the new SDK.
What NOT to Publish
plugins/*— example plugins are standalone projects that publish independently to npm underopentabs-plugin-*names
Last Updated: 10 Mar, 2026