feat: initial companion repo for OpenClaw vs Claude Code article
40 files demonstrating every major OpenClaw capability using Claude Code: - 3 agents (researcher, writer, reviewer) - 3 skills (daily-briefing, slack-message, web-research) - 2 security hooks (pre-tool-use blocker, post-tool-use logger) - 10 self-contained examples with copy-paste prompts - Complete feature map (20 capabilities, 11 full match, 7 different, 2 gap) - Security docs including NemoClaw comparison - Automation, messaging, browser, memory documentation Zero dependencies. Clone and run. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
commit
2491f5c732
40 changed files with 2037 additions and 0 deletions
75
hooks/README.md
Normal file
75
hooks/README.md
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
# Hooks
|
||||
|
||||
Claude Code hooks are shell scripts or HTTP endpoints that run
|
||||
before or after tool execution. They are the primary security
|
||||
mechanism for Claude Code, equivalent to OpenClaw's exec approvals
|
||||
and Docker sandboxing.
|
||||
|
||||
## Files in this directory
|
||||
|
||||
| File | Hook event | Purpose |
|
||||
|------|-----------|---------|
|
||||
| `pre-tool-use.sh` | PreToolUse | Blocks dangerous shell commands |
|
||||
| `post-tool-use.sh` | PostToolUse | Logs all tool executions |
|
||||
| `audit.log` | (generated) | Append-only audit trail |
|
||||
|
||||
## How hooks work
|
||||
|
||||
Hooks are configured in `.claude/settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"PreToolUse": [{
|
||||
"matcher": "Bash",
|
||||
"hooks": [{
|
||||
"type": "command",
|
||||
"command": "bash hooks/pre-tool-use.sh"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### PreToolUse
|
||||
|
||||
Runs before a tool executes. The script receives JSON on stdin
|
||||
with `tool_name` and `tool_input`. Return decisions:
|
||||
|
||||
- Exit 0: allow (no output needed)
|
||||
- Exit 2 + JSON `{"decision": "block", "reason": "..."}`: block the tool call
|
||||
|
||||
### PostToolUse
|
||||
|
||||
Runs after a tool executes. Same stdin format plus `tool_output`.
|
||||
Cannot block (already executed). Use for logging, notifications,
|
||||
or triggering follow-up actions.
|
||||
|
||||
### Other hook events
|
||||
|
||||
Claude Code supports these additional events:
|
||||
|
||||
| Event | When it fires |
|
||||
|-------|--------------|
|
||||
| SessionStart | When Claude Code launches |
|
||||
| SessionEnd | When the session closes |
|
||||
| Stop | When Claude Code finishes a response |
|
||||
| SubagentStop | When a subagent completes |
|
||||
| UserPromptSubmit | Before processing user input |
|
||||
| PreCompact | Before context compaction |
|
||||
| Notification | When Claude Code shows a notification |
|
||||
|
||||
## Comparison to OpenClaw
|
||||
|
||||
| Feature | OpenClaw | Claude Code |
|
||||
|---------|----------|-------------|
|
||||
| Exec blocking | /approve command + DM pairing | PreToolUse hooks |
|
||||
| Audit logging | command-logger hook | PostToolUse hooks |
|
||||
| Tool deny lists | Per-session/agent config | disallowedTools + settings.json deny |
|
||||
| Container isolation | Docker sandbox (off/non-main/all) | macOS sandbox-exec |
|
||||
| Policy engine | NemoClaw YAML policies | Hook scripts (any logic) |
|
||||
| HTTP webhooks | Built-in webhook system | HTTP hooks (POST JSON to URL) |
|
||||
|
||||
Claude Code hooks are more flexible (arbitrary shell logic) but
|
||||
require more setup. OpenClaw's approach is more structured but
|
||||
less customizable.
|
||||
21
hooks/post-tool-use.sh
Executable file
21
hooks/post-tool-use.sh
Executable file
|
|
@ -0,0 +1,21 @@
|
|||
#!/bin/bash
|
||||
# PostToolUse hook: Log all tool executions to an audit trail.
|
||||
#
|
||||
# This hook runs AFTER every tool execution and appends a log entry
|
||||
# to hooks/audit.log. Useful for reviewing what Claude Code did
|
||||
# during a session.
|
||||
#
|
||||
# OpenClaw equivalent: command-logger hook + OpenTelemetry (NemoClaw)
|
||||
# Claude Code approach: PostToolUse hooks with custom logging
|
||||
|
||||
input=$(cat)
|
||||
tool_name=$(echo "$input" | python3 -c "import sys,json; print(json.load(sys.stdin).get('tool_name',''))" 2>/dev/null)
|
||||
tool_input=$(echo "$input" | python3 -c "import sys,json; d=json.load(sys.stdin).get('tool_input',{}); print(d.get('command', d.get('file_path', d.get('pattern', str(d)[:100])))" 2>/dev/null)
|
||||
|
||||
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
||||
log_dir="$(dirname "$0")"
|
||||
log_file="$log_dir/audit.log"
|
||||
|
||||
echo "$timestamp | $tool_name | $tool_input" >> "$log_file"
|
||||
|
||||
exit 0
|
||||
53
hooks/pre-tool-use.sh
Executable file
53
hooks/pre-tool-use.sh
Executable file
|
|
@ -0,0 +1,53 @@
|
|||
#!/bin/bash
|
||||
# PreToolUse hook: Block dangerous shell commands before execution.
|
||||
#
|
||||
# This hook reads the tool input from stdin (JSON with tool_name and tool_input)
|
||||
# and blocks commands that could cause serious damage.
|
||||
#
|
||||
# How it works:
|
||||
# - Claude Code calls this script BEFORE executing any Bash command
|
||||
# - If the script exits with code 2, the command is BLOCKED
|
||||
# - The "decision" field in stdout JSON controls the outcome
|
||||
#
|
||||
# OpenClaw equivalent: exec approvals + tool deny lists + Docker sandbox
|
||||
# Claude Code approach: hook-based guardrails (more flexible, user-controlled)
|
||||
|
||||
input=$(cat)
|
||||
tool_name=$(echo "$input" | python3 -c "import sys,json; print(json.load(sys.stdin).get('tool_name',''))" 2>/dev/null)
|
||||
command=$(echo "$input" | python3 -c "import sys,json; print(json.load(sys.stdin).get('tool_input',{}).get('command',''))" 2>/dev/null)
|
||||
|
||||
# Only check Bash commands
|
||||
if [ "$tool_name" != "Bash" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Blocked patterns
|
||||
blocked_patterns=(
|
||||
"rm -rf /"
|
||||
"rm -rf ~"
|
||||
"rm -rf \$HOME"
|
||||
"mkfs"
|
||||
"dd if="
|
||||
":(){:|:&};:"
|
||||
"chmod -R 777 /"
|
||||
"curl.*|.*bash"
|
||||
"wget.*|.*bash"
|
||||
"curl.*|.*sh"
|
||||
"wget.*|.*sh"
|
||||
"> /dev/sda"
|
||||
"sudo rm"
|
||||
"shutdown"
|
||||
"reboot"
|
||||
"init 0"
|
||||
"init 6"
|
||||
)
|
||||
|
||||
for pattern in "${blocked_patterns[@]}"; do
|
||||
if echo "$command" | grep -qi "$pattern"; then
|
||||
echo '{"decision": "block", "reason": "Blocked by security hook: command matches dangerous pattern '"'$pattern'"'"}'
|
||||
exit 2
|
||||
fi
|
||||
done
|
||||
|
||||
# Allow everything else
|
||||
exit 0
|
||||
Loading…
Add table
Add a link
Reference in a new issue