plankit

pk guard

pk guard is a PreToolUse hook on shell commands. Before the agent runs a git mutation (commit, merge, push, rebase, reset), guard reads .pk.json and answers with a permission decision. Three policies apply; the strongest decision wins, and deny beats ask.

The hook recognizes git through chains (&&, ;, |), environment prefixes, absolute paths, git -C, and git.exe. A compound command is judged by its parts.

What guard is

A guardrail against an agent following its defaults, not a security boundary. An internal error fails open with a note on stderr. An unconfigured repository (no .pk.json) is a no-op.

Changing policy

Edit .pk.json and commit it. The keys, their values, and their defaults are under Settings below.

"guard": {
  "branches": ["main"],
  "breaking": "ask",
  "mode": "block",
  "push": "block"
}

Breaking markers

A breaking marker (! after the type, or a BREAKING CHANGE: footer) drives the next major version. The marker is the developer's claim, and an agent never adds one on its own judgment. The hook asks before a git commit whose inline message carries a marker. guard.breaking: "off" disables the ask, not the rule.

Only -m and --message arguments are inspected; -F files and editor commits pass through. That covers the case the rule exists for, since agent commits are -m commits.

Settings

The guard section of .pk.json:

"guard": {
  "branches": ["<branch>", ...],
  "breaking": "ask" | "off",
  "mode": "block" | "ask" | "off",
  "push": "block" | "ask" | "off"
}

An unknown key or a value outside these fails the whole file when it loads, with a message naming the key: pk commands exit 2, and each hook reports the message and takes no action until it is fixed. An absent key means its default. pk status reads the file back and reports the first problem.