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>
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
enginesin rootpackage.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
packageManagerfield) - Lockfile:
pnpm-lock.yaml— present and committed - Patched dependency:
embedded-postgres@18.1.0-beta.16(patch inpatches/)
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/express5.0.0
WebSocket (Realtime):
ws^8.18.0 — native WebSocket server atserver/src/realtime/live-events-ws.ts- Used for live event streaming to the board UI
Authentication:
better-auth1.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 packagesajv^8.18.0 +ajv-formats^3.0.1 — JSON Schema validation (plugin manifests)
Logging:
pino^9.6.0 — structured JSON loggingpino-http^10.4.0 — HTTP request logging middlewarepino-pretty^13.1.3 — dev-mode pretty-print
File Handling:
multer^2.0.2 — multipart/form-data upload handlingsharp^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 builderdrizzle-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.middlewaresintegration
Styling:
- Tailwind CSS 4.0.7 — utility-first CSS
@tailwindcss/vite^4.0.7 — Vite plugin@tailwindcss/typography^0.5.19 — prose stylestailwind-merge^3.0+ — conditional class mergingclass-variance-authority^0.7.1 — component variant managementclsx^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 librarycmdk^1.1.1 — command palette
Rich Text / Markdown:
@mdxeditor/editor^3.52.4 — rich markdown editor componentlexical0.35.0 +@lexical/link— editor framework (peer dep of MDXEditor)react-markdown^10.1.0 — Markdown renderingremark-gfm^4.0.1 — GitHub-flavored Markdownmermaid^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 promptspicocolors^1.1.1 — terminal color output
Build:
esbuild^0.27.3 — bundles CLI to singledist/index.js(config:cli/esbuild.config.mjs)
Storage
Providers (runtime-selectable):
- Local disk —
server/src/storage/local-disk-provider.ts— default, stores underPAPERCLIP_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.tsas 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:
promptfoo0.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,NodeNextmodule 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:
base— Node + pnpm + ca-certificates + curl + gitdeps— install all dependencies with frozen lockfilebuild— build UI, plugin-sdk, server in orderproduction— 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 17docker-compose.quickstart.yml— single container, embedded Postgresdocker-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 secretPAPERCLIP_DEPLOYMENT_MODE—authenticated|unauthenticatedPAPERCLIP_DEPLOYMENT_EXPOSURE—private|publicPAPERCLIP_PUBLIC_URL— public-facing URLANTHROPIC_API_KEY/OPENAI_API_KEY— AI provider keysPAPERCLIP_HOME— data root directory (default/paperclipin 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