63 lines
2.8 KiB
Markdown
63 lines
2.8 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project
|
|
|
|
Security hooks for AI coding agents (Claude Code, Gemini CLI, Codex). A Rust shim forwards tool-call payloads over a Unix socket to an Elixir daemon that evaluates rules using regex and tree-sitter-bash AST analysis. See the [design spec](docs/specs/2026-03-26-security-hooks-design.md) for full details.
|
|
|
|
**Status:** Design phase. No implementation code yet.
|
|
|
|
## Architecture
|
|
|
|
```
|
|
AI Agent --> Rust Shim (<1ms) --> Unix Socket --> Elixir Daemon --> allow/deny/ask
|
|
```
|
|
|
|
- **shim/** — Rust binary. Reads JSON from stdin, sends to daemon socket, prints response. Cross-compiled for macOS/Linux.
|
|
- **daemon/** — Elixir OTP app distributed as a Burrito binary. Rule engine, bash AST analyzer (tree-sitter-bash via Rust NIF), config manager, file watcher for hot-reload.
|
|
- **rules/** — Custom `.rules` DSL files. Regex patterns (literal to end of line, never quoted) and AST match functions (`command()`, `pipeline_to()`, etc.).
|
|
- **config/** — TOML files. `config.toml` for defaults, `config.local.toml` for user overrides (gitignored).
|
|
- **service/** — systemd socket activation units (Linux/WSL) and launchd plist (macOS).
|
|
|
|
## Build commands (once implementation starts)
|
|
|
|
```bash
|
|
# Rust shim
|
|
cd shim && cargo build --release
|
|
|
|
# Elixir daemon
|
|
cd daemon && mix deps.get && mix release
|
|
|
|
# Burrito binary (cross-platform)
|
|
cd daemon && mix release --burrito
|
|
|
|
# Run tests
|
|
cd shim && cargo test
|
|
cd daemon && mix test
|
|
```
|
|
|
|
## Key design decisions
|
|
|
|
- **Fail-closed**: shim returns exit code 2 (deny) if daemon is unreachable within 200ms (3s for cold start).
|
|
- **Two-pass evaluation**: regex rules run first (fast pre-filter, can only deny/suspect, never allow). AST rules run second only if no regex matched.
|
|
- **Regex vs AST auto-detection**: if a `match` value starts with a DSL function name like `command(`, it's AST. Otherwise it's regex.
|
|
- **Validators compiled in**: Elixir validator modules are compiled into the Burrito binary at build time to prevent code injection into the security daemon.
|
|
- **Adapter pattern**: Claude/Gemini/Codex differences are isolated in thin adapter modules (`daemon/lib/security_hooks/adapters/`). The rule engine operates on a normalized internal payload.
|
|
|
|
## Crosslink workflow
|
|
|
|
This repo uses crosslink for issue tracking. Before making code changes:
|
|
|
|
```bash
|
|
crosslink quick "describe the work" -p low -l <label> # creates issue + starts work
|
|
crosslink issue comment <id> "approach" --kind plan # required before commit
|
|
```
|
|
|
|
## Conventions
|
|
|
|
- Elixir: follow standard `mix format` conventions
|
|
- Rust: follow `cargo fmt` / `cargo clippy`
|
|
- Rule files: 2-space indent, 4-space indent for `match_any` sub-patterns
|
|
- Commit messages: imperative mood, explain why not what
|