@theglitchking/babel-fish 1.0.1 → 2.0.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/.claude/install.sh +666 -0
- package/.claude/project-map/PROJECT_MAP.md +61 -0
- package/.claude/project-map/checksums.json +6 -0
- package/.claude/project-map/generate.py +1481 -0
- package/.claude/project-map/grader.py +583 -0
- package/.claude/project-map/learned-vocabulary.json +1 -0
- package/.claude/project-map/mine-sessions.py +419 -0
- package/.claude/project-map/reports/install-report.md +54 -0
- package/.claude/project-map/reports/iteration-01-report.md +54 -0
- package/.claude/project-map/reports/iteration-01-score.json +7 -0
- package/.claude/project-map/sections/01-vocabulary.md +8 -0
- package/.claude/project-map/sections/02-service-topology.md +6 -0
- package/.claude/project-map/sections/03-environment.md +6 -0
- package/.claude/project-map/sections/04-api-routes.md +6 -0
- package/.claude/project-map/sections/05-data-models.md +4 -0
- package/.claude/project-map/sections/06-schemas.md +4 -0
- package/.claude/project-map/sections/07-services.md +6 -0
- package/.claude/project-map/sections/08-background-jobs.md +5 -0
- package/.claude/project-map/sections/09-frontend-features.md +4 -0
- package/.claude/project-map/sections/10-tools-commands.md +8 -0
- package/.claude/project-map/sections/11-migrations.md +4 -0
- package/.claude/project-map/sections/12-import-chains.md +7 -0
- package/.claude/project-map/sections/13-frontend-backend-map.md +8 -0
- package/.claude/project-map/sections/14-reverse-proxy.md +4 -0
- package/.claude/project-map/sections/15-auth-config.md +6 -0
- package/.claude/project-map/sections/16-infra-profile.md +13 -0
- package/.claude/project-map/sections/17-learned-vocabulary.md +7 -0
- package/.claude/project-map/sections/18-dead-code.md +9 -0
- package/.claude/project-map/sections/19-doc-pointers.md +5 -0
- package/.claude/project-map/stack.json +12 -0
- package/.claude/rules/operational-runbook.md +40 -0
- package/.claude/rules/project-vocabulary.md +25 -0
- package/.claude/scripts/detect-stack.sh +222 -0
- package/.claude/scripts/ensure-python.sh +100 -0
- package/.claude/scripts/statusline.sh +27 -0
- package/.claude/scripts/validate.sh +59 -0
- package/.claude/settings.json +6 -0
- package/.claude/skills/babel-fish-developer-skill/SKILL.md +56 -0
- package/.claude/templates/SKILL.md.template +56 -0
- package/.claude/templates/operational-runbook.md.template +40 -0
- package/.claude/templates/project-vocabulary.md.template +25 -0
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/.githooks/install.sh +4 -0
- package/.githooks/pre-commit +22 -0
- package/CHANGELOG.md +72 -0
- package/README.md +18 -0
- package/bin/babel-fish.js +78 -71
- package/commands/policy.md +16 -0
- package/commands/relink.md +6 -0
- package/commands/status.md +6 -0
- package/commands/update.md +6 -0
- package/hooks/hooks.json +15 -0
- package/hooks/session-start.js +11 -0
- package/package.json +17 -4
- package/scripts/link-skills.js +31 -0
|
@@ -0,0 +1,666 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ============================================================
|
|
3
|
+
# Babel Fish Plugin — Installer
|
|
4
|
+
# Triggered automatically on plugin installation.
|
|
5
|
+
#
|
|
6
|
+
# What this does:
|
|
7
|
+
# 1. Checks / installs Python >= 3.8
|
|
8
|
+
# 2. Detects project stack
|
|
9
|
+
# 3. Runs generate.py → grades with grader.py (up to 3 iterations)
|
|
10
|
+
# 4. Renders skill + rules files from templates
|
|
11
|
+
# 5. Installs git hooks
|
|
12
|
+
# 6. Prints a final summary with the grade report path
|
|
13
|
+
#
|
|
14
|
+
# Usage:
|
|
15
|
+
# bash .claude/install.sh [project-root]
|
|
16
|
+
# ============================================================
|
|
17
|
+
|
|
18
|
+
set -euo pipefail
|
|
19
|
+
|
|
20
|
+
# ── Help ──────────────────────────────────────────────────────────────────────
|
|
21
|
+
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
|
|
22
|
+
cat <<'HELP'
|
|
23
|
+
|
|
24
|
+
╔══════════════════════════════════════════════════════════════════╗
|
|
25
|
+
║ Babel Fish Plugin — Help ║
|
|
26
|
+
╚══════════════════════════════════════════════════════════════════╝
|
|
27
|
+
|
|
28
|
+
WHAT IT DOES
|
|
29
|
+
Builds a self-updating developer context system for your repo:
|
|
30
|
+
- Project map split into 19 focused sections (routes, models, infra, etc.)
|
|
31
|
+
- Vocabulary translator: maps plain English to exact file paths
|
|
32
|
+
- Developer skill auto-loaded in every Claude Code session
|
|
33
|
+
- Operational runbook for gotchas and deploy procedures
|
|
34
|
+
- Pre-commit hook that keeps the map current automatically
|
|
35
|
+
- Iterative quality grading (0-100%) with a 90% pass threshold
|
|
36
|
+
|
|
37
|
+
REQUIREMENTS
|
|
38
|
+
- Claude Code >= 1.0.0
|
|
39
|
+
- Python >= 3.8 (auto-installed if missing)
|
|
40
|
+
- bash
|
|
41
|
+
- Optional: pip install pyyaml (for docker-compose parsing)
|
|
42
|
+
|
|
43
|
+
INSTALLATION
|
|
44
|
+
Preview all changes first (nothing is modified):
|
|
45
|
+
|
|
46
|
+
bash .claude/install.sh --dry-run
|
|
47
|
+
|
|
48
|
+
Run the installer:
|
|
49
|
+
|
|
50
|
+
bash .claude/install.sh
|
|
51
|
+
|
|
52
|
+
Or with an explicit project root:
|
|
53
|
+
|
|
54
|
+
bash .claude/install.sh /path/to/your/project
|
|
55
|
+
|
|
56
|
+
One-liner from the internet (checksum-verified):
|
|
57
|
+
|
|
58
|
+
curl -sSL https://raw.githubusercontent.com/TheGlitchKing/babel-fish/main/install.sh | bash
|
|
59
|
+
|
|
60
|
+
Preview before running remotely:
|
|
61
|
+
|
|
62
|
+
curl -sSL https://raw.githubusercontent.com/TheGlitchKing/babel-fish/main/install.sh | bash -s -- --dry-run
|
|
63
|
+
|
|
64
|
+
Via npm (no curl needed):
|
|
65
|
+
|
|
66
|
+
npx @theglitchking/babel-fish dry-run
|
|
67
|
+
npx @theglitchking/babel-fish init
|
|
68
|
+
|
|
69
|
+
Via the Glitch Kingdom Marketplace in Claude Code:
|
|
70
|
+
|
|
71
|
+
/plugin marketplace add TheGlitchKing/glitch-kingdom-of-plugins
|
|
72
|
+
/plugin install TheGlitchKing/babel-fish
|
|
73
|
+
|
|
74
|
+
WHAT HAPPENS ON INSTALL
|
|
75
|
+
1. Python >= 3.8 is checked and installed if missing
|
|
76
|
+
2. Stack is detected (language, framework, DB, ORM, auth, infra)
|
|
77
|
+
3. generate.py runs to build the 19-section project map
|
|
78
|
+
4. grader.py scores the output 0-100% across 7 categories
|
|
79
|
+
5. If score < 90%, it retries up to 3 times automatically
|
|
80
|
+
6. Skills and rules files are rendered from templates
|
|
81
|
+
7. Pre-commit git hook is installed
|
|
82
|
+
8. CLAUDE.md is updated with a project map pointer
|
|
83
|
+
9. A final quality report is written to:
|
|
84
|
+
.claude/project-map/reports/install-report.md
|
|
85
|
+
|
|
86
|
+
POST-INSTALL COMMANDS
|
|
87
|
+
Regenerate the map (forced):
|
|
88
|
+
python .claude/project-map/generate.py --force
|
|
89
|
+
|
|
90
|
+
Regenerate only if files changed (fast, used by pre-commit):
|
|
91
|
+
python .claude/project-map/generate.py
|
|
92
|
+
|
|
93
|
+
Re-grade the current map output:
|
|
94
|
+
python .claude/project-map/grader.py
|
|
95
|
+
|
|
96
|
+
Mine past Claude Code sessions for vocabulary aliases:
|
|
97
|
+
python .claude/project-map/mine-sessions.py
|
|
98
|
+
python .claude/project-map/mine-sessions.py --verbose
|
|
99
|
+
python .claude/project-map/mine-sessions.py --dry-run
|
|
100
|
+
|
|
101
|
+
Re-install git hooks (if you cloned a fresh copy):
|
|
102
|
+
bash .githooks/install.sh
|
|
103
|
+
|
|
104
|
+
Re-run the full installer:
|
|
105
|
+
bash .claude/install.sh
|
|
106
|
+
|
|
107
|
+
USING THE DEVELOPER SKILL
|
|
108
|
+
After install, invoke your project skill in Claude Code:
|
|
109
|
+
|
|
110
|
+
/babel-fish-developer (or /<your-project-slug>-developer)
|
|
111
|
+
|
|
112
|
+
The skill reads PROJECT_MAP.md and loads only the 2-3 sections
|
|
113
|
+
relevant to your current task (typically 5-20KB of context).
|
|
114
|
+
|
|
115
|
+
KEY FILES AFTER INSTALL
|
|
116
|
+
.claude/project-map/PROJECT_MAP.md — Map index + quick routing
|
|
117
|
+
.claude/project-map/sections/01-*.md — Vocabulary translator
|
|
118
|
+
.claude/project-map/sections/04-*.md — API routes
|
|
119
|
+
.claude/project-map/sections/05-*.md — Data models
|
|
120
|
+
.claude/project-map/reports/install-report.md — Quality report
|
|
121
|
+
.claude/rules/project-vocabulary.md — Auto-loaded every session
|
|
122
|
+
.claude/rules/operational-runbook.md — Edit manually to grow over time
|
|
123
|
+
.claude/skills/<slug>-developer-skill/ — Your developer skill
|
|
124
|
+
.githooks/pre-commit — Auto-regenerates map on commit
|
|
125
|
+
|
|
126
|
+
GRADING CATEGORIES (90% to pass)
|
|
127
|
+
Section completeness 25% — All 19 sections generated
|
|
128
|
+
Vocabulary accuracy 20% — Entries map to real files
|
|
129
|
+
Import chain validity 15% — Chains trace to real modules
|
|
130
|
+
Secret safety 15% — No API keys or tokens leaked
|
|
131
|
+
Section size bounds 10% — Each section 0.1-50KB
|
|
132
|
+
Structural integrity 10% — Valid markdown, working TOC links
|
|
133
|
+
Checksum function 5% — Re-run skips when nothing changed
|
|
134
|
+
|
|
135
|
+
EXAMPLES
|
|
136
|
+
# Install on current directory
|
|
137
|
+
bash .claude/install.sh
|
|
138
|
+
|
|
139
|
+
# Install on a specific project
|
|
140
|
+
bash .claude/install.sh /mnt/e/my-project
|
|
141
|
+
|
|
142
|
+
# Force-regenerate after adding new routes
|
|
143
|
+
python .claude/project-map/generate.py --force
|
|
144
|
+
|
|
145
|
+
# Check map quality after a big refactor
|
|
146
|
+
python .claude/project-map/grader.py
|
|
147
|
+
|
|
148
|
+
# See what vocabulary aliases were learned from your sessions
|
|
149
|
+
python .claude/project-map/mine-sessions.py --dry-run --verbose
|
|
150
|
+
|
|
151
|
+
HELP
|
|
152
|
+
|
|
153
|
+
exit 0
|
|
154
|
+
fi
|
|
155
|
+
|
|
156
|
+
# ── Argument parsing ─────────────────────────────────────────────────────────
|
|
157
|
+
DRY_RUN=false
|
|
158
|
+
POSITIONAL=""
|
|
159
|
+
for arg in "$@"; do
|
|
160
|
+
case "$arg" in
|
|
161
|
+
--dry-run) DRY_RUN=true ;;
|
|
162
|
+
-*) ;; # ignore unknown flags
|
|
163
|
+
*) POSITIONAL="$arg" ;;
|
|
164
|
+
esac
|
|
165
|
+
done
|
|
166
|
+
|
|
167
|
+
# Resolve absolute path immediately
|
|
168
|
+
PROJECT_ROOT="$(cd "${POSITIONAL:-$(pwd)}" && pwd)"
|
|
169
|
+
PLUGIN_SOURCE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
170
|
+
CLAUDE_DIR="$PROJECT_ROOT/.claude"
|
|
171
|
+
MAP_DIR="$CLAUDE_DIR/project-map"
|
|
172
|
+
REPORTS_DIR="$MAP_DIR/reports"
|
|
173
|
+
SCRIPTS_DIR="$CLAUDE_DIR/scripts"
|
|
174
|
+
TEMPLATES_DIR="$CLAUDE_DIR/templates"
|
|
175
|
+
|
|
176
|
+
MAX_ITERATIONS=3
|
|
177
|
+
PASS_THRESHOLD=90
|
|
178
|
+
PREVIOUS_SCORE=""
|
|
179
|
+
|
|
180
|
+
# Dry-run helper — prints the action instead of doing it
|
|
181
|
+
_dry() { printf '%b\n' "${YELLOW} [dry-run] $*${RESET}"; }
|
|
182
|
+
|
|
183
|
+
# ── Colors ───────────────────────────────────────────────────────────────────
|
|
184
|
+
CYAN='\033[36m'; GREEN='\033[32m'; YELLOW='\033[33m'; RED='\033[31m'
|
|
185
|
+
BOLD='\033[1m'; RESET='\033[0m'
|
|
186
|
+
|
|
187
|
+
banner() { printf '\n%b\n' "${CYAN}${BOLD}══ $* ══${RESET}"; }
|
|
188
|
+
step() { printf '%b\n' "${CYAN}▶ $*${RESET}"; }
|
|
189
|
+
ok() { printf '%b\n' "${GREEN}✓ $*${RESET}"; }
|
|
190
|
+
warn() { printf '%b\n' "${YELLOW}⚠ $*${RESET}"; }
|
|
191
|
+
fail() { printf '%b\n' "${RED}✗ $*${RESET}"; }
|
|
192
|
+
info() { printf '%b\n' " $*"; }
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
# ╔══════════════════════════════════════════════════════════════════════════╗
|
|
196
|
+
# ║ HELPER FUNCTIONS (must be defined before main flow) ║
|
|
197
|
+
# ╚══════════════════════════════════════════════════════════════════════════╝
|
|
198
|
+
|
|
199
|
+
_improve_for_next_iteration() {
|
|
200
|
+
local score_json="$1"
|
|
201
|
+
local python_cmd="$3"
|
|
202
|
+
|
|
203
|
+
[ -f "$score_json" ] || return
|
|
204
|
+
|
|
205
|
+
local issues
|
|
206
|
+
issues=$("$python_cmd" -c "
|
|
207
|
+
import json
|
|
208
|
+
d = json.load(open('$score_json'))
|
|
209
|
+
for issue in d.get('issues', []):
|
|
210
|
+
print(issue['category'] + ': ' + issue['issue'])
|
|
211
|
+
" 2>/dev/null || true)
|
|
212
|
+
|
|
213
|
+
if [ -n "$issues" ]; then
|
|
214
|
+
info "Issues from previous iteration:"
|
|
215
|
+
echo "$issues" | while IFS= read -r line; do
|
|
216
|
+
info " → $line"
|
|
217
|
+
done
|
|
218
|
+
fi
|
|
219
|
+
info "Will re-run generate.py with --force for next iteration..."
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
_render_vocabulary() {
|
|
223
|
+
local project_root="$1"
|
|
224
|
+
local name="$2"
|
|
225
|
+
local lang="$3"
|
|
226
|
+
local framework="$4"
|
|
227
|
+
local rules_dir="$5"
|
|
228
|
+
local out="$rules_dir/project-vocabulary.md"
|
|
229
|
+
local template="$TEMPLATES_DIR/project-vocabulary.md.template"
|
|
230
|
+
|
|
231
|
+
if [ -f "$template" ]; then
|
|
232
|
+
sed \
|
|
233
|
+
-e "s|{{PROJECT_NAME}}|$name|g" \
|
|
234
|
+
-e "s|{{LANGUAGE}}|$lang|g" \
|
|
235
|
+
-e "s|{{FRAMEWORK}}|$framework|g" \
|
|
236
|
+
"$template" > "$out"
|
|
237
|
+
else
|
|
238
|
+
cat > "$out" <<VOCAB
|
|
239
|
+
# ${name} — Project Vocabulary
|
|
240
|
+
|
|
241
|
+
> Auto-loaded every session. Maps human language to exact code locations.
|
|
242
|
+
|
|
243
|
+
## Feature → Code Location
|
|
244
|
+
|
|
245
|
+
| You Say | Frontend | Backend | Model/Table |
|
|
246
|
+
|---------|----------|---------|-------------|
|
|
247
|
+
| _(vocabulary populates as source code is added)_ | | | |
|
|
248
|
+
|
|
249
|
+
## Quick Actions
|
|
250
|
+
|
|
251
|
+
| You Say | What To Do |
|
|
252
|
+
|---------|-----------|
|
|
253
|
+
| regenerate map | \`python .claude/project-map/generate.py --force\` |
|
|
254
|
+
| grade map | \`python .claude/project-map/grader.py\` |
|
|
255
|
+
VOCAB
|
|
256
|
+
fi
|
|
257
|
+
ok "Rendered: $out"
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
_render_runbook() {
|
|
261
|
+
local name="$2"
|
|
262
|
+
local rules_dir="$3"
|
|
263
|
+
local out="$rules_dir/operational-runbook.md"
|
|
264
|
+
local template="$TEMPLATES_DIR/operational-runbook.md.template"
|
|
265
|
+
|
|
266
|
+
if [ -f "$out" ]; then
|
|
267
|
+
ok "Runbook already exists — preserving: $out"
|
|
268
|
+
return
|
|
269
|
+
fi
|
|
270
|
+
|
|
271
|
+
if [ -f "$template" ]; then
|
|
272
|
+
sed -e "s|{{PROJECT_NAME}}|$name|g" "$template" > "$out"
|
|
273
|
+
else
|
|
274
|
+
cat > "$out" <<RUNBOOK
|
|
275
|
+
# ${name} — Operational Runbook
|
|
276
|
+
|
|
277
|
+
> Auto-loaded every session. Edit this file manually — NOT overwritten on regeneration.
|
|
278
|
+
|
|
279
|
+
## Environment Differences
|
|
280
|
+
|
|
281
|
+
| | Dev | Staging | Production |
|
|
282
|
+
|---|---|---|---|
|
|
283
|
+
| **URL** | | | |
|
|
284
|
+
| **Database** | | | |
|
|
285
|
+
|
|
286
|
+
## Known Issues & Workarounds
|
|
287
|
+
|
|
288
|
+
_No known issues documented yet._
|
|
289
|
+
|
|
290
|
+
## Key Commands
|
|
291
|
+
|
|
292
|
+
| Command | What It Does |
|
|
293
|
+
|---------|-------------|
|
|
294
|
+
| \`python .claude/project-map/generate.py --force\` | Regenerate project map |
|
|
295
|
+
| \`python .claude/project-map/grader.py\` | Grade map quality |
|
|
296
|
+
RUNBOOK
|
|
297
|
+
fi
|
|
298
|
+
ok "Rendered: $out"
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
_render_skill() {
|
|
302
|
+
local project_root="$1"
|
|
303
|
+
local name="$2"
|
|
304
|
+
local slug="$3"
|
|
305
|
+
local lang="$4"
|
|
306
|
+
local framework="$5"
|
|
307
|
+
local skills_dir="$6"
|
|
308
|
+
local out="$skills_dir/SKILL.md"
|
|
309
|
+
local template="$TEMPLATES_DIR/SKILL.md.template"
|
|
310
|
+
|
|
311
|
+
if [ -f "$template" ]; then
|
|
312
|
+
sed \
|
|
313
|
+
-e "s|{{PROJECT_NAME}}|$name|g" \
|
|
314
|
+
-e "s|{{PROJECT_SLUG}}|$slug|g" \
|
|
315
|
+
-e "s|{{LANGUAGE}}|$lang|g" \
|
|
316
|
+
-e "s|{{FRAMEWORK}}|$framework|g" \
|
|
317
|
+
"$template" > "$out"
|
|
318
|
+
else
|
|
319
|
+
cat > "$out" <<SKILL
|
|
320
|
+
---
|
|
321
|
+
name: ${slug}-developer-skill
|
|
322
|
+
description: |
|
|
323
|
+
Full-stack developer context for ${name} (${lang}/${framework}).
|
|
324
|
+
Invoke when working on any ${name} feature, bug, or infrastructure task.
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
# /${slug}-developer — ${name} Developer Context
|
|
328
|
+
|
|
329
|
+
## On Trigger
|
|
330
|
+
|
|
331
|
+
\`\`\`
|
|
332
|
+
Read: .claude/project-map/PROJECT_MAP.md
|
|
333
|
+
\`\`\`
|
|
334
|
+
|
|
335
|
+
Use the Quick Routing table to pick 2-3 sections to load.
|
|
336
|
+
|
|
337
|
+
## Section Routing
|
|
338
|
+
|
|
339
|
+
| Task | Read These Sections |
|
|
340
|
+
|------|-------------------|
|
|
341
|
+
| Feature / UX work | 01-vocabulary → 09-frontend → 04-routes |
|
|
342
|
+
| Add a model or field | 05-models → 06-schemas → 12-import-chains |
|
|
343
|
+
| Troubleshoot error | 02-topology → 03-environment → 14-proxy |
|
|
344
|
+
| Infrastructure | 16-infra-profile → 02-topology |
|
|
345
|
+
| Auth / security | 15-auth-config |
|
|
346
|
+
| Tools | 10-tools-commands |
|
|
347
|
+
|
|
348
|
+
## Stack: ${lang} / ${framework}
|
|
349
|
+
SKILL
|
|
350
|
+
fi
|
|
351
|
+
ok "Rendered: $out"
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
_install_git_hooks() {
|
|
355
|
+
local project_root="$1"
|
|
356
|
+
local hooks_dir="$2"
|
|
357
|
+
local pre_commit="$hooks_dir/pre-commit"
|
|
358
|
+
|
|
359
|
+
local hook_snippet='# ── Codebase Mapper: regenerate project map on relevant changes ──
|
|
360
|
+
STAGED_FILES=$(git diff --cached --name-only 2>/dev/null || true)
|
|
361
|
+
EXTENSIONS_PATTERN='"'"'\.(py|ts|tsx|js|jsx|go|java|yaml|yml)$|docker-compose|package\.json|Cargo\.toml|go\.mod'"'"'
|
|
362
|
+
if echo "$STAGED_FILES" | grep -qE "$EXTENSIONS_PATTERN" 2>/dev/null; then
|
|
363
|
+
MAP_SCRIPT=".claude/project-map/generate.py"
|
|
364
|
+
if [ -f "$MAP_SCRIPT" ]; then
|
|
365
|
+
PYTHON=""
|
|
366
|
+
if [ -f ".venv/bin/python3" ]; then PYTHON=".venv/bin/python3"
|
|
367
|
+
elif command -v python3 &>/dev/null; then PYTHON="python3"
|
|
368
|
+
elif command -v python &>/dev/null; then PYTHON="python"
|
|
369
|
+
fi
|
|
370
|
+
if [ -n "$PYTHON" ]; then
|
|
371
|
+
echo "[codebase-mapper] Regenerating project map..."
|
|
372
|
+
if $PYTHON "$MAP_SCRIPT" 2>/dev/null; then
|
|
373
|
+
git add .claude/project-map/PROJECT_MAP.md .claude/project-map/checksums.json \
|
|
374
|
+
.claude/project-map/sections/*.md .claude/project-map/learned-vocabulary.json 2>/dev/null || true
|
|
375
|
+
fi
|
|
376
|
+
fi
|
|
377
|
+
fi
|
|
378
|
+
fi
|
|
379
|
+
# ── End Codebase Mapper ──────────────────────────────────────────────────────'
|
|
380
|
+
|
|
381
|
+
if [ -f "$pre_commit" ]; then
|
|
382
|
+
if ! grep -q 'Codebase Mapper' "$pre_commit" 2>/dev/null; then
|
|
383
|
+
{ echo ""; echo "$hook_snippet"; } >> "$pre_commit"
|
|
384
|
+
ok "Appended to existing pre-commit hook"
|
|
385
|
+
else
|
|
386
|
+
ok "pre-commit hook already contains Codebase Mapper snippet"
|
|
387
|
+
fi
|
|
388
|
+
else
|
|
389
|
+
printf '#!/bin/bash\n%s\n' "$hook_snippet" > "$pre_commit"
|
|
390
|
+
ok "Created pre-commit hook"
|
|
391
|
+
fi
|
|
392
|
+
|
|
393
|
+
chmod +x "$pre_commit"
|
|
394
|
+
|
|
395
|
+
cat > "$hooks_dir/install.sh" <<'INSTALL'
|
|
396
|
+
#!/bin/bash
|
|
397
|
+
git config core.hooksPath .githooks
|
|
398
|
+
chmod +x .githooks/*
|
|
399
|
+
echo "Git hooks installed (.githooks/ directory configured)"
|
|
400
|
+
INSTALL
|
|
401
|
+
chmod +x "$hooks_dir/install.sh"
|
|
402
|
+
|
|
403
|
+
if git -C "$project_root" rev-parse --git-dir > /dev/null 2>&1; then
|
|
404
|
+
git -C "$project_root" config core.hooksPath .githooks
|
|
405
|
+
ok "Configured git to use .githooks/"
|
|
406
|
+
fi
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
_update_claude_md() {
|
|
410
|
+
local project_root="$1"
|
|
411
|
+
local name="$2"
|
|
412
|
+
local claude_md="$project_root/.claude/CLAUDE.md"
|
|
413
|
+
|
|
414
|
+
if [ -f "$claude_md" ] && grep -q 'Project Map' "$claude_md" 2>/dev/null; then
|
|
415
|
+
ok "CLAUDE.md already has Project Map section"
|
|
416
|
+
return
|
|
417
|
+
fi
|
|
418
|
+
|
|
419
|
+
local pointer
|
|
420
|
+
pointer=$(cat <<'POINTER'
|
|
421
|
+
|
|
422
|
+
## Project Map
|
|
423
|
+
|
|
424
|
+
**Project Map**: For any project-specific question, read
|
|
425
|
+
[`.claude/project-map/PROJECT_MAP.md`](.claude/project-map/PROJECT_MAP.md) —
|
|
426
|
+
auto-generated index of routes, models, import chains, infra profile,
|
|
427
|
+
and vocabulary translator. Regenerated automatically on commit.
|
|
428
|
+
|
|
429
|
+
To regenerate manually:
|
|
430
|
+
```bash
|
|
431
|
+
python .claude/project-map/generate.py --force
|
|
432
|
+
```
|
|
433
|
+
POINTER
|
|
434
|
+
)
|
|
435
|
+
|
|
436
|
+
if [ -f "$claude_md" ]; then
|
|
437
|
+
echo "$pointer" >> "$claude_md"
|
|
438
|
+
ok "Updated CLAUDE.md with Project Map pointer"
|
|
439
|
+
else
|
|
440
|
+
cat > "$claude_md" <<CLAUDEMD
|
|
441
|
+
# CLAUDE.md
|
|
442
|
+
|
|
443
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
444
|
+
|
|
445
|
+
## Project Overview
|
|
446
|
+
|
|
447
|
+
**${name}** — see README.md for details.
|
|
448
|
+
${pointer}
|
|
449
|
+
CLAUDEMD
|
|
450
|
+
ok "Created CLAUDE.md"
|
|
451
|
+
fi
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
# ╔══════════════════════════════════════════════════════════════════════════╗
|
|
456
|
+
# ║ MAIN FLOW ║
|
|
457
|
+
# ╚══════════════════════════════════════════════════════════════════════════╝
|
|
458
|
+
|
|
459
|
+
clear
|
|
460
|
+
printf '%b\n' "
|
|
461
|
+
${CYAN}${BOLD}
|
|
462
|
+
╔══════════════════════════════════════════╗
|
|
463
|
+
║ Babel Fish Plugin Installer ║
|
|
464
|
+
║ by TheGlitchKing ║
|
|
465
|
+
╚══════════════════════════════════════════╝
|
|
466
|
+
${RESET}"
|
|
467
|
+
|
|
468
|
+
info "Project root: $PROJECT_ROOT"
|
|
469
|
+
info "Timestamp: $(date '+%Y-%m-%d %H:%M:%S')"
|
|
470
|
+
echo
|
|
471
|
+
|
|
472
|
+
# ── Dry-run preview ──────────────────────────────────────────────────────────
|
|
473
|
+
if $DRY_RUN; then
|
|
474
|
+
printf '%b\n' "${YELLOW}${BOLD} DRY RUN — nothing will be created or modified${RESET}"
|
|
475
|
+
echo
|
|
476
|
+
printf '%b\n' "${CYAN}${BOLD} Files this installer will create:${RESET}"
|
|
477
|
+
_dry "mkdir -p $CLAUDE_DIR/scripts"
|
|
478
|
+
_dry "mkdir -p $CLAUDE_DIR/templates"
|
|
479
|
+
_dry "mkdir -p $CLAUDE_DIR/project-map/sections"
|
|
480
|
+
_dry "mkdir -p $CLAUDE_DIR/project-map/reports"
|
|
481
|
+
_dry "mkdir -p $CLAUDE_DIR/rules"
|
|
482
|
+
_dry "mkdir -p $CLAUDE_DIR/skills/<project>-developer-skill/"
|
|
483
|
+
_dry "copy scripts/*.sh → $CLAUDE_DIR/scripts/"
|
|
484
|
+
_dry "copy templates/*.template → $CLAUDE_DIR/templates/"
|
|
485
|
+
_dry "copy project-map/*.py → $CLAUDE_DIR/project-map/"
|
|
486
|
+
_dry "write $CLAUDE_DIR/project-map/PROJECT_MAP.md"
|
|
487
|
+
_dry "write $CLAUDE_DIR/project-map/sections/01-vocabulary.md (+ 18 more sections)"
|
|
488
|
+
_dry "write $CLAUDE_DIR/project-map/reports/install-report.md"
|
|
489
|
+
_dry "write $CLAUDE_DIR/rules/project-vocabulary.md"
|
|
490
|
+
_dry "write $CLAUDE_DIR/rules/operational-runbook.md"
|
|
491
|
+
_dry "write $CLAUDE_DIR/skills/<project>-developer-skill/SKILL.md"
|
|
492
|
+
_dry "write .githooks/pre-commit"
|
|
493
|
+
_dry "run git config core.hooksPath .githooks"
|
|
494
|
+
_dry "write/update CLAUDE.md (appends project map pointer)"
|
|
495
|
+
echo
|
|
496
|
+
printf '%b\n' "${CYAN}${BOLD} What the installer will NOT do:${RESET}"
|
|
497
|
+
_dry " — will not modify any of your source files"
|
|
498
|
+
_dry " — will not install packages globally"
|
|
499
|
+
_dry " — will not make network requests (except git clone if run via curl)"
|
|
500
|
+
_dry " — will not run Python with elevated permissions"
|
|
501
|
+
echo
|
|
502
|
+
printf '%b\n' "${GREEN} Run without --dry-run to apply.${RESET}"
|
|
503
|
+
exit 0
|
|
504
|
+
fi
|
|
505
|
+
|
|
506
|
+
# ── Step 0: Bootstrap plugin files into target project ───────────────────────
|
|
507
|
+
# When running from an external source (e.g. marketplace install), copy all
|
|
508
|
+
# plugin scripts, templates, and python files into the target project's .claude/
|
|
509
|
+
if [ "$PLUGIN_SOURCE_DIR" != "$CLAUDE_DIR" ]; then
|
|
510
|
+
mkdir -p "$CLAUDE_DIR/scripts" "$CLAUDE_DIR/templates" "$CLAUDE_DIR/project-map" "$CLAUDE_DIR/rules" "$CLAUDE_DIR/skills"
|
|
511
|
+
cp -r "$PLUGIN_SOURCE_DIR/scripts/." "$CLAUDE_DIR/scripts/"
|
|
512
|
+
cp -r "$PLUGIN_SOURCE_DIR/templates/." "$CLAUDE_DIR/templates/"
|
|
513
|
+
cp -r "$PLUGIN_SOURCE_DIR/project-map/generate.py" "$CLAUDE_DIR/project-map/" 2>/dev/null || true
|
|
514
|
+
cp -r "$PLUGIN_SOURCE_DIR/project-map/grader.py" "$CLAUDE_DIR/project-map/" 2>/dev/null || true
|
|
515
|
+
cp -r "$PLUGIN_SOURCE_DIR/project-map/mine-sessions.py" "$CLAUDE_DIR/project-map/" 2>/dev/null || true
|
|
516
|
+
fi
|
|
517
|
+
|
|
518
|
+
# ── Step 1: Ensure Python ─────────────────────────────────────────────────────
|
|
519
|
+
banner "Step 1: Python"
|
|
520
|
+
|
|
521
|
+
if [ ! -f "$SCRIPTS_DIR/ensure-python.sh" ]; then
|
|
522
|
+
fail "ensure-python.sh not found at $SCRIPTS_DIR/ensure-python.sh"
|
|
523
|
+
exit 2
|
|
524
|
+
fi
|
|
525
|
+
|
|
526
|
+
PYTHON_CMD=$(bash "$SCRIPTS_DIR/ensure-python.sh")
|
|
527
|
+
if [ -z "$PYTHON_CMD" ]; then
|
|
528
|
+
fail "Could not find or install Python >= 3.8"
|
|
529
|
+
exit 2
|
|
530
|
+
fi
|
|
531
|
+
|
|
532
|
+
ok "Python: $("$PYTHON_CMD" --version 2>&1)"
|
|
533
|
+
|
|
534
|
+
# ── Step 2: Detect Stack ──────────────────────────────────────────────────────
|
|
535
|
+
banner "Step 2: Stack Detection"
|
|
536
|
+
|
|
537
|
+
STACK_JSON="$MAP_DIR/stack.json"
|
|
538
|
+
mkdir -p "$MAP_DIR" "$REPORTS_DIR"
|
|
539
|
+
|
|
540
|
+
if [ -f "$SCRIPTS_DIR/detect-stack.sh" ]; then
|
|
541
|
+
bash "$SCRIPTS_DIR/detect-stack.sh" "$PROJECT_ROOT" > "$STACK_JSON" 2>/dev/null || true
|
|
542
|
+
fi
|
|
543
|
+
|
|
544
|
+
if [ -f "$STACK_JSON" ] && "$PYTHON_CMD" -c "import json; json.load(open('$STACK_JSON'))" 2>/dev/null; then
|
|
545
|
+
LANG=$("$PYTHON_CMD" -c "import json; d=json.load(open('$STACK_JSON')); print(d.get('language','unknown'))")
|
|
546
|
+
FRAMEWORK=$("$PYTHON_CMD" -c "import json; d=json.load(open('$STACK_JSON')); print(d.get('framework','unknown'))")
|
|
547
|
+
NAME=$("$PYTHON_CMD" -c "import json; d=json.load(open('$STACK_JSON')); print(d.get('name','project'))")
|
|
548
|
+
SLUG=$("$PYTHON_CMD" -c "import json; d=json.load(open('$STACK_JSON')); print(d.get('slug','project'))")
|
|
549
|
+
ok "Detected: $NAME ($LANG / $FRAMEWORK)"
|
|
550
|
+
else
|
|
551
|
+
warn "Stack detection unavailable — using directory name as defaults"
|
|
552
|
+
NAME=$(basename "$PROJECT_ROOT")
|
|
553
|
+
SLUG=$(echo "$NAME" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g;s/^-//;s/-$//')
|
|
554
|
+
LANG="unknown"
|
|
555
|
+
FRAMEWORK="unknown"
|
|
556
|
+
fi
|
|
557
|
+
|
|
558
|
+
# ── Step 3: Iterative Generation + Grading ────────────────────────────────────
|
|
559
|
+
banner "Step 3: Generate → Grade (up to $MAX_ITERATIONS iterations)"
|
|
560
|
+
|
|
561
|
+
FINAL_SCORE=0
|
|
562
|
+
FINAL_PASSED=false
|
|
563
|
+
|
|
564
|
+
for ITERATION in $(seq 1 $MAX_ITERATIONS); do
|
|
565
|
+
echo
|
|
566
|
+
step "Iteration $ITERATION / $MAX_ITERATIONS"
|
|
567
|
+
echo
|
|
568
|
+
|
|
569
|
+
step "Running generate.py..."
|
|
570
|
+
set +e
|
|
571
|
+
"$PYTHON_CMD" "$MAP_DIR/generate.py" --force \
|
|
572
|
+
--project-root "$PROJECT_ROOT" \
|
|
573
|
+
--stack-json "$STACK_JSON"
|
|
574
|
+
GEN_EXIT=$?
|
|
575
|
+
set -e
|
|
576
|
+
[ $GEN_EXIT -ne 0 ] && warn "generate.py exited with errors (continuing to grade what was produced)"
|
|
577
|
+
|
|
578
|
+
step "Running grader.py..."
|
|
579
|
+
GRADE_ARGS=(--iteration "$ITERATION" --total "$MAX_ITERATIONS" --project-root "$PROJECT_ROOT")
|
|
580
|
+
[ -n "$PREVIOUS_SCORE" ] && GRADE_ARGS+=(--previous-score "$PREVIOUS_SCORE")
|
|
581
|
+
|
|
582
|
+
set +e
|
|
583
|
+
"$PYTHON_CMD" "$MAP_DIR/grader.py" "${GRADE_ARGS[@]}"
|
|
584
|
+
GRADE_EXIT=$?
|
|
585
|
+
set -e
|
|
586
|
+
|
|
587
|
+
SCORE_JSON="$REPORTS_DIR/iteration-$(printf '%02d' "$ITERATION")-score.json"
|
|
588
|
+
if [ -f "$SCORE_JSON" ]; then
|
|
589
|
+
FINAL_SCORE=$("$PYTHON_CMD" -c "import json; print(json.load(open('$SCORE_JSON'))['score'])")
|
|
590
|
+
PASSED=$("$PYTHON_CMD" -c "import json; print(json.load(open('$SCORE_JSON'))['passed'])")
|
|
591
|
+
else
|
|
592
|
+
FINAL_SCORE=0
|
|
593
|
+
PASSED="False"
|
|
594
|
+
fi
|
|
595
|
+
|
|
596
|
+
PREVIOUS_SCORE="$FINAL_SCORE"
|
|
597
|
+
|
|
598
|
+
if [ "$PASSED" = "True" ]; then
|
|
599
|
+
FINAL_PASSED=true
|
|
600
|
+
ok "Score: ${FINAL_SCORE}% — PASSED ✓ (>= ${PASS_THRESHOLD}%)"
|
|
601
|
+
break
|
|
602
|
+
else
|
|
603
|
+
warn "Score: ${FINAL_SCORE}% — below ${PASS_THRESHOLD}% threshold"
|
|
604
|
+
if [ "$ITERATION" -lt "$MAX_ITERATIONS" ]; then
|
|
605
|
+
step "Attempting improvements for iteration $((ITERATION + 1))..."
|
|
606
|
+
_improve_for_next_iteration "$SCORE_JSON" "$MAP_DIR" "$PYTHON_CMD"
|
|
607
|
+
fi
|
|
608
|
+
fi
|
|
609
|
+
done
|
|
610
|
+
|
|
611
|
+
# ── Step 4: Render Templates ──────────────────────────────────────────────────
|
|
612
|
+
banner "Step 4: Render Skills & Rules"
|
|
613
|
+
|
|
614
|
+
RULES_DIR="$CLAUDE_DIR/rules"
|
|
615
|
+
SKILLS_DIR="$CLAUDE_DIR/skills/${SLUG}-developer-skill"
|
|
616
|
+
mkdir -p "$RULES_DIR" "$SKILLS_DIR"
|
|
617
|
+
|
|
618
|
+
_render_vocabulary "$PROJECT_ROOT" "$NAME" "$LANG" "$FRAMEWORK" "$RULES_DIR"
|
|
619
|
+
_render_runbook "$PROJECT_ROOT" "$NAME" "$RULES_DIR"
|
|
620
|
+
_render_skill "$PROJECT_ROOT" "$NAME" "$SLUG" "$LANG" "$FRAMEWORK" "$SKILLS_DIR"
|
|
621
|
+
|
|
622
|
+
# ── Step 5: Git Hooks ─────────────────────────────────────────────────────────
|
|
623
|
+
banner "Step 5: Git Hooks"
|
|
624
|
+
|
|
625
|
+
HOOKS_DIR="$PROJECT_ROOT/.githooks"
|
|
626
|
+
mkdir -p "$HOOKS_DIR"
|
|
627
|
+
_install_git_hooks "$PROJECT_ROOT" "$HOOKS_DIR"
|
|
628
|
+
|
|
629
|
+
# ── Step 6: Update CLAUDE.md ──────────────────────────────────────────────────
|
|
630
|
+
banner "Step 6: Update CLAUDE.md"
|
|
631
|
+
_update_claude_md "$PROJECT_ROOT" "$NAME"
|
|
632
|
+
|
|
633
|
+
# ── Step 7: Final Validation ──────────────────────────────────────────────────
|
|
634
|
+
banner "Step 7: Validation"
|
|
635
|
+
|
|
636
|
+
if [ -f "$SCRIPTS_DIR/validate.sh" ]; then
|
|
637
|
+
bash "$SCRIPTS_DIR/validate.sh" "$PROJECT_ROOT" || true
|
|
638
|
+
else
|
|
639
|
+
warn "validate.sh not found — skipping"
|
|
640
|
+
fi
|
|
641
|
+
|
|
642
|
+
# ── Summary ────���──────────────────────────────────────────────────────────────
|
|
643
|
+
echo
|
|
644
|
+
printf '%b\n' "${CYAN}${BOLD}══════════════════════════════════════════════════${RESET}"
|
|
645
|
+
printf '%b\n' "${BOLD} Installation Complete${RESET}"
|
|
646
|
+
printf '%b\n' "${CYAN}══════════════════════════════════════════════════${RESET}"
|
|
647
|
+
echo
|
|
648
|
+
|
|
649
|
+
if [ "$FINAL_PASSED" = "true" ]; then
|
|
650
|
+
printf '%b\n' " ${GREEN}${BOLD}✓ PASSED${RESET} — Score: ${GREEN}${FINAL_SCORE}%${RESET}"
|
|
651
|
+
else
|
|
652
|
+
printf '%b\n' " ${YELLOW}${BOLD}⚠ COMPLETED WITH WARNINGS${RESET} — Score: ${YELLOW}${FINAL_SCORE}%${RESET}"
|
|
653
|
+
info "Map generated but scored below 90%. Review report for details."
|
|
654
|
+
fi
|
|
655
|
+
|
|
656
|
+
echo
|
|
657
|
+
info "Project Map: .claude/project-map/PROJECT_MAP.md"
|
|
658
|
+
info "Install Report: .claude/project-map/reports/install-report.md"
|
|
659
|
+
info "Developer Skill: /${SLUG}-developer-skill"
|
|
660
|
+
echo
|
|
661
|
+
info "To regenerate:"
|
|
662
|
+
info " $PYTHON_CMD .claude/project-map/generate.py --force"
|
|
663
|
+
info " $PYTHON_CMD .claude/project-map/grader.py"
|
|
664
|
+
echo
|
|
665
|
+
printf '%b\n' "${CYAN}══════════════════════════════════════════════════${RESET}"
|
|
666
|
+
echo
|