oh-my-claude-sisyphus 3.6.2 → 3.7.0

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.
Files changed (124) hide show
  1. package/README.md +16 -0
  2. package/commands/doctor.md +1 -1
  3. package/dist/__tests__/delegation-enforcement-levels.test.d.ts +9 -0
  4. package/dist/__tests__/delegation-enforcement-levels.test.d.ts.map +1 -0
  5. package/dist/__tests__/delegation-enforcement-levels.test.js +550 -0
  6. package/dist/__tests__/delegation-enforcement-levels.test.js.map +1 -0
  7. package/dist/__tests__/installer.test.js +1 -1
  8. package/dist/__tests__/rate-limit-wait/daemon.test.d.ts +5 -0
  9. package/dist/__tests__/rate-limit-wait/daemon.test.d.ts.map +1 -0
  10. package/dist/__tests__/rate-limit-wait/daemon.test.js +313 -0
  11. package/dist/__tests__/rate-limit-wait/daemon.test.js.map +1 -0
  12. package/dist/__tests__/rate-limit-wait/integration.test.d.ts +8 -0
  13. package/dist/__tests__/rate-limit-wait/integration.test.d.ts.map +1 -0
  14. package/dist/__tests__/rate-limit-wait/integration.test.js +329 -0
  15. package/dist/__tests__/rate-limit-wait/integration.test.js.map +1 -0
  16. package/dist/__tests__/rate-limit-wait/rate-limit-monitor.test.d.ts +5 -0
  17. package/dist/__tests__/rate-limit-wait/rate-limit-monitor.test.d.ts.map +1 -0
  18. package/dist/__tests__/rate-limit-wait/rate-limit-monitor.test.js +167 -0
  19. package/dist/__tests__/rate-limit-wait/rate-limit-monitor.test.js.map +1 -0
  20. package/dist/__tests__/rate-limit-wait/tmux-detector.test.d.ts +5 -0
  21. package/dist/__tests__/rate-limit-wait/tmux-detector.test.d.ts.map +1 -0
  22. package/dist/__tests__/rate-limit-wait/tmux-detector.test.js +295 -0
  23. package/dist/__tests__/rate-limit-wait/tmux-detector.test.js.map +1 -0
  24. package/dist/__tests__/skills.test.js +6 -5
  25. package/dist/__tests__/skills.test.js.map +1 -1
  26. package/dist/cli/commands/wait.d.ts +52 -0
  27. package/dist/cli/commands/wait.d.ts.map +1 -0
  28. package/dist/cli/commands/wait.js +229 -0
  29. package/dist/cli/commands/wait.js.map +1 -0
  30. package/dist/cli/index.js +54 -0
  31. package/dist/cli/index.js.map +1 -1
  32. package/dist/features/rate-limit-wait/daemon.d.ts +52 -0
  33. package/dist/features/rate-limit-wait/daemon.d.ts.map +1 -0
  34. package/dist/features/rate-limit-wait/daemon.js +545 -0
  35. package/dist/features/rate-limit-wait/daemon.js.map +1 -0
  36. package/dist/features/rate-limit-wait/index.d.ts +16 -0
  37. package/dist/features/rate-limit-wait/index.d.ts.map +1 -0
  38. package/dist/features/rate-limit-wait/index.js +18 -0
  39. package/dist/features/rate-limit-wait/index.js.map +1 -0
  40. package/dist/features/rate-limit-wait/rate-limit-monitor.d.ts +22 -0
  41. package/dist/features/rate-limit-wait/rate-limit-monitor.d.ts.map +1 -0
  42. package/dist/features/rate-limit-wait/rate-limit-monitor.js +99 -0
  43. package/dist/features/rate-limit-wait/rate-limit-monitor.js.map +1 -0
  44. package/dist/features/rate-limit-wait/tmux-detector.d.ts +59 -0
  45. package/dist/features/rate-limit-wait/tmux-detector.d.ts.map +1 -0
  46. package/dist/features/rate-limit-wait/tmux-detector.js +304 -0
  47. package/dist/features/rate-limit-wait/tmux-detector.js.map +1 -0
  48. package/dist/features/rate-limit-wait/types.d.ts +121 -0
  49. package/dist/features/rate-limit-wait/types.d.ts.map +1 -0
  50. package/dist/features/rate-limit-wait/types.js +8 -0
  51. package/dist/features/rate-limit-wait/types.js.map +1 -0
  52. package/dist/hooks/bridge.d.ts +1 -1
  53. package/dist/hooks/bridge.d.ts.map +1 -1
  54. package/dist/hooks/bridge.js +50 -4
  55. package/dist/hooks/bridge.js.map +1 -1
  56. package/dist/hooks/index.d.ts +5 -0
  57. package/dist/hooks/index.d.ts.map +1 -1
  58. package/dist/hooks/index.js +15 -0
  59. package/dist/hooks/index.js.map +1 -1
  60. package/dist/hooks/omc-orchestrator/audit.d.ts +2 -1
  61. package/dist/hooks/omc-orchestrator/audit.d.ts.map +1 -1
  62. package/dist/hooks/omc-orchestrator/audit.js.map +1 -1
  63. package/dist/hooks/omc-orchestrator/index.d.ts +7 -0
  64. package/dist/hooks/omc-orchestrator/index.d.ts.map +1 -1
  65. package/dist/hooks/omc-orchestrator/index.js +95 -8
  66. package/dist/hooks/omc-orchestrator/index.js.map +1 -1
  67. package/dist/hooks/permission-handler/__tests__/index.test.d.ts +2 -0
  68. package/dist/hooks/permission-handler/__tests__/index.test.d.ts.map +1 -0
  69. package/dist/hooks/permission-handler/__tests__/index.test.js +244 -0
  70. package/dist/hooks/permission-handler/__tests__/index.test.js.map +1 -0
  71. package/dist/hooks/permission-handler/index.d.ts +42 -0
  72. package/dist/hooks/permission-handler/index.d.ts.map +1 -0
  73. package/dist/hooks/permission-handler/index.js +111 -0
  74. package/dist/hooks/permission-handler/index.js.map +1 -0
  75. package/dist/hooks/pre-compact/index.d.ts +82 -0
  76. package/dist/hooks/pre-compact/index.d.ts.map +1 -0
  77. package/dist/hooks/pre-compact/index.js +265 -0
  78. package/dist/hooks/pre-compact/index.js.map +1 -0
  79. package/dist/hooks/session-end/index.d.ts +50 -0
  80. package/dist/hooks/session-end/index.d.ts.map +1 -0
  81. package/dist/hooks/session-end/index.js +207 -0
  82. package/dist/hooks/session-end/index.js.map +1 -0
  83. package/dist/hooks/setup/index.d.ts +66 -0
  84. package/dist/hooks/setup/index.d.ts.map +1 -0
  85. package/dist/hooks/setup/index.js +299 -0
  86. package/dist/hooks/setup/index.js.map +1 -0
  87. package/dist/hooks/setup/types.d.ts +25 -0
  88. package/dist/hooks/setup/types.d.ts.map +1 -0
  89. package/dist/hooks/setup/types.js +5 -0
  90. package/dist/hooks/setup/types.js.map +1 -0
  91. package/dist/hooks/subagent-tracker/index.d.ts +68 -29
  92. package/dist/hooks/subagent-tracker/index.d.ts.map +1 -1
  93. package/dist/hooks/subagent-tracker/index.js +301 -131
  94. package/dist/hooks/subagent-tracker/index.js.map +1 -1
  95. package/dist/installer/index.d.ts +1 -1
  96. package/dist/installer/index.js +1 -1
  97. package/docs/MIGRATION.md +2 -2
  98. package/hooks/hooks.json +83 -1
  99. package/package.json +3 -1
  100. package/scripts/permission-handler.mjs +23 -0
  101. package/scripts/pre-compact.mjs +23 -0
  102. package/scripts/session-end.mjs +23 -0
  103. package/scripts/setup-init.mjs +23 -0
  104. package/scripts/setup-maintenance.mjs +23 -0
  105. package/scripts/subagent-tracker.mjs +35 -0
  106. package/skills/doctor/SKILL.md +1 -1
  107. package/templates/hooks/keyword-detector.mjs +198 -0
  108. package/templates/hooks/keyword-detector.sh +102 -0
  109. package/templates/hooks/persistent-mode.mjs +249 -0
  110. package/templates/hooks/persistent-mode.sh +187 -0
  111. package/templates/hooks/post-tool-use.mjs +133 -0
  112. package/templates/hooks/post-tool-use.sh +90 -0
  113. package/templates/hooks/pre-tool-use.mjs +145 -0
  114. package/templates/hooks/pre-tool-use.sh +113 -0
  115. package/templates/hooks/session-start.mjs +100 -0
  116. package/templates/hooks/session-start.sh +62 -0
  117. package/templates/hooks/stop-continuation.mjs +80 -0
  118. package/templates/hooks/stop-continuation.sh +40 -0
  119. package/templates/rules/README.md +40 -0
  120. package/templates/rules/coding-style.md +74 -0
  121. package/templates/rules/git-workflow.md +41 -0
  122. package/templates/rules/performance.md +40 -0
  123. package/templates/rules/security.md +41 -0
  124. package/templates/rules/testing.md +42 -0
