What it does
Paperclip is a Node.js server and React UI that orchestrates multiple AI agents — Claude Code, Codex, Cursor, Gemini, OpenClaw — into something that resembles a company. You define goals, hire agents into roles, set budgets, and let them work autonomously. It ships with an embedded PostgreSQL database, so npx paperclipai onboard --yes gets you running with zero setup.
Why I starred it
I run 5-10 Claude Code sessions concurrently for different tasks. Keeping track of who's doing what, which session is stuck, and how much I'm burning on API calls is a real problem. Paperclip doesn't just solve the "too many terminal tabs" issue — it models the coordination layer that you'd otherwise build ad-hoc with scripts and spreadsheets. The fact that it treats agents as employees with reporting lines and budget caps instead of just "processes to spawn" is what caught my eye.
How it works
The architecture is a pnpm monorepo with four main pieces: server/ (Express API + embedded Postgres), ui/ (React dashboard), cli/ (onboarding and management commands), and packages/ (shared adapters, DB schema, plugin SDK).
The adapter registry
The "bring your own agent" system lives in server/src/adapters/registry.ts. Each adapter — Claude, Codex, Cursor, Gemini, OpenClaw, and more — implements a ServerAdapterModule interface with execute, testEnvironment, listSkills, syncSkills, and an optional sessionCodec. The registry loads all built-in adapters at startup and supports external adapters via the plugin system:
const claudeLocalAdapter: ServerAdapterModule = {
type: "claude_local",
execute: claudeExecute,
testEnvironment: claudeTestEnvironment,
listSkills: listClaudeSkills,
syncSkills: syncClaudeSkills,
sessionCodec: claudeSessionCodec,
sessionManagement: getAdapterSessionManagement("claude_local") ?? undefined,
models: claudeModels,
supportsLocalAgentJwt: true,
agentConfigurationDoc: claudeAgentConfigurationDoc,
getQuotaWindows: claudeGetQuotaWindows,
};
The sessionCodec is particularly interesting. Agents like Claude Code and Codex maintain local sessions across heartbeats — the codec serializes and restores session state so an agent can pick up where it left off instead of cold-starting every run. The constant SESSIONED_LOCAL_ADAPTERS in server/src/services/heartbeat.ts tracks which adapters support this.
Heartbeat scheduler
This is the engine room. The heartbeat service in server/src/services/heartbeat.ts wakes agents on a configurable interval. Each tick calls tickTimers() which checks every agent's schedule, enqueues runs for those that are due, and respects concurrency limits — HEARTBEAT_MAX_CONCURRENT_RUNS_DEFAULT is 1, capped at 10. Agents don't poll. They get woken up, check their assigned issues, do work, and go back to sleep.
The run lifecycle is atomic. Before an agent starts working, the heartbeat service calls into the budget service to enforce spend limits. The budget system in server/src/services/budgets.ts resolves spending windows (monthly or lifetime) and computes status against thresholds:
function budgetStatusFromObserved(
observedAmount: number,
amount: number,
warnPercent: number,
): BudgetPolicySummary["status"] {
if (amount <= 0) return "ok";
if (observedAmount >= amount) return "hard_stop";
if (observedAmount >= Math.ceil((amount * warnPercent) / 100))
return "warning";
return "ok";
}
When an agent hits hard_stop, it gets paused with pauseReason: "budget". No more heartbeats until someone raises the limit. This is the kind of guardrail you want when agents run 24/7.
Company portability
The export/import system in server/src/services/company-portability.ts is ambitious. You can export an entire company — agents, org charts, projects, skills, routines — into a portable manifest. It scrubs secrets, handles ID collisions on import, and even generates an org chart PNG and README for the export package. The upcoming "Clipmart" feature will let you download pre-built company templates, which makes sense given this infrastructure.
The database layer
The schema in packages/db/src/schema/ has 60+ table definitions. This isn't a toy. You've got agents, heartbeat_runs, heartbeat_run_events, budget_policies, budget_incidents, cost_events, approval_comments, workspace_runtime_services — the full data model of an organization. Drizzle ORM handles migrations, and the embedded Postgres option means you don't need to provision anything for local development.
Plugin system
The plugin architecture is substantial. There's a plugin-loader, plugin-worker-manager, plugin-job-scheduler, plugin-job-coordinator, plugin-event-bus, plugin-tool-dispatcher, plugin-runtime-sandbox, and plugin-state-store — all separate services in server/src/services/. Plugins run in isolated workers, get their own job queues, and communicate through the event bus. The host services layer provides controlled access to the database and other server internals.
Using it
npx paperclipai onboard --yes
This clones the repo, installs dependencies, starts the embedded Postgres, runs migrations, and opens the dashboard at http://localhost:3100. From there you create a company, add agents with their adapter type (Claude, Codex, etc.), assign them to projects, and set heartbeat schedules.
For development:
git clone https://github.com/paperclipai/paperclip.git
cd paperclip
pnpm install
pnpm dev # API + UI with hot reload
pnpm test:run # Vitest suite
pnpm typecheck # TypeScript checks
Rough edges
Test coverage is thin for a project this size. The tests/ directory only contains e2e/ and release-smoke/ — one Playwright spec for onboarding and one for release smoke tests. Unit tests exist scattered across packages (vitest configs in each package), but the server/src/services/ directory — the most critical code — has a single __tests__ folder. For 60+ services handling budget enforcement and agent coordination, that's a gap.
The embedded Postgres approach is clever for onboarding but adds complexity. The startup code in server/src/index.ts is over 400 lines of database initialization, migration handling, stale PID detection, and port negotiation. That's a lot of surface area for edge cases.
Documentation lives at paperclip.ing/docs but the repo's own doc/ folder is sparse. The DEVELOPING.md reference exists but discovering how adapters work or how to write a plugin requires reading the source.
The 48k stars on a repo this young means the community is growing faster than the docs. That usually sorts itself out, but right now, extending Paperclip means reading TypeScript.
Bottom line
If you're running more than a handful of AI agents and you've started building your own coordination scripts, Paperclip replaces that entire layer. The budget enforcement alone is worth it — runaway agent costs are a real problem, and having atomic spend checks before every heartbeat run is the right way to solve it.
