nexus/.planning/codebase/STACK.md
Mikkel Georgsen 6c4272ce85 [nexus] chore: migrate .planning/ from agent repo to nexus repo
Planning artifacts (milestones v1.0-v1.2.1, v1.3 queue, PROJECT.md,
STATE.md, config) now live alongside the code they describe.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 03:55:42 +00:00

9.5 KiB

Technology Stack

Analysis Date: 2026-03-30 Project Name: Paperclip (package name paperclip, npm org @paperclipai)


Languages

Primary:

  • TypeScript 5.7.x — all source code across every package, compiled to ESM
  • JavaScript (ESM) — build scripts, generated output

Secondary:

  • Bash — release scripts, smoke tests, DB backup (scripts/, tests/)

Runtime

Environment:

  • Node.js >=20 (enforced via engines in root package.json)
  • ESM-first: all packages set "type": "module"
  • tsx (^4.19.2) used as TS runner during development and for CLI execution

Package Manager:

  • pnpm 9.15.4 (pinned via packageManager field)
  • Lockfile: pnpm-lock.yaml — present and committed
  • Patched dependency: embedded-postgres@18.1.0-beta.16 (patch in patches/)

Monorepo Structure

Workspace layout (pnpm-workspace.yaml):

packages/*
packages/adapters/*
packages/plugins/*
packages/plugins/examples/*
server
ui
cli

Packages:

Package Name Purpose
server/ @paperclipai/server Express HTTP server + WebSocket + plugin host
ui/ @paperclipai/ui React SPA (board UI)
cli/ paperclipai CLI binary (Node.js, esbuild-bundled)
packages/db/ @paperclipai/db Drizzle ORM schema, migrations, embedded-postgres helpers
packages/shared/ @paperclipai/shared Shared Zod schemas and TypeScript types
packages/adapter-utils/ @paperclipai/adapter-utils Shared utilities across AI adapters
packages/adapters/claude-local/ @paperclipai/adapter-claude-local Adapter for Anthropic Claude Code CLI
packages/adapters/codex-local/ @paperclipai/adapter-codex-local Adapter for OpenAI Codex CLI
packages/adapters/cursor-local/ @paperclipai/adapter-cursor-local Adapter for Cursor editor agent
packages/adapters/gemini-local/ @paperclipai/adapter-gemini-local Adapter for Google Gemini CLI
packages/adapters/openclaw-gateway/ @paperclipai/adapter-openclaw-gateway Gateway adapter (WebSocket, external agent relay)
packages/adapters/opencode-local/ @paperclipai/adapter-opencode-local Adapter for opencode-ai CLI
packages/adapters/pi-local/ @paperclipai/adapter-pi-local Adapter for pi.ai
packages/plugins/sdk/ @paperclipai/plugin-sdk Public plugin API (worker-side + UI bridge hooks)

Backend Framework

HTTP Server:

  • Express 5.1.0 (express) — REST API, static file serving, middleware chain
  • @types/express 5.0.0

WebSocket (Realtime):

  • ws ^8.18.0 — native WebSocket server at server/src/realtime/live-events-ws.ts
  • Used for live event streaming to the board UI

Authentication:

  • better-auth 1.4.18 — pluggable auth library with Drizzle adapter
  • Session handling at server/src/auth/better-auth.ts
  • JWT used for agent-to-server auth (server/src/agent-auth-jwt.ts)

Validation:

  • zod ^3.24.2 — schema validation throughout server and shared packages
  • ajv ^8.18.0 + ajv-formats ^3.0.1 — JSON Schema validation (plugin manifests)

Logging:

  • pino ^9.6.0 — structured JSON logging
  • pino-http ^10.4.0 — HTTP request logging middleware
  • pino-pretty ^13.1.3 — dev-mode pretty-print

File Handling:

  • multer ^2.0.2 — multipart/form-data upload handling
  • sharp ^0.34.5 — server-side image processing

HTML Sanitization:

  • dompurify ^3.3.2 + jsdom ^28.1.0 — server-side sanitization of rich text

Database

ORM:

  • drizzle-orm ^0.38.4 — TypeScript ORM, query builder
  • drizzle-kit ^0.31.9 — migration generation (drizzle-kit generate)

Driver:

  • postgres ^3.4.5 — native PostgreSQL client

Database Server:

  • PostgreSQL 17 (Docker: postgres:17-alpine)
  • embedded-postgres ^18.1.0-beta.16 — bundled PostgreSQL for local/single-binary deployments (patched)

Schema location: packages/db/src/schema/ — 50+ individual table files Migrations: packages/db/src/migrations/ Client factory: packages/db/src/client.ts (createDb(url))

Database modes:

  • embedded-postgres — default for local CLI use (no external DB required)
  • postgres — external PostgreSQL for Docker/production deployments

Frontend Framework

Framework:

  • React 19.0.0 (react, react-dom)
  • React Router DOM 7.1.5 (react-router-dom) — SPA routing
  • React Query / TanStack Query 5.x (@tanstack/react-query) — server state, data fetching

Build Tool:

  • Vite 6.1.0 — dev server (port 5173) and production bundler
  • @vitejs/plugin-react ^4.3.4 — JSX/Fast Refresh
  • In dev mode, Vite runs as Express middleware via vite.middlewares integration

Styling:

  • Tailwind CSS 4.0.7 — utility-first CSS
  • @tailwindcss/vite ^4.0.7 — Vite plugin
  • @tailwindcss/typography ^0.5.19 — prose styles
  • tailwind-merge ^3.0+ — conditional class merging
  • class-variance-authority ^0.7.1 — component variant management
  • clsx ^2.1.1 — conditional class names

UI Components:

  • radix-ui ^1.4.3 — unstyled accessible primitives
  • @radix-ui/react-slot ^1.2.4
  • Component files in ui/src/components/ui/: button, card, dialog, input, badge, tabs, tooltip, etc. (shadcn-style pattern)
  • lucide-react ^0.574.0 — icon library
  • cmdk ^1.1.1 — command palette

Rich Text / Markdown:

  • @mdxeditor/editor ^3.52.4 — rich markdown editor component
  • lexical 0.35.0 + @lexical/link — editor framework (peer dep of MDXEditor)
  • react-markdown ^10.1.0 — Markdown rendering
  • remark-gfm ^4.0.1 — GitHub-flavored Markdown
  • mermaid ^11.12.0 — diagram rendering

Drag-and-Drop:

  • @dnd-kit/core ^6.3.1, @dnd-kit/sortable ^10.0.0, @dnd-kit/utilities ^3.2.2

Path Alias: @/ maps to ui/src/ (configured in vite.config.ts)


CLI

Framework:

  • commander ^13.1.0 — command parsing
  • @clack/prompts ^0.10.0 — interactive terminal prompts
  • picocolors ^1.1.1 — terminal color output

Build:

  • esbuild ^0.27.3 — bundles CLI to single dist/index.js (config: cli/esbuild.config.mjs)

Storage

Providers (runtime-selectable):

  • Local disk — server/src/storage/local-disk-provider.ts — default, stores under PAPERCLIP_HOME
  • AWS S3 — server/src/storage/s3-provider.ts — via @aws-sdk/client-s3 ^3.888.0

Secrets:

  • Local encrypted provider — server/src/secrets/local-encrypted-provider.ts
  • External stub providers — server/src/secrets/external-stub-providers.ts

Testing Frameworks

Unit / Integration:

  • Vitest ^3.0.5 — test runner (configured in root vitest.config.ts as multi-project)
  • Projects under test: packages/db, packages/adapters/opencode-local, server, ui, cli
  • Server tests: server/src/__tests__/ (~95 test files)
  • Server vitest config: server/vitest.config.ts (env: node)
  • supertest ^7.0.0 — HTTP integration testing for Express routes

E2E:

  • Playwright ^1.58.2 — browser E2E tests
  • Config: tests/e2e/playwright.config.ts
  • Browser: Chromium only
  • tests/e2e/ — feature specs, tests/release-smoke/ — release smoke tests

Evaluations:

  • promptfoo 0.103.3 — LLM prompt evaluation (evals/promptfoo/)

Build and Tooling

TypeScript:

  • TypeScript 5.7.3 across all packages
  • Base config: tsconfig.base.json — target ES2023, NodeNext module resolution, strict mode
  • Each package extends base or defines its own tsconfig.json

Dev Runner:

  • scripts/dev-runner.mjs — coordinates parallel dev processes (server + UI)
  • chokidar ^4.0.3 — file watching in server dev mode

CLI published as: paperclipai on npm (binary: dist/index.js) Server published as: @paperclipai/server on npm Plugin SDK published as: @paperclipai/plugin-sdk on npm


Docker / Deployment

Base image: node:lts-trixie-slim (Debian-based)

Multi-stage Dockerfile:

  1. base — Node + pnpm + ca-certificates + curl + git
  2. deps — install all dependencies with frozen lockfile
  3. build — build UI, plugin-sdk, server in order
  4. production — copy build output; globally install @anthropic-ai/claude-code, @openai/codex, opencode-ai

Port: 3100 (configurable via PORT env var) Data volume: /paperclip — all persistent state (DB, uploads, config)

Compose variants:

  • docker-compose.yml — full stack with external Postgres 17
  • docker-compose.quickstart.yml — single container, embedded Postgres
  • docker-compose.untrusted-review.yml — special security sandbox mode

Key env vars:

  • DATABASE_URL — external PostgreSQL URL (omit for embedded mode)
  • BETTER_AUTH_SECRET — required auth secret
  • PAPERCLIP_DEPLOYMENT_MODEauthenticated | unauthenticated
  • PAPERCLIP_DEPLOYMENT_EXPOSUREprivate | public
  • PAPERCLIP_PUBLIC_URL — public-facing URL
  • ANTHROPIC_API_KEY / OPENAI_API_KEY — AI provider keys
  • PAPERCLIP_HOME — data root directory (default /paperclip in Docker)

AI Agent Integrations (Adapters)

Each adapter follows a consistent three-export pattern: ./server, ./ui, ./cli.

Adapter Target Agent CLI
adapter-claude-local @anthropic-ai/claude-code
adapter-codex-local @openai/codex
adapter-cursor-local Cursor editor
adapter-gemini-local Gemini CLI
adapter-openclaw-gateway Remote agent relay (WebSocket, ws)
adapter-opencode-local opencode-ai
adapter-pi-local pi.ai

The hermes-paperclip-adapter 0.1.1 is an additional server-side dependency (third-party adapter protocol).


Stack analysis: 2026-03-30