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
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# install-codex.sh — CortexHawk installer for OpenAI Codex CLI
|
|
3
|
+
# Sourced by install.sh when --target codex is used
|
|
4
|
+
# Uses shared functions: copy_skills, generate_agents_md, convert_modes_to_skills, merge_mcp_toml, create_docs_workspace
|
|
5
|
+
|
|
6
|
+
install_codex() {
|
|
7
|
+
if [ "$GLOBAL" = true ]; then
|
|
8
|
+
TARGET="$HOME/.codex"
|
|
9
|
+
AGENTS_DIR="$HOME/.agents"
|
|
10
|
+
echo "Installing for Codex CLI globally to $TARGET"
|
|
11
|
+
else
|
|
12
|
+
TARGET="$(pwd)/.codex"
|
|
13
|
+
AGENTS_DIR="$(pwd)/.agents"
|
|
14
|
+
echo "Installing for Codex CLI to project: $TARGET"
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
mkdir -p "$TARGET"
|
|
18
|
+
mkdir -p "$AGENTS_DIR/skills"
|
|
19
|
+
|
|
20
|
+
# 1. Skills — direct copy via shared function
|
|
21
|
+
echo " Copying skills..."
|
|
22
|
+
if [ -d "$SCRIPT_DIR/skills" ]; then
|
|
23
|
+
copy_skills "$AGENTS_DIR" "$PROFILE"
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
# 2. Commands → Skills (explicit invocation via $cmd-name)
|
|
27
|
+
echo " Converting commands to skills..."
|
|
28
|
+
for cmd_file in "$SCRIPT_DIR"/commands/*.md; do
|
|
29
|
+
[ -f "$cmd_file" ] || continue
|
|
30
|
+
local cmd_name
|
|
31
|
+
cmd_name=$(basename "$cmd_file" .md)
|
|
32
|
+
local cmd_dir="$AGENTS_DIR/skills/cmd-$cmd_name"
|
|
33
|
+
mkdir -p "$cmd_dir/agents"
|
|
34
|
+
cp "$cmd_file" "$cmd_dir/SKILL.md"
|
|
35
|
+
cat > "$cmd_dir/agents/openai.yaml" << 'YAML'
|
|
36
|
+
policy:
|
|
37
|
+
allow_implicit_invocation: false
|
|
38
|
+
YAML
|
|
39
|
+
done
|
|
40
|
+
local cmd_count
|
|
41
|
+
cmd_count=$(find "$AGENTS_DIR/skills/cmd-"* -maxdepth 0 -type d 2>/dev/null | wc -l | tr -d ' ')
|
|
42
|
+
echo " Converted $cmd_count commands to skills (invoke with \$cmd-name)"
|
|
43
|
+
|
|
44
|
+
# 3. Modes → Skills via shared function
|
|
45
|
+
convert_modes_to_skills "$AGENTS_DIR/skills" "mode-"
|
|
46
|
+
|
|
47
|
+
# 4. AGENTS.md — via shared function with commands section injected
|
|
48
|
+
echo " Generating AGENTS.md..."
|
|
49
|
+
local agents_md
|
|
50
|
+
if [ "$GLOBAL" = true ]; then
|
|
51
|
+
agents_md="$HOME/AGENTS.md"
|
|
52
|
+
else
|
|
53
|
+
agents_md="$(pwd)/AGENTS.md"
|
|
54
|
+
fi
|
|
55
|
+
# Build commands listing for extra_content
|
|
56
|
+
local commands_section
|
|
57
|
+
commands_section="## Commands"$'\n'$'\n'"Commands are installed as skills. Invoke explicitly with \\\$cmd-name:"$'\n'
|
|
58
|
+
for cmd_file in "$SCRIPT_DIR"/commands/*.md; do
|
|
59
|
+
[ -f "$cmd_file" ] || continue
|
|
60
|
+
local name desc
|
|
61
|
+
name=$(basename "$cmd_file" .md)
|
|
62
|
+
desc=$(grep '^description:' "$cmd_file" | sed 's/description: *//')
|
|
63
|
+
commands_section="${commands_section}"$'\n'"- \`\$cmd-$name\` — $desc"
|
|
64
|
+
done
|
|
65
|
+
generate_agents_md "$agents_md" "optimized agents, skills, commands, and modes for Codex CLI." "$commands_section"
|
|
66
|
+
|
|
67
|
+
# 5. config.toml — settings + MCP servers via shared function
|
|
68
|
+
echo " Generating config.toml..."
|
|
69
|
+
{
|
|
70
|
+
echo "# CortexHawk configuration for Codex CLI"
|
|
71
|
+
echo ""
|
|
72
|
+
echo 'model = "o4-mini"'
|
|
73
|
+
echo 'approval_mode = "suggest"'
|
|
74
|
+
echo ""
|
|
75
|
+
echo "[history]"
|
|
76
|
+
echo 'persistence = "save-all"'
|
|
77
|
+
echo "send_to_cloud = false"
|
|
78
|
+
echo ""
|
|
79
|
+
merge_mcp_toml
|
|
80
|
+
} > "$TARGET/config.toml"
|
|
81
|
+
|
|
82
|
+
# 6. Hooks — dispatcher for after_tool_use
|
|
83
|
+
echo " Installing hooks dispatcher..."
|
|
84
|
+
mkdir -p "$AGENTS_DIR/hooks"
|
|
85
|
+
cp "$SCRIPT_DIR/hooks/codex-dispatcher.sh" "$AGENTS_DIR/hooks/"
|
|
86
|
+
cp "$SCRIPT_DIR/hooks/self-review.sh" "$AGENTS_DIR/hooks/"
|
|
87
|
+
cp "$SCRIPT_DIR/hooks/dependency-check.sh" "$AGENTS_DIR/hooks/"
|
|
88
|
+
cp "$SCRIPT_DIR/hooks/test-reminder.sh" "$AGENTS_DIR/hooks/"
|
|
89
|
+
cp "$SCRIPT_DIR/hooks/agent-analytics.sh" "$AGENTS_DIR/hooks/"
|
|
90
|
+
chmod +x "$AGENTS_DIR/hooks/"*.sh
|
|
91
|
+
|
|
92
|
+
# Add hooks config to config.toml (commented — uncomment when Codex stabilizes hooks config)
|
|
93
|
+
{
|
|
94
|
+
echo "# Hooks — uncomment when Codex CLI hooks config is stabilized"
|
|
95
|
+
echo "# [hooks.after_tool_use]"
|
|
96
|
+
echo "# command = \"bash\""
|
|
97
|
+
echo "# args = [\"$AGENTS_DIR/hooks/codex-dispatcher.sh\"]"
|
|
98
|
+
echo ""
|
|
99
|
+
} >> "$TARGET/config.toml"
|
|
100
|
+
|
|
101
|
+
# 7. Create docs/ workspace via shared function (local only)
|
|
102
|
+
if [ "$GLOBAL" = false ]; then
|
|
103
|
+
create_docs_workspace "$(dirname "$TARGET")"
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
# 8. Info
|
|
107
|
+
echo ""
|
|
108
|
+
echo " Info: hooks dispatcher installed (after_tool_use), config commented — uncomment when Codex stabilizes"
|
|
109
|
+
echo " Info: PreToolUse guards (file-guard, branch-guard, commit-guard) skipped — not yet available in Codex"
|
|
110
|
+
|
|
111
|
+
# Write manifest
|
|
112
|
+
write_manifest "$TARGET" "$PROFILE" "codex" false
|
|
113
|
+
|
|
114
|
+
echo ""
|
|
115
|
+
echo "CortexHawk installed successfully for Codex CLI!"
|
|
116
|
+
echo ""
|
|
117
|
+
echo "Available: 20 agents (in AGENTS.md), 36 skills, $cmd_count commands (as skills), 7 modes (as skills), MCP servers, hooks dispatcher"
|
|
118
|
+
echo ""
|
|
119
|
+
echo "Commands: invoke with \$cmd-plan, \$cmd-build, \$cmd-test, etc."
|
|
120
|
+
echo "Modes: invoke with \$mode-fast, \$mode-research, etc."
|
|
121
|
+
|
|
122
|
+
run_audit "$(dirname "$TARGET")"
|
|
123
|
+
update_gitignore "$(dirname "$TARGET")" ".codex"
|
|
124
|
+
update_gitignore "$(dirname "$TARGET")" ".agents"
|
|
125
|
+
|
|
126
|
+
echo ""
|
|
127
|
+
echo " To activate: exit Codex (ctrl+c) and relaunch 'codex' in this directory."
|
|
128
|
+
}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# interactive-init.sh — Interactive onboarding wizard for CortexHawk
|
|
3
|
+
# Sourced by install.sh --init. Sets: TARGET_CLI, GLOBAL, PROFILE, PROFILE_FILE,
|
|
4
|
+
# GIT_BRANCHING, GIT_COMMIT_CONVENTION, GIT_PR_PREFERENCE, GIT_AUTO_PUSH, GIT_WORK_BRANCH
|
|
5
|
+
|
|
6
|
+
cyan() { printf "\033[36m%s\033[0m\n" "$1"; }
|
|
7
|
+
green() { printf "\033[32m%s\033[0m\n" "$1"; }
|
|
8
|
+
yellow(){ printf "\033[33m%s\033[0m\n" "$1"; }
|
|
9
|
+
bold() { printf "\033[1m%s\033[0m\n" "$1"; }
|
|
10
|
+
|
|
11
|
+
echo ""
|
|
12
|
+
cyan "================================"
|
|
13
|
+
cyan "CortexHawk Interactive Setup"
|
|
14
|
+
cyan "================================"
|
|
15
|
+
echo ""
|
|
16
|
+
|
|
17
|
+
# --- Step 1: Target CLI ---
|
|
18
|
+
bold "1. Target CLI"
|
|
19
|
+
echo " 1) Claude Code (default) — fully supported"
|
|
20
|
+
echo " 2) Kimi CLI (experimental)"
|
|
21
|
+
echo " 3) Codex CLI (experimental)"
|
|
22
|
+
echo " 4) All (install for all CLIs simultaneously)"
|
|
23
|
+
read -r -p "Choice [1-4] (default: 1): " target_choice
|
|
24
|
+
case "$target_choice" in
|
|
25
|
+
2) TARGET_CLI="kimi" ;;
|
|
26
|
+
3) TARGET_CLI="codex" ;;
|
|
27
|
+
4) TARGET_CLI="all" ;;
|
|
28
|
+
*) TARGET_CLI="claude" ;;
|
|
29
|
+
esac
|
|
30
|
+
green " → $TARGET_CLI"
|
|
31
|
+
echo ""
|
|
32
|
+
|
|
33
|
+
# --- Step 2: Scope ---
|
|
34
|
+
bold "2. Install Scope"
|
|
35
|
+
echo " 1) Local project — install in current directory (default)"
|
|
36
|
+
echo " 2) Global — install in ~/.${TARGET_CLI}/ (shared across all projects)"
|
|
37
|
+
read -r -p "Choice [1-2] (default: 1): " scope_choice
|
|
38
|
+
case "$scope_choice" in
|
|
39
|
+
2) GLOBAL=true ;;
|
|
40
|
+
*) GLOBAL=false ;;
|
|
41
|
+
esac
|
|
42
|
+
green " → $([ "$GLOBAL" = true ] && echo "global" || echo "local")"
|
|
43
|
+
echo ""
|
|
44
|
+
|
|
45
|
+
# --- Step 3: Skills ---
|
|
46
|
+
bold "3. Skills"
|
|
47
|
+
echo " 1) All skills (36) — everything included"
|
|
48
|
+
echo " 2) Fullstack — React, Next.js, Tailwind, testing, devops"
|
|
49
|
+
echo " 3) API — FastAPI, Python, security, databases"
|
|
50
|
+
echo " 4) Data — Python, SQL, performance, pattern detection"
|
|
51
|
+
echo " 5) Custom — pick individual categories"
|
|
52
|
+
echo " 6) Autodetect — scan project files and recommend"
|
|
53
|
+
read -r -p "Choice [1-6] (default: 1): " skill_choice
|
|
54
|
+
|
|
55
|
+
case "$skill_choice" in
|
|
56
|
+
2) PROFILE="fullstack"; green " → fullstack (21 skills)" ;;
|
|
57
|
+
3) PROFILE="api"; green " → api (21 skills)" ;;
|
|
58
|
+
4) PROFILE="data"; green " → data (17 skills)" ;;
|
|
59
|
+
5)
|
|
60
|
+
echo ""
|
|
61
|
+
echo " Skill categories:"
|
|
62
|
+
echo " 1) databases (2) 2) devops (3) 3) frameworks (8)"
|
|
63
|
+
echo " 4) meta (2) 5) optimization (1) 6) quality (4)"
|
|
64
|
+
echo " 7) security (10) 8) testing (3) 9) workflow (3)"
|
|
65
|
+
echo ""
|
|
66
|
+
read -r -p " Enter numbers (space-separated) or 'all': " cat_input
|
|
67
|
+
|
|
68
|
+
# Map numbers to category names (bash 3 compatible — no declare -A)
|
|
69
|
+
SELECTED_CATS=""
|
|
70
|
+
if [ "$cat_input" = "all" ]; then
|
|
71
|
+
SELECTED_CATS="databases devops frameworks meta optimization quality security testing workflow"
|
|
72
|
+
else
|
|
73
|
+
for num in $cat_input; do
|
|
74
|
+
case "$num" in
|
|
75
|
+
1) SELECTED_CATS="$SELECTED_CATS databases" ;;
|
|
76
|
+
2) SELECTED_CATS="$SELECTED_CATS devops" ;;
|
|
77
|
+
3) SELECTED_CATS="$SELECTED_CATS frameworks" ;;
|
|
78
|
+
4) SELECTED_CATS="$SELECTED_CATS meta" ;;
|
|
79
|
+
5) SELECTED_CATS="$SELECTED_CATS optimization" ;;
|
|
80
|
+
6) SELECTED_CATS="$SELECTED_CATS quality" ;;
|
|
81
|
+
7) SELECTED_CATS="$SELECTED_CATS security" ;;
|
|
82
|
+
8) SELECTED_CATS="$SELECTED_CATS testing" ;;
|
|
83
|
+
9) SELECTED_CATS="$SELECTED_CATS workflow" ;;
|
|
84
|
+
esac
|
|
85
|
+
done
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
# Generate custom profile JSON
|
|
89
|
+
PROFILE_FILE="/tmp/cortexhawk-custom-$(date +%s).json"
|
|
90
|
+
SKILL_LINES=""
|
|
91
|
+
SKILL_COUNT=0
|
|
92
|
+
for category in $SELECTED_CATS; do
|
|
93
|
+
cat_dir="$SCRIPT_DIR/skills/$category"
|
|
94
|
+
[ -d "$cat_dir" ] || continue
|
|
95
|
+
for skill_dir in "$cat_dir"/*/; do
|
|
96
|
+
[ -d "$skill_dir" ] || continue
|
|
97
|
+
skill_name=$(basename "$skill_dir")
|
|
98
|
+
[ -n "$SKILL_LINES" ] && SKILL_LINES="$SKILL_LINES,"
|
|
99
|
+
SKILL_LINES="$SKILL_LINES
|
|
100
|
+
\"$category/$skill_name\""
|
|
101
|
+
SKILL_COUNT=$((SKILL_COUNT + 1))
|
|
102
|
+
done
|
|
103
|
+
done
|
|
104
|
+
|
|
105
|
+
printf '{\n "name": "custom",\n "description": "Custom category selection",\n "skills": [%s\n ]\n}\n' "$SKILL_LINES" > "$PROFILE_FILE"
|
|
106
|
+
PROFILE="custom"
|
|
107
|
+
green " → custom ($SKILL_COUNT skills)"
|
|
108
|
+
;;
|
|
109
|
+
6)
|
|
110
|
+
source "$SCRIPT_DIR/scripts/autodetect-profile.sh"
|
|
111
|
+
PROFILE="autodetect"
|
|
112
|
+
green " → autodetect ($SKILL_COUNT skills detected)"
|
|
113
|
+
;;
|
|
114
|
+
*) PROFILE=""; green " → all (36 skills)" ;;
|
|
115
|
+
esac
|
|
116
|
+
echo ""
|
|
117
|
+
|
|
118
|
+
# --- Step 3b: SkillsMP API key (optional) ---
|
|
119
|
+
bold "3b. SkillsMP (optional)"
|
|
120
|
+
echo " Search 87k+ community skills. Get a free key at: https://skillsmp.com/docs/api"
|
|
121
|
+
echo ""
|
|
122
|
+
read -r -p " API key (press Enter to skip): " SKILLSMP_KEY
|
|
123
|
+
if [ -n "$SKILLSMP_KEY" ]; then
|
|
124
|
+
if [ -f ".env" ] && grep -q '^SKILLSMP_API_KEY=' .env 2>/dev/null; then
|
|
125
|
+
sed -i "s/^SKILLSMP_API_KEY=.*/SKILLSMP_API_KEY=$SKILLSMP_KEY/" .env
|
|
126
|
+
else
|
|
127
|
+
echo "SKILLSMP_API_KEY=$SKILLSMP_KEY" >> .env
|
|
128
|
+
fi
|
|
129
|
+
green " → saved to .env"
|
|
130
|
+
else
|
|
131
|
+
yellow " → skipped (use --search with local REGISTRY.md only)"
|
|
132
|
+
fi
|
|
133
|
+
echo ""
|
|
134
|
+
|
|
135
|
+
# --- Step 4: Git Workflow ---
|
|
136
|
+
if [ "$GLOBAL" = false ]; then
|
|
137
|
+
bold "4. Git Workflow"
|
|
138
|
+
echo ""
|
|
139
|
+
|
|
140
|
+
# 4a. Branching
|
|
141
|
+
echo " Branching strategy:"
|
|
142
|
+
echo " 1) Direct main — commit + push direct to main (solo/small team)"
|
|
143
|
+
echo " 2) Dev branch — work on a fixed branch, PR to main when ready"
|
|
144
|
+
echo " 3) Feature branch — one branch per feature, merge via PR"
|
|
145
|
+
echo " 4) GitFlow — develop/release/hotfix (formal release cycles)"
|
|
146
|
+
read -r -p " Choice [1-4] (default: 1): " branch_choice
|
|
147
|
+
case "$branch_choice" in
|
|
148
|
+
2) GIT_BRANCHING="dev-branch" ;;
|
|
149
|
+
3) GIT_BRANCHING="feature-branches" ;;
|
|
150
|
+
4) GIT_BRANCHING="gitflow" ;;
|
|
151
|
+
*) GIT_BRANCHING="direct-main" ;;
|
|
152
|
+
esac
|
|
153
|
+
|
|
154
|
+
# If dev-branch, ask for branch name
|
|
155
|
+
GIT_WORK_BRANCH=""
|
|
156
|
+
if [ "$GIT_BRANCHING" = "dev-branch" ]; then
|
|
157
|
+
read -r -p " Working branch name (default: dev): " work_branch
|
|
158
|
+
GIT_WORK_BRANCH="${work_branch:-dev}"
|
|
159
|
+
green " → $GIT_BRANCHING (branch: $GIT_WORK_BRANCH)"
|
|
160
|
+
else
|
|
161
|
+
green " → $GIT_BRANCHING"
|
|
162
|
+
fi
|
|
163
|
+
echo ""
|
|
164
|
+
|
|
165
|
+
# 4b. Commit convention
|
|
166
|
+
echo " Commit convention:"
|
|
167
|
+
echo " 1) Conventional — feat(scope): description (default)"
|
|
168
|
+
echo " 2) Freeform — no enforced format"
|
|
169
|
+
read -r -p " Choice [1-2] (default: 1): " commit_choice
|
|
170
|
+
case "$commit_choice" in
|
|
171
|
+
2) GIT_COMMIT_CONVENTION="freeform" ;;
|
|
172
|
+
*) GIT_COMMIT_CONVENTION="conventional" ;;
|
|
173
|
+
esac
|
|
174
|
+
green " → $GIT_COMMIT_CONVENTION"
|
|
175
|
+
echo ""
|
|
176
|
+
|
|
177
|
+
# 4c. PR preference
|
|
178
|
+
echo " Pull requests:"
|
|
179
|
+
echo " 1) Never — /ship does commit + push, no PR"
|
|
180
|
+
echo " 2) On demand — /ship asks before creating a PR (default)"
|
|
181
|
+
echo " 3) Always — /ship always creates a PR"
|
|
182
|
+
read -r -p " Choice [1-3] (default: 2): " pr_choice
|
|
183
|
+
case "$pr_choice" in
|
|
184
|
+
1) GIT_PR_PREFERENCE="never" ;;
|
|
185
|
+
3) GIT_PR_PREFERENCE="always" ;;
|
|
186
|
+
*) GIT_PR_PREFERENCE="on-demand" ;;
|
|
187
|
+
esac
|
|
188
|
+
green " → $GIT_PR_PREFERENCE"
|
|
189
|
+
echo ""
|
|
190
|
+
|
|
191
|
+
# 4d. Auto-push
|
|
192
|
+
echo " Auto-push after commit:"
|
|
193
|
+
echo " 1) Never — commit only, manual push"
|
|
194
|
+
echo " 2) After commit — push automatically after each commit (default)"
|
|
195
|
+
echo " 3) Ask — ask each time"
|
|
196
|
+
read -r -p " Choice [1-3] (default: 2): " push_choice
|
|
197
|
+
case "$push_choice" in
|
|
198
|
+
1) GIT_AUTO_PUSH="never" ;;
|
|
199
|
+
3) GIT_AUTO_PUSH="ask" ;;
|
|
200
|
+
*) GIT_AUTO_PUSH="after-commit" ;;
|
|
201
|
+
esac
|
|
202
|
+
green " → $GIT_AUTO_PUSH"
|
|
203
|
+
echo ""
|
|
204
|
+
else
|
|
205
|
+
GIT_BRANCHING=""
|
|
206
|
+
GIT_COMMIT_CONVENTION=""
|
|
207
|
+
GIT_PR_PREFERENCE=""
|
|
208
|
+
GIT_AUTO_PUSH=""
|
|
209
|
+
GIT_WORK_BRANCH=""
|
|
210
|
+
fi
|
|
211
|
+
|
|
212
|
+
# --- Step 5: Summary + Confirmation ---
|
|
213
|
+
bold "5. Summary"
|
|
214
|
+
echo " Target: $TARGET_CLI"
|
|
215
|
+
echo " Scope: $([ "$GLOBAL" = true ] && echo "global (~/.${TARGET_CLI}/)" || echo "local (.${TARGET_CLI}/)")"
|
|
216
|
+
echo " Skills: $([ -n "$PROFILE" ] && echo "$PROFILE" || echo "all (36)")"
|
|
217
|
+
echo " SkillsMP: $([ -n "$SKILLSMP_KEY" ] && echo "configured" || echo "skipped")"
|
|
218
|
+
if [ -n "$GIT_BRANCHING" ]; then
|
|
219
|
+
echo " Branching: $GIT_BRANCHING$([ -n "$GIT_WORK_BRANCH" ] && echo " ($GIT_WORK_BRANCH)")"
|
|
220
|
+
echo " Commits: $GIT_COMMIT_CONVENTION"
|
|
221
|
+
echo " PRs: $GIT_PR_PREFERENCE"
|
|
222
|
+
echo " Auto-push: $GIT_AUTO_PUSH"
|
|
223
|
+
fi
|
|
224
|
+
echo ""
|
|
225
|
+
read -r -p "Proceed? [Y/n]: " confirm
|
|
226
|
+
case "$confirm" in
|
|
227
|
+
[nN]*)
|
|
228
|
+
yellow "Installation cancelled."
|
|
229
|
+
[ -n "$PROFILE_FILE" ] && rm -f "$PROFILE_FILE" 2>/dev/null
|
|
230
|
+
exit 0
|
|
231
|
+
;;
|
|
232
|
+
esac
|
|
233
|
+
|
|
234
|
+
# --- Auto git setup ---
|
|
235
|
+
if [ "$GLOBAL" = false ]; then
|
|
236
|
+
if [ ! -d ".git" ]; then
|
|
237
|
+
echo ""
|
|
238
|
+
read -r -p "No git repo detected. Initialize one? [Y/n]: " git_confirm
|
|
239
|
+
case "$git_confirm" in
|
|
240
|
+
[nN]*) yellow " → skipped git init" ;;
|
|
241
|
+
*)
|
|
242
|
+
git init -q
|
|
243
|
+
green " → git init done"
|
|
244
|
+
;;
|
|
245
|
+
esac
|
|
246
|
+
fi
|
|
247
|
+
if [ ! -f ".gitignore" ]; then
|
|
248
|
+
cat > .gitignore <<'GITIGNORE'
|
|
249
|
+
node_modules/
|
|
250
|
+
__pycache__/
|
|
251
|
+
.env
|
|
252
|
+
.env.local
|
|
253
|
+
*.log
|
|
254
|
+
dist/
|
|
255
|
+
build/
|
|
256
|
+
.DS_Store
|
|
257
|
+
GITIGNORE
|
|
258
|
+
green " → .gitignore created"
|
|
259
|
+
fi
|
|
260
|
+
fi
|
|
261
|
+
|
|
262
|
+
echo ""
|
|
263
|
+
green "Starting installation..."
|
|
264
|
+
echo ""
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# post-install-audit.sh — Lightweight security audit after CortexHawk install
|
|
3
|
+
# Usage: bash scripts/post-install-audit.sh <project_root>
|
|
4
|
+
# Always exits 0 — warnings only, never blocking
|
|
5
|
+
|
|
6
|
+
PROJECT_ROOT="${1:-.}"
|
|
7
|
+
|
|
8
|
+
if [ ! -d "$PROJECT_ROOT" ]; then
|
|
9
|
+
echo "post-install-audit: directory not found: $PROJECT_ROOT"
|
|
10
|
+
exit 0
|
|
11
|
+
fi
|
|
12
|
+
|
|
13
|
+
cd "$PROJECT_ROOT" || exit 0
|
|
14
|
+
|
|
15
|
+
WARNINGS=0
|
|
16
|
+
|
|
17
|
+
yellow() { printf "\033[33m%s\033[0m\n" "$1"; }
|
|
18
|
+
green() { printf "\033[32m%s\033[0m\n" "$1"; }
|
|
19
|
+
cyan() { printf "\033[36m%s\033[0m\n" "$1"; }
|
|
20
|
+
|
|
21
|
+
warn() { yellow " WARN: $1"; WARNINGS=$((WARNINGS + 1)); }
|
|
22
|
+
ok() { green " OK: $1"; }
|
|
23
|
+
|
|
24
|
+
echo ""
|
|
25
|
+
echo "================================"
|
|
26
|
+
cyan "Post-Install Security Audit"
|
|
27
|
+
echo "================================"
|
|
28
|
+
echo ""
|
|
29
|
+
|
|
30
|
+
# --- 1. .gitignore covers .env ---
|
|
31
|
+
echo "Checking .gitignore..."
|
|
32
|
+
if [ -f ".gitignore" ]; then
|
|
33
|
+
if grep -qE '^\s*\.env\b' ".gitignore"; then
|
|
34
|
+
ok ".gitignore covers .env"
|
|
35
|
+
else
|
|
36
|
+
warn ".gitignore exists but does not cover .env"
|
|
37
|
+
fi
|
|
38
|
+
else
|
|
39
|
+
warn "No .gitignore found — create one with .env listed"
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
# --- 2. No .env files committed ---
|
|
43
|
+
echo "Checking for committed .env files..."
|
|
44
|
+
if command -v git &>/dev/null && [ -d ".git" ]; then
|
|
45
|
+
ENV_FILES=$(git ls-files '*.env' '.env' '.env.*' '.env.local' '.env.production' 2>/dev/null)
|
|
46
|
+
if [ -n "$ENV_FILES" ]; then
|
|
47
|
+
warn "Tracked .env files found: $ENV_FILES"
|
|
48
|
+
else
|
|
49
|
+
ok "No .env files in git history"
|
|
50
|
+
fi
|
|
51
|
+
else
|
|
52
|
+
ok "Not a git repo — skipping tracked .env check"
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
# --- 3. Hardcoded secrets in source files ---
|
|
56
|
+
echo "Checking for hardcoded secrets..."
|
|
57
|
+
SECRET_PATTERNS='(api[_-]?key|api[_-]?secret|password|passwd|token|secret[_-]?key|PRIVATE.KEY|AWS_SECRET)\s*[=:]\s*["'"'"'][^\s"'"'"']{8,}'
|
|
58
|
+
if command -v git &>/dev/null && [ -d ".git" ]; then
|
|
59
|
+
HITS=$(git ls-files -- '*.py' '*.js' '*.ts' '*.jsx' '*.tsx' '*.go' '*.rs' '*.java' '*.rb' '*.sh' '*.yaml' '*.yml' '*.toml' 2>/dev/null \
|
|
60
|
+
| xargs grep -lEi "$SECRET_PATTERNS" 2>/dev/null || true)
|
|
61
|
+
else
|
|
62
|
+
HITS=$(find . -maxdepth 3 -type f \( -name '*.py' -o -name '*.js' -o -name '*.ts' -o -name '*.jsx' -o -name '*.tsx' -o -name '*.go' -o -name '*.rs' -o -name '*.java' -o -name '*.rb' -o -name '*.sh' \) 2>/dev/null \
|
|
63
|
+
| xargs grep -lEi "$SECRET_PATTERNS" 2>/dev/null || true)
|
|
64
|
+
fi
|
|
65
|
+
if [ -n "$HITS" ]; then
|
|
66
|
+
for f in $HITS; do
|
|
67
|
+
warn "Potential secret in: $f"
|
|
68
|
+
done
|
|
69
|
+
else
|
|
70
|
+
ok "No hardcoded secrets detected"
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
# --- 4. Dependency vulnerabilities (non-blocking) ---
|
|
74
|
+
echo "Checking dependency vulnerabilities..."
|
|
75
|
+
AUDIT_RAN=false
|
|
76
|
+
if [ -f "package-lock.json" ] || [ -f "package.json" ]; then
|
|
77
|
+
if command -v npm &>/dev/null; then
|
|
78
|
+
VULN_OUTPUT=$(npm audit --json 2>/dev/null | grep -o '"total":[0-9]*' | head -1 | cut -d: -f2)
|
|
79
|
+
if [ -n "$VULN_OUTPUT" ] && [ "$VULN_OUTPUT" -gt 0 ] 2>/dev/null; then
|
|
80
|
+
warn "npm audit: $VULN_OUTPUT vulnerabilities found — run 'npm audit' for details"
|
|
81
|
+
else
|
|
82
|
+
ok "npm audit: no vulnerabilities"
|
|
83
|
+
fi
|
|
84
|
+
AUDIT_RAN=true
|
|
85
|
+
fi
|
|
86
|
+
fi
|
|
87
|
+
if [ -f "requirements.txt" ] || [ -f "pyproject.toml" ]; then
|
|
88
|
+
if command -v pip-audit &>/dev/null; then
|
|
89
|
+
VULN_COUNT=$(pip-audit 2>/dev/null | grep -c 'VULN' || echo 0)
|
|
90
|
+
if [ "$VULN_COUNT" -gt 0 ]; then
|
|
91
|
+
warn "pip-audit: $VULN_COUNT vulnerabilities found — run 'pip-audit' for details"
|
|
92
|
+
else
|
|
93
|
+
ok "pip-audit: no vulnerabilities"
|
|
94
|
+
fi
|
|
95
|
+
AUDIT_RAN=true
|
|
96
|
+
fi
|
|
97
|
+
fi
|
|
98
|
+
if [ "$AUDIT_RAN" = false ]; then
|
|
99
|
+
ok "No supported dependency manager detected — skipping"
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
# --- 5. Sensitive files tracked in git ---
|
|
103
|
+
echo "Checking for tracked sensitive files..."
|
|
104
|
+
SENSITIVE_PATTERNS='\.pem$|\.key$|\.p12$|\.pfx$|\.keystore$|id_rsa|id_ed25519|\.ssh/'
|
|
105
|
+
if command -v git &>/dev/null && [ -d ".git" ]; then
|
|
106
|
+
SENSITIVE_FILES=$(git ls-files 2>/dev/null | grep -E "$SENSITIVE_PATTERNS" || true)
|
|
107
|
+
if [ -n "$SENSITIVE_FILES" ]; then
|
|
108
|
+
for f in $SENSITIVE_FILES; do
|
|
109
|
+
warn "Sensitive file tracked: $f"
|
|
110
|
+
done
|
|
111
|
+
else
|
|
112
|
+
ok "No sensitive files tracked"
|
|
113
|
+
fi
|
|
114
|
+
else
|
|
115
|
+
ok "Not a git repo — skipping sensitive file check"
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
# --- Summary ---
|
|
119
|
+
echo ""
|
|
120
|
+
echo "================================"
|
|
121
|
+
if [ "$WARNINGS" -gt 0 ]; then
|
|
122
|
+
yellow "Audit complete: $WARNINGS warning(s)"
|
|
123
|
+
echo ""
|
|
124
|
+
cyan "Run /scan for a full AI-powered security audit."
|
|
125
|
+
else
|
|
126
|
+
green "Audit complete: all checks clean"
|
|
127
|
+
fi
|
|
128
|
+
echo ""
|
|
129
|
+
|
|
130
|
+
exit 0
|