fix: restore docs deleted in v0.2.3 release, add Paperclip branding

- Restored docs/ directory that was accidentally deleted by `git add -A`
  in the v0.2.3 release script
- Replaced generic "P" favicon with actual paperclip icon using brand
  primary color (#2563EB)
- Added light/dark logo SVGs for Mintlify navbar (paperclip icon + wordmark)
- Updated docs.json with logo configuration for dark/light mode
- Fixed release.sh to stage only release-related files instead of `git add -A`
  to prevent sweeping unrelated changes into release commits

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dotta
2026-03-03 15:49:43 -06:00
parent d18312d6de
commit 09d2ef1a37
55 changed files with 4159 additions and 2 deletions

77
docs/deploy/database.md Normal file
View File

@@ -0,0 +1,77 @@
---
title: Database
summary: Embedded PGlite vs Docker Postgres vs hosted
---
Paperclip uses PostgreSQL via Drizzle ORM. There are three ways to run the database.
## 1. Embedded PostgreSQL (Default)
Zero config. If you don't set `DATABASE_URL`, the server starts an embedded PostgreSQL instance automatically.
```sh
pnpm dev
```
On first start, the server:
1. Creates `~/.paperclip/instances/default/db/` for storage
2. Ensures the `paperclip` database exists
3. Runs migrations automatically
4. Starts serving requests
Data persists across restarts. To reset: `rm -rf ~/.paperclip/instances/default/db`.
The Docker quickstart also uses embedded PostgreSQL by default.
## 2. Local PostgreSQL (Docker)
For a full PostgreSQL server locally:
```sh
docker compose up -d
```
This starts PostgreSQL 17 on `localhost:5432`. Set the connection string:
```sh
cp .env.example .env
# DATABASE_URL=postgres://paperclip:paperclip@localhost:5432/paperclip
```
Push the schema:
```sh
DATABASE_URL=postgres://paperclip:paperclip@localhost:5432/paperclip \
npx drizzle-kit push
```
## 3. Hosted PostgreSQL (Supabase)
For production, use a hosted provider like [Supabase](https://supabase.com/).
1. Create a project at [database.new](https://database.new)
2. Copy the connection string from Project Settings > Database
3. Set `DATABASE_URL` in your `.env`
Use the **direct connection** (port 5432) for migrations and the **pooled connection** (port 6543) for the application.
If using connection pooling, disable prepared statements:
```ts
// packages/db/src/client.ts
export function createDb(url: string) {
const sql = postgres(url, { prepare: false });
return drizzlePg(sql, { schema });
}
```
## Switching Between Modes
| `DATABASE_URL` | Mode |
|----------------|------|
| Not set | Embedded PostgreSQL |
| `postgres://...localhost...` | Local Docker PostgreSQL |
| `postgres://...supabase.com...` | Hosted Supabase |
The Drizzle schema (`packages/db/src/schema/`) is the same regardless of mode.

View File

@@ -0,0 +1,85 @@
---
title: Deployment Modes
summary: local_trusted vs authenticated (private/public)
---
Paperclip supports two runtime modes with different security profiles.
## `local_trusted`
The default mode. Optimized for single-operator local use.
- **Host binding**: loopback only (localhost)
- **Authentication**: no login required
- **Use case**: local development, solo experimentation
- **Board identity**: auto-created local board user
```sh
# Set during onboard
pnpm paperclipai onboard
# Choose "local_trusted"
```
## `authenticated`
Login required. Supports two exposure policies.
### `authenticated` + `private`
For private network access (Tailscale, VPN, LAN).
- **Authentication**: login required via Better Auth
- **URL handling**: auto base URL mode (lower friction)
- **Host trust**: private-host trust policy required
```sh
pnpm paperclipai onboard
# Choose "authenticated" -> "private"
```
Allow custom Tailscale hostnames:
```sh
pnpm paperclipai allowed-hostname my-machine
```
### `authenticated` + `public`
For internet-facing deployment.
- **Authentication**: login required
- **URL**: explicit public URL required
- **Security**: stricter deployment checks in doctor
```sh
pnpm paperclipai onboard
# Choose "authenticated" -> "public"
```
## Board Claim Flow
When migrating from `local_trusted` to `authenticated`, Paperclip emits a one-time claim URL at startup:
```
/board-claim/<token>?code=<code>
```
A signed-in user visits this URL to claim board ownership. This:
- Promotes the current user to instance admin
- Demotes the auto-created local board admin
- Ensures active company membership for the claiming user
## Changing Modes
Update the deployment mode:
```sh
pnpm paperclipai configure --section server
```
Runtime override via environment variable:
```sh
PAPERCLIP_DEPLOYMENT_MODE=authenticated pnpm paperclipai run
```

69
docs/deploy/docker.md Normal file
View File

@@ -0,0 +1,69 @@
---
title: Docker
summary: Docker Compose quickstart
---
Run Paperclip in Docker without installing Node or pnpm locally.
## Compose Quickstart (Recommended)
```sh
docker compose -f docker-compose.quickstart.yml up --build
```
Open [http://localhost:3100](http://localhost:3100).
Defaults:
- Host port: `3100`
- Data directory: `./data/docker-paperclip`
Override with environment variables:
```sh
PAPERCLIP_PORT=3200 PAPERCLIP_DATA_DIR=./data/pc \
docker compose -f docker-compose.quickstart.yml up --build
```
## Manual Docker Build
```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
```
## Data Persistence
All data is persisted under the bind mount (`./data/docker-paperclip`):
- Embedded PostgreSQL data
- Uploaded assets
- Local secrets key
- Agent workspace data
## Claude and Codex Adapters in Docker
The Docker image pre-installs:
- `claude` (Anthropic Claude Code CLI)
- `codex` (OpenAI Codex CLI)
Pass API keys to enable local adapter runs inside the container:
```sh
docker run --name paperclip \
-p 3100:3100 \
-e HOST=0.0.0.0 \
-e PAPERCLIP_HOME=/paperclip \
-e OPENAI_API_KEY=sk-... \
-e ANTHROPIC_API_KEY=sk-... \
-v "$(pwd)/data/docker-paperclip:/paperclip" \
paperclip-local
```
Without API keys, the app runs normally — adapter environment checks will surface missing prerequisites.

View File

@@ -0,0 +1,50 @@
---
title: Environment Variables
summary: Full environment variable reference
---
All environment variables that Paperclip uses for server configuration.
## Server Configuration
| Variable | Default | Description |
|----------|---------|-------------|
| `PORT` | `3100` | Server port |
| `HOST` | `127.0.0.1` | Server host binding |
| `DATABASE_URL` | (embedded) | PostgreSQL connection string |
| `PAPERCLIP_HOME` | `~/.paperclip` | Base directory for all Paperclip data |
| `PAPERCLIP_INSTANCE_ID` | `default` | Instance identifier (for multiple local instances) |
| `PAPERCLIP_DEPLOYMENT_MODE` | `local_trusted` | Runtime mode override |
## Secrets
| Variable | Default | Description |
|----------|---------|-------------|
| `PAPERCLIP_SECRETS_MASTER_KEY` | (from file) | 32-byte encryption key (base64/hex/raw) |
| `PAPERCLIP_SECRETS_MASTER_KEY_FILE` | `~/.paperclip/.../secrets/master.key` | Path to key file |
| `PAPERCLIP_SECRETS_STRICT_MODE` | `false` | Require secret refs for sensitive env vars |
## Agent Runtime (Injected into agent processes)
These are set automatically by the server when invoking agents:
| Variable | Description |
|----------|-------------|
| `PAPERCLIP_AGENT_ID` | Agent's unique ID |
| `PAPERCLIP_COMPANY_ID` | Company ID |
| `PAPERCLIP_API_URL` | Paperclip API base URL |
| `PAPERCLIP_API_KEY` | Short-lived JWT for API auth |
| `PAPERCLIP_RUN_ID` | Current heartbeat run ID |
| `PAPERCLIP_TASK_ID` | Issue that triggered this wake |
| `PAPERCLIP_WAKE_REASON` | Wake trigger reason |
| `PAPERCLIP_WAKE_COMMENT_ID` | Comment that triggered this wake |
| `PAPERCLIP_APPROVAL_ID` | Resolved approval ID |
| `PAPERCLIP_APPROVAL_STATUS` | Approval decision |
| `PAPERCLIP_LINKED_ISSUE_IDS` | Comma-separated linked issue IDs |
## LLM Provider Keys (for adapters)
| Variable | Description |
|----------|-------------|
| `ANTHROPIC_API_KEY` | Anthropic API key (for Claude Local adapter) |
| `OPENAI_API_KEY` | OpenAI API key (for Codex Local adapter) |

View File

@@ -0,0 +1,90 @@
---
title: Local Development
summary: Set up Paperclip for local development
---
Run Paperclip locally with zero external dependencies.
## Prerequisites
- Node.js 20+
- pnpm 9+
## Start Dev Server
```sh
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:
```sh
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
## Tailscale/Private Auth Dev Mode
To run in `authenticated/private` mode for network access:
```sh
pnpm dev --tailscale-auth
```
This binds the server to `0.0.0.0` for private-network access.
Allow additional private hostnames:
```sh
pnpm paperclipai allowed-hostname dotta-macbook-pro
```
## Health Checks
```sh
curl http://localhost:3100/api/health
# -> {"status":"ok"}
curl http://localhost:3100/api/companies
# -> []
```
## Reset Dev Data
To wipe local data and start fresh:
```sh
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:
```sh
PAPERCLIP_HOME=/custom/path PAPERCLIP_INSTANCE_ID=dev pnpm paperclipai run
```

55
docs/deploy/overview.md Normal file
View File

@@ -0,0 +1,55 @@
---
title: Deployment Overview
summary: Deployment modes at a glance
---
Paperclip supports three deployment configurations, from zero-friction local to internet-facing production.
## Deployment Modes
| Mode | Auth | Best For |
|------|------|----------|
| `local_trusted` | No login required | Single-operator local machine |
| `authenticated` + `private` | Login required | Private network (Tailscale, VPN, LAN) |
| `authenticated` + `public` | Login required | Internet-facing cloud deployment |
## Quick Comparison
### Local Trusted (Default)
- Loopback-only host binding (localhost)
- No human login flow
- Fastest local startup
- Best for: solo development and experimentation
### Authenticated + Private
- Login required via Better Auth
- Binds to all interfaces for network access
- Auto base URL mode (lower friction)
- Best for: team access over Tailscale or local network
### Authenticated + Public
- Login required
- Explicit public URL required
- Stricter security checks
- Best for: cloud hosting, internet-facing deployment
## Choosing a Mode
- **Just trying Paperclip?** Use `local_trusted` (the default)
- **Sharing with a team on private network?** Use `authenticated` + `private`
- **Deploying to the cloud?** Use `authenticated` + `public`
Set the mode during onboarding:
```sh
pnpm paperclipai onboard
```
Or update it later:
```sh
pnpm paperclipai configure --section server
```

83
docs/deploy/secrets.md Normal file
View File

@@ -0,0 +1,83 @@
---
title: Secrets Management
summary: Master key, encryption, and strict mode
---
Paperclip encrypts secrets at rest using a local master key. Agent environment variables that contain sensitive values (API keys, tokens) are stored as encrypted secret references.
## Default Provider: `local_encrypted`
Secrets are encrypted with a local master key stored at:
```
~/.paperclip/instances/default/secrets/master.key
```
This key is auto-created during onboarding. The key never leaves your machine.
## Configuration
### CLI Setup
Onboarding writes default secrets config:
```sh
pnpm paperclipai onboard
```
Update secrets settings:
```sh
pnpm paperclipai configure --section secrets
```
Validate secrets config:
```sh
pnpm paperclipai doctor
```
### Environment Overrides
| Variable | Description |
|----------|-------------|
| `PAPERCLIP_SECRETS_MASTER_KEY` | 32-byte key as base64, hex, or raw string |
| `PAPERCLIP_SECRETS_MASTER_KEY_FILE` | Custom key file path |
| `PAPERCLIP_SECRETS_STRICT_MODE` | Set to `true` to enforce secret refs |
## Strict Mode
When strict mode is enabled, sensitive env keys (matching `*_API_KEY`, `*_TOKEN`, `*_SECRET`) must use secret references instead of inline plain values.
```sh
PAPERCLIP_SECRETS_STRICT_MODE=true
```
Recommended for any deployment beyond local trusted.
## Migrating Inline Secrets
If you have existing agents with inline API keys in their config, migrate them to encrypted secret refs:
```sh
pnpm secrets:migrate-inline-env # dry run
pnpm secrets:migrate-inline-env --apply # apply migration
```
## Secret References in Agent Config
Agent environment variables use secret references:
```json
{
"env": {
"ANTHROPIC_API_KEY": {
"type": "secret_ref",
"secretId": "8f884973-c29b-44e4-8ea3-6413437f8081",
"version": "latest"
}
}
}
```
The server resolves and decrypts these at runtime, injecting the real value into the agent process environment.

39
docs/deploy/storage.md Normal file
View File

@@ -0,0 +1,39 @@
---
title: Storage
summary: Local disk vs S3-compatible storage
---
Paperclip stores uploaded files (issue attachments, images) using a configurable storage provider.
## Local Disk (Default)
Files are stored at:
```
~/.paperclip/instances/default/data/storage
```
No configuration required. Suitable for local development and single-machine deployments.
## S3-Compatible Storage
For production or multi-node deployments, use S3-compatible object storage (AWS S3, MinIO, Cloudflare R2, etc.).
Configure via CLI:
```sh
pnpm paperclipai configure --section storage
```
## Configuration
| Provider | Best For |
|----------|----------|
| `local_disk` | Local development, single-machine deployments |
| `s3` | Production, multi-node, cloud deployments |
Storage configuration is stored in the instance config file:
```
~/.paperclip/instances/default/config.json
```