2026-02-17 09:07:15 -06:00
# Developing
This project can run fully in local dev without setting up PostgreSQL manually.
2026-02-23 14:41:35 -06:00
## Deployment Modes
For mode definitions and intended CLI behavior, see `doc/DEPLOYMENT-MODES.md` .
Current implementation status:
- canonical model: `local_trusted` and `authenticated` (with `private/public` exposure)
2026-02-17 09:07:15 -06:00
## Prerequisites
- Node.js 20+
- pnpm 9+
2026-03-06 21:21:28 -03:00
## Dependency Lockfile Policy
GitHub Actions owns `pnpm-lock.yaml` .
- Do not commit `pnpm-lock.yaml` in pull requests.
- Pull request CI validates dependency resolution when manifests change.
- Pushes to `master` regenerate `pnpm-lock.yaml` with `pnpm install --lockfile-only --no-frozen-lockfile` , commit it back if needed, and then run verification with `--frozen-lockfile` .
2026-02-17 09:07:15 -06:00
## Start Dev
From repo root:
```sh
pnpm install
pnpm dev
```
This starts:
- API server: `http://localhost:3100`
2026-02-18 11:45:43 -06:00
- UI: served by the API server in dev middleware mode (same origin as API)
2026-02-17 09:07:15 -06:00
2026-03-06 15:48:35 -06:00
`pnpm dev` runs the server in watch mode and restarts on changes from workspace packages (including adapter packages). Use `pnpm dev:once` to run without file watching.
2026-02-23 16:08:17 -06:00
Tailscale/private-auth dev mode:
```sh
pnpm dev --tailscale-auth
```
This runs dev as `authenticated/private` and binds the server to `0.0.0.0` for private-network access.
2026-02-23 19:43:52 -06:00
Allow additional private hostnames (for example custom Tailscale hostnames):
```sh
2026-03-03 08:45:26 -06:00
pnpm paperclipai allowed-hostname dotta-macbook-pro
2026-02-23 19:43:52 -06:00
```
2026-02-20 07:10:58 -06:00
## One-Command Local Run
For a first-time local install, you can bootstrap and run in one command:
```sh
2026-03-03 08:45:26 -06:00
pnpm paperclipai run
2026-02-20 07:10:58 -06:00
```
2026-03-03 08:45:26 -06:00
`paperclipai run` does:
2026-02-20 07:10:58 -06:00
1. auto-onboard if config is missing
2026-03-03 08:45:26 -06:00
2. `paperclipai doctor` with repair enabled
2026-02-20 07:10:58 -06:00
3. starts the server when checks pass
2026-02-26 10:32:33 -06:00
## Docker Quickstart (No local Node install)
Build and run Paperclip in Docker:
```sh
docker build -t paperclip-local .
docker run --name paperclip \
-p 3100:3100 \
-e HOST=0.0.0.0 \
-e PAPERCLIP_HOME=/paperclip \
-v "$(pwd)/data/docker-paperclip:/paperclip" \
paperclip-local
```
Or use Compose:
```sh
docker compose -f docker-compose.quickstart.yml up --build
```
See `doc/DOCKER.md` for API key wiring (`OPENAI_API_KEY` / `ANTHROPIC_API_KEY` ) and persistence details.
2026-02-17 09:07:15 -06:00
## Database in Dev (Auto-Handled)
For local development, leave `DATABASE_URL` unset.
2026-02-18 11:45:43 -06:00
The server will automatically use embedded PostgreSQL and persist data at:
2026-02-17 09:07:15 -06:00
2026-02-20 07:10:58 -06:00
- `~/.paperclip/instances/default/db`
Override home and instance:
```sh
2026-03-03 08:45:26 -06:00
PAPERCLIP_HOME=/custom/path PAPERCLIP_INSTANCE_ID=dev pnpm paperclipai run
2026-02-20 07:10:58 -06:00
```
2026-02-17 09:07:15 -06:00
No Docker or external database is required for this mode.
2026-02-20 10:33:47 -06:00
## Storage in Dev (Auto-Handled)
For local development, the default storage provider is `local_disk` , which persists uploaded images/attachments at:
- `~/.paperclip/instances/default/data/storage`
Configure storage provider/settings:
```sh
2026-03-03 08:45:26 -06:00
pnpm paperclipai configure --section storage
2026-02-20 10:33:47 -06:00
```
2026-02-25 08:38:58 -06:00
## Default Agent Workspaces
When a local agent run has no resolved project/session workspace, Paperclip falls back to an agent home workspace under the instance root:
- `~/.paperclip/instances/default/workspaces/<agent-id>`
This path honors `PAPERCLIP_HOME` and `PAPERCLIP_INSTANCE_ID` in non-default setups.
2026-03-10 10:08:13 -05:00
## Worktree-local Instances
When developing from multiple git worktrees, do not point two Paperclip servers at the same embedded PostgreSQL data directory.
Instead, create a repo-local Paperclip config plus an isolated instance for the worktree:
```sh
paperclipai worktree init
```
This command:
- writes repo-local files at `.paperclip/config.json` and `.paperclip/.env`
- creates an isolated instance under `~/.paperclip-worktrees/instances/<worktree-id>/`
- picks a free app port and embedded PostgreSQL port
- by default seeds the isolated DB from your main instance via a logical SQL snapshot
After `worktree init` , both the server and the CLI auto-load the repo-local `.paperclip/.env` when run inside that worktree, so normal commands like `pnpm dev` , `paperclipai doctor` , and `paperclipai db:backup` stay scoped to the worktree instance.
Print shell exports explicitly when needed:
```sh
paperclipai worktree env
# or:
eval "$(paperclipai worktree env)"
```
Useful options:
```sh
paperclipai worktree init --no-seed
paperclipai worktree init --from-instance default
paperclipai worktree init --from-data-dir ~/.paperclip
paperclipai worktree init --force
```
2026-02-17 09:07:15 -06:00
## Quick Health Checks
In another terminal:
```sh
curl http://localhost:3100/api/health
curl http://localhost:3100/api/companies
```
Expected:
- `/api/health` returns `{"status":"ok"}`
- `/api/companies` returns a JSON array
## Reset Local Dev Database
To wipe local dev data and start fresh:
```sh
2026-02-20 07:10:58 -06:00
rm -rf ~/.paperclip/instances/default/db
2026-02-17 09:07:15 -06:00
pnpm dev
```
## Optional: Use External Postgres
2026-02-18 11:45:43 -06:00
If you set `DATABASE_URL` , the server will use that instead of embedded PostgreSQL.
2026-02-19 15:44:11 -06:00
2026-03-04 18:03:23 -06:00
## Automatic DB Backups
Paperclip can run automatic DB backups on a timer. Defaults:
- enabled
- every 60 minutes
- retain 30 days
- backup dir: `~/.paperclip/instances/default/data/backups`
Configure these in:
```sh
pnpm paperclipai configure --section database
```
2026-03-05 06:02:12 -06:00
Run a one-off backup manually:
```sh
pnpm paperclipai db:backup
# or:
pnpm db:backup
```
2026-03-04 18:03:23 -06:00
Environment overrides:
- `PAPERCLIP_DB_BACKUP_ENABLED=true|false`
- `PAPERCLIP_DB_BACKUP_INTERVAL_MINUTES=<minutes>`
- `PAPERCLIP_DB_BACKUP_RETENTION_DAYS=<days>`
- `PAPERCLIP_DB_BACKUP_DIR=/absolute/or/~/path`
2026-02-19 15:44:11 -06:00
## Secrets in Dev
Agent env vars now support secret references. By default, secret values are stored with local encryption and only secret refs are persisted in agent config.
2026-02-20 07:10:58 -06:00
- Default local key path: `~/.paperclip/instances/default/secrets/master.key`
2026-02-19 15:44:11 -06:00
- Override key material directly: `PAPERCLIP_SECRETS_MASTER_KEY`
- Override key file path: `PAPERCLIP_SECRETS_MASTER_KEY_FILE`
Strict mode (recommended outside local trusted machines):
```sh
PAPERCLIP_SECRETS_STRICT_MODE=true
```
When strict mode is enabled, sensitive env keys (for example `*_API_KEY` , `*_TOKEN` , `*_SECRET` ) must use secret references instead of inline plain values.
CLI configuration support:
2026-03-03 08:45:26 -06:00
- `pnpm paperclipai onboard` writes a default `secrets` config section (`local_encrypted` , strict mode off, key file path set) and creates a local key file when needed.
- `pnpm paperclipai configure --section secrets` lets you update provider/strict mode/key path and creates the local key file when needed.
- `pnpm paperclipai doctor` validates secrets adapter configuration and can create a missing local key file with `--repair` .
2026-02-19 15:44:11 -06:00
Migration helper for existing inline env secrets:
```sh
pnpm secrets:migrate-inline-env # dry run
pnpm secrets:migrate-inline-env --apply # apply migration
```
2026-02-20 07:10:58 -06:00
2026-03-02 16:44:10 -06:00
## Company Deletion Toggle
Company deletion is intended as a dev/debug capability and can be disabled at runtime:
```sh
PAPERCLIP_ENABLE_COMPANY_DELETION=false
```
Default behavior:
- `local_trusted` : enabled
- `authenticated` : disabled
2026-02-20 07:10:58 -06:00
## CLI Client Operations
Paperclip CLI now includes client-side control-plane commands in addition to setup commands.
Quick examples:
```sh
2026-03-03 08:45:26 -06:00
pnpm paperclipai issue list --company-id < company-id >
pnpm paperclipai issue create --company-id < company-id > --title "Investigate checkout conflict"
pnpm paperclipai issue update < issue-id > --status in_progress --comment "Started triage"
2026-02-20 07:10:58 -06:00
```
Set defaults once with context profiles:
```sh
2026-03-03 08:45:26 -06:00
pnpm paperclipai context set --api-base http://localhost:3100 --company-id < company-id >
2026-02-20 07:10:58 -06:00
```
Then run commands without repeating flags:
```sh
2026-03-03 08:45:26 -06:00
pnpm paperclipai issue list
pnpm paperclipai dashboard get
2026-02-20 07:10:58 -06:00
```
See full command reference in `doc/CLI.md` .
2026-02-26 16:33:20 -06:00
## OpenClaw Invite Onboarding Endpoints
Agent-oriented invite onboarding now exposes machine-readable API docs:
- `GET /api/invites/:token` returns invite summary plus onboarding and skills index links.
- `GET /api/invites/:token/onboarding` returns onboarding manifest details (registration endpoint, claim endpoint template, skill install hints).
2026-03-05 12:28:27 -06:00
- `GET /api/invites/:token/onboarding.txt` returns a plain-text onboarding doc intended for both human operators and agents (llm.txt-style handoff), including optional inviter message and suggested network host candidates.
2026-02-26 16:33:20 -06:00
- `GET /api/skills/index` lists available skill documents.
- `GET /api/skills/paperclip` returns the Paperclip heartbeat skill markdown.
2026-03-04 16:29:14 -06:00
## OpenClaw Join Smoke Test
Run the end-to-end OpenClaw join smoke harness:
```sh
pnpm smoke:openclaw-join
```
What it validates:
- invite creation for agent-only join
- agent join request using `adapterType=openclaw`
- board approval + one-time API key claim semantics
- callback delivery on wakeup to a dockerized OpenClaw-style webhook receiver
2026-03-04 16:37:55 -06:00
Required permissions:
- This script performs board-governed actions (create invite, approve join, wakeup another agent).
- In authenticated mode, run with board auth via `PAPERCLIP_AUTH_HEADER` or `PAPERCLIP_COOKIE` .
2026-03-04 16:29:14 -06:00
Optional auth flags (for authenticated mode):
- `PAPERCLIP_AUTH_HEADER` (for example `Bearer ...` )
- `PAPERCLIP_COOKIE` (session cookie header value)
2026-03-05 09:15:46 -06:00
## OpenClaw Docker UI One-Command Script
To boot OpenClaw in Docker and print a host-browser dashboard URL in one command:
```sh
pnpm smoke:openclaw-docker-ui
```
This script lives at `scripts/smoke/openclaw-docker-ui.sh` and automates clone/build/config/start for Compose-based local OpenClaw UI testing.
2026-03-05 11:04:14 -06:00
Pairing behavior for this smoke script:
2026-03-05 11:14:30 -06:00
- default `OPENCLAW_DISABLE_DEVICE_AUTH=1` (no Control UI pairing prompt for local smoke; no extra pairing env vars required)
2026-03-05 11:04:14 -06:00
- set `OPENCLAW_DISABLE_DEVICE_AUTH=0` to require standard device pairing
2026-03-05 11:29:29 -06:00
Model behavior for this smoke script:
- defaults to OpenAI models (`openai/gpt-5.2` + OpenAI fallback) so it does not require Anthropic auth by default
2026-03-05 11:42:50 -06:00
State behavior for this smoke script:
- defaults to isolated config dir `~/.openclaw-paperclip-smoke`
- resets smoke agent state each run by default (`OPENCLAW_RESET_STATE=1` ) to avoid stale provider/auth drift
2026-03-05 12:22:14 -06:00
Networking behavior for this smoke script:
- auto-detects and prints a Paperclip host URL reachable from inside OpenClaw Docker
- default container-side host alias is `host.docker.internal` (override with `PAPERCLIP_HOST_FROM_CONTAINER` / `PAPERCLIP_HOST_PORT` )
- if Paperclip rejects container hostnames in authenticated/private mode, allow `host.docker.internal` via `pnpm paperclipai allowed-hostname host.docker.internal` and restart Paperclip