Skip to content

feat(packaging): publish omp-deck as a global npm CLI#3

Merged
bjb2 merged 2 commits into
mainfrom
feat/npm-publish
May 29, 2026
Merged

feat(packaging): publish omp-deck as a global npm CLI#3
bjb2 merged 2 commits into
mainfrom
feat/npm-publish

Conversation

@bjb2
Copy link
Copy Markdown
Owner

@bjb2 bjb2 commented May 29, 2026

What

Wires omp-deck to ship as a globally-installable npm package. After this lands, install + run is:

```sh
npm install -g omp-deck
omp-deck
```

(Requires Bun ≥ 1.3.14 — the deck is Bun-native. The shim prints an actionable install message if Bun is missing.)

How

Ships raw TS server source + pre-built `apps/web/dist/` + the bundled `@omp-deck/protocol` workspace package. A small Node-runnable shim is the `bin` entry — Node is used so a missing-Bun install can print install instructions instead of `ENOENT`. The shim sets sensible env defaults (data dir `~/.omp-deck/`, `OMP_DECK_WEB_DIST`, `OMP_DECK_STARTER_*_DIR`), then `spawn('bun', [serverEntry])` with stdio + signals + exit code forwarded.

Workspace-dep plumbing was the only real friction:

  • `bundledDependencies: ["@omp-deck/protocol"]` so npm pack picks up the workspace package
  • `scripts/prepack.mjs` replaces the symlinked `packages/protocol` with a real directory copy at `node_modules/@omp-deck/protocol/`, and strips `private` + `dependencies` + `devDependencies` from the bundled `package.json`. The strip is load-bearing: without it npm sees the bundled package's deps and assumes they're already satisfied → never installs ajv/ajv-formats at the parent → server crashes on `Cannot find module 'ajv/dist/2020'`
  • `scripts/postpack.mjs` runs `bun install` after pack to restore the workspace symlinks so the dev workflow keeps working

Lifted the server's runtime deps + `ajv` + `ajv-formats` to the root `package.json` so they get installed alongside.

Files

  • `bin/omp-deck.mjs` — Node shim (bun detection, env defaults, spawn)
  • `scripts/prepack.mjs` — web build + materialize bundled protocol
  • `scripts/postpack.mjs` — restore workspace symlinks
  • `package.json` — unprivate, add `bin` / `files` / `bundledDependencies` / lift deps / wire prepack+postpack
  • `README.md` — new "Global install" section above "From source"
  • `.gitignore` — ignore `omp-deck-*.tgz` pack output

Verified end-to-end

  • `npm pack` → 3.3 MB tarball (10.5 MB unpacked); bundled `node_modules/@omp-deck/protocol/` confirmed via `tar -tzf`
  • `npm install -g --prefix ` into a clean prefix installs 267 packages and produces `omp-deck` / `omp-deck.cmd` / `omp-deck.ps1` shims
  • Running the shim with `OMP_DECK_DATA_DIR= OMP_DECK_PORT=8797`:
    • server up in ~3s
    • `/deck.db` created with migrations applied + welcome task seeded
    • starter-skills + starter-extensions install from the bundled paths ("already present" because the test host has them)
    • web assets serve, `GET /api/tasks` returns 200
  • Workspace symlinks restored by postpack: `node_modules/@omp-deck/protocol` is a symlink to `packages/protocol` again
  • Full typecheck across 4 packages clean

What is NOT in this PR

  • A CI workflow to auto-publish on tag. Add this in a follow-up once we have the `NPM_TOKEN` secret wired and have done a manual `npm publish` first to claim the name.
  • Browser auto-open on start. The launcher scripts do it; CLI prints the URL — kept simple, no `open` dep.
  • Single-binary distribution via `bun build --compile` (option C from the design discussion). Bun-requiring install keeps the package small (3.3 MB vs ~80 MB per platform) and ships the existing source untouched; revisit if there's demand from Node-only users.

Release / publish playbook (for whoever ships this)

  1. Bump version in root `package.json` (and update the `@omp-deck/protocol: "X.Y.Z"` line to match — the bundled-dep version must agree with the bundled `packages/protocol/package.json`)
  2. `npm login` (one-time)
  3. `npm publish --access public` — runs prepack → packs → publishes → postpack restores workspace
  4. Smoke: `npm install -g omp-deck && omp-deck` from a fresh shell

bjb2 added 2 commits May 29, 2026 11:27
Adds the wiring to ship omp-deck as a globally-installable npm package
that exposes an `omp-deck` command.

Approach: ship raw TS server source + pre-built web/dist + bundled
`@omp-deck/protocol` and let Bun execute the server. A small Node-runnable
shim is the `bin` entry: it checks for Bun on PATH (with an actionable
install message if missing), sets sensible env defaults (data dir
`~/.omp-deck/`, web dist next to the bundled assets, starter dirs from
the package), then `spawn('bun', [serverEntry])` with stdio + signals +
exit code forwarded.

Workspace-dep plumbing:
- `bundledDependencies: ['@omp-deck/protocol']` so npm picks up the
  workspace package
- `scripts/prepack.mjs` materializes the symlinked `packages/protocol`
  into `node_modules/@omp-deck/protocol/` as a real directory, strips
  `private` + `dependencies` from the bundled package.json (otherwise
  npm thinks the bundled deps are already satisfied and never installs
  ajv/ajv-formats at the parent)
- `scripts/postpack.mjs` runs `bun install` to restore the workspace
  symlinks so the dev workflow keeps working after a local `npm pack`

Lifts the server's runtime deps + ajv/ajv-formats to the root
package.json so npm installs them globally.

Verified end-to-end:
- `npm pack` produces a 3.3 MB tarball (10.5 MB unpacked); `bundled deps:
  1` confirmed via `tar -tzf`
- `npm install -g --prefix <tmp>` installs 267 packages and produces
  `omp-deck.cmd` / `omp-deck.ps1` / `omp-deck` shims
- Running the shim boots the server, creates `~/.omp-deck/deck.db` (with
  migrations + welcome seed), starter-skills + starter-extensions install
  from the bundled paths, web assets served, API responds 200
- Repo workspace symlinks restored after pack; typecheck across all 4
  packages still clean
Audit of the v0.5.0 tarball turned up files that sit under `files`-
allowlisted paths but should never ship publicly:

- `apps/server/src/templates/paper-trading-*.yaml` — operator-private
  routine templates (already gitignored). Hardcoded `C:\Users\bryan\...`
  paths and personal trading workflow. No API secrets, but explicitly
  marked 'never lands in the public repo' in .gitignore.
- `apps/server/**/*.test.ts` — bloat with no runtime value (~50 files).
- `apps/web/dist/**/*.map` — the JS source map alone was 6.9 MB.

`.npmignore` cannot subtract from a `files` allowlist (documented npm
behavior), so the fix is physical: prepack moves these files into
`.publish-stash/` with a manifest, npm packs the tree without them,
postpack moves them back.

Result: tarball drops from 3.3 MB / 214 files → 1.6 MB / 185 files.
Re-verified: clean install + boot end-to-end, all five paper-trading
templates restored to the workspace, all bridge tests restored,
`node_modules/@omp-deck/protocol` symlink restored.
@bjb2 bjb2 merged commit 172bacd into main May 29, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant