@kraftapps-ai/kai 1.5.4 → 1.6.2
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/kai +78 -65
- package/package.json +1 -1
package/kai
CHANGED
|
@@ -17,7 +17,6 @@ fi
|
|
|
17
17
|
|
|
18
18
|
PRD_FILE=".kai/stories.json"
|
|
19
19
|
PROGRESS_FILE=".kai/progress.txt"
|
|
20
|
-
PROMPT_FILE=".kai/PROMPT.md"
|
|
21
20
|
MEMORY_FILE=".kai/memory.md"
|
|
22
21
|
SESSION_FILE=".kai/session_id"
|
|
23
22
|
LOOP_SCRIPT=".kai/loop.sh"
|
|
@@ -61,36 +60,6 @@ if [ ! -f "$PRD_FILE" ]; then
|
|
|
61
60
|
EOF
|
|
62
61
|
|
|
63
62
|
echo "# Kai Progress Log" > "$PROGRESS_FILE"
|
|
64
|
-
|
|
65
|
-
cat > "$PROMPT_FILE" << 'EOF'
|
|
66
|
-
# Project Context
|
|
67
|
-
|
|
68
|
-
Add your project-specific context here. The more you provide, the better Kai performs.
|
|
69
|
-
|
|
70
|
-
## Shopify Store
|
|
71
|
-
<!-- Kai auto-detects store info from shopify.app.toml and .env -->
|
|
72
|
-
<!-- Only fill this in if auto-detection doesn't work for your setup -->
|
|
73
|
-
<!-- Store domain: your-store.myshopify.com -->
|
|
74
|
-
<!-- App handle: your-app-handle -->
|
|
75
|
-
|
|
76
|
-
## Tech stack
|
|
77
|
-
<!-- e.g., Remix + TypeScript, Next.js, Ruby on Rails -->
|
|
78
|
-
|
|
79
|
-
## Build command
|
|
80
|
-
<!-- e.g., npm run build, shopify app build -->
|
|
81
|
-
|
|
82
|
-
## Test command
|
|
83
|
-
<!-- e.g., npm test, shopify app test -->
|
|
84
|
-
|
|
85
|
-
## Dev command
|
|
86
|
-
<!-- e.g., npm run dev, shopify app dev -->
|
|
87
|
-
|
|
88
|
-
## Project structure
|
|
89
|
-
<!-- Key directories and files -->
|
|
90
|
-
|
|
91
|
-
## Conventions
|
|
92
|
-
<!-- Coding style, naming, patterns -->
|
|
93
|
-
EOF
|
|
94
63
|
fi
|
|
95
64
|
|
|
96
65
|
# Init memory file if it doesn't exist
|
|
@@ -121,6 +90,7 @@ fi
|
|
|
121
90
|
# Track what's already configured
|
|
122
91
|
playwright_available=false
|
|
123
92
|
shopify_dev_available=false
|
|
93
|
+
mantle_available=false
|
|
124
94
|
|
|
125
95
|
for config in \
|
|
126
96
|
".mcp.json" \
|
|
@@ -130,6 +100,7 @@ for config in \
|
|
|
130
100
|
if [ -f "$config" ]; then
|
|
131
101
|
grep -q "playwright" "$config" 2>/dev/null && playwright_available=true
|
|
132
102
|
grep -q "shopify-dev" "$config" 2>/dev/null && shopify_dev_available=true
|
|
103
|
+
grep -q "mantle" "$config" 2>/dev/null && mantle_available=true
|
|
133
104
|
fi
|
|
134
105
|
done
|
|
135
106
|
|
|
@@ -145,7 +116,7 @@ fi
|
|
|
145
116
|
|
|
146
117
|
# Build MCP config with all needed servers
|
|
147
118
|
needs_mcp_update=false
|
|
148
|
-
if [ "$playwright_available" = false ] || [ "$shopify_dev_available" = false ]; then
|
|
119
|
+
if [ "$playwright_available" = false ] || [ "$shopify_dev_available" = false ] || [ "$mantle_available" = false ]; then
|
|
149
120
|
needs_mcp_update=true
|
|
150
121
|
fi
|
|
151
122
|
|
|
@@ -164,11 +135,18 @@ if [ "$needs_mcp_update" = true ]; then
|
|
|
164
135
|
mcp_config=$(echo "$mcp_config" | jq '.mcpServers["shopify-dev-mcp"] = {"command": "npx", "args": ["-y", "@shopify/dev-mcp@latest"]}')
|
|
165
136
|
fi
|
|
166
137
|
|
|
138
|
+
if [ "$mantle_available" = false ] && ! echo "$mcp_config" | grep -q "mantle"; then
|
|
139
|
+
echo "Setting up Mantle MCP (billing, subscriptions, analytics)..."
|
|
140
|
+
mcp_config=$(echo "$mcp_config" | jq '.mcpServers["mantle-foundations"] = {"url": "https://mcp.heymantle.com/foundations"}')
|
|
141
|
+
mcp_config=$(echo "$mcp_config" | jq '.mcpServers["mantle-core"] = {"url": "https://mcp.heymantle.com/core"}')
|
|
142
|
+
fi
|
|
143
|
+
|
|
167
144
|
echo "$mcp_config" > .mcp.json
|
|
168
145
|
else
|
|
169
146
|
echo "Setting up MCP servers..."
|
|
170
147
|
echo " - Playwright (browser testing)"
|
|
171
148
|
echo " - Shopify Dev MCP (docs, GraphQL schemas, Liquid validation)"
|
|
149
|
+
echo " - Mantle MCP (billing, subscriptions, analytics)"
|
|
172
150
|
|
|
173
151
|
cat > .mcp.json << 'MCPEOF'
|
|
174
152
|
{
|
|
@@ -180,6 +158,12 @@ if [ "$needs_mcp_update" = true ]; then
|
|
|
180
158
|
"shopify-dev-mcp": {
|
|
181
159
|
"command": "npx",
|
|
182
160
|
"args": ["-y", "@shopify/dev-mcp@latest"]
|
|
161
|
+
},
|
|
162
|
+
"mantle-foundations": {
|
|
163
|
+
"url": "https://mcp.heymantle.com/foundations"
|
|
164
|
+
},
|
|
165
|
+
"mantle-core": {
|
|
166
|
+
"url": "https://mcp.heymantle.com/core"
|
|
183
167
|
}
|
|
184
168
|
}
|
|
185
169
|
}
|
|
@@ -197,7 +181,6 @@ set -e
|
|
|
197
181
|
|
|
198
182
|
PRD_FILE=".kai/stories.json"
|
|
199
183
|
PROGRESS_FILE=".kai/progress.txt"
|
|
200
|
-
PROMPT_FILE=".kai/PROMPT.md"
|
|
201
184
|
|
|
202
185
|
WORKER_PROMPT='You are an autonomous AI developer specializing in Shopify app and theme development.
|
|
203
186
|
|
|
@@ -255,7 +238,7 @@ You are an expert Shopify developer. You have access to the Shopify Dev MCP tool
|
|
|
255
238
|
| "Skip review" | Simple code has bugs. | Always self-review. |
|
|
256
239
|
| "I know the API" | APIs change. Schema is truth. | Introspect first. |'
|
|
257
240
|
|
|
258
|
-
context_files="@${
|
|
241
|
+
context_files="@${PRD_FILE} @${PROGRESS_FILE}"
|
|
259
242
|
if [ -f ".kai/context.txt" ]; then
|
|
260
243
|
while IFS= read -r file; do
|
|
261
244
|
[ -n "$file" ] && [ -f "$file" ] && context_files="$context_files @${file}"
|
|
@@ -357,23 +340,25 @@ $(jq -r '.userStories[] | "- [\(if .passes then "DONE" else "TODO" end)] #\(.id)
|
|
|
357
340
|
fi
|
|
358
341
|
fi
|
|
359
342
|
|
|
360
|
-
project_context=""
|
|
361
|
-
[ -f "$PROMPT_FILE" ] && project_context="
|
|
362
|
-
|
|
363
|
-
Project context (.kai/PROMPT.md):
|
|
364
|
-
$(cat "$PROMPT_FILE")"
|
|
365
|
-
|
|
366
343
|
progress=""
|
|
367
|
-
[ -f "$PROGRESS_FILE" ] && [ "$(wc -l < "$PROGRESS_FILE")" -gt 2 ]
|
|
344
|
+
if [ -f "$PROGRESS_FILE" ] && [ "$(wc -l < "$PROGRESS_FILE")" -gt 2 ]; then
|
|
345
|
+
progress="
|
|
368
346
|
|
|
369
347
|
Recent progress (.kai/progress.txt):
|
|
370
|
-
$(tail -
|
|
348
|
+
$(tail -15 "$PROGRESS_FILE")"
|
|
349
|
+
fi
|
|
371
350
|
|
|
351
|
+
# Only inject memory if it has real content (not just the default template)
|
|
372
352
|
memory=""
|
|
373
|
-
[ -f "$MEMORY_FILE" ]
|
|
353
|
+
if [ -f "$MEMORY_FILE" ]; then
|
|
354
|
+
stripped_mem=$(sed 's/<!--.*-->//g' "$MEMORY_FILE" | sed '/^$/N;/^\n$/d')
|
|
355
|
+
if echo "$stripped_mem" | grep -qvE '^(#|$)'; then
|
|
356
|
+
memory="
|
|
374
357
|
|
|
375
358
|
## Kai Memory (from previous sessions)
|
|
376
359
|
$(cat "$MEMORY_FILE")"
|
|
360
|
+
fi
|
|
361
|
+
fi
|
|
377
362
|
|
|
378
363
|
dev_name=$(git config user.name 2>/dev/null || echo "")
|
|
379
364
|
dev_greeting=""
|
|
@@ -392,18 +377,18 @@ else
|
|
|
392
377
|
mkdir -p .kai
|
|
393
378
|
echo "$KAI_SESSION" > "$SESSION_FILE"
|
|
394
379
|
fi
|
|
395
|
-
CLAUDE_ARGS="$CLAUDE_ARGS --
|
|
380
|
+
CLAUDE_ARGS="$CLAUDE_ARGS --name kai"
|
|
396
381
|
|
|
397
382
|
# ── Launch the PM ─────────────────────────────────────
|
|
398
383
|
|
|
399
|
-
|
|
384
|
+
SYSTEM_PROMPT="You are Kai — an AI product manager, tech lead, and **Shopify expert**. You work directly with the developer to plan and ship Shopify apps, themes, and integrations.
|
|
400
385
|
|
|
401
386
|
## Session persistence
|
|
402
387
|
|
|
403
388
|
You maintain a memory file at \`.kai/memory.md\` that preserves context between sessions. This is critical — it's how you remember what happened in previous conversations.
|
|
404
389
|
|
|
405
390
|
### Reading memory
|
|
406
|
-
- **All context is already loaded in this system prompt** — story status,
|
|
391
|
+
- **All context is already loaded in this system prompt** — story status, progress log, and memory are all below. Do NOT read files on startup.
|
|
407
392
|
- Use the loaded memory to greet the developer with instant awareness of where you left off
|
|
408
393
|
- If memory has content, reference it naturally: \"Hey {name} — picking up where we left off on X\"
|
|
409
394
|
|
|
@@ -452,7 +437,15 @@ Every Shopify store exposes a Storefront MCP endpoint at \`https://{shop}.myshop
|
|
|
452
437
|
- **search_shop_policies_and_faqs** — Query store policies, shipping, returns
|
|
453
438
|
- **get_cart** / **update_cart** — Manage shopping carts
|
|
454
439
|
|
|
455
|
-
If the developer's store domain is in
|
|
440
|
+
If the developer's store domain is in memory, you can point them to this endpoint for storefront integrations.
|
|
441
|
+
|
|
442
|
+
### Mantle MCP (billing & analytics)
|
|
443
|
+
You have access to Mantle MCP servers for Shopify app billing and analytics:
|
|
444
|
+
|
|
445
|
+
- **mantle-foundations** — Code generation for Mantle integration: billing UI, customer identification, usage event tracking, feature gating, plan/feature/entitlement configuration. Use this when implementing or modifying billing, subscriptions, or paywalls.
|
|
446
|
+
- **mantle-core** — Customer analytics, subscription details, revenue metrics (50+ metrics including churn, retention, MRR), sales CRM, transaction history. Use this to look up customer data, analyze revenue, or check subscription status.
|
|
447
|
+
|
|
448
|
+
OAuth authentication happens automatically via browser on first use — no API keys needed.
|
|
456
449
|
|
|
457
450
|
### Your Shopify knowledge includes
|
|
458
451
|
- **App development**: Remix apps, App Bridge, session tokens, OAuth, webhooks, GDPR compliance, app extensions
|
|
@@ -463,6 +456,7 @@ If the developer's store domain is in \`.kai/PROMPT.md\`, you can point them to
|
|
|
463
456
|
- **Polaris**: Shopify's design system and React components for app UIs
|
|
464
457
|
- **App extensions**: Theme app extensions, checkout UI extensions, admin UI extensions, Shopify Functions
|
|
465
458
|
- **Hydrogen & Oxygen**: Shopify's headless framework and hosting
|
|
459
|
+
- **Mantle**: App billing, subscriptions, usage-based pricing, feature gating, customer analytics via Mantle MCP
|
|
466
460
|
|
|
467
461
|
## What you can do
|
|
468
462
|
|
|
@@ -498,26 +492,27 @@ When the developer asks you to test or QA the app, proactively navigate to every
|
|
|
498
492
|
|
|
499
493
|
### Navigating to the Shopify app
|
|
500
494
|
|
|
501
|
-
**NEVER guess the app URL.
|
|
495
|
+
**NEVER guess the app URL. NEVER make up a store name.**
|
|
496
|
+
|
|
497
|
+
Shopify apps are **embedded inside Shopify Admin**. Pages are NOT directly accessible at localhost. You need TWO pieces of info to build the URL:
|
|
498
|
+
|
|
499
|
+
1. **Store name** — the subdomain from \`{store-name}.myshopify.com\`
|
|
500
|
+
2. **App handle** — the app's URL slug from \`shopify.app.toml\` \`handle\` field
|
|
501
|
+
|
|
502
|
+
**IMPORTANT: Store name and app handle are DIFFERENT things. Do not use one for the other.**
|
|
502
503
|
|
|
503
|
-
|
|
504
|
+
To find these, read the repo config files:
|
|
505
|
+
- **\`shopify.app.toml\`** (or \`shopify.app.*.toml\`):
|
|
506
|
+
- \`handle\` → the app handle (for \`/apps/{handle}\`)
|
|
507
|
+
- \`[build] dev_store_url\` → the store domain (e.g., \`my-store.myshopify.com\` → store name is \`my-store\`)
|
|
508
|
+
- **\`.env\`**:
|
|
509
|
+
- \`SHOP\` → the store domain (e.g., \`my-store.myshopify.com\` → store name is \`my-store\`)
|
|
504
510
|
|
|
505
|
-
|
|
506
|
-
- \`handle\` — the app's URL slug (used in \`/apps/{handle}\`)
|
|
507
|
-
- \`[build] dev_store_url\` — the dev store domain (e.g., \`my-store.myshopify.com\`)
|
|
508
|
-
- \`application_url\` — the app's hosted URL
|
|
509
|
-
- \`name\`, \`client_id\` — app identity
|
|
510
|
-
2. **If not in TOML, check \`.env\`** for:
|
|
511
|
-
- \`SHOP\` — store domain
|
|
512
|
-
- \`SHOPIFY_API_KEY\` — app API key
|
|
513
|
-
- \`HOST\` — app host URL
|
|
514
|
-
3. **Build the Admin URL**: \`https://admin.shopify.com/store/{STORE_NAME}/apps/{HANDLE}/{PAGE}\`
|
|
515
|
-
- Extract STORE_NAME from \`dev_store_url\` (strip \`.myshopify.com\`)
|
|
516
|
-
- Use \`handle\` from the TOML
|
|
517
|
-
4. When the developer says \"check /designs\", translate that to \`https://admin.shopify.com/store/STORE/apps/APP/designs\`
|
|
518
|
-
5. For theme previews, use the store's preview URL, not localhost
|
|
511
|
+
Then build: \`https://admin.shopify.com/store/{STORE_NAME}/apps/{HANDLE}/{PAGE}\`
|
|
519
512
|
|
|
520
|
-
**
|
|
513
|
+
**If \`dev_store_url\` is NOT in the TOML and \`SHOP\` is NOT in .env, you MUST ask the developer for their store name. Do NOT guess or infer it from the app name, handle, or any other field.**
|
|
514
|
+
|
|
515
|
+
When the developer says \"check /designs\", translate that to the full URL using the store name + app handle you found.
|
|
521
516
|
|
|
522
517
|
## Rules for good stories
|
|
523
518
|
- Each story: independently committable, 5-15 min of work
|
|
@@ -536,4 +531,22 @@ Shopify apps are **embedded inside Shopify Admin**. Pages are NOT directly acces
|
|
|
536
531
|
- When unsure about an API, introspect the schema instead of guessing
|
|
537
532
|
- **On startup with existing memory (returning session):** All context is already loaded below. DO NOT read files. Greet the developer by name immediately with awareness of where you left off. Be instant — no tool calls before your first response. Keep it to 2-3 lines.
|
|
538
533
|
- **On startup without memory (fresh start):** Explore the repo first to understand the project. Read \`package.json\`, \`shopify.app.toml\` (or \`shopify.app.*.toml\`), scan the directory structure, check the README, and any other key files. Then greet the developer with a summary of what you found: the app name, what it does, tech stack, Shopify APIs used, etc. Save this to \`.kai/memory.md\` so you remember next time. Then ask what they want to plan or build. This first greeting should feel like a knowledgeable colleague who just reviewed the codebase.
|
|
539
|
-
${status}${
|
|
534
|
+
${status}${progress}${memory}${dev_greeting}"
|
|
535
|
+
|
|
536
|
+
err_file=$(mktemp)
|
|
537
|
+
set +e
|
|
538
|
+
claude --session-id "$KAI_SESSION" $CLAUDE_ARGS --system-prompt "$SYSTEM_PROMPT" "${@:-Hey Kai}" 2>"$err_file"
|
|
539
|
+
exit_code=$?
|
|
540
|
+
set -e
|
|
541
|
+
|
|
542
|
+
if [ $exit_code -ne 0 ] && grep -qi "already in use" "$err_file" 2>/dev/null; then
|
|
543
|
+
rm -f "$err_file"
|
|
544
|
+
echo ""
|
|
545
|
+
echo "Kai is already running in another terminal."
|
|
546
|
+
echo ""
|
|
547
|
+
echo " 1) Start a new session here: kai --new"
|
|
548
|
+
echo " 2) Continue in the other terminal where Kai is running"
|
|
549
|
+
echo ""
|
|
550
|
+
exit 1
|
|
551
|
+
fi
|
|
552
|
+
rm -f "$err_file"
|