{"record":{"id":"a81022a5c55473f0","repo":"paperclipai/paperclip","slug":"refusing-to-delete-without-yes","errorCode":null,"errorMessage":"Refusing to delete without --yes","messagePattern":"Refusing to delete without --yes","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"cli/src/commands/client/agent.ts","lineNumber":402,"sourceCode":"          const ctx = resolveCommandContext(opts);\n          const payload = updateAgentSchema.parse(parseJson(opts.payloadJson));\n          const updated = await ctx.api.patch<Agent>(apiPath`/api/agents/${agentId}`, payload);\n          printOutput(updated, { json: ctx.json });\n        } catch (err) {\n          handleCommandError(err);\n        }\n      }),\n  );\n\n  addCommonClientOptions(\n    agent\n      .command(\"delete\")\n      .description(\"Delete an agent\")\n      .argument(\"<agentId>\", \"Agent ID\")\n      .option(\"--yes\", \"Confirm deletion\")\n      .action(async (agentId: string, opts: AgentDeleteOptions) => {\n        try {\n          if (!opts.yes) throw new Error(\"Refusing to delete without --yes\");\n          const ctx = resolveCommandContext(opts);\n          const result = await ctx.api.delete(apiPath`/api/agents/${agentId}`);\n          printOutput(result, { json: ctx.json });\n        } catch (err) {\n          handleCommandError(err);\n        }\n      }),\n  );\n\n  for (const [name, path, description] of [\n    [\"pause\", \"pause\", \"Pause an agent\"],\n    [\"resume\", \"resume\", \"Resume an agent\"],\n    [\"approve\", \"approve\", \"Approve a pending agent\"],\n    [\"terminate\", \"terminate\", \"Terminate an agent\"],\n    [\"heartbeat:invoke\", \"heartbeat/invoke\", \"Invoke an agent heartbeat\"],\n    [\"claude-login\", \"claude-login\", \"Trigger Claude login for an agent\"],\n  ] as const) {\n    addCommonClientOptions(","sourceCodeStart":384,"sourceCodeEnd":420,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/cli/src/commands/client/agent.ts#L384-L420","documentation":"Intentional safety guard in `paperclipai agent delete`. Commander wires `--yes` as the confirmation flag; the action handler refuses to proceed if opts.yes is falsy, before making any API call. No network request is issued, so this is a usage error, not a server error.","triggerScenarios":"Running `paperclipai agent delete <agentId>` without `--yes`. The default for --yes is undefined/false, so any invocation missing the flag throws.","commonSituations":"Operator forgot the flag. Script wrapping the CLI that did not propagate confirmation. Muscle memory from a different CLI that uses `-y` or `--force`.","solutions":["Add `--yes` to confirm: `paperclipai agent delete <agentId> --yes`.","If scripting, set --yes explicitly in the wrapper.","If you did not mean to delete, this throw protected you — no further action needed."],"exampleFix":"// before\npaperclipai agent delete agt_123\n// after\npaperclipai agent delete agt_123 --yes","handlingStrategy":"validation","validationCode":"// In a wrapper script, assert confirmation before invoking.\nfunction buildDeleteCmd(agentId: string, confirmed: boolean): string[] {\n  if (!confirmed) throw new Error('Refusing to build delete command without confirmation');\n  return ['agent', 'delete', agentId, '--yes'];\n}","typeGuard":null,"tryCatchPattern":"try { await runAgentDelete(agentId, { yes: true }); }\ncatch (err) {\n  if (err instanceof Error && err.message === 'Refusing to delete without --yes') {\n    // impossible — we passed yes; surface as a logic bug\n  }\n  throw err;\n}","preventionTips":["Always pass --yes for scripted deletes; never assume a default.","In interactive wrappers, prompt the user once and forward --yes.","Treat the absence of --yes as intentional protection, not friction."],"tags":["cli","agent","confirmation-guard","usage"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}