chiefwiggum 1.2.8 → 1.3.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/chiefwiggum DELETED
@@ -1,862 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- ###########################################
5
- # ░█▀▀░█░█░▀█▀░█▀▀░█▀▀░░░█░█░▀█▀░█▀▀░█▀▀░█░█░█▄█
6
- # ░█░░░█▀█░░█░░█▀▀░█▀▀░░░█▄█░░█░░█░█░█░█░█░█░█░█
7
- # ░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀░░░░░▀░▀░▀▀▀░▀▀▀░▀▀▀░▀▀▀░▀░▀
8
- #
9
- # Autonomous coding agent CLI
10
- ###########################################
11
-
12
- VERSION="$(grep '"version"' "$(dirname "$(realpath "$0")")/package.json" 2>/dev/null | sed 's/.*"version": "\([^"]*\)".*/\1/' || echo "dev")"
13
-
14
- # =========================================
15
- # COLORS
16
- # =========================================
17
- GREEN='\033[0;32m'
18
- YELLOW='\033[1;33m'
19
- RED='\033[0;31m'
20
- BLUE='\033[0;34m'
21
- CYAN='\033[0;36m'
22
- BOLD='\033[1m'
23
- NC='\033[0m'
24
-
25
- # =========================================
26
- # CONFIGURATION
27
- # =========================================
28
- SCRIPT_DIR="$(dirname "$(realpath "$0")")"
29
- CHIEFWIGGUM_HOME="${CHIEFWIGGUM_HOME:-$HOME/.chiefwiggum}"
30
- TEMPLATES_DIR="${CHIEFWIGGUM_HOME}/templates"
31
- BUNDLED_TEMPLATES="${SCRIPT_DIR}/templates"
32
- TODO_FILE="${TODO_FILE:-TODO.md}"
33
- COOLDOWN_SECONDS="${COOLDOWN_SECONDS:-5}"
34
-
35
- # Guardrails
36
- ITERATION_TIMEOUT_MINUTES="${ITERATION_TIMEOUT_MINUTES:-60}"
37
- MAX_CONSECUTIVE_FAILURES="${MAX_CONSECUTIVE_FAILURES:-3}"
38
- MAX_NO_COMMIT_CYCLES="${MAX_NO_COMMIT_CYCLES:-5}"
39
- MAX_CLAUDE_ATTEMPTS="${MAX_CLAUDE_ATTEMPTS:-3}"
40
-
41
- # Claude Code reliability hardening
42
- export CLAUDE_CODE_EXIT_AFTER_STOP_DELAY="${CLAUDE_CODE_EXIT_AFTER_STOP_DELAY:-30000}"
43
- export NODE_OPTIONS="--unhandled-rejections=strict${NODE_OPTIONS:+ $NODE_OPTIONS}"
44
-
45
- # =========================================
46
- # BANNER
47
- # =========================================
48
- show_banner() {
49
- echo ""
50
- echo -e "${YELLOW}░█▀▀░█░█░▀█▀░█▀▀░█▀▀░░░█░█░▀█▀░█▀▀░█▀▀░█░█░█▄█${NC}"
51
- echo -e "${YELLOW}░█░░░█▀█░░█░░█▀▀░█▀▀░░░█▄█░░█░░█░█░█░█░█░█░█░█${NC}"
52
- echo -e "${YELLOW}░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀░░░░░▀░▀░▀▀▀░▀▀▀░▀▀▀░▀▀▀░▀░▀${NC}"
53
- echo -e "${YELLOW} Autonomous Coding Agent v${VERSION}${NC}"
54
- echo ""
55
-
56
- # Check for updates (non-blocking, 2s timeout)
57
- check_for_updates
58
- }
59
-
60
- check_for_updates() {
61
- local latest
62
- latest=$(timeout 2s npm view chiefwiggum version 2>/dev/null || echo "")
63
-
64
- if [ -n "$latest" ] && [ "$latest" != "$VERSION" ]; then
65
- echo -e "${CYAN} ✨ Update available: v${VERSION} → v${latest}${NC}"
66
- echo -e "${CYAN} Run: npx chiefwiggum@latest${NC}"
67
- echo ""
68
- fi
69
- }
70
-
71
- # =========================================
72
- # HELP
73
- # =========================================
74
- show_help() {
75
- show_banner
76
- echo "Usage: chiefwiggum [command] [options]"
77
- echo ""
78
- echo "Commands:"
79
- echo " new [plan.md] Initialize project (interactive or from plan file)"
80
- echo " loop Run the build loop on existing TODO.md"
81
- echo " status Show current project status"
82
- echo " help Show this help message"
83
- echo ""
84
- echo "Examples:"
85
- echo " chiefwiggum new # Interactive setup"
86
- echo " chiefwiggum new plans/myplan.md # Setup from plan file"
87
- echo " chiefwiggum loop # Start build loop"
88
- echo " chiefwiggum # Same as 'loop'"
89
- echo ""
90
- echo "Templates:"
91
- echo -e " ${CYAN}${TEMPLATES_DIR}${NC}"
92
- echo " Edit these to customize how specs are generated."
93
- echo ""
94
- }
95
-
96
- # =========================================
97
- # PROMPT HELPERS
98
- # =========================================
99
- ask_choice() {
100
- local prompt="$1"
101
- shift
102
- local options=("$@")
103
-
104
- echo ""
105
- echo -e "${BOLD}${prompt}${NC}"
106
- echo ""
107
-
108
- local i=1
109
- for opt in "${options[@]}"; do
110
- echo -e " ${CYAN}${i})${NC} ${opt}"
111
- ((i++))
112
- done
113
- echo ""
114
-
115
- while true; do
116
- read -rp "Enter choice [1-${#options[@]}]: " choice
117
- if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le "${#options[@]}" ]; then
118
- return $((choice - 1))
119
- fi
120
- echo -e "${RED}Invalid choice. Please enter 1-${#options[@]}${NC}"
121
- done
122
- }
123
-
124
- ask_text() {
125
- local prompt="$1"
126
- local default="${2:-}"
127
-
128
- echo ""
129
- if [ -n "$default" ]; then
130
- read -rp "${prompt} [${default}]: " response
131
- echo "${response:-$default}"
132
- else
133
- read -rp "${prompt}: " response
134
- echo "$response"
135
- fi
136
- }
137
-
138
- ask_confirm() {
139
- local prompt="$1"
140
- local default="${2:-y}"
141
-
142
- if [ "$default" = "y" ]; then
143
- read -rp "${prompt} [Y/n]: " response
144
- [[ ! "$response" =~ ^[Nn] ]]
145
- else
146
- read -rp "${prompt} [y/N]: " response
147
- [[ "$response" =~ ^[Yy] ]]
148
- fi
149
- }
150
-
151
- # =========================================
152
- # STATUS COMMAND
153
- # =========================================
154
- cmd_status() {
155
- show_banner
156
-
157
- echo -e "${BOLD}Project Status${NC}"
158
- echo ""
159
-
160
- # Check for key files
161
- local has_todo=false
162
- local has_specs=false
163
- local has_claude_md=false
164
-
165
- [ -f "$TODO_FILE" ] && has_todo=true
166
- [ -d "specs" ] && has_specs=true
167
- [ -f "CLAUDE.md" ] && has_claude_md=true
168
-
169
- echo -e " TODO.md: $([ "$has_todo" = true ] && echo -e "${GREEN}✓${NC}" || echo -e "${RED}✗${NC}")"
170
- echo -e " specs/: $([ "$has_specs" = true ] && echo -e "${GREEN}✓${NC}" || echo -e "${RED}✗${NC}")"
171
- echo -e " CLAUDE.md: $([ "$has_claude_md" = true ] && echo -e "${GREEN}✓${NC}" || echo -e "${RED}✗${NC}")"
172
- echo ""
173
-
174
- if [ "$has_todo" = true ]; then
175
- local total=$(grep -c "^\s*- \[" "$TODO_FILE" 2>/dev/null || echo "0")
176
- local done=$(grep -c "^\s*- \[x\]" "$TODO_FILE" 2>/dev/null || echo "0")
177
- local remaining=$((total - done))
178
-
179
- echo -e "${BOLD}Tasks${NC}"
180
- echo -e " Total: ${total}"
181
- echo -e " Completed: ${GREEN}${done}${NC}"
182
- echo -e " Remaining: ${YELLOW}${remaining}${NC}"
183
- echo ""
184
- fi
185
-
186
- # Git status
187
- if git rev-parse --git-dir &>/dev/null; then
188
- local branch=$(git branch --show-current 2>/dev/null || echo "unknown")
189
- local commits=$(git rev-list --count HEAD 2>/dev/null || echo "0")
190
- echo -e "${BOLD}Git${NC}"
191
- echo -e " Branch: ${branch}"
192
- echo -e " Commits: ${commits}"
193
- fi
194
- echo ""
195
- }
196
-
197
- # =========================================
198
- # NEW COMMAND - INTERACTIVE SETUP
199
- # =========================================
200
- cmd_new() {
201
- local plan_file="${1:-}"
202
-
203
- show_banner
204
-
205
- echo -e "${BOLD}Project Setup${NC}"
206
- echo ""
207
-
208
- # Show current directory
209
- echo -e "Working directory: ${CYAN}$(pwd)${NC}"
210
- echo ""
211
-
212
- if ! ask_confirm "Initialize Chief Wiggum in this directory?"; then
213
- echo -e "${YELLOW}Aborted.${NC}"
214
- exit 0
215
- fi
216
-
217
- # Check for existing chiefwiggum files (not CLAUDE.md - that's project-specific)
218
- local existing_files=()
219
- [ -f "$TODO_FILE" ] && existing_files+=("TODO.md")
220
- [ -d "specs" ] && existing_files+=("specs/")
221
-
222
- if [ ${#existing_files[@]} -gt 0 ]; then
223
- echo ""
224
- echo -e "${YELLOW}Existing files found:${NC}"
225
- for f in "${existing_files[@]}"; do
226
- echo " - $f"
227
- done
228
- echo ""
229
- if ! ask_confirm "Overwrite these files?" "n"; then
230
- echo -e "${YELLOW}Aborted.${NC}"
231
- exit 0
232
- fi
233
- fi
234
-
235
- # Note if CLAUDE.md exists (we'll preserve it)
236
- local has_claude_md=false
237
- [ -f "CLAUDE.md" ] && has_claude_md=true
238
-
239
- # If plan file provided, use it directly
240
- if [ -n "$plan_file" ]; then
241
- if [ ! -f "$plan_file" ]; then
242
- echo -e "${RED}Plan file not found: ${plan_file}${NC}"
243
- exit 1
244
- fi
245
- generate_from_plan "$plan_file"
246
- start_loop
247
- return
248
- fi
249
-
250
- # Interactive setup
251
- ask_choice "How would you like to set up this project?" \
252
- "From a plan file - I have a plan.md ready" \
253
- "Describe it - I'll tell you what to build" \
254
- "Existing TODO - Just start the loop with current TODO.md"
255
- local setup_choice=$?
256
-
257
- case $setup_choice in
258
- 0)
259
- # From plan file
260
- echo ""
261
- # Show available plans
262
- if [ -d "plans" ] && [ "$(ls -A plans/*.md 2>/dev/null)" ]; then
263
- echo -e "${BOLD}Available plans:${NC}"
264
- for f in plans/*.md; do
265
- echo -e " ${CYAN}${f}${NC}"
266
- done
267
- echo ""
268
- fi
269
- # Use read -e for tab completion
270
- local plan_path
271
- read -e -p "Path to plan file [plans/plan.md]: " plan_path
272
- plan_path="${plan_path:-plans/plan.md}"
273
- if [ ! -f "$plan_path" ]; then
274
- echo -e "${RED}Plan file not found: ${plan_path}${NC}"
275
- exit 1
276
- fi
277
- generate_from_plan "$plan_path"
278
- ;;
279
- 1)
280
- # Describe project
281
- interactive_describe
282
- ;;
283
- 2)
284
- # Existing TODO
285
- if [ ! -f "$TODO_FILE" ]; then
286
- echo -e "${RED}No TODO.md found. Run 'chiefwiggum new' to set up first.${NC}"
287
- exit 1
288
- fi
289
- ;;
290
- esac
291
-
292
- # Ask about starting the loop
293
- echo ""
294
- ask_choice "Ready to start. What would you like to do?" \
295
- "Start the build loop now" \
296
- "Review files first, then start manually with 'chiefwiggum loop'" \
297
- "Exit"
298
- local start_choice=$?
299
-
300
- case $start_choice in
301
- 0) start_loop ;;
302
- 1)
303
- echo ""
304
- echo -e "${GREEN}Setup complete!${NC} Review your files, then run:"
305
- echo -e " ${CYAN}chiefwiggum loop${NC}"
306
- ;;
307
- 2)
308
- echo -e "${YELLOW}Exiting.${NC}"
309
- ;;
310
- esac
311
- }
312
-
313
- # =========================================
314
- # INTERACTIVE PROJECT DESCRIPTION
315
- # =========================================
316
- interactive_describe() {
317
- echo ""
318
- echo -e "${BOLD}Tell me about your project${NC}"
319
- echo ""
320
-
321
- # Project name
322
- local project_name
323
- project_name=$(ask_text "Project name")
324
-
325
- # Project type
326
- ask_choice "What type of project is this?" \
327
- "Web application (Next.js, React, etc.)" \
328
- "API / Backend service" \
329
- "CLI tool" \
330
- "Library / Package" \
331
- "Mobile app" \
332
- "Other"
333
- local project_type=$?
334
- local project_type_names=("web" "api" "cli" "library" "mobile" "other")
335
- local project_type_name="${project_type_names[$project_type]}"
336
-
337
- # Tech stack
338
- local tech_stack
339
- tech_stack=$(ask_text "Tech stack (e.g., Next.js, TypeScript, Convex)")
340
-
341
- # Description
342
- echo ""
343
- echo -e "${BOLD}Describe what you're building:${NC}"
344
- echo "(Enter description, then press Enter twice to finish)"
345
- echo ""
346
- local description=""
347
- local empty_lines=0
348
- while IFS= read -r line; do
349
- if [ -z "$line" ]; then
350
- ((empty_lines++))
351
- [ $empty_lines -ge 1 ] && break
352
- else
353
- empty_lines=0
354
- fi
355
- description+="$line"$'\n'
356
- done
357
-
358
- # Key features
359
- echo ""
360
- echo -e "${BOLD}List key features (one per line, empty line to finish):${NC}"
361
- local features=""
362
- while IFS= read -r line; do
363
- [ -z "$line" ] && break
364
- features+="- $line"$'\n'
365
- done
366
-
367
- # Generate plan content
368
- local plan_content="# ${project_name}
369
-
370
- ## Overview
371
- ${description}
372
-
373
- ## Project Type
374
- ${project_type_name}
375
-
376
- ## Tech Stack
377
- ${tech_stack}
378
-
379
- ## Key Features
380
- ${features}
381
- "
382
-
383
- # Save plan
384
- mkdir -p plans
385
- local plan_file="plans/plan.md"
386
- echo "$plan_content" > "$plan_file"
387
- echo ""
388
- echo -e "${GREEN}Plan saved to ${plan_file}${NC}"
389
-
390
- # Generate specs from plan
391
- generate_from_plan "$plan_file"
392
- }
393
-
394
- # =========================================
395
- # GENERATE SPECS FROM PLAN
396
- # =========================================
397
- generate_from_plan() {
398
- local plan_file="$1"
399
- local plan_content
400
- plan_content="$(cat "$plan_file")"
401
-
402
- echo ""
403
- echo -e "${GREEN}════════════════════════════════════════${NC}"
404
- echo -e "${GREEN} Generating specs from: ${plan_file}${NC}"
405
- echo -e "${GREEN}════════════════════════════════════════${NC}"
406
-
407
- # Check templates exist
408
- if [ ! -d "$TEMPLATES_DIR" ]; then
409
- echo -e "${RED}Templates not found at: ${TEMPLATES_DIR}${NC}"
410
- echo ""
411
- echo "Run this to set up templates:"
412
- echo -e " ${CYAN}npx chiefwiggum@latest${NC}"
413
- exit 1
414
- fi
415
-
416
- mkdir -p specs
417
-
418
- # Load templates
419
- local prd_template=$(cat "$TEMPLATES_DIR/specs/prd.md")
420
- local tech_template=$(cat "$TEMPLATES_DIR/specs/technical.md")
421
- local todo_template=$(cat "$TEMPLATES_DIR/TODO.md")
422
- local claude_template=$(cat "$TEMPLATES_DIR/CLAUDE.md")
423
-
424
- # Step 1: Generate PRD
425
- echo ""
426
- echo -e "${YELLOW}[1/4] Generating specs/prd.md...${NC}"
427
-
428
- local prd_prompt="You are filling in a PRD template based on a project plan.
429
-
430
- Here is the plan:
431
- <plan>
432
- ${plan_content}
433
- </plan>
434
-
435
- Here is the template to fill in:
436
- <template>
437
- ${prd_template}
438
- </template>
439
-
440
- Fill in the template with specific details from the plan.
441
- Replace all placeholder text in [brackets] with real content.
442
- Write the completed PRD directly to specs/prd.md.
443
- Do NOT ask questions — infer everything from the plan."
444
-
445
- echo "$prd_prompt" | claude -p --dangerously-skip-permissions 2>/dev/null
446
- echo -e "${GREEN} ✓ specs/prd.md${NC}"
447
-
448
- # Step 2: Generate Technical Spec
449
- echo ""
450
- echo -e "${YELLOW}[2/4] Generating specs/technical.md...${NC}"
451
- local prd_generated
452
- prd_generated="$(cat specs/prd.md 2>/dev/null || echo "")"
453
-
454
- local tech_prompt="You are filling in a Technical Specification template based on a PRD.
455
-
456
- Here is the PRD:
457
- <prd>
458
- ${prd_generated}
459
- </prd>
460
-
461
- Here is the template to fill in:
462
- <template>
463
- ${tech_template}
464
- </template>
465
-
466
- Fill in the template with specific technical details.
467
- Replace all placeholder text in [brackets] with real content.
468
- Write the completed spec directly to specs/technical.md.
469
- Do NOT ask questions — infer everything from the PRD."
470
-
471
- echo "$tech_prompt" | claude -p --dangerously-skip-permissions 2>/dev/null
472
- echo -e "${GREEN} ✓ specs/technical.md${NC}"
473
-
474
- # Step 3: Generate CLAUDE.md (skip if exists)
475
- echo ""
476
- if [ -f "CLAUDE.md" ]; then
477
- echo -e "${YELLOW}[3/4] Skipping CLAUDE.md (already exists)${NC}"
478
- else
479
- echo -e "${YELLOW}[3/4] Generating CLAUDE.md...${NC}"
480
-
481
- local claude_prompt="You are filling in a CLAUDE.md template for a project.
482
-
483
- Here is the PRD:
484
- <prd>
485
- ${prd_generated}
486
- </prd>
487
-
488
- Here is the Technical Spec:
489
- <technical>
490
- $(cat specs/technical.md 2>/dev/null || echo "")
491
- </technical>
492
-
493
- Here is the template to fill in:
494
- <template>
495
- ${claude_template}
496
- </template>
497
-
498
- Fill in the template with project-specific details.
499
- Replace all placeholder text in [brackets] with real content.
500
- Keep it concise - this is a quick reference for AI agents.
501
- Write directly to CLAUDE.md."
502
-
503
- echo "$claude_prompt" | claude -p --dangerously-skip-permissions 2>/dev/null
504
- echo -e "${GREEN} ✓ CLAUDE.md${NC}"
505
- fi
506
-
507
- # Step 4: Generate TODO
508
- echo ""
509
- echo -e "${YELLOW}[4/4] Generating TODO.md...${NC}"
510
-
511
- local todo_prompt="You are filling in a TODO template based on specs.
512
-
513
- Here is the PRD:
514
- <prd>
515
- ${prd_generated}
516
- </prd>
517
-
518
- Here is the Technical Specification:
519
- <technical>
520
- $(cat specs/technical.md 2>/dev/null || echo "")
521
- </technical>
522
-
523
- Here is the template to follow:
524
- <template>
525
- ${todo_template}
526
- </template>
527
-
528
- Create a phased TODO.md following the template structure.
529
- Use checkbox format: - [ ] Task description
530
- Keep tasks granular (1-2 hours max each).
531
- End each phase with: - [ ] Phase N review
532
- Write directly to TODO.md."
533
-
534
- echo "$todo_prompt" | claude -p --dangerously-skip-permissions 2>/dev/null
535
- echo -e "${GREEN} ✓ TODO.md${NC}"
536
-
537
- echo ""
538
- echo -e "${GREEN}Specs generated:${NC}"
539
- echo " - specs/prd.md"
540
- echo " - specs/technical.md"
541
- if [ ! -f "CLAUDE.md" ]; then
542
- echo " - CLAUDE.md"
543
- fi
544
- echo " - TODO.md"
545
-
546
- # Commit specs
547
- if git rev-parse --git-dir &>/dev/null; then
548
- git add specs/ TODO.md CLAUDE.md 2>/dev/null || true
549
- git commit -m "chore: generate specs from plan" 2>/dev/null || true
550
- fi
551
- }
552
-
553
- # =========================================
554
- # BUILD LOOP
555
- # =========================================
556
- start_loop() {
557
- [ -f "$TODO_FILE" ] || { echo -e "${RED}Missing $TODO_FILE${NC}"; exit 1; }
558
-
559
- local max_iterations
560
- max_iterations=$(grep -c "\[ \]" "$TODO_FILE" 2>/dev/null) || max_iterations=0
561
-
562
- if [ "$max_iterations" -eq 0 ]; then
563
- echo -e "${GREEN}No unchecked tasks in $TODO_FILE. All done!${NC}"
564
- exit 0
565
- fi
566
-
567
- echo ""
568
- echo -e "${GREEN}════════════════════════════════════════${NC}"
569
- echo -e "${GREEN} Starting Build Loop${NC}"
570
- echo -e "${GREEN} Tasks remaining: ${max_iterations}${NC}"
571
- echo -e "${GREEN} Timeout: ${ITERATION_TIMEOUT_MINUTES}m per task${NC}"
572
- echo -e "${GREEN}════════════════════════════════════════${NC}"
573
-
574
- local consecutive_failures=0
575
- local no_commit_cycles=0
576
- local last_commit
577
- last_commit="$(git rev-parse HEAD 2>/dev/null || echo "none")"
578
-
579
- for i in $(seq 1 "$max_iterations"); do
580
- echo ""
581
- echo -e "${YELLOW}══════════ Task $i of $max_iterations ══════════${NC}"
582
-
583
- cleanup_stale_processes
584
-
585
- local start_time
586
- start_time="$(date +%s)"
587
-
588
- set +e
589
- run_task_iteration "$i"
590
- local claude_exit=$?
591
- set -e
592
-
593
- local duration=$(($(date +%s) - start_time))
594
- echo ""
595
- echo -e "Completed in ${duration}s (exit: ${claude_exit})"
596
-
597
- # Track failures
598
- if [ "$claude_exit" -ne 0 ]; then
599
- consecutive_failures=$((consecutive_failures + 1))
600
- echo -e "${RED}Failure ${consecutive_failures}/${MAX_CONSECUTIVE_FAILURES}${NC}"
601
- sleep 30
602
- else
603
- consecutive_failures=0
604
- fi
605
-
606
- # Track commits
607
- local current_commit
608
- current_commit="$(git rev-parse HEAD 2>/dev/null || echo "none")"
609
- if [ "$current_commit" = "$last_commit" ]; then
610
- if [ "$claude_exit" -eq 0 ]; then
611
- no_commit_cycles=$((no_commit_cycles + 1))
612
- echo -e "${YELLOW}No commit (${no_commit_cycles}/${MAX_NO_COMMIT_CYCLES})${NC}"
613
- fi
614
- else
615
- no_commit_cycles=0
616
- last_commit="$current_commit"
617
- echo -e "${GREEN}New commit: ${current_commit:0:7}${NC}"
618
- git push origin HEAD 2>/dev/null && echo "Pushed to origin" || true
619
- fi
620
-
621
- # Guardrails
622
- if [ "$consecutive_failures" -ge "$MAX_CONSECUTIVE_FAILURES" ]; then
623
- echo -e "${RED}Stopping: ${MAX_CONSECUTIVE_FAILURES} consecutive failures${NC}"
624
- exit 1
625
- fi
626
-
627
- if [ "$no_commit_cycles" -ge "$MAX_NO_COMMIT_CYCLES" ]; then
628
- echo -e "${RED}Stopping: No commits for ${MAX_NO_COMMIT_CYCLES} cycles${NC}"
629
- exit 1
630
- fi
631
-
632
- # Check if done
633
- if ! grep -q "\[ \]" "$TODO_FILE"; then
634
- echo ""
635
- echo -e "${GREEN}════════════════════════════════════════${NC}"
636
- echo -e "${GREEN} All tasks completed!${NC}"
637
- echo -e "${GREEN}════════════════════════════════════════${NC}"
638
- git push origin HEAD 2>/dev/null || true
639
- exit 0
640
- fi
641
-
642
- sleep "$COOLDOWN_SECONDS"
643
- done
644
-
645
- echo -e "${YELLOW}Reached max iterations (${max_iterations})${NC}"
646
- git push origin HEAD 2>/dev/null || true
647
- }
648
-
649
- run_task_iteration() {
650
- local iteration="$1"
651
- local log_file="/tmp/chiefwiggum-iter${iteration}.log"
652
-
653
- local task_prompt='You are an autonomous coding agent. Complete ONE task from TODO.md.
654
-
655
- ## Before Starting
656
- Read these files to understand the project:
657
- - CLAUDE.md — Project context and conventions
658
- - specs/prd.md — What we are building
659
- - specs/technical.md — How we are building it
660
- - TODO.md — Task list
661
-
662
- ## Workflow
663
- 1. Find the FIRST unchecked task (- [ ]) in TODO.md
664
- 2. Plan: Understand what needs to be done
665
- 3. Implement: Write the code
666
- 4. Review: Verify it works
667
- 5. Mark complete: Change - [ ] to - [x] in TODO.md
668
- 6. Commit: git add . && git commit -m "type(scope): description"
669
-
670
- ## Rules
671
- - ONE task per iteration
672
- - Follow existing code patterns
673
- - Use conventional commits (feat, fix, docs, refactor, test, chore)
674
- - If blocked after 3 attempts, output RALPH_BLOCKED: <reason>
675
-
676
- ## When Done
677
- Output: RALPH_COMPLETE
678
- If no tasks remain: RALPH_ALL_DONE'
679
-
680
- local claude_exit=1
681
-
682
- for attempt in $(seq 1 "$MAX_CLAUDE_ATTEMPTS"); do
683
- echo -e "${YELLOW}Attempt ${attempt}/${MAX_CLAUDE_ATTEMPTS}${NC}"
684
-
685
- echo "$task_prompt" \
686
- | timeout --kill-after=10s "${ITERATION_TIMEOUT_MINUTES}m" \
687
- claude -p --dangerously-skip-permissions --no-session-persistence \
688
- --verbose --output-format stream-json \
689
- 2>&1 \
690
- | tee "$log_file" \
691
- | jq -r '
692
- if .type == "assistant" then
693
- (.message.content[]? | select(.type=="text") | .text? // empty),
694
- (.message.content[]? | select(.type=="tool_use") | "🔧 " + .name)
695
- elif .type == "result" then
696
- "✅ " + (.subtype // "done")
697
- else empty end
698
- ' 2>/dev/null || true &
699
- local claude_pid=$!
700
-
701
- # Monitor for freeze
702
- while kill -0 $claude_pid 2>/dev/null; do
703
- if grep -q "No messages returned" "$log_file" 2>/dev/null; then
704
- echo -e "${RED}Freeze detected, killing...${NC}"
705
- kill -9 $claude_pid 2>/dev/null || true
706
- sleep 2
707
- break
708
- fi
709
- sleep 1
710
- done
711
-
712
- wait $claude_pid 2>/dev/null
713
- claude_exit=$?
714
-
715
- # Check for transient errors
716
- if [ "$claude_exit" -ne 0 ]; then
717
- if grep -qE "(No messages returned|ECONNRESET|ETIMEDOUT)" "$log_file" 2>/dev/null; then
718
- echo -e "${YELLOW}Transient error, retrying...${NC}"
719
- sleep $((attempt * 5))
720
- continue
721
- fi
722
- fi
723
-
724
- break
725
- done
726
-
727
- rm -f "$log_file"
728
- return $claude_exit
729
- }
730
-
731
- cleanup_stale_processes() {
732
- pkill -f playwright 2>/dev/null || true
733
- pkill -f chromium 2>/dev/null || true
734
- if command -v lsof &>/dev/null; then
735
- lsof -ti:3000 | xargs kill -9 2>/dev/null || true
736
- fi
737
- sleep 1
738
- }
739
-
740
- # =========================================
741
- # SETUP TEMPLATES
742
- # =========================================
743
- setup_templates() {
744
- # Copy bundled templates to ~/.chiefwiggum/templates
745
- if [ -d "$BUNDLED_TEMPLATES" ]; then
746
- mkdir -p "$CHIEFWIGGUM_HOME"
747
- cp -r "$BUNDLED_TEMPLATES" "$CHIEFWIGGUM_HOME/"
748
- echo -e "${GREEN}✓ Templates installed to: ${TEMPLATES_DIR}${NC}"
749
- fi
750
- }
751
-
752
- # =========================================
753
- # INSTALL COMMAND
754
- # =========================================
755
- cmd_install() {
756
- show_banner
757
-
758
- echo -e "${BOLD}Installing Chief Wiggum...${NC}"
759
- echo ""
760
-
761
- # Check if already installed globally
762
- if command -v chiefwiggum &>/dev/null; then
763
- local installed_path=$(which chiefwiggum)
764
- if [[ "$installed_path" != *"npx"* ]] && [[ "$installed_path" != *".npm/_npx"* ]]; then
765
- echo -e "${GREEN}✓ Already installed at: ${installed_path}${NC}"
766
- # Still set up templates in case they're missing
767
- setup_templates
768
- echo ""
769
- echo "Run 'chiefwiggum new' to get started."
770
- return 0
771
- fi
772
- fi
773
-
774
- # Install globally
775
- echo "Running: npm install -g chiefwiggum@latest"
776
- echo ""
777
-
778
- if npm install -g chiefwiggum@latest; then
779
- echo ""
780
- # Set up templates after install
781
- # Need to get the installed location
782
- local installed_dir=$(dirname "$(realpath "$(which chiefwiggum)")")
783
- if [ -d "${installed_dir}/templates" ]; then
784
- mkdir -p "$CHIEFWIGGUM_HOME"
785
- cp -r "${installed_dir}/templates" "$CHIEFWIGGUM_HOME/"
786
- echo -e "${GREEN}✓ Templates installed to: ${TEMPLATES_DIR}${NC}"
787
- fi
788
-
789
- echo ""
790
- echo -e "${GREEN}════════════════════════════════════════${NC}"
791
- echo -e "${GREEN} ✓ Installation complete!${NC}"
792
- echo -e "${GREEN}════════════════════════════════════════${NC}"
793
- echo ""
794
- echo -e "Templates: ${CYAN}${TEMPLATES_DIR}${NC}"
795
- echo ""
796
- echo "Get started:"
797
- echo -e " ${CYAN}chiefwiggum new${NC} # Set up a new project"
798
- echo -e " ${CYAN}chiefwiggum loop${NC} # Run the build loop"
799
- echo -e " ${CYAN}chiefwiggum help${NC} # See all commands"
800
- echo ""
801
- else
802
- echo ""
803
- echo -e "${RED}Installation failed.${NC}"
804
- echo "Try running with sudo: sudo npm install -g chiefwiggum"
805
- exit 1
806
- fi
807
- }
808
-
809
- # =========================================
810
- # MAIN
811
- # =========================================
812
- main() {
813
- local cmd="${1:-}"
814
-
815
- case "$cmd" in
816
- install)
817
- cmd_install
818
- ;;
819
- new)
820
- shift
821
- cmd_new "$@"
822
- ;;
823
- loop)
824
- show_banner
825
- start_loop
826
- ;;
827
- status)
828
- cmd_status
829
- ;;
830
- help|--help|-h)
831
- show_help
832
- ;;
833
- "")
834
- # No command: if running via npx, install. Otherwise run loop.
835
- if [[ "${0}" == *"npx"* ]] || [[ "${0}" == *".npm/_npx"* ]]; then
836
- cmd_install
837
- else
838
- show_banner
839
- if [ -f "$TODO_FILE" ]; then
840
- start_loop
841
- else
842
- echo -e "${YELLOW}No TODO.md found. Run 'chiefwiggum new' to get started.${NC}"
843
- exit 1
844
- fi
845
- fi
846
- ;;
847
- *)
848
- # Check if it's a file path (for backward compat with ralph.sh)
849
- if [ -f "$cmd" ]; then
850
- show_banner
851
- generate_from_plan "$cmd"
852
- start_loop
853
- else
854
- echo -e "${RED}Unknown command: ${cmd}${NC}"
855
- echo "Run 'chiefwiggum help' for usage."
856
- exit 1
857
- fi
858
- ;;
859
- esac
860
- }
861
-
862
- main "$@"