Skip to content

v2.1.37 — Permission-Mode Awareness

Choose a tag to compare

@agent-kay-it agent-kay-it released this 15 Aug 12:47
· 8 commits to main since this release
99db284

Two responses in one release. bkit stops asking questions nobody is there to
answer, and adapts to a Claude Code default that changed underneath it.

What changes for you

If you run --dangerously-skip-permissions, dontAsk, or acceptEdits,
bkit stops interrupting you.

You run with Before After
--dangerously-skip-permissions bkit still asked before scoped deletes, hard resets, pushes to main it does not ask
--permission-mode dontAsk (CI) the same asks became silent refusals with no recourse it does not ask
--permission-mode acceptEdits asked it does not ask
default / plan mode asked unchanged — still asks
any mode at all rm -rf /, force push, curl … | sh, DROP TABLE refused unchanged — still refused

Claude Code sends permission_mode on every hook event. bkit read it in zero
places, so a session started with maximum autonomy was interrupted exactly as
often as one that had asked to be. The cost was worse than noise: a PreToolUse
question needs a human answer, and an unattended run has none — so the agent
stalled instead of failing, roughly 15 minutes per incident.

The line is the decision's grade, not the mode. A question can be skipped where
nobody can answer it; a refusal cannot be skipped anywhere — the same line Claude
Code draws by keeping a circuit breaker on rm -rf / in bypass mode. Measured
across 7 modes × 21 commands: benign commands stopped 14 → 0, all 49
negative controls intact
.

Three commands that used to interrupt you and no longer do:

grep -rn delete src/ a b c d e           # read-only — the rule matched the WORD "delete"
npm remove lodash react vue axios dayjs  # a package manager, not a file deletion
npm install --force                      # only during the phase-9 deployment skill

If you are on Claude Code v2.1.232 or later, bkit tells you what changed and
what it means.

v2.1.232 turns fork mode on by default in interactive sessions. A subagent's
result now arrives as a notification on a later turn, and the Agent tool no
longer accepts run_in_background, so the foreground cannot be requested.

  • Your skills are unaffected. The background: false bkit added in v2.1.31
    still holds — confirmed in the binary, not inferred.
  • A sprint gate that measures through a subagent reports "not measured" rather
    than a score, and names fork mode as the likely cause. A missing number, never
    a wrong one.
  • Set CLAUDE_CODE_FORK_SUBAGENT=0 to get in-turn results back.

bkit surfaces this once at SessionStart and never blocks on it.

Three git commands that destroy work are now guarded, taking the rule set to
19: git clean -f* (deletes untracked files with no reflog entry to recover
from), the three spellings that discard uncommitted work (checkout -f,
restore against the worktree, switch --discard-changes), and expiring the
reflog with an immediate prune. --amend and --no-verify are deliberately not
guarded — an amended commit survives in the reflog, and publishing the rewrite
needs a force push, which was already refused.

Your .env file is guarded on the Bash surface for the first time, and your
JavaScript is not. The rule meant to notice .env had never matched it: \b
cannot express "start of a filename" when the filename starts with a dot. It had
been matching process.env.NODE_ENV instead, so editing any file that reads
configuration prompted for confirmation. Both directions are fixed and asserted.

Compatibility

Breaking changes: 0. The hook contract is byte-identical across Claude Code
v2.1.228, v2.1.229, v2.1.231 and v2.1.232 — 10 markers measured on all four
binaries. Consecutive compatible releases: 171.

Recommended runtime stays v2.1.220. Install floor v2.1.143, runtime floor
v2.1.78, model floor v2.1.170 for the Fable-pinned agents.

Withdrawn

"PostToolUse continueOnBlock" was not unimplemented. It was unimplementable.
continueOnBlock is a configuration field on a prompt-type hook definition,
confirmed at three places in the v2.1.232 binary. All 28 bkit hook handlers are
"type": "command", so no bkit hook can carry the field at all.

It had been advertised on four surfaces, including the marketplace description
you read before installing. bkit now claims five differentiations rather than six.

The test that let it survive three releases mattered more than the claim: it
asserted that a string appeared in a markdown file — which is true of a claim
nobody implemented, true of a claim nobody can implement, and true of a claim
that is simply wrong. A regex over source text does not verify a feature. Its
replacement checks that every hook handler is still command-type, so if that ever
stops being true the claim gets re-examined on evidence instead of shipping again.

Quality

  • Suite: 5,272 / 5,277 pass, 0 fail, 5 skipped across 382 files
  • Live QA on a real Claude Code v2.1.232 session: 145 / 145, 0 fail — 44 skills,
    34 agents, 21 hook events, 19 MCP tools, plus a new fork-mode layer that
    proves the gate is live before asserting anything under it
  • CI gates 22 / 22
  • Every new regression suite was verified failing against the pre-fix tree

What this QA did not cover is written down in the report rather than left
implied: binary measurement is macOS x86_64 only, fork mode was reached through
CLAUDE_CODE_FORK_SUBAGENT=1 rather than a genuinely interactive session, and
the stdout visibility of eight hook events was taken from Claude Code's
documentation rather than probed live.

Also fixed

  • A regression guard that had never fired once since v2.1.10, because it read a
    payload field Claude Code has never sent
  • Two guards declared removeWhen(ccVersion) and nothing called it — on v2.1.231
    they were still watching for regressions fixed 113 releases earlier
  • git reset --hard was auto-denied by one bkit surface and merely confirmed by
    another; searching for a dangerous string was graded as performing one
  • Sprint iterate no longer burns up to five auto-fix cycles against a gap list
    whose only entry was "no JSON in output"
  • Three agents now preload the five skills they declared — the field was
    skills_preload, which appears nowhere in Claude Code's documentation, and 23
    such declarations across six keys were removed or moved to a field that works
  • Hook messages composed for the model now reach it on the nine events that have
    a context channel, instead of being written to a log
  • 148 test files ran nowhere — neither the local runner nor CI referenced
    them. All are now registered
  • scripts/cc-binary-equivalence.js — the binary measurement three analysis
    cycles had rebuilt by hand, with each erratum recorded beside the line that
    enforces it

Full detail: CHANGELOG.md ·
CC v2.1.228–v2.1.232 impact analysis ·
QA report