codexkit 1.0.3 → 1.0.5

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.
@@ -8,6 +8,7 @@ REPO_DIR="$(dirname "$SCRIPT_DIR")"
8
8
  PROJECT_DIR=""
9
9
  FORCE=false
10
10
  UPGRADE=false
11
+ VERBOSE=false
11
12
  TEMPLATE_NAME=""
12
13
  AUTO_APPLY_PATCHES=false
13
14
  FULL_LOCAL=false
@@ -15,6 +16,7 @@ for arg in "$@"; do
15
16
  case "$arg" in
16
17
  --force) FORCE=true ;;
17
18
  --upgrade) UPGRADE=true ;;
19
+ --verbose|-v) VERBOSE=true ;;
18
20
  --auto-apply-patches) AUTO_APPLY_PATCHES=true ;;
19
21
  --full-local) FULL_LOCAL=true ;;
20
22
  --template=*) TEMPLATE_NAME="${arg#--template=}" ;;
@@ -44,16 +46,23 @@ GLOBAL_CODEX_DIR="${HOME}/.codex"
44
46
  MANIFEST="$REPO_DIR/.codex/.template-manifest.json"
45
47
  [ -f "$MANIFEST" ] || MANIFEST="$REPO_DIR/.template-manifest.json"
46
48
 
