@kraftapps-ai/kai 1.7.1 → 1.8.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 (3) hide show
  1. package/CLAUDE.md +20 -11
  2. package/kai +105 -17
  3. package/package.json +1 -1
package/CLAUDE.md CHANGED
@@ -6,29 +6,38 @@ Autonomous AI Shopify expert, product manager, and developer loop for Claude Cod
6
6
 
7
7
  - `kai` — the entire tool; a single bash script that bootstraps the PM agent and dev loop
8
8
  - `package.json` — npm metadata and version
9
- - `.kai/PROMPT.md` — per-project context (generated at runtime, not in repo)
10
9
  - `.kai/memory.md` — persistent memory across sessions (generated at runtime, not in repo)
11
10
  - `.kai/loop.sh` — dev loop script (generated at runtime, not in repo)
11
+ - `.kai/loop-mcp.json` — MCP config without Playwright for the dev loop (generated at runtime)
12
12
 
13
13
  ## How it works
14
14
 
15
- 1. `kai` script auto-inits project files (`kai.json`, `kai-progress.txt`, `.kai/PROMPT.md`, `.kai/memory.md`)
15
+ 1. `kai` script auto-inits project files (`.kai/stories.json`, `.kai/progress.txt`, `.kai/memory.md`)
16
16
  2. Auto-installs MCP servers if not already configured:
17
- - **Playwright** — browser testing inside Shopify Admin
17
+ - **Playwright** — browser testing inside Shopify Admin (PM only, excluded from dev loop)
18
18
  - **@shopify/dev-mcp** — Shopify docs, GraphQL schema introspection, Liquid/GraphQL/component validation
19
- 3. Generates `.kai/loop.sh` (the autonomous dev loop)
20
- 4. Launches Claude with `--continue` to resume the last conversation (per-repo)
21
- 5. Falls back to `.kai/memory.md` for context if conversation history is unavailable
19
+ - **Mantle** Shopify app billing, subscriptions, analytics
20
+ 3. Generates `.kai/loop.sh` (the autonomous dev loop) and `.kai/loop-mcp.json` (MCP config without Playwright)
21
+ 4. Launches a tmux session with two panes: PM (left) and dev loop (right)
22
+ 5. Falls back to non-tmux mode if tmux is not installed or `--no-tmux` is passed
23
+
24
+ ## tmux integration
25
+
26
+ Kai runs inside a tmux session (`kai`) with two panes:
27
+ - **Pane 0 (left)** — The PM: interactive Claude session where you chat with Kai
28
+ - **Pane 1 (right)** — Dev loop: streams live output when the PM kicks off `.kai/loop.sh`
29
+
30
+ When you exit and run `kai` again, it reattaches to the existing tmux session. If the dev loop is still running in pane 1, it continues undisturbed — the PM respawns in pane 0 with full context from `.kai/memory.md`, `.kai/stories.json`, and `.kai/progress.txt`.
31
+
32
+ Use `kai --no-tmux` to skip tmux and run in the current terminal (original behavior).
22
33
 
23
34
  ## Session persistence
24
35
 
25
- Kai uses a two-layer persistence strategy:
26
- - **`claude --continue`** — resumes the exact last conversation in this directory (primary)
27
- - **`.kai/memory.md`** — Kai-maintained memory file with key decisions, current focus, and session log (fallback)
36
+ Kai uses `.kai/memory.md` to preserve context between sessions. The PM system prompt injects story status, progress log, and memory on every startup.
28
37
 
29
38
  Use `kai --new` to force a fresh conversation (memory.md is still loaded for context).
30
39
 
31
- The PM creates user stories in `kai.json`, then kicks off `.kai/loop.sh` which runs Claude in a loop — one story per iteration with self-review. Both the PM and the dev loop worker use Shopify Dev MCP tools to introspect APIs, search docs, and validate code.
40
+ The PM creates user stories in `.kai/stories.json`, then kicks off `.kai/loop.sh` which runs Claude in a loop — one story per iteration with self-review. The dev loop uses a Playwright-free MCP config (`.kai/loop-mcp.json`) to avoid spawning Chromium browsers. Only the PM uses Playwright for QA.
32
41
 
