All notable changes to RuleZ (AI Policy Engine) will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
rulez skillssubcommand family — New CLI for managing skills across AI coding runtimes (install, status, diff, sync, clean)- Multi-runtime skill portability — Author skills once in
.claude/, convert at install time to OpenCode, Gemini CLI, Codex, or custom runtimes - 6 content transforms — Tool name mapping, path reference rewriting, command name flattening, YAML frontmatter conversion, color hex conversion, MCP tool handling
- Config file generation — Auto-updates GEMINI.md and AGENTS.md with skill registry sections using idempotent marker-based replacement
rulez skills diff— Shows what would change if skills were re-installed, comparing transformed content against existing filesrulez skills status— Human-readable relative timestamps (e.g., "2h ago") showing installation freshness per runtimerulez skills sync— Install to all detected runtimes (OpenCode, Gemini, Codex) in one command- Custom runtime support —
--runtime skills --dir .qwen/skillsfor generic skill-based runtimes - Mastering-hooks auto-discovery — Repo-root skill sources discovered and installed alongside
.claude/skills/
- New
rulez/src/skills/module tree: profiles, discovery, transform pipeline, transforms (6 types), writer, config_gen - 42 unit tests covering all transform types, discovery, writing, config gen, and CLI helpers
- Clean-install writer pattern (remove + recreate) prevents orphaned files across versions
- Renamed release-cch skill to release-rulez — Fixed 149+ stale "cch" references across
.claude/skills/and.opencode/skill/directories - Fixed broken preflight-check.sh — Updated stale
cch_cli/directory path to use workspace-level cargo commands
- 9 missing CLI commands documented — Added
test,lint,upgrade,gemini install,gemini doctor,copilot install,copilot doctor,opencode install,opencode doctorto mastering-hooks reference - ConfigDiffView wired into UI — Added "Diff" button to header with routing to Monaco DiffEditor component
- Subagent hook patterns (Phase 29) —
agent-inline-hooks.mdreference, updated rule-patterns, troubleshooting guide, and hooks template with subagent examples rulez test(Phase 30) — Batch test command runs multiple event scenarios from a YAML file with pass/fail summary- External logging backends (Phase 33) — OTLP, Datadog, and Splunk integrations via curl subprocess transport with fallback to local JSON Lines
- BeforeAgent event guide (Phase 32) — Event scoping documentation, platform support table, and Issue #107 resolution
- Config diff view (Phase 34) — Side-by-side global vs project config comparison in rulez-ui using Monaco DiffEditor
- API documentation (Phase 35) — Event schema and config schema reference docs, expanded rustdoc for library crate
rulez lint(Phase 36) — Rule quality analysis with 9 checks: duplicate names, empty matchers, conflicting actions, overlapping rules, dead rules, missing descriptions, invalid regex, glob consolidation, missing priority
- Cold-start performance baseline established (Phase 31) — moved CLI parse before config init
- OpenCode CLI E2E testing — Adapter, fixtures, and 4 E2E scenarios (install, hook-fire, deny, inject) for OpenCode CLI
- Codex CLI E2E testing — Adapter, fixtures, and 4 E2E scenarios (1 install + 3 skip stubs — Codex has no hooks support)
- Gemini CLI E2E testing — Adapter, fixtures, and 4 E2E scenarios completing Gemini headless integration
- All 5 CLIs covered — E2E scenario matrix now spans Claude Code, Gemini, Copilot, OpenCode, and Codex
- GSD tracking reconciliation — all 28 phases and 78 plans properly tracked across milestones v1.2–v2.1
rulez upgrade— Auto-check and upgrade binary to latest GitHub release using self_update crate (rustls backend)- tool_input eval context —
tool_input_prefixed variables injected intoenabled_whenexpressions (string, bool, number fields) - Debug script trace —
script_outputfield in JSON rule evaluations shows run action script results - Parallel rule evaluation —
join_allparallel matching for rule sets >= 10 rules (sequential action execution preserved)
- Regex fail-closed — Invalid regex in
command_matchnow returns non-match instead of silent match-all; validated at config load - Config cache — mtime-based
CachedConfiginvalidation inConfig::from_file()prevents stale config reads - Globset matching —
build_glob_set()replaces naivecontains()directory matching with proper glob patterns - Skill docs — 7 field name mismatches corrected in mastering-hooks hooks-yaml-schema.md and rule-patterns.md
- UI log filter debounce — Reduced from 300ms to 200ms in LogFilterBar.tsx for snappier filtering
- 5 GitHub issues closed (#101–#105)
- Tool name canonicalization — Platform-specific tool names are now normalized to Claude Code's PascalCase canonical names at adapter ingestion time. Rules with
tools: [Bash]work across Gemini CLI (run_shell_command), Copilot (shell), and OpenCode (bash) - Platform tool name preservation — Original platform tool name stored in
tool_input.platform_tool_namewhen mapping occurs, for debugging and auditability - TOOL-MAPPING.md — Cross-platform tool name mapping reference documenting all canonical names, platform aliases, and confidence levels
- Multi-platform adapter documentation — New
platform-adapters.mdreference covering Gemini CLI, GitHub Copilot, and OpenCode event mappings - Dual-fire event documentation — Complete coverage of dual-fire triggers across Gemini and OpenCode adapters
- Agent lifecycle patterns — New BeforeAgent/AfterAgent rule patterns for agent governance
- Cross-platform rule writing guide — Tips for writing rules that work across all supported platforms
- Debug CLI alias table — All 11 event types with their shorthand aliases documented
- Gemini adapter — Corrected tool name mappings to match verified Gemini CLI docs (
run_shell_command,glob,search_file_content/grep_search); refactored to Map-first pattern fixing Rust ownership bug - Copilot adapter — Refactored to Map-first pattern fixing Rust ownership bug (E0382)
- OpenCode adapter — Added
webfetchas alias alongside existingfetchfor WebFetch mapping - Mastering-hooks skill v2.0.0 — Complete rewrite of the Claude Code skill with multi-platform support
- CCH → RuleZ rename — All remaining CCH references in skill docs, templates, and scripts updated to RuleZ
- Event types table — Expanded from 13 to 16 event types (added BeforeAgent, AfterAgent, BeforeModel, AfterModel, BeforeToolSelection)
- SubagentStart/SubagentStop deprecated — Marked as deprecated aliases for BeforeAgent/AfterAgent
- Environment variables — CCH_CONFIG, CCH_LOG_LEVEL, CCH_LOG_FILE, CCH_TIMEOUT renamed to RULEZ_* equivalents
- Hooks template — Updated with BeforeAgent example and multi-platform compatibility note
- Event type unification — 16 canonical event types with serde aliases for backward compatibility
- Multi-platform adapters — Gemini CLI, GitHub Copilot, and OpenCode adapter implementations
- Dual-fire events — Platform events that map to multiple RuleZ event types
- TeammateIdle and TaskCompleted — Claude Code-specific event types
- Project renamed from CCH (Claude Context Hooks) to RuleZ — binary, configs, logs, and all references updated
- Binary:
cch->rulez - Log file:
cch.log->rulez.log - Release assets:
cch-*->rulez-*
inject_inline— Embed context directly in YAML rules without external filesinject_command— Generate dynamic context via shell commands at evaluation timeenabled_when— Conditional rule activation with evalexpr expressions (e.g.,event_type == "PreToolUse")
prompt_match— Regex intent routing against prompt text with case-insensitive, anchored, AND/OR logicrequire_fields/field_types— Fail-closed field existence and type validation with dot-notation pathsvalidate_expr— Inline evalexpr expressions withget_field()/has_field()custom functionsinline_script— Shell scripts embedded in YAML with configurable timeout protection
- JSON Schema validation — Fail-open schema validation for hook event payloads (<0.1ms overhead via LazyLock pre-compiled validators)
- Debug CLI UserPromptSubmit support — Debug command now handles prompt-submit events
- LRU regex cache (100 entries) — Replaces unbounded HashMap to prevent memory growth
- Cross-platform E2E tests — Path canonicalization for macOS symlinks, CI matrix (ubuntu, macOS, Windows)
- Tauri CI build pipeline — E2E gate before desktop builds, multi-platform Tauri packaging
- Tauri 2.0 desktop app scaffold with React 18, TypeScript 5.7+, Tailwind CSS 4
- 18 React components, 3 Zustand stores, Monaco YAML editor with schema validation
- Dual-mode architecture (Tauri desktop + web browser fallback)
- Playwright E2E tests with Page Object Model (56 tests)
task run-appcommand for launching the desktop app
- Broken pipe in inline scripts —
Stdio::null()for stdout/stderr when only checking exit code (Linux CI fix) - Zombie process reaping — Timeout path now calls
child.kill()+child.wait() - Stale binary artifacts — Cleaned up old
cchbinaries after rename - E2E test strict mode — Added
data-testidattributes for Playwright strict selector compliance - Merge conflict resolution — Fixed 12 files with leftover conflict markers from concurrent PRs
- 634 tests passing (up from 64 in v1.0.0)
- <3ms rule processing latency maintained across all new features
- Monorepo structure:
rulez/(core),mastering-hooks/(skill),rulez-ui/(desktop app) - Release workflow updated: asset names now use
rulez-*prefix
v1.0.0 was fundamentally broken for blocking operations. This release contains essential fixes:
- Exit Code 2 for Blocking - v1.0.0 incorrectly used exit code 0 with
continue:false, which did NOT prevent tool execution. CCH now exits with code 2 when blocking, per Claude Code hook protocol. - Event Parsing Fix - Fixed to correctly parse
hook_event_namefield (notevent_type) per Claude Code hook event protocol. - Config Resolution - Now uses the event's
cwdfield to locate project-levelhooks.yaml, fixing incorrect rule matching in some scenarios.
- Taskfile Architecture - Modular Taskfiles for CLI (
cch_cli/Taskfile.yml) and UI (rulez_ui/Taskfile.yml) with root orchestration - Playwright E2E Testing - Expanded test infrastructure with Page Object Models and CI integration
- E2E GitHub Workflow - Automated Playwright tests on push to main/develop
- Page Object Models for maintainable E2E tests
- Test fixtures for mock configurations and event scenarios
- Enhanced Playwright configuration for CI environments
- Root Taskfile now includes subproject Taskfiles via
includes: - Orchestrated commands:
task build,task test:all,task dev,task ci-full - Playwright config updated with JUnit reporter, video capture on retry, and visual regression settings
Upgrade from v1.0.x is strongly recommended. Blocking rules were not functioning correctly in v1.0.0-1.0.2.
To verify blocking works correctly after upgrade:
echo '{"hook_event_name":"PreToolUse","tool_name":"Bash","tool_input":{"command":"git push --force"}}' | cch pre-tool-use
echo $? # Should output: 2- Block Dangerous Operations - Prevent destructive commands like
git push --force - Inject Context - Automatically inject context files based on directory patterns
- Run Custom Validators - Execute Python/shell scripts to validate tool inputs
- Permission Explanations - Provide structured explanations for permission requests
cch init- Create default hooks.yaml with example rules and context filescch install- Register CCH with Claude Code settings.jsoncch uninstall- Remove CCH from Claude Code settingscch validate- Validate hooks.yaml configuration syntax and schemacch logs- Query and filter JSON Lines log entriescch explain- Explain which rules matched an eventcch debug- Simulate events to test rule matchingcch repl- Interactive debug mode for testing rules
- YAML-based rule configuration in
.claude/hooks.yaml - Support for global (
~/.claude/hooks.yaml) and project-level configs - Rule matchers:
tools,extensions,directories,operations,command_patterns - Rule actions:
block,block_if_match,inject,run
- JSON Lines format for machine-readable logs
- Structured event details for all tool types
- Response summary logging (continue, reason, context_length)
- Debug mode with raw event and rule evaluation details
- Sub-10ms event processing (<3ms actual)
- Cold start under 5ms p95
- Minimal memory footprint (<50MB resident)
- Language: Rust 2024 edition
- Runtime: Tokio async (current_thread flavor)
- Zero unsafe code: Memory safety guaranteed by compiler
- Cross-platform: Linux (x86_64, aarch64), macOS (x86_64, aarch64), Windows (x86_64)
- 64 tests covering all user stories
- Unit tests for core logic
- Integration tests for CLI commands
- Performance tests for latency requirements