paperclip Documentation

The open-source app everyone uses to manage agents at work

77,777 stars TypeScript TypeScript 1 file · ~27,618 tokens
RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy paperclip on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name paperclip -p 5432:5432 --restart always postgres:17-alpine
Configured Services & Ports
⚙️ db
image: postgres:17-alpine
🔌 Ports: 5432:5432
⚙️ server
image: build locally
🔌 Ports: 3100:3100
docker-compose.yml
yaml (docker-compose.yml)
services:
  db:
    image: postgres:17-alpine
    environment:
      POSTGRES_USER: paperclip
      POSTGRES_PASSWORD: paperclip
      POSTGRES_DB: paperclip
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U paperclip -d paperclip"]
      interval: 2s
      timeout: 5s
      retries: 30
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data

  server:
    build:
      context: ..
      dockerfile: Dockerfile
    # No `init: true` here on purpose. The image makes tini PID 1 itself
    # (Dockerfile ENTRYPOINT), which covers every launch path -- compose, plain
    # `docker run`, the quadlet units and the ECS task definition -- instead of
    # one lever per orchestrator. Setting it here too would nest docker-init
    # around tini and make tini warn that it is not PID 1 on every boot.
    # pids_limit is the backstop: if something ever does leak processes again,
    # this container hits its own ceiling and dies visibly rather than starving
    # the whole host of pids.
    pids_limit: 2048
    # Includes the shared 30s adapter-settlement window and final cleanup.
    stop_grace_period: 90s
    ports:
      - "3100:3100"
    environment:
      DATABASE_URL: postgres://paperclip:paperclip@db:5432/paperclip
      PORT: "3100"
      SERVE_UI: "true"
      PAPERCLIP_DEPLOYMENT_MODE: "authenticated"
      PAPERCLIP_DEPLOYMENT_EXPOSURE: "private"
      PAPERCLIP_PUBLIC_URL: "${PAPERCLIP_PUBLIC_URL:-http://localhost:3100}"
      BETTER_AUTH_SECRET: "${BETTER_AUTH_SECRET:?BETTER_AUTH_SECRET must be set}"
    volumes:
      - paperclip-data:/paperclip
    depends_on:
      db:
        condition: service_healthy

volumes:
  pgdata:
  paperclip-data:

1. Project Overview & Quickstart (paperclipai/paperclip)

File: README.md

Paperclip is the app people use to manage AI agents for work.

Open-source orchestration for teams of AI agents.

If OpenClaw is an employee, Paperclip is the company.

Paperclip is a Node.js server and React UI that orchestrates a team of AI agents to run a business. Bring your own agents, assign goals, and track work and costs from one dashboard.

It looks like a task manager. Under the hood: org charts, budgets, governance, goal alignment, and agent coordination.

Manage business goals, not pull requests.

Step Example
01 Define the goal "Build the #1 AI note-taking app to $1M MRR."
02 Hire the team CEO, CTO, engineers, designers, marketers — any bot, any provider.
03 Approve and run Review strategy. Set budgets. Hit go. Monitor from the dashboard.

Paperclip is right for you if

  • ✅ You want to build autonomous AI companies
  • ✅ You coordinate many different agents (OpenClaw, Codex, Claude, Cursor) toward a common goal
  • ✅ You have 20 simultaneous Claude Code terminals open and lose track of what everyone is doing
  • ✅ You want agents running autonomously 24/7, but still want to audit work and chime in when needed
  • ✅ You want to monitor costs and enforce budgets
  • ✅ You want a process for managing agents that feels like using a task manager
  • ✅ You want to manage your autonomous businesses from your phone

The four pillars

Four things have to work for an organization of AI agents to actually produce: the tasks, the org, the training, and the infrastructure. Paperclip is built around exactly those four pillars.

Pillar Built for What it covers
Agentic Task Manager — Declare intent. Agents work. You verify the output. Everyone, daily Tasks, approvals & review gates · proactive agent coworkers · auditable routines & workflows · verify from diffs, screenshots & tests
Org Chart for Agents — Roles, permissions & boundaries for humans and agents. Managers Mixed human + agent org chart · responsibilities, delegation, specialization · governance: who can do what · scoped secrets & company boundaries
Agent Employee Training — Design, train & evaluate your AI employees. Enablers Skill Studio & shared org-wide skills · evals & saved test runs · active learning loops & quality metrics · performance reviews for agents
Agentic OS — The infrastructure that makes the work run. IT & platform Cross-provider runtime: any model, any agent · sandboxing, integrations & MCP servers · SSO, GRC, RBAC & cost controls · data privacy, internal trace collection, compounding data value

Features

| 🔌 Bring Your Own Agent
Any agent, any runtime, one org chart. If it can receive a heartbeat, it's hired. | 🎯 Goal Alignment
Every task traces back to the company mission. Agents know what to do and why. | 💓 Heartbeats

Agents wake on a schedule, check work, and act. Delegation flows up and down the org chart. |
| --- | --- | --- |
| 💰 Cost Control
Monthly budgets per agent. When they hit the limit, they stop. No runaway costs. | 🏢 Multi-Company
One deployment, many companies. Complete data isolation. One control plane for your portfolio. | 🎫 Ticket System
Every conversation traced. Every decision explained. Full tool-call tracing and immutable audit log. |
| 🛡️ Governance
Approve hires, override strategy, pause or terminate any agent — at any time. | 📊 Org Chart
Hierarchies, roles, reporting lines. Your agents have a boss, a title, and a job description. | 📱 Mobile Ready
Monitor and manage your autonomous businesses from anywhere. |

Problems Paperclip solves

Without Paperclip With Paperclip
❌ You have 20 Claude Code tabs open and can't track which one does what. On reboot you lose everything. ✅ Tasks are ticket-based, conversations are threaded, sessions persist across reboots.
❌ You manually gather context from several places to remind your bot what you're actually doing. ✅ Context flows from the task up through the project and company goals — your agent always knows what to do and why.
❌ Folders of agent configs are disorganized and you're re-inventing task management, communication, and coordination between agents. ✅ Paperclip gives you org charts, ticketing, delegation, and governance out of the box — so you run a company, not a pile of scripts.
❌ Runaway loops waste hundreds of dollars of tokens and max your quota before you even know what happened. ✅ Cost tracking surfaces token budgets and throttles agents when they're out. Management prioritizes with budgets.
❌ You have recurring jobs (customer support, social, reports) and have to remember to manually kick them off. ✅ Heartbeats handle regular work on a schedule. Management supervises.
❌ You have an idea, you have to find your repo, fire up Claude Code, keep a tab open, and babysit it. ✅ Add a task in Paperclip. Your coding agent works on it until it's done. Management reviews their work.

Why Paperclip is special

Paperclip handles the hard orchestration details correctly.

Atomic execution. Task checkout and budget enforcement are atomic, so no double-work and no runaway spend.
Persistent agent state. Agents resume the same task context across heartbeats instead of restarting from scratch.
Runtime skill injection. Agents can learn Paperclip workflows and project context at runtime, without retraining.
Governance with rollback. Approval gates are enforced, config changes are revisioned, and bad changes can be rolled back safely.
Goal-aware execution. Tasks carry full goal ancestry so agents consistently see the "why," not just a title.
Portable company templates. Export/import orgs, agents, and skills with secret scrubbing and collision handling.
True multi-company isolation. Every entity is company-scoped, so one deployment can run many companies with separate data and audit trails.

What's Under the Hood

Paperclip is a full control plane, not a wrapper. Before you build any of this yourself, know that it already exists:

text
┌──────────────────────────────────────────────────────────────┐
│                       PAPERCLIP SERVER                       │
│                                                              │
│  ┌───────────┐  ┌───────────┐  ┌───────────┐  ┌───────────┐  │
│  │Identity & │  │  Work &   │  │ Heartbeat │  │Governance │  │
│  │  Access   │  │   Tasks   │  │ Execution │  │& Approvals│  │
│  └───────────┘  └───────────┘  └───────────┘  └───────────┘  │
│                                                              │
│  ┌───────────┐  ┌───────────┐  ┌───────────┐  ┌───────────┐  │
│  │ Org Chart │  │Workspaces │  │  Plugins  │  │  Budget   │  │
│  │ & Agents  │  │ & Runtime │  │           │  │ & Costs   │  │
│  └───────────┘  └───────────┘  └───────────┘  └───────────┘  │
│                                                              │
│  ┌───────────┐  ┌───────────┐  ┌───────────┐  ┌───────────┐  │
│  │ Routines  │  │ Secrets & │  │ Activity  │  │  Company  │  │
│  │& Schedules│  │  Storage  │  │ & Events  │  │Portability│  │
│  └───────────┘  └───────────┘  └───────────┘  └───────────┘  │
└──────────────────────────────────────────────────────────────┘
         ▲              ▲              ▲              ▲
   ┌─────┴─────┐  ┌─────┴─────┐  ┌─────┴─────┐  ┌─────┴─────┐
   │  Claude   │  │   Codex   │  │   CLI     │  │ HTTP/web  │
   │   Code    │  │           │  │  agents   │  │   bots    │
   └───────────┘  └───────────┘  └───────────┘  └───────────┘

The Systems

Identity & Access — Two deployment modes (trusted local or authenticated), board users, agent API keys, short-lived run JWTs, company memberships, invite flows, and OpenClaw onboarding. Every mutating request is traced to an actor. Org Chart & Agents — Agents have roles, titles, reporting lines, permissions, and budgets. Adapter examples match the diagram: Claude Code, Codex, CLI agents such as Cursor/Gemini/bash, HTTP/webhook bots such as OpenClaw, and external adapter plugins. If it can receive a heartbeat, it's hired.
Work & Task System — Issues carry company/project/goal/parent links, atomic checkout with execution locks, first-class blocker dependencies, comments, documents, attachments, work products, labels, and inbox state. No double-work, no lost context. Heartbeat Execution — DB-backed wakeup queue with coalescing, budget checks, workspace resolution, secret injection, skill loading, and adapter invocation. Runs produce structured logs, cost events, session state, and audit trails. Recovery handles orphaned runs automatically.
Workspaces & Runtime — Project workspaces, isolated execution workspaces (git worktrees, operator branches), and runtime services (dev servers, preview URLs). Agents work in the right directory with the right context every time. Governance & Approvals — Board approval workflows, execution policies with review/approval stages, decision tracking, budget hard-stops, agent pause/resume/terminate, and full audit logging. Nothing ships without your sign-off.
Budget & Cost Control — Token and cost tracking by company, agent, project, goal, issue, provider, and model. Scoped budget policies with warning thresholds and hard stops. Overspend pauses agents and cancels queued work automatically. Routines & Schedules — Recurring tasks with cron, webhook, and API triggers. Concurrency and catch-up policies. Each routine execution creates a tracked issue and wakes the assigned agent — no manual kick-offs needed.
Plugins — Instance-wide plugin system with out-of-process workers, capability-gated host services, job scheduling, tool exposure, and UI contributions. Extend Paperclip without forking it. Secrets & Storage — Instance and company secrets, encrypted local storage, provider-backed object storage, attachments, and work products. Sensitive values stay out of prompts unless a scoped run explicitly needs them.
Activity & Events — Mutating actions, heartbeat state changes, cost events, approvals, comments, and work products are recorded as durable activity so operators can audit what happened and why. Company Portability — Export and import entire organizations — agents, skills, projects, routines, and issues — with secret scrubbing and collision handling. One deployment, many companies, complete data isolation.

What Paperclip is not

Not a chatbot. Agents have jobs, not chat windows.
Not an agent framework. We don't tell you how to build agents. We tell you how to run a company made of them.
Not a workflow builder. No drag-and-drop pipelines. Paperclip models companies — with org charts, goals, budgets, and governance.
Not a prompt manager. Agents bring their own prompts, models, and runtimes. Paperclip manages the organization they work in.
Not a single-agent tool. This is for teams. If you have one agent, you probably don't need Paperclip. If you have twenty — you definitely do.
Not a code review tool. Paperclip orchestrates work, not pull requests. Bring your own review process.