33
42
  ## MCP servers
34
43
 
@@ -46,4 +55,4 @@ Version lives in `package.json` only.
46
55
 
47
56
  ## Testing changes
48
57
 
49
- Run `./kai` in any project directory. It will auto-init if `kai.json` doesn't exist.
58
+ Run `./kai` in any project directory. It will auto-init if `.kai/stories.json` doesn't exist. Use `./kai --no-tmux` to test without tmux.
package/kai CHANGED
@@ -15,6 +15,48 @@ if [ "${1:-}" = "--version" ] || [ "${1:-}" = "-v" ]; then
15
15
  exit 0
16
16
  fi
17
17
 
18
+ # ── Parse kai flags ──────────────────────────────────
19
+
20
+ KAI_TMUX=true
21
+ PASSTHROUGH_ARGS=()
22
+ for arg in "$@"; do
23
+ case "$arg" in
24
+ --no-tmux) KAI_TMUX=false ;;
25
+ --new) PASSTHROUGH_ARGS+=("$arg") ;;
26
+ *) PASSTHROUGH_ARGS+=("$arg") ;;
27
+ esac
28
+ done
29
+ set -- "${PASSTHROUGH_ARGS[@]}"
30
+
31
+ # Fall back if tmux is not installed
32
+ if ! command -v tmux &>/dev/null; then
33
+ KAI_TMUX=false
34
+ fi
35
+
36
+ # ── tmux session management ──────────────────────────
37
+
38
+ KAI_TMUX_SESSION="kai"
39
+
40
+ if [ "$KAI_TMUX" = true ]; then
41
+ # Already inside the kai tmux session — skip setup, run PM directly
42
+ if [ -n "${TMUX:-}" ] && [ "$(tmux display-message -p '#S' 2>/dev/null)" = "$KAI_TMUX_SESSION" ]; then
43
+ : # continue to normal execution below
44
+ elif tmux has-session -t "$KAI_TMUX_SESSION" 2>/dev/null; then
45
+ # Existing session — respawn PM in pane 0, reattach
46
+ tmux respawn-pane -k -t "${KAI_TMUX_SESSION}:0.0" \
47
+ "kai --no-tmux $(printf '%q ' "$@")"
48
+ exec tmux attach-session -t "$KAI_TMUX_SESSION"
49
+ else
50
+ # New session: pane 0 = PM, pane 1 = dev loop (waiting)
51
+ tmux new-session -d -s "$KAI_TMUX_SESSION" \
52
+ "kai --no-tmux $(printf '%q ' "$@")"
53
+ tmux split-window -h -t "${KAI_TMUX_SESSION}:0" \
54
+ "echo '⏳ Dev loop pane — waiting for PM to start the loop...'; cat"
55
+ tmux select-pane -t "${KAI_TMUX_SESSION}:0.0"
56
+ exec tmux attach-session -t "$KAI_TMUX_SESSION"
57
+ fi
58
+ fi
59
+
18
60
  PRD_FILE=".kai/stories.json"
19
61
  PROGRESS_FILE=".kai/progress.txt"
20
62
  MEMORY_FILE=".kai/memory.md"
@@ -167,6 +209,15 @@ MCPEOF
167
209
  echo " MCP servers configured in .mcp.json"
168
210
  fi
169
211
 
212
+ # ── Create loop MCP config (no Playwright) ───────────
213
+
214
+ # Worker/reviewer don't need Playwright — it spawns Chromium and causes freezes
215
+ if [ -f ".mcp.json" ]; then
216
+ jq 'del(.mcpServers.playwright)' .mcp.json > .kai/loop-mcp.json
217
+ else
218
+ echo '{"mcpServers":{}}' > .kai/loop-mcp.json
219
+ fi
220
+
170
221
  # ── Create the implementation loop script ─────────────
171
222
 
172
223
  cat > "$LOOP_SCRIPT" << 'LOOPEOF'
@@ -176,6 +227,13 @@ set -e
176
227
 
177
228
  PRD_FILE=".kai/stories.json"
178
229
  PROGRESS_FILE=".kai/progress.txt"
