@kraftapps-ai/kai 1.7.1 → 1.8.1

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 +104 -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,47 @@ 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
+ tmux select-pane -t "${KAI_TMUX_SESSION}:0.0"
55
+ exec tmux attach-session -t "$KAI_TMUX_SESSION"
56
+ fi
57
+ fi
58
+
18
59
  PRD_FILE=".kai/stories.json"
19
60
  PROGRESS_FILE=".kai/progress.txt"
20
61
  MEMORY_FILE=".kai/memory.md"
@@ -167,6 +208,15 @@ MCPEOF
167
208
  echo " MCP servers configured in .mcp.json"
168
209
  fi
169
210
 
211
+ # ── Create loop MCP config (no Playwright) ───────────
212
+
213
+ # Worker/reviewer don't need Playwright — it spawns Chromium and causes freezes
214
+ if [ -f ".mcp.json" ]; then
215
+ jq 'del(.mcpServers.playwright)' .mcp.json > .kai/loop-mcp.json
216
+ else
217
+ echo '{"mcpServers":{}}' > .kai/loop-mcp.json
218
+ fi
219
+
170
220
  # ── Create the implementation loop script ─────────────
171
221
 
172
222
  cat > "$LOOP_SCRIPT" << 'LOOPEOF'
@@ -176,6 +226,13 @@ set -e
176
226
 
177
227
  PRD_FILE=".kai/stories.json"
178
228
  PROGRESS_FILE=".kai/progress.txt"
229
+ LOOP_MCP_ARGS="--mcp-config .kai/loop-mcp.json"
230
+
231
+ # Stream output live when running in a tmux pane
232
+ KAI_STREAM=false
233
+ if [ -n "${TMUX:-}" ]; then
234
+ KAI_STREAM=true
235
+ fi
179
236
 
180
237
  WORKER_PROMPT='You are an autonomous AI developer specializing in Shopify app and theme development.
181
238
 
@@ -268,12 +325,18 @@ while :; do
268
325
  start_time=$(date +%s)
269
326
 
270
327
  set +e
271
- result=$(claude -p --dangerously-skip-permissions --system-prompt "$WORKER_PROMPT" $context_files)
272
- exit_code=$?
328
+ if [ "$KAI_STREAM" = true ]; then
329
+ claude -p --dangerously-skip-permissions $LOOP_MCP_ARGS --system-prompt "$WORKER_PROMPT" $context_files 2>&1 | tee .kai/worker-output.tmp
330
+ exit_code=${PIPESTATUS[0]}
331
+ result=$(cat .kai/worker-output.tmp)
332
+ else
333
+ result=$(claude -p --dangerously-skip-permissions $LOOP_MCP_ARGS --system-prompt "$WORKER_PROMPT" $context_files)
334
+ exit_code=$?
335
+ echo "$result" | tail -20
336
+ fi
273
337
  set -e
274
338
 
275
339
  elapsed=$(( $(date +%s) - start_time ))
276
- echo "$result" | tail -20
277
340
 
278
341
  if [ $exit_code -ne 0 ]; then
279
342
  echo "Failed (code ${exit_code}). Restarting..."
@@ -286,14 +349,12 @@ while :; do
286
349
  fi
287
350
 
288
351
  # Review
289
- STORY_PASSES=$(jq -r ".userStories[] | select(.id == $NEXT_ID) | .passes" "$PRD_FILE")
352
+ STORY_PASSES=$(jq -r --arg id "$NEXT_ID" '.userStories[] | select(.id == $id) | .passes' "$PRD_FILE")
290
353
  if [ "$STORY_PASSES" = "true" ]; then
291
354
  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")
355
+ ACCEPTANCE=$(jq -r --arg id "$NEXT_ID" '.userStories[] | select(.id == $id) | .acceptanceCriteria | join("\n- ")' "$PRD_FILE")
293
356
 
