axel-setup 0.2.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 (117) hide show
  1. package/CHANGELOG.md +218 -0
  2. package/CONTRIBUTING.md +58 -0
  3. package/LICENSE +21 -0
  4. package/README.md +518 -0
  5. package/agents/api-design.md +51 -0
  6. package/agents/bughunter.md +136 -0
  7. package/agents/changelog.md +89 -0
  8. package/agents/cleanup.md +126 -0
  9. package/agents/compare-branch.md +35 -0
  10. package/agents/cross-repo.md +97 -0
  11. package/agents/db-check.md +14 -0
  12. package/agents/debug.md +47 -0
  13. package/agents/deploy-check.md +100 -0
  14. package/agents/draft-message.md +19 -0
  15. package/agents/excelsior-coordinator.md +75 -0
  16. package/agents/excelsior-verifier.md +94 -0
  17. package/agents/feature.md +48 -0
  18. package/agents/harness-optimizer.md +40 -0
  19. package/agents/incident.md +48 -0
  20. package/agents/linear-task.md +18 -0
  21. package/agents/onboard.md +24 -0
  22. package/agents/perf.md +44 -0
  23. package/agents/production-validator.md +96 -0
  24. package/agents/review.md +113 -0
  25. package/agents/security-check.md +29 -0
  26. package/agents/sprint-summary.md +15 -0
  27. package/agents/tdd-mainder.md +178 -0
  28. package/agents/test-gen.md +39 -0
  29. package/axel-manifest.json +129 -0
  30. package/bin/axel-setup.js +597 -0
  31. package/bootstrap.sh +1087 -0
  32. package/commands/create-pr.md +13 -0
  33. package/commands/daily.md +182 -0
  34. package/commands/deslop.md +13 -0
  35. package/commands/draft-message.md +23 -0
  36. package/commands/eod-review.md +154 -0
  37. package/commands/execute-prp.md +37 -0
  38. package/commands/generate-prp.md +75 -0
  39. package/commands/multi-repo-feature.md +60 -0
  40. package/commands/roadmap.md +31 -0
  41. package/commands/sprint-status.md +486 -0
  42. package/commands/style.md +68 -0
  43. package/commands/visualize.md +17 -0
  44. package/docs/roadmap/multi-runtime.md +73 -0
  45. package/docs/superpowers/plans/2026-06-12-setup-hardening-roadmap.md +61 -0
  46. package/hooks/desktop-notify.sh +26 -0
  47. package/hooks/enforce-agent-model.jq +14 -0
  48. package/hooks/gsd-context-monitor.js +156 -0
  49. package/hooks/linear-lifecycle-sync.sh +112 -0
  50. package/hooks/memory-dedup.sh +122 -0
  51. package/hooks/memory-extractor.sh +218 -0
  52. package/hooks/post-commit-memory-trigger.sh +16 -0
  53. package/hooks/post-commit-verify.sh +41 -0
  54. package/hooks/post-edit-lint.sh +43 -0
  55. package/hooks/precompact-save-context.sh +124 -0
  56. package/hooks/priority-map-staleness.sh +29 -0
  57. package/hooks/proactive-resolver.sh +104 -0
  58. package/hooks/session-auto-title.sh +165 -0
  59. package/hooks/session-checkpoint.sh +97 -0
  60. package/hooks/session-cost-log.sh +77 -0
  61. package/hooks/session-log-action.sh +36 -0
  62. package/hooks/session-log-prompt.sh +25 -0
  63. package/hooks/session-restore.sh +45 -0
  64. package/hooks/session-save.sh +81 -0
  65. package/hooks/session-summarize.sh +154 -0
  66. package/hooks/validate-commit-format.sh +38 -0
  67. package/hooks/weekly-priority-map-review.sh +143 -0
  68. package/install.sh +46 -0
  69. package/package.json +67 -0
  70. package/scripts/ci/bootstrap-dry-run.sh +40 -0
  71. package/scripts/ci/check.sh +65 -0
  72. package/scripts/posthog-snapshot-loader.sh +112 -0
  73. package/skills/context-budget/SKILL.md +86 -0
  74. package/skills/memory-review/SKILL.md +100 -0
  75. package/skills/model-routing/SKILL.md +70 -0
  76. package/skills/posthog-weekly/SKILL.md +271 -0
  77. package/skills/ui-ux-pro-max/SKILL.md +377 -0
  78. package/skills/ui-ux-pro-max/data/charts.csv +26 -0
  79. package/skills/ui-ux-pro-max/data/colors.csv +97 -0
  80. package/skills/ui-ux-pro-max/data/icons.csv +101 -0
  81. package/skills/ui-ux-pro-max/data/landing.csv +31 -0
  82. package/skills/ui-ux-pro-max/data/products.csv +97 -0
  83. package/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
  84. package/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -0
  85. package/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  86. package/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  87. package/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  88. package/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  89. package/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  90. package/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  91. package/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  92. package/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  93. package/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  94. package/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  95. package/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  96. package/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  97. package/skills/ui-ux-pro-max/data/styles.csv +68 -0
  98. package/skills/ui-ux-pro-max/data/typography.csv +58 -0
  99. package/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  100. package/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  101. package/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
  102. package/skills/ui-ux-pro-max/scripts/core.py +253 -0
  103. package/skills/ui-ux-pro-max/scripts/design_system.py +1067 -0
  104. package/skills/ui-ux-pro-max/scripts/search.py +114 -0
  105. package/templates/AGENTS.runtime.md +17 -0
  106. package/templates/CLAUDE.md +252 -0
  107. package/templates/claude-monitor.plist +35 -0
  108. package/templates/keybindings.json +13 -0
  109. package/templates/merge-settings.jq +53 -0
  110. package/templates/review-upgrades.md +44 -0
  111. package/templates/settings.json +255 -0
  112. package/templates/statusline-command.sh +182 -0
  113. package/tests/fixtures/hooks/events.json +32 -0
  114. package/tools/session-costs-view.sh +128 -0
  115. package/tools/session-dashboard-gen.sh +369 -0
  116. package/tools/session-live.sh +173 -0
  117. package/tools/session-server.js +441 -0
