{"slug": "kun-s-pi-agent-config", "title": "Kun's Pi Agent Config", "summary": "Kun, a developer, shared his minimal and practical configuration for the Pi coding agent, which he uses for all LLMs except Claude due to Anthropic's ban on third-party harnesses. His setup includes settings like hiding thinking blocks, enabling all steering and follow-up modes, and using three third-party extensions: pi-web-access for web browsing, pi-extension-codex-fast-mode for faster GPT requests, and pi-openai-server-compaction for server-side context compaction. He also overrides context window sizes for OpenAI's gpt-5.6 models to 272,000 tokens to avoid doubled costs on larger requests.", "body_md": "# Kun's Pi Agent Config\n\n### Minimal, practical, and elegant\n\nIt’s the 67th time I got asked how I’ve configured my Pi agent - it’s time to write it down and share! This is not going to be “here’s 100 fancy tricks you can do with Pi”. This is “here’s what I actually use and can’t live without.”\n\n## When and why do I use Pi\n\nI use Pi heavily for any model that’s not Claude, because Anthropic banned 3rd party harnesses from using their subscription quota. There are some workarounds, but none is perfect - so for Claude I’m stuck with Claude Code. For any other LLM, I pretty much only use Pi at this point, barring some exceptions.\n\nI pick Pi because it’s provider-neutral, minimal, and deeply customizable. I believe this is how agent harnesses should be, because the AI models are constantly advancing, and the harness needs to be flexible enough to evolve with them.\n\n## Main settings\n\n`~/.pi/agent/settings.json`\n\n```\n{\n  \"images\": {\n    \"blockImages\": false\n  },\n  \"terminal\": {\n    \"showImages\": false\n  },\n  \"hideThinkingBlock\": true,\n  \"quietStartup\": true,\n  \"theme\": \"rose-pine-moon\",\n  \"steeringMode\": \"all\",\n  \"followUpMode\": \"all\",\n  \"collapseChangelog\": true,\n  \"packages\": [\n    \"npm:pi-web-access@0.14.0\",\n    \"npm:@ryan_nookpi/pi-extension-codex-fast-mode@0.2.6\",\n    \"git:github.com/algal/pi-openai-server-compaction@c6d593087709e9481223dc6c6c2269b371b5e055\"\n  ]\n}\n```\n\nSome of these are personal preferences, but a few important ones -\n\n`hideThinkingBlock`\n\nhelps create a less noisy terminal. I don’t find any value in watching what the LLM is thinking in its own head.`steeringMode=all`\n\nis a no-brainer because if I sent multiple steering prompts I of course want all of them to go out asap.`followUpMode=all`\n\nis important to me because I like to keep queuing follow up prompts when the model is working. Having all of the queued prompts sent all at once is a lot more efficient than letting them go out one by one.\n\n## 3rd party extensions\n\nYou can see from the settings file above I only have a few 3rd party extensions. I’ll quickly explain what they are and why I use them here.\n\n`pi-web-access`\n\nis a no-brainer because the stock Pi is so minimal that it doesn’t even have the ability to search and browse web content.`pi-extension-codex-fast-mode`\n\nis what allows me to activate fast mode when using gpt models. It’s a very simple extension that just has an on/off toggle to control whether requests to Codex backend activates fast mode. Fast mode uses 2x tokens for 2.5x speed, so use it with the tradeoff in mind.`pi-openai-server-compaction`\n\nmakes Pi use OpenAI’s secret sauce “server side compaction” whenever the context window is too long and needs to be compacted. The server side compaction is what Codex uses by default, and is what makes Codex so good at long running tasks despite gpt models have a short context window there.\n\n## Model overrides\n\n`~/.pi/agent/models.json`\n\n```\n{\n  \"providers\": {\n    \"openai-codex\": {\n      \"modelOverrides\": {\n        \"gpt-5.6-luna\": {\n          \"contextWindow\": 272000\n        },\n        \"gpt-5.6-sol\": {\n          \"contextWindow\": 272000\n        },\n        \"gpt-5.6-terra\": {\n          \"contextWindow\": 272000\n        }\n      }\n    }\n  }\n}\n```\n\nThis is an interesting one. OpenAI’s gpt models actually can support longer context requests, but whenever the request goes above 272k input tokens, it will double the cost. See [https://developers.openai.com/api/docs/pricing](https://developers.openai.com/api/docs/pricing) for details.\n\nThe settings above makes Pi set the context window length for those models at 272k, so whenever the request becomes larger than that, it will do compaction and dial it back down. This helps avoid draining our quota or API cost more quickly than we want.\n\n## Color theme\n\n`~/.pi/agent/themes/rose-pine-moon.json`\n\n```\n{\n  \"$schema\": \"https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json\",\n  \"name\": \"rose-pine-moon\",\n  \"vars\": {\n    \"base\": \"#232136\",\n    \"surface\": \"#2a273f\",\n    \"overlay\": \"#393552\",\n    \"muted\": \"#6e6a86\",\n    \"subtle\": \"#908caa\",\n    \"text\": \"#e0def4\",\n    \"love\": \"#eb6f92\",\n    \"gold\": \"#f6c177\",\n    \"rose\": \"#ea9a97\",\n    \"pine\": \"#3e8fb0\",\n    \"foam\": \"#9ccfd8\",\n    \"iris\": \"#c4a7e7\",\n    \"highlightLow\": \"#2a283e\",\n    \"highlightMed\": \"#44415a\",\n    \"highlightHigh\": \"#56526e\"\n  },\n  \"colors\": {\n    \"accent\": \"iris\",\n    \"border\": \"overlay\",\n    \"borderAccent\": \"iris\",\n    \"borderMuted\": \"muted\",\n    \"success\": \"foam\",\n    \"error\": \"love\",\n    \"warning\": \"gold\",\n    \"muted\": \"subtle\",\n    \"dim\": \"muted\",\n    \"text\": \"text\",\n    \"thinkingText\": \"subtle\",\n    \"selectedBg\": \"highlightMed\",\n    \"userMessageBg\": \"surface\",\n    \"userMessageText\": \"text\",\n    \"customMessageBg\": \"surface\",\n    \"customMessageText\": \"text\",\n    \"customMessageLabel\": \"iris\",\n    \"toolPendingBg\": \"highlightLow\",\n    \"toolSuccessBg\": \"surface\",\n    \"toolErrorBg\": \"surface\",\n    \"toolTitle\": \"foam\",\n    \"toolOutput\": \"text\",\n    \"mdHeading\": \"iris\",\n    \"mdLink\": \"foam\",\n    \"mdLinkUrl\": \"subtle\",\n    \"mdCode\": \"rose\",\n    \"mdCodeBlock\": \"text\",\n    \"mdCodeBlockBorder\": \"overlay\",\n    \"mdQuote\": \"subtle\",\n    \"mdQuoteBorder\": \"foam\",\n    \"mdHr\": \"overlay\",\n    \"mdListBullet\": \"iris\",\n    \"toolDiffAdded\": \"foam\",\n    \"toolDiffRemoved\": \"love\",\n    \"toolDiffContext\": \"subtle\",\n    \"syntaxComment\": \"muted\",\n    \"syntaxKeyword\": \"iris\",\n    \"syntaxFunction\": \"foam\",\n    \"syntaxVariable\": \"text\",\n    \"syntaxString\": \"gold\",\n    \"syntaxNumber\": \"rose\",\n    \"syntaxType\": \"pine\",\n    \"syntaxOperator\": \"iris\",\n    \"syntaxPunctuation\": \"subtle\",\n    \"thinkingOff\": \"muted\",\n    \"thinkingMinimal\": \"pine\",\n    \"thinkingLow\": \"foam\",\n    \"thinkingMedium\": \"iris\",\n    \"thinkingHigh\": \"rose\",\n    \"thinkingXhigh\": \"love\",\n    \"thinkingMax\": \"gold\",\n    \"bashMode\": \"gold\"\n  }\n}\n```\n\n`rose-pine-moon`\n\nis totally a personal choice. What you should know is that you can just talk to Pi and ask it to make you any theme you want. Point it at an official color theme you like, and it’ll do it for you.\n\n## Terminal title\n\n`.pi/agent/extensions/terminal-status-title.js`\n\n``` js\nconst DEFAULT_TITLE = \"π\";\nconst PREFIX = \"π\";\nconst MAX_TITLE_LENGTH = 40;\nconst SPINNER_INTERVAL_MS = 120;\nconst SPINNER_FRAMES = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"];\n\nfunction truncateTitle(title) {\n  if (title.length <= MAX_TITLE_LENGTH) return title;\n  return title.slice(0, MAX_TITLE_LENGTH - 3) + \"...\";\n}\n\nfunction basename(path) {\n  if (!path) return DEFAULT_TITLE;\n\n  const trimmed = path.replace(/[\\\\/]+$/, \"\");\n  if (!trimmed) return DEFAULT_TITLE;\n\n  return trimmed.split(/[\\\\/]/).pop() || DEFAULT_TITLE;\n}\n\nfunction getSessionName(pi) {\n  const name = pi.getSessionName?.();\n  return typeof name === \"string\" ? name.trim() : \"\";\n}\n\nfunction getRawTitle(pi, ctx) {\n  return getSessionName(pi) || basename(ctx.cwd);\n}\n\nfunction isSpinningStatus(status) {\n  return status === \"working\";\n}\n\nfunction statusIndicator(status, spinnerFrame) {\n  if (isSpinningStatus(status)) {\n    if (SPINNER_FRAMES.length === 0) return \"◉\";\n    return SPINNER_FRAMES[spinnerFrame % SPINNER_FRAMES.length];\n  }\n\n  if (status === \"done\") return \"✓\";\n  if (status === \"error\") return \"✗\";\n  return \"○\";\n}\n\nfunction formatTitle(pi, ctx, status, spinnerFrame) {\n  const rawTitle = getRawTitle(pi, ctx);\n  const suffix = rawTitle === DEFAULT_TITLE ? DEFAULT_TITLE : `${PREFIX} | ${truncateTitle(rawTitle)}`;\n\n  return `${statusIndicator(status, spinnerFrame)} | ${suffix}`;\n}\n\nexport default function terminalStatusTitle(pi) {\n  let status = \"idle\";\n  let spinnerFrame = 0;\n  let spinnerInterval;\n  let deferredWrite;\n  let lastCtx;\n\n  function clearDeferredWrite() {\n    if (!deferredWrite) return;\n\n    clearTimeout(deferredWrite);\n    deferredWrite = undefined;\n  }\n\n  function writeTitle(ctx = lastCtx) {\n    if (!ctx?.hasUI) return;\n\n    lastCtx = ctx;\n    ctx.ui.setTitle(formatTitle(pi, ctx, status, spinnerFrame));\n  }\n\n  function stopSpinner() {\n    if (!spinnerInterval) return;\n\n    clearInterval(spinnerInterval);\n    spinnerInterval = undefined;\n    spinnerFrame = 0;\n  }\n\n  function startSpinner(ctx) {\n    if (!ctx?.hasUI || spinnerInterval) return;\n\n    spinnerFrame = 0;\n    spinnerInterval = setInterval(() => {\n      if (!isSpinningStatus(status)) {\n        stopSpinner();\n        return;\n      }\n\n      spinnerFrame = (spinnerFrame + 1) % SPINNER_FRAMES.length;\n      writeTitle();\n    }, SPINNER_INTERVAL_MS);\n    spinnerInterval.unref?.();\n  }\n\n  function setStatus(nextStatus, ctx) {\n    clearDeferredWrite();\n    status = nextStatus;\n    lastCtx = ctx;\n\n    if (isSpinningStatus(status)) {\n      startSpinner(ctx);\n    } else {\n      stopSpinner();\n    }\n\n    writeTitle(ctx);\n  }\n\n  function scheduleWrite(ctx) {\n    clearDeferredWrite();\n    deferredWrite = setTimeout(() => {\n      deferredWrite = undefined;\n      writeTitle(ctx);\n    }, 0);\n    deferredWrite.unref?.();\n  }\n\n  pi.on(\"session_start\", async (_event, ctx) => {\n    setStatus(\"idle\", ctx);\n    scheduleWrite(ctx);\n  });\n\n  pi.on(\"agent_start\", async (_event, ctx) => {\n    setStatus(\"working\", ctx);\n  });\n\n  pi.on(\"agent_settled\", async (_event, ctx) => {\n    setStatus(\"done\", ctx);\n  });\n\n  pi.on(\"session_shutdown\", async () => {\n    clearDeferredWrite();\n    stopSpinner();\n  });\n}\n```\n\nThis is a custom extension built to print live agent status as terminal title. With this extension, if I spin up many terminal tabs of Pi agents, I can easily see which agent is working or waiting for my input.\n\n## Published config\n\nAll the config above is shared in my public dotfiles repo - [https://github.com/kunchenguid/dotfiles](https://github.com/kunchenguid/dotfiles). Feel free to copy/fork or do whatever you like with it.\n\nAnd there’s a little bonus hides in here - [https://github.com/kunchenguid/dotfiles/tree/main/home/.pi/agent/extensions/calm](https://github.com/kunchenguid/dotfiles/tree/main/home/.pi/agent/extensions/calm). This is another custom extension that adds a “/calm” command in your Pi, which allows you to toggle on/off a calm mode.\n\nWhen calm mode is on, it hides all tool calls from the agent, making the terminal extremely clean and peaceful. It also replaces the “Thinking” indicator with a little boat that sails on calm seas.\n\nThat’s everything - no fancy skills or workflows. Just the minimum to give me the core primitives I need, help me achieve good efficiency, and remove distractions.", "url": "https://wpnews.pro/news/kun-s-pi-agent-config", "canonical_source": "https://blog.kunchenguid.com/p/kuns-pi-agent-config", "published_at": "2026-08-01 19:11:24+00:00", "updated_at": "2026-08-01 19:22:25.473389+00:00", "lang": "en", "topics": ["developer-tools", "ai-agents", "ai-tools"], "entities": ["Pi", "Kun", "Anthropic", "Claude", "OpenAI", "pi-web-access", "pi-extension-codex-fast-mode", "pi-openai-server-compaction"], "alternates": {"html": "https://wpnews.pro/news/kun-s-pi-agent-config", "markdown": "https://wpnews.pro/news/kun-s-pi-agent-config.md", "text": "https://wpnews.pro/news/kun-s-pi-agent-config.txt", "jsonld": "https://wpnews.pro/news/kun-s-pi-agent-config.jsonld"}}