{"slug": "pi-prompt-before-dangerous-commands", "title": "pi: prompt before dangerous commands", "summary": "Pi, an extension for the earendil-works coding agent, now prompts users for confirmation before executing dangerous shell commands such as `rm -rf`, `terraform destroy`, and destructive Git operations, instead of blocking them outright. The update, made by developer Thiago Perrotta in the dangerous-command-guard/guard.ts file, uses the tool_call event and ctx.ui.confirm to ask for approval in interactive sessions, while print and JSON modes still fail closed. All 48 tests pass.", "body_md": "♠ [Previously](https://perrotta.dev/2026/07/pi-block-dangerous-commands-syntax-aware/).\n\n**Problem statement**: my Pi extension blocked dangerous shell commands outright,\neven when I had already preserved the state they could destroy.\n\nThe guard parses every `bash`\n\ntool call with tree-sitter, catching commands such\nas `rm -rf`\n\n, `terraform destroy`\n\n, and destructive Git operations. Today it did\nexactly what I had asked:\n\n```\n% git -C \"$(brew --repo thiagowfx/pancake)\" reset --hard origin/master\ngit reset --hard is blocked - discards changes irreversibly\n```\n\nBlocking remains the right default, but an interactive session can ask me. Pi\nextensions can intercept the\n[ tool_call event](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/docs/extensions.md#tool_call)\nand open a confirmation dialog through\n\n`ctx.ui`\n\n.The change in\n[ dangerous-command-guard/guard.ts](https://github.com/thiagowfx/.dotfiles/commit/b5cb42f8deafae176ecddc12fccbd7c04ca264dd):\n\n``` js\n-  pi.on(\"tool_call\", async (event) => {\n+  pi.on(\"tool_call\", async (event, ctx) => {\n     if (event.toolName !== \"bash\") return;\n\n     const command = event.input.command;\n     if (typeof command !== \"string\") return;\n\n     const blocked = await findBlockedCommand(command);\n-    if (blocked) return { block: true, reason: blocked.reason };\n+    if (!blocked) return;\n+    if (!ctx.hasUI) return { block: true, reason: blocked.reason };\n+\n+    const allowed = await ctx.ui.confirm(\n+      \"Allow dangerous command?\",\n+      `${blocked.command}\\n\\n${blocked.reason}`,\n+    );\n+    if (!allowed) return { block: true, reason: \"Blocked by user\" };\n   });\n```\n\nInteractive Pi now pauses for approval. Print and JSON modes have no UI, so they still fail closed. Safe commands never prompt.\n\nThe tests exercise all three decisions:\n\n```\n✔ extension prompts before dangerous bash tool calls (0.66225ms)\nℹ tests 48\nℹ pass 48\nℹ fail 0\n```\n\nSame guardrails, with an escape hatch operated by a human rather than a model.\n\n🤖 *Drafted with *\n\n`/bloggify`\n\n.— § —\n\nReply via [email](mailto:serendipity@perrotta.dev?subject=Reply to: pi: prompt before dangerous commands)", "url": "https://wpnews.pro/news/pi-prompt-before-dangerous-commands", "canonical_source": "https://perrotta.dev/2026/08/pi-prompt-before-dangerous-commands/", "published_at": "2026-08-16 11:28:44+00:00", "updated_at": "2026-08-16 11:41:28.006390+00:00", "lang": "en", "topics": ["ai-tools", "developer-tools", "ai-agents"], "entities": ["Pi", "earendil-works", "Thiago Perrotta", "dangerous-command-guard/guard.ts", "tree-sitter"], "alternates": {"html": "https://wpnews.pro/news/pi-prompt-before-dangerous-commands", "markdown": "https://wpnews.pro/news/pi-prompt-before-dangerous-commands.md", "text": "https://wpnews.pro/news/pi-prompt-before-dangerous-commands.txt", "jsonld": "https://wpnews.pro/news/pi-prompt-before-dangerous-commands.jsonld"}}