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.
Files changed (136) hide show
  1. package/.cortexhawk-team.yml +65 -0
  2. package/CHANGELOG.md +268 -0
  3. package/CLAUDE.md +96 -0
  4. package/LICENSE +21 -0
  5. package/PACKS.md +14 -0
  6. package/README.md +418 -0
  7. package/REGISTRY.md +23 -0
  8. package/agents/architect.md +46 -0
  9. package/agents/brainstormer.md +57 -0
  10. package/agents/code-simplifier.md +56 -0
  11. package/agents/codebase-mapper.md +63 -0
  12. package/agents/copywriter.md +48 -0
  13. package/agents/debugger.md +44 -0
  14. package/agents/designer.md +53 -0
  15. package/agents/devops.md +49 -0
  16. package/agents/docs-manager.md +50 -0
  17. package/agents/fullstack-developer.md +55 -0
  18. package/agents/git-manager.md +63 -0
  19. package/agents/implementer.md +30 -0
  20. package/agents/journal-writer.md +53 -0
  21. package/agents/planner.md +52 -0
  22. package/agents/project-manager.md +50 -0
  23. package/agents/researcher.md +46 -0
  24. package/agents/reviewer.md +63 -0
  25. package/agents/security-auditor.md +92 -0
  26. package/agents/teacher.md +71 -0
  27. package/agents/tester.md +41 -0
  28. package/commands/api-gen.md +17 -0
  29. package/commands/backlog.md +26 -0
  30. package/commands/bootstrap.md +32 -0
  31. package/commands/brainstorm.md +18 -0
  32. package/commands/build.md +16 -0
  33. package/commands/chain.md +46 -0
  34. package/commands/changelog.md +16 -0
  35. package/commands/check.md +40 -0
  36. package/commands/ci.md +32 -0
  37. package/commands/context.md +35 -0
  38. package/commands/debug.md +16 -0
  39. package/commands/deploy.md +16 -0
  40. package/commands/doc.md +15 -0
  41. package/commands/export.md +17 -0
  42. package/commands/journal.md +18 -0
  43. package/commands/learn.md +16 -0
  44. package/commands/map.md +16 -0
  45. package/commands/migrate.md +17 -0
  46. package/commands/monitor.md +16 -0
  47. package/commands/optimize.md +17 -0
  48. package/commands/plan.md +17 -0
  49. package/commands/pulse.md +46 -0
  50. package/commands/refactor.md +16 -0
  51. package/commands/research.md +18 -0
  52. package/commands/review.md +16 -0
  53. package/commands/scan.md +19 -0
  54. package/commands/ship.md +17 -0
  55. package/commands/simplify.md +16 -0
  56. package/commands/task.md +32 -0
  57. package/commands/tdd.md +17 -0
  58. package/commands/test.md +16 -0
  59. package/commands/upgrade.md +27 -0
  60. package/cortexhawk +450 -0
  61. package/hooks/agent-analytics.sh +67 -0
  62. package/hooks/branch-guard.sh +56 -0
  63. package/hooks/codex-dispatcher.sh +84 -0
  64. package/hooks/commit-guard.sh +71 -0
  65. package/hooks/compose.yml +47 -0
  66. package/hooks/dependency-check.sh +56 -0
  67. package/hooks/file-guard.sh +69 -0
  68. package/hooks/hooks.json +46 -0
  69. package/hooks/self-review.sh +71 -0
  70. package/hooks/session-start.sh +132 -0
  71. package/hooks/session-telemetry.sh +60 -0
  72. package/hooks/test-reminder.sh +75 -0
  73. package/install.sh +3805 -0
  74. package/mcp/README.md +37 -0
  75. package/mcp/context7.json +8 -0
  76. package/mcp/puppeteer.json +8 -0
  77. package/mcp/sequential-thinking.json +8 -0
  78. package/modes/default.md +5 -0
  79. package/modes/fast.md +5 -0
  80. package/modes/learn.md +9 -0
  81. package/modes/orchestration.md +5 -0
  82. package/modes/pair.md +10 -0
  83. package/modes/research.md +5 -0
  84. package/modes/review.md +5 -0
  85. package/package.json +32 -0
  86. package/profiles/api.json +27 -0
  87. package/profiles/data.json +23 -0
  88. package/profiles/fullstack.json +27 -0
  89. package/scripts/autodetect-profile.sh +68 -0
  90. package/scripts/benchmark.sh +106 -0
  91. package/scripts/chain-post-save.sh +23 -0
  92. package/scripts/generate-plans-index.sh +50 -0
  93. package/scripts/git-workflow-init.sh +115 -0
  94. package/scripts/install-codex.sh +128 -0
  95. package/scripts/interactive-init.sh +264 -0
  96. package/scripts/post-install-audit.sh +130 -0
  97. package/scripts/validate.sh +214 -0
  98. package/settings.json +90 -0
  99. package/setup.sh +67 -0
  100. package/skills/databases/schema-designer/SKILL.md +54 -0
  101. package/skills/databases/sql-optimizer/SKILL.md +37 -0
  102. package/skills/devops/ci-cd/SKILL.md +59 -0
  103. package/skills/devops/deployment/SKILL.md +49 -0
  104. package/skills/devops/docker/SKILL.md +57 -0
  105. package/skills/frameworks/api-design/SKILL.md +103 -0
  106. package/skills/frameworks/fastapi/SKILL.md +68 -0
  107. package/skills/frameworks/nextjs/SKILL.md +74 -0
  108. package/skills/frameworks/python/SKILL.md +89 -0
  109. package/skills/frameworks/react/SKILL.md +83 -0
  110. package/skills/frameworks/sveltekit/SKILL.md +69 -0
  111. package/skills/frameworks/tailwindcss/SKILL.md +75 -0
  112. package/skills/frameworks/typescript/SKILL.md +94 -0
  113. package/skills/meta/mcp-builder/SKILL.md +54 -0
  114. package/skills/meta/skill-creator/SKILL.md +43 -0
  115. package/skills/optimization/performance/SKILL.md +70 -0
  116. package/skills/quality/complexity-analyzer/SKILL.md +52 -0
  117. package/skills/quality/error-handling/SKILL.md +123 -0
  118. package/skills/quality/log-analyzer/SKILL.md +31 -0
  119. package/skills/quality/pattern-detector/SKILL.md +50 -0
  120. package/skills/security/auth-analyzer/SKILL.md +96 -0
  121. package/skills/security/compliance-checker/SKILL.md +92 -0
  122. package/skills/security/container-security/SKILL.md +128 -0
  123. package/skills/security/dependency-auditor/SKILL.md +100 -0
  124. package/skills/security/encryption/SKILL.md +94 -0
  125. package/skills/security/incident-response/SKILL.md +127 -0
  126. package/skills/security/secrets/SKILL.md +93 -0
  127. package/skills/security/security-headers/SKILL.md +83 -0
  128. package/skills/security/security-logging/SKILL.md +107 -0
  129. package/skills/security/vulnerability-scanner/SKILL.md +114 -0
  130. package/skills/testing/e2e-testing/SKILL.md +119 -0
  131. package/skills/testing/tdd/SKILL.md +40 -0
  132. package/skills/testing/test-generator/SKILL.md +39 -0
  133. package/skills/workflow/commit/SKILL.md +61 -0
  134. package/skills/workflow/confidence-check/SKILL.md +90 -0
  135. package/skills/workflow/pr-review-comments/SKILL.md +81 -0
  136. package/skills/workflow/pr-review-comments/scripts/fetch_comments.py +237 -0
