cortexhawk 3.1.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.
- package/.cortexhawk-team.yml +65 -0
- package/CHANGELOG.md +268 -0
- package/CLAUDE.md +96 -0
- package/LICENSE +21 -0
- package/PACKS.md +14 -0
- package/README.md +418 -0
- package/REGISTRY.md +23 -0
- package/agents/architect.md +46 -0
- package/agents/brainstormer.md +57 -0
- package/agents/code-simplifier.md +56 -0
- package/agents/codebase-mapper.md +63 -0
- package/agents/copywriter.md +48 -0
- package/agents/debugger.md +44 -0
- package/agents/designer.md +53 -0
- package/agents/devops.md +49 -0
- package/agents/docs-manager.md +50 -0
- package/agents/fullstack-developer.md +55 -0
- package/agents/git-manager.md +63 -0
- package/agents/implementer.md +30 -0
- package/agents/journal-writer.md +53 -0
- package/agents/planner.md +52 -0
- package/agents/project-manager.md +50 -0
- package/agents/researcher.md +46 -0
- package/agents/reviewer.md +63 -0
- package/agents/security-auditor.md +92 -0
- package/agents/teacher.md +71 -0
- package/agents/tester.md +41 -0
- package/commands/api-gen.md +17 -0
- package/commands/backlog.md +26 -0
- package/commands/bootstrap.md +32 -0
- package/commands/brainstorm.md +18 -0
- package/commands/build.md +16 -0
- package/commands/chain.md +46 -0
- package/commands/changelog.md +16 -0
- package/commands/check.md +40 -0
- package/commands/ci.md +32 -0
- package/commands/context.md +35 -0
- package/commands/debug.md +16 -0
- package/commands/deploy.md +16 -0
- package/commands/doc.md +15 -0
- package/commands/export.md +17 -0
- package/commands/journal.md +18 -0
- package/commands/learn.md +16 -0
- package/commands/map.md +16 -0
- package/commands/migrate.md +17 -0
- package/commands/monitor.md +16 -0
- package/commands/optimize.md +17 -0
- package/commands/plan.md +17 -0
- package/commands/pulse.md +46 -0
- package/commands/refactor.md +16 -0
- package/commands/research.md +18 -0
- package/commands/review.md +16 -0
- package/commands/scan.md +19 -0
- package/commands/ship.md +17 -0
- package/commands/simplify.md +16 -0
- package/commands/task.md +32 -0
- package/commands/tdd.md +17 -0
- package/commands/test.md +16 -0
- package/commands/upgrade.md +27 -0
- package/cortexhawk +450 -0
- package/hooks/agent-analytics.sh +67 -0
- package/hooks/branch-guard.sh +56 -0
- package/hooks/codex-dispatcher.sh +84 -0
- package/hooks/commit-guard.sh +71 -0
- package/hooks/compose.yml +47 -0
- package/hooks/dependency-check.sh +56 -0
- package/hooks/file-guard.sh +69 -0
- package/hooks/hooks.json +46 -0
- package/hooks/self-review.sh +71 -0
- package/hooks/session-start.sh +132 -0
- package/hooks/session-telemetry.sh +60 -0
- package/hooks/test-reminder.sh +75 -0
- package/install.sh +3805 -0
- package/mcp/README.md +37 -0
- package/mcp/context7.json +8 -0
- package/mcp/puppeteer.json +8 -0
- package/mcp/sequential-thinking.json +8 -0
- package/modes/default.md +5 -0
- package/modes/fast.md +5 -0
- package/modes/learn.md +9 -0
- package/modes/orchestration.md +5 -0
- package/modes/pair.md +10 -0
- package/modes/research.md +5 -0
- package/modes/review.md +5 -0
- package/package.json +32 -0
- package/profiles/api.json +27 -0
- package/profiles/data.json +23 -0
- package/profiles/fullstack.json +27 -0
- package/scripts/autodetect-profile.sh +68 -0
- package/scripts/benchmark.sh +106 -0
- package/scripts/chain-post-save.sh +23 -0
- package/scripts/generate-plans-index.sh +50 -0
- package/scripts/git-workflow-init.sh +115 -0
- package/scripts/install-codex.sh +128 -0
- package/scripts/interactive-init.sh +264 -0
- package/scripts/post-install-audit.sh +130 -0
- package/scripts/validate.sh +214 -0
- package/settings.json +90 -0
- package/setup.sh +67 -0
- package/skills/databases/schema-designer/SKILL.md +54 -0
- package/skills/databases/sql-optimizer/SKILL.md +37 -0
- package/skills/devops/ci-cd/SKILL.md +59 -0
- package/skills/devops/deployment/SKILL.md +49 -0
- package/skills/devops/docker/SKILL.md +57 -0
- package/skills/frameworks/api-design/SKILL.md +103 -0
- package/skills/frameworks/fastapi/SKILL.md +68 -0
- package/skills/frameworks/nextjs/SKILL.md +74 -0
- package/skills/frameworks/python/SKILL.md +89 -0
- package/skills/frameworks/react/SKILL.md +83 -0
- package/skills/frameworks/sveltekit/SKILL.md +69 -0
- package/skills/frameworks/tailwindcss/SKILL.md +75 -0
- package/skills/frameworks/typescript/SKILL.md +94 -0
- package/skills/meta/mcp-builder/SKILL.md +54 -0
- package/skills/meta/skill-creator/SKILL.md +43 -0
- package/skills/optimization/performance/SKILL.md +70 -0
- package/skills/quality/complexity-analyzer/SKILL.md +52 -0
- package/skills/quality/error-handling/SKILL.md +123 -0
- package/skills/quality/log-analyzer/SKILL.md +31 -0
- package/skills/quality/pattern-detector/SKILL.md +50 -0
- package/skills/security/auth-analyzer/SKILL.md +96 -0
- package/skills/security/compliance-checker/SKILL.md +92 -0
- package/skills/security/container-security/SKILL.md +128 -0
- package/skills/security/dependency-auditor/SKILL.md +100 -0
- package/skills/security/encryption/SKILL.md +94 -0
- package/skills/security/incident-response/SKILL.md +127 -0
- package/skills/security/secrets/SKILL.md +93 -0
- package/skills/security/security-headers/SKILL.md +83 -0
- package/skills/security/security-logging/SKILL.md +107 -0
- package/skills/security/vulnerability-scanner/SKILL.md +114 -0
- package/skills/testing/e2e-testing/SKILL.md +119 -0
- package/skills/testing/tdd/SKILL.md +40 -0
- package/skills/testing/test-generator/SKILL.md +39 -0
- package/skills/workflow/commit/SKILL.md +61 -0
- package/skills/workflow/confidence-check/SKILL.md +90 -0
- package/skills/workflow/pr-review-comments/SKILL.md +81 -0
- package/skills/workflow/pr-review-comments/scripts/fetch_comments.py +237 -0
package/cortexhawk
ADDED
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# cortexhawk — CLI wrapper for CortexHawk development toolkit
|
|
3
|
+
# Install via: npm install -g cortexhawk | ./setup.sh | git clone
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
# Resolve CORTEXHAWK_HOME: env var > script location > default
|
|
8
|
+
if [ -z "$CORTEXHAWK_HOME" ]; then
|
|
9
|
+
# Resolve symlinks to find the actual script location (npm global symlinks)
|
|
10
|
+
SOURCE="${BASH_SOURCE[0]}"
|
|
11
|
+
while [ -L "$SOURCE" ]; do
|
|
12
|
+
DIR="$(cd -P "$(dirname "$SOURCE")" && pwd)"
|
|
13
|
+
SOURCE="$(readlink "$SOURCE")"
|
|
14
|
+
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
|
|
15
|
+
done
|
|
16
|
+
SCRIPT_DIR="$(cd -P "$(dirname "$SOURCE")" && pwd)"
|
|
17
|
+
|
|
18
|
+
if [ -f "$SCRIPT_DIR/install.sh" ]; then
|
|
19
|
+
CORTEXHAWK_HOME="$SCRIPT_DIR"
|
|
20
|
+
else
|
|
21
|
+
CORTEXHAWK_HOME="$HOME/.cortexhawk"
|
|
22
|
+
fi
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
INSTALL_SH="$CORTEXHAWK_HOME/install.sh"
|
|
26
|
+
|
|
27
|
+
green() { printf "\033[32m%s\033[0m\n" "$1"; }
|
|
28
|
+
yellow() { printf "\033[33m%s\033[0m\n" "$1"; }
|
|
29
|
+
red() { printf "\033[31m%s\033[0m\n" "$1"; }
|
|
30
|
+
|
|
31
|
+
get_version() {
|
|
32
|
+
grep -m1 '## \[' "$CORTEXHAWK_HOME/CHANGELOG.md" 2>/dev/null | sed 's/.*\[\([^]]*\)\].*/\1/' || echo "unknown"
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
# --- validate command ---
|
|
36
|
+
do_validate() {
|
|
37
|
+
local project_root="${1:-.}"
|
|
38
|
+
local ok=0 fail=0 warn=0
|
|
39
|
+
|
|
40
|
+
echo "CortexHawk Validate"
|
|
41
|
+
echo "======================"
|
|
42
|
+
echo " Project: $(cd "$project_root" && pwd)"
|
|
43
|
+
echo ""
|
|
44
|
+
|
|
45
|
+
# Detect installed targets
|
|
46
|
+
local targets_found=()
|
|
47
|
+
[ -f "$project_root/.claude/.cortexhawk-manifest" ] && targets_found+=("claude")
|
|
48
|
+
[ -f "$project_root/.kimi/.cortexhawk-manifest" ] && targets_found+=("kimi")
|
|
49
|
+
[ -f "$project_root/.codex/.cortexhawk-manifest" ] && targets_found+=("codex")
|
|
50
|
+
|
|
51
|
+
if [ ${#targets_found[@]} -eq 0 ]; then
|
|
52
|
+
red " No CortexHawk installation found in this directory."
|
|
53
|
+
echo " Run: cortexhawk install"
|
|
54
|
+
return 1
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
echo " Targets found: ${targets_found[*]}"
|
|
58
|
+
echo ""
|
|
59
|
+
|
|
60
|
+
check() {
|
|
61
|
+
local label="$1" result="$2"
|
|
62
|
+
if [ "$result" = "ok" ]; then
|
|
63
|
+
printf " \033[32m[OK]\033[0m %s\n" "$label"
|
|
64
|
+
ok=$((ok + 1))
|
|
65
|
+
elif [ "$result" = "warn" ]; then
|
|
66
|
+
printf " \033[33m[!!]\033[0m %s\n" "$label"
|
|
67
|
+
warn=$((warn + 1))
|
|
68
|
+
else
|
|
69
|
+
printf " \033[31m[FAIL]\033[0m %s\n" "$label"
|
|
70
|
+
fail=$((fail + 1))
|
|
71
|
+
fi
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
for target in "${targets_found[@]}"; do
|
|
75
|
+
echo "--- $target ---"
|
|
76
|
+
local target_dir=""
|
|
77
|
+
case "$target" in
|
|
78
|
+
claude) target_dir="$project_root/.claude" ;;
|
|
79
|
+
kimi) target_dir="$project_root/.kimi" ;;
|
|
80
|
+
codex) target_dir="$project_root/.codex" ;;
|
|
81
|
+
esac
|
|
82
|
+
|
|
83
|
+
# 1. Manifest
|
|
84
|
+
if [ -f "$target_dir/.cortexhawk-manifest" ]; then
|
|
85
|
+
local ver
|
|
86
|
+
ver=$(grep -o '"version": "[^"]*"' "$target_dir/.cortexhawk-manifest" 2>/dev/null | head -1 | cut -d'"' -f4)
|
|
87
|
+
check "Manifest present (v$ver)" "ok"
|
|
88
|
+
else
|
|
89
|
+
check "Manifest missing" "fail"
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
# 2. Skills count
|
|
93
|
+
local skills_count=0
|
|
94
|
+
if [ -d "$target_dir/skills" ]; then
|
|
95
|
+
skills_count=$(find "$target_dir/skills" -name "*.md" -type f 2>/dev/null | wc -l | tr -d ' ')
|
|
96
|
+
fi
|
|
97
|
+
if [ "$skills_count" -gt 0 ]; then
|
|
98
|
+
check "Skills: $skills_count files found" "ok"
|
|
99
|
+
else
|
|
100
|
+
check "Skills: none found in $target_dir/skills/" "fail"
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
# 3. Target-specific checks
|
|
104
|
+
case "$target" in
|
|
105
|
+
claude)
|
|
106
|
+
# Agents
|
|
107
|
+
local agent_count=0
|
|
108
|
+
[ -d "$target_dir/agents" ] && agent_count=$(find "$target_dir/agents" -name "*.md" -type f 2>/dev/null | wc -l | tr -d ' ')
|
|
109
|
+
[ "$agent_count" -gt 0 ] && check "Agents: $agent_count files" "ok" || check "Agents: none found" "fail"
|
|
110
|
+
|
|
111
|
+
# Commands
|
|
112
|
+
local cmd_count=0
|
|
113
|
+
[ -d "$target_dir/commands" ] && cmd_count=$(find "$target_dir/commands" -name "*.md" -type f 2>/dev/null | wc -l | tr -d ' ')
|
|
114
|
+
[ "$cmd_count" -gt 0 ] && check "Commands: $cmd_count files" "ok" || check "Commands: none found" "fail"
|
|
115
|
+
|
|
116
|
+
# Hooks
|
|
117
|
+
local hook_count=0
|
|
118
|
+
[ -d "$target_dir/hooks" ] && hook_count=$(find "$target_dir/hooks" -name "*.sh" -type f 2>/dev/null | wc -l | tr -d ' ')
|
|
119
|
+
[ "$hook_count" -gt 0 ] && check "Hooks: $hook_count files" "ok" || check "Hooks: none found" "warn"
|
|
120
|
+
|
|
121
|
+
# settings.json
|
|
122
|
+
if [ -f "$target_dir/settings.json" ]; then
|
|
123
|
+
if python3 -c "import json; json.load(open('$target_dir/settings.json'))" 2>/dev/null || \
|
|
124
|
+
node -e "JSON.parse(require('fs').readFileSync('$target_dir/settings.json'))" 2>/dev/null; then
|
|
125
|
+
check "settings.json valid JSON" "ok"
|
|
126
|
+
else
|
|
127
|
+
check "settings.json invalid JSON" "fail"
|
|
128
|
+
fi
|
|
129
|
+
else
|
|
130
|
+
check "settings.json missing" "warn"
|
|
131
|
+
fi
|
|
132
|
+
|
|
133
|
+
# Modes
|
|
134
|
+
local mode_count=0
|
|
135
|
+
[ -d "$target_dir/modes" ] && mode_count=$(find "$target_dir/modes" -name "*.md" -type f 2>/dev/null | wc -l | tr -d ' ')
|
|
136
|
+
[ "$mode_count" -gt 0 ] && check "Modes: $mode_count files" "ok" || check "Modes: none found" "warn"
|
|
137
|
+
;;
|
|
138
|
+
|
|
139
|
+
kimi)
|
|
140
|
+
# AGENTS.md at project root
|
|
141
|
+
if [ -f "$project_root/AGENTS.md" ] && grep -q "CortexHawk" "$project_root/AGENTS.md" 2>/dev/null; then
|
|
142
|
+
check "AGENTS.md in project root" "ok"
|
|
143
|
+
else
|
|
144
|
+
check "AGENTS.md missing or not CortexHawk" "fail"
|
|
145
|
+
fi
|
|
146
|
+
|
|
147
|
+
# Commands as skills
|
|
148
|
+
local cmd_skills=0
|
|
149
|
+
cmd_skills=$(find "$target_dir/skills/cmd-"* -maxdepth 0 -type d 2>/dev/null | wc -l | tr -d ' ')
|
|
150
|
+
[ "$cmd_skills" -gt 0 ] && check "Commands as skills: $cmd_skills" "ok" || check "Commands as skills: none" "fail"
|
|
151
|
+
|
|
152
|
+
# Hooks as skills
|
|
153
|
+
local hook_skills=0
|
|
154
|
+
hook_skills=$(find "$target_dir/skills/hook-"* -maxdepth 0 -type d 2>/dev/null | wc -l | tr -d ' ')
|
|
155
|
+
[ "$hook_skills" -gt 0 ] && check "Hooks as skills: $hook_skills" "ok" || check "Hooks as skills: none" "warn"
|
|
156
|
+
|
|
157
|
+
# Agents as skills
|
|
158
|
+
local agent_skills=0
|
|
159
|
+
agent_skills=$(find "$target_dir/skills/agent-"* -maxdepth 0 -type d 2>/dev/null | wc -l | tr -d ' ')
|
|
160
|
+
[ "$agent_skills" -gt 0 ] && check "Agents as skills: $agent_skills" "ok" || check "Agents as skills: none" "fail"
|
|
161
|
+
|
|
162
|
+
# Modes as skills
|
|
163
|
+
local mode_skills=0
|
|
164
|
+
[ -d "$target_dir/skills/modes" ] && mode_skills=$(find "$target_dir/skills/modes" -maxdepth 1 -type d 2>/dev/null | wc -l | tr -d ' ')
|
|
165
|
+
mode_skills=$((mode_skills - 1)) 2>/dev/null || mode_skills=0
|
|
166
|
+
[ "$mode_skills" -gt 0 ] && check "Modes as skills: $mode_skills" "ok" || check "Modes as skills: none" "warn"
|
|
167
|
+
|
|
168
|
+
# .envrc
|
|
169
|
+
if [ -f "$project_root/.envrc" ] && grep -q "KIMI_SHARE_DIR" "$project_root/.envrc" 2>/dev/null; then
|
|
170
|
+
check ".envrc with KIMI_SHARE_DIR" "ok"
|
|
171
|
+
else
|
|
172
|
+
check ".envrc missing KIMI_SHARE_DIR (sessions will use global)" "warn"
|
|
173
|
+
fi
|
|
174
|
+
;;
|
|
175
|
+
|
|
176
|
+
codex)
|
|
177
|
+
local agents_dir="$project_root/.agents"
|
|
178
|
+
|
|
179
|
+
# AGENTS.md at project root
|
|
180
|
+
if [ -f "$project_root/AGENTS.md" ] && grep -q "CortexHawk" "$project_root/AGENTS.md" 2>/dev/null; then
|
|
181
|
+
check "AGENTS.md in project root" "ok"
|
|
182
|
+
else
|
|
183
|
+
check "AGENTS.md missing or not CortexHawk" "fail"
|
|
184
|
+
fi
|
|
185
|
+
|
|
186
|
+
# .agents/ directory
|
|
187
|
+
if [ -d "$agents_dir/skills" ]; then
|
|
188
|
+
local codex_skills=0
|
|
189
|
+
codex_skills=$(find "$agents_dir/skills" -name "*.md" -type f 2>/dev/null | wc -l | tr -d ' ')
|
|
190
|
+
check ".agents/skills/: $codex_skills files" "ok"
|
|
191
|
+
else
|
|
192
|
+
check ".agents/skills/ missing" "fail"
|
|
193
|
+
fi
|
|
194
|
+
|
|
195
|
+
# config.toml
|
|
196
|
+
if [ -f "$target_dir/config.toml" ]; then
|
|
197
|
+
check "config.toml present" "ok"
|
|
198
|
+
else
|
|
199
|
+
check "config.toml missing" "fail"
|
|
200
|
+
fi
|
|
201
|
+
;;
|
|
202
|
+
esac
|
|
203
|
+
echo ""
|
|
204
|
+
done
|
|
205
|
+
|
|
206
|
+
# Shared checks
|
|
207
|
+
echo "--- shared ---"
|
|
208
|
+
|
|
209
|
+
# .gitignore
|
|
210
|
+
if [ -f "$project_root/.gitignore" ]; then
|
|
211
|
+
local ignored=0
|
|
212
|
+
for target in "${targets_found[@]}"; do
|
|
213
|
+
case "$target" in
|
|
214
|
+
claude) grep -qx ".claude/" "$project_root/.gitignore" 2>/dev/null && ignored=$((ignored + 1)) ;;
|
|
215
|
+
kimi) grep -qx ".kimi/" "$project_root/.gitignore" 2>/dev/null && ignored=$((ignored + 1)) ;;
|
|
216
|
+
codex) grep -qx ".codex/" "$project_root/.gitignore" 2>/dev/null && ignored=$((ignored + 1)) ;;
|
|
217
|
+
esac
|
|
218
|
+
done
|
|
219
|
+
[ "$ignored" -eq "${#targets_found[@]}" ] && check "All targets in .gitignore" "ok" || check "Some targets missing from .gitignore" "warn"
|
|
220
|
+
else
|
|
221
|
+
check ".gitignore missing" "warn"
|
|
222
|
+
fi
|
|
223
|
+
|
|
224
|
+
# docs/ workspace
|
|
225
|
+
if [ -d "$project_root/docs" ]; then
|
|
226
|
+
check "docs/ workspace present" "ok"
|
|
227
|
+
else
|
|
228
|
+
check "docs/ workspace missing" "warn"
|
|
229
|
+
fi
|
|
230
|
+
|
|
231
|
+
# git-workflow.conf
|
|
232
|
+
local found_conf=false
|
|
233
|
+
for target in "${targets_found[@]}"; do
|
|
234
|
+
case "$target" in
|
|
235
|
+
claude) [ -f "$project_root/.claude/git-workflow.conf" ] && found_conf=true ;;
|
|
236
|
+
esac
|
|
237
|
+
done
|
|
238
|
+
[ "$found_conf" = true ] && check "git-workflow.conf configured" "ok" || check "git-workflow.conf not found" "warn"
|
|
239
|
+
|
|
240
|
+
echo ""
|
|
241
|
+
echo "============================="
|
|
242
|
+
echo " OK: $ok | WARN: $warn | FAIL: $fail"
|
|
243
|
+
if [ "$fail" -gt 0 ]; then
|
|
244
|
+
red " Some checks failed. Run 'cortexhawk doctor' or reinstall."
|
|
245
|
+
return 1
|
|
246
|
+
elif [ "$warn" -gt 0 ]; then
|
|
247
|
+
yellow " All critical checks passed. Some warnings to review."
|
|
248
|
+
else
|
|
249
|
+
green " All checks passed!"
|
|
250
|
+
fi
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
# Verify CortexHawk source exists
|
|
254
|
+
check_home() {
|
|
255
|
+
if [ ! -f "$INSTALL_SH" ]; then
|
|
256
|
+
red "CortexHawk not found in $CORTEXHAWK_HOME"
|
|
257
|
+
echo ""
|
|
258
|
+
echo "Install with:"
|
|
259
|
+
echo " git clone https://github.com/Spechawk94/CortexHawk.git ~/.cortexhawk"
|
|
260
|
+
echo ""
|
|
261
|
+
echo "Or set CORTEXHAWK_HOME to your clone location."
|
|
262
|
+
exit 1
|
|
263
|
+
fi
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
show_help() {
|
|
267
|
+
echo "CortexHawk CLI v$(get_version)"
|
|
268
|
+
echo ""
|
|
269
|
+
echo "Usage: cortexhawk <command> [options]"
|
|
270
|
+
echo ""
|
|
271
|
+
echo "Setup:"
|
|
272
|
+
echo " init Interactive setup wizard (auto-detects CLIs)"
|
|
273
|
+
echo " install [opts] Install CortexHawk (--target, --profile, --global, --pack)"
|
|
274
|
+
echo " update [--force] Update existing installation"
|
|
275
|
+
echo " uninstall Remove CortexHawk installation"
|
|
276
|
+
echo ""
|
|
277
|
+
echo "Diagnostics:"
|
|
278
|
+
echo " validate [path] Verify skills/agents discovery per target"
|
|
279
|
+
echo " doctor Check installation health"
|
|
280
|
+
echo " stats Show installation overview"
|
|
281
|
+
echo " quickstart Getting-started guide"
|
|
282
|
+
echo " demo Create sandbox project with intentional bugs"
|
|
283
|
+
echo ""
|
|
284
|
+
echo "Skills:"
|
|
285
|
+
echo " search <keyword> Search community skills (SkillsMP or local)"
|
|
286
|
+
echo " add-skill <url> Install skill from GitHub"
|
|
287
|
+
echo " publish <path> Publish local skill to GitHub"
|
|
288
|
+
echo ""
|
|
289
|
+
echo "Snapshots:"
|
|
290
|
+
echo " snapshot [--portable] Save installation state"
|
|
291
|
+
echo " snapshots List saved snapshots"
|
|
292
|
+
echo " restore <file> Restore from snapshot"
|
|
293
|
+
echo " diff [file] [file] Compare states"
|
|
294
|
+
echo ""
|
|
295
|
+
echo "Hooks:"
|
|
296
|
+
echo " hooks List all hooks with status"
|
|
297
|
+
echo " enable-hook <name> Enable a hook"
|
|
298
|
+
echo " disable-hook <name> Disable a hook"
|
|
299
|
+
echo " test-hooks Dry-run hooks with synthetic inputs"
|
|
300
|
+
echo ""
|
|
301
|
+
echo "Other:"
|
|
302
|
+
echo " self-update Update CortexHawk source (git pull)"
|
|
303
|
+
echo " version Show version"
|
|
304
|
+
echo " help Show this help"
|
|
305
|
+
echo ""
|
|
306
|
+
echo "All install.sh flags also work: cortexhawk --dry-run --target kimi"
|
|
307
|
+
echo ""
|
|
308
|
+
echo "CORTEXHAWK_HOME=$CORTEXHAWK_HOME"
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
# Main dispatcher
|
|
312
|
+
cmd="${1:-help}"
|
|
313
|
+
|
|
314
|
+
case "$cmd" in
|
|
315
|
+
init)
|
|
316
|
+
check_home
|
|
317
|
+
shift
|
|
318
|
+
bash "$INSTALL_SH" --init "$@"
|
|
319
|
+
;;
|
|
320
|
+
install)
|
|
321
|
+
check_home
|
|
322
|
+
shift
|
|
323
|
+
bash "$INSTALL_SH" "$@"
|
|
324
|
+
;;
|
|
325
|
+
update)
|
|
326
|
+
check_home
|
|
327
|
+
shift
|
|
328
|
+
bash "$INSTALL_SH" --update "$@"
|
|
329
|
+
;;
|
|
330
|
+
uninstall)
|
|
331
|
+
check_home
|
|
332
|
+
shift
|
|
333
|
+
bash "$INSTALL_SH" --uninstall "$@"
|
|
334
|
+
;;
|
|
335
|
+
validate)
|
|
336
|
+
shift
|
|
337
|
+
do_validate "$@"
|
|
338
|
+
;;
|
|
339
|
+
doctor)
|
|
340
|
+
check_home
|
|
341
|
+
shift
|
|
342
|
+
bash "$INSTALL_SH" --doctor "$@"
|
|
343
|
+
;;
|
|
344
|
+
stats)
|
|
345
|
+
check_home
|
|
346
|
+
shift
|
|
347
|
+
bash "$INSTALL_SH" --stats "$@"
|
|
348
|
+
;;
|
|
349
|
+
quickstart)
|
|
350
|
+
check_home
|
|
351
|
+
shift
|
|
352
|
+
bash "$INSTALL_SH" --quickstart "$@"
|
|
353
|
+
;;
|
|
354
|
+
demo)
|
|
355
|
+
check_home
|
|
356
|
+
shift
|
|
357
|
+
bash "$INSTALL_SH" --demo "$@"
|
|
358
|
+
;;
|
|
359
|
+
search)
|
|
360
|
+
check_home
|
|
361
|
+
shift
|
|
362
|
+
bash "$INSTALL_SH" --search "$@"
|
|
363
|
+
;;
|
|
364
|
+
add-skill)
|
|
365
|
+
check_home
|
|
366
|
+
shift
|
|
367
|
+
bash "$INSTALL_SH" --add-skill "$@"
|
|
368
|
+
;;
|
|
369
|
+
publish)
|
|
370
|
+
check_home
|
|
371
|
+
shift
|
|
372
|
+
bash "$INSTALL_SH" --publish-skill "$@"
|
|
373
|
+
;;
|
|
374
|
+
snapshot)
|
|
375
|
+
check_home
|
|
376
|
+
shift
|
|
377
|
+
bash "$INSTALL_SH" --snapshot "$@"
|
|
378
|
+
;;
|
|
379
|
+
snapshots)
|
|
380
|
+
check_home
|
|
381
|
+
shift
|
|
382
|
+
bash "$INSTALL_SH" --snapshots "$@"
|
|
383
|
+
;;
|
|
384
|
+
restore)
|
|
385
|
+
check_home
|
|
386
|
+
shift
|
|
387
|
+
bash "$INSTALL_SH" --restore "$@"
|
|
388
|
+
;;
|
|
389
|
+
diff)
|
|
390
|
+
check_home
|
|
391
|
+
shift
|
|
392
|
+
bash "$INSTALL_SH" --diff "$@"
|
|
393
|
+
;;
|
|
394
|
+
hooks)
|
|
395
|
+
check_home
|
|
396
|
+
shift
|
|
397
|
+
bash "$INSTALL_SH" --list-hooks "$@"
|
|
398
|
+
;;
|
|
399
|
+
enable-hook)
|
|
400
|
+
check_home
|
|
401
|
+
shift
|
|
402
|
+
bash "$INSTALL_SH" --enable-hook "$@"
|
|
403
|
+
;;
|
|
404
|
+
disable-hook)
|
|
405
|
+
check_home
|
|
406
|
+
shift
|
|
407
|
+
bash "$INSTALL_SH" --disable-hook "$@"
|
|
408
|
+
;;
|
|
409
|
+
test-hooks)
|
|
410
|
+
check_home
|
|
411
|
+
shift
|
|
412
|
+
bash "$INSTALL_SH" --test-hooks "$@"
|
|
413
|
+
;;
|
|
414
|
+
self-update)
|
|
415
|
+
check_home
|
|
416
|
+
if [ ! -d "$CORTEXHAWK_HOME/.git" ]; then
|
|
417
|
+
yellow "CortexHawk installed via npm — use: npm update -g cortexhawk"
|
|
418
|
+
exit 0
|
|
419
|
+
fi
|
|
420
|
+
echo "Updating CortexHawk source..."
|
|
421
|
+
cd "$CORTEXHAWK_HOME"
|
|
422
|
+
local_version=$(get_version)
|
|
423
|
+
git pull --quiet
|
|
424
|
+
new_version=$(get_version)
|
|
425
|
+
if [ "$local_version" = "$new_version" ]; then
|
|
426
|
+
green "Already up to date (v$new_version)"
|
|
427
|
+
else
|
|
428
|
+
green "Updated: v$local_version → v$new_version"
|
|
429
|
+
echo "Run 'cortexhawk update' to apply changes to your projects."
|
|
430
|
+
fi
|
|
431
|
+
;;
|
|
432
|
+
version|--version|-v)
|
|
433
|
+
check_home
|
|
434
|
+
echo "cortexhawk v$(get_version)"
|
|
435
|
+
echo "Source: $CORTEXHAWK_HOME"
|
|
436
|
+
;;
|
|
437
|
+
help|--help|-h)
|
|
438
|
+
show_help
|
|
439
|
+
;;
|
|
440
|
+
-*)
|
|
441
|
+
# Raw flags passthrough to install.sh
|
|
442
|
+
check_home
|
|
443
|
+
bash "$INSTALL_SH" "$@"
|
|
444
|
+
;;
|
|
445
|
+
*)
|
|
446
|
+
red "Unknown command: $cmd"
|
|
447
|
+
echo "Run 'cortexhawk help' for usage."
|
|
448
|
+
exit 1
|
|
449
|
+
;;
|
|
450
|
+
esac
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# agent-analytics — Track agent invocations via docs/ writes
|
|
3
|
+
# Hook type: PostToolUse (Write|Edit)
|
|
4
|
+
|
|
5
|
+
# Read file_path from stdin JSON (Claude Code hook protocol)
|
|
6
|
+
if [ -n "$CORTEXHAWK_FILE_PATH" ]; then
|
|
7
|
+
FILE_PATH="$CORTEXHAWK_FILE_PATH"
|
|
8
|
+
else
|
|
9
|
+
INPUT=$(cat)
|
|
10
|
+
FILE_PATH=$(printf '%s' "$INPUT" | grep -o '"file_path" *: *"[^"]*"' | head -1 | sed 's/.*: *"//;s/"$//')
|
|
11
|
+
fi
|
|
12
|
+
|
|
13
|
+
if [[ -z "$FILE_PATH" ]] || [[ ! -f "$FILE_PATH" ]]; then
|
|
14
|
+
exit 0
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
# Reject directory traversal or suspicious characters
|
|
18
|
+
if [[ "$FILE_PATH" =~ \.\. ]] || [[ "$FILE_PATH" =~ [^a-zA-Z0-9/_.\-] ]]; then
|
|
19
|
+
exit 0
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
# Only track docs/ writes
|
|
23
|
+
case "$FILE_PATH" in
|
|
24
|
+
docs/*) ;;
|
|
25
|
+
*) exit 0 ;;
|
|
26
|
+
esac
|
|
27
|
+
|
|
28
|
+
# Skip _shared.md (auto-generated by session-start)
|
|
29
|
+
case "$FILE_PATH" in
|
|
30
|
+
docs/.context/_shared.md) exit 0 ;;
|
|
31
|
+
esac
|
|
32
|
+
|
|
33
|
+
# Map directory to agent
|
|
34
|
+
AGENT=""
|
|
35
|
+
case "$FILE_PATH" in
|
|
36
|
+
docs/brainstorms/*) AGENT="brainstormer" ;;
|
|
37
|
+
docs/plans/*) AGENT="planner" ;;
|
|
38
|
+
docs/decisions/*) AGENT="architect" ;;
|
|
39
|
+
docs/research/*) AGENT="researcher" ;;
|
|
40
|
+
docs/audits/*) AGENT="security-auditor" ;;
|
|
41
|
+
docs/conversations/*) AGENT="copywriter" ;;
|
|
42
|
+
docs/chains/*) AGENT="chain" ;;
|
|
43
|
+
docs/.context/*) AGENT="context-update" ;;
|
|
44
|
+
*) exit 0 ;;
|
|
45
|
+
esac
|
|
46
|
+
|
|
47
|
+
# Compute metrics
|
|
48
|
+
SIZE_BYTES=$(wc -c < "$FILE_PATH" | tr -d ' ')
|
|
49
|
+
ESTIMATED_TOKENS=$((SIZE_BYTES / 4))
|
|
50
|
+
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
51
|
+
TODAY=$(date +"%Y-%m-%d")
|
|
52
|
+
|
|
53
|
+
# Ensure metrics directory exists
|
|
54
|
+
METRICS_DIR="docs/.metrics"
|
|
55
|
+
mkdir -p "$METRICS_DIR"
|
|
56
|
+
|
|
57
|
+
# Escape strings for safe JSON output
|
|
58
|
+
json_escape() { printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g'; }
|
|
59
|
+
|
|
60
|
+
# Append JSONL entry
|
|
61
|
+
FILENAME=$(json_escape "$(basename "$FILE_PATH")")
|
|
62
|
+
FILEPATH_ESC=$(json_escape "$FILE_PATH")
|
|
63
|
+
printf '{"timestamp":"%s","agent":"%s","file":"%s","path":"%s","size_bytes":%d,"estimated_tokens":%d}\n' \
|
|
64
|
+
"$TIMESTAMP" "$AGENT" "$FILENAME" "$FILEPATH_ESC" "$SIZE_BYTES" "$ESTIMATED_TOKENS" \
|
|
65
|
+
>> "$METRICS_DIR/$TODAY.jsonl"
|
|
66
|
+
|
|
67
|
+
exit 0
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# branch-guard — Prevents direct push to protected branches
|
|
3
|
+
# Hook type: PreToolUse (Bash)
|
|
4
|
+
|
|
5
|
+
# Read command from stdin JSON (Claude Code hook protocol)
|
|
6
|
+
if [ -n "$CORTEXHAWK_COMMAND" ]; then
|
|
7
|
+
CMD="$CORTEXHAWK_COMMAND"
|
|
8
|
+
else
|
|
9
|
+
INPUT=$(cat)
|
|
10
|
+
CMD=$(printf '%s' "$INPUT" | grep -o '"command" *: *"[^"]*"' | head -1 | sed 's/.*: *"//;s/"$//')
|
|
11
|
+
fi
|
|
12
|
+
|
|
13
|
+
if [[ -z "$CMD" ]]; then
|
|
14
|
+
exit 0
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
PROTECTED_BRANCHES=("main" "master" "production" "release")
|
|
18
|
+
|
|
19
|
+
# Load git workflow config — allow direct-main push if configured
|
|
20
|
+
CONF_FILE="$(git rev-parse --show-toplevel 2>/dev/null)/.claude/git-workflow.conf"
|
|
21
|
+
if [[ -f "$CONF_FILE" ]]; then
|
|
22
|
+
_BRANCHING=$(grep '^BRANCHING=' "$CONF_FILE" | cut -d= -f2)
|
|
23
|
+
if [[ "$_BRANCHING" == "direct-main" ]]; then
|
|
24
|
+
PROTECTED_BRANCHES=("master" "production" "release")
|
|
25
|
+
fi
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
# Check for git push to protected branches
|
|
29
|
+
if echo "$CMD" | grep -qE 'git\s+push'; then
|
|
30
|
+
CURRENT_BRANCH=$(git branch --show-current 2>/dev/null)
|
|
31
|
+
|
|
32
|
+
for branch in "${PROTECTED_BRANCHES[@]}"; do
|
|
33
|
+
# Direct push: git push origin main
|
|
34
|
+
if echo "$CMD" | grep -qE "git\s+push\s+\S+\s+${branch}(\s|$)"; then
|
|
35
|
+
echo "BLOCKED: Direct push to '$branch' denied by branch-guard" >&2
|
|
36
|
+
echo "Use a feature branch and create a PR instead" >&2
|
|
37
|
+
exit 2
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
# Push current branch if it's protected: git push (while on main)
|
|
41
|
+
if [[ "$CURRENT_BRANCH" == "$branch" ]]; then
|
|
42
|
+
echo "BLOCKED: Push from protected branch '$branch' denied by branch-guard" >&2
|
|
43
|
+
echo "Use a feature branch and create a PR instead" >&2
|
|
44
|
+
exit 2
|
|
45
|
+
fi
|
|
46
|
+
done
|
|
47
|
+
|
|
48
|
+
# Block force push
|
|
49
|
+
if echo "$CMD" | grep -qE 'git\s+push\s+.*(-f|--force|--force-with-lease)'; then
|
|
50
|
+
echo "BLOCKED: Force push denied by branch-guard" >&2
|
|
51
|
+
echo "Force push can destroy remote history — use with extreme caution" >&2
|
|
52
|
+
exit 2
|
|
53
|
+
fi
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
exit 0
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# codex-dispatcher.sh — Bridges Codex after_tool_use events to CortexHawk PostToolUse hooks
|
|
3
|
+
# Reads JSON payload from stdin, extracts modified files, dispatches to hooks
|
|
4
|
+
# Hook type: Codex after_tool_use
|
|
5
|
+
|
|
6
|
+
# Read payload from stdin
|
|
7
|
+
PAYLOAD=$(cat)
|
|
8
|
+
|
|
9
|
+
# Require jq for JSON parsing
|
|
10
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
11
|
+
exit 0
|
|
12
|
+
fi
|
|
13
|
+
|
|
14
|
+
# Extract fields from payload
|
|
15
|
+
EVENT_TYPE=$(echo "$PAYLOAD" | jq -r '.hook_event.event_type // empty')
|
|
16
|
+
if [ "$EVENT_TYPE" != "after_tool_use" ]; then
|
|
17
|
+
exit 0
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
SUCCESS=$(echo "$PAYLOAD" | jq -r '.hook_event.success // false')
|
|
21
|
+
if [ "$SUCCESS" != "true" ]; then
|
|
22
|
+
exit 0
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
MUTATING=$(echo "$PAYLOAD" | jq -r '.hook_event.mutating // false')
|
|
26
|
+
if [ "$MUTATING" != "true" ]; then
|
|
27
|
+
exit 0
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
CWD=$(echo "$PAYLOAD" | jq -r '.cwd // empty')
|
|
31
|
+
|
|
32
|
+
# Extract modified file paths — two strategies:
|
|
33
|
+
# 1. From output_preview (apply_patch output: "M filename" lines)
|
|
34
|
+
# 2. From tool_input (apply_patch input: "*** Update File: filename" lines)
|
|
35
|
+
FILES=""
|
|
36
|
+
|
|
37
|
+
# Strategy 1: output_preview → fromjson → .output → grep "^[MA] "
|
|
38
|
+
OUTPUT_FILES=$(echo "$PAYLOAD" | jq -r '(.hook_event.output_preview | fromjson).output // empty' 2>/dev/null \
|
|
39
|
+
| grep -E '^[MA] ' | sed 's/^[MA] //' || true)
|
|
40
|
+
if [ -n "$OUTPUT_FILES" ]; then
|
|
41
|
+
FILES="$OUTPUT_FILES"
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
# Strategy 2: tool_input.input → grep "Update File:"
|
|
45
|
+
if [ -z "$FILES" ]; then
|
|
46
|
+
INPUT_FILES=$(echo "$PAYLOAD" | jq -r '.hook_event.tool_input.input // empty' 2>/dev/null \
|
|
47
|
+
| grep 'Update File:' | sed 's/.*Update File: *//' || true)
|
|
48
|
+
FILES="$INPUT_FILES"
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
if [ -z "$FILES" ]; then
|
|
52
|
+
exit 0
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
# Locate hooks directory (relative to this script)
|
|
56
|
+
HOOKS_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
57
|
+
|
|
58
|
+
# Dispatch each modified file to PostToolUse hooks
|
|
59
|
+
while IFS= read -r file; do
|
|
60
|
+
[ -z "$file" ] && continue
|
|
61
|
+
|
|
62
|
+
# Resolve to absolute path
|
|
63
|
+
if [[ "$file" != /* ]]; then
|
|
64
|
+
file="$CWD/$file"
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
# Pass file path via env var (hooks read CORTEXHAWK_FILE_PATH or stdin JSON)
|
|
68
|
+
export CORTEXHAWK_FILE_PATH="$file"
|
|
69
|
+
|
|
70
|
+
# self-review
|
|
71
|
+
[ -f "$HOOKS_DIR/self-review.sh" ] && bash "$HOOKS_DIR/self-review.sh" < /dev/null 2>/dev/null || true
|
|
72
|
+
|
|
73
|
+
# dependency-check
|
|
74
|
+
[ -f "$HOOKS_DIR/dependency-check.sh" ] && bash "$HOOKS_DIR/dependency-check.sh" < /dev/null 2>/dev/null || true
|
|
75
|
+
|
|
76
|
+
# test-reminder
|
|
77
|
+
[ -f "$HOOKS_DIR/test-reminder.sh" ] && bash "$HOOKS_DIR/test-reminder.sh" < /dev/null 2>/dev/null || true
|
|
78
|
+
|
|
79
|
+
# agent-analytics
|
|
80
|
+
[ -f "$HOOKS_DIR/agent-analytics.sh" ] && bash "$HOOKS_DIR/agent-analytics.sh" < /dev/null 2>/dev/null || true
|
|
81
|
+
|
|
82
|
+
done <<< "$FILES"
|
|
83
|
+
|
|
84
|
+
exit 0
|