From 8269607d58b981ab95e56a26934eca19c0794966 Mon Sep 17 00:00:00 2001 From: kaihere14 Date: Mon, 27 Apr 2026 22:15:31 +0530 Subject: [PATCH 1/4] refactor: update Convex skill descriptions and prevent dev script shutdown on ngrok failure --- .../skills/convex-create-component/SKILL.md | 2 +- .../skills/convex-migration-helper/SKILL.md | 2 +- .../skills/convex-performance-audit/SKILL.md | 2 +- .agents/skills/convex-quickstart/SKILL.md | 2 +- .agents/skills/convex-setup-auth/SKILL.md | 2 +- .agents/skills/convex/SKILL.md | 2 +- package-lock.json | 88 +++++++++++++++++++ scripts/dev.mjs | 13 ++- skills-lock.json | 12 +-- 9 files changed, 112 insertions(+), 13 deletions(-) diff --git a/.agents/skills/convex-create-component/SKILL.md b/.agents/skills/convex-create-component/SKILL.md index 22af601f..64bd42f9 100644 --- a/.agents/skills/convex-create-component/SKILL.md +++ b/.agents/skills/convex-create-component/SKILL.md @@ -1,6 +1,6 @@ --- name: convex-create-component -description: Designs and builds Convex components with isolated tables, clear boundaries, and app-facing wrappers. Use this skill when creating a new Convex component, extracting reusable backend logic into a component, building a third-party integration that owns its own tables, packaging Convex functionality for reuse, or when the user mentions defineComponent, app.use, ComponentApi, ctx.runQuery/runMutation across component boundaries, or wants to separate concerns into isolated Convex modules. +description: Builds reusable Convex components with isolated tables and app-facing APIs. Use for new components, reusable backend modules, integrations, or component boundary work. --- # Convex Create Component diff --git a/.agents/skills/convex-migration-helper/SKILL.md b/.agents/skills/convex-migration-helper/SKILL.md index db36c622..4a4ed167 100644 --- a/.agents/skills/convex-migration-helper/SKILL.md +++ b/.agents/skills/convex-migration-helper/SKILL.md @@ -1,6 +1,6 @@ --- name: convex-migration-helper -description: Plans and executes safe Convex schema and data migrations using the widen-migrate-narrow workflow and the @convex-dev/migrations component. Use this skill when a deployment fails schema validation, existing documents need backfilling, fields need adding or removing or changing type, tables need splitting or merging, or a zero-downtime migration strategy is needed. Also use when the user mentions breaking schema changes, multi-deploy rollouts, or data transformations on existing Convex tables. +description: Plans Convex schema and data migrations with widen-migrate-narrow and @convex-dev/migrations. Use for breaking schema changes, backfills, table reshaping, or zero-downtime rollouts. --- # Convex Migration Helper diff --git a/.agents/skills/convex-performance-audit/SKILL.md b/.agents/skills/convex-performance-audit/SKILL.md index 382951cf..f2554dca 100644 --- a/.agents/skills/convex-performance-audit/SKILL.md +++ b/.agents/skills/convex-performance-audit/SKILL.md @@ -1,6 +1,6 @@ --- name: convex-performance-audit -description: Audits and optimizes Convex application performance across hot-path reads, write contention, subscription cost, and function limits. Use this skill when a Convex feature is slow or expensive, npx convex insights shows high bytes or documents read, OCC conflict errors or mutation retries appear, subscriptions or UI updates are costly, functions hit execution or transaction limits, or the user mentions performance, latency, read amplification, or invalidation problems in a Convex app. +description: Audits Convex performance for reads, subscriptions, write contention, and function limits. Use for slow features, insights findings, OCC conflicts, or read amplification. --- # Convex Performance Audit diff --git a/.agents/skills/convex-quickstart/SKILL.md b/.agents/skills/convex-quickstart/SKILL.md index 5bff17bc..f506b3e4 100644 --- a/.agents/skills/convex-quickstart/SKILL.md +++ b/.agents/skills/convex-quickstart/SKILL.md @@ -1,6 +1,6 @@ --- name: convex-quickstart -description: Initializes a new Convex project from scratch or adds Convex to an existing app. Use this skill when starting a new project with Convex, scaffolding with npm create convex@latest, adding Convex to an existing React, Next.js, Vue, Svelte, or other frontend, wiring up ConvexProvider, configuring environment variables for the deployment URL, or running npx convex dev for the first time, even if the user just says "set up Convex" or "add a backend." +description: Creates or adds Convex to an app. Use for new Convex projects, npm create convex@latest, frontend setup, env vars, or the first npx convex dev run. --- # Convex Quickstart diff --git a/.agents/skills/convex-setup-auth/SKILL.md b/.agents/skills/convex-setup-auth/SKILL.md index 0d1d9dd6..59a92285 100644 --- a/.agents/skills/convex-setup-auth/SKILL.md +++ b/.agents/skills/convex-setup-auth/SKILL.md @@ -1,6 +1,6 @@ --- name: convex-setup-auth -description: Sets up Convex authentication with user management, identity mapping, and access control. Use this skill when adding login or signup to a Convex app, configuring Convex Auth, Clerk, WorkOS AuthKit, Auth0, or custom JWT providers, wiring auth.config.ts, protecting queries and mutations with ctx.auth.getUserIdentity(), creating a users table with identity mapping, or setting up role-based access control, even if the user just says "add auth" or "make it require login." +description: Sets up Convex auth, identity mapping, and access control. Use for login, auth providers, users tables, protected functions, or roles in a Convex app. --- # Convex Authentication Setup diff --git a/.agents/skills/convex/SKILL.md b/.agents/skills/convex/SKILL.md index d4678270..9e8ebbd8 100644 --- a/.agents/skills/convex/SKILL.md +++ b/.agents/skills/convex/SKILL.md @@ -1,6 +1,6 @@ --- name: convex -description: Routing skill for Convex work in this repo. Use when the user explicitly invokes the `convex` skill, asks which Convex workflow or skill to use, or says they are working on a Convex app without naming a specific task yet. Do not prefer this skill when the request is clearly about setting up Convex, authentication, components, migrations, or performance. +description: Routes general Convex requests to the right project skill. Use when the user asks which Convex skill to use or gives an underspecified Convex app task. --- # Convex diff --git a/package-lock.json b/package-lock.json index 28c33860..6fa0a51e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -985,6 +985,44 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", + "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", + "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@img/sharp-linux-arm": { "version": "0.33.5", "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", @@ -1051,6 +1089,56 @@ "@img/sharp-libvips-linux-x64": "1.0.4" } }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", + "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", + "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.0.4" + } + }, "node_modules/@img/sharp-win32-x64": { "version": "0.33.5", "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", diff --git a/scripts/dev.mjs b/scripts/dev.mjs index 4696eb23..79ec7188 100644 --- a/scripts/dev.mjs +++ b/scripts/dev.mjs @@ -212,6 +212,7 @@ const debugChild = run( /Local:\s+http/, ); const children = [serverChild, convexChild, debugChild]; +const criticalChildren = [serverChild, convexChild, debugChild]; let ngrokUrlReady = Promise.resolve(null); if (useNgrok && ngrokInstalled) { @@ -220,6 +221,16 @@ if (useNgrok && ngrokInstalled) { : ["http", port, "--log=stdout", "--log-format=term", "--log-level=info"]; const ngrokChild = run("ngrok", "ngrok", args); children.push(ngrokChild); + ngrokChild.on("exit", (code) => { + if (!shuttingDown && code !== null && code !== 0) { + console.error( + `${C.ngrok}ngrok${C.reset} │ exited with code ${code}; keeping local dev services running.`, + ); + console.error( + `${C.dim} iMessage replies via Sendblue need a public tunnel. Check ngrok auth/network, set a stable PUBLIC_URL, or use npm run dev:parallel for local-only work.${C.reset}`, + ); + } + }); ngrokUrlReady = waitForNgrokUrl().catch(() => null); } @@ -299,7 +310,7 @@ const shutdown = (code = 0) => { }; process.on("SIGINT", () => shutdown(0)); process.on("SIGTERM", () => shutdown(0)); -for (const c of children) { +for (const c of criticalChildren) { c.on("exit", (code) => { if (!shuttingDown && code !== null && code !== 0) { console.error(`\nA child process exited with code ${code}. Shutting down.`); diff --git a/skills-lock.json b/skills-lock.json index bf33b964..a87a22de 100644 --- a/skills-lock.json +++ b/skills-lock.json @@ -4,32 +4,32 @@ "convex": { "source": "get-convex/agent-skills", "sourceType": "github", - "computedHash": "613ee9955985085d0fca8f96e1fc6d7cfd204dffa203499a1d508b8def76577b" + "computedHash": "70ecfb9cd4439ccbf6570b6dc23eab53f7ce7dcf70ef63bbfdf8f4f21353dfb4" }, "convex-create-component": { "source": "get-convex/agent-skills", "sourceType": "github", - "computedHash": "d110fca7f65b4919367e6fc63a93bf54abea2cf5e4e097234c947559ffa6e527" + "computedHash": "e4ad9cbe6d2bb0d5171dfd04019bc4ff228f26fb52312429376c885d2ec4935a" }, "convex-migration-helper": { "source": "get-convex/agent-skills", "sourceType": "github", - "computedHash": "46d1ac354eefbed05e1367d828e893816c13302276080bfaf6bcd828281be486" + "computedHash": "c6416032d2f2e947ebe9d6b2389d89592d0229a0e6c4202f9a1197f2bd76019f" }, "convex-performance-audit": { "source": "get-convex/agent-skills", "sourceType": "github", - "computedHash": "30ea0d3c259df011e44ea9b70502ab272f5ac3bd1fb3672ae18489ba99b2c4ae" + "computedHash": "c048b44beca5616108bfebc9822b6238cbff5c99facb88b3cf3d3a2af0dac502" }, "convex-quickstart": { "source": "get-convex/agent-skills", "sourceType": "github", - "computedHash": "8ae9e1b02f526ea65e7895fac82af74142cd8e70e364d9dae9dbf79a296fb5ef" + "computedHash": "c95728c430a441325c865b06f0f0e912923c34deecbf6f24e9f03e13046b469c" }, "convex-setup-auth": { "source": "get-convex/agent-skills", "sourceType": "github", - "computedHash": "e719d31d1ab0d19ca7b942d1154d3ff436b5c156900eea9866c2aaeb910a1388" + "computedHash": "f60559165edd5b616fda726ed5726c798e33f905361ed9892ab6013e53ab2588" } } } From 49c45a0a588cf1d2cef84b272d497fecac9bf486 Mon Sep 17 00:00:00 2001 From: kaihere14 Date: Tue, 28 Apr 2026 04:05:26 +0530 Subject: [PATCH 2/4] feat: add Docker support and configure Vite for containerized development --- .dockerignore | 25 +++++++++++++++++++++++++ Dockerfile | 30 ++++++++++++++++++++++++++++++ debug/vite.config.ts | 1 + docker-compose.yml | 38 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 docker-compose.yml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..0ecfab4e --- /dev/null +++ b/.dockerignore @@ -0,0 +1,25 @@ +node_modules +npm-debug.log* +*.log + +.git +.gitignore +.DS_Store + +.env +.env.local +.env.*.local +.convex + +dist +build +debug/dist +.vite +.cache +*.tsbuildinfo + +data +*.db +*.db-journal +*.sqlite +*.sqlite-journal diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..5c39986a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,30 @@ +FROM node:22-bookworm-slim + +WORKDIR /app + +ENV NODE_ENV=development + +RUN apt-get update \ + && apt-get install -y --no-install-recommends ca-certificates curl git gnupg \ + && curl -fsSL https://ngrok-agent.s3.amazonaws.com/ngrok.asc | tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null \ + && echo "deb https://ngrok-agent.s3.amazonaws.com buster main" | tee /etc/apt/sources.list.d/ngrok.list \ + && apt-get update \ + && apt-get install -y --no-install-recommends ngrok \ + && rm -rf /var/lib/apt/lists/* + +# Create non-root user — Claude Code blocks bypassPermissions when running as root +RUN useradd -m -u 1001 boop + +COPY package*.json ./ +RUN npm ci && npm install -g @anthropic-ai/claude-code + +COPY . . + +RUN mkdir -p /home/boop/.claude /home/boop/.convex /home/boop/.sendblue \ + && chown -R boop:boop /app /home/boop + +USER boop + +EXPOSE 3456 5173 + +CMD ["npm", "run", "dev"] diff --git a/debug/vite.config.ts b/debug/vite.config.ts index 489d57c0..cd834f63 100644 --- a/debug/vite.config.ts +++ b/debug/vite.config.ts @@ -16,6 +16,7 @@ export default defineConfig(({ mode }) => { envDir: PROJECT_ROOT, plugins: [react(), tailwindcss()], server: { + host: "0.0.0.0", port: 5173, proxy: { "/api": { diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..ecd5d91d --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,38 @@ +services: + boop: + build: + context: . + image: boop-agent:local + command: npm run dev + init: true + restart: unless-stopped + stop_signal: SIGINT + env_file: + - .env.local + environment: + NODE_ENV: development + BOOP_UPSTREAM_CHECK: "false" + ports: + - "3456:3456" + - "5173:5173" + volumes: + - .:/app + - boop_node_modules:/app/node_modules + - boop_npm_cache:/home/boop/.npm + - ${HOME}/.convex:/home/boop/.convex + - ${HOME}/.claude:/home/boop/.claude + - ${HOME}/.sendblue:/home/boop/.sendblue + healthcheck: + test: + [ + "CMD-SHELL", + "node -e \"fetch('http://127.0.0.1:3456/health').then(r => process.exit(r.ok ? 0 : 1)).catch(() => process.exit(1))\"", + ] + interval: 30s + timeout: 5s + retries: 3 + start_period: 30s + +volumes: + boop_node_modules: + boop_npm_cache: From 8dbac27fa898b5134521995b51101965a463ab82 Mon Sep 17 00:00:00 2001 From: kaihere14 Date: Tue, 28 Apr 2026 04:20:50 +0530 Subject: [PATCH 3/4] feat: enable network-accessible host in vite development server --- debug/vite.config.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/debug/vite.config.ts b/debug/vite.config.ts index cd834f63..ffe88c2e 100644 --- a/debug/vite.config.ts +++ b/debug/vite.config.ts @@ -16,7 +16,11 @@ export default defineConfig(({ mode }) => { envDir: PROJECT_ROOT, plugins: [react(), tailwindcss()], server: { +<<<<<<< Updated upstream host: "0.0.0.0", +======= + host: true, +>>>>>>> Stashed changes port: 5173, proxy: { "/api": { From d279f7d01dbc15f995032579f7e35002e066bd73 Mon Sep 17 00:00:00 2001 From: kaihere14 Date: Tue, 28 Apr 2026 04:20:55 +0530 Subject: [PATCH 4/4] refactor: set Vite dev server host to true to resolve upstream configuration conflict --- debug/vite.config.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/debug/vite.config.ts b/debug/vite.config.ts index ffe88c2e..d9e1d0e8 100644 --- a/debug/vite.config.ts +++ b/debug/vite.config.ts @@ -16,11 +16,7 @@ export default defineConfig(({ mode }) => { envDir: PROJECT_ROOT, plugins: [react(), tailwindcss()], server: { -<<<<<<< Updated upstream - host: "0.0.0.0", -======= host: true, ->>>>>>> Stashed changes port: 5173, proxy: { "/api": {