[BUG] --settings flag does not properly override hook configurations
Resolved 💬 3 comments Opened Aug 16, 2025 by arn314 Closed Jan 5, 2026
Environment
- Platform (select one):
- [x] Anthropic API
- [ ] AWS Bedrock
- [ ] Google Vertex AI
- [ ] Other: <!-- specify -->
- Claude CLI version: 1.0.83
- Operating System: macOS 14.6
- Terminal: iTerm2
Bug Description
The --settings flag does not properly override hook configurations. When using --settings to provide a different hook configuration, both the original hooks (from settings.json) and the override hooks run simultaneously, instead of the override completely replacing the original configuration.
Steps to Reproduce
- Run the reproducer script below with a valid auth token:
#!/bin/bash
# Bug reproducer: --settings flag doesn't override hook configurations
# Usage: CLAUDE_CODE_OAUTH_TOKEN=your_token ./settings-bug-reproducer.sh
set -euo pipefail
echo "Claude Code version: $(claude --version)"
echo ""
if [[ -z "${CLAUDE_CODE_OAUTH_TOKEN:-}" ]]; then
echo "Error: CLAUDE_CODE_OAUTH_TOKEN environment variable required"
echo "Usage: CLAUDE_CODE_OAUTH_TOKEN=your_token $0"
exit 1
fi
# Create isolated test environment
export HOME=/tmp/fake-home-claude-test-$(date +%s)
mkdir -p "$HOME/.claude"
# Create settings.json with default hook
echo '{
"hooks": {
"SessionStart": [{
"hooks": [{"type": "command", "command": "echo DEFAULT_HOOK_OUTPUT"}]
}]
}
}' > "$HOME/.claude/settings.json"
echo "=== Testing --settings override behavior ==="
# Test 1: Default hook
TEST1_ID=$(uuidgen)
echo "Test 1 (default): $TEST1_ID"
claude --session-id "$TEST1_ID" -p "test" >/dev/null
# Test 2: --settings override
TEST2_ID=$(uuidgen)
echo "Test 2 (override): $TEST2_ID"
claude --settings '{"hooks":{"SessionStart":[{"hooks":[{"type":"command","command":"echo OVERRIDE_HOOK_OUTPUT"}]}]}}' --session-id "$TEST2_ID" -p "test" >/dev/null
# Check results in specific transcripts
PROJECT_DIR="$HOME/.claude/projects/$(pwd | sed 's|/|-|g' | sed 's|\.|-|g')"
TEST1_FILE="$PROJECT_DIR/$TEST1_ID.jsonl"
TEST2_FILE="$PROJECT_DIR/$TEST2_ID.jsonl"
if grep -q "DEFAULT_HOOK_OUTPUT" "$TEST1_FILE" && grep -q "OVERRIDE_HOOK_OUTPUT" "$TEST2_FILE" && grep -q "DEFAULT_HOOK_OUTPUT" "$TEST2_FILE"; then
echo "🐛 BUG: Both hooks ran in test 2. --settings did not override properly."
elif grep -q "DEFAULT_HOOK_OUTPUT" "$TEST1_FILE" && grep -q "OVERRIDE_HOOK_OUTPUT" "$TEST2_FILE" && ! grep -q "DEFAULT_HOOK_OUTPUT" "$TEST2_FILE"; then
echo "✅ OK: --settings override worked correctly."
else
echo "❓ Unexpected results. Check transcripts manually:"
echo " Test 1: $TEST1_FILE"
echo " Test 2: $TEST2_FILE"
fi
echo "Test complete"
Expected Behavior
- Test 1 should show only
DEFAULT_HOOK_OUTPUTin the session transcript - Test 2 should show only
OVERRIDE_HOOK_OUTPUTin the session transcript (the--settingsshould completely replace the hook configuration)
Actual Behavior
- Test 1 shows
DEFAULT_HOOK_OUTPUT(correct) - Test 2 shows BOTH
DEFAULT_HOOK_OUTPUTANDOVERRIDE_HOOK_OUTPUT(incorrect - both hooks run instead of override replacing the original)
Additional Context
This suggests that --settings is merging with or adding to the existing configuration rather than completely overriding it. The expected behavior would be for --settings to completely replace the hook configuration, not supplement it.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