Files
PaperClipAI/docs/deploy/local-development.md
Dotta a70b0f70b6 Merge remote-tracking branch 'origin/master' into PAP-16679-paperclip-runner
* origin/master: (57 commits)
  fix(adapter-utils): extend the duplex fail-closed run disposition to the CLI lane (#11966)
  fix(recovery): stop automatic stranded-task takeovers (#11961)
  feat(sandbox): add the duplex bridge broker, gated transport selection, and fixed observability (#11769)
  Drop the mission step from the wizard arc (#11935)
  fix(runtime): guard empty Bash 3.2 array expansion (#11891)
  chore(lockfile): refresh pnpm-lock.yaml (#11915)
  feat(commitperclip): surface the Co-Authored-By trailers a squash merge needs (#11498)
  Rebuild the onboarding agent arc on the prototype's step design (#11905)
  fix(workspaces): read process cwd on macOS so port-owner adoption works (#11763)
  fix(workspaces): attach PR preparation to existing branches (#11703)
  fix(grok-local): stop defaulting --permission-mode to dontAsk (#11898)
  Fix remote-only workspace base refs and pre-adapter retry loops (#11892)
  feat(environments): refer to the managed default environment by name, not the sandbox driver key (#11838)
  test(server): cover buffered duplex chunk drain after a late listener bind (#11865)
  fix(server,ui,claude-local): verify auth on the adapter Test lane and enforce managed-sandbox tenant binding (#11810)
  chore(lockfile): refresh pnpm-lock.yaml (#11867)
  fix(kimi): align package with Node 24 policy (#11890)
  feat(ui): rename "Agent mode" to "Auto mode" and show full work-mode labels (#11866)
  fix(build): enforce Node 24 across Paperclip (#11792)
  fix(server): end the duplex route on the pre-bind bounds when frames arrive before the bind (#11860)
  ...

# Conflicts:
#	Dockerfile
#	packages/db/src/migrations/meta/0226_snapshot.json
#	packages/db/src/migrations/meta/_journal.json
#	pnpm-lock.yaml
#	server/package.json
#	server/src/routes/agents.ts
#	server/src/services/heartbeat.ts
#	server/src/services/issues.ts
#	server/src/services/recovery/service.ts
#	ui/package.json
#	ui/src/adapters/transcript.test.ts
#	ui/src/components/TaskChatThread.test.tsx
#	ui/src/components/TaskChatThread.tsx
#	ui/src/components/task-chat/TaskChatTurn.tsx
#	ui/src/index.css
#	ui/src/pages/Agents.tsx
2026-08-22 15:46:15 -05:00

3.3 KiB

title, summary
title summary
Local Development Set up Paperclip for local development

Run Paperclip locally with zero external dependencies.

Prerequisites

  • Node.js 24.11+
  • pnpm 9+

Start Dev Server

pnpm install
pnpm dev

This starts:

  • API server at http://localhost:3100
  • UI served by the API server in dev middleware mode (same origin)

No Docker or external database required. Paperclip uses embedded PostgreSQL automatically.

One-Command Bootstrap

For a first-time install:

pnpm paperclipai run

This does:

  1. Auto-onboards if config is missing
  2. Runs paperclipai doctor with repair enabled
  3. Starts the server when checks pass

Bind Presets In Dev

Default pnpm dev stays in local_trusted with loopback-only binding.

The commands in this section configure a fresh local instance. When a managed Paperclip host already has Tailscale and its app service running, first reuse the existing service and advertised URL. A feature task or package preview must not reconfigure Tailscale Serve, request an operator grant, or create a certificate unless that network change is an explicit task requirement.

To open Paperclip to a private network with login enabled:

pnpm dev --bind lan

For Tailscale-only binding on a detected tailnet address:

pnpm dev --bind tailnet

Legacy aliases still work and map to the older broad private-network behavior:

pnpm dev --tailscale-auth
pnpm dev --authenticated-private

Allow additional private hostnames:

npx paperclipai allowed-hostname dotta-macbook-pro

For full setup and troubleshooting, see Tailscale Private Access.

Health Checks

curl http://localhost:3100/api/health
# -> {"status":"ok"}

curl http://localhost:3100/api/companies
# -> []

Safe Worktree Bootstrap for Local Agent Runs

For safer parallel local experiments, initialize a dedicated worktree instance instead of reusing your main checkout:

npx paperclipai worktree:make local-lab --seed-mode minimal
cd ~/paperclip-local-lab
pnpm paperclipai worktree env                       # inspect generated env exports
eval "$(npx paperclipai worktree env)"             # bash/zsh
pnpm paperclipai run
pnpm paperclipai doctor

If the experiment gets noisy, repair or reseed the worktree without touching the main branch:

# worktree repair rebuilds the local checkout metadata, so run the checked-out CLI through the direct-exec form.
node cli/node_modules/tsx/dist/cli.mjs cli/src/index.ts worktree repair --branch paperclip-local-lab
npx paperclipai worktree reseed --from . --to paperclip-local-lab

When done, shut it down and remove the isolated state explicitly:

npx paperclipai worktree:cleanup local-lab --force

Reset Dev Data

To wipe local data and start fresh:

rm -rf ~/.paperclip/instances/default/db
pnpm dev

Data Locations

Data Path
Config ~/.paperclip/instances/default/config.json
Database ~/.paperclip/instances/default/db
Storage ~/.paperclip/instances/default/data/storage
Secrets key ~/.paperclip/instances/default/secrets/master.key
Logs ~/.paperclip/instances/default/logs

Override with environment variables:

PAPERCLIP_HOME=/custom/path PAPERCLIP_INSTANCE_ID=dev pnpm paperclipai run