{"slug": "pi-caveman-mode", "title": "pi: caveman mode", "summary": "Alessandro Perrotta, developer of the pi coding agent, reimplemented the terse-speak 'caveman mode' natively in pi using a 40-line extension and skill, after finding the upstream caveman project too bloated. The extension, auto-discovered at ~/.pi/agent/extensions/caveman.ts, rewrites the system prompt on every turn via the before_agent_start event and adds a /caveman command to toggle the mode, with code blocks, commit messages, and PR descriptions always remaining at full verbosity.", "body_md": "♠ [Previously](https://perrotta.dev/2025/12/pi/),\n[previously](https://perrotta.dev/2026/06/caveman-talk-like-caveman-save-tokens/).\n\n**Problem statement**: adopt [caveman](https://github.com/JuliusBrussee/caveman)\nin [pi](https://github.com/earendil-works/pi).\n\nPi isn’t one of the 30+ agents caveman auto-detects. The install matrix\n(`INSTALL.md`\n\n) lists agent detection rules one by one — `claude`\n\n, `cursor`\n\n,\n`windsurf`\n\n, `opencode`\n\n, `openclaw`\n\n, etc — and pi isn’t in it. Running the\none-liner installer here would just skip everything silently. Booo!\n\nRather than run someone else’s `curl | bash`\n\nagainst an agent it wasn’t built\nfor, “““I””” reimplemented the terse-speak part natively, since `pi`\n\nalready ships the\ntwo primitives needed: [skills](https://agentskills.io/specification) and\n[extensions](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/extensions.md).\n\nA\n[skill](https://github.com/thiagowfx/.dotfiles/blob/7c495489141fd6036e4be70de9a065c53f7a8394/pi/.pi/agent/extensions/caveman.ts)\nfor `/skill:caveman`\n\ndocumentation, and an extension that rewrites the system\nprompt on every turn via `pi.on(\"before_agent_start\", (event) => ...)`\n\n:\n\n``` js\nconst INSTRUCTIONS = `Caveman mode: on. Respond terse. Drop articles (a/an/the), filler (just/really/basically), pleasantries, hedging. Fragments OK. Short synonyms. Technical terms exact. Pattern: [thing] [action] [reason]. [next step]. Example — not: \"Sure! I'd be happy to help you with that.\" yes: \"Bug in auth middleware. Fix:\"\nBoundaries, always: code blocks, commit messages, and PR descriptions stay normal full verbosity, never compressed. Drop caveman style for security warnings, irreversible/destructive actions, or when the user seems confused — resume caveman after.`;\n\nexport default function (pi: ExtensionAPI) {\n  let on = true; // auto-on by default, every session\n\n  const applyStatus = (ctx: { ui: { setStatus: (k: string, v?: string) => void } }) => {\n    ctx.ui.setStatus(\"caveman\", on ? \"[caveman]\" : undefined);\n  };\n\n  pi.on(\"session_start\", async (_event, ctx) => applyStatus(ctx));\n\n  pi.on(\"before_agent_start\", (event) => {\n    if (!on) return;\n    return { systemPrompt: `${event.systemPrompt}\\n\\n${INSTRUCTIONS}` };\n  });\n\n  pi.registerCommand(\"caveman\", {\n    description: \"Toggle caveman terse-response mode: on|off (default: on)\",\n    handler: async (args, ctx) => {\n      const arg = args.trim().toLowerCase();\n      if (arg === \"off\" || arg === \"stop\" || arg === \"normal\") on = false;\n      else if (arg === \"on\" || arg === \"\") on = true;\n      else return ctx.ui.notify(`Unknown arg \"${arg}\". Use: on | off`, \"error\");\n      applyStatus(ctx);\n      ctx.ui.notify(on ? \"Caveman mode on.\" : \"Caveman mode off.\", \"info\");\n    },\n  });\n}\n```\n\n[ before_agent_start](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/extensions.md#before_agent_start)\nfires on\n\n`~/.pi/agent/extensions/caveman.ts`\n\n, auto-discovered, no `/reload`\n\nneeded after\nthe first load.Unlike the Claude Code plugin, I skipped `lite`\n\n/`full`\n\n/`ultra`\n\n/`wenyan`\n\n— I\ncalled that bloat back in June, and I’m not adding it to my own version\neither. On or off is enough.\n\nThe result, *unprompted*:\n\nuser: caveman on or off now?\n\nassistant: Caveman: on.\n\nuser: how to turn it off?\n\nassistant:`/caveman off`\n\nI also skipped the parts that don’t have a pi equivalent: the statusline\nsavings counter, `/caveman-stats`\n\n, the `caveman-shrink`\n\nMCP proxy that rewrites\ntool descriptions (a proxy that rewrites what an agent sees is exactly the\nkind of thing worth reading before installing). The 40-line extension above\ncovers what I actually wanted.\n\nOne rule baked into both the skill and the extension: code, commits, and PRs stay full verbosity, never compressed.\n\nThis experience was an eye-opener for me to realize how bloated the upstream caveman project became.\n\n🤖 *Drafted with *\n\n`/bloggify`\n\n.— § —\n\nReply via [email](mailto:serendipity@perrotta.dev?subject=Reply to: pi: caveman mode)", "url": "https://wpnews.pro/news/pi-caveman-mode", "canonical_source": "https://perrotta.dev/2026/07/pi-caveman-mode/", "published_at": "2026-07-22 10:14:47+00:00", "updated_at": "2026-08-04 09:04:32.450959+00:00", "lang": "en", "topics": ["developer-tools", "ai-agents"], "entities": ["Alessandro Perrotta", "pi", "caveman", "JuliusBrussee", "earendil-works"], "alternates": {"html": "https://wpnews.pro/news/pi-caveman-mode", "markdown": "https://wpnews.pro/news/pi-caveman-mode.md", "text": "https://wpnews.pro/news/pi-caveman-mode.txt", "jsonld": "https://wpnews.pro/news/pi-caveman-mode.jsonld"}}