Quickstart

Open source. Self-hosted. No Paperclip account required.

bash
curl -fsSLO https://paperclip.ing/install.sh
curl -fsSLO https://paperclip.ing/install.sh.sha256
if command -v sha256sum >/dev/null 2>&1; then
  sha256sum -c install.sh.sha256
else
  shasum -a 256 -c install.sh.sha256
fi
bash install.sh

The installer ensures Node.js 20 or newer is available, installs a managed
Paperclip CLI under ~/.paperclip/cli, and starts interactive onboarding. It
can also install Paperclip as a background service on supported Linux and
macOS systems. The checksum detects transfer or publishing mistakes, but it is
served from the same origin as the script; use a release-tag or commit-pinned
GitHub copy when you need an independently hosted source.

For a non-interactive managed install:

bash
curl -fsSL https://paperclip.ing/install.sh | bash -s -- --no-prompt --no-onboard
paperclipai onboard --yes

The piped form requires supported Node.js, npm, and npx to already be present.
If Node.js bootstrap is required, download and review install.sh before
running it so no privileged dependency-install command is accepted through a
pipe.

To try Paperclip without installing anything permanently:

bash
npx --registry https://registry.npmjs.org paperclipai onboard --yes

Troubleshooting: private npm registry .npmrc

If this fails with an E404 for paperclipai (or similar) and you use a private npm registry (for example GitHub Packages) via a global ~/.npmrc, npx may be resolving paperclipai against that private registry instead of the public npm registry.

Diagnostic:

bash
npm config get registry

Workaround (cross-platform; force the public npm registry for this command):

bash
npx --registry https://registry.npmjs.org paperclipai onboard --yes

That quickstart path now defaults to trusted local loopback mode for the fastest first run. To start in authenticated/private mode instead, choose a bind preset explicitly:

bash
paperclipai onboard --yes --bind lan
# or:
paperclipai onboard --yes --bind tailnet

If you already have Paperclip configured, rerunning onboard keeps the existing config in place. Use paperclipai configure to edit settings.

See doc/INSTALLING.md for pinned versions, canary and
git-ref installs, updates, rollback, service management, and uninstalling.

Or manually:

bash
git clone https://github.com/paperclipai/paperclip.git
cd paperclip
pnpm install
pnpm dev

This starts the API server at http://localhost:3100. An embedded PostgreSQL database is created automatically — no setup required.

Requirements: Node.js 20+, pnpm 9.15+

FAQ

What does a typical setup look like?
Locally, a single Node.js process manages an embedded Postgres and local file storage. For production, point it at your own Postgres and deploy however you like. Configure projects, agents, and goals — the agents take care of the rest.

If you're a solo entrepreneur you can use Tailscale to access Paperclip on the go. Then later you can deploy to e.g. Vercel when you need it.

Can I run multiple companies?
Yes. A single deployment can run an unlimited number of companies with complete data isolation.

How is Paperclip different from agents like OpenClaw or Claude Code?
Paperclip uses those agents. It orchestrates them into a company — with org charts, budgets, goals, governance, and accountability.

Why should I use Paperclip instead of just pointing my OpenClaw to Asana or Trello?
Agent orchestration has subtleties in how you coordinate who has work checked out, how to maintain sessions, monitoring costs, establishing governance - Paperclip does this for you.

(Bring-your-own-ticket-system is on the Roadmap)

Do agents run continuously?
By default, agents run on scheduled heartbeats and event-based triggers (task assignment, @-mentions). You can also hook in continuous agents like OpenClaw. You bring your agent and Paperclip coordinates.

Development

bash
pnpm dev              # Full dev (API + UI, watch mode)
pnpm dev:once         # Full dev without file watching
pnpm dev:server       # Server only
pnpm dev:mobile       # Serve prebuilt UI on :3101 for phones/tablets (proxies /api → :3100)
pnpm dev:both         # Run `pnpm dev` and `pnpm dev:mobile` together
pnpm build            # Build all
pnpm typecheck        # Type checking
pnpm test             # Cheap default test run (Vitest only)
pnpm test:watch       # Vitest watch mode
pnpm test:e2e         # Playwright browser suite
pnpm db:generate      # Generate DB migration
pnpm db:migrate       # Apply migrations

pnpm test does not run Playwright. Browser suites stay separate and are typically run only when working on those flows or in CI.

See doc/DEVELOPING.md for the full development guide.

Roadmap

  • ✅ Plugin system (e.g. add a knowledge base, custom tracing, queues, etc)
  • ✅ Get OpenClaw / claw-style agent employees
  • ✅ companies.sh - import and export entire organizations
  • ✅ Easy AGENTS.md configurations
  • ✅ Skills Manager, Skill Studio & Skills Store
  • ✅ Scheduled Routines
  • ✅ Better Budgeting
  • ✅ Agent Reviews and Approvals
  • ✅ Multiple Human Users
  • ✅ Cloud / Sandbox agents (e2b, Cloudflare, Daytona, Modal, Novita, self-hosted Kubernetes)
  • ✅ Artifacts & Work Products
  • ✅ Deep Planning (planning mode, revisioned plans, plan approvals)
  • ✅ Enforced Outcomes (watchdogs, recovery actions, review gates)
  • ✅ MCP Tool Gateway & Apps (governed tool access)
  • ✅ Secrets Manager with per-agent access
  • ✅ Activity log & action attribution
  • ✅ Self-healing runs & automatic recovery
  • ✅ Agent evals & feedback
  • ⚪ Memory / Knowledge
  • ⚪ MAXIMIZER MODE
  • ⚪ Work Queues
  • ⚪ Self-Organization
  • ⚪ Automatic Organizational Learning
  • ⚪ CEO Chat
  • 🟡 Cloud deployments (multi-tenant isolation & company Import/Export shipped)
  • ⚪ Desktop App
  • ⚪ Bring-your-own-ticket-system (Asana / Linear / Jira as on-ramps)
  • ⚪ Connected Apps (one-click integrations, e.g. Vercel)

This is the short roadmap preview. See the full roadmap in ROADMAP.md.

Community & Plugins

Find Plugins and more at awesome-paperclip

Observability

