oh-my-claude-sisyphus 3.8.2 → 3.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +14 -1
- package/dist/__tests__/installer.test.js +1 -1
- package/dist/__tests__/installer.test.js.map +1 -1
- package/dist/installer/index.d.ts +1 -1
- package/dist/installer/index.d.ts.map +1 -1
- package/dist/installer/index.js +1 -1
- package/dist/installer/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/hooks/keyword-detector.mjs +28 -4
- package/templates/hooks/persistent-mode.mjs +4 -4
- package/templates/hooks/post-tool-use.mjs +5 -2
- package/templates/hooks/pre-tool-use.mjs +14 -2
- package/templates/hooks/session-start.mjs +102 -2
- package/templates/hooks/stop-continuation.mjs +1 -1
- package/templates/hooks/keyword-detector.sh +0 -268
- package/templates/hooks/persistent-mode.sh +0 -244
- package/templates/hooks/post-tool-use.sh +0 -90
- package/templates/hooks/pre-tool-use.sh +0 -113
- package/templates/hooks/session-start.sh +0 -62
- package/templates/hooks/stop-continuation.sh +0 -93
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# OMC Pre-Tool-Use Hook
|
|
3
|
-
# Enforces delegation by warning when orchestrator attempts direct source file edits
|
|
4
|
-
|
|
5
|
-
# Read stdin (JSON input from Claude Code)
|
|
6
|
-
INPUT=$(cat)
|
|
7
|
-
|
|
8
|
-
# Extract tool name and file path
|
|
9
|
-
TOOL_NAME=""
|
|
10
|
-
FILE_PATH=""
|
|
11
|
-
if command -v jq &> /dev/null; then
|
|
12
|
-
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // .toolName // ""' 2>/dev/null)
|
|
13
|
-
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.filePath // .toolInput.file_path // .toolInput.filePath // ""' 2>/dev/null)
|
|
14
|
-
else
|
|
15
|
-
TOOL_NAME=$(echo "$INPUT" | grep -oP '"tool_name"\s*:\s*"\K[^"]+' | head -1)
|
|
16
|
-
if [ -z "$TOOL_NAME" ]; then
|
|
17
|
-
TOOL_NAME=$(echo "$INPUT" | grep -oP '"toolName"\s*:\s*"\K[^"]+' | head -1)
|
|
18
|
-
fi
|
|
19
|
-
FILE_PATH=$(echo "$INPUT" | grep -oP '"file_path"\s*:\s*"\K[^"]+' | head -1)
|
|
20
|
-
if [ -z "$FILE_PATH" ]; then
|
|
21
|
-
FILE_PATH=$(echo "$INPUT" | grep -oP '"filePath"\s*:\s*"\K[^"]+' | head -1)
|
|
22
|
-
fi
|
|
23
|
-
fi
|
|
24
|
-
|
|
25
|
-
# Handle Bash tool separately - check for file modification patterns
|
|
26
|
-
if [ "$TOOL_NAME" = "Bash" ] || [ "$TOOL_NAME" = "bash" ]; then
|
|
27
|
-
# Extract command
|
|
28
|
-
COMMAND=""
|
|
29
|
-
if command -v jq &> /dev/null; then
|
|
30
|
-
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // .toolInput.command // ""' 2>/dev/null)
|
|
31
|
-
else
|
|
32
|
-
COMMAND=$(echo "$INPUT" | grep -oP '"command"\s*:\s*"\K[^"]+' | head -1)
|
|
33
|
-
fi
|
|
34
|
-
|
|
35
|
-
# Check for file modification patterns
|
|
36
|
-
if echo "$COMMAND" | grep -qE '(sed\s+-i|>\s*[^&]|>>\s*|tee\s+|cat\s+.*>\s*|echo\s+.*>\s*|printf\s+.*>\s*)'; then
|
|
37
|
-
# Check if modifying source files
|
|
38
|
-
SOURCE_PATTERN='\.(ts|tsx|js|jsx|mjs|cjs|py|pyw|go|rs|java|kt|scala|c|cpp|cc|h|hpp|rb|php|svelte|vue|graphql|gql|sh|bash|zsh)'
|
|
39
|
-
if echo "$COMMAND" | grep -qE "$SOURCE_PATTERN"; then
|
|
40
|
-
# Might be modifying source files - warn
|
|
41
|
-
WARNING="[DELEGATION NOTICE] Bash command may modify source files: $COMMAND
|
|
42
|
-
|
|
43
|
-
Recommended: Delegate to executor agent instead:
|
|
44
|
-
Task(subagent_type=\"oh-my-claudecode:executor\", model=\"sonnet\", prompt=\"...\")
|
|
45
|
-
|
|
46
|
-
This is a soft warning. Operation will proceed."
|
|
47
|
-
WARNING_ESCAPED=$(echo "$WARNING" | jq -Rs . 2>/dev/null || echo "\"$WARNING\"")
|
|
48
|
-
echo "{\"continue\": true, \"message\": $WARNING_ESCAPED}"
|
|
49
|
-
exit 0
|
|
50
|
-
fi
|
|
51
|
-
fi
|
|
52
|
-
# Bash command is OK
|
|
53
|
-
echo '{"continue": true}'
|
|
54
|
-
exit 0
|
|
55
|
-
fi
|
|
56
|
-
|
|
57
|
-
# Only check Edit and Write tools
|
|
58
|
-
if [ "$TOOL_NAME" != "Edit" ] && [ "$TOOL_NAME" != "Write" ] && \
|
|
59
|
-
[ "$TOOL_NAME" != "edit" ] && [ "$TOOL_NAME" != "write" ]; then
|
|
60
|
-
echo '{"continue": true}'
|
|
61
|
-
exit 0
|
|
62
|
-
fi
|
|
63
|
-
|
|
64
|
-
# No file path? Allow
|
|
65
|
-
if [ -z "$FILE_PATH" ]; then
|
|
66
|
-
echo '{"continue": true}'
|
|
67
|
-
exit 0
|
|
68
|
-
fi
|
|
69
|
-
|
|
70
|
-
# Check allowed paths (always OK)
|
|
71
|
-
if [[ "$FILE_PATH" == *".omc/"* ]] || \
|
|
72
|
-
[[ "$FILE_PATH" == *".claude/"* ]] || \
|
|
73
|
-
[[ "$FILE_PATH" == *"/.claude/"* ]] || \
|
|
74
|
-
[[ "$FILE_PATH" == "CLAUDE.md" ]] || \
|
|
75
|
-
[[ "$FILE_PATH" == *"/CLAUDE.md" ]] || \
|
|
76
|
-
[[ "$FILE_PATH" == "AGENTS.md" ]] || \
|
|
77
|
-
[[ "$FILE_PATH" == *"/AGENTS.md" ]]; then
|
|
78
|
-
echo '{"continue": true}'
|
|
79
|
-
exit 0
|
|
80
|
-
fi
|
|
81
|
-
|
|
82
|
-
# Check if source file extension (should warn)
|
|
83
|
-
EXT="${FILE_PATH##*.}"
|
|
84
|
-
EXT_LOWER=$(echo "$EXT" | tr '[:upper:]' '[:lower:]')
|
|
85
|
-
|
|
86
|
-
SOURCE_EXTS="ts tsx js jsx mjs cjs py pyw go rs java kt scala c cpp cc h hpp rb php svelte vue graphql gql sh bash zsh"
|
|
87
|
-
|
|
88
|
-
IS_SOURCE=false
|
|
89
|
-
for src_ext in $SOURCE_EXTS; do
|
|
90
|
-
if [ "$EXT_LOWER" = "$src_ext" ]; then
|
|
91
|
-
IS_SOURCE=true
|
|
92
|
-
break
|
|
93
|
-
fi
|
|
94
|
-
done
|
|
95
|
-
|
|
96
|
-
if [ "$IS_SOURCE" = true ]; then
|
|
97
|
-
# Emit warning but allow (soft enforcement)
|
|
98
|
-
WARNING="[DELEGATION NOTICE] Direct $TOOL_NAME on source file: $FILE_PATH
|
|
99
|
-
|
|
100
|
-
Recommended: Delegate to executor agent instead:
|
|
101
|
-
Task(subagent_type=\"oh-my-claudecode:executor\", model=\"sonnet\", prompt=\"...\")
|
|
102
|
-
|
|
103
|
-
This is a soft warning. Operation will proceed."
|
|
104
|
-
|
|
105
|
-
# Escape for JSON
|
|
106
|
-
WARNING_ESCAPED=$(echo "$WARNING" | jq -Rs .)
|
|
107
|
-
echo "{\"continue\": true, \"message\": $WARNING_ESCAPED}"
|
|
108
|
-
exit 0
|
|
109
|
-
fi
|
|
110
|
-
|
|
111
|
-
# Not a source file, allow without warning
|
|
112
|
-
echo '{"continue": true}'
|
|
113
|
-
exit 0
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# OMC Session Start Hook
|
|
3
|
-
# Restores persistent mode states and injects context when session starts
|
|
4
|
-
|
|
5
|
-
# Read stdin
|
|
6
|
-
INPUT=$(cat)
|
|
7
|
-
|
|
8
|
-
# Get directory
|
|
9
|
-
DIRECTORY=""
|
|
10
|
-
if command -v jq &> /dev/null; then
|
|
11
|
-
DIRECTORY=$(echo "$INPUT" | jq -r '.directory // ""' 2>/dev/null)
|
|
12
|
-
fi
|
|
13
|
-
|
|
14
|
-
if [ -z "$DIRECTORY" ]; then
|
|
15
|
-
DIRECTORY=$(pwd)
|
|
16
|
-
fi
|
|
17
|
-
|
|
18
|
-
MESSAGES=""
|
|
19
|
-
|
|
20
|
-
# Check for active ultrawork state
|
|
21
|
-
if [ -f "$DIRECTORY/.omc/state/ultrawork-state.json" ] || [ -f "$HOME/.omc/state/ultrawork-state.json" ]; then
|
|
22
|
-
if [ -f "$DIRECTORY/.omc/state/ultrawork-state.json" ]; then
|
|
23
|
-
ULTRAWORK_STATE=$(cat "$DIRECTORY/.omc/state/ultrawork-state.json" 2>/dev/null)
|
|
24
|
-
else
|
|
25
|
-
ULTRAWORK_STATE=$(cat "$HOME/.omc/state/ultrawork-state.json" 2>/dev/null)
|
|
26
|
-
fi
|
|
27
|
-
|
|
28
|
-
IS_ACTIVE=$(echo "$ULTRAWORK_STATE" | jq -r '.active // false' 2>/dev/null)
|
|
29
|
-
if [ "$IS_ACTIVE" = "true" ]; then
|
|
30
|
-
STARTED_AT=$(echo "$ULTRAWORK_STATE" | jq -r '.started_at // ""' 2>/dev/null)
|
|
31
|
-
PROMPT=$(echo "$ULTRAWORK_STATE" | jq -r '.original_prompt // ""' 2>/dev/null)
|
|
32
|
-
MESSAGES="$MESSAGES<session-restore>\\n\\n[ULTRAWORK MODE RESTORED]\\n\\nYou have an active ultrawork session from $STARTED_AT.\\nOriginal task: $PROMPT\\n\\nContinue working in ultrawork mode until all tasks are complete.\\n\\n</session-restore>\\n\\n---\\n\\n"
|
|
33
|
-
fi
|
|
34
|
-
fi
|
|
35
|
-
|
|
36
|
-
# Check for incomplete todos
|
|
37
|
-
INCOMPLETE_COUNT=0
|
|
38
|
-
TODOS_DIR="$HOME/.claude/todos"
|
|
39
|
-
if [ -d "$TODOS_DIR" ]; then
|
|
40
|
-
for todo_file in "$TODOS_DIR"/*.json; do
|
|
41
|
-
if [ -f "$todo_file" ]; then
|
|
42
|
-
if command -v jq &> /dev/null; then
|
|
43
|
-
COUNT=$(jq '[.[] | select(.status != "completed" and .status != "cancelled")] | length' "$todo_file" 2>/dev/null || echo "0")
|
|
44
|
-
INCOMPLETE_COUNT=$((INCOMPLETE_COUNT + COUNT))
|
|
45
|
-
fi
|
|
46
|
-
fi
|
|
47
|
-
done
|
|
48
|
-
fi
|
|
49
|
-
|
|
50
|
-
if [ "$INCOMPLETE_COUNT" -gt 0 ]; then
|
|
51
|
-
MESSAGES="$MESSAGES<session-restore>\\n\\n[PENDING TASKS DETECTED]\\n\\nYou have $INCOMPLETE_COUNT incomplete tasks from a previous session.\\nPlease continue working on these tasks.\\n\\n</session-restore>\\n\\n---\\n\\n"
|
|
52
|
-
fi
|
|
53
|
-
|
|
54
|
-
# Output message if we have any
|
|
55
|
-
if [ -n "$MESSAGES" ]; then
|
|
56
|
-
# Escape for JSON
|
|
57
|
-
MESSAGES_ESCAPED=$(echo "$MESSAGES" | sed 's/"/\\"/g')
|
|
58
|
-
echo "{\"continue\": true, \"message\": \"$MESSAGES_ESCAPED\"}"
|
|
59
|
-
else
|
|
60
|
-
echo '{"continue": true}'
|
|
61
|
-
fi
|
|
62
|
-
exit 0
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# OMC Stop Continuation Hook
|
|
3
|
-
# Checks for incomplete todos and injects continuation prompt
|
|
4
|
-
# Ported from oh-my-opencode's todo-continuation-enforcer
|
|
5
|
-
|
|
6
|
-
# Validate session ID to prevent path traversal attacks
|
|
7
|
-
is_valid_session_id() {
|
|
8
|
-
local id="$1"
|
|
9
|
-
if [ -z "$id" ]; then
|
|
10
|
-
return 1
|
|
11
|
-
fi
|
|
12
|
-
if echo "$id" | grep -qE '^[a-zA-Z0-9][a-zA-Z0-9_-]{0,255}$'; then
|
|
13
|
-
return 0
|
|
14
|
-
fi
|
|
15
|
-
return 1
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
# Read stdin
|
|
19
|
-
INPUT=$(cat)
|
|
20
|
-
|
|
21
|
-
# Get session ID if available
|
|
22
|
-
SESSION_ID=""
|
|
23
|
-
if command -v jq &> /dev/null; then
|
|
24
|
-
SESSION_ID=$(echo "$INPUT" | jq -r '.sessionId // .session_id // ""' 2>/dev/null)
|
|
25
|
-
fi
|
|
26
|
-
|
|
27
|
-
# Check for incomplete tasks in new Task system
|
|
28
|
-
TASKS_DIR="$HOME/.claude/tasks"
|
|
29
|
-
TASK_COUNT=0
|
|
30
|
-
JQ_AVAILABLE=false
|
|
31
|
-
if command -v jq &> /dev/null; then
|
|
32
|
-
JQ_AVAILABLE=true
|
|
33
|
-
fi
|
|
34
|
-
|
|
35
|
-
if [ -n "$SESSION_ID" ] && is_valid_session_id "$SESSION_ID" && [ -d "$TASKS_DIR/$SESSION_ID" ]; then
|
|
36
|
-
for task_file in "$TASKS_DIR/$SESSION_ID"/*.json; do
|
|
37
|
-
if [ -f "$task_file" ] && [ "$(basename "$task_file")" != ".lock" ]; then
|
|
38
|
-
if [ "$JQ_AVAILABLE" = "true" ]; then
|
|
39
|
-
STATUS=$(jq -r '.status // "pending"' "$task_file" 2>/dev/null)
|
|
40
|
-
# Match TypeScript isTaskIncomplete(): only pending/in_progress are incomplete
|
|
41
|
-
# 'deleted' and 'completed' are both treated as done
|
|
42
|
-
if [ "$STATUS" = "pending" ] || [ "$STATUS" = "in_progress" ]; then
|
|
43
|
-
TASK_COUNT=$((TASK_COUNT + 1))
|
|
44
|
-
fi
|
|
45
|
-
else
|
|
46
|
-
# Fallback: grep for incomplete status values (pending or in_progress)
|
|
47
|
-
if grep -qE '"status"[[:space:]]*:[[:space:]]*"(pending|in_progress)"' "$task_file" 2>/dev/null; then
|
|
48
|
-
TASK_COUNT=$((TASK_COUNT + 1))
|
|
49
|
-
fi
|
|
50
|
-
fi
|
|
51
|
-
fi
|
|
52
|
-
done
|
|
53
|
-
|
|
54
|
-
if [ "$JQ_AVAILABLE" = "false" ] && [ "$TASK_COUNT" -gt 0 ]; then
|
|
55
|
-
echo "[OMC WARNING] jq not installed - Task counting may be less accurate." >&2
|
|
56
|
-
fi
|
|
57
|
-
fi
|
|
58
|
-
|
|
59
|
-
# Check for incomplete todos in the Claude todos directory
|
|
60
|
-
TODOS_DIR="$HOME/.claude/todos"
|
|
61
|
-
if [ -d "$TODOS_DIR" ]; then
|
|
62
|
-
# Look for any todo files with incomplete items
|
|
63
|
-
INCOMPLETE_COUNT=0
|
|
64
|
-
for todo_file in "$TODOS_DIR"/*.json; do
|
|
65
|
-
if [ -f "$todo_file" ]; then
|
|
66
|
-
if command -v jq &> /dev/null; then
|
|
67
|
-
COUNT=$(jq '[.[] | select(.status != "completed" and .status != "cancelled")] | length' "$todo_file" 2>/dev/null || echo "0")
|
|
68
|
-
INCOMPLETE_COUNT=$((INCOMPLETE_COUNT + COUNT))
|
|
69
|
-
fi
|
|
70
|
-
fi
|
|
71
|
-
done
|
|
72
|
-
|
|
73
|
-
# Combine task and todo counts
|
|
74
|
-
TOTAL_INCOMPLETE=$((TASK_COUNT + INCOMPLETE_COUNT))
|
|
75
|
-
|
|
76
|
-
if [ "$TOTAL_INCOMPLETE" -gt 0 ]; then
|
|
77
|
-
# Use Task terminology if we have tasks, otherwise todos
|
|
78
|
-
if [ "$TASK_COUNT" -gt 0 ]; then
|
|
79
|
-
cat << EOF
|
|
80
|
-
{"continue": false, "reason": "[SYSTEM REMINDER - TASK CONTINUATION]\\n\\nIncomplete Tasks remain ($TOTAL_INCOMPLETE remaining). Continue working on the next pending Task.\\n\\n- Proceed without asking for permission\\n- Mark each Task complete when finished\\n- Do not stop until all Tasks are done"}
|
|
81
|
-
EOF
|
|
82
|
-
else
|
|
83
|
-
cat << EOF
|
|
84
|
-
{"continue": false, "reason": "[SYSTEM REMINDER - TODO CONTINUATION]\\n\\nIncomplete tasks remain in your todo list ($TOTAL_INCOMPLETE remaining). Continue working on the next pending task.\\n\\n- Proceed without asking for permission\\n- Mark each task complete when finished\\n- Do not stop until all tasks are done"}
|
|
85
|
-
EOF
|
|
86
|
-
fi
|
|
87
|
-
exit 0
|
|
88
|
-
fi
|
|
89
|
-
fi
|
|
90
|
-
|
|
91
|
-
# No incomplete todos - allow stop
|
|
92
|
-
echo '{"continue": true}'
|
|
93
|
-
exit 0
|