Release notes
What's new in pk, and how to use it.
v0.26.0 — 2026-07-15 — Security patch, wider guard, atomic release push
pk now builds on Go 1.26.5, closing GO-2026-5856 — an Encrypted Client Hello privacy leak in crypto/tls. pk’s only TLS surface is the GitHub API call behind the update notice, so the practical exposure was narrow, but every earlier release pins Go 1.26.4 or older and the upgrade costs you nothing.
pk guard catches shell forms it used to miss. A mutation could reach git as true | git push, /usr/bin/git push, GIT_DIR=. git push, command git push, or a second line of a multi-line command, and the block policy never saw it. Guard now splits on pipes and newlines — on top of the &&, ||, and ; it already handled — with quotes still respected, and it matches git by path basename after skipping env assignments and a leading command word. It stays a guardrail against an agent following its defaults, not a boundary against an adversary — it fails open by design, and command substitution and subshells are still out of scope.
pk release now pushes atomically. A rejected branch push could strand the tag on origin: git accepted the tag ref, rejected the non-fast-forward branch, and the local rollback never reached the remote. The push is now git push --atomic, so a rejected branch takes the tag down with it. A new pre-flight also fails before the tag is created when origin/main has diverged from your source branch, and prints the merge command to reconcile it.
The versioning invariant now ships as always-on guidance. pk’s model — the git tag is the single source of truth, and versions are computed from tag history and written into files, never read back out of them — lived only in the docs, so an agent doing ordinary feature work had no ambient statement of it and could reach for the anti-pattern. It is now part of the rules pk setup installs, pointing at the mechanisms that were always there: versionFiles for a root JSON version field, pk pin for source constants, a hook script for anything else. No new mechanism, no new config key. Re-run pk setup to pick it up.
v0.25.0 — 2026-06-24 — Homebrew-aware update notice
If you installed pk with Homebrew, the update notice now speaks your language. When a newer version is available, pk detects how it was installed and suggests the right upgrade command: brew upgrade plankit for Homebrew installs, go install for everyone else. No more copying a command that doesn’t match how you got pk. Homebrew is also now documented as an install option in the README, alongside go install and release binaries.
v0.24.0 — 2026-06-12 — Release readiness and one voice
pk status now reports release readiness. Run it before shipping and it tells you what’s standing between you and a release — a missing baseline tag, a release branch not on origin, unpushed work — each with the exact command to fix it. And when the working branch itself is missing, errors now point at the failure point instead of leaving you to guess.
/conventions now guides the move between branch strategies. Switching a project from main-only to develop→main (or back) used to mean rewiring .pk.json by hand; the skill now walks the transition. A new moving-between-setups guide covers the details.
Every pk command speaks with one voice now: consistent Error:/Warning:/Note: prefixes, hints that are exact runnable commands, and the git equivalent shown when pk is a thin wrapper over one or two git commands. pk <cmd> --help shows the real, current flags — including the off modes that were previously undocumented. And pk no longer HTML-escapes the JSON it writes: a hook command like a && b in .pk.json or .claude/settings.json stays readable instead of turning into a \u0026\u0026 b.
v0.23.0 — 2026-06-10 — Modes move into .pk.json
Guard mode, push-guard, and preserve mode used to be baked into the hook commands in settings.json — readable only by squinting at flags. Now they’re plain keys in .pk.json — guard.mode, guard.push, preserve.mode — that you read and edit in one place, and the hook commands are bare. Re-run pk setup to migrate an existing project: the lift is automatic, and your old hooks keep working until you do.
push-guard is now on by default (block). In a Claude Code session the agent can no longer run git push directly — you push from your own terminal, or let pk release / pk preserve publish through pk. Pass pk setup --push-guard off to opt out; a project that already had push-guard off keeps it off. pk status now shows the push-guard mode next to guard and preserve.
Two more things. pk’s managed rules moved to .claude/rules/plankit/, so they no longer collide with your project’s own .claude/rules/ files — the same pk setup re-run relocates them. And the adoption docs gained a migration guide for bringing plankit into an existing repo: a copy-pasteable prompt that walks Claude through the baseline tag, an existing CHANGELOG, and version-file hooks.
v0.22.0 — 2026-06-07 — See what your rules cost, and guard your pushes
pk rules shows what your rules actually cost. It reports the always-on context footprint of your .claude/rules/ and CLAUDE.md — total and per file — with each rule’s provenance (pk-managed, modified, or your own) and its craft-or-conduct kind. Token counts are calibrated against a real tokenizer, not the usual chars/4 guess, which runs about 25% low for this kind of markdown. Add --lint to scan rule files for hidden or Trojan-source characters, or --lint --strict for plankit’s house-style checks. It only reports — it writes no files.
pk setup --push-guard block is a new opt-in dial on pk guard. The guard already blocks git mutations on protected branches; push-guard goes further and blocks the agent from running git push on any branch. Commit and push stay separate decisions: the agent commits, you decide when to publish — or let pk preserve and pk release push through pk. Off by default; turn it on when you want every push to be your call.
plankit now states its own shipped-rules footprint in the README — being honest about the always-on context cost it adds to every session. pk rules gives you the same number for your project.
v0.21.0 — 2026-06-03 — Less friction in setup and release
pk setup now points you at /conventions when it finds no .pk.json, so a fresh repo gets nudged to define its conventions instead of running config-less.
/ship now ignores a version tacked onto it — the number comes from your commits, computed by pk changelog, so Claude can’t derail a release by guessing one.
The development standard pk ships into your repo also gained a debugging rule: a failed text search means “not found by this method,” never “not present.” A grep miss against escaped JSON or an encoded ID can send Claude chasing a bug that isn’t there.
v0.20.3 — 2026-05-31 — Hardening the files pk writes into your repo
The rules and skills pk setup installs are now scanned for hidden and invisible characters — zero-width spaces, bidi overrides, the “Trojan Source” class — before they ship. AI agents read these files every session, so a hidden instruction would fan out to every project. Now it can’t slip in.
v0.20.0 — 2026-05-27 — Use what you need
pk setup now accepts --guard off and --preserve off. If you want release management (pk changelog / pk release / /ship) without plan preservation, run pk setup --preserve off. Same for branch protection: --guard off disables the guard hook entirely. Already-committed plans in docs/plans/ stay protected regardless — pk protect is unconditional.
Windows: hooks and skills now explicitly specify Bash as their shell. When Claude Code uses PowerShell as its primary shell (CLAUDE_CODE_USE_POWERSHELL_TOOL), plankit’s hooks were silently receiving no stdin payload — plan preservation broke without warning. That’s fixed. The guard matcher also widened to catch commands run through either Bash or PowerShell, closing a bypass gap.
v0.19.0 — 2026-05-07 — Private repos and init polish
/new-plankit-project now supports private repos. Pass private <org> to create a private repo under a GitHub org. The emitted script handles the differences: no license file, --private flag, empty anchor commit, and org-scoped paths.
/init’s question format was also simplified, restoring one-at-a-time presentation.
v0.18.0 — 2026-05-06 — /ship auto
Type /ship auto and the release workflow runs end-to-end without pausing. Same dry-run safety checks at each step — if either preview hits an error, it stops and asks. Otherwise: changelog, tag, merge, push, done.
Also new: a versioning guide covering how to flow tag-derived versions into project files — versionFiles for JSON, pk pin --name for source constants, ldflags for build-time injection, and hook scripts for frameworks with no built-in version sync.
v0.17.0 — 2026-05-05 — flexible version pinning
pk pin --name pins versions in any file with an identifier assignment, not just shell variables. A Go project with const version = "0.1.0" in main.go can now use:
"preCommit": "pk pin --file cmd/myapp/main.go --name version $VERSION"
Works with Go constants, Python __version__, TOML version fields, and anything else that assigns a quoted string. The v-prefix is inferred from the existing value — bare stays bare, prefixed stays prefixed. The legacy shell-variable pattern (PK_VERSION="v...") still works without --name, unchanged.
v0.16.0 — 2026-05-02 — setup that remembers
pk setup now preserves your mode configuration. Previously, re-running pk setup after upgrading would silently reset --guard and --preserve to their defaults. Now it infers the current modes from your existing settings.json. Pass --guard or --preserve explicitly only when you want to change them.
/init works without pk setup. If CLAUDE.md doesn't exist when you run /init, it creates the Critical Rules header for you and continues. No more chicken-and-egg between setup and init.
$VERSION in .pk.json lifecycle hooks now works on Windows, macOS, and Linux. pk pre-expands variables before passing the command to the shell, so hook authors write $VERSION once and it works everywhere.
v0.15.1 — 2026-04-30 — fewer skills, same workflow
pk setup now installs three skills instead of five — /init, /preserve, and /ship. The standalone /changelog and /release skills are gone, since /ship already chained both with preview+confirm at each step. If you were using /changelog followed by /release, switch to /ship. The underlying pk changelog and pk release CLI commands are unchanged — power users who type them directly won't notice a difference.
The methodology has been restructured into 14 scannable sections — same content, less essay. Silent semantic narrowing — Claude's habit of adding defensive bounds that quietly drop data — is now documented as an anti-pattern.
v0.15.0 — 2026-04-28 — self-cleaning setup, trunk releases, methodology refresh
Run pk setup after upgrading and it now removes managed files that newer pk versions have deprecated — but only if you haven't touched them. The pk_sha256 hash gates the removal: customized files are preserved with a warning, and files you authored yourself are left alone.
Trunk-based projects are now first-class in /ship. If your repo commits directly to a single branch with no develop→main split, omit release.branch from .pk.json and pk release tags HEAD, pushes the branch and tag, no merge step. The docs and the /ship skill text now cover both the trunk flow and the merge flow side by side, without presuming one.
The methodology picks up two pieces. A new section, “Discipline as the multiplier,” frames plankit's pieces — plan, rules, review, tests, model execution — as one system: the result of plan-driven AI work belongs to the system, not to the model alone. “Reviewing the plan” now covers what's actually in a plan — approach, scope, code excerpts, verification — and names the most common AI-introduced bug to scan for at the code layer: silent semantic narrowing. Defensive LIMIT N, --max-count=N, head -n N, filters that drop legitimate values, loops that break on first match.
v0.14.1 — 2026-04-24 — sandbox tag fetch, /ship undo note
Claude Code on the web now sees your version tags. The SessionStart bootstrap runs a best-effort git fetch --tags right after installing pk, so pk changelog and pk release have the history they need. The sandbox used to clone only the working branch, so pk changelog failed with “no version tags found” and pointed you at creating a baseline — wrong advice when tags already existed on origin. That error now tells you to run git fetch --tags instead; baseline advice still appears when origin is actually bare.
v0.14.2 and v0.14.3 smoothed two more sandbox bootstrap rough edges that only surfaced once we could test in the cloud.
If you change your mind after pk changelog but before pk release, /ship now reaches for pk changelog --undo to unwind cleanly — no more improvising with git reset.
v0.14.0 — 2026-04-23 — tamper-checked binaries, tidier upgrades
install-pk.sh now fetches checksums.txt alongside the binary and verifies the SHA256 before installing — no more wondering whether a network hop tampered with the download, and if sha256sum is missing, install fails loudly rather than silently installing an unverified binary. And when pk setup actually updates a managed file, it now suggests committing those changes on their own: chore(pk): update managed files for v<VERSION>, so pk-upgrade churn stays distinguishable from feature work in your history.
pk teardown used to silently skip plankit hook removal if it couldn’t parse a settings file; now it logs the path and category before continuing, so you can see what it can’t clean up. There’s also a new methodology section, when the model shifts, on working with plankit across Claude model changes.
v0.13.1 — 2026-04-22 — /preserve polish + settings.json safety
Typing /preserve right after approving a plan now saves it immediately — no dry-run preview, no extra confirmation. The plan was already approved; preserving it is just bookkeeping. A new .git/pk-pending-plan pointer also makes /preserve pick the correct plan when two Claude sessions have plans open in parallel; before, it sometimes grabbed whichever file in the shared ~/.claude/plans/ had the freshest mtime.
pk setup now keeps its hands off .claude/settings.json. It no longer rewrites the file with alphabetical key order, and it no longer silently drops hook-object fields it didn’t recognize — whether those come from another tool or a future Claude Code release. Key order is your choice; unknown fields survive.
v0.13.0 — 2026-04-21 — /ship skill
Cutting a release is now one command. Run /ship in Claude Code and it chains /changelog → /release, keeping the preview-and-confirm gate on each step so nothing lands unreviewed. If the release half fails, rerun /ship — it reads the Release-Tag trailer on HEAD and resumes from the release step. pk setup installs it alongside the other managed skills.
v0.12.0 — 2026-04-19 — clearer errors and better nudges
Run pk setup in a repo without a version tag and it now nudges you toward pk setup --baseline — the one-step way to anchor pk changelog. When pk version notices an update after a go install bump, it suggests re-running pk setup so your project's pinned install-pk.sh stays in sync. Error messages got friendlier across the board: pk changelog outside a git repo, pk release with an unpushed source branch, and pk version's semver output. Paired guidance for server-side enforcement lives in the new branch protection guide.
v0.11.1 — 2026-04-19 — polish and a repo split
The pk setup tip that appears when no version tags exist is now conditional — trunk-based projects don't get pushed toward --baseline. The pk changelog error for missing tags mentions --at <ref> inline, so late adopters discover the flag at the moment they need it. The plankit site now lives at github.com/markwharton/plankit.com, separate from the CLI repo.
v0.11.0 — 2026-04-18 — pk setup --baseline
Anchoring pk changelog is now one command. If your project uses versioned releases, run pk setup --baseline --push — it tags v0.0.0 on HEAD and publishes the tag. Works on new repos and existing ones; pass --at <ref> to fold prior commits into the first changelog entry. Trunk-based projects can skip it. Bonus: /preserve now continues with implementation after saving a plan.
Full history in the CHANGELOG on GitHub.