Paperclip ships with opt-in OpenTelemetry auto-instrumentation for the server (traces only). It activates when OTEL_EXPORTER_OTLP_ENDPOINT is set and supports grpc, http/protobuf, and http/json via the standard OTEL_EXPORTER_OTLP_PROTOCOL env var. The @opentelemetry/* packages are optional peer dependencies — install them only if you want tracing. See doc/observability.md for install commands and the full env-var reference.

Telemetry

Paperclip collects anonymous usage telemetry to help us understand how the product is used and improve it. No personal information, issue content, prompts, file paths, or secrets are ever collected. Private repository references are hashed with a per-install salt before being sent.

Contributors changing emitted telemetry events should follow the Telemetry Data Contract.
For proposed first-party events that are not in the generated contract yet, follow Telemetry Workflow.

Telemetry is enabled by default and can be disabled with any of the following:

Method How
Environment variable PAPERCLIP_TELEMETRY_DISABLED=1
Standard convention DO_NOT_TRACK=1
CI environments Automatically disabled when CI=true
Config file Set telemetry.enabled: false in your Paperclip config

Contributing

We welcome contributions. See the contributing guide for details.

Community

License

MIT © 2026 Paperclip Labs, Inc

Star History



File: cli/README.md

Paperclip is the app people use to manage AI agents for work.

Open-source orchestration for teams of AI agents.

If OpenClaw is an employee, Paperclip is the company.

Paperclip is a Node.js server and React UI that orchestrates a team of AI agents to run a business. Bring your own agents, assign goals, and track work and costs from one dashboard.

It looks like a task manager. Under the hood: org charts, budgets, governance, goal alignment, and agent coordination.

Manage business goals, not pull requests.

Step Example
01 Define the goal "Build the #1 AI note-taking app to $1M MRR."
02 Hire the team CEO, CTO, engineers, designers, marketers — any bot, any provider.
03 Approve and run Review strategy. Set budgets. Hit go. Monitor from the dashboard.

Paperclip is right for you if

  • ✅ You want to build autonomous AI companies
  • ✅ You coordinate many different agents (OpenClaw, Codex, Claude, Cursor) toward a common goal
  • ✅ You have 20 simultaneous Claude Code terminals open and lose track of what everyone is doing
  • ✅ You want agents running autonomously 24/7, but still want to audit work and chime in when needed
  • ✅ You want to monitor costs and enforce budgets
  • ✅ You want a process for managing agents that feels like using a task manager
  • ✅ You want to manage your autonomous businesses from your phone

Features

| 🔌 Bring Your Own Agent
Any agent, any runtime, one org chart. If it can receive a heartbeat, it's hired. | 🎯 Goal Alignment
Every task traces back to the company mission. Agents know what to do and why. | 💓 Heartbeats

Agents wake on a schedule, check work, and act. Delegation flows up and down the org chart. |
| --- | --- | --- |
| 💰 Cost Control
Monthly budgets per agent. When they hit the limit, they stop. No runaway costs. | 🏢 Multi-Company
One deployment, many companies. Complete data isolation. One control plane for your portfolio. | 🎫 Ticket System
Every conversation traced. Every decision explained. Full tool-call tracing and immutable audit log. |
| 🛡️ Governance
Approve hires, override strategy, pause or terminate any agent — at any time. | 📊 Org Chart
Hierarchies, roles, reporting lines. Your agents have a boss, a title, and a job description. | 📱 Mobile Ready
Monitor and manage your autonomous businesses from anywhere. |

Problems Paperclip solves

Without Paperclip With Paperclip
❌ You have 20 Claude Code tabs open and can't track which one does what. On reboot you lose everything. ✅ Tasks are ticket-based, conversations are threaded, sessions persist across reboots.
❌ You manually gather context from several places to remind your bot what you're actually doing. ✅ Context flows from the task up through the project and company goals — your agent always knows what to do and why.
❌ Folders of agent configs are disorganized and you're re-inventing task management, communication, and coordination between agents. ✅ Paperclip gives you org charts, ticketing, delegation, and governance out of the box — so you run a company, not a pile of scripts.
❌ Runaway loops waste hundreds of dollars of tokens and max your quota before you even know what happened. ✅ Cost tracking surfaces token budgets and throttles agents when they're out. Management prioritizes with budgets.
❌ You have recurring jobs (customer support, social, reports) and have to remember to manually kick them off. ✅ Heartbeats handle regular work on a schedule. Management supervises.
❌ You have an idea, you have to find your repo, fire up Claude Code, keep a tab open, and babysit it. ✅ Add a task in Paperclip. Your coding agent works on it until it's done. Management reviews their work.

Why Paperclip is special

Paperclip handles the hard orchestration details correctly.

Atomic execution. Task checkout and budget enforcement are atomic, so no double-work and no runaway spend.
Persistent agent state. Agents resume the same task context across heartbeats instead of restarting from scratch.
Runtime skill injection. Agents can learn Paperclip workflows and project context at runtime, without retraining.
Governance with rollback. Approval gates are enforced, config changes are revisioned, and bad changes can be rolled back safely.
Goal-aware execution. Tasks carry full goal ancestry so agents consistently see the "why," not just a title.
Portable company templates. Export/import orgs, agents, and skills with secret scrubbing and collision handling.
True multi-company isolation. Every entity is company-scoped, so one deployment can run many companies with separate data and audit trails.

What's Under the Hood

Paperclip is a full control plane, not a wrapper. Before you build any of this yourself, know that it already exists:

text
┌──────────────────────────────────────────────────────────────┐
│                       PAPERCLIP SERVER                       │
│                                                              │
│  ┌───────────┐  ┌───────────┐  ┌───────────┐  ┌───────────┐  │
│  │Identity & │  │  Work &   │  │ Heartbeat │  │Governance │  │
│  │  Access   │  │   Tasks   │  │ Execution │  │& Approvals│  │
│  └───────────┘  └───────────┘  └───────────┘  └───────────┘  │
│                                                              │
│  ┌───────────┐  ┌───────────┐  ┌───────────┐  ┌───────────┐  │
│  │ Org Chart │  │Workspaces │  │  Plugins  │  │  Budget   │  │
│  │ & Agents  │  │ & Runtime │  │           │  │ & Costs   │  │
│  └───────────┘  └───────────┘  └───────────┘  └───────────┘  │
│                                                              │
│  ┌───────────┐  ┌───────────┐  ┌───────────┐  ┌───────────┐  │
│  │ Routines  │  │ Secrets & │  │ Activity  │  │  Company  │  │
│  │& Schedules│  │  Storage  │  │ & Events  │  │Portability│  │
│  └───────────┘  └───────────┘  └───────────┘  └───────────┘  │
└──────────────────────────────────────────────────────────────┘
         ▲              ▲              ▲              ▲
   ┌─────┴─────┐  ┌─────┴─────┐  ┌─────┴─────┐  ┌─────┴─────┐
   │  Claude   │  │   Codex   │  │   CLI     │  │ HTTP/web  │
   │   Code    │  │           │  │  agents   │  │   bots    │
   └───────────┘  └───────────┘  └───────────┘  └───────────┘

The Systems

Identity & Access — Two deployment modes (trusted local or authenticated), board users, agent API keys, short-lived run JWTs, company memberships, invite flows, and OpenClaw onboarding. Every mutating request is traced to an actor. Org Chart & Agents — Agents have roles, titles, reporting lines, permissions, and budgets. Adapter examples match the diagram: Claude Code, Codex, CLI agents such as Cursor/Gemini/bash, HTTP/webhook bots such as OpenClaw, and external adapter plugins. If it can receive a heartbeat, it's hired.
Work & Task System — Issues carry company/project/goal/parent links, atomic checkout with execution locks, first-class blocker dependencies, comments, documents, attachments, work products, labels, and inbox state. No double-work, no lost context. Heartbeat Execution — DB-backed wakeup queue with coalescing, budget checks, workspace resolution, secret injection, skill loading, and adapter invocation. Runs produce structured logs, cost events, session state, and audit trails. Recovery handles orphaned runs automatically.
Workspaces & Runtime — Project workspaces, isolated execution workspaces (git worktrees, operator branches), and runtime services (dev servers, preview URLs). Agents work in the right directory with the right context every time. Governance & Approvals — Board approval workflows, execution policies with review/approval stages, decision tracking, budget hard-stops, agent pause/resume/terminate, and full audit logging. Nothing ships without your sign-off.
Budget & Cost Control — Token and cost tracking by company, agent, project, goal, issue, provider, and model. Scoped budget policies with warning thresholds and hard stops. Overspend pauses agents and cancels queued work automatically. Routines & Schedules — Recurring tasks with cron, webhook, and API triggers. Concurrency and catch-up policies. Each routine execution creates a tracked issue and wakes the assigned agent — no manual kick-offs needed.
Plugins — Instance-wide plugin system with out-of-process workers, capability-gated host services, job scheduling, tool exposure, and UI contributions. Extend Paperclip without forking it. Secrets & Storage — Instance and company secrets, encrypted local storage, provider-backed object storage, attachments, and work products. Sensitive values stay out of prompts unless a scoped run explicitly needs them.
Activity & Events — Mutating actions, heartbeat state changes, cost events, approvals, comments, and work products are recorded as durable activity so operators can audit what happened and why. Company Portability — Export and import entire organizations — agents, skills, projects, routines, and issues — with secret scrubbing and collision handling. One deployment, many companies, complete data isolation.

What Paperclip is not

Not a chatbot. Agents have jobs, not chat windows.
Not an agent framework. We don't tell you how to build agents. We tell you how to run a company made of them.
Not a workflow builder. No drag-and-drop pipelines. Paperclip models companies — with org charts, goals, budgets, and governance.
Not a prompt manager. Agents bring their own prompts, models, and runtimes. Paperclip manages the organization they work in.
Not a single-agent tool. This is for teams. If you have one agent, you probably don't need Paperclip. If you have twenty — you definitely do.
Not a code review tool. Paperclip orchestrates work, not pull requests. Bring your own review process.

Quickstart

Open source. Self-hosted. No Paperclip account required.

bash
npx paperclipai onboard --yes

That quickstart path now defaults to trusted local loopback mode for the fastest first run. To start in authenticated/private mode instead, choose a bind preset explicitly:

bash
npx paperclipai onboard --yes --bind lan
# or:
npx paperclipai onboard --yes --bind tailnet

If you already have Paperclip configured, rerunning onboard keeps the existing config in place. Use paperclipai configure to edit settings.

Or manually:

bash
git clone https://github.com/paperclipai/paperclip.git
cd paperclip
pnpm install
pnpm dev

This starts the API server at http://localhost:3100. An embedded PostgreSQL database is created automatically — no setup required.

Requirements: Node.js 20+, pnpm 9.15+

FAQ

What does a typical setup look like?
Locally, a single Node.js process manages an embedded Postgres and local file storage. For production, point it at your own Postgres and deploy however you like. Configure projects, agents, and goals — the agents take care of the rest.

If you're a solo entrepreneur you can use Tailscale to access Paperclip on the go. Then later you can deploy to e.g. Vercel when you need it.

Can I run multiple companies?
Yes. A single deployment can run an unlimited number of companies with complete data isolation.

How is Paperclip different from agents like OpenClaw or Claude Code?
Paperclip uses those agents. It orchestrates them into a company — with org charts, budgets, goals, governance, and accountability.

Why should I use Paperclip instead of just pointing my OpenClaw to Asana or Trello?
Agent orchestration has subtleties in how you coordinate who has work checked out, how to maintain sessions, monitoring costs, establishing governance - Paperclip does this for you.

(Bring-your-own-ticket-system is on the Roadmap)

Do agents run continuously?
By default, agents run on scheduled heartbeats and event-based triggers (task assignment, @-mentions). You can also hook in continuous agents like OpenClaw. You bring your agent and Paperclip coordinates.

Importing & Exporting Companies

Export a company to a portable package and import it into any other instance — local or cloud — from a local path or GitHub:

bash
paperclipai company export <company-id> --out ./my-export
paperclipai company import ./my-export --dry-run
paperclipai company import org/repo --target new

The board UI has matching Export and Import pages in company settings: the Export page shows a fidelity panel listing what the bundle will not carry, and the Import page starts imported agents and routines paused by default, with a post-import activation step. See the Importing & Exporting guide for details.

Development

bash
pnpm dev              # Full dev (API + UI, watch mode)
pnpm dev:once         # Full dev without file watching
pnpm dev:server       # Server only
pnpm build            # Build all
pnpm typecheck        # Type checking
pnpm test             # Cheap default test run (Vitest only)
pnpm test:watch       # Vitest watch mode
pnpm test:e2e         # Playwright browser suite
pnpm db:generate      # Generate DB migration
pnpm db:migrate       # Apply migrations

pnpm test does not run Playwright. Browser suites stay separate and are typically run only when working on those flows or in CI.

See doc/DEVELOPING.md for the full development guide.

Roadmap

  • ✅ Plugin system (e.g. add a knowledge base, custom tracing, queues, etc)
  • ✅ Get OpenClaw / claw-style agent employees
  • ✅ companies.sh - import and export entire organizations
  • ✅ Easy AGENTS.md configurations
  • ✅ Skills Manager
  • ✅ Scheduled Routines
  • ✅ Better Budgeting
  • ✅ Agent Reviews and Approvals
  • ✅ Multiple Human Users
  • ⚪ Cloud / Sandbox agents (e.g. Cursor / e2b / Novita agents)
  • ⚪ Artifacts & Work Products
  • ⚪ Memory / Knowledge
  • ⚪ Enforced Outcomes
  • ⚪ MAXIMIZER MODE
  • ⚪ Deep Planning
  • ⚪ Work Queues
  • ⚪ Self-Organization
  • ⚪ Automatic Organizational Learning
  • ⚪ CEO Chat
  • ⚪ Cloud deployments
  • ⚪ Desktop App

This is the short roadmap preview. See the full roadmap in ROADMAP.md.

Community & Plugins

Find Plugins and more at awesome-paperclip

Telemetry

Paperclip collects anonymous usage telemetry to help us understand how the product is used and improve it. No personal information, issue content, prompts, file paths, or secrets are ever collected. Private repository references are hashed with a per-install salt before being sent.

Telemetry is enabled by default and can be disabled with any of the following:

Method How
Environment variable PAPERCLIP_TELEMETRY_DISABLED=1
Standard convention DO_NOT_TRACK=1
CI environments Automatically disabled when CI=true
Config file Set telemetry.enabled: false in your Paperclip config

Contributing

We welcome contributions. See the contributing guide for details.

Community

License

MIT © 2026 Paperclip Labs, Inc

Star History



File: doc/experimental/issue-worktree-support.md

Issue worktree support

Status: experimental, runtime-only, not shipping as a user-facing feature yet.

This branch contains the runtime and seeding work needed for issue-scoped worktrees:

  • project execution workspace policy support
  • issue-level execution workspace settings
  • git worktree realization for isolated issue execution
  • optional command-based worktree provisioning
  • seeded worktree fixes for secrets key compatibility
  • seeded project workspace rebinding to the current git worktree

We are intentionally not shipping the UI for this yet. The runtime code remains in place, but the main UI entrypoints are hard-gated off for now.

What works today

  • projects can carry execution workspace policy in the backend
  • issues can carry execution workspace settings in the backend
  • heartbeat execution can realize isolated git worktrees
  • runtime can run a project-defined provision command inside the derived worktree
  • seeded worktree instances can keep local-encrypted secrets working
  • seeded worktree instances can rebind same-repo project workspace paths onto the current git worktree

Shared workspace concurrency policy

Projects and individual issues can set sharedWorkspaceConcurrency in their execution workspace policy/settings:

  • auto (the default when absent): allow concurrent shared-workspace runs on local and ssh environments, and serialize runs on sandbox and plugin environments. An instance forced to Kubernetes always serializes in auto mode.
  • serialize: defer a run while another live run holds the same project workspace, using the workspace_busy retry path.
  • allow: dispatch alongside a live holder on every environment.

Issue settings override the project policy, which overrides the default auto. When concurrency is allowed and a live holder exists, Paperclip adds the holder run and issue to the dispatched task context so agents can coordinate concurrent mutations through commits. The setting is optional JSON policy data, so existing databases require no migration.

Hidden UI entrypoints

These are the current user-facing UI surfaces for the feature, now intentionally disabled:

  • project settings:

    • ui/src/components/ProjectProperties.tsx
    • execution workspace policy controls
    • git worktree base ref / branch template / parent dir
    • provision / teardown command inputs
  • issue creation:

    • ui/src/components/NewIssueDialog.tsx
    • isolated issue checkout toggle
    • defaulting issue execution workspace settings from project policy
  • issue editing:

    • ui/src/components/IssueProperties.tsx
    • issue-level workspace mode toggle
    • defaulting issue execution workspace settings when project changes
  • agent/runtime settings:

    • ui/src/adapters/runtime-json-fields.tsx
    • runtime services JSON field, which is part of the broader workspace-runtime support surface

Why the UI is hidden

  • the runtime behavior is still being validated
  • the workflow and operator ergonomics are not final
  • we do not want to expose a partially-baked user-facing feature in issues, projects, or settings

Re-enable plan

When this is ready to ship:

  • re-enable the gated UI sections in the files above
  • review wording and defaults for project and issue controls
  • decide which agent/runtime settings should remain advanced-only
  • add end-to-end product-level verification for the full UI workflow

File: doc/plans/2026-02-16-module-system.md

Paperclip Module System

Supersession note: the company-template/package-format direction in this document is no longer current. For the current markdown-first company import/export plan, see doc/plans/2026-03-13-company-import-export-v2.md and docs/companies/companies-spec.md.

Overview

Paperclip's module system lets you extend the control plane with new capabilities — revenue tracking, observability, notifications, dashboards — without forking core. Modules are self-contained packages that register routes, UI pages, database tables, and lifecycle hooks.

Separately, Company Templates are code-free data packages (agent teams, org charts, goal hierarchies) that you can import to bootstrap a new company.

Both are discoverable through the Company Store.


Concepts

Concept What it is Contains code?
Module A package that extends Paperclip's API, UI, and data model Yes
Company Template A data snapshot — agents, projects, goals, org structure No (JSON only)
Company Store Registry for browsing/installing modules and templates —
Hook A named event in the core that modules can subscribe to —
Slot An exclusive category where only one module can be active (e.g., observability) —

Module Architecture

File Structure

text
modules/
  observability/
    paperclip.module.json     # manifest (required)
    src/
      index.ts                # entry point — exports register function
      routes.ts               # Express router
      hooks.ts                # hook handlers
      schema.ts               # Drizzle table definitions
      migrations/             # SQL migrations (generated by drizzle-kit)
      ui/                     # React components (lazy-loaded by the shell)
        index.ts              # exports page/widget definitions
        TokenDashboard.tsx

Modules live in a top-level modules/ directory. Each module is a pnpm workspace package.

Manifest (`paperclip.module.json`)

json
{
  "id": "observability",
  "name": "Observability",
  "description": "Token tracking, cost metrics, and agent performance instrumentation",
  "version": "0.1.0",
  "author": "paperclip",

  "slot": "observability",

  "hooks": [
    "agent:heartbeat",
    "agent:created",
    "issue:status_changed",
    "budget:threshold_crossed"
  ],

  "routes": {
    "prefix": "/observability",
    "entry": "./src/routes.ts"
  },

  "ui": {
    "pages": [
      {
        "path": "/observability",
        "label": "Observability",
        "entry": "./src/ui/index.ts"
      }
    ],
    "widgets": [
      {
        "id": "token-burn-rate",
        "label": "Token Burn Rate",
        "placement": "dashboard",
        "entry": "./src/ui/index.ts"
      }
    ]
  },

  "schema": "./src/schema.ts",

  "configSchema": {
    "type": "object",
    "properties": {
      "retentionDays": { "type": "number", "default": 30 },
      "enablePrometheus": { "type": "boolean", "default": false },
      "prometheusPort": { "type": "number", "default": 9090 }
    }
  },

  "requires": {
    "core": ">=0.1.0"
  }
}

Key fields:

  • id: Unique identifier, used as the npm package name suffix (@paperclipai/mod-observability)
  • slot: Optional exclusive category. If set, only one module with this slot can be active. Omit for modules that can coexist freely.
  • hooks: Which core events this module subscribes to. Declared upfront so the core knows what to emit.
  • routes.prefix: Mounted under /api/modules/. The module owns this namespace.
  • ui.pages: Adds entries to the sidebar. Lazy-loaded React components.
  • ui.widgets: Injects components into existing pages (e.g., dashboard cards).
  • schema: Drizzle table definitions for module-owned tables. Prefixed with mod__ to avoid collisions.
  • configSchema: JSON Schema for module configuration. Validated before the module loads.

Entry Point

The module's src/index.ts exports a register function that receives the module API:

typescript
import type { ModuleAPI } from "@paperclipai/core";
import { createRouter } from "./routes.js";
import { onHeartbeat, onBudgetThreshold } from "./hooks.js";

export default function register(api: ModuleAPI) {
  // Register route handler
  api.registerRoutes(createRouter(api.db, api.config));

  // Subscribe to hooks
  api.on("agent:heartbeat", onHeartbeat);
  api.on("budget:threshold_crossed", onBudgetThreshold);

  // Register a background service (optional)
  api.registerService({
    name: "metrics-aggregator",
    interval: 60_000, // run every 60s
    async run(ctx) {
      await aggregateMetrics(ctx.db);
    },
  });
}

Module API Surface

typescript
interface ModuleAPI {
  // Identity
  moduleId: string;
  config: Record<string, unknown>;  // validated against configSchema

  // Database
  db: Db;                           // shared Drizzle client

  // Routes
  registerRoutes(router: Router): void;

  // Hooks
  on(event: HookEvent, handler: HookHandler): void;

  // Background services
  registerService(service: ServiceDef): void;

  // Logging (scoped to module)
  logger: Logger;

  // Access core services (read-only helpers)
  core: {
    agents: AgentService;
    issues: IssueService;
    projects: ProjectService;
    goals: GoalService;
    activity: ActivityService;
  };
}

Modules get a scoped logger, access to the shared database, and read access to core services. They register their own routes and hook handlers. They do NOT monkey-patch core — they extend through defined interfaces.


Hook System

Core Hook Points

Hooks are the primary integration point. The core emits events at well-defined moments. Modules subscribe in their register function.

Hook Payload When
server:started { port } After the Express server begins listening
agent:created { agent } After a new agent is inserted
agent:updated { agent, changes } After an agent record is modified
agent:deleted { agent } After an agent is removed
agent:heartbeat { agentId, timestamp, meta } When an agent checks in. meta carries tokens_used, cost, latency, etc.
agent:status_changed { agent, from, to } When agent status transitions (idle→active, active→error, etc.)
issue:created { issue } After a new issue is inserted
issue:status_changed { issue, from, to } When issue moves between statuses
issue:assigned { issue, agent } When an issue is assigned to an agent
goal:created { goal } After a new goal is inserted
goal:completed { goal } When a goal's status becomes complete
budget:spend_recorded { agentId, amount, total } After spend is incremented
budget:threshold_crossed { agentId, budget, spent, percent } When an agent crosses 80%, 90%, or 100% of budget

Hook Execution Model

typescript
// In the core — hook emitter
class HookBus {
  private handlers = new Map<string, HookHandler[]>();

  register(event: string, handler: HookHandler) {
    const list = this.handlers.get(event) ?? [];
    list.push(handler);
    this.handlers.set(event, list);
  }

  async emit(event: string, payload: unknown) {
    const handlers = this.handlers.get(event) ?? [];
    // Run all handlers concurrently. Failures are logged, never block core.
    await Promise.allSettled(
      handlers.map(h => h(payload))
    );
  }
}

Design rules:

  • Hooks are fire-and-forget. A failing hook handler never crashes or blocks the core operation.
  • Hooks are concurrent. All handlers for an event run in parallel via Promise.allSettled.
  • Hooks are post-commit. They fire after the database write succeeds, not before. No vetoing.
  • Hooks receive immutable snapshots. Handlers get a copy of the data, not a mutable reference.

This keeps the core fast and resilient. If you need pre-commit validation (e.g., "reject this budget change"), that's a different mechanism (middleware/interceptor) we can add later if needed.

Observability Hook Example

typescript
// modules/observability/src/hooks.ts
import type { Db } from "@paperclipai/db";
import { tokenMetrics } from "./schema.js";

export function createHeartbeatHandler(db: Db) {
  return async (payload: {
    agentId: string;
    timestamp: Date;
    meta: { tokensUsed?: number; costCents?: number; model?: string };
  }) => {
    const { agentId, timestamp, meta } = payload;

    if (meta.tokensUsed != null) {
      await db.insert(tokenMetrics).values({
        agentId,
        tokensUsed: meta.tokensUsed,
        costCents: meta.costCents ?? 0,
        model: meta.model ?? "unknown",
        recordedAt: timestamp,
      });
    }
  };
}

Every heartbeat, the observability module records token usage into its own mod_observability_token_metrics table. The core doesn't know or care about this table — it just emits the hook.


Database Strategy for Modules

Table Namespacing

Module tables are prefixed with mod_<moduleId>_ to avoid collisions with core tables and other modules:

typescript
// modules/observability/src/schema.ts
import { pgTable, uuid, integer, text, timestamp } from "drizzle-orm/pg-core";

export const tokenMetrics = pgTable("mod_observability_token_metrics", {
  id: uuid("id").primaryKey().defaultRandom(),
  agentId: uuid("agent_id").notNull(),
  tokensUsed: integer("tokens_used").notNull(),
  costCents: integer("cost_cents").notNull().default(0),
  model: text("model").notNull(),
  recordedAt: timestamp("recorded_at", { withTimezone: true }).notNull().defaultNow(),
});

export const alertRules = pgTable("mod_observability_alert_rules", {
  id: uuid("id").primaryKey().defaultRandom(),
  agentId: uuid("agent_id"),
  metricName: text("metric_name").notNull(),
  threshold: integer("threshold").notNull(),
  enabled: boolean("enabled").notNull().default(true),
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
});

Migration Strategy

Each module manages its own migrations in src/migrations/. The core migration runner discovers and applies them:

  1. Core migrations run first (always)
  2. Module migrations run in dependency order
  3. Each module's migrations are tracked in a mod_migrations table with the module ID
  4. pnpm db:migrate runs everything. pnpm db:migrate --module observability runs one.

Modules can reference core tables via foreign keys (e.g., agent_id → agents.id) but core tables never reference module tables. This is a strict one-way dependency.


Module Loading & Lifecycle

Discovery

On server startup:

text
1. Scan modules/ directory for paperclip.module.json manifests
2. Validate each manifest (JSON Schema check on configSchema, required fields)
3. Check slot conflicts (error if two active modules claim the same slot)
4. Topological sort by dependencies (if module A requires module B)
5. For each module in order:
   a. Validate module config against configSchema
   b. Run pending migrations
   c. Import entry point and call register(api)
   d. Mount routes at /api/modules/
   e. Start background services
6. Emit server:started hook

Configuration

Module config lives in the server's environment or a config file:

jsonc
// paperclip.config.json (or env vars)
{
  "modules": {
    "enabled": ["observability", "revenue", "notifications"],
    "config": {
      "observability": {
        "retentionDays": 90,
        "enablePrometheus": true
      },
      "revenue": {
        "stripeSecretKey": "$STRIPE_SECRET_KEY"
      }
    }
  }
}

$ENV_VAR references are resolved at load time. Secrets never go in the config file directly.

Disabling a Module

Setting a module's enabled state to false:

  1. Stops its background services
  2. Unmounts its routes (returns 404)
  3. Unsubscribes its hook handlers
  4. Does NOT drop its database tables (data is preserved)

UI Integration

How Module UI Works

The core UI shell provides:

  • A sidebar with slots for module-contributed nav items
  • A dashboard with widget mount points
  • A module settings page

Modules declare pages and widgets in the manifest. The shell lazy-loads them:

typescript
// ui/src/modules/loader.ts
// At build time or runtime, discover module UI entries and create lazy routes

import { lazy } from "react";

// Generated from manifests
export const modulePages = [
  {
    path: "/observability",
    label: "Observability",
    component: lazy(() => import("@paperclipai/mod-observability/ui")),
  },
];

export const dashboardWidgets = [
  {
    id: "token-burn-rate",
    label: "Token Burn Rate",
    placement: "dashboard",
    component: lazy(() => import("@paperclipai/mod-observability/ui").then(m => ({ default: m.TokenBurnRateWidget }))),
  },
];

Module UI Contract

A module's UI entry exports named components:

typescript
// modules/observability/src/ui/index.ts
export { default } from "./ObservabilityPage";
export { TokenBurnRateWidget } from "./TokenBurnRateWidget";

Module UI components receive a standard props interface:

typescript
interface ModulePageProps {
  moduleId: string;
  config: Record<string, unknown>;
}

interface ModuleWidgetProps {
  moduleId: string;
  config: Record<string, unknown>;
  className?: string;
}

Module UI hits the module's own API routes (/api/modules/observability/*) for data.


Company Templates

Format

A company template is a JSON file describing a full company structure:

text
/* Detailed source-code truncated for AI context efficiency. */

