[FEATURE] Permission system should be JSON-rule-based, not hardcoded — three proposals

Resolved 💬 4 comments Opened Apr 2, 2026 by woolkingx Closed Apr 19, 2026

Problem

The current permission system has three structural issues that can't be fixed incrementally:

1. Bypass-immune safetyCheck has no opt-out

bypassPermissions mode still prompts for .claude/skills/, .claude/commands/, .claude/agents/ paths. This is hardcoded — no setting, no env var, no documentation. Power users who run their own hook-based permission systems have no way to delegate this decision.

Each permission mode (plan, auto, bypassPermissions) should have a clear, documented scope. If a mode claims "bypass permissions", hidden exceptions that still prompt the user break the contract. At minimum, provide an opt-out for users who have external policy enforcement.

2. Permission rules should be structured JSON, not pattern strings

The current Bash(git:*) pattern syntax is broken in well-documented ways (#30519, #25441, #29616):

  • Wildcards don't match compound commands
  • "Always Allow" saves dead one-off strings
  • Colon vs space syntax contradicts itself
  • Carefully written rules still don't match

Proposal: Replace pattern strings with JSON Schema (Draft-07) rule documents:

{
  "event": "PreToolUse",
  "tool": ["Bash"],
  "action": "allow",
  "match": {
    "properties": {
      "tool_input": {
        "properties": {
          "command": { "pattern": "^git\\s" }
        }
      }
    }
  }
}

Benefits:

  • Model can generate rules by filling a JSON template — no custom syntax to learn
  • Schema validation catches malformed rules at write time
  • match uses JSON Schema, which models already understand natively
  • Multiple rules merge by priority (deny > ask > allow), not first-match
  • Rules are data — auditable, diffable, shareable

I'm currently preparing a hooks system with 50+ production rules for public release as a reference implementation.

3. Hook events should cover the full stream JSON type set

Current hook events (PreToolUse, PostToolUse, PermissionRequest, etc.) cover tool lifecycle but miss many stream JSON message types. To enable fine-grained policy:

  • Token-level events (streaming content blocks)
  • Model switching / routing decisions
  • Context window operations (compaction, truncation)
  • MCP server lifecycle (connect, disconnect, error)
  • Cost/usage thresholds

The hook event set should map 1:1 to stream JSON type values. This lets external systems make policy decisions at any point in the pipeline, not just around tool calls.

Summary

| issue | current | proposed |
|-------|---------|----------|
| safetyCheck | hardcoded, no opt-out | per-mode scope contract + external policy delegation |
| rule syntax | Bash(git:*) pattern strings | JSON Schema Draft-07 documents |
| hook coverage | tool lifecycle only | full stream JSON type mapping |

The permission system should be data-driven (JSON rules the model can fill) rather than code-driven (hardcoded if/else the user can't change).

View original on GitHub ↗

This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