Reference

OpenCode bash policy enforcement

SCE can block bash tool commands before they execute in OpenCode, so repositories can enforce safer command paths and preferred workflows.

OpenCode only

This page documents the current OpenCode integration only. Enforcement is implemented by the generated plugin at config/.opencode/plugins/sce-bash-policy.ts. That plugin intercepts bash tool calls, reads the resolved bash policy config, and throws a blocking error before any subprocess starts when a rule matches.

Overview

When an active rule matches a normalized command segment, the whole OpenCode bash tool command is blocked. The failure message keeps a stable shape so users and tooling can recognize policy failures consistently.

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.

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.

Normalization before matching

  • leading env assignments like FOO=bar are ignored
  • wrappers like env, command, nohup, and sudo are stripped away
  • executable paths are reduced to the command name, so /usr/bin/git matches as git
  • chained commands split on shell operators like |, &&, ||, ;, and &
  • nested commands passed through nix ... -c, nix ... --command, sh -c, and bash -c are checked too

Presets

The built-in preset catalog currently includes the following IDs:

  • forbid-git-all
  • forbid-git-commit
  • use-pnpm-over-npm
  • use-bun-over-npm
  • use-nix-flake-over-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.

Preset constraints

  • use-pnpm-over-npm and use-bun-over-npm are mutually exclusive
  • forbid-git-all and forbid-git-commit can be combined, but SCE flags that as redundant

Custom policies

Custom rules let you block narrower command shapes than the preset catalog.

{
  "$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.

Custom rule requirements

  • each rule must include id, match, and message
  • match must contain exactly argv_prefix
  • argv_prefix must be a non-empty array of non-empty strings
  • custom IDs must be unique and must not collide with preset IDs
  • duplicate custom argv_prefix values 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:

  1. longest matching argv prefix
  2. custom policy over preset when prefix lengths tie
  3. earlier custom entry when multiple custom entries tie
  4. preset catalog order when multiple presets tie

This lets you keep broad presets while still overriding them with a narrower repo-specific custom rule.

Validation

After changing bash policy config, validate it before relying on the new rules.

sce config validate

Validation 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.

For broader Shared Context Engineering background, read Why SCE Exists. For setup and onboarding, continue with the Getting Started guide.