47
- should_copy() {
49
+ # Counters for install summary
50
+ _count_created=0
51
+ _count_upgraded=0
52
+ _count_kept=0
53
+ _count_skipped=0
54
+
55
+ # Returns: 0 = new file, 1 = skip (customized/exists), 2 = safe to upgrade (unchanged from template)
56
+ check_copy_action() {
48
57
  local target="$1"
49
58
  local source_path="$2"
50
59
  local manifest_hash installed_hash
51
60
 
52
- # New file → always copy
61
+ # New file
53
62
  [ ! -f "$target" ] && return 0
54
63
 
55
- # Force → always copy
56
- $FORCE && return 0
64
+ # Force → treat as upgrade
65
+ $FORCE && return 2
57
66
 
58
67
  # Upgrade mode → check if customized
59
68
  if $UPGRADE && [ -f "$MANIFEST" ]; then
@@ -61,8 +70,8 @@ should_copy() {
61
70
  installed_hash=$(shasum -a 256 "$target" 2>/dev/null | cut -d' ' -f1)
62
71
 
63
72
  if [ -n "$manifest_hash" ] && [ "$installed_hash" = "$manifest_hash" ]; then
64
- # File matches original template → safe to update
65
- return 0
73
+ # File matches original template → safe to upgrade
74
+ return 2
66
75
  fi
67
76
 
68
77
  # File was customized (or not tracked) → skip
@@ -73,6 +82,149 @@ should_copy() {
73
82
  return 1
74
83
  }
75
84
 
85
+ # Backward-compatible wrapper (returns 0 for both new and upgrade)
86
+ should_copy() {
87
+ local rc=0
88
+ check_copy_action "$1" "$2" || rc=$?
89
+ [ "$rc" -ne 1 ]
90
+ }
91
+
92
+ # Log and count a file operation. Usage: log_file_op <display_path> <action>
93
+ # action: created | upgraded | kept | skipped
94
+ log_file_op() {
95
+ local display_path="$1"
96
+ local action="$2"
97
+ case "$action" in
98
+ created)
99
+ if $VERBOSE; then echo " CREATED $display_path"; fi
100
+ _count_created=$((_count_created + 1))
101
+ ;;
102
+ upgraded)
103
+ if $VERBOSE; then echo " UPGRADED $display_path"; fi
104
+ _count_upgraded=$((_count_upgraded + 1))
105
+ ;;
106
+ kept)
107
+ if $VERBOSE; then echo " KEPT $display_path (customized)"; fi
108
+ _count_kept=$((_count_kept + 1))
109
+ ;;
110
+ skipped)
111
+ if $VERBOSE; then echo " SKIP $display_path (exists)"; fi
112
+ _count_skipped=$((_count_skipped + 1))
113
+ ;;
114
+ esac
115
+ }
116
+
117
+ # Determine action label for a file copy operation
118
+ copy_and_log() {
119
+ local target="$1"
120
+ local source="$2"
121
+ local source_path="$3"
122
+ local display_path="$4"
123
+ local rc=0
124
+
125
+ check_copy_action "$target" "$source_path" || rc=$?
126
+
127
+ if [ "$rc" -eq 0 ]; then
128
+ cp "$source" "$target"
129
+ log_file_op "$display_path" "created"
130
+ elif [ "$rc" -eq 2 ]; then
131
+ cp "$source" "$target"
132
+ log_file_op "$display_path" "upgraded"
133
+ elif $UPGRADE; then
134
+ log_file_op "$display_path" "kept"
135
+ else
136
+ log_file_op "$display_path" "skipped"
137
+ fi
138
+ }
139
+
140
+ print_version_comparison() {
141
+ local installed_version latest_version
142
+ latest_version=""
143
+ installed_version=""
144
+
145
+ # Latest version from codexkit source
146
+ if [ -f "$REPO_DIR/.codex/.version" ]; then
147
+ latest_version=$(cat "$REPO_DIR/.codex/.version" 2>/dev/null | tr -d '[:space:]')
148
+ fi
149
+
150
+ # Installed version from target project
151
+ if [ -f "$PROJECT_DIR/.codex/.version" ]; then
152
+ installed_version=$(cat "$PROJECT_DIR/.codex/.version" 2>/dev/null | tr -d '[:space:]')
153
+ fi
154
+
155
+ if [ -n "$installed_version" ] && [ -n "$latest_version" ]; then
156
+ if [ "$installed_version" = "$latest_version" ]; then
157
+ echo " Version: $latest_version (up to date)"
158
+ else
159
+ echo " Version: $installed_version → $latest_version"
160
+ fi
161
+ elif [ -n "$latest_version" ]; then
162
+ echo " Version: $latest_version (fresh install)"
163
+ fi
164
+ }
165
+
166
+ detect_orphans() {
167
+ local project_codex="$PROJECT_DIR/.codex"
168
+ local orphan_count=0
169
+ local rel_path=""
170
+ local manifest_file=""
171
+
172
+ [ -f "$MANIFEST" ] || return 0
173
+ [ -d "$project_codex" ] || return 0
174
+
175
+ # Write manifest keys to a temp file for O(1) lookup via grep -Fxf
176
+ manifest_file=$(mktemp)
177
+ python3 -c '
178
+ import json, sys
179
+ d = json.load(open(sys.argv[1]))
180
+ for k in sorted(d.get("files", {}).keys()):
181
+ print(k)
182
+ ' "$MANIFEST" > "$manifest_file" 2>/dev/null || true
183
+
184
+ if [ ! -s "$manifest_file" ]; then
185
+ rm -f "$manifest_file"
186
+ return 0
187
+ fi
188
+
189
+ # Scan project .codex for files not in manifest
190
+ # Exclude user-owned directories: context/, memory/project/, plans/
191
+ while IFS= read -r file; do
192
+ rel_path="${file#$PROJECT_DIR/}"
193
+ # Skip user-owned content
194
+ case "$rel_path" in
195
+ .codex/context/*|.codex/memory/project/*|.codex/memory/research/*|.codex/plans/*) continue ;;
196
+ .codex/.env|.codex/.env.*) continue ;;
197
+ esac
198
+ if ! grep -qxF "$rel_path" "$manifest_file"; then
199
+ orphan_count=$((orphan_count + 1))
200
+ if $VERBOSE; then echo " ORPHAN $rel_path"; fi
201
+ fi
202
+ done < <(find "$project_codex" -type f ! -name '.gitkeep' 2>/dev/null | sort)
203
+
204
+ rm -f "$manifest_file"
205
+
206
+ if [ "$orphan_count" -gt 0 ]; then
207
+ echo " ○ $orphan_count orphan file(s) not in template"
208
+ fi
209
+ }
210
+
211
+ print_summary() {
212
+ echo ""
213
+ local parts=()
214
+ [ "$_count_created" -gt 0 ] && parts+=("◆ Created $_count_created new files")
215
+ [ "$_count_upgraded" -gt 0 ] && parts+=("◆ Upgraded $_count_upgraded files")
216
+ [ "$_count_kept" -gt 0 ] && parts+=("● Preserved $_count_kept customized files")
217
+ [ "$_count_skipped" -gt 0 ] && parts+=("○ Skipped $_count_skipped existing files")
218
+
219
+ for part in "${parts[@]+"${parts[@]}"}"; do
220
+ echo " $part"
221
+ done
222
+
223
+ if $UPGRADE; then
224
+ detect_orphans
225
+ fi
226
+ }
227
+
76
228
  root_shared_inventory_available() {
77
229
  [ -f "$GLOBAL_CODEX_DIR/config.toml" ] &&
78
230
  [ -d "$GLOBAL_CODEX_DIR/agents" ] &&
@@ -95,19 +247,19 @@ bootstrap_user_prompt_discovery() {
95
247
 
96
248
  if should_copy "$target" "$source_path"; then
97
249
  cp "$prompt_file" "$target"
98
- echo " BOOTSTRAPPED ~/.codex/prompts/$(basename "$prompt_file")"
250
+ if $VERBOSE; then echo " BOOTSTRAPPED ~/.codex/prompts/$(basename "$prompt_file")"; fi
99
251
  copied=$((copied + 1))
100
252
  elif $UPGRADE; then
101
- echo " KEPT ~/.codex/prompts/$(basename "$prompt_file") (customized)"
253
+ if $VERBOSE; then echo " KEPT ~/.codex/prompts/$(basename "$prompt_file") (customized)"; fi
102
254
  else
103
- echo " KEPT ~/.codex/prompts/$(basename "$prompt_file")"
255
+ if $VERBOSE; then echo " KEPT ~/.codex/prompts/$(basename "$prompt_file")"; fi
104
256
  fi
105
257
  done
106
258
 
107
259
  if [ "$copied" -gt 0 ]; then
108
- echo " Prompt discovery bootstrap: synced $copied prompt files into ~/.codex/prompts"
260
+ if $VERBOSE; then echo " Prompt discovery bootstrap: synced $copied prompt files into ~/.codex/prompts"; fi
109
261
  else
110
- echo " Prompt discovery bootstrap: ~/.codex/prompts already ready"
262
+ if $VERBOSE; then echo " Prompt discovery bootstrap: ~/.codex/prompts already ready"; fi
111
263
  fi
112
264
  }
113
265
 
@@ -348,23 +500,32 @@ install_seed_file() {
348
500
  local target="$1"
349
501
  local source_path="$2"
350
502
  local seed_key="$3"
503
+ local display_path="${target#$PROJECT_DIR/}"
504
+ local rc=0
505
+
506
+ check_copy_action "$target" "$source_path" || rc=$?
351
507
 
352
- if should_copy "$target" "$source_path"; then
508
+ if [ "$rc" -eq 0 ]; then
353
509
  mkdir -p "$(dirname "$target")"
354
510
  write_seed_file "$target" "$seed_key"
355
- echo " CREATED ${target#$PROJECT_DIR/}"
511
+ log_file_op "$display_path" "created"
512
+ elif [ "$rc" -eq 2 ]; then
513
+ mkdir -p "$(dirname "$target")"
514
+ write_seed_file "$target" "$seed_key"
515
+ log_file_op "$display_path" "upgraded"
356
516
  elif $UPGRADE; then
357
- echo " KEPT ${target#$PROJECT_DIR/} (customized)"
517
+ log_file_op "$display_path" "kept"
358
518
  else
359
- echo " SKIP ${target#$PROJECT_DIR/} (exists)"
519
+ log_file_op "$display_path" "skipped"
360
520
  fi
361
521
  }
362
522
 
363
523
  echo "=== Codexkit Project Install ==="
364
524
  echo " Target: $PROJECT_DIR"
525
+ print_version_comparison
365
526
 
366
527
  if $UPGRADE && [ ! -f "$MANIFEST" ] && ! $FORCE; then
367
- echo "⚠ Upgrade checks unavailable (missing .template-manifest.json); existing files will be kept"
528
+ echo " ⚠ Upgrade checks unavailable (missing .template-manifest.json); existing files will be kept"
368
529
  fi
369
530
 
370
531
  # Verify git repo
@@ -380,30 +541,30 @@ if root_shared_inventory_available; then
380
541
  fi
381
542
 
382
543
  if $UPGRADE && $ROOT_SHARED_AVAILABLE && ! $FULL_LOCAL; then
383
- echo " Shared inventory detected at $GLOBAL_CODEX_DIR"
384
- echo " Upgrading shared inventory first..."
544
+ if $VERBOSE; then echo " Shared inventory detected at $GLOBAL_CODEX_DIR"; fi
545
+ if $VERBOSE; then echo " Upgrading shared inventory first..."; fi
385
546
  HOME="$HOME" "$REPO_DIR/install/install-global.sh" --upgrade
386
547
  fi
387
548
 
388
549
  USE_SHARED_ROOT=false
389
550
  if $ROOT_SHARED_AVAILABLE && ! $FULL_LOCAL; then
390
551
  USE_SHARED_ROOT=true
391
- echo " Shared inventory mode: reusing $GLOBAL_CODEX_DIR for profiles, agents, prompts, and skills"
552
+ if $VERBOSE; then echo " Shared inventory mode: reusing $GLOBAL_CODEX_DIR for profiles, agents, prompts, and skills"; fi
392
553
  elif ! $FULL_LOCAL; then
393
- echo " Shared inventory mode unavailable: ~/.codex shared inventory not found"
394
- echo " Falling back to full local install for this project"
554
+ if $VERBOSE; then echo " Shared inventory mode unavailable: ~/.codex shared inventory not found"; fi
555
+ if $VERBOSE; then echo " Falling back to full local install for this project"; fi
395
556
  fi
396
557
 
397
558
  if $USE_SHARED_ROOT; then
398
559
  for legacy_dir in "$PROJECT_DIR/.codex/agents" "$PROJECT_DIR/.codex/prompts" "$PROJECT_DIR/.codex/skills" "$PROJECT_DIR/.agents"; do
399
560
  if [ -e "$legacy_dir" ]; then
400
- echo " KEPT $legacy_dir (legacy local shared inventory)"
561
+ if $VERBOSE; then echo " KEPT $legacy_dir (legacy local shared inventory)"; fi
401
562
  fi
402
563
  done
403
564
  fi
404
565
 
405
566
  # Create directory structure
406
- mkdir -p "$PROJECT_DIR/.codex"/{context,hooks,scripts,mcp,memory,plans}
567
+ mkdir -p "$PROJECT_DIR/.codex"/{context,context/archive,hooks,scripts,mcp,memory,plans}
407
568
  if ! $USE_SHARED_ROOT; then
408
569
  mkdir -p "$PROJECT_DIR/.codex"/{agents,prompts,skills}
409
570
  fi
@@ -418,14 +579,9 @@ if ! $USE_SHARED_ROOT; then
418
579
  fi
419
580
 
420
581
  if $USE_SHARED_ROOT && [ -f "$config_target" ] && ! $FORCE; then
421
- echo " KEPT .codex/config.toml (existing project config)"
422
- elif should_copy "$config_target" "$config_source_path"; then
423
- cp "$config_source" "$config_target"
424
- echo " CREATED .codex/config.toml"
425
- elif $UPGRADE; then
426
- echo " KEPT .codex/config.toml (customized)"
582
+ log_file_op ".codex/config.toml" "kept"
427
583
  else
428
- echo " SKIP .codex/config.toml (exists)"
584
+ copy_and_log "$config_target" "$config_source" "$config_source_path" ".codex/config.toml"
429
585
  fi
430
586
 
431
587
  # Copy project metadata files
@@ -434,27 +590,13 @@ for metadata in .env.example .version .template-manifest.json; do
434
590
  target="$PROJECT_DIR/.codex/$metadata"
435
591
  source_path=".codex/$metadata"
436
592
  [ -f "$source" ] || continue
437
- if should_copy "$target" "$source_path"; then
438
- cp "$source" "$target"
439
- echo " CREATED .codex/$metadata"
440
- elif $UPGRADE; then
441
- echo " KEPT .codex/$metadata (customized)"
442
- else
443
- echo " SKIP .codex/$metadata (exists)"
444
- fi
593
+ copy_and_log "$target" "$source" "$source_path" ".codex/$metadata"
445
594
  done
446
595
 
447
596
  # Copy AGENTS.md template
448
597
  agents_source="$REPO_DIR/templates/project/AGENTS.md.template"
449
598
  agents_target="$PROJECT_DIR/AGENTS.md"
450
- if should_copy "$agents_target" "templates/project/AGENTS.md.template"; then
451
- cp "$agents_source" "$agents_target"
452
- echo " CREATED AGENTS.md"
453
- elif $UPGRADE; then
454
- echo " KEPT AGENTS.md (customized)"
455
- else
456
- echo " SKIP AGENTS.md (exists)"
457
- fi
599
+ copy_and_log "$agents_target" "$agents_source" "templates/project/AGENTS.md.template" "AGENTS.md"
458
600
 
459
601
  # Create neutral context docs for target projects
460
602
  for doc in index.md architecture.md conventions.md current-priorities.md decision-log.md worklog.md gotchas.md session-context.md; do
@@ -463,20 +605,19 @@ for doc in index.md architecture.md conventions.md current-priorities.md decisio
463
605
  install_seed_file "$target" "$source_path" "context/$doc"
464
606
  done
465
607
 
608
+ # Ensure archive directory has a .gitkeep
609
+ if [ ! -f "$PROJECT_DIR/.codex/context/archive/.gitkeep" ]; then
610
+ : > "$PROJECT_DIR/.codex/context/archive/.gitkeep"
611
+ log_file_op ".codex/context/archive/.gitkeep" "created"
612
+ fi
613
+
466
614
  # Copy agent role files when the project owns shared inventory locally.
467
615
  if ! $USE_SHARED_ROOT && [ -d "$REPO_DIR/.codex/agents" ]; then
468
616
  for agent_file in "$REPO_DIR/.codex/agents"/*.toml; do
469
617
  [ -f "$agent_file" ] || continue
470
618
  target="$PROJECT_DIR/.codex/agents/$(basename "$agent_file")"
471
619
  source_path=".codex/agents/$(basename "$agent_file")"
472
- if should_copy "$target" "$source_path"; then
473
- cp "$agent_file" "$target"
474
- echo " CREATED .codex/agents/$(basename "$agent_file")"
475
- elif $UPGRADE; then
476
- echo " KEPT .codex/agents/$(basename "$agent_file") (customized)"
477
- else
478
- echo " SKIP .codex/agents/$(basename "$agent_file") (exists)"
479
- fi
620
+ copy_and_log "$target" "$agent_file" "$source_path" ".codex/agents/$(basename "$agent_file")"
480
621
  done
481
622
  fi
482
623
 
@@ -486,14 +627,7 @@ if ! $USE_SHARED_ROOT && [ -d "$REPO_DIR/.codex/prompts" ]; then
486
627
  [ -f "$prompt_file" ] || continue
487
628
  target="$PROJECT_DIR/.codex/prompts/$(basename "$prompt_file")"
488
629
  source_path=".codex/prompts/$(basename "$prompt_file")"
489
- if should_copy "$target" "$source_path"; then
490
- cp "$prompt_file" "$target"
491
- echo " CREATED .codex/prompts/$(basename "$prompt_file")"
492
- elif $UPGRADE; then
493
- echo " KEPT .codex/prompts/$(basename "$prompt_file") (customized)"
494
- else
495
- echo " SKIP .codex/prompts/$(basename "$prompt_file") (exists)"
496
- fi
630
+ copy_and_log "$target" "$prompt_file" "$source_path" ".codex/prompts/$(basename "$prompt_file")"
497
631
  done
498
632
  fi
499
633
 
@@ -507,15 +641,8 @@ if [ -d "$REPO_DIR/.codex/hooks" ]; then
507
641
  [ -f "$hook_file" ] || continue
508
642
  target="$PROJECT_DIR/.codex/hooks/$(basename "$hook_file")"
509
643
  source_path=".codex/hooks/$(basename "$hook_file")"
510
- if should_copy "$target" "$source_path"; then
511
- cp "$hook_file" "$target"
512
- chmod +x "$target"
513
- echo " CREATED .codex/hooks/$(basename "$hook_file")"
514
- elif $UPGRADE; then
515
- echo " KEPT .codex/hooks/$(basename "$hook_file") (customized)"
516
- else
517
- echo " SKIP .codex/hooks/$(basename "$hook_file") (exists)"
518
- fi
644
+ copy_and_log "$target" "$hook_file" "$source_path" ".codex/hooks/$(basename "$hook_file")"
645
+ [ -f "$target" ] && chmod +x "$target"
519
646
  done
520
647
  fi
521
648
 
@@ -525,15 +652,8 @@ if [ -d "$REPO_DIR/.codex/scripts" ]; then
525
652
  [ -f "$script_file" ] || continue
526
653
  target="$PROJECT_DIR/.codex/scripts/$(basename "$script_file")"
527
654
  source_path=".codex/scripts/$(basename "$script_file")"
528
- if should_copy "$target" "$source_path"; then
529
- cp "$script_file" "$target"
530
- chmod +x "$target"
531
- echo " CREATED .codex/scripts/$(basename "$script_file")"
532
- elif $UPGRADE; then
533
- echo " KEPT .codex/scripts/$(basename "$script_file") (customized)"
534
- else
535
- echo " SKIP .codex/scripts/$(basename "$script_file") (exists)"
536
- fi
655
+ copy_and_log "$target" "$script_file" "$source_path" ".codex/scripts/$(basename "$script_file")"
656
+ [ -f "$target" ] && chmod +x "$target"
537
657
  done
538
658
  fi
539
659
 
@@ -544,19 +664,12 @@ if ! $USE_SHARED_ROOT && [ -d "$REPO_DIR/.codex/skills" ]; then
544
664
  target="$PROJECT_DIR/.codex/skills/$rel_path"
545
665
  source_path=".codex/skills/$rel_path"
546
666
  mkdir -p "$(dirname "$target")"
547
- if should_copy "$target" "$source_path"; then
548
- cp "$skill_file" "$target"
549
- echo " CREATED .codex/skills/$rel_path"
550
- elif $UPGRADE; then
551
- echo " KEPT .codex/skills/$rel_path (customized)"
552
- else
553
- echo " SKIP .codex/skills/$rel_path (exists)"
554
- fi
667
+ copy_and_log "$target" "$skill_file" "$source_path" ".codex/skills/$rel_path"
555
668
  done < <(find "$REPO_DIR/.codex/skills" -type f | sort)
556
669
  fi
557
670
 
558
671
  # Seed neutral memory files for target projects
559
- for rel_path in README.md session-context.md project/user.md project/tech-stack.md project/project.md project/roadmap.md project/state.md project/gotchas.md; do
672
+ for rel_path in README.md project/user.md project/tech-stack.md project/project.md project/roadmap.md project/state.md project/gotchas.md; do
560
673
  target="$PROJECT_DIR/.codex/memory/$rel_path"
561
674
  source_path=".codex/memory/$rel_path"
562
675
  install_seed_file "$target" "$source_path" "memory/$rel_path"
@@ -565,7 +678,7 @@ done
565
678
  if [ ! -d "$PROJECT_DIR/.codex/memory/research" ]; then
566
679
  mkdir -p "$PROJECT_DIR/.codex/memory/research"
567
680
  : > "$PROJECT_DIR/.codex/memory/research/.gitkeep"
568
- echo " CREATED .codex/memory/research/.gitkeep"
681
+ log_file_op ".codex/memory/research/.gitkeep" "created"
569
682
  fi
570
683
 
571
684
  if [ -d "$REPO_DIR/.codex/memory/_templates" ]; then
@@ -574,14 +687,7 @@ if [ -d "$REPO_DIR/.codex/memory/_templates" ]; then
574
687
  target="$PROJECT_DIR/.codex/memory/$rel_path"
575
688
  source_path=".codex/memory/$rel_path"
576
689
  mkdir -p "$(dirname "$target")"
577
- if should_copy "$target" "$source_path"; then
578
- cp "$template_file" "$target"
579
- echo " CREATED .codex/memory/$rel_path"
580
- elif $UPGRADE; then
581
- echo " KEPT .codex/memory/$rel_path (customized)"
582
- else
583
- echo " SKIP .codex/memory/$rel_path (exists)"
584
- fi
690
+ copy_and_log "$target" "$template_file" "$source_path" ".codex/memory/$rel_path"
585
691
  done < <(find "$REPO_DIR/.codex/memory/_templates" -type f | sort)
586
692
  fi
587
693
 
@@ -592,14 +698,7 @@ if [ -d "$REPO_DIR/.codex/plans" ]; then
592
698
  target="$PROJECT_DIR/.codex/plans/$rel_path"
593
699
  source_path=".codex/plans/$rel_path"
594
700
  mkdir -p "$(dirname "$target")"
595
- if should_copy "$target" "$source_path"; then
596
- cp "$plan_file" "$target"
597
- echo " CREATED .codex/plans/$rel_path"
598
- elif $UPGRADE; then
599
- echo " KEPT .codex/plans/$rel_path (customized)"
600
- else
601
- echo " SKIP .codex/plans/$rel_path (exists)"
602
- fi
701
+ copy_and_log "$target" "$plan_file" "$source_path" ".codex/plans/$rel_path"
603
702
  done < <(find "$REPO_DIR/.codex/plans" -type f | sort)
604
703
  fi
605
704
 
@@ -609,19 +708,12 @@ if [ -d "$REPO_DIR/.codex/mcp" ]; then
609
708
  [ -f "$mcp_file" ] || continue
610
709
  target="$PROJECT_DIR/.codex/mcp/$(basename "$mcp_file")"
611
710
  source_path=".codex/mcp/$(basename "$mcp_file")"
612
- if should_copy "$target" "$source_path"; then
613
- cp "$mcp_file" "$target"
614
- echo " CREATED .codex/mcp/$(basename "$mcp_file")"
615
- elif $UPGRADE; then
616
- echo " KEPT .codex/mcp/$(basename "$mcp_file") (customized)"
617
- else
618
- echo " SKIP .codex/mcp/$(basename "$mcp_file") (exists)"
619
- fi
711
+ copy_and_log "$target" "$mcp_file" "$source_path" ".codex/mcp/$(basename "$mcp_file")"
620
712
  done
621
713
  fi
622
714
 
623
715
  if [ -e "$PROJECT_DIR/.agents" ]; then
624
- echo " KEPT .agents (legacy compatibility path)"
716
+ if $VERBOSE; then echo " KEPT .agents (legacy compatibility path)"; fi
625
717
  fi
626
718
 
627
719
  # ─── Custom template overlay ────────────────────────────────────────────
@@ -689,9 +781,9 @@ for k, v in vars.items():
689
781
  sed -i "s|{{${var_name}}}|${TMPL_VARS[$var_name]}|g" "$target" 2>/dev/null || true
690
782
  done
691
783
  fi
692
- echo " CREATED $rel_path (from template)"
784
+ log_file_op "$rel_path" "created"
693
785
  else
694
- echo " SKIP $rel_path (exists)"
786
+ log_file_op "$rel_path" "skipped"
695
787
  fi
696
788
  done < <(find "$TMPL_DIR/files" -type f | sort)
697
789
  fi
@@ -711,6 +803,8 @@ if $UPGRADE && $AUTO_APPLY_PATCHES; then
711
803
  CODEXKIT_PROJECT_DIR="$PROJECT_DIR" "$REPO_DIR/install/patch.sh" apply-all
712
804
  fi
713
805
 
806
+ print_summary
807
+ echo ""
714
808
  echo "✓ Project install complete"
715
809
  echo " Structure:"
716
810
  echo " AGENTS.md (project root)"
@@ -430,7 +430,7 @@ done
430
430
  # ─── Memory ──────────────────────────────────────────────────────
431
431
  echo ""
432
432
  echo "Memory:"
433
- for doc in README.md session-context.md project/user.md project/tech-stack.md project/project.md project/roadmap.md project/state.md project/gotchas.md; do
433
+ for doc in README.md project/user.md project/tech-stack.md project/project.md project/roadmap.md project/state.md project/gotchas.md; do
434
434
  if [ -f ".codex/memory/$doc" ]; then
435
435
  check ".codex/memory/$doc" "pass"
436
436
  else
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codexkit",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "Professional configuration kit for OpenAI Codex CLI",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -11,7 +11,7 @@
11
11
  "installer"
12
12
  ],
13
13
  "bin": {
14
- "codexkit": "bin/codexkit"
14
+ "codexkit": "bin/codexkit.js"
15
15
  },
16
16
  "files": [
17
17
  "bin",