chiefwiggum 1.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.
Files changed (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +144 -0
  3. package/chiefwiggum +782 -0
  4. package/package.json +28 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Addison Kowalski
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,144 @@
1
+ # Chief Wiggum
2
+
3
+ ```
4
+ ░█▀▀░█░█░▀█▀░█▀▀░█▀▀░░░█░█░▀█▀░█▀▀░█▀▀░█░█░█▄█
5
+ ░█░░░█▀█░░█░░█▀▀░█▀▀░░░█▄█░░█░░█░█░█░█░█░█░█░█
6
+ ░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀░░░░░▀░▀░▀▀▀░▀▀▀░▀▀▀░▀▀▀░▀░▀
7
+ ```
8
+
9
+ Autonomous coding agent CLI. Point it at a plan, watch it build.
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ npx chiefwiggum@latest
15
+ ```
16
+
17
+ That's it. Now you can use `chiefwiggum` anywhere.
18
+
19
+ **Requires:** [Claude Code](https://claude.ai/code) installed and authenticated.
20
+
21
+ ## Usage
22
+
23
+ ### Interactive Setup
24
+
25
+ ```bash
26
+ cd your-project
27
+ chiefwiggum new
28
+ ```
29
+
30
+ You'll be prompted with numbered options:
31
+
32
+ ```
33
+ How would you like to set up this project?
34
+
35
+ 1) From a plan file - I have a plan.md ready
36
+ 2) Describe it - I'll tell you what to build
37
+ 3) Existing TODO - Just start the loop with current TODO.md
38
+
39
+ Enter choice [1-3]:
40
+ ```
41
+
42
+ ### From a Plan File
43
+
44
+ ```bash
45
+ chiefwiggum new plans/myplan.md
46
+ ```
47
+
48
+ Generates specs and starts building.
49
+
50
+ ### Just Run the Loop
51
+
52
+ ```bash
53
+ chiefwiggum loop
54
+ # or just
55
+ chiefwiggum
56
+ ```
57
+
58
+ Works through existing TODO.md tasks.
59
+
60
+ ### Check Status
61
+
62
+ ```bash
63
+ chiefwiggum status
64
+ ```
65
+
66
+ Shows project status and task progress.
67
+
68
+ ## What It Does
69
+
70
+ 1. **Setup** (`chiefwiggum new`)
71
+ - Interactive Q&A or use existing plan
72
+ - Generates: `specs/prd.md`, `specs/technical.md`, `CLAUDE.md`, `TODO.md`
73
+
74
+ 2. **Build Loop** (`chiefwiggum loop`)
75
+ - Picks first unchecked task from TODO.md
76
+ - Spawns Claude to implement it
77
+ - Commits changes
78
+ - Repeats until done
79
+
80
+ 3. **Guardrails**
81
+ - 3 consecutive failures → stops
82
+ - 5 cycles without commits → stops
83
+ - 60 minute timeout per task
84
+
85
+ ## Project Structure
86
+
87
+ After setup:
88
+
89
+ ```
90
+ your-project/
91
+ ├── specs/
92
+ │ ├── prd.md # Product requirements
93
+ │ └── technical.md # Technical specification
94
+ ├── CLAUDE.md # Project context for AI
95
+ ├── TODO.md # Task list (checkbox format)
96
+ └── plans/
97
+ └── plan.md # Your original plan (if provided)
98
+ ```
99
+
100
+ ## Configuration
101
+
102
+ Environment variables:
103
+
104
+ | Variable | Default | Description |
105
+ |----------|---------|-------------|
106
+ | `TODO_FILE` | `TODO.md` | Task list file |
107
+ | `ITERATION_TIMEOUT_MINUTES` | `60` | Max time per task |
108
+ | `MAX_CONSECUTIVE_FAILURES` | `3` | Failures before stopping |
109
+ | `MAX_NO_COMMIT_CYCLES` | `5` | Cycles without progress |
110
+ | `COOLDOWN_SECONDS` | `5` | Pause between tasks |
111
+
112
+ ## Requirements
113
+
114
+ - [Claude Code CLI](https://claude.ai/code) (authenticated)
115
+ - Git
116
+ - jq
117
+ - tmux (recommended for long builds)
118
+
119
+ ## Tips
120
+
121
+ - **Run in tmux**: For long builds, use `tmux` so you can detach
122
+ - **Review specs first**: After `chiefwiggum new`, review generated specs before starting loop
123
+ - **Watch the output**: Claude streams progress so you can see what it's doing
124
+ - **Check commits**: Each task should produce a commit - if not, something's wrong
125
+
126
+ ## Troubleshooting
127
+
128
+ **Loop stops with "3 consecutive failures"**
129
+ - Check `/tmp/chiefwiggum-iter*.log` for error details
130
+ - Fix the issue, then run `chiefwiggum` again
131
+
132
+ **Loop stops with "No commits for 5 cycles"**
133
+ - Tasks may be too vague or blocked
134
+ - Review TODO.md and make tasks more specific
135
+
136
+ **`jq: command not found`**
137
+ ```bash
138
+ brew install jq # macOS
139
+ sudo apt install jq # Ubuntu
140
+ ```
141
+
142
+ ## License
143
+
144
+ MIT
package/chiefwiggum ADDED
@@ -0,0 +1,782 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ ###########################################
5
+ # ░█▀▀░█░█░▀█▀░█▀▀░█▀▀░░░█░█░▀█▀░█▀▀░█▀▀░█░█░█▄█
6
+ # ░█░░░█▀█░░█░░█▀▀░█▀▀░░░█▄█░░█░░█░█░█░█░█░█░█░█
7
+ # ░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀░░░░░▀░▀░▀▀▀░▀▀▀░▀▀▀░▀▀▀░▀░▀
8
+ #
9
+ # Autonomous coding agent CLI
10
+ ###########################################
11
+
12
+ VERSION="1.0.0"
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
+ TODO_FILE="${TODO_FILE:-TODO.md}"
29
+ COOLDOWN_SECONDS="${COOLDOWN_SECONDS:-5}"
30
+
31
+ # Guardrails
32
+ ITERATION_TIMEOUT_MINUTES="${ITERATION_TIMEOUT_MINUTES:-60}"
33
+ MAX_CONSECUTIVE_FAILURES="${MAX_CONSECUTIVE_FAILURES:-3}"
34
+ MAX_NO_COMMIT_CYCLES="${MAX_NO_COMMIT_CYCLES:-5}"
35
+ MAX_CLAUDE_ATTEMPTS="${MAX_CLAUDE_ATTEMPTS:-3}"
36
+
37
+ # Claude Code reliability hardening
38
+ export CLAUDE_CODE_EXIT_AFTER_STOP_DELAY="${CLAUDE_CODE_EXIT_AFTER_STOP_DELAY:-30000}"
39
+ export NODE_OPTIONS="--unhandled-rejections=strict${NODE_OPTIONS:+ $NODE_OPTIONS}"
40
+
41
+ # =========================================
42
+ # BANNER
43
+ # =========================================
44
+ show_banner() {
45
+ echo ""
46
+ echo -e "${CYAN}░█▀▀░█░█░▀█▀░█▀▀░█▀▀░░░█░█░▀█▀░█▀▀░█▀▀░█░█░█▄█${NC}"
47
+ echo -e "${CYAN}░█░░░█▀█░░█░░█▀▀░█▀▀░░░█▄█░░█░░█░█░█░█░█░█░█░█${NC}"
48
+ echo -e "${CYAN}░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀░░░░░▀░▀░▀▀▀░▀▀▀░▀▀▀░▀▀▀░▀░▀${NC}"
49
+ echo -e "${BLUE} Autonomous Coding Agent v${VERSION}${NC}"
50
+ echo ""
51
+ }
52
+
53
+ # =========================================
54
+ # HELP
55
+ # =========================================
56
+ show_help() {
57
+ show_banner
58
+ echo "Usage: chiefwiggum [command] [options]"
59
+ echo ""
60
+ echo "Commands:"
61
+ echo " new [plan.md] Initialize project (interactive or from plan file)"
62
+ echo " loop Run the build loop on existing TODO.md"
63
+ echo " status Show current project status"
64
+ echo " help Show this help message"
65
+ echo ""
66
+ echo "Examples:"
67
+ echo " chiefwiggum new # Interactive setup"
68
+ echo " chiefwiggum new plans/myplan.md # Setup from plan file"
69
+ echo " chiefwiggum loop # Start build loop"
70
+ echo " chiefwiggum # Same as 'loop'"
71
+ echo ""
72
+ }
73
+
74
+ # =========================================
75
+ # PROMPT HELPERS
76
+ # =========================================
77
+ ask_choice() {
78
+ local prompt="$1"
79
+ shift
80
+ local options=("$@")
81
+
82
+ echo ""
83
+ echo -e "${BOLD}${prompt}${NC}"
84
+ echo ""
85
+
86
+ local i=1
87
+ for opt in "${options[@]}"; do
88
+ echo -e " ${CYAN}${i})${NC} ${opt}"
89
+ ((i++))
90
+ done
91
+ echo ""
92
+
93
+ while true; do
94
+ read -rp "Enter choice [1-${#options[@]}]: " choice
95
+ if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le "${#options[@]}" ]; then
96
+ return $((choice - 1))
97
+ fi
98
+ echo -e "${RED}Invalid choice. Please enter 1-${#options[@]}${NC}"
99
+ done
100
+ }
101
+
102
+ ask_text() {
103
+ local prompt="$1"
104
+ local default="${2:-}"
105
+
106
+ echo ""
107
+ if [ -n "$default" ]; then
108
+ read -rp "${prompt} [${default}]: " response
109
+ echo "${response:-$default}"
110
+ else
111
+ read -rp "${prompt}: " response
112
+ echo "$response"
113
+ fi
114
+ }
115
+
116
+ ask_confirm() {
117
+ local prompt="$1"
118
+ local default="${2:-y}"
119
+
120
+ if [ "$default" = "y" ]; then
121
+ read -rp "${prompt} [Y/n]: " response
122
+ [[ ! "$response" =~ ^[Nn] ]]
123
+ else
124
+ read -rp "${prompt} [y/N]: " response
125
+ [[ "$response" =~ ^[Yy] ]]
126
+ fi
127
+ }
128
+
129
+ # =========================================
130
+ # STATUS COMMAND
131
+ # =========================================
132
+ cmd_status() {
133
+ show_banner
134
+
135
+ echo -e "${BOLD}Project Status${NC}"
136
+ echo ""
137
+
138
+ # Check for key files
139
+ local has_todo=false
140
+ local has_specs=false
141
+ local has_claude_md=false
142
+
143
+ [ -f "$TODO_FILE" ] && has_todo=true
144
+ [ -d "specs" ] && has_specs=true
145
+ [ -f "CLAUDE.md" ] && has_claude_md=true
146
+
147
+ echo -e " TODO.md: $([ "$has_todo" = true ] && echo -e "${GREEN}✓${NC}" || echo -e "${RED}✗${NC}")"
148
+ echo -e " specs/: $([ "$has_specs" = true ] && echo -e "${GREEN}✓${NC}" || echo -e "${RED}✗${NC}")"
149
+ echo -e " CLAUDE.md: $([ "$has_claude_md" = true ] && echo -e "${GREEN}✓${NC}" || echo -e "${RED}✗${NC}")"
150
+ echo ""
151
+
152
+ if [ "$has_todo" = true ]; then
153
+ local total=$(grep -c "^\s*- \[" "$TODO_FILE" 2>/dev/null || echo "0")
154
+ local done=$(grep -c "^\s*- \[x\]" "$TODO_FILE" 2>/dev/null || echo "0")
155
+ local remaining=$((total - done))
156
+
157
+ echo -e "${BOLD}Tasks${NC}"
158
+ echo -e " Total: ${total}"
159
+ echo -e " Completed: ${GREEN}${done}${NC}"
160
+ echo -e " Remaining: ${YELLOW}${remaining}${NC}"
161
+ echo ""
162
+ fi
163
+
164
+ # Git status
165
+ if git rev-parse --git-dir &>/dev/null; then
166
+ local branch=$(git branch --show-current 2>/dev/null || echo "unknown")
167
+ local commits=$(git rev-list --count HEAD 2>/dev/null || echo "0")
168
+ echo -e "${BOLD}Git${NC}"
169
+ echo -e " Branch: ${branch}"
170
+ echo -e " Commits: ${commits}"
171
+ fi
172
+ echo ""
173
+ }
174
+
175
+ # =========================================
176
+ # NEW COMMAND - INTERACTIVE SETUP
177
+ # =========================================
178
+ cmd_new() {
179
+ local plan_file="${1:-}"
180
+
181
+ show_banner
182
+
183
+ echo -e "${BOLD}Project Setup${NC}"
184
+ echo ""
185
+
186
+ # Show current directory
187
+ echo -e "Working directory: ${CYAN}$(pwd)${NC}"
188
+ echo ""
189
+
190
+ if ! ask_confirm "Initialize Chief Wiggum in this directory?"; then
191
+ echo -e "${YELLOW}Aborted.${NC}"
192
+ exit 0
193
+ fi
194
+
195
+ # Check for existing files
196
+ local existing_files=()
197
+ [ -f "$TODO_FILE" ] && existing_files+=("TODO.md")
198
+ [ -d "specs" ] && existing_files+=("specs/")
199
+ [ -f "CLAUDE.md" ] && existing_files+=("CLAUDE.md")
200
+
201
+ if [ ${#existing_files[@]} -gt 0 ]; then
202
+ echo ""
203
+ echo -e "${YELLOW}Existing files found:${NC}"
204
+ for f in "${existing_files[@]}"; do
205
+ echo " - $f"
206
+ done
207
+ echo ""
208
+ if ! ask_confirm "Overwrite these files?" "n"; then
209
+ echo -e "${YELLOW}Aborted.${NC}"
210
+ exit 0
211
+ fi
212
+ fi
213
+
214
+ # If plan file provided, use it directly
215
+ if [ -n "$plan_file" ]; then
216
+ if [ ! -f "$plan_file" ]; then
217
+ echo -e "${RED}Plan file not found: ${plan_file}${NC}"
218
+ exit 1
219
+ fi
220
+ generate_from_plan "$plan_file"
221
+ start_loop
222
+ return
223
+ fi
224
+
225
+ # Interactive setup
226
+ ask_choice "How would you like to set up this project?" \
227
+ "From a plan file - I have a plan.md ready" \
228
+ "Describe it - I'll tell you what to build" \
229
+ "Existing TODO - Just start the loop with current TODO.md"
230
+ local setup_choice=$?
231
+
232
+ case $setup_choice in
233
+ 0)
234
+ # From plan file
235
+ local plan_path
236
+ plan_path=$(ask_text "Path to plan file" "plans/plan.md")
237
+ if [ ! -f "$plan_path" ]; then
238
+ echo -e "${RED}Plan file not found: ${plan_path}${NC}"
239
+ exit 1
240
+ fi
241
+ generate_from_plan "$plan_path"
242
+ ;;
243
+ 1)
244
+ # Describe project
245
+ interactive_describe
246
+ ;;
247
+ 2)
248
+ # Existing TODO
249
+ if [ ! -f "$TODO_FILE" ]; then
250
+ echo -e "${RED}No TODO.md found. Run 'chiefwiggum new' to set up first.${NC}"
251
+ exit 1
252
+ fi
253
+ ;;
254
+ esac
255
+
256
+ # Ask about starting the loop
257
+ echo ""
258
+ ask_choice "Ready to start. What would you like to do?" \
259
+ "Start the build loop now" \
260
+ "Review files first, then start manually with 'chiefwiggum loop'" \
261
+ "Exit"
262
+ local start_choice=$?
263
+
264
+ case $start_choice in
265
+ 0) start_loop ;;
266
+ 1)
267
+ echo ""
268
+ echo -e "${GREEN}Setup complete!${NC} Review your files, then run:"
269
+ echo -e " ${CYAN}chiefwiggum loop${NC}"
270
+ ;;
271
+ 2)
272
+ echo -e "${YELLOW}Exiting.${NC}"
273
+ ;;
274
+ esac
275
+ }
276
+
277
+ # =========================================
278
+ # INTERACTIVE PROJECT DESCRIPTION
279
+ # =========================================
280
+ interactive_describe() {
281
+ echo ""
282
+ echo -e "${BOLD}Tell me about your project${NC}"
283
+ echo ""
284
+
285
+ # Project name
286
+ local project_name
287
+ project_name=$(ask_text "Project name")
288
+
289
+ # Project type
290
+ ask_choice "What type of project is this?" \
291
+ "Web application (Next.js, React, etc.)" \
292
+ "API / Backend service" \
293
+ "CLI tool" \
294
+ "Library / Package" \
295
+ "Mobile app" \
296
+ "Other"
297
+ local project_type=$?
298
+ local project_type_names=("web" "api" "cli" "library" "mobile" "other")
299
+ local project_type_name="${project_type_names[$project_type]}"
300
+
301
+ # Tech stack
302
+ local tech_stack
303
+ tech_stack=$(ask_text "Tech stack (e.g., Next.js, TypeScript, Convex)")
304
+
305
+ # Description
306
+ echo ""
307
+ echo -e "${BOLD}Describe what you're building:${NC}"
308
+ echo "(Enter description, then press Enter twice to finish)"
309
+ echo ""
310
+ local description=""
311
+ local empty_lines=0
312
+ while IFS= read -r line; do
313
+ if [ -z "$line" ]; then
314
+ ((empty_lines++))
315
+ [ $empty_lines -ge 1 ] && break
316
+ else
317
+ empty_lines=0
318
+ fi
319
+ description+="$line"$'\n'
320
+ done
321
+
322
+ # Key features
323
+ echo ""
324
+ echo -e "${BOLD}List key features (one per line, empty line to finish):${NC}"
325
+ local features=""
326
+ while IFS= read -r line; do
327
+ [ -z "$line" ] && break
328
+ features+="- $line"$'\n'
329
+ done
330
+
331
+ # Generate plan content
332
+ local plan_content="# ${project_name}
333
+
334
+ ## Overview
335
+ ${description}
336
+
337
+ ## Project Type
338
+ ${project_type_name}
339
+
340
+ ## Tech Stack
341
+ ${tech_stack}
342
+
343
+ ## Key Features
344
+ ${features}
345
+ "
346
+
347
+ # Save plan
348
+ mkdir -p plans
349
+ local plan_file="plans/plan.md"
350
+ echo "$plan_content" > "$plan_file"
351
+ echo ""
352
+ echo -e "${GREEN}Plan saved to ${plan_file}${NC}"
353
+
354
+ # Generate specs from plan
355
+ generate_from_plan "$plan_file"
356
+ }
357
+
358
+ # =========================================
359
+ # GENERATE SPECS FROM PLAN
360
+ # =========================================
361
+ generate_from_plan() {
362
+ local plan_file="$1"
363
+ local plan_content
364
+ plan_content="$(cat "$plan_file")"
365
+
366
+ echo ""
367
+ echo -e "${GREEN}════════════════════════════════════════${NC}"
368
+ echo -e "${GREEN} Generating specs from: ${plan_file}${NC}"
369
+ echo -e "${GREEN}════════════════════════════════════════${NC}"
370
+
371
+ mkdir -p specs
372
+
373
+ # Step 1: Generate PRD
374
+ echo ""
375
+ echo -e "${YELLOW}[1/4] Generating specs/prd.md...${NC}"
376
+
377
+ local prd_prompt="You are generating a PRD (Product Requirements Document) from a project plan.
378
+
379
+ Here is the plan:
380
+ <plan>
381
+ ${plan_content}
382
+ </plan>
383
+
384
+ Generate a complete PRD with these sections:
385
+ - Overview
386
+ - Problem Statement
387
+ - Goals & Success Metrics
388
+ - User Stories
389
+ - Functional Requirements
390
+ - Non-Functional Requirements
391
+ - Out of Scope
392
+
393
+ Write it directly to specs/prd.md.
394
+ Do NOT ask questions — infer everything from the plan.
395
+ Be concise but comprehensive."
396
+
397
+ echo "$prd_prompt" | claude -p --dangerously-skip-permissions 2>/dev/null
398
+ echo -e "${GREEN} ✓ specs/prd.md${NC}"
399
+
400
+ # Step 2: Generate Technical Spec
401
+ echo ""
402
+ echo -e "${YELLOW}[2/4] Generating specs/technical.md...${NC}"
403
+ local prd_generated
404
+ prd_generated="$(cat specs/prd.md 2>/dev/null || echo "")"
405
+
406
+ local tech_prompt="You are generating a Technical Specification from a PRD.
407
+
408
+ Here is the PRD:
409
+ <prd>
410
+ ${prd_generated}
411
+ </prd>
412
+
413
+ Generate a complete Technical Specification with:
414
+ - Architecture Overview
415
+ - Tech Stack
416
+ - Data Model
417
+ - API Design (if applicable)
418
+ - Key Components
419
+ - Security Considerations
420
+ - Performance Considerations
421
+
422
+ Write it directly to specs/technical.md.
423
+ Do NOT ask questions — infer everything from the PRD."
424
+
425
+ echo "$tech_prompt" | claude -p --dangerously-skip-permissions 2>/dev/null
426
+ echo -e "${GREEN} ✓ specs/technical.md${NC}"
427
+
428
+ # Step 3: Generate CLAUDE.md
429
+ echo ""
430
+ echo -e "${YELLOW}[3/4] Generating CLAUDE.md...${NC}"
431
+
432
+ local claude_prompt="You are generating a CLAUDE.md file for a project.
433
+
434
+ Here is the PRD:
435
+ <prd>
436
+ ${prd_generated}
437
+ </prd>
438
+
439
+ Here is the Technical Spec:
440
+ <technical>
441
+ $(cat specs/technical.md 2>/dev/null || echo "")
442
+ </technical>
443
+
444
+ Generate a CLAUDE.md with:
445
+ - Brief project overview
446
+ - Key commands to run
447
+ - Architecture summary
448
+ - Important conventions
449
+ - Empty '## Learnings' section at the bottom
450
+
451
+ Write it directly to CLAUDE.md.
452
+ Keep it concise - this is a quick reference for AI agents."
453
+
454
+ echo "$claude_prompt" | claude -p --dangerously-skip-permissions 2>/dev/null
455
+ echo -e "${GREEN} ✓ CLAUDE.md${NC}"
456
+
457
+ # Step 4: Generate TODO
458
+ echo ""
459
+ echo -e "${YELLOW}[4/4] Generating TODO.md...${NC}"
460
+
461
+ local todo_prompt="You are generating a TODO task list from a PRD and Technical Specification.
462
+
463
+ Here is the PRD:
464
+ <prd>
465
+ ${prd_generated}
466
+ </prd>
467
+
468
+ Here is the Technical Specification:
469
+ <technical>
470
+ $(cat specs/technical.md 2>/dev/null || echo "")
471
+ </technical>
472
+
473
+ Generate a phased TODO.md with:
474
+ - Logical phases (Setup, Core Features, Polish, etc.)
475
+ - Granular tasks using checkbox format: - [ ] Task description
476
+ - Each phase ends with: - [ ] Phase review
477
+ - Tasks should be completable in 1-2 hours max
478
+
479
+ Write it directly to TODO.md.
480
+ Do NOT ask questions — infer everything from the specs."
481
+
482
+ echo "$todo_prompt" | claude -p --dangerously-skip-permissions 2>/dev/null
483
+ echo -e "${GREEN} ✓ TODO.md${NC}"
484
+
485
+ echo ""
486
+ echo -e "${GREEN}Specs generated:${NC}"
487
+ echo " - specs/prd.md"
488
+ echo " - specs/technical.md"
489
+ echo " - CLAUDE.md"
490
+ echo " - TODO.md"
491
+
492
+ # Commit specs
493
+ if git rev-parse --git-dir &>/dev/null; then
494
+ git add specs/ TODO.md CLAUDE.md 2>/dev/null || true
495
+ git commit -m "chore: generate specs from plan" 2>/dev/null || true
496
+ fi
497
+ }
498
+
499
+ # =========================================
500
+ # BUILD LOOP
501
+ # =========================================
502
+ start_loop() {
503
+ [ -f "$TODO_FILE" ] || { echo -e "${RED}Missing $TODO_FILE${NC}"; exit 1; }
504
+
505
+ local max_iterations
506
+ max_iterations=$(grep -c "\[ \]" "$TODO_FILE" 2>/dev/null) || max_iterations=0
507
+
508
+ if [ "$max_iterations" -eq 0 ]; then
509
+ echo -e "${GREEN}No unchecked tasks in $TODO_FILE. All done!${NC}"
510
+ exit 0
511
+ fi
512
+
513
+ echo ""
514
+ echo -e "${GREEN}════════════════════════════════════════${NC}"
515
+ echo -e "${GREEN} Starting Build Loop${NC}"
516
+ echo -e "${GREEN} Tasks remaining: ${max_iterations}${NC}"
517
+ echo -e "${GREEN} Timeout: ${ITERATION_TIMEOUT_MINUTES}m per task${NC}"
518
+ echo -e "${GREEN}════════════════════════════════════════${NC}"
519
+
520
+ local consecutive_failures=0
521
+ local no_commit_cycles=0
522
+ local last_commit
523
+ last_commit="$(git rev-parse HEAD 2>/dev/null || echo "none")"
524
+
525
+ for i in $(seq 1 "$max_iterations"); do
526
+ echo ""
527
+ echo -e "${YELLOW}══════════ Task $i of $max_iterations ══════════${NC}"
528
+
529
+ cleanup_stale_processes
530
+
531
+ local start_time
532
+ start_time="$(date +%s)"
533
+
534
+ set +e
535
+ run_task_iteration "$i"
536
+ local claude_exit=$?
537
+ set -e
538
+
539
+ local duration=$(($(date +%s) - start_time))
540
+ echo ""
541
+ echo -e "Completed in ${duration}s (exit: ${claude_exit})"
542
+
543
+ # Track failures
544
+ if [ "$claude_exit" -ne 0 ]; then
545
+ consecutive_failures=$((consecutive_failures + 1))
546
+ echo -e "${RED}Failure ${consecutive_failures}/${MAX_CONSECUTIVE_FAILURES}${NC}"
547
+ sleep 30
548
+ else
549
+ consecutive_failures=0
550
+ fi
551
+
552
+ # Track commits
553
+ local current_commit
554
+ current_commit="$(git rev-parse HEAD 2>/dev/null || echo "none")"
555
+ if [ "$current_commit" = "$last_commit" ]; then
556
+ if [ "$claude_exit" -eq 0 ]; then
557
+ no_commit_cycles=$((no_commit_cycles + 1))
558
+ echo -e "${YELLOW}No commit (${no_commit_cycles}/${MAX_NO_COMMIT_CYCLES})${NC}"
559
+ fi
560
+ else
561
+ no_commit_cycles=0
562
+ last_commit="$current_commit"
563
+ echo -e "${GREEN}New commit: ${current_commit:0:7}${NC}"
564
+ git push origin HEAD 2>/dev/null && echo "Pushed to origin" || true
565
+ fi
566
+
567
+ # Guardrails
568
+ if [ "$consecutive_failures" -ge "$MAX_CONSECUTIVE_FAILURES" ]; then
569
+ echo -e "${RED}Stopping: ${MAX_CONSECUTIVE_FAILURES} consecutive failures${NC}"
570
+ exit 1
571
+ fi
572
+
573
+ if [ "$no_commit_cycles" -ge "$MAX_NO_COMMIT_CYCLES" ]; then
574
+ echo -e "${RED}Stopping: No commits for ${MAX_NO_COMMIT_CYCLES} cycles${NC}"
575
+ exit 1
576
+ fi
577
+
578
+ # Check if done
579
+ if ! grep -q "\[ \]" "$TODO_FILE"; then
580
+ echo ""
581
+ echo -e "${GREEN}════════════════════════════════════════${NC}"
582
+ echo -e "${GREEN} All tasks completed!${NC}"
583
+ echo -e "${GREEN}════════════════════════════════════════${NC}"
584
+ git push origin HEAD 2>/dev/null || true
585
+ exit 0
586
+ fi
587
+
588
+ sleep "$COOLDOWN_SECONDS"
589
+ done
590
+
591
+ echo -e "${YELLOW}Reached max iterations (${max_iterations})${NC}"
592
+ git push origin HEAD 2>/dev/null || true
593
+ }
594
+
595
+ run_task_iteration() {
596
+ local iteration="$1"
597
+ local log_file="/tmp/chiefwiggum-iter${iteration}.log"
598
+
599
+ local task_prompt='You are an autonomous coding agent. Complete ONE task from TODO.md.
600
+
601
+ ## Before Starting
602
+ Read these files to understand the project:
603
+ - CLAUDE.md — Project context and conventions
604
+ - specs/prd.md — What we are building
605
+ - specs/technical.md — How we are building it
606
+ - TODO.md — Task list
607
+
608
+ ## Workflow
609
+ 1. Find the FIRST unchecked task (- [ ]) in TODO.md
610
+ 2. Plan: Understand what needs to be done
611
+ 3. Implement: Write the code
612
+ 4. Review: Verify it works
613
+ 5. Mark complete: Change - [ ] to - [x] in TODO.md
614
+ 6. Commit: git add . && git commit -m "type(scope): description"
615
+
616
+ ## Rules
617
+ - ONE task per iteration
618
+ - Follow existing code patterns
619
+ - Use conventional commits (feat, fix, docs, refactor, test, chore)
620
+ - If blocked after 3 attempts, output RALPH_BLOCKED: <reason>
621
+
622
+ ## When Done
623
+ Output: RALPH_COMPLETE
624
+ If no tasks remain: RALPH_ALL_DONE'
625
+
626
+ local claude_exit=1
627
+
628
+ for attempt in $(seq 1 "$MAX_CLAUDE_ATTEMPTS"); do
629
+ echo -e "${YELLOW}Attempt ${attempt}/${MAX_CLAUDE_ATTEMPTS}${NC}"
630
+
631
+ echo "$task_prompt" \
632
+ | timeout --kill-after=10s "${ITERATION_TIMEOUT_MINUTES}m" \
633
+ claude -p --dangerously-skip-permissions --no-session-persistence \
634
+ --verbose --output-format stream-json \
635
+ 2>&1 \
636
+ | tee "$log_file" \
637
+ | jq -r '
638
+ if .type == "assistant" then
639
+ (.message.content[]? | select(.type=="text") | .text? // empty),
640
+ (.message.content[]? | select(.type=="tool_use") | "🔧 " + .name)
641
+ elif .type == "result" then
642
+ "✅ " + (.subtype // "done")
643
+ else empty end
644
+ ' 2>/dev/null || true &
645
+ local claude_pid=$!
646
+
647
+ # Monitor for freeze
648
+ while kill -0 $claude_pid 2>/dev/null; do
649
+ if grep -q "No messages returned" "$log_file" 2>/dev/null; then
650
+ echo -e "${RED}Freeze detected, killing...${NC}"
651
+ kill -9 $claude_pid 2>/dev/null || true
652
+ sleep 2
653
+ break
654
+ fi
655
+ sleep 1
656
+ done
657
+
658
+ wait $claude_pid 2>/dev/null
659
+ claude_exit=$?
660
+
661
+ # Check for transient errors
662
+ if [ "$claude_exit" -ne 0 ]; then
663
+ if grep -qE "(No messages returned|ECONNRESET|ETIMEDOUT)" "$log_file" 2>/dev/null; then
664
+ echo -e "${YELLOW}Transient error, retrying...${NC}"
665
+ sleep $((attempt * 5))
666
+ continue
667
+ fi
668
+ fi
669
+
670
+ break
671
+ done
672
+
673
+ rm -f "$log_file"
674
+ return $claude_exit
675
+ }
676
+
677
+ cleanup_stale_processes() {
678
+ pkill -f playwright 2>/dev/null || true
679
+ pkill -f chromium 2>/dev/null || true
680
+ if command -v lsof &>/dev/null; then
681
+ lsof -ti:3000 | xargs kill -9 2>/dev/null || true
682
+ fi
683
+ sleep 1
684
+ }
685
+
686
+ # =========================================
687
+ # INSTALL COMMAND
688
+ # =========================================
689
+ cmd_install() {
690
+ show_banner
691
+
692
+ echo -e "${BOLD}Installing Chief Wiggum...${NC}"
693
+ echo ""
694
+
695
+ # Check if already installed globally
696
+ if command -v chiefwiggum &>/dev/null; then
697
+ local installed_path=$(which chiefwiggum)
698
+ if [[ "$installed_path" != *"npx"* ]] && [[ "$installed_path" != *".npm/_npx"* ]]; then
699
+ echo -e "${GREEN}✓ Already installed at: ${installed_path}${NC}"
700
+ echo ""
701
+ echo "Run 'chiefwiggum new' to get started."
702
+ return 0
703
+ fi
704
+ fi
705
+
706
+ # Install globally
707
+ echo "Running: npm install -g chiefwiggum"
708
+ echo ""
709
+
710
+ if npm install -g chiefwiggum; then
711
+ echo ""
712
+ echo -e "${GREEN}════════════════════════════════════════${NC}"
713
+ echo -e "${GREEN} ✓ Installation complete!${NC}"
714
+ echo -e "${GREEN}════════════════════════════════════════${NC}"
715
+ echo ""
716
+ echo "Get started:"
717
+ echo -e " ${CYAN}chiefwiggum new${NC} # Set up a new project"
718
+ echo -e " ${CYAN}chiefwiggum loop${NC} # Run the build loop"
719
+ echo -e " ${CYAN}chiefwiggum help${NC} # See all commands"
720
+ echo ""
721
+ else
722
+ echo ""
723
+ echo -e "${RED}Installation failed.${NC}"
724
+ echo "Try running with sudo: sudo npm install -g chiefwiggum"
725
+ exit 1
726
+ fi
727
+ }
728
+
729
+ # =========================================
730
+ # MAIN
731
+ # =========================================
732
+ main() {
733
+ local cmd="${1:-}"
734
+
735
+ case "$cmd" in
736
+ install)
737
+ cmd_install
738
+ ;;
739
+ new)
740
+ shift
741
+ cmd_new "$@"
742
+ ;;
743
+ loop)
744
+ show_banner
745
+ start_loop
746
+ ;;
747
+ status)
748
+ cmd_status
749
+ ;;
750
+ help|--help|-h)
751
+ show_help
752
+ ;;
753
+ "")
754
+ # No command: if running via npx, install. Otherwise run loop.
755
+ if [[ "${0}" == *"npx"* ]] || [[ "${0}" == *".npm/_npx"* ]]; then
756
+ cmd_install
757
+ else
758
+ show_banner
759
+ if [ -f "$TODO_FILE" ]; then
760
+ start_loop
761
+ else
762
+ echo -e "${YELLOW}No TODO.md found. Run 'chiefwiggum new' to get started.${NC}"
763
+ exit 1
764
+ fi
765
+ fi
766
+ ;;
767
+ *)
768
+ # Check if it's a file path (for backward compat with ralph.sh)
769
+ if [ -f "$cmd" ]; then
770
+ show_banner
771
+ generate_from_plan "$cmd"
772
+ start_loop
773
+ else
774
+ echo -e "${RED}Unknown command: ${cmd}${NC}"
775
+ echo "Run 'chiefwiggum help' for usage."
776
+ exit 1
777
+ fi
778
+ ;;
779
+ esac
780
+ }
781
+
782
+ main "$@"
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "chiefwiggum",
3
+ "version": "1.0.0",
4
+ "description": "Autonomous coding agent CLI. Point it at a plan, watch it build.",
5
+ "bin": {
6
+ "chiefwiggum": "./chiefwiggum"
7
+ },
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/addisonk/chief-wiggum.git"
11
+ },
12
+ "keywords": [
13
+ "cli",
14
+ "autonomous",
15
+ "coding-agent",
16
+ "claude",
17
+ "ai"
18
+ ],
19
+ "author": "Addison Kowalski",
20
+ "license": "MIT",
21
+ "bugs": {
22
+ "url": "https://github.com/addisonk/chief-wiggum/issues"
23
+ },
24
+ "homepage": "https://github.com/addisonk/chief-wiggum#readme",
25
+ "engines": {
26
+ "node": ">=18"
27
+ }
28
+ }