@@ -0,0 +1,145 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * OMC Pre-Tool-Use Hook (Node.js)
4
+ * Enforces delegation by warning when orchestrator attempts direct source file edits
5
+ */
6
+
7
+ import * as path from 'path';
8
+
9
+ // Allowed path patterns (no warning)
10
+ const ALLOWED_PATH_PATTERNS = [
11
+ /\.omc\//,
12
+ /\.claude\//,
13
+ /\/\.claude\//,
14
+ /CLAUDE\.md$/,
15
+ /AGENTS\.md$/,
16
+ ];
17
+
18
+ // Source file extensions (should warn)
19
+ const SOURCE_EXTENSIONS = new Set([
20
+ '.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs',
21
+ '.py', '.pyw',
22
+ '.go', '.rs', '.java', '.kt', '.scala',
23
+ '.c', '.cpp', '.cc', '.h', '.hpp',
24
+ '.rb', '.php',
25
+ '.svelte', '.vue',
26
+ '.graphql', '.gql',
27
+ '.sh', '.bash', '.zsh',
28
+ ]);
29
+
30
+ function isAllowedPath(filePath) {
31
+ if (!filePath) return true;
32
+ return ALLOWED_PATH_PATTERNS.some(pattern => pattern.test(filePath));
33
+ }
34
+
35
+ function isSourceFile(filePath) {
36
+ if (!filePath) return false;
37
+ const ext = path.extname(filePath).toLowerCase();
38
+ return SOURCE_EXTENSIONS.has(ext);
39
+ }
40
+
41
+ // Patterns that indicate file modification in bash commands
42
+ const FILE_MODIFY_PATTERNS = [
43
+ /sed\s+-i/,
44
+ />\s*[^&]/,
45
+ />>/,
46
+ /tee\s+/,
47
+ /cat\s+.*>\s*/,
48
+ /echo\s+.*>\s*/,
49
+ /printf\s+.*>\s*/,
50
+ ];
51
+
52
+ // Source file pattern for command inspection
53
+ const SOURCE_EXT_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)/i;
54
+
55
+ function checkBashCommand(command) {
56
+ // Check if command might modify files
57
+ const mayModify = FILE_MODIFY_PATTERNS.some(pattern => pattern.test(command));
58
+ if (!mayModify) return null;
59
+
60
+ // Check if it might affect source files
61
+ if (SOURCE_EXT_PATTERN.test(command)) {
62
+ return `[DELEGATION NOTICE] Bash command may modify source files: ${command}
63
+
64
+ Recommended: Delegate to executor agent instead:
65
+ Task(subagent_type="oh-my-claudecode:executor", model="sonnet", prompt="...")
66
+
67
+ This is a soft warning. Operation will proceed.`;
68
+ }
69
+ return null;
70
+ }
71
+
72
+ async function main() {
73
+ let input = '';
74
+
75
+ // Read stdin
76
+ for await (const chunk of process.stdin) {
77
+ input += chunk;
78
+ }
79
+
80
+ let data;
81
+ try {
82
+ data = JSON.parse(input);
83
+ } catch {
84
+ console.log(JSON.stringify({ continue: true }));
85
+ return;
86
+ }
87
+
88
+ // Extract tool name (handle both cases)
89
+ const toolName = data.tool_name || data.toolName || '';
90
+
91
+ // Handle Bash tool separately - check for file modification patterns
92
+ if (toolName === 'Bash' || toolName === 'bash') {
93
+ const toolInput = data.tool_input || data.toolInput || {};
94
+ const command = toolInput.command || '';
95
+ const warning = checkBashCommand(command);
96
+ if (warning) {
97
+ console.log(JSON.stringify({ continue: true, message: warning }));
98
+ } else {
99
+ console.log(JSON.stringify({ continue: true }));
100
+ }
101
+ return;
102
+ }
103
+
104
+ // Only check Edit and Write tools
105
+ if (!['Edit', 'Write', 'edit', 'write'].includes(toolName)) {
106
+ console.log(JSON.stringify({ continue: true }));
107
+ return;
108
+ }
109
+
110
+ // Extract file path (handle nested structures)
111
+ const toolInput = data.tool_input || data.toolInput || {};
112
+ const filePath = toolInput.file_path || toolInput.filePath || '';
113
+
114
+ // No file path? Allow
115
+ if (!filePath) {
116
+ console.log(JSON.stringify({ continue: true }));
117
+ return;
118
+ }
119
+
120
+ // Check if allowed path
121
+ if (isAllowedPath(filePath)) {
122
+ console.log(JSON.stringify({ continue: true }));
123
+ return;
124
+ }
125
+
126
+ // Check if source file
127
+ if (isSourceFile(filePath)) {
128
+ const warning = `[DELEGATION NOTICE] Direct ${toolName} on source file: ${filePath}
129
+
130
+ Recommended: Delegate to executor agent instead:
131
+ Task(subagent_type="oh-my-claudecode:executor", model="sonnet", prompt="...")
132
+
133
+ This is a soft warning. Operation will proceed.`;
134
+
135
+ console.log(JSON.stringify({ continue: true, message: warning }));
136
+ return;
137
+ }
138
+
139
+ // Not a source file, allow without warning
140
+ console.log(JSON.stringify({ continue: true }));
141
+ }
142
+
143
+ main().catch(() => {
144
+ console.log(JSON.stringify({ continue: true }));
145
+ });
@@ -0,0 +1,113 @@
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
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env node
2
+ // OMC Session Start Hook (Node.js)
3
+ // Restores persistent mode states when session starts
4
+ // Cross-platform: Windows, macOS, Linux
5
+
6
+ import { existsSync, readFileSync, readdirSync } from 'fs';
7
+ import { join } from 'path';
8
+ import { homedir } from 'os';
9
+
10
+ async function readStdin() {
11
+ const chunks = [];
12
+ for await (const chunk of process.stdin) {
13
+ chunks.push(chunk);
14
+ }
15
+ return Buffer.concat(chunks).toString('utf-8');
16
+ }
17
+
18
+ function readJsonFile(path) {
19
+ try {
20
+ if (!existsSync(path)) return null;
21
+ return JSON.parse(readFileSync(path, 'utf-8'));
22
+ } catch {
23
+ return null;
24
+ }
25
+ }
26
+
27
+ function countIncompleteTodos(todosDir) {
28
+ let count = 0;
29
+ if (existsSync(todosDir)) {
30
+ try {
31
+ const files = readdirSync(todosDir).filter(f => f.endsWith('.json'));
32
+ for (const file of files) {
33
+ const todos = readJsonFile(join(todosDir, file));
34
+ if (Array.isArray(todos)) {
35
+ count += todos.filter(t => t.status !== 'completed' && t.status !== 'cancelled').length;
36
+ }
37
+ }
38
+ } catch {}
39
+ }
40
+ return count;
41
+ }
42
+
43
+ async function main() {
44
+ try {
45
+ const input = await readStdin();
46
+ let data = {};
47
+ try { data = JSON.parse(input); } catch {}
48
+
49
+ const directory = data.directory || process.cwd();
50
+ const messages = [];
51
+
52
+ // Check for ultrawork state
53
+ const ultraworkState = readJsonFile(join(directory, '.omc', 'ultrawork-state.json'))
54
+ || readJsonFile(join(homedir(), '.claude', 'ultrawork-state.json'));
55
+
56
+ if (ultraworkState?.active) {
57
+ messages.push(`<session-restore>
58
+
59
+ [ULTRAWORK MODE RESTORED]
60
+
61
+ You have an active ultrawork session from ${ultraworkState.started_at}.
62
+ Original task: ${ultraworkState.original_prompt}
63
+
64
+ Continue working in ultrawork mode until all tasks are complete.
65
+
66
+ </session-restore>
67
+
68
+ ---
69
+ `);
70
+ }
71
+
72
+ // Check for incomplete todos
73
+ const todosDir = join(homedir(), '.claude', 'todos');
74
+ const incompleteCount = countIncompleteTodos(todosDir);
75
+
76
+ if (incompleteCount > 0) {
77
+ messages.push(`<session-restore>
78
+
79
+ [PENDING TASKS DETECTED]
80
+
81
+ You have ${incompleteCount} incomplete tasks from a previous session.
82
+ Please continue working on these tasks.
83
+
84
+ </session-restore>
85
+
86
+ ---
87
+ `);
88
+ }
89
+
90
+ if (messages.length > 0) {
91
+ console.log(JSON.stringify({ continue: true, message: messages.join('\n') }));
92
+ } else {
93
+ console.log(JSON.stringify({ continue: true }));
94
+ }
95
+ } catch (error) {
96
+ console.log(JSON.stringify({ continue: true }));
97
+ }
98
+ }
99
+
100
+ main();
@@ -0,0 +1,62 @@
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/ultrawork-state.json" ] || [ -f "$HOME/.claude/ultrawork-state.json" ]; then
22
+ if [ -f "$DIRECTORY/.omc/ultrawork-state.json" ]; then
23
+ ULTRAWORK_STATE=$(cat "$DIRECTORY/.omc/ultrawork-state.json" 2>/dev/null)
24
+ else
25
+ ULTRAWORK_STATE=$(cat "$HOME/.claude/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
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env node
2
+ // OMC Stop Continuation Hook (Node.js)
3
+ // Checks for incomplete todos and injects continuation prompt
4
+ // Cross-platform: Windows, macOS, Linux
5
+
6
+ import { readdirSync, readFileSync, existsSync } from 'fs';
7
+ import { join } from 'path';
8
+ import { homedir } from 'os';
9
+
10
+ // Read all stdin
11
+ async function readStdin() {
12
+ const chunks = [];
13
+ for await (const chunk of process.stdin) {
14
+ chunks.push(chunk);
15
+ }
16
+ return Buffer.concat(chunks).toString('utf-8');
17
+ }
18
+
19
+ // Main
20
+ async function main() {
21
+ try {
22
+ // Read stdin (we don't use it much, but need to consume it)
23
+ await readStdin();
24
+
25
+ // Check for incomplete todos
26
+ const todosDir = join(homedir(), '.claude', 'todos');
27
+
28
+ if (!existsSync(todosDir)) {
29
+ console.log(JSON.stringify({ continue: true }));
30
+ return;
31
+ }
32
+
33
+ let incompleteCount = 0;
34
+
35
+ try {
36
+ const files = readdirSync(todosDir).filter(f => f.endsWith('.json'));
37
+
38
+ for (const file of files) {
39
+ try {
40
+ const content = readFileSync(join(todosDir, file), 'utf-8');
41
+ const todos = JSON.parse(content);
42
+
43
+ if (Array.isArray(todos)) {
44
+ const incomplete = todos.filter(
45
+ t => t.status !== 'completed' && t.status !== 'cancelled'
46
+ );
47
+ incompleteCount += incomplete.length;
48
+ }
49
+ } catch {
50
+ // Skip files that can't be parsed
51
+ }
52
+ }
53
+ } catch {
54
+ // Directory read error - allow continuation
55
+ console.log(JSON.stringify({ continue: true }));
56
+ return;
57
+ }
58
+
59
+ if (incompleteCount > 0) {
60
+ const reason = `[SYSTEM REMINDER - TODO CONTINUATION]
61
+
62
+ Incomplete tasks remain in your todo list (${incompleteCount} remaining). Continue working on the next pending task.
63
+
64
+ - Proceed without asking for permission
65
+ - Mark each task complete when finished
66
+ - Do not stop until all tasks are done`;
67
+
68
+ console.log(JSON.stringify({ continue: false, reason }));
69
+ return;
70
+ }
71
+
72
+ // No incomplete todos - allow stop
73
+ console.log(JSON.stringify({ continue: true }));
74
+ } catch (error) {
75
+ // On any error, allow continuation
76
+ console.log(JSON.stringify({ continue: true }));
77
+ }
78
+ }
79
+
80
+ main();
@@ -0,0 +1,40 @@
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
+ # Read stdin
7
+ INPUT=$(cat)
8
+
9
+ # Get session ID if available
10
+ SESSION_ID=""
11
+ if command -v jq &> /dev/null; then
12
+ SESSION_ID=$(echo "$INPUT" | jq -r '.sessionId // .session_id // ""' 2>/dev/null)
13
+ fi
14
+
15
+ # Check for incomplete todos in the Claude todos directory
16
+ TODOS_DIR="$HOME/.claude/todos"
17
+ if [ -d "$TODOS_DIR" ]; then
18
+ # Look for any todo files with incomplete items
19
+ INCOMPLETE_COUNT=0
20
+ for todo_file in "$TODOS_DIR"/*.json; do
21
+ if [ -f "$todo_file" ]; then
22
+ if command -v jq &> /dev/null; then
23
+ COUNT=$(jq '[.[] | select(.status != "completed" and .status != "cancelled")] | length' "$todo_file" 2>/dev/null || echo "0")
24
+ INCOMPLETE_COUNT=$((INCOMPLETE_COUNT + COUNT))
25
+ fi
26
+ fi
27
+ done
28
+
29
+ if [ "$INCOMPLETE_COUNT" -gt 0 ]; then
30
+ # Output continuation message
31
+ cat << EOF
32
+ {"continue": false, "reason": "[SYSTEM REMINDER - TODO CONTINUATION]\\n\\nIncomplete tasks remain in your todo list ($INCOMPLETE_COUNT 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"}
33
+ EOF
34
+ exit 0
35
+ fi
36
+ fi
37
+
38
+ # No incomplete todos - allow stop
39
+ echo '{"continue": true}'
40
+ exit 0
@@ -0,0 +1,40 @@
1
+ # Rules Templates
2
+
3
+ This directory contains rule templates that you can copy to your project's `.claude/rules/` directory.
4
+
5
+ ## How to Use
6
+
7
+ 1. Create a `.claude/rules/` directory in your project root
8
+ 2. Copy the templates you want to use
9
+ 3. Customize them for your project
10
+ 4. Rules in `.claude/rules/*.md` will be auto-discovered and injected into context
11
+
12
+ ## Available Templates
13
+
14
+ | Template | Purpose |
15
+ |----------|---------|
16
+ | `coding-style.md` | Code style and formatting guidelines |
17
+ | `testing.md` | Testing requirements and coverage targets |
18
+ | `security.md` | Security checklist and best practices |
19
+ | `performance.md` | Performance guidelines and model selection |
20
+ | `git-workflow.md` | Git commit and PR workflow |
21
+
22
+ ## Auto-Discovery
23
+
24
+ When you place rules in `.claude/rules/`, they are automatically discovered by oh-my-claudecode and injected into the context for all agents working in your project.
25
+
26
+ ## Example
27
+
28
+ ```bash
29
+ # Copy templates to your project
30
+ mkdir -p .claude/rules
31
+ cp templates/rules/security.md .claude/rules/
32
+ cp templates/rules/testing.md .claude/rules/
33
+
34
+ # Customize for your project
35
+ # Edit .claude/rules/security.md to add project-specific checks
36
+ ```
37
+
38
+ ## Customization
39
+
40
+ Each template has `[CUSTOMIZE]` markers where you should add project-specific guidelines.
@@ -0,0 +1,74 @@
1
+ # Coding Style Rules
2
+
3
+ ## Immutability (CRITICAL)
4
+
5
+ ALWAYS create new objects, NEVER mutate:
6
+
7
+ ```javascript
8
+ // WRONG: Mutation
9
+ function updateUser(user, name) {
10
+ user.name = name // MUTATION!
11
+ return user
12
+ }
13
+
14
+ // CORRECT: Immutability
15
+ function updateUser(user, name) {
16
+ return { ...user, name }
17
+ }
18
+ ```
19
+
20
+ ## File Organization
21
+
22
+ MANY SMALL FILES > FEW LARGE FILES:
23
+ - High cohesion, low coupling
24
+ - 200-400 lines typical, 800 max
25
+ - Extract utilities from large components
26
+ - Organize by feature/domain, not by type
27
+
28
+ ## Error Handling
29
+
30
+ ALWAYS handle errors comprehensively:
31
+
32
+ ```typescript
33
+ try {
34
+ const result = await riskyOperation()
35
+ return result
36
+ } catch (error) {
37
+ console.error('Operation failed:', error)
38
+ throw new Error('User-friendly error message')
39
+ }
40
+ ```
41
+
42
+ ## Input Validation
43
+
44
+ ALWAYS validate user input:
45
+
46
+ ```typescript
47
+ import { z } from 'zod'
48
+
49
+ const schema = z.object({
50
+ email: z.string().email(),
51
+ age: z.number().int().min(0).max(150)
52
+ })
53
+
54
+ const validated = schema.parse(input)
55
+ ```
56
+
57
+ ## Code Quality Checklist
58
+
59
+ Before marking work complete:
60
+ - [ ] Code is readable and well-named
61
+ - [ ] Functions are small (<50 lines)
62
+ - [ ] Files are focused (<800 lines)
63
+ - [ ] No deep nesting (>4 levels)
64
+ - [ ] Proper error handling
65
+ - [ ] No console.log statements
66
+ - [ ] No hardcoded values
67
+ - [ ] Immutable patterns used
68
+
69
+ ## [CUSTOMIZE] Project-Specific Style
70
+
71
+ Add your project-specific coding style rules here:
72
+ - Naming conventions
73
+ - File structure requirements
74
+ - Framework-specific patterns
@@ -0,0 +1,41 @@
1
+ # Git Workflow Rules
2
+
3
+ ## Commit Message Format
4
+
5
+ ```
6
+ <type>: <description>
7
+
8
+ <optional body>
9
+ ```
10
+
11
+ Types: feat, fix, refactor, docs, test, chore, perf, ci
12
+
13
+ ## Pull Request Workflow
14
+
15
+ When creating PRs:
16
+ 1. Analyze full commit history (not just latest commit)
17
+ 2. Use `git diff [base-branch]...HEAD` to see all changes
18
+ 3. Draft comprehensive PR summary
19
+ 4. Include test plan with TODOs
20
+ 5. Push with `-u` flag if new branch
21
+
22
+ ## Feature Implementation Workflow
23
+
24
+ 1. **Plan First** - Use `planner` agent
25
+ 2. **TDD Approach** - Use `tdd-guide` agent
26
+ 3. **Code Review** - Use `code-reviewer` agent after writing code
27
+ 4. **Commit** - Follow conventional commits format
28
+
29
+ ## Branch Naming
30
+
31
+ - `feature/` - New features
32
+ - `fix/` - Bug fixes
33
+ - `refactor/` - Code refactoring
34
+ - `docs/` - Documentation changes
35
+
36
+ ## [CUSTOMIZE] Project-Specific Git Rules
37
+
38
+ Add your project-specific git workflow here:
39
+ - Branch protection rules
40
+ - Required reviewers
41
+ - CI/CD requirements