claude-dev-kit 2.1.3 → 2.1.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-dev-kit",
3
- "version": "2.1.3",
3
+ "version": "2.1.6",
4
4
  "description": "Transform Claude Code into a fully autonomous development team — orchestrated sub-agents for planning, implementation, testing, and review.",
5
5
  "bin": {
6
6
  "claude-dev-kit": "./bin/claude-dev-kit.js"
@@ -15,7 +15,9 @@
15
15
  ".claude/skills/",
16
16
  ".claude/templates/",
17
17
  "CLAUDE.local.md.example",
18
- "scripts/install.sh"
18
+ "scripts/install.sh",
19
+ "scripts/migrate.sh",
20
+ "scripts/lib/"
19
21
  ],
20
22
  "keywords": [
21
23
  "claude",
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env node
2
+ // scripts/lib/merge-settings.js
3
+ // Merges CDK's settings.json into a user's existing settings.json.
4
+ //
5
+ // Usage: node merge-settings.js <user-settings-path> <cdk-settings-path>
6
+ // Output: merged JSON on stdout
7
+ //
8
+ // Merge rules:
9
+ // permissions.allow — union (add CDK entries not already present)
10
+ // permissions.deny — union (add CDK entries not already present)
11
+ // hooks — per-event: add CDK hook commands not already present
12
+ // (dedup key: command string, trimmed)
13
+ // All other user settings are preserved unchanged.
14
+
15
+ 'use strict';
16
+
17
+ const fs = require('fs');
18
+
19
+ const [, , userPath, cdkPath] = process.argv;
20
+
21
+ if (!userPath || !cdkPath) {
22
+ process.stderr.write('Usage: node merge-settings.js <user-settings-path> <cdk-settings-path>\n');
23
+ process.exit(1);
24
+ }
25
+
26
+ let user, cdk;
27
+ try {
28
+ user = JSON.parse(fs.readFileSync(userPath, 'utf8'));
29
+ } catch (e) {
30
+ process.stderr.write(`Failed to parse user settings at ${userPath}: ${e.message}\n`);
31
+ process.exit(1);
32
+ }
33
+ try {
34
+ cdk = JSON.parse(fs.readFileSync(cdkPath, 'utf8'));
35
+ } catch (e) {
36
+ process.stderr.write(`Failed to parse CDK settings at ${cdkPath}: ${e.message}\n`);
37
+ process.exit(1);
38
+ }
39
+
40
+ // Deep clone user settings as the base
41
+ const result = JSON.parse(JSON.stringify(user));
42
+
43
+ // Strip CDK internal-only comment keys if they leaked in
44
+ delete result._comment;
45
+ delete result._hooks_note;
46
+
47
+ // ── Merge permissions.allow ──────────────────────────────────────────────────
48
+ result.permissions = result.permissions ?? {};
49
+ const userAllow = new Set(result.permissions.allow ?? []);
50
+ for (const entry of (cdk.permissions?.allow ?? [])) {
51
+ userAllow.add(entry);
52
+ }
53
+ result.permissions.allow = [...userAllow];
54
+
55
+ // ── Merge permissions.deny ───────────────────────────────────────────────────
56
+ const userDeny = new Set(result.permissions.deny ?? []);
57
+ for (const entry of (cdk.permissions?.deny ?? [])) {
58
+ userDeny.add(entry);
59
+ }
60
+ result.permissions.deny = [...userDeny];
61
+
62
+ // ── Merge hooks ──────────────────────────────────────────────────────────────
63
+ result.hooks = result.hooks ?? {};
64
+
65
+ for (const [event, cdkGroups] of Object.entries(cdk.hooks ?? {})) {
66
+ result.hooks[event] = result.hooks[event] ?? [];
67
+
68
+ // Collect all command strings already present for this event
69
+ const existingCommands = new Set();
70
+ for (const group of result.hooks[event]) {
71
+ for (const h of (group.hooks ?? [])) {
72
+ if (h.command) existingCommands.add(h.command.trim());
73
+ }
74
+ }
75
+
76
+ // For each CDK hook group, keep only commands not already present
77
+ for (const cdkGroup of cdkGroups) {
78
+ const newHooks = (cdkGroup.hooks ?? []).filter(
79
+ (h) => h.command && !existingCommands.has(h.command.trim())
80
+ );
81
+ if (newHooks.length > 0) {
82
+ result.hooks[event].push({ ...cdkGroup, hooks: newHooks });
83
+ }
84
+ }
85
+ }
86
+
87
+ process.stdout.write(JSON.stringify(result, null, 2) + '\n');
@@ -0,0 +1,444 @@
1
+ #!/usr/bin/env bash
2
+ # scripts/migrate.sh — Claude Dev Kit Migration Tool
3
+ #
4
+ # Intelligently merges CDK into an existing .claude/ setup without data loss.
5
+ # Detects NEW / UNCHANGED / MODIFIED files, asks about conflicts, and
6
+ # performs smart merges of settings.json and CLAUDE.md.
7
+ #
8
+ # Usage (called by install.sh):
9
+ # bash scripts/migrate.sh <kit-root> <target-dir>
10
+ #
11
+ # Safe to run standalone. Exit codes: 0 = success, 1 = aborted/error.
12
+
13
+ set -euo pipefail
14
+
15
+ # ─── Args ─────────────────────────────────────────────────────────────────────
16
+ KIT_ROOT="${1:-}"
17
+ TARGET="${2:-}"
18
+
19
+ if [[ -z "$KIT_ROOT" || -z "$TARGET" ]]; then
20
+ echo "Usage: bash scripts/migrate.sh <kit-root> <target-dir>" >&2
21
+ exit 1
22
+ fi
23
+
24
+ CDK_CLAUDE="$KIT_ROOT/.claude"
25
+ TGT_CLAUDE="$TARGET/.claude"
26
+ MANIFEST="$TGT_CLAUDE/.cdk-manifest"
27
+
28
+ # ─── Colors ───────────────────────────────────────────────────────────────────
29
+ BOLD='\033[1m'
30
+ DIM='\033[2m'
31
+ GREEN='\033[0;32m'
32
+ YELLOW='\033[1;33m'
33
+ CYAN='\033[0;36m'
34
+ RED='\033[0;31m'
35
+ BLUE='\033[0;34m'
36
+ NC='\033[0m'
37
+
38
+ info() { echo -e "${CYAN} →${NC} $*"; }
39
+ success() { echo -e "${GREEN} ✓${NC} $*"; }
40
+ warn() { echo -e "${YELLOW} ⚠${NC} $*"; }
41
+ error() { echo -e "${RED} ✗${NC} $*" >&2; }
42
+ header() { echo -e "\n${BOLD}$*${NC}"; }
43
+ dim() { echo -e "${DIM}$*${NC}"; }
44
+
45
+ CI_MODE="${CI:-false}"
46
+
47
+ # ─── Section 1: Load existing manifest ────────────────────────────────────────
48
+ IS_FIRST_INSTALL=false
49
+
50
+ mkdir -p "$TGT_CLAUDE"
51
+
52
+ if [[ -f "$MANIFEST" ]]; then
53
+ while IFS= read -r line; do
54
+ [[ "$line" =~ ^# ]] && continue
55
+ [[ -z "$line" ]] && continue
56
+ done < "$MANIFEST"
57
+ else
58
+ IS_FIRST_INSTALL=true
59
+ fi
60
+
61
+ # ─── Section 2: Enumerate CDK files ───────────────────────────────────────────
62
+ declare -a cdk_files=()
63
+
64
+ while IFS= read -r -d '' f; do
65
+ rel="${f#"$CDK_CLAUDE"/}"
66
+ # Skip files that have their own special merge logic or should never be copied
67
+ [[ "$rel" == "settings.json" ]] && continue
68
+ [[ "$rel" == "settings.json.example" ]] && continue
69
+ [[ "$rel" == ".cdk-manifest" ]] && continue
70
+ [[ "$rel" == *"node_modules"* ]] && continue
71
+ [[ "$rel" == *.jsonl ]] && continue
72
+ [[ "$rel" == "learning/"* ]] && continue
73
+ cdk_files+=("$rel")
74
+ done < <(find "$CDK_CLAUDE" -type f -print0 2>/dev/null | sort -z)
75
+
76
+ # ─── Section 3: Categorize files ──────────────────────────────────────────────
77
+ declare -a cat_new=()
78
+ declare -a cat_unchanged=()
79
+ declare -a cat_modified=()
80
+
81
+ for rel in "${cdk_files[@]}"; do
82
+ src="$CDK_CLAUDE/$rel"
83
+ dst="$TGT_CLAUDE/$rel"
84
+
85
+ if [[ ! -f "$dst" ]]; then
86
+ cat_new+=("$rel")
87
+ elif cmp -s "$src" "$dst"; then
88
+ cat_unchanged+=("$rel")
89
+ else
90
+ # File exists in both and content differs — it was modified
91
+ cat_modified+=("$rel")
92
+ fi
93
+ done
94
+
95
+ # Count user-only files (in target .claude but not in CDK source)
96
+ user_only_count=0
97
+ if [[ -d "$TGT_CLAUDE" ]]; then
98
+ while IFS= read -r -d '' f; do
99
+ rel="${f#"$TGT_CLAUDE"/}"
100
+ [[ "$rel" == ".cdk-manifest" ]] && continue
101
+ # Check if this file is in the CDK source
102
+ if [[ ! -f "$CDK_CLAUDE/$rel" ]]; then
103
+ (( user_only_count++ )) || true
104
+ fi
105
+ done < <(find "$TGT_CLAUDE" -type f -print0 2>/dev/null)
106
+ fi
107
+
108
+ # ─── Section 4: Print migration report ────────────────────────────────────────
109
+ echo ""
110
+ echo -e "${BOLD}╔═══════════════════════════════════════════╗${NC}"
111
+ echo -e "${BOLD}║ Claude Dev Kit — Migration Tool ║${NC}"
112
+ echo -e "${BOLD}╚═══════════════════════════════════════════╝${NC}"
113
+ echo ""
114
+ echo -e " ${DIM}Source: $KIT_ROOT${NC}"
115
+ echo -e " ${DIM}Target: $TARGET${NC}"
116
+ echo ""
117
+
118
+ if [[ "$IS_FIRST_INSTALL" == "true" ]] && [[ ! -d "$TARGET/.claude" || -z "$(ls -A "$TGT_CLAUDE" 2>/dev/null)" ]]; then
119
+ info "No existing .claude/ found — performing fresh install"
120
+ else
121
+ header "Migration Report"
122
+ echo ""
123
+
124
+ echo -e " ${GREEN}${BOLD}NEW${NC} ${#cat_new[@]} file(s) — will be added"
125
+ if [[ ${#cat_new[@]} -gt 0 && ${#cat_new[@]} -le 10 ]]; then
126
+ for f in "${cat_new[@]}"; do echo -e " ${DIM}$f${NC}"; done
127
+ elif [[ ${#cat_new[@]} -gt 10 ]]; then
128
+ for f in "${cat_new[@]:0:5}"; do echo -e " ${DIM}$f${NC}"; done
129
+ echo -e " ${DIM}... and $((${#cat_new[@]} - 5)) more${NC}"
130
+ fi
131
+ echo ""
132
+
133
+ echo -e " ${CYAN}${BOLD}UNCHANGED${NC} ${#cat_unchanged[@]} file(s) — CDK version matches yours, will refresh"
134
+ echo ""
135
+
136
+ if [[ ${#cat_modified[@]} -gt 0 ]]; then
137
+ echo -e " ${YELLOW}${BOLD}MODIFIED${NC} ${#cat_modified[@]} file(s) — differ from CDK, ${BOLD}requires your input${NC}"
138
+ for f in "${cat_modified[@]}"; do echo -e " ${YELLOW}$f${NC}"; done
139
+ echo ""
140
+ fi
141
+
142
+ if [[ $user_only_count -gt 0 ]]; then
143
+ echo -e " ${BLUE}${BOLD}YOURS${NC} $user_only_count file(s) — only in your .claude/, CDK will never touch"
144
+ echo ""
145
+ fi
146
+
147
+ echo -e " ${BOLD}SPECIAL MERGES${NC}"
148
+ if [[ -f "$TGT_CLAUDE/settings.json" ]]; then
149
+ echo -e " ${DIM}settings.json${NC} — will merge hooks + permissions (yours preserved)"
150
+ else
151
+ echo -e " ${DIM}settings.json${NC} — will be created from CDK template"
152
+ fi
153
+ if [[ -f "$TARGET/CLAUDE.md" ]]; then
154
+ if grep -qF "CDK:GENERATED:START" "$TARGET/CLAUDE.md" 2>/dev/null; then
155
+ echo -e " ${DIM}CLAUDE.md${NC} — will update CDK block (your custom content preserved)"
156
+ else
157
+ echo -e " ${DIM}CLAUDE.md${NC} — will append CDK block (your existing content preserved)"
158
+ fi
159
+ else
160
+ echo -e " ${DIM}CLAUDE.md${NC} — will be created from template"
161
+ fi
162
+ echo ""
163
+ fi
164
+
165
+ # ─── Section 5: Confirm before proceeding ─────────────────────────────────────
166
+ if [[ "$CI_MODE" != "true" && ${#cat_modified[@]} -eq 0 ]]; then
167
+ echo -ne " Proceed with migration? ${DIM}[Y/n]${NC}: "
168
+ read -r _confirm </dev/tty
169
+ if [[ "$_confirm" =~ ^[Nn]$ ]]; then
170
+ echo " Aborted."
171
+ exit 1
172
+ fi
173
+ fi
174
+
175
+ # ─── Section 6: Resolve MODIFIED files interactively ──────────────────────────
176
+ declare -a resolution_files=()
177
+ declare -a resolution_actions=()
178
+
179
+ set_resolution() {
180
+ local file="$1"
181
+ local action="$2"
182
+ local i
183
+ for (( i=0; i<${#resolution_files[@]}; i++ )); do
184
+ if [[ "${resolution_files[$i]}" == "$file" ]]; then
185
+ resolution_actions[$i]="$action"
186
+ return
187
+ fi
188
+ done
189
+ resolution_files+=("$file")
190
+ resolution_actions+=("$action")
191
+ }
192
+
193
+ get_resolution() {
194
+ local file="$1"
195
+ local i
196
+ for (( i=0; i<${#resolution_files[@]}; i++ )); do
197
+ if [[ "${resolution_files[$i]}" == "$file" ]]; then
198
+ printf '%s\n' "${resolution_actions[$i]}"
199
+ return
200
+ fi
201
+ done
202
+ printf 'keep\n'
203
+ }
204
+
205
+ if [[ ${#cat_modified[@]} -gt 0 ]]; then
206
+ if [[ "$CI_MODE" == "true" ]]; then
207
+ warn "CI mode — all ${#cat_modified[@]} modified file(s) will be preserved (keeping your versions)"
208
+ warn "To update them: run scripts/migrate.sh manually and choose [u] for each"
209
+ for rel in "${cat_modified[@]}"; do
210
+ set_resolution "$rel" "keep"
211
+ done
212
+ else
213
+ header "Resolving modified files"
214
+ echo -e " ${DIM}For each file that differs from CDK, choose what to do.${NC}"
215
+ echo ""
216
+
217
+ for rel in "${cat_modified[@]}"; do
218
+ src="$CDK_CLAUDE/$rel"
219
+ dst="$TGT_CLAUDE/$rel"
220
+
221
+ echo -e " ${YELLOW}${BOLD}MODIFIED:${NC} $rel"
222
+
223
+ while true; do
224
+ echo -ne " [k]eep mine [u]se CDK version [d]iff [s]kip: "
225
+ read -r -n1 choice </dev/tty
226
+ echo ""
227
+
228
+ case "$choice" in
229
+ k|K)
230
+ set_resolution "$rel" "keep"
231
+ info "Keeping your version"
232
+ break
233
+ ;;
234
+ u|U)
235
+ set_resolution "$rel" "cdk"
236
+ info "Will use CDK version"
237
+ break
238
+ ;;
239
+ d|D)
240
+ echo ""
241
+ if command -v diff &>/dev/null; then
242
+ diff --color=always -u "$dst" "$src" 2>/dev/null | head -80 || true
243
+ else
244
+ warn "diff not available — cannot show comparison"
245
+ fi
246
+ echo ""
247
+ ;;
248
+ s|S)
249
+ resolutions["$rel"]="keep"
250
+ info "Skipped (keeping yours)"
251
+ break
252
+ ;;
253
+ *)
254
+ echo -ne " Invalid choice. "
255
+ ;;
256
+ esac
257
+ done
258
+ echo ""
259
+ done
260
+ fi
261
+ fi
262
+
263
+ # ─── Section 7: Apply regular file changes ────────────────────────────────────
264
+ header "Applying changes"
265
+ echo ""
266
+
267
+ new_count=0
268
+ unchanged_count=0
269
+ modified_applied=0
270
+ modified_kept=0
271
+
272
+ # Apply NEW files
273
+ for rel in "${cat_new[@]}"; do
274
+ src="$CDK_CLAUDE/$rel"
275
+ dst="$TGT_CLAUDE/$rel"
276
+ mkdir -p "$(dirname "$dst")"
277
+ cp "$src" "$dst"
278
+ (( new_count++ )) || true
279
+ done
280
+
281
+ # Apply UNCHANGED files (refresh to latest CDK version — they're identical so this is safe)
282
+ for rel in "${cat_unchanged[@]}"; do
283
+ src="$CDK_CLAUDE/$rel"
284
+ dst="$TGT_CLAUDE/$rel"
285
+ mkdir -p "$(dirname "$dst")"
286
+ cp "$src" "$dst"
287
+ (( unchanged_count++ )) || true
288
+ done
289
+
290
+ # Apply MODIFIED based on user decisions
291
+ for rel in "${cat_modified[@]}"; do
292
+ case "$(get_resolution "$rel")" in
293
+ cdk)
294
+ mkdir -p "$(dirname "$TGT_CLAUDE/$rel")"
295
+ cp "$CDK_CLAUDE/$rel" "$TGT_CLAUDE/$rel"
296
+ (( modified_applied++ )) || true
297
+ ;;
298
+ keep)
299
+ (( modified_kept++ )) || true
300
+ ;;
301
+ esac
302
+ done
303
+
304
+ [[ $new_count -gt 0 ]] && success "$new_count new file(s) added"
305
+ [[ $unchanged_count -gt 0 ]] && success "$unchanged_count unchanged file(s) refreshed"
306
+ [[ $modified_applied -gt 0 ]] && success "$modified_applied modified file(s) updated to CDK version"
307
+ [[ $modified_kept -gt 0 ]] && info "$modified_kept modified file(s) kept as your version"
308
+
309
+ # ─── Section 8: Merge settings.json ───────────────────────────────────────────
310
+ merge_settings() {
311
+ local tgt_settings="$TGT_CLAUDE/settings.json"
312
+ local cdk_settings="$CDK_CLAUDE/settings.json"
313
+ local merge_script="$KIT_ROOT/scripts/lib/merge-settings.js"
314
+
315
+ if [[ ! -f "$cdk_settings" ]]; then
316
+ warn "settings.json: CDK source not found — skipping"
317
+ return
318
+ fi
319
+
320
+ if [[ ! -f "$tgt_settings" ]]; then
321
+ # No existing settings — install CDK's (strip internal comment keys)
322
+ node -e "
323
+ const s = JSON.parse(require('fs').readFileSync('$cdk_settings', 'utf8'));
324
+ delete s._comment; delete s._hooks_note;
325
+ process.stdout.write(JSON.stringify(s, null, 2) + '\n');
326
+ " > "$tgt_settings"
327
+ success "settings.json: created from CDK template"
328
+ return
329
+ fi
330
+
331
+ local tmp
332
+ tmp=$(mktemp /tmp/cdk-settings-XXXXXX.json)
333
+ # shellcheck disable=SC2064
334
+ trap "rm -f '$tmp'" RETURN
335
+
336
+ if node "$merge_script" "$tgt_settings" "$cdk_settings" > "$tmp" 2>&1; then
337
+ # Validate output is parseable JSON before overwriting
338
+ if node -e "JSON.parse(require('fs').readFileSync('$tmp', 'utf8'))" 2>/dev/null; then
339
+ cp "$tmp" "$tgt_settings"
340
+ success "settings.json: merged (permissions + hooks updated)"
341
+ else
342
+ warn "settings.json: merge produced invalid JSON — your original preserved"
343
+ warn "Manual merge reference: $CDK_CLAUDE/settings.json.example"
344
+ fi
345
+ else
346
+ warn "settings.json: merge failed — your original preserved"
347
+ warn "Manual merge reference: $CDK_CLAUDE/settings.json.example"
348
+ fi
349
+ }
350
+
351
+ merge_settings
352
+
353
+ # ─── Section 9: Merge CLAUDE.md ───────────────────────────────────────────────
354
+ merge_claude_md() {
355
+ local tgt_md="$TARGET/CLAUDE.md"
356
+ local cdk_template="$CDK_CLAUDE/templates/claude-md-template.md"
357
+ local START_MARKER="CDK:GENERATED:START"
358
+ local END_MARKER="CDK:GENERATED:END"
359
+
360
+ if [[ ! -f "$cdk_template" ]]; then
361
+ warn "CLAUDE.md: template not found at $cdk_template — skipping"
362
+ return
363
+ fi
364
+
365
+ if [[ ! -f "$tgt_md" ]]; then
366
+ cp "$cdk_template" "$tgt_md"
367
+ success "CLAUDE.md: created from template"
368
+ return
369
+ fi
370
+
371
+ if grep -qF "$START_MARKER" "$tgt_md" 2>/dev/null; then
372
+ # Has CDK markers — replace only the block between markers (inclusive)
373
+ local tmp
374
+ tmp=$(mktemp /tmp/cdk-claude-md-XXXXXX.md)
375
+ # shellcheck disable=SC2064
376
+ trap "rm -f '$tmp'" RETURN
377
+
378
+ # Extract CDK block from template
379
+ local cdk_block
380
+ cdk_block=$(awk "/<!-- ${START_MARKER}/,/<!-- ${END_MARKER} -->/" "$cdk_template")
381
+
382
+ # Build merged file: content before START + cdk block + content after END
383
+ awk -v block="$cdk_block" \
384
+ -v start="$START_MARKER" \
385
+ -v end="$END_MARKER" \
386
+ 'BEGIN { in_block=0; printed=0 }
387
+ index($0, start) > 0 {
388
+ if (!printed) { print block; printed=1 }
389
+ in_block=1; next
390
+ }
391
+ in_block && index($0, end) > 0 { in_block=0; next }
392
+ !in_block { print }
393
+ ' "$tgt_md" > "$tmp"
394
+
395
+ cp "$tmp" "$tgt_md"
396
+ success "CLAUDE.md: CDK block updated (your custom content preserved)"
397
+ else
398
+ # No CDK markers — append the CDK block at the end
399
+ local cdk_block
400
+ cdk_block=$(awk "/<!-- ${START_MARKER}/,/<!-- ${END_MARKER} -->/" "$cdk_template")
401
+ {
402
+ echo ""
403
+ echo "---"
404
+ echo ""
405
+ printf '%s\n' "$cdk_block"
406
+ } >> "$tgt_md"
407
+ success "CLAUDE.md: CDK block appended (your existing content preserved)"
408
+ info "Tip: you can move the appended block anywhere in the file — the markers let future migrations update it in place"
409
+ fi
410
+ }
411
+
412
+ merge_claude_md
413
+
414
+ # ─── Section 10: Write manifest ───────────────────────────────────────────────
415
+ write_manifest() {
416
+ {
417
+ echo "# CDK Manifest — generated by scripts/migrate.sh"
418
+ echo "# Lists all files installed by claude-dev-kit."
419
+ echo "# Do not edit manually. Used to distinguish CDK-owned from user-created files."
420
+ echo "#"
421
+ for rel in "${cdk_files[@]}"; do
422
+ echo "$rel"
423
+ done
424
+ } > "$MANIFEST"
425
+ success "Manifest written (.claude/.cdk-manifest — tracks CDK-owned files for future migrations)"
426
+ }
427
+
428
+ write_manifest
429
+
430
+ # ─── Done ─────────────────────────────────────────────────────────────────────
431
+ echo ""
432
+ success "Migration complete"
433
+ echo ""
434
+ echo -e " ${DIM}Next steps:${NC}"
435
+ if [[ ! -f "$TARGET/CLAUDE.md" ]] || ! grep -qF "CDK:GENERATED" "$TARGET/CLAUDE.md" 2>/dev/null; then
436
+ echo -e " ${DIM} 1. Run \`/init\` inside Claude Code to configure CLAUDE.md for your stack${NC}"
437
+ echo -e " ${DIM} 2. Copy CLAUDE.local.md.example → CLAUDE.local.md for personal preferences${NC}"
438
+ echo -e " ${DIM} 3. Run \`/primer\` to verify Claude understands the project${NC}"
439
+ else
440
+ echo -e " ${DIM} 1. Copy CLAUDE.local.md.example → CLAUDE.local.md for personal preferences${NC}"
441
+ echo -e " ${DIM} 2. Review any modified files you chose to keep — ensure they're still compatible${NC}"
442
+ echo -e " ${DIM} 3. Run \`/primer\` to verify Claude understands the project${NC}"
443
+ fi
444
+ echo ""