@@ -0,0 +1,71 @@
1
+ #!/bin/bash
2
+ # commit-guard — Validates commit format and checks for staged secrets
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
+ # Only check git commit commands
18
+ if ! echo "$CMD" | grep -qE 'git\s+commit'; then
19
+ exit 0
20
+ fi
21
+
22
+ # Extract commit message from -m flag
23
+ COMMIT_MSG=$(echo "$CMD" | grep -oP '(?<=-m\s["\x27]).*?(?=["\x27])' 2>/dev/null)
24
+ if [[ -z "$COMMIT_MSG" ]]; then
25
+ COMMIT_MSG=$(echo "$CMD" | grep -oP '(?<=-m\s)(\S+)' 2>/dev/null)
26
+ fi
27
+
28
+ # Load git workflow config — skip conventional check if freeform
29
+ CONF_FILE="$(git rev-parse --show-toplevel 2>/dev/null)/.claude/git-workflow.conf"
30
+ _COMMIT_CONVENTION="conventional"
31
+ if [[ -f "$CONF_FILE" ]]; then
32
+ _COMMIT_CONVENTION=$(grep '^COMMIT_CONVENTION=' "$CONF_FILE" | cut -d= -f2)
33
+ fi
34
+
35
+ # Validate conventional commit format
36
+ if [[ -n "$COMMIT_MSG" ]] && [[ "$_COMMIT_CONVENTION" != "freeform" ]]; then
37
+ VALID_TYPES="feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert"
38
+ if ! echo "$COMMIT_MSG" | grep -qE "^(${VALID_TYPES})(\(.+\))?!?:\s.+"; then
39
+ echo "commit-guard: Non-conventional commit format detected"
40
+ echo "Expected: type(scope): description"
41
+ echo "Types: $VALID_TYPES"
42
+ echo "Got: $COMMIT_MSG"
43
+ # Warning only — don't block
44
+ fi
45
+ fi
46
+
47
+ # Check staged files for secrets
48
+ STAGED_FILES=$(git diff --cached --name-only 2>/dev/null)
49
+ if [[ -n "$STAGED_FILES" ]]; then
50
+ SECRET_PATTERNS='(PRIVATE.KEY|AWS_SECRET|api_key|password|secret)\s*[=:]\s*["\x27][^\s"'\'']{8,}'
51
+
52
+ while IFS= read -r file; do
53
+ if [[ -f "$file" ]]; then
54
+ MATCHES=$(grep -cEi "$SECRET_PATTERNS" "$file" 2>/dev/null || echo 0)
55
+ if [[ "$MATCHES" -gt 0 ]]; then
56
+ echo "BLOCKED: Potential secret detected in staged file: $file" >&2
57
+ echo "Review the file and remove secrets before committing" >&2
58
+ exit 2
59
+ fi
60
+ fi
61
+ done <<< "$STAGED_FILES"
62
+
63
+ # Warn if .env files are staged
64
+ if echo "$STAGED_FILES" | grep -qE '\.env($|\.)'; then
65
+ echo "BLOCKED: .env file staged for commit" >&2
66
+ echo "Remove with: git reset HEAD <file>" >&2
67
+ exit 2
68
+ fi
69
+ fi
70
+
71
+ exit 0
@@ -0,0 +1,47 @@
1
+ # CortexHawk Hook Compositions
2
+ # Defines hook pipelines per event type. Converted to settings.json at install.
3
+ #
4
+ # Format:
5
+ # composition-name:
6
+ # event: SessionStart|PreToolUse|PostToolUse|SessionEnd
7
+ # matcher: tool pattern (e.g., "Read|Edit|Write", "Bash", "*")
8
+ # hooks:
9
+ # - hook-name (matches .sh file in hooks/)
10
+ #
11
+ # To add a hook: add its name to the hooks list
12
+ # To remove a hook: delete or comment the line
13
+
14
+ compositions:
15
+ session-init:
16
+ event: SessionStart
17
+ matcher: "*"
18
+ hooks:
19
+ - session-start
20
+
21
+ pre-file-access:
22
+ event: PreToolUse
23
+ matcher: "Read|Edit|Write"
24
+ hooks:
25
+ - file-guard
26
+
27
+ pre-command:
28
+ event: PreToolUse
29
+ matcher: Bash
30
+ hooks:
31
+ - branch-guard
32
+ - commit-guard
33
+
34
+ post-edit:
35
+ event: PostToolUse
36
+ matcher: "Write|Edit"
37
+ hooks:
38
+ - self-review
39
+ - dependency-check
40
+ - test-reminder
41
+ - agent-analytics
42
+
43
+ session-cleanup:
44
+ event: SessionEnd
45
+ matcher: "*"
46
+ hooks:
47
+ - session-telemetry
@@ -0,0 +1,56 @@
1
+ #!/bin/bash
2
+ # dependency-check — Alerts when dependency files are modified
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
+ MODIFIED_FILE="$CORTEXHAWK_FILE_PATH"
8
+ else
9
+ INPUT=$(cat)
10
+ MODIFIED_FILE=$(printf '%s' "$INPUT" | grep -o '"file_path" *: *"[^"]*"' | head -1 | sed 's/.*: *"//;s/"$//')
11
+ fi
12
+
13
+ if [[ -z "$MODIFIED_FILE" ]]; then
14
+ exit 0
15
+ fi
16
+
17
+ BASENAME=$(basename "$MODIFIED_FILE")
18
+
19
+ case "$BASENAME" in
20
+ package.json)
21
+ echo "Dependencies modified: $BASENAME"
22
+ echo "- Run 'npm install' to sync node_modules"
23
+ echo "- Run 'npm audit' to check for vulnerabilities"
24
+ echo "- Commit package-lock.json alongside package.json"
25
+ ;;
26
+ requirements.txt|requirements-*.txt)
27
+ echo "Dependencies modified: $BASENAME"
28
+ echo "- Run 'pip install -r $BASENAME' to sync"
29
+ echo "- Run 'pip audit' or 'safety check' for vulnerabilities"
30
+ echo "- Pin exact versions for reproducible builds"
31
+ ;;
32
+ pyproject.toml)
33
+ if grep -q '\[project.dependencies\]\|dependencies\s*=' "$MODIFIED_FILE" 2>/dev/null; then
34
+ echo "Dependencies modified: $BASENAME"
35
+ echo "- Run 'pip install -e .' or 'poetry install' to sync"
36
+ echo "- Lock file should be committed too"
37
+ fi
38
+ ;;
39
+ Cargo.toml)
40
+ echo "Dependencies modified: $BASENAME"
41
+ echo "- Run 'cargo build' to sync and generate Cargo.lock"
42
+ echo "- Run 'cargo audit' for vulnerability check"
43
+ ;;
44
+ go.mod)
45
+ echo "Dependencies modified: $BASENAME"
46
+ echo "- Run 'go mod tidy' to sync"
47
+ echo "- Commit go.sum alongside go.mod"
48
+ ;;
49
+ Gemfile)
50
+ echo "Dependencies modified: $BASENAME"
51
+ echo "- Run 'bundle install' to sync"
52
+ echo "- Commit Gemfile.lock alongside Gemfile"
53
+ ;;
54
+ esac
55
+
56
+ exit 0
@@ -0,0 +1,69 @@
1
+ #!/bin/bash
2
+ # file-guard — Blocks Claude from accessing sensitive files
3
+ # Hook type: PreToolUse (Read|Edit|Write)
4
+
5
+ BLOCKED_PATTERNS=(
6
+ ".env"
7
+ ".env.*"
8
+ "*.pem"
9
+ "*.key"
10
+ "*credentials*"
11
+ "*secret*"
12
+ "id_rsa"
13
+ "id_ed25519"
14
+ ".ssh/*"
15
+ "*.p12"
16
+ "*.pfx"
17
+ "*.keystore"
18
+ "docker-compose*.yml"
19
+ )
20
+
21
+ # Read file_path from stdin JSON (Claude Code hook protocol)
22
+ if [ -n "$CORTEXHAWK_FILE_PATH" ]; then
23
+ FILE_ARG="$CORTEXHAWK_FILE_PATH"
24
+ else
25
+ INPUT=$(cat)
26
+ FILE_ARG=$(printf '%s' "$INPUT" | grep -o '"file_path" *: *"[^"]*"' | head -1 | sed 's/.*: *"//;s/"$//')
27
+ fi
28
+
29
+ if [[ -z "$FILE_ARG" ]]; then
30
+ exit 0
31
+ fi
32
+
33
+ # Normalize path — resolve symlinks and relative paths
34
+ if command -v realpath &>/dev/null; then
35
+ RESOLVED=$(realpath -m "$FILE_ARG" 2>/dev/null || echo "$FILE_ARG")
36
+ else
37
+ RESOLVED=$(cd "$(dirname "$FILE_ARG")" 2>/dev/null && echo "$(pwd)/$(basename "$FILE_ARG")" || echo "$FILE_ARG")
38
+ fi
39
+
40
+ # Extract just the filename for pattern matching
41
+ BASENAME=$(basename "$RESOLVED")
42
+ # Also check against the full resolved path
43
+ RELPATH="$RESOLVED"
44
+
45
+ for pattern in "${BLOCKED_PATTERNS[@]}"; do
46
+ if [[ "$BASENAME" == $pattern ]] || [[ "$RELPATH" == *$pattern ]]; then
47
+ echo "BLOCKED: Access to '$FILE_ARG' denied by file-guard" >&2
48
+ echo "Resolved path: $RESOLVED" >&2
49
+ echo "Matched pattern: '$pattern'" >&2
50
+ exit 2
51
+ fi
52
+ done
53
+
54
+ # Block symlinks pointing to sensitive files
55
+ if [[ -L "$FILE_ARG" ]]; then
56
+ LINK_TARGET=$(readlink -f "$FILE_ARG" 2>/dev/null)
57
+ if [[ -n "$LINK_TARGET" ]]; then
58
+ LINK_BASENAME=$(basename "$LINK_TARGET")
59
+ for pattern in "${BLOCKED_PATTERNS[@]}"; do
60
+ if [[ "$LINK_BASENAME" == $pattern ]]; then
61
+ echo "BLOCKED: Symlink '$FILE_ARG' -> '$LINK_TARGET' denied by file-guard" >&2
62
+ echo "Matched pattern: '$pattern'" >&2
63
+ exit 2
64
+ fi
65
+ done
66
+ fi
67
+ fi
68
+
69
+ exit 0
@@ -0,0 +1,46 @@
1
+ {
2
+ "hooks": [
3
+ {
4
+ "name": "session-start",
5
+ "type": "SessionStart",
6
+ "script": "hooks/session-start.sh",
7
+ "description": "Injects project context on startup"
8
+ },
9
+ {
10
+ "name": "file-guard",
11
+ "type": "PreToolUse",
12
+ "script": "hooks/file-guard.sh",
13
+ "description": "Blocks access to sensitive files (.env, keys, secrets)"
14
+ },
15
+ {
16
+ "name": "self-review",
17
+ "type": "PostToolUse",
18
+ "script": "hooks/self-review.sh",
19
+ "description": "Auto-review after code edits"
20
+ },
21
+ {
22
+ "name": "branch-guard",
23
+ "type": "PreToolUse",
24
+ "script": "hooks/branch-guard.sh",
25
+ "description": "Prevents direct push to protected branches"
26
+ },
27
+ {
28
+ "name": "dependency-check",
29
+ "type": "PostToolUse",
30
+ "script": "hooks/dependency-check.sh",
31
+ "description": "Alerts when dependency files are modified"
32
+ },
33
+ {
34
+ "name": "commit-guard",
35
+ "type": "PreToolUse",
36
+ "script": "hooks/commit-guard.sh",
37
+ "description": "Validates commit format and checks for staged secrets"
38
+ },
39
+ {
40
+ "name": "test-reminder",
41
+ "type": "PostToolUse",
42
+ "script": "hooks/test-reminder.sh",
43
+ "description": "Reminds to update tests when source files change"
44
+ }
45
+ ]
46
+ }
@@ -0,0 +1,71 @@
1
+ #!/bin/bash
2
+ # self-review — Auto-review after file edits
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
+ MODIFIED_FILE="$CORTEXHAWK_FILE_PATH"
8
+ else
9
+ INPUT=$(cat)
10
+ MODIFIED_FILE=$(printf '%s' "$INPUT" | grep -o '"file_path" *: *"[^"]*"' | head -1 | sed 's/.*: *"//;s/"$//')
11
+ fi
12
+
13
+ if [[ -z "$MODIFIED_FILE" ]] || [[ ! -f "$MODIFIED_FILE" ]]; then
14
+ exit 0
15
+ fi
16
+
17
+ # Only review code files
18
+ case "$MODIFIED_FILE" in
19
+ *.py|*.js|*.ts|*.jsx|*.tsx|*.go|*.rs|*.java|*.rb|*.sh)
20
+ ;;
21
+ *)
22
+ exit 0
23
+ ;;
24
+ esac
25
+
26
+ ISSUES=""
27
+
28
+ # Check for TODO/FIXME
29
+ TODO_COUNT=$(grep -cEi 'TODO|FIXME|HACK|XXX' "$MODIFIED_FILE" 2>/dev/null || echo 0)
30
+ if [[ "$TODO_COUNT" -gt 0 ]]; then
31
+ ISSUES="${ISSUES}\n- $TODO_COUNT TODO/FIXME markers found"
32
+ fi
33
+
34
+ # Check for hardcoded secrets patterns
35
+ SECRET_PATTERNS='(api[_-]?key|api[_-]?secret|password|passwd|token|secret[_-]?key)\s*[=:]\s*["\x27][^\s"'\'']{8,}'
36
+ SECRET_COUNT=$(grep -cEi "$SECRET_PATTERNS" "$MODIFIED_FILE" 2>/dev/null || echo 0)
37
+ if [[ "$SECRET_COUNT" -gt 0 ]]; then
38
+ ISSUES="${ISSUES}\n- ⚠️ $SECRET_COUNT potential hardcoded secret(s) detected"
39
+ fi
40
+
41
+ # Check for debug artifacts
42
+ case "$MODIFIED_FILE" in
43
+ *.py)
44
+ DBG_COUNT=$(grep -cE '^\s*(print\(|breakpoint\(\)|import pdb|pdb\.set_trace)' "$MODIFIED_FILE" 2>/dev/null || echo 0)
45
+ ;;
46
+ *.js|*.ts|*.jsx|*.tsx)
47
+ DBG_COUNT=$(grep -cE '^\s*console\.(log|debug|warn|error)\(' "$MODIFIED_FILE" 2>/dev/null || echo 0)
48
+ ;;
49
+ *)
50
+ DBG_COUNT=0
51
+ ;;
52
+ esac
53
+ if [[ "$DBG_COUNT" -gt 0 ]]; then
54
+ ISSUES="${ISSUES}\n- $DBG_COUNT debug statement(s) found (console.log/print)"
55
+ fi
56
+
57
+ # Syntax check for shell scripts
58
+ if [[ "$MODIFIED_FILE" == *.sh ]]; then
59
+ SYNTAX_ERR=$(bash -n "$MODIFIED_FILE" 2>&1)
60
+ if [[ $? -ne 0 ]]; then
61
+ ISSUES="${ISSUES}\n- Syntax error: $SYNTAX_ERR"
62
+ fi
63
+ fi
64
+
65
+ # Report
66
+ if [[ -n "$ISSUES" ]]; then
67
+ echo "🔍 Self-review: $MODIFIED_FILE"
68
+ echo -e "$ISSUES"
69
+ fi
70
+
71
+ exit 0
@@ -0,0 +1,132 @@
1
+ #!/bin/bash
2
+ # session-start — Inject project context on Claude Code startup
3
+ # Hook type: SessionStart
4
+
5
+ echo "CortexHawk loaded"
6
+ echo ""
7
+
8
+ # Write session start timestamp for telemetry
9
+ if [ -d "docs/.metrics" ] || [ -d "docs" ]; then
10
+ mkdir -p "docs/.metrics"
11
+ date +%s > "docs/.metrics/.session-start"
12
+ fi
13
+
14
+ # Detect project type
15
+ if [ -f "package.json" ]; then
16
+ echo "Project: Node.js/TypeScript"
17
+ DEP_COUNT=$(grep -c '"dependencies"' package.json 2>/dev/null || echo 0)
18
+ echo "Dependency groups: $DEP_COUNT"
19
+ fi
20
+
21
+ if [ -f "requirements.txt" ] || [ -f "pyproject.toml" ]; then
22
+ echo "Project: Python"
23
+ fi
24
+
25
+ if [ -f "Cargo.toml" ]; then
26
+ echo "Project: Rust"
27
+ fi
28
+
29
+ if [ -f "go.mod" ]; then
30
+ echo "Project: Go"
31
+ fi
32
+
33
+ if [ -f "docker-compose.yml" ] || [ -f "docker-compose.yaml" ]; then
34
+ echo "Docker: compose detected"
35
+ fi
36
+
37
+ if [ -f ".env.example" ] && [ ! -f ".env" ]; then
38
+ echo "Warning: .env missing — copy from .env.example"
39
+ fi
40
+
41
+ # Generate shared context for all agents
42
+ if [ -d "docs/.context" ] && [ ! -L "docs/.context" ]; then
43
+ SHARED="docs/.context/_shared.md"
44
+
45
+ echo "# Shared Context" > "$SHARED"
46
+ echo "" >> "$SHARED"
47
+ echo "_Auto-generated by session-start. Do not edit manually._" >> "$SHARED"
48
+ echo "" >> "$SHARED"
49
+
50
+ # Backlog summary
51
+ if [ -f "docs/backlog.md" ]; then
52
+ ACTIVE=$(grep -c '| todo |' docs/backlog.md 2>/dev/null || echo 0)
53
+ DEFERRED=$(grep -c '| deferred |' docs/backlog.md 2>/dev/null || echo 0)
54
+ DONE=$(grep -c '| done |' docs/backlog.md 2>/dev/null || echo 0)
55
+ echo "## Backlog" >> "$SHARED"
56
+ echo "- Active: $ACTIVE | Deferred: $DEFERRED | Done: $DONE" >> "$SHARED"
57
+ # List active items
58
+ grep '| todo |' docs/backlog.md >> "$SHARED" 2>/dev/null || true
59
+ echo "" >> "$SHARED"
60
+ fi
61
+
62
+ # Recent commits
63
+ if git rev-parse --is-inside-work-tree > /dev/null 2>&1; then
64
+ echo "## Recent Commits" >> "$SHARED"
65
+ git log --oneline -5 2>/dev/null >> "$SHARED" || true
66
+ echo "" >> "$SHARED"
67
+ fi
68
+
69
+ # User context (persistent key-value pairs from /context set)
70
+ if [ -f "docs/.context/_user.md" ]; then
71
+ cat "docs/.context/_user.md" >> "$SHARED"
72
+ echo "" >> "$SHARED"
73
+ fi
74
+
75
+ # Active warnings
76
+ echo "## Warnings" >> "$SHARED"
77
+ WARNINGS=0
78
+ if [ -f ".env.example" ] && [ ! -f ".env" ]; then
79
+ echo "- .env missing — copy from .env.example" >> "$SHARED"
80
+ WARNINGS=$((WARNINGS + 1))
81
+ fi
82
+ if [ "$WARNINGS" -eq 0 ]; then
83
+ echo "- None" >> "$SHARED"
84
+ fi
85
+ echo "" >> "$SHARED"
86
+ fi
87
+
88
+ # Agent memory status
89
+ if [ -d "docs/.context" ] && [ ! -L "docs/.context" ]; then
90
+ CONTEXT_COUNT=$(find docs/.context -maxdepth 1 -type f -name '*.md' 2>/dev/null | wc -l | tr -d ' ')
91
+ if [ "$CONTEXT_COUNT" -gt 0 ]; then
92
+ echo "Agent memory: $CONTEXT_COUNT context file(s)"
93
+ fi
94
+ fi
95
+
96
+ # Agent analytics summary
97
+ if [ -d "docs/.metrics" ]; then
98
+ TODAY=$(date +"%Y-%m-%d")
99
+ if [ -f "docs/.metrics/$TODAY.jsonl" ]; then
100
+ INVOCATIONS=$(grep -c '"agent"' "docs/.metrics/$TODAY.jsonl" 2>/dev/null || echo 0)
101
+ echo "Agent analytics: $INVOCATIONS invocation(s) today"
102
+ fi
103
+ fi
104
+
105
+ # Skill suggestions — detect relevant but uninstalled skills
106
+ CORTEXHAWK_SRC="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")/.." && pwd)"
107
+ SKILL_DIR=".claude/skills"
108
+ if [ -d "$SKILL_DIR" ]; then
109
+ MISSING=""
110
+ for skill_file in "$CORTEXHAWK_SRC"/skills/*/*/SKILL.md; do
111
+ [ -f "$skill_file" ] || continue
112
+ detect=$(sed -n '/^---$/,/^---$/{ /^detect:/{ s/^detect: //; p; } }' "$skill_file")
113
+ [ -z "$detect" ] && continue
114
+ skill_path="${skill_file#$CORTEXHAWK_SRC/skills/}"
115
+ skill_path="${skill_path%/SKILL.md}"
116
+ [ -f "$SKILL_DIR/$skill_path/SKILL.md" ] && continue
117
+ for marker in $detect; do
118
+ case "$marker" in
119
+ base) matched=true ;;
120
+ dir:*) [ -d "${marker#dir:}" ] && matched=true ;;
121
+ *:*) f="${marker%%:*}"; p="${marker#*:}"; [ -f "$f" ] && grep -qi "$p" "$f" 2>/dev/null && matched=true ;;
122
+ *) [ -f "$marker" ] && matched=true ;;
123
+ esac
124
+ [ "${matched:-}" = true ] && { MISSING="${MISSING:+$MISSING, }$skill_path"; break; }
125
+ unset matched
126
+ done
127
+ done
128
+ [ -n "$MISSING" ] && echo "Suggested skills: $MISSING"
129
+ fi
130
+
131
+ echo ""
132
+ echo "Commands: /plan /build /test /review /ship /debug /scan /check /refactor /research /doc /bootstrap /tdd /optimize /migrate /monitor /api-gen /changelog /journal /brainstorm /simplify /deploy /export /backlog /pulse /map /learn /chain /task /ci /context"
@@ -0,0 +1,60 @@
1
+ #!/bin/bash
2
+ # session-telemetry — Generate session summary on exit
3
+ # Hook type: SessionEnd
4
+
5
+ # Read session_id from stdin JSON (Claude Code hook protocol)
6
+ INPUT=$(cat)
7
+ SESSION_ID=$(printf '%s' "$INPUT" | grep -o '"session_id" *: *"[^"]*"' | head -1 | sed 's/.*: *"//;s/"$//')
8
+ SESSION_ID="${SESSION_ID:-unknown}"
9
+ METRICS_DIR="docs/.metrics"
10
+ TODAY=$(date +"%Y-%m-%d")
11
+ JSONL_FILE="$METRICS_DIR/$TODAY.jsonl"
12
+ START_FILE="$METRICS_DIR/.session-start"
13
+ TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
14
+
15
+ mkdir -p "$METRICS_DIR"
16
+
17
+ # Duration
18
+ DURATION=0
19
+ if [ -f "$START_FILE" ]; then
20
+ START_TS=$(cat "$START_FILE")
21
+ NOW_TS=$(date +%s)
22
+ DURATION=$((NOW_TS - START_TS))
23
+ [ "$DURATION" -lt 0 ] && DURATION=0
24
+ fi
25
+
26
+ # Agent invocations from today's JSONL
27
+ AGENTS_INVOKED=0
28
+ UNIQUE_AGENTS=""
29
+ TOTAL_TOKENS=0
30
+ if [ -f "$JSONL_FILE" ]; then
31
+ AGENTS_INVOKED=$(grep -c '"agent"' "$JSONL_FILE" 2>/dev/null || echo 0)
32
+ UNIQUE_AGENTS=$(grep -o '"agent":"[^"]*"' "$JSONL_FILE" 2>/dev/null \
33
+ | sort -u | sed 's/"agent":"//;s/"//' | paste -sd ',' - || echo "")
34
+ TOTAL_TOKENS=$(grep -o '"estimated_tokens":[0-9]*' "$JSONL_FILE" 2>/dev/null \
35
+ | sed 's/"estimated_tokens"://' | awk '{s+=$1} END {print s+0}')
36
+ fi
37
+
38
+ # Files modified (uncommitted + last commit)
39
+ FILES_MODIFIED=0
40
+ if git rev-parse --is-inside-work-tree > /dev/null 2>&1; then
41
+ UNCOMMITTED=$(git diff --name-only HEAD 2>/dev/null | wc -l | tr -d ' ')
42
+ UNTRACKED=$(git ls-files --others --exclude-standard 2>/dev/null | wc -l | tr -d ' ')
43
+ FILES_MODIFIED=$((UNCOMMITTED + UNTRACKED))
44
+ fi
45
+
46
+ # Escape strings for safe JSON
47
+ json_escape() { printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g'; }
48
+
49
+ SESSION_ESC=$(json_escape "$SESSION_ID")
50
+ AGENTS_ESC=$(json_escape "$UNIQUE_AGENTS")
51
+
52
+ # Append session summary to JSONL
53
+ printf '{"type":"session","timestamp":"%s","session_id":"%s","duration_seconds":%d,"agents_invoked":%d,"unique_agents":"%s","total_estimated_tokens":%d,"files_modified":%d}\n' \
54
+ "$TIMESTAMP" "$SESSION_ESC" "$DURATION" "$AGENTS_INVOKED" "$AGENTS_ESC" "$TOTAL_TOKENS" "$FILES_MODIFIED" \
55
+ >> "$JSONL_FILE"
56
+
57
+ # Cleanup start marker
58
+ rm -f "$START_FILE"
59
+
60
+ exit 0
@@ -0,0 +1,75 @@
1
+ #!/bin/bash
2
+ # test-reminder — Reminds to update tests when source files change
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
+ MODIFIED_FILE="$CORTEXHAWK_FILE_PATH"
8
+ else
9
+ INPUT=$(cat)
10
+ MODIFIED_FILE=$(printf '%s' "$INPUT" | grep -o '"file_path" *: *"[^"]*"' | head -1 | sed 's/.*: *"//;s/"$//')
11
+ fi
12
+
13
+ if [[ -z "$MODIFIED_FILE" ]] || [[ ! -f "$MODIFIED_FILE" ]]; then
14
+ exit 0
15
+ fi
16
+
17
+ # Skip non-code files
18
+ case "$MODIFIED_FILE" in
19
+ *.py|*.js|*.ts|*.jsx|*.tsx|*.go|*.rs|*.java|*.rb)
20
+ ;;
21
+ *)
22
+ exit 0
23
+ ;;
24
+ esac
25
+
26
+ # Skip if already a test file
27
+ if echo "$MODIFIED_FILE" | grep -qE '(test_|_test\.|\.test\.|\.spec\.|tests/|__tests__/)'; then
28
+ exit 0
29
+ fi
30
+
31
+ BASENAME=$(basename "$MODIFIED_FILE")
32
+ FILENAME="${BASENAME%.*}"
33
+ EXT="${BASENAME##*.}"
34
+ DIR=$(dirname "$MODIFIED_FILE")
35
+
36
+ # Build possible test file paths
37
+ TEST_CANDIDATES=()
38
+
39
+ case "$EXT" in
40
+ py)
41
+ TEST_CANDIDATES+=("${DIR}/test_${BASENAME}" "${DIR}/tests/test_${BASENAME}" "${DIR}/../tests/test_${BASENAME}")
42
+ ;;
43
+ js|ts|jsx|tsx)
44
+ TEST_CANDIDATES+=("${DIR}/${FILENAME}.test.${EXT}" "${DIR}/${FILENAME}.spec.${EXT}")
45
+ TEST_CANDIDATES+=("${DIR}/__tests__/${BASENAME}" "${DIR}/../__tests__/${BASENAME}")
46
+ ;;
47
+ go)
48
+ TEST_CANDIDATES+=("${DIR}/${FILENAME}_test.go")
49
+ ;;
50
+ rs)
51
+ # Rust tests are usually inline — skip
52
+ exit 0
53
+ ;;
54
+ java)
55
+ TEST_CANDIDATES+=("${DIR}/${FILENAME}Test.java" "${DIR}/../test/${BASENAME}")
56
+ ;;
57
+ rb)
58
+ TEST_CANDIDATES+=("${DIR}/${FILENAME}_spec.rb" "${DIR}/../spec/${BASENAME}")
59
+ ;;
60
+ esac
61
+
62
+ # Check if any test file exists
63
+ for candidate in "${TEST_CANDIDATES[@]}"; do
64
+ if [[ -f "$candidate" ]]; then
65
+ echo "Test reminder: $BASENAME has tests at $(basename "$candidate")"
66
+ echo "- Consider updating tests to cover your changes"
67
+ exit 0
68
+ fi
69
+ done
70
+
71
+ # No test file found
72
+ echo "Test reminder: No test file found for $BASENAME"
73
+ echo "- Consider creating tests for this file"
74
+
75
+ exit 0