@@ -0,0 +1,38 @@
1
+ #!/bin/bash
2
+ # Validates commit message format: tipo (Modelo/Archivo): Mensaje
3
+ # Reads $TOOL_INPUT as JSON, extracts the command, then validates the commit message
4
+ # Valid types: feat|fix|chore|refactor|test|docs|style|perf|ci|build|revert
5
+
6
+ TOOL_JSON="$TOOL_INPUT"
7
+
8
+ # Extract the command field from the Bash tool JSON input
9
+ CMD=$(echo "$TOOL_JSON" | jq -r '.command // empty' 2>/dev/null)
10
+ [ -z "$CMD" ] && CMD="$TOOL_JSON"
11
+
12
+ # Only check git commit commands
13
+ echo "$CMD" | grep -qE 'git commit' || exit 0
14
+
15
+ # Extract commit message from -m flag
16
+ # Handles: -m "msg", -m 'msg', -m "$(cat <<'EOF'\nmsg\nEOF\n)"
17
+ MSG=$(echo "$CMD" | sed -n 's/.*-m[[:space:]]*["'\'']\{0,1\}\(.*\)/\1/p' | sed 's/["'\'']\{0,1\}[[:space:]]*$//' | head -1)
18
+
19
+ # For heredoc pattern: extract the first content line
20
+ if echo "$MSG" | grep -q '<<'; then
21
+ MSG=$(echo "$CMD" | tr '\n' '|' | sed 's/.*<<[^|]*|//' | sed 's/|.*//' | sed 's/^[[:space:]]*//')
22
+ fi
23
+
24
+ # If we couldn't extract a message, skip validation (might be --amend or interactive)
25
+ [ -z "$MSG" ] && exit 0
26
+
27
+ # Validate format: tipo (Scope): message
28
+ if ! echo "$MSG" | grep -qE '^(feat|fix|chore|refactor|test|docs|style|perf|ci|build|revert)\s*\('; then
29
+ echo "BLOCKED: Commit format is incorrect." >&2
30
+ echo "Required: type (Scope): Descriptive message" >&2
31
+ echo "Canonical example: feat (AuthController): add OAuth2 login flow" >&2
32
+ echo "Valid types: feat|fix|chore|refactor|test|docs|style|perf|ci|build|revert" >&2
33
+ echo "Do not use --no-verify to bypass this check. Fix the message instead." >&2
34
+ echo "Got: $MSG" >&2
35
+ exit 1
36
+ fi
37
+
38
+ exit 0
@@ -0,0 +1,143 @@
1
+ #!/bin/bash
2
+ # Weekly priority-map review — intended to run every Monday 9am via LaunchAgent/cron.
3
+ # Analyzes git activity from the last 7 days + current priority-map and writes
4
+ # an update proposal. Does not modify priority-map directly — user reviews and applies.
5
+ #
6
+ # Configuration (env vars):
7
+ # PRIORITY_MAP_REPOS — space-separated list of absolute repo paths to scan.
8
+ # Example: "$HOME/work/api $HOME/work/web"
9
+ # If unset/empty, the git-evidence section is skipped.
10
+
11
+ set -e
12
+
13
+ MEMORY_DIR="$HOME/.claude/memory"
14
+ PRIORITY_MAP="$MEMORY_DIR/priority-map.md"
15
+ ARCHIVE="$MEMORY_DIR/MEMORY-archive.md"
16
+ LOG_DIR="$HOME/.claude/logs"
17
+ mkdir -p "$LOG_DIR"
18
+ LOG_FILE="$LOG_DIR/priority-map-review.log"
19
+
20
+ TIMESTAMP=$(date +%Y-%m-%d)
21
+ PROPOSAL_FILE="$MEMORY_DIR/priority-map.proposed-${TIMESTAMP}.md"
22
+ REVIEW_SUMMARY="$MEMORY_DIR/priority-map-review-${TIMESTAMP}.md"
23
+
24
+ echo "=== priority-map review $(date) ===" >> "$LOG_FILE"
25
+
26
+ if [[ ! -f "$PRIORITY_MAP" ]]; then
27
+ echo "ERROR: priority-map.md does not exist at $MEMORY_DIR" >> "$LOG_FILE"
28
+ exit 1
29
+ fi
30
+
31
+ # Anti-recursion guard: prevents infinite loops if this hook is wired into a
32
+ # lifecycle event that fires during the claude -p subprocess below.
33
+ if [[ -n "$CLAUDE_HOOK_RUNNING" ]]; then
34
+ echo "SKIP: CLAUDE_HOOK_RUNNING set — avoiding recursion" >> "$LOG_FILE"
35
+ exit 0
36
+ fi
37
+ export CLAUDE_HOOK_RUNNING=1
38
+
39
+ # Isolated JSONL session to avoid polluting /resume history.
40
+ ISOLATED_SESSION_DIR=$(mktemp -d)
41
+ export CLAUDE_SESSION_DIR="$ISOLATED_SESSION_DIR"
42
+
43
+ # Collect git evidence from the last 7 days across configured repos.
44
+ REPOS="${PRIORITY_MAP_REPOS:-}"
45
+ GIT_EVIDENCE=$(
46
+ if [[ -z "$REPOS" ]]; then
47
+ echo "(PRIORITY_MAP_REPOS not set — skipping git evidence collection)"
48
+ else
49
+ for repo in $REPOS; do
50
+ [ -d "$repo/.git" ] || continue
51
+ repo_name=$(basename "$repo")
52
+ echo "## $repo_name"
53
+ cd "$repo" 2>/dev/null && {
54
+ git fetch origin --quiet 2>/dev/null || true
55
+ echo "### Merged PRs last 7 days"
56
+ git log --first-parent origin/main --since="7 days ago" --pretty=format:'- %s' 2>/dev/null | head -30
57
+ echo ""
58
+ echo "### New branches (not merged to main)"
59
+ if [[ "$(uname)" == "Darwin" ]]; then
60
+ SEVEN_DAYS_AGO=$(date -v-7d +%Y-%m-%d)
61
+ else
62
+ SEVEN_DAYS_AGO=$(date -d '7 days ago' +%Y-%m-%d)
63
+ fi
64
+ git for-each-ref --sort=-committerdate --format='%(refname:short) %(committerdate:short)' refs/remotes/origin 2>/dev/null | awk -v d="$SEVEN_DAYS_AGO" '$2 >= d {print "- " $0}' | head -20
65
+ echo ""
66
+ }
67
+ done
68
+ fi
69
+ )
70
+
71
+ PROMPT=$(cat <<PROMPT_EOF
72
+ It is Monday morning. Your task: review the user priority-map.md and propose an update based on recent git activity.
73
+
74
+ **Input 1 — current priority-map:**
75
+ \`\`\`
76
+ $(cat "$PRIORITY_MAP")
77
+ \`\`\`
78
+
79
+ **Input 2 — git activity last 7 days (tracked repos):**
80
+ \`\`\`
81
+ $GIT_EVIDENCE
82
+ \`\`\`
83
+
84
+ **Input 3 — current archive:**
85
+ \`\`\`
86
+ $(cat "$ARCHIVE" 2>/dev/null || echo "empty")
87
+ \`\`\`
88
+
89
+ **Expected output — write TWO files:**
90
+
91
+ 1. \`$REVIEW_SUMMARY\` — short analysis summary:
92
+ - P0 items in the priority-map that look CLOSED based on git (matching merged PR)
93
+ - P1 items in the priority-map that look CLOSED based on git
94
+ - New items detected in git that should be promoted to P0/P1 (large features, recent PRs with no card in the map)
95
+ - P0/P1 items with NO activity in 7 days → flag as stale
96
+ - Concrete question at the end: "Confirm moving items [X, Y, Z] to archive and adding [A, B] to P0/P1?"
97
+
98
+ 2. \`$PROPOSAL_FILE\` — full proposal for the new priority-map.md:
99
+ - Same structure as current
100
+ - Closed items removed
101
+ - New items added in the matching bucket
102
+ - Updated field set to $TIMESTAMP
103
+ - Sprint field only if you can infer it from context, otherwise leave it
104
+ - Do NOT overwrite \`$PRIORITY_MAP\` directly — only the .proposed file
105
+
106
+ **Rules:**
107
+ - Conservative: if an item does not clearly match a merged PR, do NOT move it to the archive.
108
+ - If there is not enough evidence to propose changes → write "No changes suggested — priority-map looks up to date" in the review summary.
109
+ - Do not invent new P0s without git evidence.
110
+ PROMPT_EOF
111
+ )
112
+
113
+ # Resolve claude CLI: prefer PATH, fall back gracefully if not found.
114
+ CLAUDE_BIN=$(command -v claude || true)
115
+ if [[ -z "$CLAUDE_BIN" ]]; then
116
+ echo "ERROR: claude CLI not found in PATH" >> "$LOG_FILE"
117
+ rm -rf "$ISOLATED_SESSION_DIR"
118
+ exit 1
119
+ fi
120
+
121
+ echo "Running claude -p..." >> "$LOG_FILE"
122
+ "$CLAUDE_BIN" -p "$PROMPT" \
123
+ --allowed-tools "Read,Write,Edit,Bash,Glob,Grep" \
124
+ >> "$LOG_FILE" 2>&1 || {
125
+ echo "ERROR: claude -p failed" >> "$LOG_FILE"
126
+ /usr/bin/osascript -e 'display notification "claude -p failed — check ~/.claude/logs/priority-map-review.log" with title "Priority Map Review"' 2>/dev/null || true
127
+ rm -rf "$ISOLATED_SESSION_DIR"
128
+ exit 1
129
+ }
130
+
131
+ rm -rf "$ISOLATED_SESSION_DIR"
132
+
133
+ # Notify via macOS notification center (no-op on Linux).
134
+ if [[ -f "$REVIEW_SUMMARY" ]]; then
135
+ /usr/bin/osascript -e "display notification \"Review $REVIEW_SUMMARY and $PROPOSAL_FILE\" with title \"Priority Map Review — Monday\" sound name \"Purr\"" 2>/dev/null || true
136
+ echo "OK — files generated: $REVIEW_SUMMARY, $PROPOSAL_FILE" >> "$LOG_FILE"
137
+ else
138
+ /usr/bin/osascript -e 'display notification "Review produced no files — check ~/.claude/logs/priority-map-review.log" with title "Priority Map Review"' 2>/dev/null || true
139
+ echo "WARNING: claude -p finished but $REVIEW_SUMMARY is missing" >> "$LOG_FILE"
140
+ fi
141
+
142
+ echo "=== end $(date) ===" >> "$LOG_FILE"
143
+ exit 0
package/install.sh ADDED
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env sh
2
+ set -eu
3
+
4
+ AXEL_PACKAGE="${AXEL_SETUP_PACKAGE:-axel-setup@latest}"
5
+ AXEL_NPX="${AXEL_SETUP_NPX:-npx}"
6
+
7
+ die() {
8
+ printf '%s\n' "AXEL install error: $*" >&2
9
+ exit 1
10
+ }
11
+
12
+ require_command() {
13
+ if ! command -v "$1" >/dev/null 2>&1; then
14
+ die "$2"
15
+ fi
16
+ }
17
+
18
+ uses_non_claude_target() {
19
+ target="claude"
20
+ while [ "$#" -gt 0 ]; do
21
+ case "$1" in
22
+ --target=*)
23
+ target="${1#*=}"
24
+ ;;
25
+ --target)
26
+ shift
27
+ target="${1:-claude}"
28
+ ;;
29
+ esac
30
+ [ "$#" -gt 0 ] || break
31
+ shift
32
+ done
33
+
34
+ [ "$target" = "codex" ] || [ "$target" = "generic" ]
35
+ }
36
+
37
+ require_command zsh "zsh is required. Install Xcode Command Line Tools or a zsh package before running AXEL."
38
+ require_command jq "jq is required. On macOS, install it with: brew install jq"
39
+ require_command node "Node.js is required because the packaged AXEL CLI runs through npx. Install Node 18 or newer."
40
+ require_command "$AXEL_NPX" "npx is required. Install npm with Node.js, then rerun this installer."
41
+
42
+ if ! uses_non_claude_target "$@" && [ "${AXEL_SETUP_SKIP_CLAUDE_CHECK:-false}" != "true" ]; then
43
+ require_command claude "Claude Code CLI is required for the default target. Install Claude Code, pass --target codex or --target generic, or set AXEL_SETUP_SKIP_CLAUDE_CHECK=true."
44
+ fi
45
+
46
+ exec "$AXEL_NPX" -y "$AXEL_PACKAGE" "$@"
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "axel-setup",
3
+ "version": "0.2.0",
4
+ "description": "Claude Code-first team configuration package with hooks, agents, commands, skills, plugins, and repeatable bootstrap tooling.",
5
+ "license": "MIT",
6
+ "author": {
7
+ "name": "Cristian Vera Lyon",
8
+ "url": "https://github.com/cveralyon"
9
+ },
10
+ "keywords": [
11
+ "claude-code",
12
+ "ai-agents",
13
+ "developer-tools",
14
+ "automation",
15
+ "devex",
16
+ "mcp",
17
+ "agentic-engineering",
18
+ "codex",
19
+ "multi-runtime",
20
+ "bootstrap"
21
+ ],
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+https://github.com/cveralyon/axel-setup.git"
25
+ },
26
+ "homepage": "https://github.com/cveralyon/axel-setup#readme",
27
+ "bugs": {
28
+ "url": "https://github.com/cveralyon/axel-setup/issues"
29
+ },
30
+ "bin": {
31
+ "axel-setup": "bin/axel-setup.js"
32
+ },
33
+ "files": [
34
+ "agents",
35
+ "commands",
36
+ "hooks",
37
+ "scripts",
38
+ "skills",
39
+ "templates",
40
+ "tools",
41
+ "docs",
42
+ "bin",
43
+ "tests/fixtures",
44
+ "install.sh",
45
+ "bootstrap.sh",
46
+ "axel-manifest.json",
47
+ "CHANGELOG.md",
48
+ "CONTRIBUTING.md",
49
+ "LICENSE",
50
+ "README.md",
51
+ "!skills/**/__pycache__",
52
+ "!skills/**/*.pyc"
53
+ ],
54
+ "scripts": {
55
+ "check": "bash scripts/ci/check.sh",
56
+ "smoke": "bash scripts/ci/bootstrap-dry-run.sh",
57
+ "pack:dry-run": "npm pack --dry-run",
58
+ "publish:dry-run": "npm publish --dry-run",
59
+ "prepublishOnly": "npm run check"
60
+ },
61
+ "engines": {
62
+ "node": ">=18"
63
+ },
64
+ "publishConfig": {
65
+ "access": "public"
66
+ }
67
+ }
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
5
+ TMP_HOME="$(mktemp -d)"
6
+ TMP_BIN="$(mktemp -d)"
7
+
8
+ cleanup() {
9
+ rm -rf "$TMP_HOME" "$TMP_BIN"
10
+ }
11
+ trap cleanup EXIT
12
+
13
+ cat >"$TMP_BIN/claude" <<'STUB'
14
+ #!/usr/bin/env bash
15
+ case "${1:-}" in
16
+ --version)
17
+ echo "Claude Code 1.0.0"
18
+ ;;
19
+ plugins)
20
+ exit 0
21
+ ;;
22
+ *)
23
+ echo "claude stub"
24
+ ;;
25
+ esac
26
+ STUB
27
+ chmod +x "$TMP_BIN/claude"
28
+
29
+ PATH="$TMP_BIN:$PATH" \
30
+ HOME="$TMP_HOME" \
31
+ bash "$ROOT/bootstrap.sh" \
32
+ --dry-run \
33
+ --user-name "CI Bot" \
34
+ --user-context "CI smoke test" \
35
+ --language english
36
+
37
+ if [ -e "$TMP_HOME/.claude" ]; then
38
+ echo "Dry run created $TMP_HOME/.claude" >&2
39
+ exit 1
40
+ fi
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
5
+ cd "$ROOT"
6
+
7
+ echo "Checking shell syntax"
8
+ while IFS= read -r -d '' file; do
9
+ if head -n 1 "$file" | grep -q "zsh"; then
10
+ zsh -n "$file"
11
+ else
12
+ bash -n "$file"
13
+ fi
14
+ done < <(find . -path ./.git -prune -o -type f -name "*.sh" -print0)
15
+
16
+ if command -v shellcheck >/dev/null 2>&1; then
17
+ echo "Running shellcheck"
18
+ while IFS= read -r -d '' file; do
19
+ if head -n 1 "$file" | grep -q "zsh"; then
20
+ continue
21
+ fi
22
+ shellcheck -S error "$file"
23
+ done < <(find . -path ./.git -prune -o -type f -name "*.sh" -print0)
24
+ else
25
+ echo "Skipping shellcheck (not installed)"
26
+ fi
27
+
28
+ if command -v shfmt >/dev/null 2>&1; then
29
+ echo "Checking shell formatting"
30
+ shfmt -d -i 2 -ci scripts/ci/*.sh tests/*.sh
31
+ else
32
+ echo "Skipping shfmt (not installed)"
33
+ fi
34
+
35
+ echo "Checking Node CLI syntax"
36
+ node --check bin/axel-setup.js
37
+
38
+ echo "Checking jq filters"
39
+ while IFS= read -r -d '' file; do
40
+ jq -n -f "$file" >/dev/null
41
+ done < <(find . -path ./.git -prune -o -type f -name "*.jq" -print0)
42
+
43
+ echo "Checking JSON files"
44
+ jq empty package.json axel-manifest.json templates/settings.json templates/keybindings.json
45
+
46
+ echo "Running bootstrap dry run smoke test"
47
+ bash scripts/ci/bootstrap-dry-run.sh
48
+
49
+ echo "Running bootstrap behavior tests"
50
+ bash tests/bootstrap-behavior.sh
51
+
52
+ echo "Running one-line installer tests"
53
+ bash tests/install-one-line.sh
54
+
55
+ echo "Running hook harness tests"
56
+ bash tests/hook-harness.sh
57
+
58
+ echo "Running CLI doctor tests"
59
+ bash tests/cli-doctor.sh
60
+
61
+ echo "Running settings merge fixture tests"
62
+ bash tests/merge-settings.sh
63
+
64
+ echo "Checking npm package contents"
65
+ npm pack --dry-run >/dev/null
@@ -0,0 +1,112 @@
1
+ #!/bin/bash
2
+ # posthog-snapshot-loader.sh
3
+ # Reads ~/.claude/cache/posthog-snapshot.json and prints a markdown summary
4
+ # for inclusion in larger reports (e.g. /sprint-status, /eod-review, /daily).
5
+ #
6
+ # Output contract:
7
+ # - If snapshot does not exist: prints a one-line nudge ("📊 No PostHog snapshot…").
8
+ # - If snapshot exists and is < 14 days old: prints a structured markdown block
9
+ # with critical findings, wins, and improvements.
10
+ # - If snapshot exists and is > 14 days old: prints a stale warning instead of
11
+ # the full block, so callers don't quote outdated insights at users.
12
+ #
13
+ # The snapshot is generated by the /posthog-weekly skill. This loader is
14
+ # read-only: it never refreshes data. To refresh, the user runs /posthog-weekly.
15
+ #
16
+ # Output format is plain markdown so callers can either include it verbatim
17
+ # in a larger report or pipe it to another tool. Exit code is always 0 — this
18
+ # script never blocks the caller, even when the snapshot is missing or stale.
19
+
20
+ set -e
21
+
22
+ SNAPSHOT="$HOME/.claude/cache/posthog-snapshot.json"
23
+ STALE_DAYS="${POSTHOG_SNAPSHOT_STALE_DAYS:-14}"
24
+
25
+ # Case 1: no snapshot at all → silent nudge, single line
26
+ if [ ! -f "$SNAPSHOT" ]; then
27
+ echo "📊 _No PostHog snapshot yet — run \`/posthog-weekly\` to generate one._"
28
+ exit 0
29
+ fi
30
+
31
+ # Case 2: snapshot exists but is unreadable / not valid JSON
32
+ if ! jq empty "$SNAPSHOT" 2>/dev/null; then
33
+ echo "⚠️ _PostHog snapshot at \`$SNAPSHOT\` is not valid JSON — re-run \`/posthog-weekly\` to regenerate._"
34
+ exit 0
35
+ fi
36
+
37
+ # Compute snapshot age in days. The snapshot stores its timestamp as ISO 8601
38
+ # UTC. macOS `date -j -f` parses it; Linux `date -d` is the GNU equivalent.
39
+ TS=$(jq -r '.timestamp // empty' "$SNAPSHOT")
40
+ if [ -z "$TS" ]; then
41
+ echo "⚠️ _PostHog snapshot has no timestamp — re-run \`/posthog-weekly\` to regenerate._"
42
+ exit 0
43
+ fi
44
+
45
+ NOW_EPOCH=$(date +%s)
46
+ SNAP_EPOCH=$(date -j -f "%Y-%m-%dT%H:%M:%SZ" "$TS" +%s 2>/dev/null \
47
+ || date -d "$TS" +%s 2>/dev/null \
48
+ || echo 0)
49
+
50
+ if [ "$SNAP_EPOCH" -eq 0 ]; then
51
+ echo "⚠️ _PostHog snapshot timestamp \`$TS\` could not be parsed — re-run \`/posthog-weekly\`._"
52
+ exit 0
53
+ fi
54
+
55
+ AGE_DAYS=$(( (NOW_EPOCH - SNAP_EPOCH) / 86400 ))
56
+
57
+ # Case 3: stale snapshot → short warning, no quoted findings
58
+ if [ "$AGE_DAYS" -gt "$STALE_DAYS" ]; then
59
+ echo "⚠️ _PostHog snapshot is **${AGE_DAYS} days old** (stale > ${STALE_DAYS}d). Run \`/posthog-weekly\` to refresh before quoting._"
60
+ exit 0
61
+ fi
62
+
63
+ # Case 4: fresh snapshot → full block
64
+ PROJECT_NAME=$(jq -r '.project_name // "PostHog"' "$SNAPSHOT")
65
+ PROJECT_URL=$(jq -r '.project_url // empty' "$SNAPSHOT")
66
+
67
+ echo "## 📊 PostHog Insights — ${PROJECT_NAME}"
68
+ echo ""
69
+ echo "_Snapshot from ${AGE_DAYS} day(s) ago — generated by \`/posthog-weekly\`_"
70
+ echo ""
71
+
72
+ # Critical findings — most important, always shown first
73
+ CRITICAL_COUNT=$(jq -r '.critical_findings | length' "$SNAPSHOT")
74
+ if [ "$CRITICAL_COUNT" -gt 0 ]; then
75
+ echo "### 🚨 Critical findings"
76
+ jq -r '.critical_findings[] | "- \(.)"' "$SNAPSHOT"
77
+ echo ""
78
+ fi
79
+
80
+ # Regressions / anomalies
81
+ REGRESSION_COUNT=$(jq -r '.regressions // [] | length' "$SNAPSHOT")
82
+ if [ "$REGRESSION_COUNT" -gt 0 ]; then
83
+ echo "### 📉 Regressions & anomalies"
84
+ jq -r '.regressions[] | "- \(.)"' "$SNAPSHOT"
85
+ echo ""
86
+ fi
87
+
88
+ # Wins
89
+ WIN_COUNT=$(jq -r '.wins // [] | length' "$SNAPSHOT")
90
+ if [ "$WIN_COUNT" -gt 0 ]; then
91
+ echo "### ✅ Wins"
92
+ jq -r '.wins[] | "- \(.)"' "$SNAPSHOT"
93
+ echo ""
94
+ fi
95
+
96
+ # Improvement opportunities
97
+ IMPROVEMENT_COUNT=$(jq -r '.improvements // [] | length' "$SNAPSHOT")
98
+ if [ "$IMPROVEMENT_COUNT" -gt 0 ]; then
99
+ echo "### 🎯 Improvement opportunities"
100
+ jq -r '.improvements[] | "- \(.)"' "$SNAPSHOT"
101
+ echo ""
102
+ fi
103
+
104
+ # Project link if available
105
+ if [ -n "$PROJECT_URL" ]; then
106
+ echo "_Project: <${PROJECT_URL}>_"
107
+ echo ""
108
+ fi
109
+
110
+ echo "_For deeper analysis, run \`/posthog-weekly\` to refresh this snapshot._"
111
+
112
+ exit 0
@@ -0,0 +1,86 @@
1
+ ---
2
+ name: context-budget
3
+ description: Audits Claude Code context consumption across agents, skills, commands, hooks, MCP servers, and the CLAUDE.md/MEMORY chain. Identifies bloat and redundancy, then produces prioritized token-savings recommendations. Backs the /context-budget command.
4
+ origin: ECC (adapted)
5
+ ---
6
+
7
+ # Context Budget
8
+
9
+ Estimate the token overhead of everything loaded into a Claude Code session and surface concrete ways to reclaim context space. Adapted from ECC's context-budget for a single-runtime (Claude Code) setup on a large Opus window.
10
+
11
+ ## When to Use
12
+
13
+ - The setup has grown (many agents, hooks, skills, MCP servers) and you want the real load cost.
14
+ - Output quality degrades, or the context monitor fires earlier than expected.
15
+ - Before adding more agents, skills, or MCP servers: check headroom first.
16
+ - Running the `/context-budget` command (this skill backs it).
17
+
18
+ ## How It Works
19
+
20
+ Token estimation: prose uses `words × 1.3`, code or JSON uses `chars / 4`.
21
+
22
+ ### Phase 1 — Inventory
23
+
24
+ Scan each source and estimate tokens.
25
+
26
+ - **Agents** (`~/.claude/agents/*.md`): tokens per file. Flag files over 200 lines (heavy) and a `description` over 30 words (it loads into every Task tool invocation, even for agents never spawned).
27
+ - **Skills** (`~/.claude/skills/*/SKILL.md`): tokens per SKILL.md. Flag over 400 lines.
28
+ - **Commands** (`~/.claude/commands/*.md`): tokens per file. Flag stale or duplicated entries.
29
+ - **Hooks** (`~/.claude/hooks/` plus the wiring in `settings.json`): count active hooks. Flag heavy or overlapping ones.
30
+ - **MCP servers** (active MCP config): count servers and total tools. Estimate ~500 tokens per tool schema. Flag servers over 20 tools, and servers that wrap a CLI already available for free (gh, git, vercel, supabase).
31
+ - **CLAUDE.md and memory chain** (`~/CLAUDE.md`, `~/.claude/memory/MEMORY.md`, any project CLAUDE.md): tokens per file. Flag a combined total over 400 lines, or a MEMORY index that carries detail instead of one-line pointers.
32
+
33
+ Note on RTK: it compresses Bash OUTPUT at runtime. It does not reduce the LOAD cost of this setup. Measure the load cost (the files above), not RTK-filtered command output.
34
+
35
+ ### Phase 2 — Classify
36
+
37
+ | Bucket | Criteria | Action |
38
+ |--------|----------|--------|
39
+ | Always needed | Referenced in CLAUDE.md, backs an active command, or matches current work | Keep |
40
+ | Sometimes needed | Domain-specific, not referenced in CLAUDE.md | On-demand or lazy-load |
41
+ | Rarely needed | No reference, overlapping content, no project match | Remove or archive |
42
+
43
+ ### Phase 3 — Detect Issues
44
+
45
+ - Bloated agent descriptions (over 30 words): present in every Task tool context.
46
+ - Heavy agents (over 200 lines): inflate Task context on every spawn.
47
+ - Redundant components: skills that duplicate agent logic, memory entries that duplicate CLAUDE.md rules.
48
+ - MCP over-subscription: many servers, or servers wrapping free CLI tools.
49
+ - CLAUDE.md or MEMORY bloat: verbose sections, stale rules, MEMORY entries carrying detail instead of a one-line hook.
50
+
51
+ ### Phase 4 — Report
52
+
53
+ ```
54
+ Context Budget Report
55
+ ═══════════════════════════════════════
56
+ Window: Opus (1M tokens)
57
+ Total estimated setup overhead: ~XX,XXX tokens (XX% of 1M)
58
+ Effective working context: ~XXX,XXX tokens
59
+
60
+ Component Breakdown:
61
+ ┌───────────────┬───────┬──────────┐
62
+ │ Component │ Count │ Tokens │
63
+ ├───────────────┼───────┼──────────┤
64
+ │ Agents │ N │ ~X,XXX │
65
+ │ Skills │ N │ ~X,XXX │
66
+ │ Commands │ N │ ~X,XXX │
67
+ │ Hooks │ N │ ~X,XXX │
68
+ │ MCP tools │ N │ ~XX,XXX │
69
+ │ CLAUDE+memory │ N │ ~X,XXX │
70
+ └───────────────┴───────┴──────────┘
71
+
72
+ Top 3 Optimizations (ranked by savings):
73
+ 1. [action] → ~X,XXX tokens
74
+ 2. [action] → ~X,XXX tokens
75
+ 3. [action] → ~X,XXX tokens
76
+ ```
77
+
78
+ In verbose mode, add per-file token counts, the heaviest files line-counted, and the MCP tool list with per-tool schema estimates.
79
+
80
+ ## Best Practices
81
+
82
+ - MCP is usually the biggest lever. One 30-tool server can cost more than every skill combined.
83
+ - Agent descriptions load always, even for agents never invoked. Keep them tight.
84
+ - On a 1M window the absolute overhead matters less than redundancy and menu noise. Prioritize removing stale or duplicated surface over shaving raw tokens.
85
+ - Re-audit after adding any agent, skill, or MCP server to catch creep early.
86
+ - Pairs with the `harness-optimizer` agent, which consumes this report as its baseline.