230
+ LOOP_MCP_ARGS="--mcp-config .kai/loop-mcp.json"
231
+
232
+ # Stream output live when running in a tmux pane
233
+ KAI_STREAM=false
234
+ if [ -n "${TMUX:-}" ]; then
235
+ KAI_STREAM=true
236
+ fi
179
237
 
180
238
  WORKER_PROMPT='You are an autonomous AI developer specializing in Shopify app and theme development.
181
239
 
@@ -268,12 +326,18 @@ while :; do
268
326
  start_time=$(date +%s)
269
327
 
270
328
  set +e
271
- result=$(claude -p --dangerously-skip-permissions --system-prompt "$WORKER_PROMPT" $context_files)
272
- exit_code=$?
329
+ if [ "$KAI_STREAM" = true ]; then
330
+ claude -p --dangerously-skip-permissions $LOOP_MCP_ARGS --system-prompt "$WORKER_PROMPT" $context_files 2>&1 | tee .kai/worker-output.tmp
331
+ exit_code=${PIPESTATUS[0]}
332
+ result=$(cat .kai/worker-output.tmp)
333
+ else
334
+ result=$(claude -p --dangerously-skip-permissions $LOOP_MCP_ARGS --system-prompt "$WORKER_PROMPT" $context_files)
335
+ exit_code=$?
336
+ echo "$result" | tail -20
337
+ fi
273
338
  set -e
274
339
 
275
340
  elapsed=$(( $(date +%s) - start_time ))
276
- echo "$result" | tail -20
277
341
 
278
342
  if [ $exit_code -ne 0 ]; then
279
343
  echo "Failed (code ${exit_code}). Restarting..."
@@ -286,14 +350,12 @@ while :; do
286
350
  fi
287
351
 
288
352
  # Review
289
- STORY_PASSES=$(jq -r ".userStories[] | select(.id == $NEXT_ID) | .passes" "$PRD_FILE")
353
+ STORY_PASSES=$(jq -r --arg id "$NEXT_ID" '.userStories[] | select(.id == $id) | .passes' "$PRD_FILE")
290
354
  if [ "$STORY_PASSES" = "true" ]; then
291
355
  last_commit=$(git log --oneline -1 2>/dev/null || echo "no git")
292
- ACCEPTANCE=$(jq -r ".userStories[] | select(.id == $NEXT_ID) | .acceptanceCriteria | join(\"\n- \")" "$PRD_FILE")
356
+ ACCEPTANCE=$(jq -r --arg id "$NEXT_ID" '.userStories[] | select(.id == $id) | .acceptanceCriteria | join("\n- ")' "$PRD_FILE")
293
357
 
