papercliped 2.2.1 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/CHANGELOG.md +20 -0
  3. package/README.md +9 -5
  4. package/dist/access/guard.js +17 -0
  5. package/dist/access/policy.js +203 -0
  6. package/dist/execute.js +25 -1
  7. package/dist/manage/routes.js +46 -2
  8. package/dist/mcp.js +6 -5
  9. package/dist/oauth/pg-store.js +13 -1
  10. package/dist/oauth/provider.js +50 -1
  11. package/dist/oauth/store.js +20 -0
  12. package/dist/public-api/types.js +1 -1
  13. package/dist/server.js +2 -2
  14. package/dist/site/markdown.js +26 -5
  15. package/dist/site/site.js +10 -1
  16. package/docs/CONTROL-ROOM.md +79 -0
  17. package/docs/SECURITY.md +1 -1
  18. package/docs/SITEMAP.md +3 -1
  19. package/docs/supabase-schema.sql +12 -1
  20. package/migrations/007_control_room.sql +9 -0
  21. package/package.json +1 -1
  22. package/site/docs/access-modes.md +72 -0
  23. package/site/docs/connect-your-paperclip.md +139 -93
  24. package/site/docs/control-room.md +61 -0
  25. package/site/docs/faq.md +16 -1
  26. package/site/docs/getting-started.md +2 -2
  27. package/site/docs/host-coolify.md +78 -0
  28. package/site/docs/host-fly.md +129 -0
  29. package/site/docs/host-railway.md +105 -0
  30. package/site/docs/host-render.md +79 -0
  31. package/site/docs/host-vps.md +202 -0
  32. package/site/docs/hosting.md +105 -0
  33. package/site/docs/limits-and-errors.md +1 -0
  34. package/site/docs/manage-api.md +12 -1
  35. package/site/docs/paperclip-plugin.md +21 -10
  36. package/site/docs/permissions.md +8 -0
  37. package/site/docs/prompts.md +349 -0
  38. package/site/docs/public-api.md +1 -1
  39. package/site/docs/signup.md +1 -1
  40. package/site/docs/tools.md +35 -35
  41. package/site/docs/troubleshooting.md +11 -1
