kstack = "Krishnan's Stack". Named as an homage to pstack, which it is heavily inspired by.
Krishnan's personal extensions for Pi.
Pi extensions execute with your full user permissions. Review extension code before installing it.
| Extension | Description |
|---|---|
steering-swap |
Swaps Enter and Alt+Enter in the main editor while Pi is working (Enter queues a follow-up, Alt+Enter steers) without breaking Enter for idle submission, autocomplete, or inline prompts. |
openrouter-floor |
Sends every OpenRouter request as the model's :floor variant and records bounded, redacted rewrite and service-tier observations. Users keep selecting plain model IDs; models that already carry a variant pass through. |
kstack-router |
Optional front door: `/kstack [--route ] [--single |
session-archive |
Provides /sessions, a searchable unified active/archive browser that immediately archives or restores one session, while preserving confirmed bulk archive commands and local SQLite/FTS5 search. |
graphite-stacked-prs |
Validates and publishes local Graphite stacks (gt) and lands complete Graphite stack prefixes through /land. Automatically claimed in Graphite mode. |
github-stacked-prs |
Publishes local Git branch stacks as chained GitHub PRs and lands confirmed prefixes through /land, with exact force-with-lease republication. Enabled by default for the Git backend. |
handoff |
Opens a lean replacement session from one editor confirmation, optionally archiving the old session first and selecting a model and effort, then gives read-only tools for normalized, on-demand access to the linked history. |
parallel-agents |
Runs bounded isolated read-only child agents for Simplify through the same shared live TUI pane, cancellation path, and persisted subagent sessions used by panel review. |
panel-review |
Runs 2–5 isolated read-only reviewer subagents in parallel against the current Git changeset, a pinned jj working-copy snapshot (including secondary workspaces), or a GitHub PR snapshot, then synthesizes a lead-review verdict with a live multi-agent TUI dashboard. |
plan-implement |
Runs a planner and optional adversary in visible Herdr panes, gates the final plan, implements on a dedicated Git/Graphite branch or jj bookmark, runs panel review, fixes findings, and publishes a draft PR with reviewer recommendations. Supports local stacks, managed worktrees, --plan-only, and a hosted --fast implementer. |
pr-autopilot |
Bounded post-PR autopilot using only tiny models (GPT-5.6 Luna, GLM 5.2, DeepSeek V4 Flash). Drives an open PR frontier through comments-first triage, CI watch, and fix → push → recheck, stopping at merge-ready. Never auto-merges, never rebases shared history. |
land |
Confirmation-gated landing of exact, merge-ready GitHub PR heads. In jj mode, selecting an upper stacked PR lands the full prefix from trunk through that PR. Land reuses pr-autopilot readiness, respects branch protection and merge queues, and verifies remote merge state. |
jj-stacked-prs |
Publishes linear jj bookmarks as GitHub-native stacks and lands a complete stack with one asynchronous GitHub stack merge. Pi can publish or land through a model tool after an explicit user request; command-driven mutations retain standard confirmation. |
Writable workstreams use a dedicated kstack/<task-slug> Git/Graphite branch or jj
bookmark and record coherent increments with the configured backend. Git
current-checkout runs stop on a dirty tree; jj runs use automatic snapshots.
No backend pushes or publishes without user authorization. An explicit
request to publish the current jj stack is sufficient authorization for
jj_stack_publish; command workflows retain their confirmation. Read-only
routes do not create workstreams.
| Skill | Description |
|---|---|
create-pi-extension |
Designs and implements Pi extensions using the installed documentation, repository patterns, lifecycle/security ground rules, and an incremental verification checklist. |
create-skill |
Creates, tests, and improves Pi skills: draft, headless with-skill vs baseline eval runs, grading, benchmark aggregation, a static review page, and description/trigger optimization. |
find-reviewers |
Recommends the 2–5 best pull-request reviewers for any git change by analyzing commit history, CODEOWNERS, adjacent-domain ownership, and author identities, returning a prioritized, evidence-backed list with a review order. |
adversarial-planning |
Drafts an implementation plan and debates it for up to three rounds with a distinct read-only adversary in a visible Herdr pane. Explicit invocation only. |
arena |
Spawns N parallel candidates at the same task, cross-judges them, picks the strongest as a base, grafts the best parts from the losers, and verifies the synthesized result. |
architect |
Grounds a change, explores structurally distinct caller-first designs through Arena, and implements against the synthesized type and module contract. Explicit invocation only. |
swarm |
Fans out N parallel workers across different slices of a task (partition, race, or mix), aggregates results, and returns one consolidated report. |
git-worktrees |
Creates, inspects, repairs, and safely cleans up Git linked worktrees managed beneath ~/.pi/kstack/worktrees, with dirty-state and ownership checks before removal. |
fix-merge-conflicts |
Resolves merge, rebase, or jj conflicts non-interactively, then validates the build and tests before finalizing. |
write-pr |
Writes a crisp pull-request title and description from a standalone branch or exact stacked-PR slice, updating the open PR or creating a draft. |
simplify |
Runs parallel read-only review lenses on scoped code changes, then applies targeted cleanup to reduce complexity while preserving behavior. |
unslop |
Removes generic AI tells from prose while preserving the intended voice, facts, and audience. |
technical-writing |
Writes and reviews clear technical docs using Diátaxis, Google developer style, STE, and Global English clarity rules. |
typescript-best-practices |
Applies TypeScript type-system discipline, boundary validation, constructive modeling, and safe narrowing patterns when reading or editing .ts or .tsx files. |
blast-radius |
Traces cross-boundary risks in a focused change and proves its safety-critical assumption with executable evidence. |
reflect |
Reviews a selected Pi session through independent judgment, tooling, and contrarian lenses, then proposes user-approved, durable workflow improvements. |
decision-trail |
Keeps an opt-in, append-only TSV decision log (what, why, evidence, result) for long-running or unattended work, then audits it against the session transcript with a cross-model review. Explicit invocation only. |
personalize |
Mines the user's own session history from any coding agent (Pi, Claude Code, Codex, Cursor) for durable, evidence-backed preferences and applies approved edits to a target such as AGENTS.md. |
how |
Explains code structure, ownership, and runtime flow through fast, allowlisted exploration models. |
why |
Investigates design rationale through fast, allowlisted evidence gathering and reports direct evidence separately from inference. |
recall |
Reconstructs recent working context across Pi sessions, reconciles it with live Git/PR state, and returns a tight brief with thread statuses and a concrete resume point. Read-only. |
setup-kstack |
Interactively discovers and validates Pi model assignments, previews a user-level kstack.json update, and writes it only after approval. |
tdd |
Makes a cheap failing-before / passing-after regression check before fixing a bug, and skips a new test when the path is expensive or unclear. |
thermo-nuclear-code-quality-review |
Extremely strict maintainability review for abstraction quality, giant files, and spaghetti-condition growth. Explicit-only; panel-review applies the same canonical lens to every reviewer and synthesis model. |
prslack and prstack format one GitHub PR or a published PR
stack as Markdown with GitHub addition and deletion counts. They are sourceable
POSIX shell functions and do not depend on Pi or Kstack at runtime. Install the
command wrappers separately with:
./shell/prslack/install.shThe installer writes to ~/.local by default and does not change shell startup
files. See the shell tool README for function-loading
instructions and options.
Short headless Kstack child agents persist native Pi sessions under ~/.pi/kstack/subagents/. The managed flat store protects active runs and retains at most 500 sessions, pruning inactive sessions oldest-first. Inactive means that the child is no longer running, not that its work succeeded. These sessions do not appear in normal /resume results; reopen one with pi --session <absolute-jsonl-path>. Panel-review verdicts expose reviewer and lead evidence paths when expanded.
Use search_subagent_history to search retained inactive sessions. Use read_subagent_history with an exact session UUID to read normalized entries or raw JSONL chunks. Both tools validate the source file and lease before returning content. They never change source files or leases. Their disposable FTS5 cache lives at $PI_CODING_AGENT_DIR/cache/kstack-subagent-history/index.sqlite3 and refreshes on demand. Search results are snapshots: retention can remove a source before a later read, so keep the reported UUID and path as expiring references.
Long-lived Herdr-hosted agents use Pi's normal session directory. Read-only roles return final replies through their sessions; the host validates completion and saves response artifacts without giving them repository write tools. Fast implementation starts a fresh hosted session: use --fast --plan-file <absolute-plan-path> to carry a selected plan explicitly.
K-Stack settings live in one config file: $PI_CODING_AGENT_DIR/kstack.json
(default ~/.pi/agent/kstack.json). The vcs.backend setting selects "git",
"jj", or "graphite" for repository mutations and defaults to "git" when omitted.
For Git, vcs.stackProvider defaults to "github"; set it to "none" to
disable stacked-PR publication and membership routing.
Model assignments for panel-review, plan-implement, plan-adversary, arena,
swarm, and the how and why investigation skills use sections in the same
file. plan-adversary selects the model and round limits for adversarial
planning. The plan-implement section also drives --fast mode, which runs the same
implementer while skipping planning, review, and publishing. A top-level
aliases array (or any {label, model, thinking}
entry anywhere in the file) defines model short names that /handoff --model
resolves alongside Pi model display names.
Copy the starter and edit:
cp kstack.example.json ~/.pi/agent/kstack.jsonSee kstack.example.json for the full schema. Each
section is optional. Missing sections use built-in defaults or prompt for
models at runtime. To choose the VCS backend, discover the local Pi model
catalog, validate selected providers, preview the update, and write only the
user configuration, run:
/skill:setup-kstack
setup-kstack does not modify repository defaults unless you explicitly ask for
a separate follow-up change.
The backends are exclusive for each run. Git mode requires Git 2.38 or newer and a plain Git working tree. It supports
current-checkout or managed-worktree single delivery and GitHub-native stacks. Graphite
mode requires gt 1.8.5+, Git 2.38+, and initialized Graphite metadata, and uses
native gt mutation in current or managed-worktree single delivery. jj mode
requires jj 0.44 or newer, a configured jj user name and email, and a Git-backed
jj workspace. Colocated, non-colocated, and secondary jj workspaces pass preflight;
jj stack operations do not require a workspace-local .git marker. It supports current-workspace single delivery and stacked
PRs, but not Git worktree isolation. K-Stack refuses a mismatched workspace
before launching a model or mutating repository state.
| Workflow | Git backend | jj backend | Graphite backend |
|---|---|---|---|
plan-implement --single |
Current branch or --worktree |
main-based change and bookmark |
Current branch or tracked --worktree |
plan-implement --stack |
Local Git branch stack (github provider) |
Local jj stack | Graphite stack adapter |
pr-autopilot |
Branch validation, Git commit/merge/push | Bookmark-at-@ validation, jj commit/merge/push |
Branch validation and native Graphite record/restack/submit |
land auto-discovery |
Current branch | Bookmark targeting @ |
Current Graphite branch |
Existing installations that omit vcs continue to use Git and now use the
GitHub stack provider by default. Set vcs.stackProvider to "none" to keep
single-PR-only Git behavior. To adopt jj or Graphite, run /skill:setup-kstack,
select the backend, review the preview, and approve the update to the user-level
kstack.json. Ensure the jj repository is Git-backed and configure
jj config set --user user.name and user.email first. The installer and
package updates never create, overwrite, or migrate kstack.json; they preserve
the user's backend choice.
how and why use only models in investigation.allowedModels. The resolver
requires every entry to come from kstack's curated fast-model set and to use at
least medium thinking. It rejects a requested model outside the configured
subset. Set defaultModel to one of the allowlisted model IDs.
Kstack names an unnamed session as soon as /plan-implement or /kstack knows
the task, before waiting, preflight, classification, or child-model work.
Automatically derived names are short lowercase slugs, such as
archive-multiple-sessions. /handoff gives its replacement session the same
kind of slug before sending that session's first user message. Existing names
are never overwritten.
For workflows started outside those commands, use Pi's built-in naming support:
pi --name "Named session archive"Or name an active interactive session:
/name Named session archive
Current and inactive sessions can be archived without names. Their archive rows stay unnamed.
- Pi 0.84.2 or newer
- Node 22.18 or newer for Pi's runtime and local tooling. CI tests Node 22.18, 24, and 26.
- A local filesystem for Pi's agent directory
gh— the GitHub CLI, authenticated (gh auth login); required by PR-scoped panel review, pr-autopilot, land, GitHub and jj stacked PRs, and plan-implement's publish stepgithub/gh-stack0.1.0 or newer (gh extension install github/gh-stack) — required for multi-PR jj publication and landingtar— required to extract the temporary source snapshot for PR-scoped panel reviewjj— Jujutsu, only whenvcs.backendis"jj"- Git 2.38 or newer for GitHub-native and Graphite stack advance/rebase behavior
gt— Graphite CLI 1.8.5 or newer, only whenvcs.backendis"graphite"- Herdr 0.8.2 or newer, with
herdr integration install pi, for plan-implement, adversarial planning, Arena, and Swarm
Pi loads one TypeScript entry, kstack.ts, from the package. The installer
links each directory in skills/ into the shared ~/.agents/skills directory.
The aggregator registers every factory under extensions/ in a fixed order. Pi
treats the set as one extension: pi config cannot toggle an individual Kstack
extension, and a factory startup failure rejects the whole set instead of leaving
a partially registered package.
This repository is a Pi package. The pi manifest loads kstack.ts.
Individual factories remain under extensions/ for tests and one-off -e
loads. Pi packages cannot provide settings.json or keybindings.json, so the
recommended installer registers the checkout, links its skills for compatible
agent harnesses, and applies Kstack's tracked Pi defaults:
cd /path/to/kstack
./scripts/install/index.mjsThe installer runs pi install, links each Kstack skill into
~/.agents/skills, and merges
config/pi-defaults/settings.json,
config/pi-defaults/keybindings.json, and
config/pi-defaults/models.json into
$PI_CODING_AGENT_DIR (default ~/.pi/agent). Set
AGENTS_SKILLS_DIR to use another shared skills directory. The installer
preserves unrelated settings and keybindings while making the tracked values
authoritative:
- Thinking blocks are hidden.
- All queued steering and follow-up messages are delivered together.
- Keybindings stay at Pi's stock values; the
steering-swapextension swaps Enter and Alt+Enter in the main editor while Pi is working, so Enter queues follow-up messages and Alt+Enter steers. Enter keeps stock behavior for idle submission, autocomplete, inline prompts, and selectors. - OpenRouter requests use the
:floorvariant automatically through theopenrouter-floorextension, so no per-model:floorentries are needed inmodels.json.
The installer keeps user-defined providers and models. It removes the :floor
custom models that earlier Kstack releases installed, since they now duplicate
the extension's behavior. It refuses to change any Pi config file if one of the
existing or tracked JSON files is malformed.
By default, pi install writes to the current user's global settings. It loads
all Kstack extensions across Pi projects. Pi and other compatible harnesses
load the skills through ~/.agents/skills. The installer does not pass -l,
which would create a project-local installation instead. To register only the
Pi extension without linking skills or applying Kstack's Pi preferences, use
pi install "$PWD" directly.
Pi and the shared skill links reference the checkout rather than copying it.
Pulling or editing the repository updates the installed resources. Use
/reload in a running Pi process, or restart Pi, after changes. Rerun the
installer if you move the checkout.
Inspect or enable the installed aggregator and skills with:
pi list
pi configThe two-model implementation workflow is available as an extension command:
/plan-implement Add optimistic locking to the archive writer
/plan-implement --change-kind bug-fix Fix the archive race
Without --change-kind, the command asks you to select one before planning. For explicit low-risk bounded edits, use /plan-implement --fast --change-kind feature <task> or /kstack --route fast-change <task>; this lower-assurance option never publishes automatically. It
keeps skills enabled in both child agents, so each role can consult the
original task-specific skills it needs. See
extensions/plan-implement/README.md
for model defaults, configuration, confirmations, and security boundaries.
Skills can then be invoked explicitly, for example:
/skill:create-pi-extension
/skill:create-skill
/skill:find-reviewers
/skill:adversarial-planning
/skill:arena
/skill:architect
/skill:swarm
/skill:simplify
/skill:unslop
/skill:technical-writing
/skill:blast-radius
/skill:reflect
/skill:decision-trail
The two-model implementation workflow also has a stacked-PR delivery mode:
/plan-implement --stack Split the auth rollout into a three-PR jj stack
In stack mode the planner and implementer build a local stack with one ref
per PR and deterministically exclude the arena skill. The configured stack
provider owns confirmed structural publication: github-stacked-prs
for Git, jj-stacked-prs for jj, or
graphite-stacked-prs for Graphite. A child
updates titles and bodies and recommends reviewers only after publication
succeeds.
After a draft PR is published, hand it to the bounded PR autopilot to drive the review/fix/CI loop with only tiny models:
/pr-autopilot --mode drive # comments → watch CI → fix → push until merge-ready
/pr-autopilot --mode watch # same loop with more cycles, watching pending checks
/pr-autopilot --mode check # one status pass, report, stop
/pr-autopilot --mode threads # address review comments only, then push
/pr-autopilot --mode cleanup # after merge: remove managed worktree and branch
/pr-autopilot --mode drive --pr 42 # run on a specific PR instead of auto-detecting
/land --pr 42 --method squash # land one PR, or its local jj stack prefix
/land --pr 42 --readiness watch # run autopilot for each selected frontier
pr-autopilot uses only tiny models (GPT-5.6 Luna, GLM 5.2, and DeepSeek
V4 Flash) recorded in the pr-autopilot section of kstack.example.json. It stops at
merge-ready — it never auto-merges or rebases shared history. See
extensions/pr-autopilot/README.md for details.
To remove the package registration, run this from the same checkout:
pi remove "$PWD"Removal does not remove the links in ~/.agents/skills or revert the merged Pi
preferences. Remove the Kstack-managed links and delete the managed keys from
settings.json and keybindings.json if they are no longer wanted.
The installer is preferred because it keeps the aggregator and shared skill
links tied to the checkout. Copying extensions/ into Pi's global user
directory is no longer supported: Pi would discover every source factory
instead of kstack.ts. Use ./scripts/install/index.mjs.
For a one-off extension test without installing anything, run from the repository root:
pi -e extensions/session-archive/index.tsAgents should read AGENTS.md before making changes.
Run the full JavaScript and TypeScript test suite from the repository root:
npm ci
npm testThe suite runs under Node's built-in test runner. The session-archive
extension and the handoff tests use the same native node:sqlite implementation
as Pi's runtime, so no separate SQLite test phase is needed.
skills/tdd/evals/ contains prompt fixtures for skill evaluations, not project
tests. The package test globs deliberately select only Kstack's .test.ts and
.test.mjs files, leaving fixture .test.js files untouched.
Check TypeScript types before submitting changes:
npm run typecheckMeasure startup from Pi process spawn to the correlated RPC get_commands response:
npm run benchmark:startup
# One measured round with no warmups.
npm run benchmark:startup -- --runs 1 --warmups 0The harness runs empty, package-disabled, skills-only, extensions-only, and full profiles. Each profile verifies the complete Kstack command and skill inventory that its filter should load.
Its primary metric is the full median - empty median. It writes raw JSON samples and a Markdown summary under local/benchmarks/startup/.
The benchmark is warm, offline, isolated, and headless. It does not measure MCP, TUI paint, disk-cold startup, network work, or an LLM request. Compare reports only when the machine, Pi executable and version, options, workload, and recorded startup-environment fingerprint match. Run node scripts/startup-benchmark/index.mjs --help to list options.
For focused runs, use the individual test commands:
node --test scripts/install/index.test.mjs
node --test scripts/check-exports/index.test.mjs
npm run test:handoff
npm run test:session-archive
node --test extensions/panel-review/
node --test extensions/plan-implement/
node --test extensions/kstack-router/
node --test extensions/land/
node --test extensions/pr-autopilot/
node --test extensions/jj-stacked-prs/
node --test 'extensions/github-stacked-prs/*.test.ts'
node --test extensions/shared/
node --test skills/reflect/
node --test skills/architect/
node --test skills/decision-trail/
node --test skills/recall/
node --test skills/setup-kstack/
node --test skills/personalize/skill.test.mjs
node --test skills/investigation-model.test.mjsThe git-worktrees planner and inspector are Node TypeScript CLIs:
node --test skills/git-worktrees/The installer links the skills listed in the table above into ~/.agents/skills. Pi and other compatible harnesses discover them there. Most skills can load automatically when a task matches their description or can be invoked with /skill:<name>. architect and decision-trail are explicit-only — one launches several design runs, the other adds a log a routine change doesn't need; invoke them with /skill:architect and /skill:decision-trail.
Skill eval workspaces live under .workspace/ (gitignored) so test runs and review pages never dirty the repository.
See the session archive README for commands, storage paths, recovery behavior, and security limitations.