294
- set +e
295
- review=$(claude -p --dangerously-skip-permissions \
296
- "You are a Shopify expert code reviewer. Story #${NEXT_ID} ('${NEXT}') claims complete.
357
+ REVIEW_PROMPT="You are a Shopify expert code reviewer. Story #${NEXT_ID} ('${NEXT}') claims complete.
297
358
  Last commit: ${last_commit}
298
359
  Acceptance criteria:
299
360
  - ${ACCEPTANCE}
@@ -301,19 +362,35 @@ Read git diff HEAD~1 HEAD. Verify EACH criterion. Be skeptical.
301
362
  If the story involves Shopify APIs, use introspect_graphql_schema to verify the code uses correct fields and types.
302
363
  If it involves Liquid, use validate_theme_codeblocks to check for errors.
303
364
  If ANY fails: REVIEW_FAIL: [reason]
304
- If all pass: REVIEW_PASS")
305
- set -e
365
+ If all pass: REVIEW_PASS"
306
366
 
307
- echo "$review" | tail -5
367
+ set +e
368
+ if [ "$KAI_STREAM" = true ]; then
369
+ claude -p --dangerously-skip-permissions $LOOP_MCP_ARGS "$REVIEW_PROMPT" 2>&1 | tee .kai/review-output.tmp
370
+ review=$(cat .kai/review-output.tmp)
371
+ else
372
+ review=$(claude -p --dangerously-skip-permissions $LOOP_MCP_ARGS "$REVIEW_PROMPT")
373
+ echo "$review" | tail -5
374
+ fi
375
+ set -e
308
376
 
309
377
  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"
378
+ jq --arg id "$NEXT_ID" '(.userStories[] | select(.id == $id)).passes = false' "$PRD_FILE" > "${PRD_FILE}.tmp" && mv "${PRD_FILE}.tmp" "$PRD_FILE"
311
379
  echo "REVIEW FEEDBACK: $review" >> "$PROGRESS_FILE"
312
380
  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
- }
381
+ if [ $review_failures -ge 3 ]; then
382
+ echo ""
383
+ echo "╔══════════════════════════════════════════════════╗"
384
+ echo "║ STALLED: Story #${NEXT_ID} failed review 3 times ║"
385
+ echo "╚══════════════════════════════════════════════════╝"
386
+ echo ""
387
+ echo "Review feedback:" >> "$PROGRESS_FILE"
388
+ echo "$review" >> "$PROGRESS_FILE"
389
+ echo "" >> "$PROGRESS_FILE"
390
+ echo "STALLED: Story #${NEXT_ID} failed review 3 times. Human intervention needed." >> "$PROGRESS_FILE"
391
+ echo "Loop stopped at $(date). Waiting for human intervention."
392
+ exit 1
393
+ fi
317
394
  else
318
395
  review_failures=0
319
396
  fi
@@ -365,6 +442,16 @@ dev_greeting=""
365
442
  [ -n "$dev_name" ] && dev_greeting="
366
443
  The developer's name is: ${dev_name}"
367
444
 
445
+ # ── Build loop run instructions for PM ────────────────
446
+
447
+ if [ "$KAI_TMUX" = true ] || [ -n "${TMUX:-}" ]; then
448
+ 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\`
449
+ The dev loop output streams live in the right tmux pane. You can also check \`tail -f .kai/loop.log\`.
450
+ To stop the loop: \`tmux send-keys -t ${KAI_TMUX_SESSION}:0.1 C-c\`"
451
+ else
452
+ LOOP_INSTRUCTIONS="To run implementation, execute: \`nohup .kai/loop.sh > .kai/loop.log 2>&1 &\` then monitor with \`tail -f .kai/loop.log\`"
453
+ fi
454
+
368
455
  # ── Build Claude args ─────────────────────────────────
369
456
 
370
457
  CLAUDE_ARGS="--dangerously-skip-permissions --name kai"
@@ -462,7 +549,7 @@ OAuth authentication happens automatically via browser on first use — no API k
462
549
 
463
550
  Stories live in .kai/stories.json. Each has: id, title, description, acceptanceCriteria, priority, passes (true/false).
464
551
  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\`
552
+ ${LOOP_INSTRUCTIONS}
466
553
 
467
554
  ## Browser testing (Playwright)
468
555
 
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.1",
4
4
  "description": "Autonomous AI developer loop for Claude Code",
5
5
  "bin": {
6
6
  "kai": "kai"