calor hook
Host-specific hook commands for Calor-first enforcement
Internal hook commands used by Claude Code, Gemini CLI, and Codex project integrations. They are normally invoked by generated configuration rather than typed by a user.
calor hook <subcommand> [args]Overview
calor init --ai <agent> writes the host-specific hook configuration.
| Subcommand | Purpose |
|---|---|
validate-write <tool-input> | Validate a Claude-style Write request |
validate-edit <tool-input> | Validate a Claude-style Edit request |
validate-calr-content <tool-input> | Check Calor content for its semantics declaration |
post-write-lint <tool-input> | Lint a .calr file after a write |
validate-ids <tool-input> | Validate declaration IDs in Calor content |
codex-write | Consume Codex's hook JSON from stdin and validate all destinations |
Subcommands
validate-write
Validates Write tool calls to enforce Calor-first development.
calor hook validate-write <tool-input-json>Behavior:
| File Type | Action |
|---|---|
.calr files | Allowed (exit 0) |
.g.cs generated files | Allowed (exit 0) |
Files in obj/ directory | Allowed (exit 0) |
Other .cs files | Blocked (exit 1) |
Example:
# This will be blocked (exit 1)
calor hook validate-write '{"file_path": "MyClass.cs"}'
# Output:
# BLOCKED: Cannot create C# file 'MyClass.cs'
#
# This is an Calor-first project. Create an .calr file instead:
# MyClass.calr
#
# Use /calor skill for Calor syntax help.
# This will be allowed (exit 0)
calor hook validate-write '{"file_path": "MyClass.calr"}'How Hooks Work
When you initialize a project with calor init --ai claude, it creates .claude/settings.json with hook configuration:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write",
"hooks": [
{
"type": "command",
"command": "calor hook validate-write $TOOL_INPUT"
}
]
}
]
}
}This hook runs before every Write tool call. If the hook returns exit code 1, Claude Code blocks the operation and shows the error message to Claude, who will then retry with an .calr file.
User Experience
When Claude tries to create a .cs file in an Calor-initialized project:
- Claude calls the Write tool with a
.csfile path - The hook intercepts the call and validates the path
- Hook returns exit 1 with guidance message
- Claude Code blocks the write operation
- Claude sees the error and creates an
.calrfile instead
This enforcement happens automatically - no user intervention required.
For Codex, the input schema and trust model differ. codex-write reads the
Codex hook envelope from stdin; it does not use Claude's $TOOL_INPUT
environment variable. Review and trust .codex/hooks.json with /hooks, run
the generated smoke test, and retain CI checks because specialized tool and
shell paths can fall outside lifecycle-hook coverage.
Troubleshooting
Hook Not Blocking .cs Files
-
Verify hooks are configured:
Bashcat .claude/settings.jsonShould contain
PreToolUsehook forWrite -
Verify calor is in PATH:
Bashwhich calor calor hook validate-write '{"file_path": "test.cs"}' echo $? # Should be 1 -
Restart Claude Code - hooks are loaded at session start
Re-enable Hooks After Manual Removal
calor init --ai claude --forceSee Also
- calor init - Initialize Calor with hook configuration
- Claude Integration - Using Calor with Claude