Templates use ref strings (not UUIDs) for internal cross-references. On import, the system maps refs to generated UUIDs.

Import Flow

text
1. Parse and validate the template JSON
2. Check for ref uniqueness and dangling references
3. Insert agents (topological sort by reportsTo)
4. Insert goals (topological sort by parentRef)
5. Insert projects
6. Insert issues (resolve projectRef, assigneeRef, goalRef to real IDs)
7. Log activity events for everything created

Export Flow

You can also export a running company as a template:

text
GET /api/templates/export → downloads the current company as a template JSON

This makes companies shareable and clonable.


Company Store

The Company Store is a registry for discovering and installing modules and templates. For v1, it's a curated GitHub repo with a JSON index. Later it could become a hosted service.

Index Format

json
{
  "modules": [
    {
      "id": "observability",
      "name": "Observability",
      "description": "Token tracking, cost metrics, and agent performance",
      "repo": "github:paperclip/mod-observability",
      "version": "0.1.0",
      "tags": ["metrics", "monitoring", "tokens"]
    }
  ],
  "templates": [
    {
      "id": "startup-in-a-box",
      "name": "Startup in a Box",
      "description": "5-agent startup team",
      "url": "https://store.paperclip.ing/templates/startup-in-a-box.json",
      "tags": ["startup", "team"]
    }
  ]
}

