You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
What's missing is the case in between: "I know exactly what this next command does, it's genuinely destructive, let me through this once, and make me acknowledge the risk before you do."
Today the only way to get that is to disable the gate wholesale, which is exactly the wrong trade. The user reaches for a permanent switch to solve a momentary problem.
Proposal: armed bypass mode
A bypass that must be explicitly armed, shows a danger alert first, and disarms itself.
/bypass
Does not enable anything. It shows the warning and asks for confirmation:
⚠ DANGER: BYPASS MODE
This disables the destructive-command gate. While armed, jcode can run
commands that PERMANENTLY DESTROY DATA with no confirmation:
• rm -rf on paths resolved at runtime
• mkfs, dd to block devices, partition edits
• DROP DATABASE / TRUNCATE
• git push --force, git reset --hard, history rewrites
There is no undo. Nothing here is recoverable.
Scope : this session only
Expires : after 1 command, or 5 minutes, whichever is first
Audit : every bypassed command is logged to ~/.jcode/bypass-audit.log
Type ARM BYPASS to continue, or anything else to cancel:
Requiring a typed phrase rather than y/N is deliberate. Muscle memory defeats y/N, and this is precisely the prompt that must not be dismissed reflexively.
Design points that matter
Auto-expiry is the core of it. A bypass that stays on is just #897 with extra steps. Default to a single command, since the honest use case is almost always one specific command the user has already reasoned about. Suggested: /bypass = next 1 command, /bypass 5m = time-boxed for a known-messy sequence like a disk migration.
Visible while armed. Persistent indicator in the status line (⚠ BYPASS ARMED (1 cmd)). Nobody should be unsure whether they're currently unprotected.
The agent must not arm it. This is a user-only control. If the model could invoke /bypass, the whole gate becomes decorative, since a sufficiently determined agent would arm and proceed. Enforce at the tool boundary: the bypass command is not exposed as a callable tool, only as a TUI slash command. This is the single most important constraint in the proposal.
Audit trail. Append every bypassed command with timestamp and cwd. When a bypass eats a directory, the user needs to reconstruct what ran.
Print what's being bypassed. At arm time, if the blocked command is already known, show it verbatim in the alert. Confirming an abstract capability is much weaker than confirming rm -rf ./build/$TARGET_DIR.
The failure mode of a safety gate isn't being too strict, it's being routinely too strict, because users then build a permanent workaround and lose the protection everywhere. An armed, expiring, loudly-announced bypass keeps the pressure release local to the moment that needed it.
It also improves agent behavior. Right now, when the gate blocks inert content (#922), the tempting workaround is base64 -d, printf-assembly, or sed-splicing, all of which are more opaque to the scanner. A legitimate front door means less incentive to tunnel under the wall.
Open questions
Should /bypass require the gate to have actually fired first? Arming pre-emptively is more flexible; arming only in response to a specific block is safer and lets the alert quote the exact command. I lean toward the latter as the default with a flag for the former.
Should time-boxed mode exist at all, or is 1-command-only sufficient? Time-boxed serves real multi-step recovery work, but it's also the mode most likely to be left armed while someone gets distracted.
Non-interactive/headless: probably should never be armable, since there's no human to read the alert. JCODE_BYPASS=1 would recreate the exact problem this avoids.
Came up after hitting #922, where the gate blocked writing a shell script whose text contained rm -f. In that case the right answer was a file-write tool rather than a bypass, but it raised the question of what to do when the command really is destructive and really is intended.
Problem
The bash risk gate has two escape hatches today, and neither is a user-facing, consciously-armed bypass:
justification— the model re-issues the call explaining itself. The agent decides to proceed; the user is never consulted. (Bash tool schema doesn't exposejustificationfield, so models can't discover the Confirm-tier bypass #722)/settings risk-gate off. Correct for its purpose, but it's a durable state change. Flip it once during a frustrating false positive and the protection is silently gone for every later session.What's missing is the case in between: "I know exactly what this next command does, it's genuinely destructive, let me through this once, and make me acknowledge the risk before you do."
Today the only way to get that is to disable the gate wholesale, which is exactly the wrong trade. The user reaches for a permanent switch to solve a momentary problem.
Proposal: armed bypass mode
A bypass that must be explicitly armed, shows a danger alert first, and disarms itself.
Does not enable anything. It shows the warning and asks for confirmation:
Requiring a typed phrase rather than
y/Nis deliberate. Muscle memory defeatsy/N, and this is precisely the prompt that must not be dismissed reflexively.Design points that matter
Auto-expiry is the core of it. A bypass that stays on is just #897 with extra steps. Default to a single command, since the honest use case is almost always one specific command the user has already reasoned about. Suggested:
/bypass= next 1 command,/bypass 5m= time-boxed for a known-messy sequence like a disk migration.Visible while armed. Persistent indicator in the status line (
⚠ BYPASS ARMED (1 cmd)). Nobody should be unsure whether they're currently unprotected.The agent must not arm it. This is a user-only control. If the model could invoke
/bypass, the whole gate becomes decorative, since a sufficiently determined agent would arm and proceed. Enforce at the tool boundary: the bypass command is not exposed as a callable tool, only as a TUI slash command. This is the single most important constraint in the proposal.Audit trail. Append every bypassed command with timestamp and cwd. When a bypass eats a directory, the user needs to reconstruct what ran.
Print what's being bypassed. At arm time, if the blocked command is already known, show it verbatim in the alert. Confirming an abstract capability is much weaker than confirming
rm -rf ./build/$TARGET_DIR.Relationship to existing issues
echo hi 2>/dev/nullis classified Catastrophic #709 / bash gate: redirect-to-null inside command substitution is still Catastrophic, and subshell/case/if bodies bypass the guardrail entirely #725 / Destructive-command safety filter false-positives on plain English inside heredoc content #922 (false positives) — these reduce demand for a bypass but don't remove it. Even a perfect classifier correctly blocks commands users legitimately want to run. That's not a bug, and a bypass is the honest answer to it.Why this shape
The failure mode of a safety gate isn't being too strict, it's being routinely too strict, because users then build a permanent workaround and lose the protection everywhere. An armed, expiring, loudly-announced bypass keeps the pressure release local to the moment that needed it.
It also improves agent behavior. Right now, when the gate blocks inert content (#922), the tempting workaround is
base64 -d,printf-assembly, orsed-splicing, all of which are more opaque to the scanner. A legitimate front door means less incentive to tunnel under the wall.Open questions
/bypassrequire the gate to have actually fired first? Arming pre-emptively is more flexible; arming only in response to a specific block is safer and lets the alert quote the exact command. I lean toward the latter as the default with a flag for the former.JCODE_BYPASS=1would recreate the exact problem this avoids.Came up after hitting #922, where the gate blocked writing a shell script whose text contained
rm -f. In that case the right answer was a file-write tool rather than a bypass, but it raised the question of what to do when the command really is destructive and really is intended.