{"_id":"@bowerjames/mypi","_rev":"2-93e791a638cdbeb18b76f9cf6f4f4741","name":"@bowerjames/mypi","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"@bowerjames/mypi","version":"0.1.0","keywords":["pi","pi-coding-agent","extensions","skills","prompts"],"author":{"name":"James Bower","email":"james.bower@xanda.net"},"license":"MIT","_id":"@bowerjames/mypi@0.1.0","maintainers":[{"name":"bowerjames","email":"bower.james1996@gmail.com"}],"homepage":"https://github.com/BowerJames/mypi#readme","bugs":{"url":"https://github.com/BowerJames/mypi/issues"},"bin":{"mypi":"dist/cli.js"},"dist":{"shasum":"21aaab6674ff273ca8ae3cb24b12c872395cb886","tarball":"https://registry.npmjs.org/@bowerjames/mypi/-/mypi-0.1.0.tgz","fileCount":84,"integrity":"sha512-yq2eaty7iFK9CqHYPTyBqar1r9z1o6+aobQ8tYEMEtWNds5pm2GyOSojYNlkjcYda5fcQeQepq/StnBf5+6SHA==","signatures":[{"sig":"MEUCIGNg6z9lTlLVAgZyjD4gUn6hfd65WKG+cl+f7JP2i3BAAiEAva4an7Z1vpOvmSYCVOay7lkvDdWK0Cq52qmOJtm1od4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":267380},"main":"./dist/cli.js","type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"d7f0760990a8e4e19298dc5e541b1229772ec458","scripts":{"dev":"tsc --watch","lint":"biome check .","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json && node scripts/copy-bundles.mjs && chmod +x dist/cli.js","prepack":"npm run build","prepare":"husky","link:dev":"ln -sf $PWD/dist/cli.js $(npm prefix -g)/bin/mypi-dev","lint:fix":"biome check --write .","typecheck":"tsc -p tsconfig.check.json","unlink:dev":"rm -f $(npm prefix -g)/bin/mypi-dev","postinstall":"chmod +x dist/cli.js","install:global":"d=$(mktemp -d) && npm pack --pack-destination $d >/dev/null 2>&1 && npm install -g $d/*.tgz && rm -rf $d","prepublishOnly":"npm run typecheck && npm test && npm run lint"},"_npmUser":{"name":"bowerjames","email":"bower.james1996@gmail.com"},"repository":{"url":"git+https://github.com/BowerJames/mypi.git","type":"git"},"_npmVersion":"11.17.0","description":"Curated library of pi extensions, skills, and prompts with profile-based launching","directories":{},"lint-staged":{"*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,json,jsonc}":"biome check --write"},"_nodeVersion":"22.22.2","dependencies":{"js-yaml":"^4.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"husky":"^9.1.0","vitest":"^4.1.4","typescript":"^5.8.0","@types/node":"^22.0.0","lint-staged":"^17.0.0","@biomejs/biome":"^2.5.0","@types/js-yaml":"^4.0.9","@earendil-works/pi-tui":"*","@earendil-works/pi-coding-agent":"*"},"peerDependencies":{"@earendil-works/pi-tui":"*","@earendil-works/pi-coding-agent":"*"},"_npmOperationalInternal":{"tmp":"tmp/mypi_0.1.0_1783080424720_0.10280745808429792","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@bowerjames/mypi","version":"0.2.0","description":"Curated library of pi extensions, skills, and prompts with profile-based launching","type":"module","bin":{"mypi":"dist/cli.js"},"main":"./dist/cli.js","publishConfig":{"access":"public"},"engines":{"node":">=18"},"author":{"name":"James Bower","email":"james.bower@xanda.net"},"repository":{"type":"git","url":"git+https://github.com/BowerJames/mypi.git"},"bugs":{"url":"https://github.com/BowerJames/mypi/issues"},"homepage":"https://github.com/BowerJames/mypi#readme","scripts":{"build":"rm -rf dist && tsc -p tsconfig.build.json && node scripts/copy-bundles.mjs && chmod +x dist/cli.js","postinstall":"chmod +x dist/cli.js","prepack":"npm run build","dev":"tsc --watch","test":"vitest run","typecheck":"tsc -p tsconfig.check.json","lint":"biome check .","lint:fix":"biome check --write .","prepare":"husky","prepublishOnly":"npm run typecheck && npm test && npm run lint","install:global":"d=$(mktemp -d) && npm pack --pack-destination $d >/dev/null 2>&1 && npm install -g $d/*.tgz && rm -rf $d","link:dev":"ln -sf $PWD/dist/cli.js $(npm prefix -g)/bin/mypi-dev","unlink:dev":"rm -f $(npm prefix -g)/bin/mypi-dev"},"dependencies":{"js-yaml":"^4.1.0"},"peerDependencies":{"@earendil-works/pi-coding-agent":"^0.83.0","@earendil-works/pi-tui":"^0.83.0"},"devDependencies":{"@biomejs/biome":"^2.5.0","@earendil-works/pi-coding-agent":"0.83.0","@earendil-works/pi-tui":"0.83.0","@types/js-yaml":"^4.0.9","@types/node":"^22.0.0","husky":"^9.1.0","lint-staged":"^17.0.0","typescript":"^5.8.0","vitest":"^4.1.4"},"keywords":["pi","pi-coding-agent","extensions","skills","prompts"],"lint-staged":{"*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,json,jsonc}":"biome check --write"},"license":"MIT","gitHead":"611f2f9b3ce52ae6526f1f018fa0155c967ac792","types":"./dist/cli.d.ts","_id":"@bowerjames/mypi@0.2.0","_nodeVersion":"22.22.2","_npmVersion":"11.17.0","dist":{"integrity":"sha512-gix58gZrJCR/pDG8nyofJGtJDZk7/t27MPiRIwwmM7r8BA1Ytub/JL1SDGy1JzkHmxlM/0kmHccdtaCx/Vzu4Q==","shasum":"9925708e8001ab5bb55072f9ce4c243e73878778","tarball":"https://registry.npmjs.org/@bowerjames/mypi/-/mypi-0.2.0.tgz","fileCount":106,"unpackedSize":450236,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCFZA2ZSjE/Updk4rnwKcq0nCpFerAM18Z4R319XOUC4wIgWWZxOt5avhUzicom2p3gcchUS0jGKhXUflbQdhfWl5s="}]},"_npmUser":{"name":"bowerjames","email":"bower.james1996@gmail.com"},"directories":{},"maintainers":[{"name":"bowerjames","email":"bower.james1996@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/mypi_0.2.0_1785724744905_0.5559385182331771"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-03T12:07:04.564Z","modified":"2026-08-03T02:39:05.216Z","0.1.0":"2026-07-03T12:07:04.863Z","0.2.0":"2026-08-03T02:39:05.053Z"},"bugs":{"url":"https://github.com/BowerJames/mypi/issues"},"author":{"name":"James Bower","email":"james.bower@xanda.net"},"license":"MIT","homepage":"https://github.com/BowerJames/mypi#readme","keywords":["pi","pi-coding-agent","extensions","skills","prompts"],"repository":{"type":"git","url":"git+https://github.com/BowerJames/mypi.git"},"description":"Curated library of pi extensions, skills, and prompts with profile-based launching","maintainers":[{"name":"bowerjames","email":"bower.james1996@gmail.com"}],"readme":"# mypi\n\nA curated library of [pi](https://shittycodingagent.ai) extensions, skills, and prompt templates with profile-based launching.\n\n## Install\n\n```bash\nnpm install -g @bowerjames/mypi\n```\n\n`mypi` shells out to `pi` (resolved from your `$PATH`). The package declares `@earendil-works/pi-coding-agent` — which provides the `pi` binary — as a peer dependency, so a fresh install also installs `pi` automatically. If you already have `pi` installed (any way), npm reuses it and your existing `pi` keeps running.\n\n### Updating the global install\n\n```bash\nnpm install -g @bowerjames/mypi@latest\n```\n\nVerify with `mypi -h` (prints help).\n\n### Dev: installing from a local checkout\n\nFor unreleased branches, `dist/` is gitignored, so a local install is done by **rebuilding from a checkout, packing it into a tarball (which carries the built `dist/` via the `files` field), and reinstalling that tarball**:\n\n```bash\ngit checkout <branch>     # whichever branch you want installed (e.g. main)\ngit pull\nnpm install               # dev dependencies (TypeScript) needed to build\nnpm run install:global    # builds dist/ (via prepack), packs a tarball, reinstalls globally\n```\n\n`npm run install:global` is shorthand for:\n\n```bash\nnpm run build             # compile src/ -> dist/\nnpm pack                  # bundle bowerjames-mypi-<version>.tgz (ships dist/ via the \"files\" field)\nnpm install -g ./bowerjames-mypi-<version>.tgz\n```\n\nNotes:\n\n- `prepack` runs `npm run build` automatically during `npm pack`, so the tarball always carries a fresh `dist/` even though `dist/` is gitignored.\n- The global reinstall runs only `postinstall` (which `chmod +x`s `dist/cli.js`); the dev-only `prepare` (husky) does **not** run when installing a tarball, so the install does not require `node_modules/` to be present.\n- Verify with `mypi -h` (prints help) and `ls -l $(which mypi)`, which should resolve to the freshly reinstalled `dist/cli.js`.\n\n## Setup\n\nmypi works out of the box with **no config** — built-in profiles\n(`developer`, `reviewer`, `llm-wiki`, `wayfinder`) are always available. To add or override profiles,\ncreate a config:\n\n```bash\nmypi init\n```\n\nThis writes a starter `mypi-config.yaml` overlay. Edit it to define your own\nprofiles (or use `mypi configure` for an interactive editor). A user profile\nwith the same name as a built-in **replaces** it.\n\n## Usage\n\n```bash\n# Show help\nmypi --help\nmypi -h\n\n# Initialize a new config file\nmypi init\nmypi init --help\n\n# Launch with a named profile\nmypi --profile fullstack\n\n# Launch with a profile and pass a prompt\nmypi --profile fullstack \"Fix the auth bug\"\n\n# Uses the default profile if none specified\nmypi\n\n# Run pi directly with bundle expansion (no profile/config needed)\nmypi run -p --model zai/glm-5.2 --bundle mode \"Summarize this repo\"\nmypi run --help\n\n# Interactive config editor\nmypi configure\nmypi configure --help\n```\n\n## Running pi directly (`mypi run`)\n\n`mypi run` forwards every argument to `pi` with no profile or config required — handy when you just want one of mypi's bundles ad hoc:\n\n```bash\n# Expand a bundle's pi-extensions/skills/prompts into pi flags\nmypi run -p --model zai/glm-5.2 --bundle mode \"Summarize this repo\"\n# -> pi -p --model zai/glm-5.2 -e <mypi>/extension-bundles/mode/pi-extensions/mode/index.ts \"Summarize this repo\"\n\n# Multiple bundles, and prompt-only / skill-only bundles, all work the same way\nmypi run -p --bundle repo-explorer --bundle code-review-prompt\n\nmypi run --help\n```\n\n`--bundle <name>` (and the `--bundle=<name>` form) is expanded into that bundle's pi flags (`-e`/`--skill`/`--prompt-template`). Anything else is passed through untouched:\n\n- Multiple `--bundle` flags are allowed; each expands independently.\n- Path-like `-e ./local.ts` and other pi flags are forwarded as-is.\n- Everything else after `run` is sent straight to `pi`.\n\n`mypi run` uses no profiles, reads no `mypi-config.yaml`, and interprets no mypi-specific flags other than `--bundle`.\n\n## Configuration\n\nmypi ships built-in profiles and **works with no config file at all**. The\noptional `mypi-config.yaml` is an **overlay** that adds new profiles,\noverrides built-ins by name (replace), and optionally sets `default`. If you\njust want to tweak things, create one:\n\n```bash\nmypi init        # writes a starter overlay\n```\n\nExample overlay adding a custom `fullstack` profile (the built-ins\n`developer`, `reviewer`, `llm-wiki`, and `wayfinder` remain available alongside it):\n\n```yaml\ndefault: fullstack\n\nprofiles:\n  fullstack:\n    bundles:\n      - mode                   # plan/develop mode system + sticky root-branch\n      - code-review            # pre-PR review guidance + /code-review-model\n      - dynamic-skills         # live shell execution inside skills\n      - loop                   # repeat messages until a terminal condition\n      - repo-explorer          # explore third-party codebases into a /tmp cache\n      - overview               # repo overview and open issues\n    cmd: \"pi --model claude-sonnet-4-20250514 --tools read,bash,edit,write,grep,find,ls\"\n```\n\nTo override a built-in instead of adding a new name, define a profile with a\nbuilt-in name (e.g. `developer:`) — your definition replaces it wholesale.\n\nA **bundle** is a single unit that packages related pi-extensions, skills, and prompts together, loaded by one name. See [Bundled Resources](#bundled-resources) for the full list.\n\n### Fields\n\n| Field | Description |\n|-------|-------------|\n| `default` | Profile to use when none is specified on the CLI. Optional — falls back to the `developer` built-in if unset or if the config file is absent. |\n| `profiles.<name>.bundles` | List of bundle names from mypi's library |\n| `profiles.<name>.cmd` | Base pi command to execute. Bundle resources are injected automatically. |\n\nAny additional arguments passed on the command line are appended to the command.\n\n### How It Works\n\n`mypi` expands each named bundle to the on-disk paths declared in its manifest and injects the appropriate flags into your `cmd`:\n\n- a bundle's pi-extensions → `-e <path>`\n- a bundle's skills → `--skill <path>`\n- a bundle's prompts → `--prompt-template <path>`\n\nA bundle may declare `dependencies`; those bundles are auto-activated and their resources are emitted **first** (dependencies before dependents), so a skill whose `SKILL.md` uses dynamic `!` blocks always has the `dynamic-skills` extension loaded by the time it expands. Dependencies are resolved transitively and **deduplicated across the whole command** — listing a dep explicitly, or two bundles sharing a dep, never double-loads an extension (which would double-register its handlers). See [Bundle dependencies](#bundle-dependencies).\n\nYou control everything else (model, tools, thinking level, etc.) through the `cmd` field.\n\nBundles live under `extension-bundles/<name>/` inside the installed package. Each bundle's `index.ts` manifest declares its resources as paths relative to itself, so they resolve wherever npm installs the package. A bundle may also declare `dependencies` (other bundle names); those are auto-activated alongside it — see [Bundle dependencies](#bundle-dependencies). `mypi run` applies the same expansion via `--bundle` (see [Running pi directly](#running-pi-directly-mypi-run)).\n\n## Bundled Resources\n\nmypi ships 12 **bundles**, each under `extension-bundles/<name>/`. Most contain a single resource type; the `code-review` feature splits into an extension bundle and a prompt-only bundle (the prompt must be loadable without the extension for the review subprocess).\n\n| Bundle | Contains | Description |\n|--------|----------|-------------|\n| `mode` | pi-extension | Plan/develop mode system — `/plan`, `/develop`, `/mode <name>` commands. Root branch auto-defaults to the current git branch on first start and persists (sticky across resume); set/clear via `/root-branch` (clear is sticky and suppresses re-defaulting) |\n| `btw` | pi-extension | Non-blocking one-off side tasks on a throwaway in-memory clone — `/btw <task>` runs in parallel without interrupting the main stream, and its result is shown in the TUI but kept out of the main agent's context. Each task is wrapped in a guardrail so the clone scopes itself to the side task and does not continue the main agent's work |\n| `loop` | pi-extension | Repeat messages until a terminal condition — `/loop [--terminal-regex <re>] [--max-iter <n>] --loop [\"msg\",...]` resets the session to the original point after every item (and between iterations) via tree navigation, so each item runs from a clean slate and the session ends back at the anchor |\n| `dynamic-skills` | pi-extension | Live shell execution inside skills — inline `!\\`cmd\\`` and fenced ```!``` blocks are replaced with their output at skill load (covers `/skill:name` and `read` of `SKILL.md`) |\n| `render-raw` | pi-extension | Append a raw (unformatted) rendering of the last assistant reply — `/render-raw` injects a custom-typed copy of the reply rendered as plain text (literal markdown), shown in the TUI but kept out of the main agent's context. Additive, not a toggle; a re-run against the same reply is a no-op |\n| `code-review` | pi-extension | Appends a \"run an independent review before a PR\" system-prompt section and provides `/code-review-model` to set the recommended review model (defaults to the active session model) |\n| `code-review-prompt` | prompt | Independent code review of an issue's implementation on a branch. Usage: `/code-review <issue_number> <branch_to_review> <target_branch_of_pr>` |\n| `repo-explorer` | skill | Explore third-party codebases/libraries/frameworks without cluttering the active workspace — clones into a `/tmp/repos/` cache and reuses existing checkouts. Auto-activates `dynamic-skills` (its `SKILL.md` uses dynamic `!` shell blocks) |\n| `overview` | prompt | Overview of the repository, core components, and open issues |\n| `terminal-status` | pi-extension | Reflect session state in the terminal tab title — on `agent_start` sets the title to `working`, on `agent_settled` sets it to `idle`. Works in any terminal (TUI mode) by emitting the OSC 1 tab-title escape sequence (`\\033]1;<title>\\007`) to stdout. Best-effort: a failed write is swallowed. Note: pi's own window-title writes (OSC 0) can momentarily override the tab title on startup/session change |\n| `llm-wiki` | pi-extension | Turn the agent into a wiki manager for an [OKF](https://github.com/GoogleCloudPlatform/knowledge-catalog/blob/main/okf/SPEC.md) wiki (Karpathy's [LLM-wiki pattern](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f)) — `/wiki-root`/`/wiki-spec` configure the bundle root and per-wiki spec doc (defaults `wiki/` and `/SPEC.md`), the spec is **auto-injected** into the system prompt each turn, `/wiki-init` scaffolds empty assets, and `/wiki-ingest`/`/wiki-query`/`/wiki-lint` inject the operating-model guidance |\n| `wayfinder` | pi-extension | Chart a large, foggy effort as a **map of decision tickets** on the issue tracker, resolving one at a time until the way to the destination is clear (inspired by [mattpocock/skills `wayfinder`](https://github.com/mattpocock/skills/tree/main/skills/engineering/wayfinder)). `/wayfinder` grills the destination and creates the map + frontier tickets; `/wayfinder <ticket-ref>` points a session at a ticket (the model auto-detects its type); `/to-spec <map-ref>` converts a closed map into a `wayfinder:spec` successor issue (PRD hand-off). Tracker is autodetected (GitHub/GitLab/local `/tmp/.wayfinder/<repo>/`), overridable via `cwd/.mypi/wayfinder-tracker.sh`. Five primitives: Map, Decision, Prototype (worktree under `~/.worktrees/`), Research (user-spawned), Task. `/implement <ref>` turns a closed spec into merged, reviewed code — kickoff slices it into Development units (then cuts the `implement/<spec-slug>` trunk + creates the Implementation Map); working an open ticket drives Development → Code Review → Merge, with Follow-Up Development and Full Review. Six implementation primitives: Implementation Map, Development, Code Review, Follow-Up Development, Merge, Full Review |\n\n### Bundle dependencies\n\nBundles are **composable**: a bundle's manifest may declare a `dependencies` field (a list of other bundle names). When you select a bundle — via a profile's `bundles` list or `mypi run --bundle <name>` — mypi **auto-activates its full transitive dependency closure**, so you only ever name the bundles you actually want.\n\nResolution rules:\n\n- **Dependencies-first.** A dependency's resources are always emitted before those of the bundle that needs them. For example, selecting `repo-explorer` (a skill whose `SKILL.md` uses dynamic `!` shell blocks) auto-activates `dynamic-skills` (the extension that expands those blocks) and emits its `-e` flag first.\n- **Transitive.** If `a` depends on `b` and `b` depends on `c`, selecting `a` activates all three (`c`, then `b`, then `a`).\n- **Deduplicated across the whole command.** If two bundles share a dependency, or you list a dependency explicitly alongside a bundle that pulls it in, the shared dependency is loaded exactly once — never double-registering an extension's handlers via duplicate `-e` flags.\n- **Silent in `mypi configure`.** The editor only toggles the bundles you name; dependencies are pulled in at launch time, so you do not need to (and should not) select a dep explicitly.\n- **Fail-fast on cycles / missing bundles.** A circular dependency raises `Circular bundle dependency: a -> b -> a`; a dependency that names a non-existent bundle surfaces the standard \"Bundle not found\" error.\n\n### Dynamic Skills\n\nThe `dynamic-skills` extension makes skills *live*: shell commands embedded in a `SKILL.md` body are executed at load time and replaced with their output. Two syntaxes are supported:\n\n| Syntax | Scope | Example |\n|--------|-------|---------|\n| `` !`command` `` | Inline — single line, no newline crossing | `` branch !`git rev-parse HEAD` `` |\n| ```` ```! ```` fence | Block — multi-line program (newlines preserved) | see below |\n\n````markdown\n```!\nmkdir -p ~/.explore/repos\nls ~/.explore/repos\n```\n````\n\nExpansion runs on **both** skill-entry paths: the `/skill:<name>` command (intercepted before pi's built-in expansion) and the model `read`ing a registered `SKILL.md` (intercepted via the `read` tool result).\n\n**Execution semantics:**\n\n- Commands run in `process.cwd()` (`/skill:name` path) or the session `cwd` (`read` path), via `sh -c` (POSIX) or `powershell.exe -Command` (Windows).\n- The full block body runs as one shell program, so multi-line state persists within a block (the `mkdir` then `ls` example works). Multiple blocks run sequentially, in source order.\n- Default timeout is **120 s**, overridable per skill via the `shell-timeout` frontmatter field (in seconds; `0` disables it; non-numeric/negative/`NaN`/`Infinity` values fall back to the default).\n- Combined stdout + stderr is truncated to **50 KB / 2000 lines** (tail-kept) so a failing `npm test` cannot blow the context budget.\n- Failures are **inlined, not fatal** — a non-zero exit becomes `[Shell error: exit code N]\\n<stderr>` and a timeout becomes `[Shell error: timed out after Ns]`; the rest of the body still reaches the model.\n- Block output that happens to contain literal `` !`...` `` is never re-executed (mask-and-restore).\n- Skills are trusted local content; there is no prompt-injection sanitisation of `$ARGUMENTS`-style input (none is supported here anyway).\n\nWhen a skill body has no shell syntax, output is byte-identical to pi's built-in expansion, so the extension is safe to enable for any existing skill collection.\n\n### Code Review\n\nThe `code-review` bundle moves the pre-PR review guidance out of shared `AGENTS.md` files so it only affects agents that opt in by enabling the bundle. When enabled it:\n\n- Appends a \"## Code Review\" section to the system prompt each turn, instructing the agent to run an independent review before opening a pull request:\n\n  ```\n  mypi run -p --model <model> --tools read,grep,find,ls --bundle code-review-prompt \"/code-review <issue_number> <branch_to_review> <target_branch_of_pr>\"\n  ```\n\n  The review runs with read-only tools (`read,grep,find,ls`) for defense-in-depth, even though the `code-review-prompt` prompt itself instructs the reviewer never to apply fixes.\n- Provides `/code-review-model [<model>]` to set the recommended review model. With no argument it clears the configured model. The choice is persisted across sessions (restored on `/resume`, `/new`, `/reload`).\n- Falls back to the **active session model** (`provider/id`) when no model is configured, so the guidance appears out of the box.\n- Shows a `🔍 review:` status indicator in the footer: the explicitly-configured model in the accent color, and the active-fallback model in a warning color (prefixed `(active)`).\n\nBecause the review subprocess is launched via `mypi run --bundle code-review-prompt` (the prompt-only bundle, which loads no extension), the reviewer agent does not re-append this section — only the interactive session that enables the `code-review` bundle sees the guidance.\n\n### btw\n\nThe `btw` extension registers a single `/btw <task>` command for non-blocking side tasks. When invoked it builds a **throwaway in-memory clone** of the current agent — same context, effective system prompt, model, and built-in tools — runs the task to completion, shows the final assistant message in the TUI, then drops the clone. The intent is to dispatch single tasks that share the main agent's context but run in parallel without interrupting its stream, e.g. while a code-review agent is describing a non-blocking issue:\n\n```\n/btw create an issue for that\n```\n\nThis creates the issue in the background while the main agent continues toward blocking fixes or the PR.\n\n**How it works:**\n\n- The `/btw` command handler snapshots the parent's conversation (`buildSessionContext`), effective system prompt (`getSystemPrompt`), model, model registry, thinking level, and active tools, then returns immediately — the clone runs in the background and never blocks the main agent.\n- The clone is built with `createAgentSession` using `SessionManager.inMemory()`, so nothing is persisted. Its system prompt is the parent's effective prompt verbatim (which already encodes contributions from `mode`, `code-review`, `AGENTS.md`, and skills), and it is seeded with the full parent conversation (compaction/branch summaries are converted to user messages so prior context survives).\n- The task text is wrapped in a `<btw-task>` guardrail before being sent to the clone. Because the clone inherits the parent's full conversation and effective prompt — which encode the main agent's in-progress work — it could otherwise decide to \"help finish\" that work rather than just answering the side task. The wrapped message is the most recent instruction in the clone's context, so it dominates steering: it frames the parent conversation as context-only and directs the clone to complete only the side task, then stop. The wrap is model-facing only — the TUI preview/status/error paths still show the raw task text.\n- When the clone goes idle, the final assistant text is shown via `ctx.ui.notify(...)` — which writes directly to the chat scrollback but **never touches the session manager**, so the result is visible yet **kept out of the main agent's LLM context**. While running, a `⚙ btw: N running` indicator is shown in the footer.\n- The full result text is persisted to a temp file (`/tmp/btw-<uuid>.md`), and the in-chat notification prepends a `↳ <path>` pointer line above the body. The body is capped at ~50 KB so a runaway clone cannot flood the scrollback, but the full answer is always recoverable from the file (and the pointer line is itself never truncated).\n- Multiple `/btw` tasks may run in parallel (no cap). Every live clone is aborted and disposed automatically when the main session shuts down (`/new`, `/resume`, `/reload`, `/fork`, `/switchSession`, or quit).\n\n**v1 limitations (accepted):**\n\n- The clone reproduces the parent's **built-in tools only** (`read`, `bash`, `edit`, `write`, `grep`, `find`, `ls`), intersected with the parent's active set. Extension-registered custom tools, event handlers, and slash commands are not re-instantiated inside the clone. The built-in `bash` tool covers the primary use case (e.g. `gh issue create`).\n- Result display uses `notify`'s info path, which coalesces consecutive status lines: if two btw tasks complete with no other chat activity between them, only the latest result line is shown. The common case (btw running *during* the main stream, where the main agent's messages land between completions) is unaffected. (The full text of every result is still persisted to `/tmp/btw-<uuid>.md`, so a coalesced-away line remains recoverable via its pointer file.)\n\nEnable it by adding `btw` to a profile's `bundles` list.\n\n### loop\n\nThe `loop` extension registers a single `/loop` command that repeats a sequence of messages to the agent until a terminal condition is met. Within each pass (an iteration over the `--loop` array), **every item runs independently** — the session is reset back to the original point after each item, so item N does not see item N−1's output (not a continuous flow within one conversation). The session is left back at the anchor when the loop exits.\n\n```\n/loop [--terminal-regex <source>] [--max-iter <n>] --loop [\"msg\", ...]\n```\n\n| Flag | Required | Default | Description |\n|------|----------|---------|-------------|\n| `--loop` | Yes | — | JSON array of strings sent to the agent in order each iteration, each from a clean anchor |\n| `--max-iter` | No | `10` | Maximum number of iterations (hard cap; guarantees termination) |\n| `--terminal-regex` | No | — | Regex **source** matched against the final assistant text of each iteration; a match stops the loop early |\n\nThere is **no goal argument** — the command is flags-only.\n\nExample:\n\n```\n/loop --terminal-regex \"<\\/end>\" --max-iter 10 --loop [\"/plan\",\"/evaluate-plan\"]\n```\n\n**How it works:**\n\n- Each iteration sends every `--loop` item in order via `sendUserMessage`, awaiting the agent going idle between items. After EACH item the session is reset back to the anchor, so items run independently — item N does **not** see item N−1's output (e.g. `/evaluate-plan` does not see `/plan`'s output).\n- The iteration's final (last) item's assistant text is read; if `--terminal-regex` matches, the loop stops. Otherwise the loop runs again, starting from the anchor.\n- The **reset** is a same-session tree navigation back to the entry that was the leaf when the command was invoked (`navigateTree` with branch summary disabled). Because this stays in one session file, each item/iteration becomes a sibling branch off that anchor and the conversation is restored to the original point — a clean slate — without starting a new session.\n- The last item's reset serves double duty as the between-iteration reset, so the session always ends back at the anchor when the loop exits (terminal match or max-iter reached). The sole exception is an explicit user cancellation of the tree navigation.\n- A `🔄 loop: N/M` indicator is shown in the footer while running, and start / per-iteration / terminal notifications are surfaced in the chat.\n\nThe loop always terminates: `--max-iter` is a hard cap (default 10), and `--terminal-regex` provides an early exit.\n\n**Argument parsing:** tokens are whitespace-separated; a token beginning with `\"` or `'` is read literally (delimiters stripped, so backslashes/`$`/`&` survive — wrap `--terminal-regex` in quotes if it contains spaces). Bare tokens are bracket-aware, so a JSON array can be typed verbatim even with internal spaces and quoted strings (`--loop [\"/plan\", \"/evaluate-plan\"]`). Unknown tokens (e.g. an accidental trailing goal) are an error.\n\n**Accepted limitations:**\n\n- The reset is **conversation-level**: in-memory state of other extensions (e.g. a toggled `/plan`) is not reset, since the loop stays in one session.\n- The terminal regex matches the **final assistant text** of the iteration, so the last `--loop` item should be one that produces an assistant response for the regex to be meaningful.\n\nEnable it by adding `loop` to a profile's `bundles` list.\n\n### render-raw\n\nThe `render-raw` extension registers a single `/render-raw` command that appends a **raw, unformatted** rendering of the last assistant reply to the chat. The model's markdown is shown literally — `**bold**` keeps its asterisks, headings keep their leading `#`, code fences keep their backticks, etc.\n\nIt exists because pi renders every assistant text block through its built-in `Markdown` component and exposes no extension hook to toggle a \"raw\" mode or swap the assistant message renderer. The only way to control how a message renders is a renderer keyed by message `customType`, which only applies to custom-typed messages — so `render-raw` injects a **copy** of the reply under a custom type and renders that copy with a plain `Text` component.\n\n**How it works:**\n\n- `/render-raw` finds the last `role === \"assistant\"` message via `ctx.sessionManager.getEntries()` and sends a custom message (`customType: \"render-raw\"`, `display: true`) whose content is that reply's text, via `pi.sendMessage(...)`.\n- A registered `render-raw` message renderer returns a plain `Text` (with a small dim `raw markdown` label) instead of `Markdown`, so the markdown syntax is shown verbatim.\n- The injected custom message is **excluded from the LLM context** via a `context` event filter — a `CustomMessageEntry` participates in context by default, so this filter is required to avoid duplicating the reply into the conversation.\n\n**Additive, not a toggle.** The original nicely-formatted assistant message stays in place; `/render-raw` appends a raw copy below it. It cannot replace or hide the original (there is no `SessionManager.removeEntry`).\n\n**Dedupe.** `SessionManager` exposes no entry removal, so a naive toggle would stack duplicate raw copies. Instead, `/render-raw` only appends a new copy when the last assistant reply's text differs from the one already rendered (tracked in memory and reconstructed from the session on `/reload`, `/resume`, `/new`). Re-running `/render-raw` for the same reply notifies \"last reply is already rendered raw\" instead of duplicating; after a new reply it renders again.\n\nEnable it by adding `render-raw` to a profile's `bundles` list.\n\n### LLM Wiki\n\nThe `llm-wiki` extension turns the agent into a **wiki manager** for an\n[Open Knowledge Format (OKF) v0.1](https://github.com/GoogleCloudPlatform/knowledge-catalog/blob/main/okf/SPEC.md)\nwiki, following Karpathy's [LLM-wiki pattern](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f):\nthe agent incrementally builds and maintains a persistent, interlinked\nmarkdown knowledge base — you curate sources and ask questions; it does all\nthe summarising, cross-referencing, and bookkeeping that makes a knowledge\nbase compound over time.\n\nA built-in `llm-wiki` profile ships with the wiki bundle enabled, plus the\n`mode` and `repo-explorer` bundles (the latter pulls in `dynamic-skills`\nautomatically as a dependency):\n\n```bash\nmypi --profile llm-wiki\nmypi run --bundle llm-wiki   # ad hoc, no profile/config needed\n```\n\n**Two configurable values** (set via slash commands, persisted across\nsessions, restored on resume):\n\n| Value | Default | Meaning |\n|-------|---------|---------|\n| `wiki-root` | `wiki` (project-relative) | The OKF bundle root — a directory tree of markdown concept files with YAML frontmatter, `index.md`/`log.md`, and cross-links |\n| `wiki-spec` | `/SPEC.md` (wiki-root-relative, OKF §5.1) | A per-wiki **purpose & conventions** doc — the runtime context that tells the agent *which* wiki it is managing (Karpathy's \"schema\" layer) |\n\nBoth auto-default on the first session start (write-once, sticky across\nresume); an explicit clear is also sticky and suppresses the default.\n\n**Auto-injection.** Each turn the extension reads `<wiki-spec>` and appends a\n`## Wiki Manager` section to the system prompt that first directs the agent to\n**read the full [OKF v0.1 spec](https://github.com/GoogleCloudPlatform/knowledge-catalog/blob/main/okf/SPEC.md)**\nonce per session (fetching it via `curl` before any other wiki work, and\n**stopping to inform the user** if it cannot be retrieved — wiki work is\nblocked until the spec can be read). The section then carries: the OKF format\nessentials (required `type` frontmatter, reserved filenames, leading-`/`\nbundle-relative links, `# Schema`/`# Examples`/`# Citations` conventions),\nthe ingest/query/lint operating model, and the spec's contents verbatim. So\nthe agent always knows the format *and* the specific wiki's purpose.\n\n**Commands:**\n\n| Command | Purpose |\n|---------|---------|\n| `/wiki-root [<path>]` | Set the wiki-root (no arg clears; re-defaults to `wiki`) |\n| `/wiki-spec [<path>]` | Set the wiki-spec path (no arg clears; re-defaults to `/SPEC.md`) |\n| `/wiki-init` | Scaffold the wiki-root and create **empty** `index.md`, `log.md`, and the spec (idempotent; creates assets only — no seeded content) |\n| `/wiki-ingest` | Inject the ingest workflow guidance (one-off message) |\n| `/wiki-query` | Inject the query workflow guidance (one-off message) |\n| `/wiki-lint` | Inject the lint workflow guidance (one-off message) |\n\nA typical first run: `mypi --profile llm-wiki`, then `/wiki-init`, open the\nempty spec and describe what the wiki is for, then `/wiki-ingest` and start\nadding sources. A `📚 wiki: <root>` indicator is shown in the footer while a\nwiki-root is active.\n\nThe agent maintains the wiki with its **built-in** tools (`read`/`write`/\n`edit`/`bash`); the extension supplies only the operating context and the\nbootstrap/config commands. It has no bundle dependencies.\n\n### Wayfinder\n\nThe `wayfinder` extension turns the agent into a **wayfinder**: it charts a\nlarge, foggy effort — too big for one agent session, where the way from here\nto the goal isn't visible yet — as a **shared map of decision tickets** on the\nrepo's issue tracker, then resolves them one at a time until the way to the\ndestination is clear (inspired by [mattpocock/skills\n`wayfinder`](https://github.com/mattpocock/skills/tree/main/skills/engineering/wayfinder)).\nIt **plans, it doesn't do**: every ticket resolves a *decision* — a question to\nsettle, not a slice of a build to execute.\n\nA built-in `wayfinder` profile ships with the wayfinder bundle enabled, plus\nthe `mode` and `repo-explorer` bundles:\n\n```bash\nmypi --profile wayfinder\nmypi run --bundle wayfinder   # ad hoc, no profile/config needed\n```\n\n**Commands** (all three one-shot doctrine injectors — no persisted state, no\nper-turn system-prompt suffix, no footer). Each **clears the conversation\nfirst** so its doctrine is the agent's entire frame on a clean slate — the\nprior conversation is preserved as the parent session (recoverable via\n`/resume`). If the agent is mid-stream, the command **refuses** and asks you to\nwait and re-run once idle:\n\n| Command | Purpose |\n|---------|---------|\n| `/wayfinder` | Grill the destination, then create the map ticket and the primitive tickets for the frontier |\n| `/wayfinder <ticket-ref>` | Point this session at a specific ticket; the model auto-detects its primitive type and acts accordingly |\n| `/to-spec <map-ref>` | Convert a **closed** map into a `wayfinder:spec` **successor** issue — a PRD-style hand-off. Synthesises the map's Decisions + every closed child's resolution (+ codebase exploration) into the verbatim 7-section template, published in one shot (no confirm gate); re-run overwrites in place. Never writes the repo — the spec lives only as the issue body |\n| `/implement <ref>` | Turn a **closed** `wayfinder:spec` into merged, reviewed code. Auto-disambiguates: a closed spec → **kickoff** (propose a slicing, then on confirm cut the `implement/<spec-slug>` trunk + create the Implementation Map and Development children); any open implementation ticket → **work** it through its lifecycle (Development → Code Review → Merge, with Follow-Up Development and Full Review). Reviews are in-band (active-session model, user gate). Writes the repo (branches/merges) on all trackers |\n\n**Five primitives** (each a child issue of the `wayfinder:map` parent, or a\n`Type:` line locally):\n\n| Primitive | Resolved by | Closed when |\n|-----------|-------------|-------------|\n| **Map** | The index: Destination · Notes · Decisions so far · Not yet specified · Out of scope | The map **and** all its child tickets are closed |\n| **Decision** | A relentless one-question-at-a-time grilling (recommended answer each); the agent never answers for the human | The decision is made |\n| **Prototype** | Scaffold a worktree at `~/.worktrees/<map-slug>/<ticket-slug>/` and build a cheap artifact to react to | The user confirms a design, or new primitives are spun off to push the fog back |\n| **Research** | Investigate against primary sources and capture findings — **not** auto-launched; the user spawns a session and points it at the ticket | The fog is pushed back enough that the correct new primitives can be created |\n| **Task** | Manual work that must precede a decision (provision access, sign up for a service, move data); the agent drives where it can, else hands over a checklist | The work is done (the resolution records what was done + any resulting facts) |\n\n**Tracker autodetection.** The extension picks the tracker from the\nenvironment (it is not configured via a slash command): GitHub Issues for a\n`github.com` remote, GitLab Issues for a `gitlab.com` remote, otherwise a\nlocal-markdown fallback at `/tmp/.wayfinder/<repo>/` (ephemeral — `<repo>` is\nthe cwd's directory name, wiped on reboot, never committed). A self-hosted\nescape hatch: if `cwd/.mypi/wayfinder-tracker.sh` exists and prints one of\n`local`/`github`/`gitlab`, that wins. The detected tracker is memoised for the\nsession and surfaced via a `Wayfinder tracker: <kind>` notification.\n\nThe agent does all tracker I/O with its **built-in** tools (`bash` → `gh` /\n`glab` / file writes); the extension supplies only the operating doctrine,\ncomposed with the correct tracker operations. Grilling is folded into the\ndoctrine (no separate command). It declares `terminal-status` as a bundle\ndependency (not in profiles), so the terminal tab always reflects session\nstate whenever wayfinder is active.\n\n**Map → spec hand-off.** When the map and all its children close, `/to-spec\n<map-ref>` converts it into a `wayfinder:spec` **successor** issue (linked both\nways — produced, not a child) — a PRD-style hand-off adopting\n[mattpocock/skills `to-spec`](https://github.com/mattpocock/skills/tree/main/skills/engineering/to-spec)'s\n7-section template verbatim (Problem · Solution · User Stories · Implementation\nDecisions · Testing Decisions · Out of Scope · Further Notes). It synthesises\nfrom durable inputs only (the map's Decisions + every closed child's resolution\n+ targeted codebase exploration — no live conversation), ingests prototype /\nresearch findings as a digest so the spec is self-contained, and publishes in\none shot with **no confirm gate**; re-running overwrites the spec body in place\n(same successor link, stable URL). The spec lives **only** as the issue body —\nit never writes the repo (no `docs/specs/` mirror). This is the spec hand-off — `/implement` takes it from there.\n\n**Spec → implementation stage.** `/implement <ref>` turns a closed `wayfinder:spec` into merged, reviewed code — a third one-shot doctrine injector (same clear-then-inject, stateless) that auto-disambiguates by the reference it is given:\n\n- **`/implement <closed-spec-ref>` → kickoff.** Reads the spec, proposes a coarse slicing into independent Development units + an ordering, and waits for a yes/no. Nothing is created until confirmed; on confirm it cuts the per-effort integration trunk `implement/<spec-slug>` **from the current branch** (recorded in the Implementation Map as the base), then creates the Implementation Map, the Development children, and a Full Review child.\n- **`/implement <open-ticket-ref>` → work.** Dispatches by primitive type per a transition table: Development (switch to the unit's worktree+branch, do the work, commit, spawn a Code Review); Code Review (in-band review, findings + non-binding recommendation, then a user gate: approve → Merge, rework → Follow-Up Development); Follow-Up Development (rework on the parent Dev's branch, then re-review); Merge (`git merge --no-ff` into the trunk, cleanup, close the Dev); Full Review (review the integrated trunk vs the full spec; approve → close the map and leave the trunk→base merge to the user; rework → fresh Development children).\n\n**Six implementation primitives** (each a child of the `wayfinder:implementation-map` parent):\n\n| Primitive | Label | Closed when |\n|-----------|-------|-------------|\n| **Implementation Map** | `wayfinder:implementation-map` | A passing Full Review (it and all children closed) |\n| **Development** | `wayfinder:development` | Merged (the unit anchor Merge consumes) |\n| **Code Review** | `wayfinder:code-review` | Self, at its approve/rework gate |\n| **Follow-Up Development** | `wayfinder:follow-up-development` | Self, once its rework is committed |\n| **Merge** | `wayfinder:merge` | Self, after landing the unit on the trunk |\n| **Full Review** | `wayfinder:full-review` | A final approve (closes itself + the map) |\n\n**Branching.** One namespace keyed on the spec slug: trunk `implement/<spec-slug>` (cut from the current branch at kickoff, recorded as the base); dev-unit branch `dev/<spec-slug>/<n>-<slug>`; dev-unit worktree `~/.worktrees/<spec-slug>/<n>-<slug>` (materialised lazily, only when a unit starts). `<n>` is the raw ticket number (no padding). Merges are non-fast-forward; a hard conflict halts in place (never `--ours`/`--theirs`/`--abort`, never commits markers).\n\n**Reviews are in-band doctrine** — the agent becomes the reviewer for one turn using the active session model (switch with `/model`), posts findings + a non-binding recommendation, and stops; pass/fail is always a user gate. The standalone `code-review`/`code-review-prompt` bundles are deliberately not reused.\n\nUnlike `/to-spec`, `/implement` **writes the repo** (branches/merges) on all three trackers. On the local tracker, tickets are ephemeral scratch under `/tmp/.wayfinder/<repo>/` and the merged branch in cwd is the sole durable record of a finished effort. The final trunk→base merge is the user's (Full Review approves; it does not land).\n\n## Development\n\n```bash\nnpm install          # installs pi packages + tooling as devDependencies\nnpm run typecheck    # tsc --noEmit over src/ (including extension bundles)\nnpm run lint         # biome check (lint + format + import sorting)\nnpm run lint:fix     # biome check --write (applies auto-fixes)\nnpm test             # vitest run\nnpm run build        # compile src/ to dist/ (extensions ship as raw .ts)\nnpm link             # test locally\n```\n\n### Git hooks\n\nPre-commit hooks (via [husky](https://typicode.github.io/husky/)) run before\nevery `git commit`:\n\n1. **Biome** via [lint-staged](https://github.com/lint-staged/lint-staged) —\n   runs `biome check --write` on staged JS/TS/JSON files and **re-stages** the\n   fixed files, so formatting / import-sort / safe-fix violations land in the\n   same commit. Unfixable lint errors exit non-zero and block the commit.\n   Staged files Biome doesn't handle (e.g. `.md`) are skipped automatically.\n2. **`tsc`** — whole-project typecheck (`tsc -p tsconfig.check.json`) over\n   `src/` (including the extension bundles).\n\nHooks are installed automatically by the `prepare` script when you run\n`npm install`. To bypass the hooks for a single commit:\n\n```bash\ngit commit --no-verify\n```\n\nThe pi packages (`@earendil-works/pi-coding-agent`, `@earendil-works/pi-tui`)\nare declared as `devDependencies` so that `tsc`, Biome, and vitest can resolve\nthem locally. At runtime pi loads them from its own bundled copies via its\nloader alias map.\n","readmeFilename":"README.md"}