Skip to main content

Hooks & Extensibility

Hooks let you run custom shell commands before and after tool execution. They're configured in ~/.openorca/config.json under the hooks section.

Configuration

{
"hooks": {
"preToolHooks": {
"bash": "echo 'About to run bash' >> /tmp/orca-audit.log",
"*": "echo 'Tool starting' >> /tmp/orca-audit.log"
},
"postToolHooks": {
"write_file": "echo 'File written' >> /tmp/orca-audit.log",
"*": "echo 'Tool finished' >> /tmp/orca-audit.log"
}
}
}

Hook Keys

KeyMatches
"bash"Only the bash tool
"write_file"Only the write_file tool
"*"Any tool (wildcard)

Specific tool names are checked first. If no specific match is found, the wildcard * is used.

Behavior

Pre-Tool Hooks

  • Run before the tool executes
  • Blocking: if the hook exits with a non-zero exit code, the tool execution is cancelled
  • Use for safety gates, audit logging, or validation
  • Timeout: 30 seconds

Post-Tool Hooks

  • Run after the tool executes (regardless of tool success/failure)
  • Fire-and-forget: non-zero exit codes are logged but don't affect anything
  • Use for audit logging, notifications, or cleanup
  • Timeout: 30 seconds

Environment Variables

Hooks receive context about the tool call via environment variables:

VariableAvailable InDescription
ORCA_TOOL_NAMEPre + PostName of the tool being executed (e.g., bash, write_file)
ORCA_TOOL_ARGSPre + PostJSON string of the tool's arguments
ORCA_TOOL_RESULTPost onlyThe tool's result text (truncated to 10,000 chars)
ORCA_TOOL_ERRORPost only"True" if the tool returned an error, "False" otherwise

Use Case Examples

Audit Logging

Log every tool call to a file:

{
"hooks": {
"preToolHooks": {
"*": "echo \"$(date -Iseconds) PRE $ORCA_TOOL_NAME $ORCA_TOOL_ARGS\" >> ~/.openorca/audit.log"
},
"postToolHooks": {
"*": "echo \"$(date -Iseconds) POST $ORCA_TOOL_NAME error=$ORCA_TOOL_ERROR\" >> ~/.openorca/audit.log"
}
}
}

Safety Gate: Block Dangerous Paths

Prevent writes to sensitive directories:

{
"hooks": {
"preToolHooks": {
"write_file": "python3 -c \"import json,sys,os; args=json.loads(os.environ['ORCA_TOOL_ARGS']); sys.exit(1 if '/etc/' in args.get('path','') or '/.ssh/' in args.get('path','') else 0)\""
}
}
}

If the path contains /etc/ or /.ssh/, the Python script exits with code 1 and the write is blocked.

Auto-Format After File Write

Run a formatter after any file write:

{
"hooks": {
"postToolHooks": {
"write_file": "python3 -c \"import json,os; args=json.loads(os.environ['ORCA_TOOL_ARGS']); path=args.get('path',''); os.system(f'prettier --write {path}') if path.endswith(('.js','.ts','.json')) else None\""
}
}
}

Git Safety: Prevent Pushes to Main

Block git_push if targeting the main branch:

{
"hooks": {
"preToolHooks": {
"git_push": "python3 -c \"import json,os,sys; args=json.loads(os.environ['ORCA_TOOL_ARGS']); sys.exit(1 if args.get('branch','') in ('main','master') else 0)\""
}
}
}

Notification on Shell Commands

Get a desktop notification when a shell command completes (macOS):

{
"hooks": {
"postToolHooks": {
"bash": "osascript -e 'display notification \"Command finished\" with title \"OpenOrca\"'"
}
}
}

Shell Execution

Hooks run via:

  • Windows: cmd.exe /c <command>
  • Linux/macOS: /bin/bash -c "<command>"

The working directory is the current working directory of the OpenOrca process.

Prompt Template Customization

Beyond hooks, you can customize the system prompt templates that control how OpenOrca instructs the model.

Editing Prompt Templates

Prompt files are stored at ~/.openorca/prompts/. You can edit them directly:

# Edit the default prompt
nano ~/.openorca/prompts/default.md

# Edit a model-specific prompt
nano ~/.openorca/prompts/mistral-7b-instruct-v0.3.md

Template Variables

Templates support these placeholders:

VariableReplaced With
{{TOOL_LIST}}Formatted list of all enabled tools with descriptions
{{CWD}}Current working directory
{{PLATFORM}}Operating system identifier
{{PROJECT_INSTRUCTIONS}}Contents of ORCA.md (if present)

Forcing a Specific Profile

Set promptProfile in config to override automatic model-based resolution:

{
"lmStudio": {
"promptProfile": "my-custom-prompt"
}
}

This loads ~/.openorca/prompts/my-custom-prompt.md regardless of which model is loaded.