Reference
Bash policy enforcement
SCE can enforce bash-tool policy for supported AI coding harnesses. The policy is designed to nudge agents toward safer, more targeted commands before broad shell usage becomes the default.
Harness support
| Harness | Status |
|---|---|
| OpenCode | Supported |
| Claude Code | Supported |
Both harnesses read the same policies.bash config and enforce it through sce policy bash. Install the relevant harness assets with sce setup.
How bash policy works
SCE evaluates bash-tool commands against repo-configured presets and custom rules before the harness launches a subprocess. When an active rule matches, the command is blocked and the agent receives a deterministic denial message. That stops the agent from repeatedly trying to run forbidden bash commands and pushes it toward the repo-approved workflow instead.
Blocked by SCE bash-tool policy '<id>': <message>Policy config lives under policies.bash in either sce/config.json or repo-local .sce/config.json. SCE resolves the active config using the normal config precedence rules, and both supported harnesses enforce the same policy surface.
Policy rules and presets
Config shape
The active bash policy config has two optional parts: built-in preset IDs and repo-defined custom rules.
{
"policies": {
"bash": {
"presets": ["use-nix-flake-over-cargo"],
"custom": [
{
"id": "block-rm",
"match": {
"argv_prefix": ["rm"]
},
"message": "This repository does not allow `rm` via the bash tool."
}
]
}
}
}presetsenables built-in policy IDs.customdefines repo-specific rules with exact argv-prefix matches.
Presets
The built-in preset catalog currently includes the following IDs:
forbid-git-allforbid-git-commituse-pnpm-over-npmuse-bun-over-npmuse-nix-flake-over-cargo
Preset constraints
use-pnpm-over-npmanduse-bun-over-npmare mutually exclusiveforbid-git-allandforbid-git-commitcan be combined, but SCE flags that as redundant
Custom policies
Custom rules let you block narrower command shapes than the preset catalog.
Custom rule requirements
- each rule must include
id,match, andmessage matchmust contain exactlyargv_prefixargv_prefixmust be a non-empty array of non-empty strings- custom IDs must be unique and must not collide with preset IDs
- duplicate custom
argv_prefixvalues are invalid
Matching and precedence
Matching is exact token-prefix matching only.
["git"]matchesgit status["git", "commit"]matchesgit commit -m "msg"["cargo", "fmt", "--check"]matches only that exact prefix.
If more than one policy matches, selection is deterministic:
- longest matching argv prefix
- custom policy over preset when prefix lengths tie
- earlier custom entry when multiple custom entries tie
- preset catalog order when multiple presets tie
This lets you keep broad presets while still overriding them with a narrower repo-specific custom rule.
Examples
These examples use the same config surface for every supported harness.
Prefer Nix flake workflows over direct Cargo
{
"$schema": "https://sce.crocoder.dev/config.json",
"policies": {
"bash": {
"presets": ["use-nix-flake-over-cargo"]
}
}
}That preset blocks direct cargo ... commands and tells the user to use the repository's Nix flake workflow instead.
Prefer nix flake check over cargo test
{
"$schema": "https://sce.crocoder.dev/config.json",
"policies": {
"bash": {
"custom": [
{
"id": "use-nix-flake-check-over-cargo-test",
"match": {
"argv_prefix": ["cargo", "test"]
},
"message": "This repository prefers `nix flake check` over direct `cargo test` commands. Run `nix flake check` instead."
}
]
}
}
}That blocks cargo test specifically, without blocking every cargo command.
Common preset outcomes include preferring pnpm or bun over npm, and blocking direct git commit flows when the repository expects an alternate workflow.
Validation
After changing bash policy config, validate it before relying on the new rules.
sce config validateValidation checks for common problems such as unknown or duplicate preset IDs, duplicate custom IDs, duplicate customargv_prefixvalues, invalid schema shape, and mutually exclusive preset combinations.
Use sce config show when you want to inspect the resolved preset and custom rules with their source. Use sce doctor to confirm the installed harness assets and config are ready.
Troubleshooting
- Policy never blocks commands. Run
sce doctorand confirm the target harness assets are installed. For OpenCode, check that.opencode/plugins/sce-bash-policy.tsexists. For Claude Code, check that.claude/settings.jsoncontains thePreToolUseBashhook. - Hooks run but nothing is denied. Confirm
sceis on your PATH, then runsce config showto verifypolicies.bashresolved the presets and custom rules you expect. - Validation fails after editing config. Run
sce config validateand fix unknown preset IDs, duplicate custom prefixes, or mutually exclusive preset combinations before retrying. - A malformed command is allowed. SCE intentionally fails open when command tokenization or policy input is malformed, so the harness can continue with its normal tool path instead of blocking on parser ambiguity.
For broader Shared Context Engineering background, read Why SCE Exists. For setup and onboarding, continue with the Getting Started guide.