CLI Commands

bash
pnpm paperclipai store list                    # browse available modules and templates
pnpm paperclipai store install <module-id>     # install a module
pnpm paperclipai store import <template-id>    # import a company template
pnpm paperclipai store export                  # export current company as template

Module Candidates

Tier 1 — Build first (core extensions)

Module What it does Key hooks
Observability Token usage tracking, cost metrics, agent performance dashboards, Prometheus export agent:heartbeat, budget:spend_recorded
Revenue Tracking Connect Stripe/crypto wallets, track income, show P&L against agent costs budget:spend_recorded
Notifications Slack/Discord/email alerts on configurable triggers All hooks (configurable)

Tier 2 — High value

Module What it does Key hooks
Analytics Dashboard Burn rate trends, agent utilization over time, goal velocity charts agent:heartbeat, issue:status_changed, goal:completed
Workflow Automation If/then rules: "when issue is done, create follow-up", "when budget at 90%, pause agent" issue:status_changed, budget:threshold_crossed
Knowledge Base Shared document store, vector search, agents read/write organizational knowledge agent:heartbeat (for context injection)

Tier 3 — Nice to have

Module What it does Key hooks
Audit & Compliance Immutable audit trail, approval workflows, spend authorization All write hooks
Agent Logs / Replay Full execution traces per agent, token-by-token replay agent:heartbeat
Multi-tenant Separate companies/orgs within one Paperclip instance server:started

Implementation Plan

Phase 1: Core infrastructure

Add to @paperclipai/server:

  1. HookBus — Event emitter with register() and emit(), using Promise.allSettled
  2. Module loader — Scans modules/, validates manifests, calls register(api)
  3. Module API object — registerRoutes(), on(), registerService(), logger, core service access
  4. Module config — paperclip.config.json with per-module config, env var interpolation
  5. Module migration runner — Extends db:migrate to discover and run module migrations
  6. Emit hooks from core services — Add hookBus.emit() calls to existing CRUD operations

Add to @paperclipai/ui:

  1. Module page loader — Reads module manifests, generates lazy routes
  2. Dashboard widget slots — Render module-contributed widgets on the Dashboard page
  3. Sidebar extension — Dynamically add module nav items

Add new package:

  1. @paperclipai/module-sdk — TypeScript types for ModuleAPI, HookEvent, HookHandler, manifest schema

Phase 2: First module (observability)

  1. Build modules/observability as the reference implementation
  2. Token metrics table + migration
  3. Heartbeat hook handler recording token usage
  4. Dashboard widget showing burn rate
  5. API routes for querying metrics

Phase 3: Templates

  1. Template import endpoint (POST /api/templates/import)
  2. Template export endpoint (GET /api/templates/export)
  3. First template: "Startup in a Box"

Phase 4: Company Store

  1. GitHub-based store index
  2. CLI commands for browse/install/import
  3. UI page for browsing the store

Design Principles

  1. Modules extend, never patch. Modules add new routes, tables, and hook handlers. They never modify core tables or override core routes.

  2. Hooks are post-commit, fire-and-forget. Module failures never break core operations.

  3. One-way dependency. Modules depend on core. Core never depends on modules. Module tables can FK to core tables, not the reverse.

  4. Declarative manifest, imperative registration. Static metadata in JSON (validated without running code). Runtime behavior registered via the API.

  5. Namespace isolation. Module routes live under /api/modules//. Module tables are prefixed mod__. Module config is scoped to its ID.

  6. Graceful degradation. If a module fails to load, log the error and continue. The rest of the system works fine.

  7. Data survives disable. Disabling a module stops its code but preserves its data. Re-enabling picks up where it left off.


File: doc/plans/2026-02-18-agent-authentication.md

Agent Authentication & Onboarding

Problem

Agents need API keys to authenticate with Paperclip. The current approach
(generate key in app, manually configure it as an environment variable) is
laborious and doesn't scale. Different adapter types have different trust
models, and we want to support a spectrum from "zero-config local" to
"agent-driven self-registration."

Design Principles

  1. Match auth complexity to the trust boundary. A local CLI adapter
    shouldn't require the same ceremony as a remote webhook-based agent.
  2. Agents should be able to onboard themselves. Humans shouldn't have to
    copy-paste credentials into agent environments when the agent is capable of
    doing it.
  3. Approval gates by default. Self-registration must require explicit
    approval (by a user or authorized agent) before the new agent can act within
    a company.

Authentication Tiers

Tier 1: Local Adapter (claude-local, codex-local)

Trust model: The adapter process runs on the same machine as the Paperclip
server (or is invoked directly by it). There is no meaningful network boundary.

Approach: Paperclip generates a token and passes it directly to the agent
process as a parameter/env var at invocation time. No manual setup required.

Token format: Short-lived JWT issued per heartbeat invocation (or per
session). The server mints the token, passes it in the adapter call, and
accepts it back on API requests.

Token lifetime considerations:

  • Coding agents can run for hours, so tokens can't expire too quickly.
  • Infinite-lived tokens are undesirable even in local contexts.
  • Use JWTs with a generous expiry (e.g. 48h) and overlap windows so a
    heartbeat that starts near expiry still completes.
  • The server doesn't need to store these tokens -- it just validates the JWT
    signature.

Status: Partially implemented. The local adapter already passes
PAPERCLIP_API_URL, PAPERCLIP_AGENT_ID, PAPERCLIP_COMPANY_ID. We need to
add a PAPERCLIP_API_KEY (JWT) to the set of injected env vars.

Tier 2: CLI-Driven Key Exchange

Trust model: A developer is setting up a remote or semi-remote agent and
has shell access to it.

Approach: Similar to claude setup-token -- the developer runs a Paperclip CLI
command that opens a browser URL for confirmation, then receives a token that
gets stored in the agent's config automatically.

text
paperclip auth login
# Opens browser -> user confirms -> token stored at ~/.paperclip/credentials

Token format: Long-lived API key (stored hashed on the server side).

Status: Future. Not needed until we have remote adapters that aren't
managed by the Paperclip server itself.

Trust model: The agent is an autonomous external system (e.g. an OpenClaw
agent, a SWE-agent instance). There is no human in the loop during setup. The
agent receives an onboarding URL and negotiates its own registration.

Approach:

  1. A company admin (user or agent) generates an invite URL from Paperclip.
  2. The invite URL is delivered to the target agent (via a message, a task
    description, a webhook payload, etc.).
  3. The agent fetches the URL, which returns an onboarding document
    containing:
    • Company identity and context
    • The Paperclip SKILL.md (or a link to it)
    • What information Paperclip needs from the agent (e.g. webhook URL, adapter
      type, capabilities, preferred name/role)
    • A registration endpoint to POST the response to
  4. The agent responds with its configuration (e.g. "here's my webhook URL,
    here's my name, here are my capabilities").
  5. Paperclip stores the pending registration.
  6. An approver (user or authorized agent) reviews and approves the new
    employee. Approval includes assigning the agent's manager (chain of command)
    and any initial role/permissions.
  7. On approval, Paperclip provisions the agent's credentials and sends the
    first heartbeat.

Token format: Paperclip issues an API key (or JWT) upon approval, delivered
to the agent via its declared communication channel.

Inspiration:

  • Allium self-registration --
    agent collects credentials, polls for confirmation, stores key automatically.
  • Allium x402 -- multi-step
    credential setup driven entirely by the agent.
  • OpenClaw webhooks -- external
    systems trigger agent actions via authenticated webhook endpoints.

Self-Registration: Onboarding Negotiation Protocol

The invite URL response should be a structured document (JSON or markdown) that
is both human-readable and machine-parseable:

text
GET /api/invite/{inviteToken}

Response:

json
{
  "company": {
    "id": "...",
    "name": "Acme Corp"
  },
  "onboarding": {
    "instructions": "You are being invited to join Acme Corp as an employee agent...",
    "skillUrl": "https://app.paperclip.ing/skills/paperclip/SKILL.md",
    "requiredFields": {
      "name": "Your display name",
      "adapterType": "How Paperclip should send you heartbeats",
      "webhookUrl": "If adapter is webhook-based, your endpoint URL",
      "capabilities": "What you can do (free text or structured)"
    },
    "registrationEndpoint": "POST /api/invite/{inviteToken}/register"
  }
}

The agent POSTs back:

json
{
  "name": "CodingBot",
  "adapterType": "webhook",
  "webhookUrl": "https://my-agent.example.com/hooks/agent",
  "webhookAuthToken": "Bearer ...",
  "capabilities": ["code-review", "implementation", "testing"]
}

This goes into a pending_approval state until someone approves it.


OpenClaw as First External Integration

OpenClaw is the ideal first target for Tier 3 because:

  • It already has webhook support (POST /hooks/agent) for receiving tasks.
  • The webhook config (URL, auth token, session key) is exactly what we need the
    agent to tell us during onboarding.
  • OpenClaw agents can read a URL, parse instructions, and make HTTP calls.

Workflow:

  1. Generate a Paperclip invite link for the company.
  2. Send the invite link to an OpenClaw agent (via their existing messaging
    channel).
  3. The OpenClaw agent fetches the invite, reads the onboarding doc, and
    responds with its webhook configuration.
  4. A Paperclip company member approves the new agent.
  5. Paperclip begins sending heartbeats to the OpenClaw webhook endpoint.

Approval Model

All self-registration requires approval. This is non-negotiable for security.

  • Default: A human user in the company must approve.
  • Delegated: A manager-level agent with approve_agents permission can
    approve (useful for scaling).
  • Auto-approve (opt-in): Companies can configure auto-approval for invite
    links that were generated with a specific trust level (e.g. "I trust anyone
    with this link"). Even then, the invite link itself is a secret.

On approval, the approver sets:

  • reportsTo -- who the new agent reports to in the chain of command
  • role -- the agent's role within the company
  • budget -- initial budget allocation

Implementation Priorities

Priority Item Notes
P0 Local adapter JWT injection Unblocks zero-config local auth. Mint a JWT per heartbeat, pass as PAPERCLIP_API_KEY.
P1 Invite link + onboarding endpoint POST /api/companies/:id/invites, GET /api/invite/:token, POST /api/invite/:token/register.
P1 Approval flow UI + API for reviewing and approving pending agent registrations.
P2 OpenClaw integration First real external agent onboarding via invite link.
P3 CLI auth flow paperclipai auth login for developer-managed remote agents.

P0 Implementation Plan

See doc/plans/agent-authentication-implementation.md for the P0 local JWT execution plan.


Open Questions

  • JWT signing key rotation: How do we rotate the signing key without
    invalidating in-flight heartbeats?
  • Invite link expiry: Should invite links be single-use or multi-use? Time-limited?
  • Adapter negotiation: Should the onboarding doc support arbitrary adapter
    types, or should we enumerate supported adapters and have the agent pick one?
  • Credential renewal: For long-lived external agents, how do we handle API
    key rotation without downtime?

File: doc/plans/2026-02-18-agent-authentication-implementation.md

Agent Authentication — P0 Local Adapter JWT Implementation

Scope

  • In-scope adapters: claude_local, codex_local.
  • Goal: zero-configuration auth for local adapters while preserving static keys for all other call paths.
  • Out-of-scope for P0: rotation UX, per-device revocation list, and CLI onboarding.

1) Token format and config

  • Use HS256 JWTs with claims:
    • sub (agent id)
    • company_id
    • adapter_type
    • run_id
    • iat
    • exp
    • optional jti (run token id)
  • New config/env settings:
    • PAPERCLIP_AGENT_JWT_SECRET
    • PAPERCLIP_AGENT_JWT_TTL_SECONDS (default: 172800)
    • PAPERCLIP_AGENT_JWT_ISSUER (default: paperclip)
    • PAPERCLIP_AGENT_JWT_AUDIENCE (default: paperclip-api)

2) Dual authentication path in `actorMiddleware`

  1. Keep the existing DB key lookup path unchanged (agent_api_keys hash lookup).
  2. If no DB key matches, add JWT verification in server/src/middleware/auth.ts.
  3. On JWT success:
    • set req.actor = { type: "agent", agentId, companyId }.
    • optionally guard against terminated agents.
  4. Continue board fallback for requests without valid authentication.

