Skip to main content

Cloud Agent Starter Skill

Use this file when you need to run or test the repo in Cursor Cloud. It is intentionally short and practical.

Read this first

  1. Read convex/_generated/ai/guidelines.md before touching Convex code.
  2. Check existing terminal sessions before starting long-running processes so you do not duplicate bun run dev or bun run convex:dev.
  3. Use Bun for installs, dev servers, linting, and tests.

Repo-wide setup

Install and env

  • Install dependencies with bun install --frozen-lockfile when node_modules is missing or stale.
  • When secrets are injected into the shell (Cursor Cloud) but .env.local is missing, run bun run env:sync-local -- --dev to materialize the file from process.env without logging secret values. Use --force to overwrite an existing file, or --dry-run to preview which keys would be filled.
  • Start Convex with bun run convex:dev. This is the normal way to generate or refresh NEXT_PUBLIC_CONVEX_URL in .env.local.
  • Start Next.js with bun run dev.
  • bun run dev uses scripts/next-dev-with-fallback.ts, so the app may start on port 3000 through 3010. Read the server output to see which port won.
  • If both servers are not already running, bun run dev:all starts Next + Convex together. Avoid bun run dev:reset; it uses a blanket process kill pattern that Cloud agents should not rely on.

Minimum .env.local checklist

Copy values from .env.example or from the task context. The most common values agents need are:
  • NEXT_PUBLIC_CONVEX_URL
  • CONVEX_SITE_URL when HTTP actions need a non-default Convex host
  • NEXT_PUBLIC_APP_URL
  • CONVEX_INTERNAL_SECRET
  • ENCRYPTION_KEY
  • GHL_APP_CLIENT_ID
  • GHL_APP_CLIENT_SECRET
  • GHL_APP_SSO_KEY
  • GHL_API_DOMAIN
  • GHL_ADMIN_LOCATION_ID
  • CRON_SECRET
  • NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY
  • CLERK_SECRET_KEY
  • CLERK_JWT_ISSUER_DOMAIN

Fast smoke checks

  • curl http://127.0.0.1:<port>/api/auth/status should return JSON, even when unauthenticated.
  • If / does not redirect where you expect in dev, set DEV_DEFAULT_LOCATION_ID because app/page.tsx and proxy.ts both use it for localhost redirects.
  • If Convex-authenticated partner portal work is involved, remember that CLERK_JWT_ISSUER_DOMAIN must also be set in Convex with bunx convex env set CLERK_JWT_ISSUER_DOMAIN <value>.

Codebase areas

1. Main app and admin (app/(main), app/admin, components/contact, components/funding-queue)

Login and local bypass

  • These areas normally expect a Lead Built / GHL session.
  • For localhost-only Cloud testing without a real iframe session, set:
    • ALLOW_LOCAL_DEV_AUTH_BYPASS=true
    • DEV_DEFAULT_LOCATION_ID=<real location id>
  • The bypass only works in development and only for localhost requests. It is implemented in components/contact/contactLocalDevAuth.ts.
  • useAuth first checks /api/auth/status, then tries POST /api/auth/location-session, and redirects to /setup-required when the location is missing an installation.

Start and verify

  • Open /dashboard?location_id=<location> for the main app.
  • Open /admin/metrics?locationId=<location> or another admin route if you are testing admin-only behavior.
  • If the app redirects unexpectedly, inspect proxy.ts before changing auth code.

Targeted test workflow

  • Auth and routing:
    • bun test tests/adminAuth.test.ts tests/adminLocation360Auth.test.ts tests/contactRedirectDomain.test.ts
  • Processing and funding queue:
    • bun test tests/processingQueueFilters.test.ts tests/internalContactProcessingStatus.test.ts tests/fundingPlanAutosave.test.ts tests/fundingQueueBulkActions.test.ts
  • Credit reports and underwriting:
    • bun test tests/adminCreditReportQuery.test.ts tests/creditReportHistory.test.ts tests/underwriting.test.ts tests/stitchCreditReportAccountFiltering.test.ts

