@nubisco/openbridge
v0.37.0
Published
Local-first home automation bridge for developers. Plugin-based, TypeScript-first, Homebridge-compatible.
Readme
OpenBridge
Local-first home automation bridge for developers. Plugin-based, TypeScript-first, Homebridge-compatible.
Table of Contents
- Why OpenBridge?
- Features
- Quick Start
- Development
- Writing a Plugin
- Configuration
- HTTP API
- Monorepo Structure
- License
Why OpenBridge?
Homebridge works, but it was designed for a different era. OpenBridge is built from scratch with a developer-first philosophy:
- No cloud, no accounts: the HAP bridge is published directly on your local network
- Clean plugin SDK:
setup / start / stoplifecycle, one exported object, full TypeScript types - Drop-in Homebridge compatibility: existing
platformplugins work with zero modification - Built-in dashboard: Vue 3 UI included; no separate install needed
- Full HTTP API: everything the UI does, your scripts can do too
- MIT licensed: no paid tiers, no telemetry, no gatekeeping
Features
- Plugin lifecycle management (load, start, stop, reload)
- HAP bridge via hap-nodejs: exposes accessories to Apple Home
- Homebridge platform plugin compatibility shim
- Vue 3 dashboard: accessories, plugins, logs, config editor, terminal
- REST API + WebSocket streams for logs and metrics
- Zod-validated JSON config
- Structured logger with in-memory buffer
Quick Start
Three ways to install. Full details, including system and network requirements, are in the Installation guide.
Install from npm
Requirements: Node.js 20 or newer.
npm install -g @nubisco/openbridge
openbridgeOpen http://localhost:8582: the dashboard is bundled in the package and loads immediately.
openbridge --help # usage
openbridge --port 9000 # run on a different portState lives in ~/.openbridge (config, plugins, HomeKit pairing), following the HOME of the user running the daemon.
Run with Docker
For servers and NAS boxes. There is no image to pull: the docker-compose.yml in this repository runs a stock node:22-alpine container that installs @nubisco/openbridge from npm into a volume on first boot, which is also what the in-app updater replaces.
curl -O https://raw.githubusercontent.com/nubisco/openbridge/master/docker-compose.yml
docker compose up -dThe first start spends a minute or two installing before the dashboard answers on port 8582. Host networking is required: HomeKit needs mDNS on your LAN, which a bridge network cannot provide. For the same reason, HomeKit pairing does not work under Docker Desktop on macOS or Windows; use npm there instead. See the Installation guide for pinning, upgrades and rollback.
Install from source
Requirements: Node.js 20+, pnpm 9+, roughly 1 GB of free disk (node_modules lands around 720 MB).
# Install dependencies
pnpm install
# Build the runtime packages and the dashboard
pnpm build
# Start the daemon
node apps/daemon/dist/index.jsOpen http://localhost:8582: the dashboard loads immediately.
Platform notes
- Alpine / musl is a supported target, on x64 and arm64. The only native
dependency,
node-pty, is optional: without it everything runs normally and only the dashboard's interactive shell pane is disabled.npm install -g @nubisco/openbridgewill try to build it and silently carry on if no compiler is present. To enable the shell pane on Alpine, installbuild-base python3 linux-headersbefore installing OpenBridge. - Building the docs site needs memory.
pnpm buildcovers the runtime packages and the dashboard only. The VitePress docs site is built separately withpnpm build:docsand needs more than 1 GB of RAM, so it is kept out of the default build to keep OpenBridge installable on small SBCs. - There is no authentication by default. Anyone who can reach port 8582 has full control. Do not expose it to the internet; use a VPN or Tailscale.
Development
# Build all packages once
pnpm build
# Start the daemon in watch mode (terminal 1)
pnpm --filter @nubisco/openbridge dev
# Start the UI dev server with HMR (terminal 2)
pnpm --filter @nubisco/openbridge-ui dev
# → UI at http://localhost:5174 (proxies /api and /ws to daemon on :8582)To rebuild individual packages during development:
pnpm --filter @nubisco/openbridge-core dev # watch mode
pnpm --filter @nubisco/openbridge-logger devWriting a Plugin
import { definePlugin } from '@nubisco/openbridge-sdk'
export default definePlugin({
manifest: {
name: 'my-plugin',
version: '1.0.0',
description: 'Does something useful',
},
async setup(ctx) {
ctx.log.info('Setup: runs once at load time')
},
async start(ctx) {
ctx.log.info('Start: begin plugin operation')
// ctx.config has values from config.json
},
async stop(ctx) {
ctx.log.info('Stop: clean up resources')
},
})For a full guide, see the Plugin Development docs.
Configuration
Default config path: ~/.openbridge/config.json
{
"bridge": {
"name": "My OpenBridge",
"port": 8582,
"logLevel": "info"
},
"plugins": [
{
"name": "my-plugin",
"enabled": true,
"config": {
"interval": 5000
}
}
]
}See Configuration Reference for all options.
HTTP API
The daemon exposes a REST API on port 8582:
| Method | Path | Description |
| ------ | -------------------------- | ---------------------------------------- |
| GET | /api/health | Daemon status, version, and capabilities |
| GET | /api/plugins | List all loaded plugins |
| GET | /api/plugins/:id | Get a single plugin |
| POST | /api/plugins/:id/start | Start a plugin |
| POST | /api/plugins/:id/stop | Stop a plugin |
| GET | /api/accessories | List all HAP accessories |
| GET | /api/logs?plugin=&limit= | Retrieve log entries |
| WS | /ws/logs | Stream live logs |
| WS | /ws/shell | Interactive terminal (requires node-pty) |
GET /api/health reports which optional features are present:
{ "status": "ok", "version": "0.29.0", "capabilities": { "shell": true, "ui": true } }capabilities.shell is false when the optional node-pty dependency is not
installed; the interactive terminal is then unavailable and nothing else is affected.
Full reference: HTTP API docs.
Monorepo Structure
openbridge/
apps/
daemon/ Node.js runtime: plugin loader + Fastify HTTP API + HAP bridge
(published to npm as `@nubisco/openbridge`, dashboard bundled in)
ui/ Vue 3 dashboard: accessories, plugins, logs, config, terminal
cli/ Standalone CLI scaffold (not published; the daemon provides `openbridge`)
docs/ VitePress documentation site
packages/
core/ Plugin types, registry, lifecycle, loader
logger/ Structured logging with in-memory buffer + WebSocket
config/ Zod-validated JSON config
sdk/ definePlugin() helper for plugin authors
compatibility-homebridge/ Homebridge platform plugin adapterPublished packages
Everything below is released together, under one version, from a single git tag.
| npm package | Source |
| ---------------------------------------------- | ----------------------------------- |
| @nubisco/openbridge | apps/daemon |
| @nubisco/openbridge-core | packages/core |
| @nubisco/openbridge-logger | packages/logger |
| @nubisco/openbridge-config | packages/config |
| @nubisco/openbridge-sdk | packages/sdk |
| @nubisco/openbridge-compatibility-homebridge | packages/compatibility-homebridge |
Releasing
Releases are automated and should not be run by hand.
- Merging to
masterruns semantic-release, which bumps the version, writes the CHANGELOG entry, commits and pushes avX.Y.Ztag. - Publishing the resulting GitHub Release triggers
npm-publish.yml, which builds, packs each package withpnpm packand publishes the tarballs to npm. It keys off the release rather than the tag because the tag points at a[skip ci]commit, which GitHub uses to suppress push-triggered workflows.
Authentication uses npm trusted publishing (OIDC), so there is no npm token stored in the repository. Each package has this workflow registered as a trusted publisher on npmjs.com, and npm accepts publishes only from it. Provenance attestations are generated automatically, so every release is cryptographically attested to the commit and workflow run it was built from, and CI fails the release if an attestation is missing.
To inspect exactly what would be published, without publishing anything:
pnpm pack:checkThat builds, stages the tarballs and asserts each one carries dist, a README and
a LICENSE, and that no workspace:* range survived into the published manifest.
Contributing
Contributions are welcome. Please read CONTRIBUTING.md before opening a pull request. All contributions are made under the Individual CLA.
Security
To report a vulnerability, please use GitHub Security Advisories rather than opening a public issue. See SECURITY.md for the full policy.
Support this project
If OpenBridge is useful to you, consider sponsoring the maintainer.
License
MIT: see LICENSE.
Part of the Nubisco ecosystem.
