Skip to content

OpenCode + Claude Code bash policy written in Rust!!!#68

Open
davidabram wants to merge 6 commits into
mainfrom
cc-bash-policy
Open

OpenCode + Claude Code bash policy written in Rust!!!#68
davidabram wants to merge 6 commits into
mainfrom
cc-bash-policy

Conversation

@davidabram

Copy link
Copy Markdown
Member

No description provided.

davidabram and others added 6 commits June 12, 2026 14:04
Implements a CLI-agnostic bash-policy evaluator that matches the
current OpenCode TypeScript runtime behavior: command tokenization,
shell segment splitting for operators, wrapper/env stripping,
executable basename normalization, nested nix/sh|bash -c recursion,
preset/custom active-policy construction, longest-prefix/custom-over-
preset precedence, and canonical block-message formatting.

Co-authored-by: SCE <sce@crocoder.dev>
Expose the Rust bash-policy evaluator through a hidden `sce policy bash`
subcommand for hook callers. The command reads JSON from STDIN, resolves
bash-policy config from the project root (git root with current-directory
fallback), evaluates the command against active policies, and emits
hook-safe output.

Input modes:
- --input claude-pre-tool-use (default): parses Claude PreToolUse event JSON
- --input normalized: parses {"command":...} for OpenCode delegation

Output modes:
- --output claude-hook (default): emits Claude Code deny JSON or empty string
- --output json: emits structured allow/deny result with normalized_argv

Also adds resolve_bash_policy_runtime_config to the config resolver so
policy evaluation can resolve config without requiring the full
observability config path.

Adds parity tests covering Claude PreToolUse parsing, normalized request
parsing, deny/allow JSON rendering, malformed custom policy handling,
parseCommandSegments edge cases, shell operator policy evaluation, and
sh -c payload unwrapping.

Co-authored-by: SCE <sce@crocoder.dev>
Replace the TypeScript bash-policy runtime with a thin wrapper
that calls `sce policy bash --input normalized --output json`
via `spawnSync`. The plugin fails open when `sce` is unavailable
or returns errors, and throws stable SCE denial messages on
deny decisions.

Remove `bash-policy/runtime.ts` and all generated copies.
Rewrite tests to mock `node:child_process` and cover allow,
deny, fail-open, and invalid JSON paths.

Co-authored-by: SCE <sce@crocoder.dev>
Add a generated Claude `.claude/settings.json` PreToolUse command hook for
the Bash tool that runs `sce policy bash`, delegating bash-policy
enforcement to the Rust evaluator. The Pkl rendering source in
claude-content.pkl is updated accordingly.

Claude and OpenCode now both delegate to the same Rust `sce policy bash`
path, with Claude using a settings.json command hook and OpenCode using a
thin TypeScript plugin wrapper.

Co-authored-by: SCE <sce@crocoder.dev>
Remove stale default-path accessors and doctor presence checks for the deleted
OpenCode bash-policy runtime asset. Update current project guidance and durable
context to reflect Rust-owned `sce policy bash` evaluation and OpenCode plugin
wrapper test ownership.

Co-authored-by: SCE <sce@crocoder.dev>
  The Claude settings $schema URL pointed at www.schemastore.org, which
  serves a redirect rather than the schema document directly. Update the
  Pkl renderer (source of truth) and its rendered config output to use
  json.schemastore.org so tooling resolves the schema in one hop.

Co-authored-by: SCE <sce@crocoder.dev>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant