feat(dev): just shell-real/shell-stub — toggle the brush confined shell#238
Merged
Conversation
While the brush fork's CommandInterceptor is unpublishable (pending reubeno/brush#1184), main stays on agent-bridle's `feat/stub-shell` branch so the workspace publishes to crates.io — but that makes run_command/shell_run return "shell temporarily unavailable". This adds a dev-only lever to run the real Caveats-confined shell locally without disturbing the publishable default. - `just shell-real` — repoints the [patch.crates-io] agent-bridle entries at agent-bridle `main` (the real brush shell). DEV ONLY; not committable. - `just shell-stub` — flips back to the publishable stub branch. - `just shell-check` — guard that fails if the real-shell override is present, so the dev patch can't reach main. A cargo `--features` flag can't express this: crates.io forbids git deps in any form (even optional/feature-gated), so toggling the real shell swaps a dependency *source*, not a feature — hence a patch-swap recipe. The guard runs in the pre-push hook and is mirrored inline in CI's lint job (PIPELINE PARITY). Verified: guard passes on the stub tree, fails when flipped to `main`, and shell-stub restores Cargo.toml byte-for-byte. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
hartsock
added a commit
that referenced
this pull request
Jun 9, 2026
…238 followup) (#240) WHAT: The `shell-real` / `shell-stub` recipes used `sed -i -E 's|...\{ git...|'`, which only works on GNU sed. On BSD/macOS sed they fail with `RE error: invalid repetition count(s)`. Two portability bugs compound: 1. `sed -i` takes its backup-suffix as the *next argument* on BSD, so `-i -E` consumes `-E` as the suffix — the regex is then parsed in BRE mode, where `\{` is an interval operator. `\{ git` is not a valid `{n,m}` → the error. 2. Even in ERE, `\{` is the wrong way to match a literal brace portably. Fix (both recipes + the mirrored `shell-check` grep, and the parity copy in .github/workflows/ci.yml): - Match the literal brace with `[{]` (a bracket expression — literal `{` in both GNU and BSD ERE, never an interval). - Replace `sed -i` with a temp-file rewrite (`sed -E '...' f > f.tmp && mv`), sidestepping the GNU-vs-BSD `-i` suffix difference and keeping `-E` a real flag. WHY: Developers on macOS could not toggle the agent-bridle confined-shell patch. GNU-only sed slipped through because CI runs on Linux. Verified on GNU sed: shell-real → shell-check fails (exit 1, real shell present) → shell-stub → shell-check passes; Cargo.toml round-trips with no residue. The `[{]` + temp-file idioms are POSIX-portable, so the same recipes work on BSD sed. HOOK/PIPELINE PARITY: the `shell-check` grep in the justfile and the "agent-bridle stub guard" grep in .github/workflows/ci.yml are updated together. Co-authored-by: hartsock <hartsock@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
hartsock
added a commit
that referenced
this pull request
Jun 27, 2026
…ell (#238) While the brush fork's CommandInterceptor is unpublishable (pending reubeno/brush#1184), main stays on agent-bridle's `feat/stub-shell` branch so the workspace publishes to crates.io — but that makes run_command/shell_run return "shell temporarily unavailable". This adds a dev-only lever to run the real Caveats-confined shell locally without disturbing the publishable default. - `just shell-real` — repoints the [patch.crates-io] agent-bridle entries at agent-bridle `main` (the real brush shell). DEV ONLY; not committable. - `just shell-stub` — flips back to the publishable stub branch. - `just shell-check` — guard that fails if the real-shell override is present, so the dev patch can't reach main. A cargo `--features` flag can't express this: crates.io forbids git deps in any form (even optional/feature-gated), so toggling the real shell swaps a dependency *source*, not a feature — hence a patch-swap recipe. The guard runs in the pre-push hook and is mirrored inline in CI's lint job (PIPELINE PARITY). Verified: guard passes on the stub tree, fails when flipped to `main`, and shell-stub restores Cargo.toml byte-for-byte. Co-authored-by: hartsock <hartsock@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
hartsock
added a commit
that referenced
this pull request
Jun 27, 2026
…238 followup) (#240) WHAT: The `shell-real` / `shell-stub` recipes used `sed -i -E 's|...\{ git...|'`, which only works on GNU sed. On BSD/macOS sed they fail with `RE error: invalid repetition count(s)`. Two portability bugs compound: 1. `sed -i` takes its backup-suffix as the *next argument* on BSD, so `-i -E` consumes `-E` as the suffix — the regex is then parsed in BRE mode, where `\{` is an interval operator. `\{ git` is not a valid `{n,m}` → the error. 2. Even in ERE, `\{` is the wrong way to match a literal brace portably. Fix (both recipes + the mirrored `shell-check` grep, and the parity copy in .github/workflows/ci.yml): - Match the literal brace with `[{]` (a bracket expression — literal `{` in both GNU and BSD ERE, never an interval). - Replace `sed -i` with a temp-file rewrite (`sed -E '...' f > f.tmp && mv`), sidestepping the GNU-vs-BSD `-i` suffix difference and keeping `-E` a real flag. WHY: Developers on macOS could not toggle the agent-bridle confined-shell patch. GNU-only sed slipped through because CI runs on Linux. Verified on GNU sed: shell-real → shell-check fails (exit 1, real shell present) → shell-stub → shell-check passes; Cargo.toml round-trips with no residue. The `[{]` + temp-file idioms are POSIX-portable, so the same recipes work on BSD sed. HOOK/PIPELINE PARITY: the `shell-check` grep in the justfile and the "agent-bridle stub guard" grep in .github/workflows/ci.yml are updated together. Co-authored-by: hartsock <hartsock@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this PR does
Adds a dev-only lever to run the real Caveats-confined brush shell locally while
mainstays on the publishable stub (thefeat/stub-shellbranch, pending reubeno/brush#1184 — see #206 / #208). Todaymainreturns "shell tool temporarily unavailable" forrun_command/shell_run; this lets a developer flip to the real shell without disturbing the crates.io-publishable default.just shell-real— repoints the[patch.crates-io]agent-bridle entries at agent-bridlemain(the real brush shell). Dev-only; must not be committed.just shell-stub— flips back to the publishable stub branch.just shell-check— guard that fails if the real-shell override is present, so the dev patch can't reachmain. Wired into the pre-push hook and mirrored inline in CI's lint job (PIPELINE PARITY).Why a recipe, not a
--featuresflagcrates.io forbids git dependencies in any form — even optional or feature-gated. The real shell requires the brush git fork, so it can't live in a publishable manifest at all. Toggling it swaps a dependency source (
[patch]target), which a cargo feature cannot do. Hence the patch-swap recipe pair + guard.Test plan
just shell-checkpasses on the stub tree.just shell-real→ guard correctly fails (branch =maindetected).just shell-stubrestoresCargo.tomlbyte-for-byte (clean round-trip, no residual diff).justfile,.githooks/pre-push,ci.ymllint job.Out of scope
Closes the "let me use bash while we wait for brush" gap noted on #206.
🤖 Generated with Claude Code