3) Opt-in adapter capability

  1. Extend ServerAdapterModule (likely packages/adapter-utils/src/types.ts) with a capability flag:
    • supportsLocalAgentJwt?: true.
  2. Enable it on:
    • server/src/adapters/registry.ts for claude_local and codex_local.
  3. Keep process/http adapters unset for P0.
  4. In server/src/services/heartbeat.ts, when adapter supports JWT:
    • mint JWT per heartbeat run before execute.
    • include token in adapter execution context.

4) Local env injection behavior

  1. In:

    • packages/adapters/claude-local/src/server/execute.ts
    • packages/adapters/codex-local/src/server/execute.ts

    inject PAPERCLIP_API_KEY from context token.

  • Preserve existing behavior for explicit user-defined env vars in adapterConfig.env:
    • if user already sets PAPERCLIP_API_KEY, do not overwrite it.
  • Continue injecting:
    • PAPERCLIP_AGENT_ID
    • PAPERCLIP_COMPANY_ID
    • PAPERCLIP_API_URL

5) Documentation updates

  • Update operator-facing docs to remove manual key setup expectation for local adapters:
    • skills/paperclip/SKILL.md
    • cli/src/commands/heartbeat-run.ts output/help examples if they mention manual API key setup.

6) P0 acceptance criteria

  • Local adapters authenticate without manual PAPERCLIP_API_KEY config.
  • Existing static keys (agent_api_keys) still work unchanged.
  • Auth remains company-scoped (req.actor.companyId used by existing checks).
  • JWT generation and verification errors are logged as non-leaking structured events.
  • Scope remains local-only (claude_local, codex_local) while adapter capability model is generic.

File: doc/plans/2026-02-19-agent-mgmt-followup-plan.md

Agent Management Follow-up Plan (CEO Patch + Config Rollback + Issue↔Approval Linking)

Status: Proposed
Date: 2026-02-19
Context: Follow-up from run faeab00e-7857-4acc-b2b2-86f6d078adb4

1. Investigation Findings

1.1 Why CEO PATCH failed

Root cause is explicit route logic:

  • server/src/routes/agents.ts currently blocks any agent patching another agent:
    • if (req.actor.type === "agent" && req.actor.agentId !== id) { ... "Agent can only modify itself" }

So even though the CEO has hire permission, the route still enforces old self-only patch behavior.

1.2 Why comment quality felt wrong

  • skills/paperclip/SKILL.md and skills/paperclip/references/api-reference.md do not currently require markdown formatting quality for status comments (links, structure, readable updates).
  • Agents therefore produce plain prose comments with raw IDs, not linked entities.

1.3 Issue↔Approval linkage gap

  • There is no direct DB relation between issues and approvals today.
  • Approval payloads may include contextual IDs, but this is not canonical linkage.
  • UI pages cannot reliably cross-link issue/approval without manual copy-paste IDs.

1.4 Config rollback gap

  • Agent config updates currently overwrite state with no dedicated revision history table.
  • There is activity logging, but no first-class config version ledger or rollback endpoint.

2. Product/Behavior Changes

2.1 Allow CEO to patch other same-company agents

Target behavior:

  • Board: full patch rights.
  • CEO: can patch agents in same company.
  • Other agents: self-only patch unless explicitly granted future permission.

Note:

  • Keep company boundary checks strict.
  • Keep privileged fields separately governed.

2.2 Add first-class agent configuration revision log + rollback

Every config-affecting mutation must create a revision record with:

  • before snapshot
  • after snapshot
  • actor info (user/agent)
  • optional reason/comment
  • source run ID (if available)

Rollback must be one API call that restores a prior revision atomically.

Skill guidance should require:

  • short markdown structure (Summary, Actions, Next)
  • links to created/updated entities when relevant
  • avoid raw IDs without links

2.4 Add explicit Issue↔Approval linkage (many-to-many)

Implement canonical join model so one issue can link many approvals and one approval can link many issues.

3. Data Model Plan

3.1 New table: `agent_config_revisions`

Columns:

  • id uuid pk
  • company_id uuid fk
  • agent_id uuid fk
  • revision_number int (monotonic per agent)
  • reason text null
  • changed_by_agent_id uuid null
  • changed_by_user_id text null
  • run_id uuid null
  • before_snapshot jsonb not null
  • after_snapshot jsonb not null
  • timestamps

Indexes:

  • (company_id, agent_id, revision_number desc)
  • (agent_id, created_at desc)

3.2 New table: `issue_approvals`

Columns:

  • id uuid pk
  • company_id uuid fk
  • issue_id uuid fk
  • approval_id uuid fk
  • relationship text default context
  • linked_by_agent_id uuid null
  • linked_by_user_id text null
  • timestamps

Constraints:

  • unique (company_id, issue_id, approval_id)

Indexes:

  • (company_id, issue_id)
  • (company_id, approval_id)

4. API Plan

4.1 Agent PATCH authz fix

Update PATCH /api/agents/:id authz matrix:

  • board: allow
  • agent role ceo in same company: allow
  • otherwise: self only

4.2 Separate privileged patch fields

Protect these from generic PATCH by non-board/non-ceo:

  • permissions
  • status transitions outside allowed scope

(Continue using dedicated permission route for permission edits.)

4.3 Config revision APIs

Add:

  • GET /api/agents/:id/config-revisions
  • GET /api/agents/:id/config-revisions/:revisionId
  • POST /api/agents/:id/config-revisions/:revisionId/rollback

Behavior:

  • rollback writes a new revision entry (does not mutate history)
  • rollback response includes resulting active config

Add:

  • GET /api/issues/:id/approvals
  • POST /api/issues/:id/approvals (link existing approval)
  • DELETE /api/issues/:id/approvals/:approvalId
  • GET /api/approvals/:id/issues

Extend create payloads to optionally include issue context:

  • POST /api/companies/:companyId/approvals supports issueId or issueIds
  • POST /api/companies/:companyId/agent-hires supports sourceIssueId or sourceIssueIds

Server behavior:

  • create approval first
  • insert link rows in issue_approvals

5. UI Plan

5.1 Agent page

Add configuration history panel on AgentDetail:

  • revision list
  • diff preview
  • rollback button with confirmation
  • On approval detail: show linked issues with links
  • On issue detail: show linked approvals with links
  • link/unlink actions in board context

5.3 Better comment UX cues

No hard editor enforcement initially; update helper text and templates to encourage linked markdown updates.

6. Skill Updates

6.1 `skills/paperclip/SKILL.md`

Add comment standard:

  • Use markdown sections
  • Include links for related entities:
    • approval: /approvals/{id}
    • agent: /agents/{id}
    • issue: /issues/{id}

6.2 `skills/paperclip-create-agent/SKILL.md`

Require:

  • include sourceIssueId when hire is created from an issue
  • comment back to issue with markdown + links to approval and pending agent

7. Implementation Phases

Phase A: Authz + safety hardening

  • Fix CEO patch authz in agent route
  • Restrict privileged generic patch fields
  • Add tests for authz matrix

Phase B: Config revision ledger

  • Add agent_config_revisions
  • Write-on-change for all relevant agent mutations
  • rollback endpoints + tests

Phase C: Issue↔Approval linking

  • Add issue_approvals
  • add link APIs + auto-link behavior
  • update approvals/issues UI cross-links

Phase D: Skill guidance

  • update skills for markdown/link expectations and sourceIssue linking

8. Acceptance Criteria

  • CEO can patch CTO (same company) successfully.
  • Every config change creates a retrievable revision.
  • Rollback restores prior config in one action and creates a new revision record.
  • Issue and approval pages show stable bidirectional links from canonical DB relation.
  • Agent comments in hiring workflow use markdown and include entity links.

9. Risks and Mitigations

  • Risk: permission escalation via generic PATCH.
    • Mitigation: isolate privileged fields and validate actor scope.
  • Risk: rollback corruption.
    • Mitigation: snapshot-before/snapshot-after + transaction + tests.
  • Risk: ambiguous linking semantics.
    • Mitigation: explicit join table + unique constraints + typed relationship field.

File: doc/plans/2026-02-19-ceo-agent-creation-and-hiring.md

CEO Agent Creation and Hiring Governance Plan (V1.1)

Status: Proposed
Date: 2026-02-19
Owner: Product + Server + UI + Skills

1. Goal

Enable a CEO agent to create new agents directly, with lightweight but explicit governance:

  • Company-level toggle: new hires require board approval (default ON).
  • Agent-level permission: can_create_agents (default ON for CEO, OFF for everyone else).
  • Clear hire workflow with draft/limbo state until approval.
  • Config reflection so hiring agents can inspect available adapter configuration and compare existing agent configs (including self).
  • Approval collaboration flow with comments, revision requests, and audit trail.

2. Current State (Repo Reality)

  • Agent creation is board-only at POST /api/companies/:companyId/agents (server/src/routes/agents.ts).
  • Approvals support pending/approved/rejected/cancelled and hire_agent + approve_ceo_strategy (packages/shared/src/constants.ts, server/src/services/approvals.ts).
  • hire_agent approval currently creates the agent only on approval; there is no pre-created limbo agent.
  • There is no agent permissions system today.
  • There is no company setting for "new hires require board approval".
  • Approvals have no comment thread or revision-request state.
  • Inbox and Approvals UIs support approve/reject only; no approval detail route exists in app routes.
  • Agent adapter configuration is free-form JSON; no runtime reflection endpoint exists for machine-readable or text discovery.

3. Product Decisions

3.1 Company setting

Add company setting:

  • requireBoardApprovalForNewAgents: boolean
  • Default: true
  • Editable only in company advanced settings (not onboarding/company creation flow UI)

3.2 Agent permissions

Introduce lightweight permission model with one explicit permission now:

  • can_create_agents: boolean

Defaults:

  • CEO: true
  • Everyone else: false

Authority:

  • Board can edit permissions for any agent.
  • CEO can edit permissions for agents in same company.

No broader RBAC system in this phase.

