Skip to content

Repository files navigation

kstack

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.

Extensions

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.

Skills

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.

Standalone shell tools

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.sh

The installer writes to ~/.local by default and does not change shell startup files. See the shell tool README for function-loading instructions and options.

Subagent sessions

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.

Configuration

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.json

See 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

Migrating existing installations

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.

Session names in development workflows

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.

Requirements

  • 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 step
  • github/gh-stack 0.1.0 or newer (gh extension install github/gh-stack) — required for multi-PR jj publication and landing
  • tar — required to extract the temporary source snapshot for PR-scoped panel review
  • jjJujutsu, only when vcs.backend is "jj"
  • Git 2.38 or newer for GitHub-native and Graphite stack advance/rebase behavior
  • gtGraphite CLI 1.8.5 or newer, only when vcs.backend is "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.

Install for the current user

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.mjs

The 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-swap extension 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 :floor variant automatically through the openrouter-floor extension, so no per-model :floor entries are needed in models.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 config

The 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.

Manual copy installation

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.ts

Development

Agents should read AGENTS.md before making changes.

Run the full JavaScript and TypeScript test suite from the repository root:

npm ci
npm test

The 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 typecheck

Startup benchmark

Measure 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 0

The 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.mjs

The 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.

About

Krishnan's preferred extensions to the Pi coding harness

Resources

Stars

1 star

Watchers

0 watching

Forks

Contributors

Languages