294
- set +e
295
- review=$(claude -p --dangerously-skip-permissions \
296
- "You are a Shopify expert code reviewer. Story #${NEXT_ID} ('${NEXT}') claims complete.
358
+ REVIEW_PROMPT="You are a Shopify expert code reviewer. Story #${NEXT_ID} ('${NEXT}') claims complete.
297
359
  Last commit: ${last_commit}
298
360
  Acceptance criteria:
299
361
  - ${ACCEPTANCE}
@@ -301,19 +363,35 @@ Read git diff HEAD~1 HEAD. Verify EACH criterion. Be skeptical.
301
363
  If the story involves Shopify APIs, use introspect_graphql_schema to verify the code uses correct fields and types.
302
364
  If it involves Liquid, use validate_theme_codeblocks to check for errors.
303
365
  If ANY fails: REVIEW_FAIL: [reason]
304
- If all pass: REVIEW_PASS")
305
- set -e
366
+ If all pass: REVIEW_PASS"
306
367
 
307
- echo "$review" | tail -5
368
+ set +e
369
+ if [ "$KAI_STREAM" = true ]; then
370
+ claude -p --dangerously-skip-permissions $LOOP_MCP_ARGS "$REVIEW_PROMPT" 2>&1 | tee .kai/review-output.tmp
371
+ review=$(cat .kai/review-output.tmp)
372
+ else
373
+ review=$(claude -p --dangerously-skip-permissions $LOOP_MCP_ARGS "$REVIEW_PROMPT")
374
+ echo "$review" | tail -5
375
+ fi
376
+ set -e
308
377
 
309
378
  if [[ "$review" == *"REVIEW_FAIL"* ]]; then
310
- jq --argjson id "$NEXT_ID" '(.userStories[] | select(.id == $id)).passes = false' "$PRD_FILE" > "${PRD_FILE}.tmp" && mv "${PRD_FILE}.tmp" "$PRD_FILE"
379
+ jq --arg id "$NEXT_ID" '(.userStories[] | select(.id == $id)).passes = false' "$PRD_FILE" > "${PRD_FILE}.tmp" && mv "${PRD_FILE}.tmp" "$PRD_FILE"
311
380
  echo "REVIEW FEEDBACK: $review" >> "$PROGRESS_FILE"
312
381
  review_failures=$((review_failures + 1))
313
- [ $review_failures -ge 3 ] && {
314
- jq --argjson id "$NEXT_ID" '(.userStories[] | select(.id == $id)).passes = true' "$PRD_FILE" > "${PRD_FILE}.tmp" && mv "${PRD_FILE}.tmp" "$PRD_FILE"
315
- review_failures=0
316
- }
382
+ if [ $review_failures -ge 3 ]; then
383
+ echo ""
384
+ echo "╔══════════════════════════════════════════════════╗"
385
+ echo "║ STALLED: Story #${NEXT_ID} failed review 3 times ║"
386
+ echo "╚══════════════════════════════════════════════════╝"
387
+ echo ""
388
+ echo "Review feedback:" >> "$PROGRESS_FILE"
389
+ echo "$review" >> "$PROGRESS_FILE"
390
+ echo "" >> "$PROGRESS_FILE"
391
+ echo "STALLED: Story #${NEXT_ID} failed review 3 times. Human intervention needed." >> "$PROGRESS_FILE"
392
+ echo "Loop stopped at $(date). Waiting for human intervention."
393
+ exit 1
394
+ fi
317
395
  else
318
396
  review_failures=0
319
397
  fi
@@ -365,6 +443,16 @@ dev_greeting=""
365
443
  [ -n "$dev_name" ] && dev_greeting="
366
444
  The developer's name is: ${dev_name}"
367
445
 
446
+ # ── Build loop run instructions for PM ────────────────
447
+
448
+ if [ "$KAI_TMUX" = true ] || [ -n "${TMUX:-}" ]; then
449
+ LOOP_INSTRUCTIONS="To run implementation, execute: \`tmux send-keys -t ${KAI_TMUX_SESSION}:0.1 '.kai/loop.sh 2>&1 | tee .kai/loop.log' Enter\`
450
+ The dev loop output streams live in the right tmux pane. You can also check \`tail -f .kai/loop.log\`.
451
+ To stop the loop: \`tmux send-keys -t ${KAI_TMUX_SESSION}:0.1 C-c\`"
452
+ else
453
+ LOOP_INSTRUCTIONS="To run implementation, execute: \`nohup .kai/loop.sh > .kai/loop.log 2>&1 &\` then monitor with \`tail -f .kai/loop.log\`"
454
+ fi
455
+
368
456
  # ── Build Claude args ─────────────────────────────────
369
457
 
370
458
  CLAUDE_ARGS="--dangerously-skip-permissions --name kai"
@@ -462,7 +550,7 @@ OAuth authentication happens automatically via browser on first use — no API k
462
550
 
463
551
  Stories live in .kai/stories.json. Each has: id, title, description, acceptanceCriteria, priority, passes (true/false).
464
552
  To add stories, edit .kai/stories.json directly using the Edit or Write tool.
465
- To run implementation, execute: \`nohup .kai/loop.sh > .kai/loop.log 2>&1 &\` then monitor with \`tail -f .kai/loop.log\`
553
+ ${LOOP_INSTRUCTIONS}
466
554
 
467
555
  ## Browser testing (Playwright)
468
556
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kraftapps-ai/kai",
3
- "version": "1.7.1",
3
+ "version": "1.8.0",
4
4
  "description": "Autonomous AI developer loop for Claude Code",
5
5
  "bin": {
6
6
  "kai": "kai"