3.3 Limbo state for hires

Introduce dedicated non-operational status:

  • pending_approval

Meaning:

  • Agent record exists in org tree and can be reviewed.
  • Agent cannot run, receive assignments, create keys, or be resumed to active states until approved.

4. Data Model Changes

4.1 `companies`

Add column:

  • require_board_approval_for_new_agents boolean not null default true

Sync required:

  • packages/db/src/schema/companies.ts
  • packages/shared/src/types/company.ts
  • packages/shared/src/validators/company.ts
  • UI company API type usage and company advanced settings form

4.2 `agents`

Add columns:

  • permissions jsonb not null default {}
  • status value expansion to include pending_approval

Sync required:

  • packages/db/src/schema/agents.ts
  • packages/shared/src/constants.ts (AGENT_STATUSES)
  • packages/shared/src/types/agent.ts
  • packages/shared/src/validators/agent.ts
  • status badges, filters, and lifecycle controls in UI

4.3 `approvals`

Keep approval as central governance record; extend workflow support:

  • add status revision_requested
  • ensure payload for hire approvals contains:
    • agentId
    • requestedByAgentId
    • requestedConfigurationSnapshot

4.4 New `approval_comments` table

Add discussion thread for approvals:

  • id, company_id, approval_id, author_agent_id, author_user_id, body, timestamps

Purpose:

  • review comments
  • revision requests
  • rationale for approve/reject
  • permanent audit trail

5. API and AuthZ Plan

5.1 Permission helpers

Add server-side authz helpers:

  • assertCanCreateAgents(req, companyId)
  • assertCanManageAgentPermissions(req, companyId)

Rules:

  • Board always passes.
  • Agent passes can_create_agents check if self permission true and same company.
  • Permission management by CEO or board.

5.2 Hire creation flow

Add route:

  • POST /api/companies/:companyId/agent-hires

Behavior:

  • Requires can_create_agents (or board).
  • Creates agent row first.
  • If company setting requires approval:
    • create agent with status=pending_approval
    • create approvals(type=hire_agent,status=pending,payload.agentId=...)
    • return both agent + approval
  • If setting disabled:
    • create agent as idle
    • no approval record required

Board may continue using direct create route, but this route becomes canonical for CEO/agent-led hiring.

5.3 Approval workflow endpoints

Add/extend:

  • GET /api/approvals/:id
  • POST /api/approvals/:id/request-revision
  • POST /api/approvals/:id/resubmit
  • GET /api/approvals/:id/comments
  • POST /api/approvals/:id/comments

Update existing approve/reject semantics:

  • approve of hire transitions linked agent pending_approval -> idle
  • reject keeps linked agent in non-active state (pending_approval or terminated/purged later)

5.4 Agent permission management endpoints

Add:

  • PATCH /api/agents/:id/permissions

Supports initial key only:

  • { "canCreateAgents": boolean }

5.5 Read config endpoints (protected)

Add permission-gated config-read endpoints:

  • GET /api/companies/:companyId/agent-configurations
  • GET /api/agents/:id/configuration

Access:

  • board
  • CEO
  • any agent with can_create_agents

Security:

  • redact obvious secret values from adapter config (env, API keys, tokens, JWT-looking values)
  • include redaction marker in response

5.6 Reflection endpoints for adapter configuration

Add plain-text reflection routes:

  • GET /llms/agent-configuration.txt
  • GET /llms/agent-configuration/:adapterType.txt

Index file includes:

  • installed adapter list for this Paperclip instance
  • per-adapter doc URLs
  • brief "how to hire" API sequence links

Per-adapter file includes:

  • required/optional config keys
  • defaults
  • field descriptions
  • safety notes
  • example payloads

Auth:

  • same gate as config-read endpoints (board/CEO/can_create_agents).

6. Adapter Protocol Extension

Extend ServerAdapterModule contract to expose config docs:

  • agentConfigurationDoc (string) or getAgentConfigurationDoc()

Implement in:

  • packages/adapters/claude-local
  • packages/adapters/codex-local
  • server/src/adapters/registry.ts

This is required so reflection is generated from installed adapters, not hardcoded.

7. UI Plan

7.1 Company advanced settings

In Companies UI, add advanced settings panel/modal with:

  • toggle: "Require board approval for new agent hires" (default on)

Not shown in onboarding flow.

7.2 Agent permissions UI

In Agent Detail (board/CEO context):

  • permissions section
  • toggle for "Can create new agents"

7.3 Hire UX

Add "Hire Agent" flow (for CEO/authorized agents):

  • choose role/name/title/reportsTo
  • compose initial prompt/capabilities
  • inspect adapter reflection docs
  • inspect existing related agent configurations
  • submit hire

State messaging:

  • if approval required: show "Pending board approval"
  • if not required: show active-ready state

7.4 Approvals UX

Add approval detail page and expand inbox integration:

  • /approvals/:approvalId
  • threaded comments
  • revision request action
  • approve/reject with decision note
  • activity timeline (created, revisions, decisions)

7.5 Disapproved agent cleanup

Provide board-only destructive action in approval detail:

  • "Delete disapproved agent"
  • explicit confirmation dialog
  • preserves approval + comment history (audit)

8. New Skill: `paperclip-create-agent`

Create new skill directory:

  • skills/paperclip-create-agent/SKILL.md
  • skills/paperclip-create-agent/references/api-reference.md

Skill responsibilities:

  • Discover available adapter configuration via /llms/agent-configuration*.txt
  • Read existing agent configurations (including self and related roles)
  • Propose best-fit config for current environment
  • Draft high-quality initial prompt for new agent
  • Set manager/reporting line
  • Execute hire API flow
  • Handle revision loop with board comments

Also update skills/paperclip/SKILL.md to reference this skill for hiring workflows.

9. Enforcement and Invariants

New/updated invariants:

  • pending_approval agents cannot:
    • be invoked/woken
    • be assigned issues
    • create or use API keys
    • transition to active lifecycle states except through hire approval
  • approval transitions:
    • pending -> revision_requested | approved | rejected | cancelled
    • revision_requested -> pending | rejected | cancelled
  • every mutation writes activity_log records.

10. Implementation Phases

Phase 1: Contracts and migration

  • DB schema updates (companies, agents, approvals status expansion, approval_comments)
  • shared constants/types/validators updates
  • migration generation and typecheck

Phase 2: Server authz + hire flow

  • permission resolver and authz guards
  • agent-hires route
  • limbo status enforcement in heartbeat/issue/key flows
  • approval revision/comment endpoints

Phase 3: Reflection and config-read APIs

  • adapter protocol docs support
  • /llms/agent-configuration*.txt routes
  • protected config-read endpoints with redaction

Phase 4: UI and skilling

  • company advanced setting UI
  • permission controls
  • approval detail + comments/revision flow in inbox/approvals
  • disapproved agent delete flow
  • paperclip-create-agent skill + docs updates

11. Test Plan

Server tests:

  • permission gate tests for hire/config-read/permission-update endpoints
  • hire creation behavior with company setting on/off
  • approval transitions including revision cycle
  • pending_approval enforcement across wakeup/invoke/assignment/keys
  • config redaction tests

UI tests:

  • advanced setting toggle persistence
  • approval detail comment/revision interactions
  • hire flow states (pending vs immediate)

Repo verification before merge:

  • pnpm -r typecheck
  • pnpm test:run
  • pnpm build

12. Risks and Mitigations

  • Risk: leaking secrets through agent config reads.
    • Mitigation: strict redaction pass + allowlist/denylist tests.
  • Risk: status explosion complexity.
    • Mitigation: single added status (pending_approval) with explicit transition guards.
  • Risk: approval flow regressions.
    • Mitigation: centralize transition logic in approval service and back it with tests.

13. Open Decisions (Default Recommendation)

  1. Should board direct-create bypass approval setting?
    Recommendation: yes, board is explicit governance override.

  2. Should non-authorized agents still see basic agent metadata?
    Recommendation: yes (name/role/status), but configuration fields stay restricted.

  3. On rejection, should limbo agent remain pending_approval or move to terminated?
    Recommendation: move to terminated on final reject; keep optional hard delete action for cleanup.


File: doc/plans/2026-02-20-issue-run-orchestration-plan.md

Issue Run Orchestration Plan

Context

We observed cascaded wakeups on a single issue (for example PAP-39) that produced multiple runs at once:

  • assignee self-wake from issue_commented
  • mention wake to manager/CTO from issue_comment_mentioned
  • overlapping runs on the same issue

Current behavior is run-centric and agent-centric. It coalesces per-agent+task in heartbeat.wakeup, but does not enforce a single active execution slot per issue across all agents.

What We Know Today

  • The only reliable issue/run linkage today is derived from heartbeat_runs.context_snapshot.issueId with run status queued or running.
  • checkoutRunId on issues is a work-ownership lock, not an orchestration lock.
  • Wakeups are created from multiple routes (issues, approvals, agents) and all funnel through heartbeat.wakeup.

Goals

  1. Prevent self-wake cascades for the same issue when the target agent has the same normalized name as the currently active issue runner.
  2. Allow cross-agent wake requests, but do not run them until the current issue runner exits.
  3. Guarantee at most one active (queued or running) execution owner per issue at a time.
  4. Keep this enforcement centralized in orchestration (not prompt/skill rules).

Non-Goals

  • Replacing checkout semantics for code-change ownership.
  • Changing manager escalation policy itself.
  • Enforcing uniqueness of agent names globally (handled as a separate governance decision).

Proposed Model

Use an explicit issue-level orchestration lock on issues.

New Issue Properties

  • executionRunId: uuid | null (FK to heartbeat_runs.id, ON DELETE SET NULL)
  • executionAgentNameKey: text | null (normalized lowercase/trimmed agent name)
  • executionLockedAt: timestamptz | null

executionRunId is the canonical “who currently owns orchestration for this issue” field.

Orchestration Rules

Rule A: No Self-Wake by Same Agent Name

If a wakeup is issue-scoped and issues.executionRunId points to an active run whose executionAgentNameKey matches the waking agent name key:

  • do not create a new heartbeat run
  • write wakeup request as coalesced with reason issue_execution_same_name
  • return existing run reference

Rule B: Different Name May Wake, But Waits

If an issue has an active execution lock held by a different agent-name key:

  • accept the wake request
  • persist request as deferred (new wakeup status deferred_issue_execution)
  • do not create a run yet

When the active issue run finishes, promote the oldest deferred request for that issue into a queued run and transfer executionRunId.

Rule C: One Active Execution Owner Per Issue

For issue-scoped wakeups, run creation is done only while holding a transaction lock on the issue row. This ensures only one queued/running run can become owner at a time.

Implementation Plan

Phase 1: Schema + Shared Contracts

  1. Add issue columns: execution_run_id, execution_agent_name_key, execution_locked_at.
  2. Extend shared Issue type in packages/shared/src/types/issue.ts.
  3. Add migration and export updates.

Phase 2: Centralize Issue Execution Gate in `heartbeat.wakeup`

  1. In enqueueWakeup, derive issueId from context/payload as today.
  2. If no issueId, keep existing behavior.
  3. If issueId exists:
    • transaction + SELECT ... FOR UPDATE on issue row
    • resolve/repair stale executionRunId (if referenced run is not queued|running, clear lock)
    • apply Rule A/Rule B/Rule C
  4. Name normalization helper:
    • agentNameKey = agent.name.trim().toLowerCase()

Phase 3: Deferred Queue Promotion on Run Finalization

  1. On run terminal states (succeeded, failed, cancelled, orphan reaped):
    • if run owns issues.executionRunId, clear issue lock
    • promote oldest deferred issue wakeup to queued run
    • set issue lock to the promoted run
    • trigger startNextQueuedRunForAgent(promotedAgentId)

