Skip to content

Development & Testing

jkrandom edited this page Aug 12, 2026 · 1 revision

Development & Testing

Prerequisites

  • Node.js >= 18
  • opencode >= 1.18.0 (for E2E tests)
  • TypeScript 5.x

Build

npm install
npm run build       # tsc → dist/
npm run typecheck   # tsc --noEmit

Run tests

npm test            # build + node --test tests/*.test.mjs

All 179 tests must pass before any PR.

Test files

File Covers
config.test.mjs Option resolution, name validation, default peer name
format.test.mjs /peers display formatting, sorting, collapse, title rendering
registry.test.mjs Registry write/read, heartbeat, prune, stale detection
session-runtime.test.mjs Lifecycle adoption, event handling, whenReady
delivery.test.mjs Injection, timeout, retry, busy delivery
queue.test.mjs Spool states, dedup, held expiry, concurrent operations
permissions.test.mjs Auto-allow scoping, protected categories, transient verdicts
listener-sender.test.mjs Transport, inbox listener, async endpoint resolution
tools.test.mjs list_agents, send_message, peer_message_status
commands.test.mjs /peers, /peers-name, /peers-inbox, /peers-outbox
real-opencode.test.mjs Full E2E with real opencode processes
tui.test.mjs TUI entry: zero-runtime-import invariant, keymap bindings

Real OpenCode E2E test

The real-opencode.test.mjs test starts actual opencode serve processes, loads the plugin, creates sessions, and verifies:

  • Busy exact injection via UDS transport
  • Restart recovery with spool persistence
  • Permission boundaries (allow vs ask, protected categories)
  • v1 interop via loopback HTTP
  • Held message ACK lifecycle (accept → delivered, drop → dropped, expiry → expired)
# Run just the E2E test
node --test tests/real-opencode.test.mjs

Requires the opencode binary on $PATH. Skips automatically if not found.

Manual E2E

Two terminals:

# terminal 1
cd /tmp/proj-a && opencode
/peers-name alpha

# terminal 2
cd /tmp/proj-b && opencode
/peers-name beta
/peers        # should show alpha

Headless variant:

cd /tmp/proj-a && opencode serve --port 14100 &
cd /tmp/proj-b && opencode serve --port 14101 &
# drive via HTTP API: POST /session, /session/:id/prompt_async

TUI E2E harness

( sleep N; printf '/cmd'; sleep 2; printf '\r'; sleep M ) | \
  script -q /tmp/out opencode -c --print-logs

macOS BSD script hangs after input pipe EOFs — pkill the TUI from outside the pipeline.

Publishing

  1. Feature branch → commit → push
  2. PR → merge to main (verification results in PR description)
  3. Version bump in package.json + PLUGIN_VERSION in src/index.ts
  4. npm publish:
    npm publish
  5. Tag & release:
    git tag vX.Y.Z && git push origin vX.Y.Z
    gh release create vX.Y.Z --latest
  6. Update local cache (gotcha):
    cd ~/.cache/opencode/packages/opencode-plugin-peers@latest
    npm install opencode-plugin-peers@latest
    opencode plugin -g <name> does NOT refresh the cache — you must manually update the pin.

Architecture constraints

  • Factory functions, not class + new (opencode's loader can break new)
  • import type only in src/tui.ts — TUI process can't resolve runtime imports
  • Config hook for command registration — opencode 1.18 doesn't scan plugin packages for commands/*.md
  • Heartbeat timer NOT unref'd — when SDK call hangs, timer must fire to unblock delivery
  • No toast popups — command results go inline; held-message notices use inline idle-only delivery

Clone this wiki locally