From run-paperclip
Make the calls only you can make — review what your agents are asking for (new hires, strategy changes) and approve, reject, ask for changes, or comment. The one place you sign off on decisions.
How this command is triggered — by the user, by Claude, or both
Slash command
/run-paperclip:pc-approve <list|show|approve|reject|revise|comment> [approval-id] [--note <text>] [-C <company-id>]This command is limited to the following tools:
The summary Claude sees in its command listing — used to decide when to auto-load this command
# /pc-approve — decide the approval queue (board, deliberate) > 🗣️ **Say it plainly** (Voice rule in `docs/mc-ux.md`). Present each pending > request in plain terms — who's asking, for what, and why — so the founder can > decide at a glance. No "approval queue B7", endpoints, or §refs in what they > see; just "**Acme** wants to hire a second engineer — approve?". Implements PRD §6.4.12 (with §9.3 and AC20). This is the **one** place the founder clears the Paperclip approval queue — hire-agent and `approve_ceo_strategy` requests that the autonomous loop *raised* but is forbidden to decide...
🗣️ Say it plainly (Voice rule in
docs/mc-ux.md). Present each pending request in plain terms — who's asking, for what, and why — so the founder can decide at a glance. No "approval queue B7", endpoints, or §refs in what they see; just "Acme wants to hire a second engineer — approve?".
Implements PRD §6.4.12 (with §9.3 and AC20). This is the one place the founder
clears the Paperclip approval queue — hire-agent and approve_ceo_strategy
requests that the autonomous loop raised but is forbidden to decide for itself.
It wraps the paperclipai approval … surface — Appendix A B7 only (see
references/api-contract.md) — and is board-persona work
(approve/reject/request-revision require the board token).
The human-in-the-loop guardrail (§9.3, the AI-proposes/human-disposes rule). The autonomous loop (
/pc-run-company,/pc-work,/pc-serve) creates and surfaces approvals but never decides its own — an embodied agent must never self-approve its own escalation (a hire it requested, a strategy change it proposed). Deciding the queue is a deliberate human action: the founder operating the plugin is the board, and only the founder runs this command. That is why this is the onlypc-*command allowed to useAskUserQuestion— a human is explicitly present at the keyboard. It is never invoked from/pc-run-company,/pc-work,/pc-serve, or the loop (disable-model-invocation: true).
Source the shared helper and resolve auth (board/operator persona) first:
: "${CLAUDE_PLUGIN_ROOT:=$(ls -d "$HOME"/.claude/plugins/cache/*/run-paperclip/*/ 2>/dev/null | sort -V | tail -1 | sed 's:/*$::')}"
. "${CLAUDE_PLUGIN_ROOT:?could not locate the run-paperclip plugin}/scripts/lib/pc-common.sh"
pc_resolve_auth
Talk to Paperclip CLI-only (paperclipai … --json, via pc_cli/pc_cli_json)
— never raw HTTP; the CLI wraps everything this command needs (the B7 ops). -C <company-id> resolves PAPERCLIP_COMPANY_ID (defaults to the resolved company).
Board persona required. Deciding an approval needs the board token. If only an
agent persona is resolved (PAPERCLIP_AGENT_ID set, no board token), stop and
report — an agent cannot (and must not) dispose of its own escalations.
Per docs/mc-ux.md: args still work — every flag in the argument-hint runs
straight through. AskUserQuestion fires only for an input the founder did
not pass, and never auto-picks a decision. This is the one command in
the whole plugin allowed to use AskUserQuestion in a decision, valid only
because a human is explicitly present at the keyboard (board persona, gated above).
Strip the pnpm > preamble before jq:
… --json | grep -v '^>' | grep -v '^$' | jq ….
ActionWhen no subcommand is passed, ask one AskUserQuestion — "What would you like to
do with the items waiting on you?" (recommended first):
(Recommended) → list. Show everything that needs your
decision.show. Open a single request to read the full story
before deciding.approve / reject / revise (the Decision MC
below). Approve, decline, or send one back with notes.comment. Add a note or ask a question,
no decision yet.CompanyIf -C <cid> was not passed and the company is ambiguous, resolve it by listing
(never ask for a UUID — map the chosen label back to its id):
paperclipai company list --json | grep -v '^>' | grep -v '^$' | jq -r '.[] | "\(.name)\t\(.id)"'
Offer each name as an option (with a short discriminator if names collide) and
map the chosen label → cid for PAPERCLIP_COMPANY_ID.
ApprovalFor show, approve/reject/revise, and comment, when no [approval-id]
was passed, list the pending queue and let the founder pick one (never a UUID):
paperclipai approval list --status pending --json | grep -v '^>' | grep -v '^$' \
| jq -r '.[] | "\(.type) · by \(.requestingAgentName // .requestingAgentId) · \(.summary)\t\(.id)"'
(Scope with -C <cid> when a company is resolved.) Each option label is
<type> · by <agent> · <one-line summary>; map the chosen label → approvalId.
Decision (the sanctioned use)Only after an approval is selected, ask one AskUserQuestion — "Your call on
<summary>:" — the human chooses; never auto-pick:
approval approve <id>.approval reject <id>.approval request-revision <id>
(returns it to the agent so they can revise and resubmit).This Decision MC is the confirmation — a human is present and disposing the
escalation, so there is no second confirm and no self-approve path. Then,
when no --note was passed, optionally gather a decision note via a free-text
prompt ("Add a decision note?") and pass it as --decision-note <note>; a note is
optional but recorded for an auditable trail.
list -C <cid>paperclipai approval list -C "$PAPERCLIP_COMPANY_ID" --status pending --json
(B7 GET /api/companies/:cid/approvals?status=pending). Render each pending
approval's id, type (show it in plain terms — a new-hire approval or a
strategy approval), requesting agent, and a one-line summary, so the
founder sees everything waiting on them at a glance. This is the same queue
the skill-driven monitor read (operator-runbook UC6) surfaces read-only.
show <id>paperclipai approval get <id> --json (B7 GET /api/approvals/:id) plus the
approval's linked issues and comments, so the founder sees the full request —
who asked, why, and what it touches — before deciding.
approve | reject | revise <id> [--note <text>]paperclipai approval approve|reject|request-revision <id> --decision-note <note>
(B7 board-only POST …/approve|reject|request-revision). revise =
request-revision (send it back to the requesting agent for changes).
--note (decision note) records why; include it for an auditable trail.AskUserQuestion to present approve / reject / request-revision as
choices to the founder. This is the one sanctioned use of AskUserQuestion
in the whole plugin — it is valid only because a human is explicitly present
and deciding. Never auto-pick a decision; the founder chooses.comment <id> --note <text>paperclipai approval comment <id> --body <note> (B7, recorded on the approval).
Add context or ask the requesting agent for clarification without deciding —
useful before a revise.
Unaffected. Approvals run no model server-side, so the cost-guard hook (§6.6) never engages here. The safety property this command upholds is governance (human-in-the-loop), not cost.
This command reads/decides approval metadata only. Never echo the board token or
the Authorization header to the transcript — pc_debug redacts Bearer tokens
if you trace.
On a 409/ownership error, a 403 (not the board persona), or any failure,
stop and report — do not retry. The CLI exits non-zero and prints the error on
failure — stop and report, never retry.
npx claudepluginhub aronprins/run-paperclip --plugin run-paperclip