2. API routes and webhooks (app/api/**, lib/auth, lib/utils, proxy.ts)

Practical workflow

  • Use curl for routes that do not require a browser.
  • GET /api/auth/status is the easiest reachability check.
  • POST /api/auth/location-session is the main session bootstrap path when a location_id is available but no stored session exists yet.
  • Many API routes are blocked by the proxy unless the request has a valid session, an allowed origin, or is listed in EXEMPT_PATHS inside proxy.ts.
  • Admin endpoints also validate origin + installation + GHL_ADMIN_LOCATION_ID in lib/utils/admin-auth.ts.

Targeted test workflow

  • Auth and impersonation:
    • bun test tests/adminAuth.test.ts tests/impersonationGuards.test.ts
  • Credit pull and history paths:
    • bun test tests/creditPullContactSync.test.ts tests/creditPullNormalization.test.ts tests/creditReportErrors.test.ts tests/creditReportDownload.test.ts
  • Webhook-style behavior:
    • bun test tests/appointmentStatus.test.ts

3. Partner portal (app/partner-portal, components/partner-portal, convex/auth.config.ts)

Login and env

  • Partner portal auth is Clerk-based, not GHL SSO.
  • Required Next env:
    • NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY
    • CLERK_SECRET_KEY
  • Required Convex auth env:
    • CLERK_JWT_ISSUER_DOMAIN in .env.local
    • CLERK_JWT_ISSUER_DOMAIN in Convex via bunx convex env set CLERK_JWT_ISSUER_DOMAIN <value>
  • Public auth routes are /partner-portal/sign-in and /partner-portal/sign-up.
  • proxy.ts skips Lead Built auth for partner portal routes and lets Clerk handle them.

Targeted test workflow

  • Manual check:
    • Start bun run convex:dev and bun run dev
    • Visit /partner-portal/sign-in
    • Confirm sign-in renders instead of redirecting to the main-app SSO flow
  • Automated checks:
    • There is no clearly named partner-portal-only Bun test file today, so use the shared repo gate after portal changes:
      • bunx tsc --noEmit
      • bun run lint
      • bun test

4. Convex backend and data scripts (convex/**, scripts/**)

Practical workflow

  • Keep bun run convex:dev running while editing Convex functions.
  • If auth behavior changed for the partner portal, re-check convex/auth.config.ts and the Convex env value for CLERK_JWT_ISSUER_DOMAIN.
  • scripts/seed-cards.ts reads .env.local directly and requires NEXT_PUBLIC_CONVEX_URL plus a CSV path argument.
  • scripts/seed-demo-data.ts loads .env.local with dotenv and can use:
    • SEED_LOCATION_ID
    • SEED_ADMIN_EMAIL

Targeted test workflow

  • For shared Convex/UI behavior that already has Bun coverage:
    • bun test tests/underwriting.test.ts tests/processingSubmissionStatusBackfill.test.ts tests/operatorInvoicesReadOnly.test.ts
  • For script runs:
    • npx tsx scripts/seed-cards.ts ./data/cards.csv # seed-cards.ts expects tsx, not bun run
    • bun run scripts/seed-demo-data.ts
  • Prefer seeding only when the task needs realistic data; otherwise stick to targeted tests.

Common gotchas

  • There is no obvious central runtime feature flag system in the repo. The most useful local testing toggle is the auth bypass pair ALLOW_LOCAL_DEV_AUTH_BYPASS=true plus DEV_DEFAULT_LOCATION_ID=<id>.
  • The main app and admin expect GHL/Lead Built context; the partner portal does not.
  • The app may not use port 3000; read the dev server output before curling or opening localhost URLs.
  • If a task only changes docs or small non-runtime strings, do not start the full app just to look busy. Validate the affected commands, file references, and nearby checks instead.

Default quality gate

Use this when the area-specific tests are unclear or when you touched shared code:
  • bunx tsc --noEmit
  • bun run lint
  • bun test

How to update this skill

When you discover a useful testing trick, setup shortcut, or runbook fact:
  1. Add it to the relevant codebase-area section instead of creating a random notes dump.
  2. Prefer exact commands, routes, env vars, or file paths over prose.
  3. Delete stale steps when the repo changes; do not leave multiple conflicting workflows.
  4. If the new knowledge is required on every task, also add a one-line pointer in AGENTS.md and CLAUDE.md.