package/dist/site/site.js CHANGED
@@ -9,10 +9,19 @@ const NAV = [
9
9
  { slug: "getting-started", title: "Getting started" },
10
10
  { slug: "what-is-papercliped", title: "What is Papercliped?" },
11
11
  { slug: "signup", title: "Create your account" },
12
- { slug: "connect-your-paperclip", title: "Set up your Paperclip" },
12
+ { slug: "hosting", title: "Host your Paperclip" },
13
+ { slug: "connect-your-paperclip", title: "At home, with a tunnel" },
14
+ { slug: "host-vps", title: "VPS with Docker" },
15
+ { slug: "host-railway", title: "Railway" },
16
+ { slug: "host-render", title: "Render" },
17
+ { slug: "host-fly", title: "Fly.io" },
18
+ { slug: "host-coolify", title: "Coolify" },
13
19
  { slug: "other-ai-apps", title: "Any AI app (MCP)" },
14
20
  { slug: "chatgpt", title: "ChatGPT setup" },
21
+ { slug: "prompts", title: "Prompt gallery" },
15
22
  { slug: "permissions", title: "Permissions" },
23
+ { slug: "control-room", title: "The control room" },
24
+ { slug: "access-modes", title: "API only, Full or Agent only" },
16
25
  { slug: "manage", title: "Manage connections" },
17
26
  { slug: "paperclip-plugin", title: "Paperclip plugin" },
18
27
  { slug: "anonymous-mode", title: "Anonymous mode" },
@@ -0,0 +1,79 @@
1
+ # The control room: audit, design and decisions
2
+
3
+ How v2.4.0 turns the Papercliped plugin into a control room inside Paperclip. Written alongside the build. The user-facing guides are `site/docs/control-room.md` and `site/docs/access-modes.md`; this page is for people changing the code.
4
+
5
+ Labels: **Observed** = read from Paperclip's installed source (2026.1001.0) or a live instance. **Decided** = a choice made for this release.
6
+
7
+ ## 1. What was asked
8
+ - See every session (one connected AI app) and manage it from inside Paperclip: which tools it may use, and whether it applies to everyone or to selected agents.
9
+ - Follow Paperclip's native design, as a control room.
10
+ - Papercliped integrated into the app like agents: finely manageable access, **full control for every agent and the API by default**, and a main-page switch between **API only | Full | Agent only**.
11
+ - Audit Paperclip to see what needs to be integrated with what, and document as we build.
12
+
13
+ ## 2. Audit of Paperclip (Observed)
14
+
15
+ ### What a plugin can be
16
+ Paperclip 2026.1001.0 has a plugin system (alpha). The UI slot types are `page`, `detailTab`, `taskDetailView`, `dashboardWidget`, `sidebar`, `routeSidebar`, `sidebarPanel`, `projectSidebarItem`, `globalToolbarButton`, `appShellOverlay`, `toolbarButton`, `contextMenuItem`, `commentAnnotation`, `commentContextMenuItem`, `settingsPage`, `companySettingsPage`. Each needs a capability: `page` ← `ui.page.register`, `sidebar`/`routeSidebar` ← `ui.sidebar.register`, `detailTab` ← `ui.detailTab.register`, `dashboardWidget` ← `ui.dashboardWidget.register`.
17
+
18
+ - `routeSidebar` replaces the company menu while a route is open. This is how Paperclip's own agent page gets its grouped left menu, so it is the native way to build a control room.
19
+ - `detailTab` with `entityTypes: ["agent"]` adds a tab to every agent's page.
20
+ - A plugin worker reads agents with `ctx.agents.list` (capability `agents.read`). The host supplies the verified company with every action call (`context.companyId`); the page's own parameters are never trusted for it.
21
+ - A `routePath` is allowed only on `page`, `routeSidebar` and `companySettingsPage` slots. The 2.2.0 manifest put one on a `sidebar` slot, which is why Paperclip refused to install it (a bare `400`). The plugin's tests now run Paperclip's own `pluginManifestV1Schema`.
22
+ - Paperclip refuses to **upgrade** a plugin whose new version asks for capabilities the old one didn't have (an admin must approve). Moving from 2.2.x to 2.4 therefore means remove and reinstall. Documented in `site/docs/paperclip-plugin.md`.
23
+ - Install is `POST /api/plugins/install` (instance admin only), which runs `npm install <pkg>@<version> --ignore-scripts` into `~/.paperclip/plugins`, then validates the manifest (schema, API version, capabilities, route conflicts, minimum host version) and registers it.
24
+
25
+ ### What Paperclip already has that overlaps
26
+ - **Tool access** (`/companies/:id/tools/*`, `/tool-connections`, `/tool-profiles`, grants and delegations) and a **tool gateway** (`/tool-gateway/*`, MCP gateways). These govern the tools *agents* use *outward* (GitHub, Google, remote MCP connectors). Papercliped is the opposite direction: AI apps controlling Paperclip *inward*. **Decided:** do not reuse or mirror them; they model a different thing, and a plugin can't extend them. The per-agent **Tools** tab in Paperclip's own UI (`AgentToolsTab`) is the closest native pattern, and is why Papercliped's per-agent control lives on the agent's own page too.
27
+ - **Agent permissions** (`PATCH /agents/:id/permissions`), **authorization grants and policies** (capabilities `authorization.*`). These are Paperclip-side permissions for principals inside Paperclip. **Decided:** not used. Papercliped's limits are enforced by the bridge, which every AI call passes through, so they hold for Claude, ChatGPT and any MCP client regardless of Paperclip's version, and need no extra capability.
28
+ - **Agent sessions** (`agent.sessions.*`, `task-sessions`, `runtime-state`). These are an agent's own runtime conversations. They are not Papercliped sessions. In the control room a **session** always means a connected AI app (an OAuth grant).
29
+
30
+ ### Native design (Observed from `ui/` and a live page)
31
+ shadcn-style components on Tailwind with CSS variables (`--background`, `--card`, `--border`, `--primary`, `--sidebar-accent`, …), light and dark via a `.dark` class, Inter, Lucide icons at 16px. The plugin uses Paperclip's **own compiled classes** (every class used is checked against the live stylesheet, see `plugin/src/ui/look.ts`), the SDK's `StatusBadge`, `MetricCard`, `DataTable` and toast, and Lucide icons. On touch screens Paperclip forces buttons to at least 44px, so controls size themselves from their buttons instead of a fixed height.
32
+
33
+ ## 3. Design
34
+
35
+ ### Sessions
36
+ A **session** is one OAuth grant (one connected AI app). `Grant.policy` (new, nullable JSON) holds `{ label, tools, agents }`; `null` for `tools` or `agents` means "all". The access **level** stays in `grant.scopes`.
37
+
38
+ ### The access switch
39
+ `Account.policy` (new, nullable JSON) holds `{ mode: "api"|"full"|"agent", agents: { [agentId]: "api"|"full"|"agent"|"off" } }`. No row means Full for every agent, so nothing changes for anyone until they choose.
40
+
41
+ ### Tool surfaces (`src/access/policy.ts`)
42
+ Every tool is exactly one of **read** (any read, and `GET` through the raw API tool), **agent** (create/update/comment on issues, wake agent: it hands work to agents), or **api** (every other change: pause, resume, clear error, budget, terminate, goals, approvals, non-`GET` raw API). A mode allows `read` plus: `api` → api, `agent` → agent, `full` → both. A test ties `site/docs/access-modes.md` and the generated tool reference to this classification.
43
+
44
+ ### Enforcement order (`evaluate`, called from `executeTool`)
45
+ 1. Session tool list. 2. For each agent the call is about (named, assigned or owner, or the assignee of the named issue): Off → refuse; the agent's (or default) mode must allow the surface; the session's agent list must include it. 3. With no agent named, the default mode must allow the surface. 4. A session limited to selected agents may only use tools that name an agent (plus companies, agents list and service status), because every other view looks across all agents. The access level (scopes) is checked before all of this, unchanged.
46
+
47
+ Refusals are `403` with `{ message, policy: <code> }`, audited as `policy_blocked`, and never reach Paperclip. The message names the setting and where to change it.
48
+
49
+ ### Hiding agents (`src/access/guard.ts`)
50
+ For agents set to **Off**, the Paperclip client handed to every tool is wrapped so each response has those agents' records removed (list items, rows keyed by agent id, anything referencing them), **before** the tool builds its answer. A report built from that client cannot name a hidden agent because it never received one. Server-side totals are left as the server computed them (documented). For a session limited to selected agents, `paperclip_list_agents` is narrowed to those agents.
51
+
52
+ An issue's agent is not named in the call, so for sessions with limits or accounts with per-agent settings the bridge looks the issue up once (`GET /issues/:id`) before deciding; if that fails, a limited session is refused and anyone else lets the tool report the real error.
53
+
54
+ ### What the AI is shown
55
+ `visibleTools(scopes, policy)` drops tools that can never run for the session (not in its tool list; no mode allows the surface; tools that look across all agents for a limited session). Tools that *might* run for some agent stay.
56
+
57
+ ### Management API (`src/manage/routes.ts`)
58
+ `GET /sessions`, `POST|DELETE /sessions/:id`, `GET|POST|PUT /policy`, `GET /tools`, `GET /activity`. Input is parsed strictly (`parseAccountPolicy`, `parseSessionPolicy`): unknown tool names, empty lists, bad ids and over-long lists are refused; damaged stored JSON falls back to the safe default instead of failing a call. Activity is read from the audit table by grant id and never contains arguments or results.
59
+
60
+ ### Plugin (`plugin/`)
61
+ New worker actions: `sessions`, `setSession`, `policy`, `setPolicy`, `tools`, `activity`, `agents`. Five slots: `sidebar` (entry), `page` (the control room), `routeSidebar` (its menu), `detailTab` on agents, `dashboardWidget`. Navigation is `/papercliped?s=<section>&id=<thing>` so links, back and reload work. The access switch is a three-position vertical switch with a sliding knob (arrow keys, announced as a radio group, reduced-motion respected); the same control is reused compactly for agents.
62
+
63
+ ### Database
64
+ `007_control_room.sql`: `accounts.policy jsonb`, `grants.policy jsonb`. No backfill. The panel views expose neither column. The generated `docs/supabase-schema.sql` is regenerated and a test fails if it is stale.
65
+
66
+ ## 4. How it was verified
67
+ - **Rule engine**: unit tests for every mode, per-agent override, Off, session tool and agent lists, issue assignee, redaction, validation and damaged-row fallback (`test/policy.test.ts`).
68
+ - **End to end through the real server** with a fake Paperclip: switching modes changes the next call, nothing blocked reaches Paperclip, Off agents vanish from lists and reports, limited sessions, another account is never affected, activity includes blocked calls and no arguments (`test/control-room.test.ts`).
69
+ - **Postgres**: the whole suite (memory, Postgres, and the least-privilege role) ran against a real PostgreSQL 16, including the new store methods.
70
+ - **Plugin**: handlers against a fake bridge, the SDK test harness (capabilities are enforced there), and the UI (`plugin/test`).
71
+ - **Paperclip's own validators**: the built manifest passes `pluginManifestV1Schema` and the host's capability validator, run on the live instance's installed code.
72
+ - **Visual**: every page, the agent tab and the widget were rendered with Paperclip's real stylesheet in light, dark and phone width.
73
+
74
+ ## 5. Known limits and next steps
75
+ - Limits apply to calls through Papercliped. The Paperclip key Papercliped holds still has the account's access (see `docs/SECURITY.md`); a bridge compromise bypasses them.
76
+ - Server-summed totals include Off agents.
77
+ - Activity is capped at 200 rows per request and, on the hosted service, kept 30 days (`BRIDGE_AUDIT_RETENTION_DAYS`).
78
+ - The plugin could not be installed into a live Paperclip with these slots before release; the manifest was validated against the live host's code instead. First live install after release should be checked: left menu replaces the company menu on `/papercliped`, the agent tab appears, the widget can be added.
79
+ - Paperclip's plugin API is alpha; `routeSidebar` and `detailTab` behaviour may change.
package/docs/SECURITY.md CHANGED
@@ -3,7 +3,7 @@
3
3
  Read this before running the bridge for people other than yourself.
4
4
 
5
5
  ## What you are holding
6
- For every connected user the bridge stores a **Paperclip board API key**. In Paperclip that key is bound to the *user*, not to a company, and carries **all** of that user's board power (verified in Paperclip's source: `board_api_keys` has no scope column, and the challenge's `requestedCompanyId` is only used to attribute activity-log entries, not to restrict the key). The bridge's two access levels (Read only and Full control) limit what *connected AI clients* may do through the bridge. They do **not** limit what the stored key can do if the bridge itself is compromised.
6
+ For every connected user the bridge stores a **Paperclip board API key**. In Paperclip that key is bound to the *user*, not to a company, and carries **all** of that user's board power (verified in Paperclip's source: `board_api_keys` has no scope column, and the challenge's `requestedCompanyId` is only used to attribute activity-log entries, not to restrict the key). The bridge's limits (the two access levels, the API only / Full / Agent only switch, per-agent settings and per-session tool and agent lists, see `docs/CONTROL-ROOM.md`) limit what *connected AI clients* may do through the bridge. They do **not** limit what the stored key can do if the bridge itself is compromised.
7
7
 
8
8
  > **Headline risk:** a full compromise of the running bridge (code execution on the Render service *and* access to its environment) exposes every connected user's Paperclip with full board access, until those keys are revoked. Everything below reduces the likelihood or blast radius; none of it removes that risk. Until Paperclip offers scoped/short-lived keys, tell users plainly, encourage a dedicated Paperclip user for the connection, and keep the user base small enough to be comfortable with that.
9
9
 
package/docs/SITEMAP.md CHANGED
@@ -29,6 +29,8 @@ One service, routed by host (`PUBLIC_HOSTS`, `src/web/`): `papercliped.co` the w
29
29
  | `/docs/manage` | Manage connections |
30
30
  | `/docs/paperclip-plugin` | Paperclip plugin |
31
31
  | `/docs/permissions` | Permissions |
32
+ | `/docs/control-room` | The control room |
33
+ | `/docs/access-modes` | API only, Full or Agent only |
32
34
  | `/docs/anonymous-mode` | Anonymous mode |
33
35
  | `/docs/public-api` | Public API and status |
34
36
  | `/docs/security` | Security |
@@ -54,7 +56,7 @@ One service, routed by host (`PUBLIC_HOSTS`, `src/web/`): `papercliped.co` the w
54
56
  | Path | Purpose |
55
57
  | --- | --- |
56
58
  | `GET /manage` | Old address: redirects to `/docs/paperclip-plugin` |
57
- | `/api/manage/*` | JSON API used by the Paperclip plugin (bearer token only, no cookies): `plugin-link/sign-in`, `me`, `connections`, `connections/:id`, `privacy`, `plugin-links`, `plugin-links/:id`, `secret/rotate`, `paperclip/disconnect`, `account/delete` (the last three need the secret key again) |
59
+ | `/api/manage/*` | JSON API used by the Paperclip plugin (bearer token only, no cookies): `plugin-link/sign-in`, `me`, `connections`, `connections/:id`, `sessions`, `sessions/:id`, `policy`, `tools`, `activity`, `privacy`, `plugin-links`, `plugin-links/:id`, `secret/rotate`, `paperclip/disconnect`, `account/delete` (the last three need the secret key again) |
58
60
  | Domain section in the plugin **(planned v3)** | Pro members: address, tunnel status, token, port, release |
59
61
 
60
62
  ## 4. AI client endpoints
@@ -274,6 +274,17 @@ update bridge.grants
274
274
  set scopes = array(select distinct s from unnest(array_replace(scopes, 'paperclip:admin', 'paperclip:control')) as s order by s desc)
275
275
  where 'paperclip:admin' = any(scopes);
276
276
 
277
+ -- ───── 007_control_room.sql ─────
278
+ -- Control room: who may do what through Papercliped.
279
+ -- accounts.policy the access switch (api | full | agent) and per-agent overrides, as JSON. Null = Full for every agent.
280
+ -- grants.policy one session's limits (a name, which tools, which agents), as JSON. Null = no limits beyond its access level.
281
+ -- The app validates both on the way in and falls back to the safe default on anything it can't read, so old rows need no backfill.
282
+ alter table bridge.accounts add column if not exists policy jsonb;
283
+ alter table bridge.grants add column if not exists policy jsonb;
284
+
285
+ -- Audit rows now also record calls the policy refused (error_class = policy_blocked).
286
+ comment on column bridge.audit_events.error_class is 'invalid_input | insufficient_scope | read_only | policy_blocked | upstream_4xx | upstream_5xx | upstream_unreachable | rate_limited | unauthorized | internal';
287
+
277
288
  -- ───── migration bookkeeping ─────
278
289
  create table if not exists bridge.schema_migrations (version text primary key, applied_at timestamptz not null default now());
279
290
  alter table bridge.schema_migrations enable row level security;
@@ -283,6 +294,6 @@ do $$ declare r text; begin
283
294
  if exists (select 1 from pg_roles where rolname = r) then execute format('revoke all on bridge.schema_migrations from %I', r); end if;
284
295
  end loop;
285
296
  end $$;
286
- insert into bridge.schema_migrations (version) values ('001_init.sql'), ('002_audit.sql'), ('003_accounts.sql'), ('004_privacy_panel.sql'), ('005_beta.sql'), ('006_two_levels.sql') on conflict (version) do nothing;
297
+ insert into bridge.schema_migrations (version) values ('001_init.sql'), ('002_audit.sql'), ('003_accounts.sql'), ('004_privacy_panel.sql'), ('005_beta.sql'), ('006_two_levels.sql'), ('007_control_room.sql') on conflict (version) do nothing;
287
298
 
288
299
  commit;
@@ -0,0 +1,9 @@
1
+ -- Control room: who may do what through Papercliped.
2
+ -- accounts.policy the access switch (api | full | agent) and per-agent overrides, as JSON. Null = Full for every agent.
3
+ -- grants.policy one session's limits (a name, which tools, which agents), as JSON. Null = no limits beyond its access level.
4
+ -- The app validates both on the way in and falls back to the safe default on anything it can't read, so old rows need no backfill.
5
+ alter table bridge.accounts add column if not exists policy jsonb;
6
+ alter table bridge.grants add column if not exists policy jsonb;
7
+
8
+ -- Audit rows now also record calls the policy refused (error_class = policy_blocked).
9
+ comment on column bridge.audit_events.error_class is 'invalid_input | insufficient_scope | read_only | policy_blocked | upstream_4xx | upstream_5xx | upstream_unreachable | rate_limited | unauthorized | internal';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "papercliped",
3
- "version": "2.2.1",
3
+ "version": "2.4.0",
4
4
  "description": "Papercliped — connect Claude, ChatGPT and any MCP app to your Paperclip: control agents, sync, report. MCP server + hosted multi-tenant OAuth bridge + public stats API.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -0,0 +1,72 @@
1
+ # API only, Full or Agent only
2
+
3
+ One switch decides how AI apps may work with your Paperclip: **API only**, **Full** or **Agent only**. **Full** is the default for every agent. You set it in the [control room](/docs/control-room), and you can set any single agent differently (or turn it **Off**).
4
+
5
+ ## What each position means
6
+ | Mode | AI apps can | AI apps can't |
7
+ | --- | --- | --- |
8
+ | **API only** | Look at everything, and control Paperclip directly: pause and resume agents, set budgets, decide approvals, manage goals, send API requests | Hand work to agents |
9
+ | **Full** (default) | Everything: look, control directly, and work through agents | Nothing is held back by the switch |
10
+ | **Agent only** | Look at everything, and work through agents: create, assign and comment on issues, wake an agent | Control Paperclip directly |
11
+
12
+ The AI app's access **level** (Read only or Full control) still applies on top. Read only can never change anything, whatever the switch says.
13
+
14
+ ## The three kinds of tool
15
+ Every tool is exactly one of these:
16
+
17
+ | Kind | Tools | Allowed in |
18
+ | --- | --- | --- |
19
+ | **Look** | Everything that only reads: lists, details, reports, sync, waiting for an agent, and raw `GET` requests | Every mode |
20
+ | **Work through agents** | Create issue, Update issue, Comment on issue, Wake agent now | Full, Agent only |
21
+ | **Direct control** | Pause agent, Resume agent, Clear agent error, Set agent budget, Terminate agent, Create goal, Update goal, Decide approval, and raw API requests that aren't `GET` | Full, API only |
22
+
23
+ The full list, with what each tool does, is the [tool reference](/docs/tools).
24
+
25
+ ## One agent at a time
26
+ Each agent can follow the default or be set apart:
27
+
28
+ - **API only**, **Full** or **Agent only** for just that agent. For example, keep the default **Full** but set one agent to **Agent only**: AI apps can give it work but can't pause or terminate it.
29
+ - **Off**: Papercliped can't see or touch that agent. It disappears from lists and reports, anything assigned to it is out of reach, and calls that name it are refused.
30
+
31
+ A call is judged by the agent it is about: the agent it names, the agent it assigns work to, or the agent an issue is assigned to. A call that isn't about one agent (for example "list goals") follows the default.
32
+
33
+ ## One session at a time
34
+ Each connected app (a **session**) can also be limited, whatever the switch says:
35
+
36
+ - **Tools:** only the tools you tick.
37
+ - **Agents:** only the agents you choose. The session then works with those agents only, and can't use views across every agent (reports, the org chart, goals, approvals).
38
+
39
+ ## How the layers combine
40
+ Papercliped checks, in this order, and refuses at the first thing that doesn't allow the call:
41
+
42
+ 1. The session's **tool list** (if it has one).
43
+ 2. The agent's **setting**: Off refuses; otherwise its mode must allow this kind of tool.
44
+ 3. The session's **agent list** (if it has one).
45
+ 4. The access **level** (Read only, Full control).
46
+
47
+ So a call goes through only if *every* layer allows it.
48
+
49
+ ## What the AI app sees
50
+ - Tools that can **never** run for a session are left out of what it is shown, so it doesn't try them. A session limited to `List agents` and `Pause agent` sees exactly those two.
51
+ - A refused call returns a message that says which setting stopped it and where to change it. In the API the response is `403` with `{ "error": { "message": "...", "policy": "<code>" } }`:
52
+
53
+ | `policy` code | Meaning |
54
+ | --- | --- |
55
+ | `tool_not_allowed` | The session's tool list doesn't include this tool |
56
+ | `mode_blocks` | The access switch (or that agent's setting) doesn't allow this kind of tool |
57
+ | `agent_off` | The agent is turned off |
58
+ | `agent_not_in_session` | The session applies to selected agents and this isn't one of them |
59
+ | `needs_all_agents` | The session applies to selected agents, and this view looks across every agent (or the issue has no agent to check) |
60
+
61
+ Blocked calls appear in [Activity](/docs/control-room) as **Blocked**, and count under `policy_blocked` in the aggregate error classes of the [public API](/docs/public-api).
62
+
63
+ ## Examples
64
+ - *"I want Claude to run my agents but never change budgets or approvals."* Give that session **Tools: Work through agents + Look** (untick the Direct control tools), or set the switch to **Agent only**.
65
+ - *"I want a reviewer app that only works on two agents."* Open its session, choose **selected agents**, tick the two. It can look at them, wake them and comment on their issues, and nothing else.
66
+ - *"Keep my finance agent away from AI apps."* Agents → set it to **Off**.
67
+ - *"Pause everything fast, but no new work."* Set the switch to **API only**.
68
+
69
+ ## Limits worth knowing
70
+ - These settings apply to calls made **through Papercliped**. They don't change what your Paperclip account can do in Paperclip itself, and the Paperclip key Papercliped holds still has your account's access (see [Security](/docs/security)). They limit the AI app, not the key.
71
+ - Totals the Paperclip server already summed (such as total spend) still include hidden agents. Lists, per-agent breakdowns and reports built from them don't.
72
+ - Changing a setting takes effect on the next request. A call already running isn't interrupted.
@@ -1,120 +1,166 @@
1
- # Set up your Paperclip for Papercliped
1
+ # At home, with a tunnel
2
2
 
3
- Papercliped talks to **your** Paperclip over the internet, so your Paperclip needs a public address. This guide gets you one, step by step, whether you already own a domain or not.
3
+ Run Paperclip on your own computer and give it a public `https://` address with a free tunnel. You don't open any ports on your router. This is the cheapest way to start, and a good way to try Papercliped before you rent a server.
4
4
 
5
- You don't need to open any ports on your router for any option below.
5
+ **You'll end up with:** Paperclip on your computer, reachable at a public address like `https://paperclip.yourdomain.com` or `https://my-pc.my-tailnet.ts.net`, connected to Papercliped.
6
6
 
7
- ## What Papercliped needs from your Paperclip
8
- - **A public `https://` address on port 443** that answers over the internet. Private, LAN, `localhost` and plain `http://` addresses are refused on purpose.
9
- - **Paperclip in authenticated mode and public exposure.** You can check from any computer:
10
- ```
11
- curl https://your-address/api/health
12
- ```
13
- A healthy answer is JSON that includes `"status":"ok"`, `"deploymentMode":"authenticated"` and `"deploymentExposure":"public"`. (On Windows PowerShell, `curl.exe https://your-address/api/health` works the same way.)
14
- - **No login wall or bot challenge in front of `/api/*`.** If you put something like Cloudflare Access, "Under Attack" mode or a managed challenge in front of Paperclip, it must skip `/api/*`, or Papercliped will be blocked.
15
- - **Paperclip must accept the new hostname.** Paperclip can reject hostnames it doesn't know, and public mode needs its public URL set. Paperclip's own settings for this include `PAPERCLIP_PUBLIC_URL` and `PAPERCLIP_ALLOWED_HOSTNAMES`; the exact steps are in Paperclip's deployment docs (search "Paperclip deployment modes" on docs.paperclip.ing). Check them there rather than guessing.
7
+ **Good to know:** while your computer sleeps or is off, your agents and your AI app's connection stop. For a Paperclip that's always on, use a [VPS or a hosting platform](/docs/hosting).
16
8
 
17
- Paperclip listens on port `3100` by default, which the examples below use. If yours is different, use your port.
9
+ ## 1. Choose a tunnel
18
10
 
19
- ## Path A: you own a domain (recommended)
20
- This gives you a stable address like `https://paperclip.yourdomain.com` that survives restarts. The tunnel and DNS are free on Cloudflare's free plan. The domain itself isn't: there is no free `.com`. (Cloudflare Registrar sells domains at wholesale cost, so it's one cheap option if you need to buy one.)
11
+ | Tunnel | Your address | Stays the same? | Needs | Good for |
12
+ | --- | --- | --- | --- | --- |
13
+ | **Cloudflare Tunnel** | `https://paperclip.yourdomain.com` | Yes | A domain on Cloudflare (free plan) | Daily use (recommended) |
14
+ | **Tailscale Funnel** | `https://<computer>.<tailnet>.ts.net` | Yes | A free Tailscale account | Daily use without a domain |
15
+ | **ngrok** | one free `*.ngrok-free.app` address | Yes | A free ngrok account | Daily use without a domain |
16
+ | **Cloudflare quick tunnel** | random `*.trycloudflare.com` | **No, changes every restart** | Nothing | Trying it for an afternoon |
21
17
 
22
- 1. **Put your domain on Cloudflare.** Create a free Cloudflare account, add your domain, and switch its nameservers to the two Cloudflare gives you (done at the company where you bought the domain). Wait until Cloudflare shows the domain as active.
23
- 2. **Install `cloudflared`** on the machine that runs Paperclip. Find the installer for Windows, macOS or Linux on Cloudflare's downloads page (search "cloudflared downloads").
24
- 3. **Log in.** This opens a browser so you can pick your domain:
25
- ```
26
- cloudflared tunnel login
27
- ```
28
- 4. **Create the tunnel.** Pick any name:
29
- ```
30
- cloudflared tunnel create papercliped-paperclip
31
- ```
32
- It prints a tunnel ID (a UUID) and saves a credentials file in your `.cloudflared` folder. Keep that file private.
33
- 5. **Write the config.** In your `.cloudflared` folder (`~/.cloudflared` on macOS/Linux, `%USERPROFILE%\.cloudflared` on Windows) create `config.yml`:
34
- ```
35
- tunnel: <TUNNEL-ID>
36
- credentials-file: <PATH-TO-THE-CREDENTIALS-FILE>.json
37
- ingress:
38
- - hostname: paperclip.yourdomain.com
39
- service: http://localhost:3100
40
- - service: http_status:404
41
- ```
42
- The last rule is required: it answers 404 for anything else.
43
- 6. **Point the name at the tunnel:**
44
- ```
45
- cloudflared tunnel route dns papercliped-paperclip paperclip.yourdomain.com
46
- ```
47
- 7. **Run it.** To try it first:
48
- ```
49
- cloudflared tunnel run papercliped-paperclip
50
- ```
51
- To keep it running (starts with your computer), install it as a service:
52
- - **macOS:** `cloudflared service install` (runs when you log in) or `sudo cloudflared service install` (runs at boot).
53
- - **Linux:** `cloudflared service install` (with `sudo` if needed).
54
- - **Windows:** run `cloudflared.exe service install` from an Administrator PowerShell. A Windows service may not read the config from your user folder; check Cloudflare's "Run as a service on Windows" page for where it expects `config.yml`.
55
- 8. **Check it** from any computer:
56
- ```
57
- curl https://paperclip.yourdomain.com/api/health
58
- ```
59
- You should see the JSON described above.
18
+ Pick one and **work out your address first**: Paperclip needs to know it during setup (step 2). The tunnel sections below show how to get it.
19
+
20
+ ## 2. Install Paperclip in public mode
21
+
22
+ You need **Node.js 24.11 or newer** (check with `node -v`; get it from nodejs.org).
23
+
24
+ ```
25
+ npx paperclipai onboard
26
+ ```
27
+
28
+ When it asks:
29
+
30
+ - **Deployment mode:** `authenticated` (people sign in).
31
+ - **Exposure:** `public`.
32
+ - **Public URL:** your tunnel address from step 1, for example `https://paperclip.yourdomain.com` (with `https://`, no slash at the end).
33
+ - **Bind:** `loopback`. The tunnel connects from your own computer, so Paperclip doesn't need to listen on your network.
34
+
35
+ These choices are the same as the settings `PAPERCLIP_DEPLOYMENT_MODE=authenticated`, `PAPERCLIP_DEPLOYMENT_EXPOSURE=public` and `PAPERCLIP_PUBLIC_URL`, which you can also set as environment variables. Onboarding creates the secrets Paperclip needs and saves them in `~/.paperclip/instances/default/.env`. Start Paperclip with:
36
+
37
+ ```
38
+ npx paperclipai run
39
+ ```
40
+
41
+ It listens on port **3100**. (If something else already uses 3100, Paperclip quietly picks another port and prints it; use that port in the tunnel instead.)
60
42
 
61
- **If your computer sleeps or turns off,** the tunnel goes down and your connected AI apps stop working until it's back. Turn off sleep on the machine, or run Paperclip on an always-on computer or server.
43
+ **Already running Paperclip on this computer** in the default `local_trusted` mode (no login)? Change it with `npx paperclipai configure --section server`: choose `authenticated`, `public`, and your tunnel address. Never put a `local_trusted` Paperclip behind a public address: anyone who finds it could control it.
62
44
 
63
- ## Path B: you don't have a domain yet
64
- All of these are free. They differ in how stable the address is.
45
+ **Prefer Docker?** Use the Compose file from the [VPS guide](/docs/host-vps#5-create-the-docker-compose-file) without the `caddy` service, add `ports: ["127.0.0.1:3100:3100"]` to the Paperclip service, and set `DOMAIN` to your tunnel's hostname.
65
46
 
66
- | Option | Address | Stable? | Good for |
67
- | --- | --- | --- | --- |
68
- | Tailscale Funnel | `https://<machine>.<tailnet>.ts.net` | Yes | Daily use |
69
- | ngrok free plan | one free static `ngrok-free.app` / `ngrok-free.dev` domain | Yes | Daily use, with a caveat below |
70
- | Cloudflare quick tunnel | random `*.trycloudflare.com` | **No, changes every restart** | Trying Papercliped only |
47
+ ## 3. Start the tunnel
71
48
 
72
- ### Tailscale Funnel (stable)
73
- Funnel makes a service on your computer reachable from the public internet at your tailnet's `ts.net` name.
74
- 1. Create a free Tailscale account and install Tailscale on the machine that runs Paperclip.
75
- 2. In the Tailscale admin console, turn on **HTTPS certificates** for your tailnet and allow Funnel. (Running the `tailscale funnel` command below walks you through enabling it and updates your tailnet policy for you.)
76
- 3. Start Funnel for Paperclip's port:
49
+ Follow the section for the tunnel you chose, then come back for step 4.
50
+
51
+ ### Cloudflare Tunnel (with your domain)
52
+
53
+ Stable address on your own domain. The tunnel and DNS are free on Cloudflare's free plan; the domain itself isn't (Cloudflare Registrar sells them at cost).
54
+
55
+ 1. **Put your domain on Cloudflare:** create a free account, add your domain, and switch its nameservers to the two Cloudflare gives you (at the company where you bought the domain). Wait until Cloudflare shows it as active.
56
+ 2. In the Cloudflare dashboard, open **Zero Trust → Networks → Tunnels → Create a tunnel**, choose **Cloudflared**, and name it `paperclip`.
57
+ 3. Cloudflare shows an install command for Windows, macOS or Linux that includes a token, like `cloudflared service install eyJ…`. Run it on this computer. It installs `cloudflared` as a service that starts with the computer. (Keep the token private; it's the key to your tunnel.)
58
+ 4. Under **Public Hostname**, add: subdomain `paperclip`, your domain, service type **HTTP**, URL **`localhost:3100`**. Save.
59
+
60
+ That's it: `https://paperclip.yourdomain.com` now reaches your Paperclip. Don't turn on Cloudflare Access, Bot Fight Mode or a WAF challenge for this hostname (or exempt `/api/*`), or Papercliped will be blocked.
61
+
62
+ <details><summary>Prefer the command line?</summary>
63
+
64
+ ```
65
+ cloudflared tunnel login
66
+ cloudflared tunnel create paperclip
67
+ cloudflared tunnel route dns paperclip paperclip.yourdomain.com
68
+ ```
69
+
70
+ Create `config.yml` in your `.cloudflared` folder (`~/.cloudflared` on macOS and Linux):
71
+
72
+ ```
73
+ tunnel: <TUNNEL-ID>
74
+ credentials-file: <PATH-TO-THE-CREDENTIALS-FILE>.json
75
+ ingress:
76
+ - hostname: paperclip.yourdomain.com
77
+ service: http://localhost:3100
78
+ - service: http_status:404
79
+ ```
80
+
81
+ Try it with `cloudflared tunnel run paperclip`, then install it as a service with `cloudflared service install` (`sudo` on Linux and for start-at-boot on macOS). **On Windows** the service runs as SYSTEM, so it doesn't read your user folder: put `config.yml` and the credentials file in `C:\Windows\System32\config\systemprofile\.cloudflared\`, then run `cloudflared.exe service install` from an Administrator PowerShell. The dashboard method above avoids all of this.
82
+
83
+ </details>
84
+
85
+ ### Tailscale Funnel (no domain)
86
+
87
+ 1. Create a free Tailscale account and install Tailscale on this computer.
88
+ 2. Run:
77
89
  ```
78
- tailscale funnel 3100
90
+ tailscale funnel --bg 3100
79
91
  ```
80
- It prints your public address, like `https://my-pc.my-tailnet.ts.net`. Funnel only serves on ports 443, 8443 and 10000; use the default 443 for Papercliped.
81
- 4. Funnel traffic has bandwidth limits you can't change. That is fine for Papercliped's small requests, but check Tailscale's Funnel docs for the current rules on your plan.
92
+ The first time, it walks you through turning on HTTPS certificates and Funnel for your tailnet. It prints your address, like `https://my-pc.my-tailnet.ts.net`, and keeps running in the background.
93
+ 3. Funnel only serves on ports 443, 8443 and 10000; the command above uses 443, which is what Papercliped needs. Funnel addresses always end in `.ts.net` (no custom domains), and bandwidth is limited, which is fine for Papercliped's small requests.
82
94
 
83
- ### ngrok free plan (stable address, one catch)
84
- 1. Create a free ngrok account. Every account gets one free static "dev domain" (for example `your-name.ngrok-free.dev`); see it in the ngrok dashboard under Domains.
95
+ Find your address any time with `tailscale funnel status`.
96
+
97
+ ### ngrok (no domain)
98
+
99
+ 1. Create a free ngrok account. Your account gets one free static address (under **Domains** in the ngrok dashboard), like `your-name.ngrok-free.app`. You can't choose it on the free plan.
85
100
  2. Install ngrok and add your authtoken (the dashboard shows the exact command).
86
- 3. Run, with your own domain:
101
+ 3. Run, with your own address:
87
102
  ```
88
- ngrok http --url=your-name.ngrok-free.dev 3100
103
+ ngrok http --url=your-name.ngrok-free.app 3100
89
104
  ```
90
- 4. **The catch:** on the free plan ngrok shows a "visit site" warning page to browsers. Papercliped's requests come from a program, not a browser, but if the connection fails with a strange HTML page, this is the likely cause. Check ngrok's free-plan docs for the current behavior and any header that skips it.
105
+ 4. On the free plan ngrok shows a "You are about to visit…" page to **web browsers** the first time. Click **Visit Site** when you open Paperclip in your browser; requests from programs like Papercliped aren't affected. If a connection ever fails with an unexpected HTML page, this page is the likely cause.
106
+
107
+ To keep ngrok running after you close the terminal, see ngrok's docs on running it as a service (`ngrok service install`).
91
108
 
92
109
  ### Cloudflare quick tunnel (trial only)
93
- No account, no domain:
110
+
111
+ No account, no domain. Install `cloudflared`, then:
112
+
94
113
  ```
95
114
  cloudflared tunnel --url http://localhost:3100
96
115
  ```
97
- It prints a random `https://something.trycloudflare.com` address. **The address changes every time you restart it**, and when it changes your Papercliped connection stops working until you connect again with the new address. Quick tunnels are for trying Papercliped for an afternoon, not for daily use.
98
116
 
99
- ## Connect to Papercliped
100
- 1. Make sure `curl https://your-address/api/health` works (see above).
101
- 2. Go to [Create your account]({{URL}}/docs/signup), add Papercliped as a connector in Claude, and choose **Connect your Paperclip**.
102
- 3. Enter your public address (just the address, no path), then approve the request in your Paperclip.
117
+ It prints a random `https://something.trycloudflare.com` address. Use that as the public URL in step 2 (`npx paperclipai configure --section server` if you already onboarded). **The address changes every time you restart it**, and then Papercliped can't reach your Paperclip until you set the new address in Paperclip and connect again. Quick tunnels are for testing only.
118
+
119
+ ## 4. Create your account
120
+
121
+ In another terminal on the same computer:
122
+
123
+ ```
124
+ npx paperclipai auth bootstrap-ceo --base-url https://your-address
125
+ ```
126
+
127
+ It prints a one-time invite link. Open it, create your account and your first company. (If you switched an existing Paperclip from `local_trusted`, it may instead print a one-time **claim** link when it starts; either works.)
128
+
129
+ ## 5. Check it works
130
+
131
+ From another network (your phone on mobile data is a good test):
132
+
133
+ ```
134
+ curl https://your-address/api/health
135
+ ```
136
+
137
+ (On Windows PowerShell use `curl.exe`.) You want JSON with `"status":"ok"`, `"deploymentMode":"authenticated"`, `"deploymentExposure":"public"` and `"bootstrapStatus":"ready"`.
138
+
139
+ ## 6. Connect Papercliped
140
+
141
+ 1. Add the connector in your AI app. In Claude: **Settings → Connectors → Add custom connector**, address `{{MCP}}/mcp`.
142
+ 2. Choose **Connect your Paperclip**, enter your public address (just the address, no path) and approve the request in your Paperclip. The box **Also install the Papercliped plugin in my Paperclip** is ticked by default; it installs the [Paperclip plugin](/docs/paperclip-plugin) and its [control room](/docs/control-room) for you if you are your Paperclip's instance admin.
143
+ 3. Pick a username, save the secret key you're shown once, and choose **Read only** or **Full control**. Every screen: [Create your account](/docs/signup).
144
+ 4. Send your first prompt: *"Catch me up on my Paperclip."* More in the [prompt gallery](/docs/prompts).
145
+
146
+ ## Keep it running
147
+
148
+ - **Turn off sleep** on this computer, or your agents and connection stop whenever it sleeps.
149
+ - **Start Paperclip with the computer.** The Cloudflare dashboard tunnel and Tailscale already do; for Paperclip itself, add `npx paperclipai run` to your login items (macOS), Task Scheduler (Windows) or a systemd service (Linux), or use the Docker setup, which restarts by itself.
150
+ - **Update Paperclip** with `npx paperclipai@latest run` when your agents are idle.
103
151
 
104
152
  ## Keep it safe
105
- - **Expose only Paperclip.** Point the tunnel at Paperclip's port and nothing else on your computer.
153
+
154
+ - **Expose only Paperclip.** Point the tunnel at port 3100 and nothing else on your computer.
155
+ - **Never expose `local_trusted` mode.** Always `authenticated` + `public`.
106
156
  - **Keep Paperclip up to date.**
107
- - **Use a dedicated Paperclip user for the connection** if you can, so you can see and limit what it does.
108
- - **You can cut access any time:** revoke the Papercliped key in Paperclip, or disconnect apps in the [Paperclip plugin](/docs/paperclip-plugin).
109
- - **If the tunnel or your computer is off,** connected apps simply stop working until it's back. Nothing is lost.
157
+ - **You can cut access any time:** disconnect apps in the [Paperclip plugin](/docs/paperclip-plugin), or revoke the key in Paperclip.
110
158
 
111
159
  ## Troubleshooting
112
- - **"Could not reach your Paperclip":** the tunnel isn't running, the DNS name hasn't spread yet (give a new name a few minutes), or the address isn't on port 443. Test with `curl https://your-address/api/health` from another network (for example, your phone's mobile data).
113
- - **"Private address" errors:** you entered a LAN address, `localhost`, or `http://`. Use the public `https://` address from your tunnel.
114
- - **A challenge or login page appears:** exempt `/api/*` from Cloudflare Access, "Under Attack" mode or any managed challenge.
115
- - **"Host not allowed" or a 4xx from Paperclip:** Paperclip doesn't know the new hostname. Set its public URL and allowed hostnames (see Paperclip's deployment docs, above) and restart it.
116
- - **Certificate warnings:** use the HTTPS address your tunnel provider gives you, not your own certificate on a raw IP. Tunnels handle certificates for you.
117
- - **Worked yesterday, not today:** the address changed (quick tunnels do this), the tunnel stopped, or the computer slept.
118
-
119
- ## Not independently confirmed
120
- These came from vendor docs summarized through search, not read page by page. Check the vendor's current docs before relying on them: Windows service setup for `cloudflared`, Tailscale's current Funnel limits, ngrok's free-plan warning page behavior, and Paperclip's exact setting names for public URL and allowed hostnames.
160
+
161
+ - **"Could not reach your Paperclip":** the tunnel or Paperclip isn't running, a new DNS name hasn't spread yet (give it a few minutes), or the address isn't on port 443. Test with `curl` from another network.
162
+ - **"Private address" errors:** you entered a LAN address, `localhost` or `http://`. Use the public `https://` address from your tunnel.
163
+ - **"This hostname is not allowed for this Paperclip instance":** Paperclip's public URL doesn't match the tunnel address, or exposure is still `private`. Fix it with `npx paperclipai configure --section server` and restart.
164
+ - **A challenge or login page appears:** exempt `/api/*` from Cloudflare Access, Bot Fight Mode, "Under Attack" mode or any managed challenge.
165
+ - **Worked yesterday, not today:** the computer slept, the tunnel stopped, or a quick tunnel's address changed.
166
+ - More: [Troubleshooting](/docs/troubleshooting).
@@ -0,0 +1,61 @@
1
+ # The control room
2
+
3
+ The control room is Papercliped inside Paperclip: one place to see every AI app connected to your Paperclip, what each is allowed to do, and what it has done. It opens from **Papercliped** in Paperclip's sidebar and uses Paperclip's own look, so it follows your theme.
4
+
5
+ You need the [Paperclip plugin](/docs/paperclip-plugin) installed and your Papercliped account linked. Everything here takes effect on the app's **next request**: nothing needs reconnecting.
6
+
7
+ ## How it fits together
8
+ Three things decide what an AI app can do. Papercliped checks all three on every call, and the strictest one wins.
9
+
10
+ | Layer | Where you set it | Decides |
11
+ | --- | --- | --- |
12
+ | **Access switch** | Overview, Agents, dashboard widget, agent tab | Whether AI apps may control Paperclip directly, work through agents, or both ([API only, Full or Agent only](/docs/access-modes)), for every agent or one agent at a time |
13
+ | **Session** | Sessions | Which tools one connected app may use, and which agents it applies to |
14
+ | **Level** | Sessions | Read only or Full control, as chosen when the app connected ([Permissions](/docs/permissions)) |
15
+
16
+ ## The menu
17
+ While the control room is open, Paperclip's left menu is replaced by Papercliped's, the same way it is on an agent's page. **Back to Paperclip** at the top returns you.
18
+
19
+ ### Overview
20
+ The front page. The **access switch** is a three-position switch: **API only**, **Full** (the default) and **Agent only**. Click a position, or use the arrow keys when the switch has focus. It saves at once. Beside it: how many sessions you have, how many agents, the calls made today and how many were blocked, a short list of things that need a look (a session that never made a call, an agent turned off, blocked calls, a Paperclip key that is not connected), and the latest calls.
21
+
22
+ ### Sessions
23
+ Every AI app connected through Papercliped is a **session**. Open one to change:
24
+
25
+ - **Name.** Rename a session to tell two apps or two devices apart. Up to 60 characters.
26
+ - **Level.** Read only or Full control.
27
+ - **Tools.** *All tools* means every tool its level and the switch allow. Untick it to choose exactly which tools this session may use, grouped as **Look**, **Work through agents** and **Direct control**. When a session is Read only, tools that change things are greyed out with "Needs Full control".
28
+ - **Agents.** *Everyone* (including agents you add later), or **selected agents**. A session limited to selected agents works only with those agents: it can look at them, pause them, wake them, give them work, and use issues assigned to them. It cannot use views across every agent, such as reports, the org chart, goals and approvals, because those would show agents it doesn't apply to. The page says so when you choose it.
29
+ - **Recent calls** for just this session, and **Disconnect**.
30
+
31
+ Save with **Save changes** (it stays disabled until something changed and says what's wrong if a list is empty). **Discard** puts everything back.
32
+
33
+ ### Agents
34
+ Papercliped follows the access switch for every agent. Here you can set any agent apart: **Default**, **API only**, **Full**, **Agent only** or **Off**.
35
+
36
+ **Off** hides the agent completely. AI apps can't see it, can't touch it, and don't see anything assigned to it or its spending in lists and reports. Use it for agents you never want an AI app near.
37
+
38
+ The default for every agent can also be changed from this page. Settings for agents that no longer exist (or are in another company) are listed so you can remove them.
39
+
40
+ ### Tools
41
+ All tools an AI app can use, grouped by what they do, with what the switch allows right now and how many of your sessions can use each. Use it to answer "can my laptop session pause an agent?" without opening each session.
42
+
43
+ ### Activity
44
+ The newest calls through your sessions: when, which session, which tool, and the result: **OK**, **Blocked** (by your settings) or **Failed** (with the reason, such as "Paperclip unreachable"). Filter by session, or to blocked and failed only. It refreshes every 20 seconds.
45
+
46
+ Activity shows *what was used and what happened*. It never records what was sent to a tool or what came back. On the hosted service it is kept for 30 days.
47
+
48
+ ### Settings
49
+ Privacy (appear anonymously in the service's logs), the Paperclips linked to your account, and the account itself (a new secret key, disconnect your Paperclip, delete the account). These ask for your secret key again. See [Anonymous mode](/docs/anonymous-mode).
50
+
51
+ ## In the rest of Paperclip
52
+ - **An "Papercliped" tab on every agent's page.** Set what AI apps may do with *this* agent, and see which sessions reach it.
53
+ - **A dashboard widget.** The access switch in small, with the number of sessions and blocked calls.
54
+ - **A sidebar entry**, with the paperclip icon, under your other sections.
55
+
56
+ ## Good to know
57
+ - These settings limit what AI apps can do **through Papercliped**. They don't change what your own Paperclip account can do in Paperclip itself.
58
+ - A blocked call returns a plain message to the AI app saying which setting stopped it and where to change it, so it doesn't keep retrying. See [Limits and errors](/docs/limits-and-errors).
59
+ - Tools that can never run for a session (switched off by the access switch or left out of its tool list) are not shown to the AI app at all.
60
+ - Totals the Paperclip server already added up (for example total spend) still include hidden agents. Lists, reports by agent and anything built from them don't.
61
+ - New permissions need approval in Paperclip. If you installed an earlier version of the plugin, remove it and install it again from **Settings → Plugins** to get the control room (see [Paperclip plugin](/docs/paperclip-plugin)).