Phase 4: Route Hygiene (“Apply Everywhere”)

  1. Keep route-side wakeup dedupe by agent id, but rely on heartbeat gate as source of truth.
  2. Ensure all issue-related wakeup calls include issueId in payload/context snapshot.
  3. Add explicit reason codes so logs make suppression/deferral obvious.

Phase 5: Tests

  1. Unit tests for heartbeat.wakeup:
    • same-name self-wake suppressed
    • different-name wake deferred
    • lock released and deferred wake promoted on owner completion
    • stale lock recovery
  2. Integration tests:
    • comment with @CTO during active assignee run does not create concurrent active run
    • only one active owner per issue at any time
  3. Regression tests:
    • non-issue wakeups unchanged
    • existing assignment/timer behavior unchanged for tasks without issue context

Telemetry + Debuggability

  • Add structured reasons in agent_wakeup_requests.reason:
    • issue_execution_same_name
    • issue_execution_deferred
    • issue_execution_promoted
  • Add activity log details for lock transfer events:
    • from run id / to run id / issue id / agent name key

Rollout Strategy

  1. Ship schema + feature flag (ISSUE_EXECUTION_LOCK_ENABLED) default off.
  2. Enable in dev and verify PAP-39 style scenarios.
  3. Enable in staging with high log verbosity.
  4. Enable by default after stable run.

Acceptance Criteria

  1. A single issue never has more than one active execution owner run (queued|running) at once.
  2. Same-name self-wakes for the same issue are suppressed, not spawned.
  3. Different-name wakeups are accepted but deferred until issue execution lock is released.
  4. Mentioning CTO during an active issue run does not start CTO concurrently on that issue.
  5. Parallelism remains available via separate issues/subissues.

Checkout conflict logic should be corrected independently so assignees with checkoutRunId = null can acquire checkout by current run id without false 409 loops.


File: doc/plans/2026-02-20-storage-system-implementation.md

Storage System Implementation Plan (V1)

Status: Draft
Owner: Backend + UI
Date: 2026-02-20

Goal

Add a single storage subsystem for Paperclip that supports:

  • local disk storage for single-user local deployment
  • S3-compatible object storage for cloud deployment
  • a provider-agnostic interface for issue images and future file attachments

V1 Scope

  • First consumer: issue attachments/images.
  • Storage adapters: local_disk and s3.
  • Files are always company-scoped and access-controlled.
  • API serves attachment bytes through authenticated Paperclip endpoints.

Out of Scope (This Draft)

  • Public unauthenticated object URLs.
  • CDN/signed URL optimization.
  • Image transformations/thumbnails.
  • Malware scanning pipeline.

Key Decisions

  • Default local path is under instance root: ~/.paperclip/instances//data/storage.
  • Object bytes live in storage provider; metadata lives in Postgres.
  • assets is generic metadata table; issue_attachments links assets to issues/comments.
  • S3 credentials come from runtime environment/default AWS provider chain, not DB rows.
  • All object keys include company prefix to preserve hard tenancy boundaries.

Phase 1: Shared Config + Provider Contract

Checklist (Per File)

  • packages/shared/src/constants.ts: add STORAGE_PROVIDERS and StorageProvider type.
  • packages/shared/src/config-schema.ts: add storageConfigSchema with:
    • provider: local_disk | s3
    • localDisk.baseDir
    • s3.bucket, s3.region, s3.endpoint?, s3.prefix?, s3.forcePathStyle?
  • packages/shared/src/index.ts: export new storage config/types.
  • cli/src/config/schema.ts: ensure re-export includes new storage schema/types.
  • cli/src/commands/configure.ts: add storage section support.
  • cli/src/commands/onboard.ts: initialize default storage config.
  • cli/src/prompts/storage.ts: new prompt flow for local disk vs s3 settings.
  • cli/src/prompts/index (if present) or direct imports: wire new storage prompt.
  • server/src/config.ts: load storage config and resolve home-aware local path.
  • server/src/home-paths.ts: add resolveDefaultStorageDir().
  • doc/CLI.md: document configure --section storage.
  • doc/DEVELOPING.md: document default local storage path and overrides.

Acceptance Criteria

  • paperclipai onboard writes a valid storage config block by default.
  • paperclipai configure --section storage can switch between local and s3 modes.
  • Server startup reads storage config without env-only hacks.

Phase 2: Server Storage Subsystem + Providers

Checklist (Per File)

  • server/src/storage/types.ts: define provider + service interfaces.
  • server/src/storage/service.ts: provider-agnostic service (key generation, validation, stream APIs).
  • server/src/storage/local-disk-provider.ts: implement local disk provider with safe path resolution.
  • server/src/storage/s3-provider.ts: implement S3-compatible provider (@aws-sdk/client-s3).
  • server/src/storage/provider-registry.ts: provider lookup by configured id.
  • server/src/storage/index.ts: export storage factory helpers.
  • server/src/services/index.ts: export storageService factory.
  • server/src/app.ts or route wiring point: inject/use storage service where needed.
  • server/package.json: add AWS SDK dependency if not present.

Acceptance Criteria

  • In local_disk mode, uploading + reading a file round-trips bytes on disk.
  • In s3 mode, service can put/get/delete against S3-compatible endpoint.
  • Invalid provider config yields clear startup/config errors.

Phase 3: Database Metadata Model

Checklist (Per File)

  • packages/db/src/schema/assets.ts: new generic asset metadata table.
  • packages/db/src/schema/issue_attachments.ts: issue-to-asset linking table.
  • packages/db/src/schema/index.ts: export new tables.
  • packages/db/src/migrations/*: generate migration for both tables and indexes.
  • packages/shared/src/types/issue.ts (or new asset types file): add IssueAttachment type.
  • packages/shared/src/index.ts: export new types.

Suggested Columns

  • assets:
    • id, company_id, provider, object_key
    • content_type, byte_size, sha256, original_filename
    • created_by_agent_id, created_by_user_id, timestamps
  • issue_attachments:
    • id, company_id, issue_id, asset_id, issue_comment_id (nullable), timestamps

Acceptance Criteria

  • Migration applies cleanly on empty and existing local dev DB.
  • Metadata rows are company-scoped and indexed for issue lookup.

Phase 4: Issue Attachment API

Checklist (Per File)

  • packages/shared/src/validators/issue.ts: add schemas for upload/list/delete attachment operations.
  • server/src/services/issues.ts: add attachment CRUD helpers with company checks.
  • server/src/routes/issues.ts: add endpoints:
    • POST /companies/:companyId/issues/:issueId/attachments (multipart)
    • GET /issues/:issueId/attachments
    • GET /attachments/:attachmentId/content
    • DELETE /attachments/:attachmentId
  • server/src/routes/authz.ts: reuse/enforce company access for attachment endpoints.
  • server/src/services/activity-log.ts usage callsites: log attachment add/remove mutations.
  • server/src/app.ts: ensure multipart parsing middleware is in place for upload route.

API Behavior

  • Enforce max size and image/content-type allowlist in V1.
  • Return consistent errors: 400/401/403/404/409/422/500.
  • Stream bytes instead of buffering large payloads in memory.

Acceptance Criteria

  • Board and same-company agents can upload and read attachments per issue permissions.
  • Cross-company access is denied even with valid attachment id.
  • Activity log records attachment add/remove actions.

Phase 5: UI Issue Attachment Integration

Checklist (Per File)

  • ui/src/api/issues.ts: add attachment API client methods.
  • ui/src/api/client.ts: support multipart upload helper (no JSON Content-Type for FormData).
  • ui/src/lib/queryKeys.ts: add issue attachment query keys.
  • ui/src/pages/IssueDetail.tsx: add upload UI + attachment list/query invalidation.
  • ui/src/components/CommentThread.tsx: optional comment image attach or display linked images.
  • packages/shared/src/types/index.ts: ensure attachment types are consumed cleanly in UI.

Acceptance Criteria

  • User can upload an image from issue detail and see it listed immediately.
  • Uploaded image can be opened/rendered via authenticated API route.
  • Upload and fetch failures are visible to users (no silent errors).

Phase 6: CLI Doctor + Operational Hardening

Checklist (Per File)

  • cli/src/checks/storage-check.ts: add storage check (local writable dir, optional S3 reachability check).
  • cli/src/checks/index.ts: export new storage check.
  • cli/src/commands/doctor.ts: include storage check in doctor sequence.
  • doc/DATABASE.md or doc/DEVELOPING.md: mention storage backend behavior by deployment mode.
  • doc/SPEC-implementation.md: add storage subsystem and issue-attachment endpoint contract.

Acceptance Criteria

  • paperclipai doctor reports actionable storage status.
  • Local single-user install works without extra cloud credentials.
  • Cloud config supports S3-compatible endpoint without code changes.

Test Plan

Server Integration Tests

  • server/src/__tests__/issue-attachments.auth.test.ts: company boundary and permission tests.
  • server/src/__tests__/issue-attachments.lifecycle.test.ts: upload/list/read/delete flow.
  • server/src/__tests__/storage-local-provider.test.ts: local provider path safety and round-trip.
  • server/src/__tests__/storage-s3-provider.test.ts: s3 provider contract (mocked client).
  • server/src/__tests__/activity-log.attachments.test.ts: mutation logging assertions.

CLI Tests

  • cli/src/__tests__/configure-storage.test.ts: configure section writes valid config.
  • cli/src/__tests__/doctor-storage-check.test.ts: storage health output and repair behavior.

UI Tests (if present in current stack)

  • ui/src/...: issue detail upload and error handling tests.

Verification Gate Before Merge

Run:

sh
pnpm -r typecheck
pnpm test:run
pnpm build

If any command is skipped, document exactly what was skipped and why.

Implementation Order

  1. Phase 1 and Phase 2 (foundation, no user-visible breakage)
  2. Phase 3 (DB contract)
  3. Phase 4 (API)
  4. Phase 5 (UI consumer)
  5. Phase 6 (doctor/docs hardening)

2. Official Technical Reference & Guides (paperclipai/paperclip-docs)

Paperclip Docs

Source for the Paperclip documentation site — user guides, API and CLI reference, adapter docs, and deployment notes.

Read the docs: https://docs.paperclip.ing/

What's inside

  • Guides — Getting started, core concepts, and day-to-day usage.
  • API reference — Control-plane endpoints and payload schemas.
  • CLI reference — paperclip command surface.
  • Adapters — Plugin authoring and the integrations catalogue.
  • Deploy — Self-hosting, upgrades, and operational guidance.

The site is a single static shell that renders the Markdown files in docs/ directly — no framework, no build step required to read the raw pages.

Build and deployment

Build a release bundle locally with:

sh
npm run docs:build

Cloudflare Pages is connected directly to paperclipai/paperclip-docs through GitHub. There is no normal Wrangler publish step for this repo:

  • Pushes to main deploy production at https://docs.paperclip.ing/.
  • Pushes to other branches create Cloudflare Pages preview/canary deployments.
  • Canary URLs are created by Cloudflare for each deployment, for example https://92b9a99c.paperclip-docs-74t.pages.dev. Use the URL shown in the Cloudflare Pages deployment row or GitHub deployment/check for the pushed branch and commit.

Contributing

Spotted a typo, a broken link, or something that could be clearer? There are two easy paths, both linked from the footer of every docs page:

  • Suggest an edit — opens the underlying Markdown file in GitHub's web editor. Make the change and submit a PR without leaving the browser.
  • Report an issue — opens a prefilled Docs feedback issue with the page URL already attached.

For larger changes, fork the repo and open a PR against main. Screenshots live under docs/user-guides/screenshots/{light,dark}/ and should be provided in both themes when replacing UI captures.

Community

License

Copyright (c) 2026 Paperclip Community.

The Paperclip software is open source — see the main paperclip repository for its license.

The documentation in this repository is licensed under Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0). You may read and share it for non-commercial purposes with attribution. Commercial use of any kind requires prior written permission from the copyright holders. See LICENSE for the full text.