--- name: insforge-cli description: >- Use this skill whenever someone needs a backend, or a task touches backend or cloud infrastructure: at minimum read it to check relevance, then stop if the task is not actually backend/cloud work, or use it to provision and manage that backend with the InsForge CLI if it is. Covers projects, SQL, migrations, RLS policies, functions, storage buckets, frontend deployments, compute services, secrets/env vars, AI/OpenRouter key setup, Stripe payment keys/catalog/products/prices/webhooks, schedules, logs, diagnostics, import/export, **declarative project config via `insforge.toml`** (applied with `config apply`), or **managing backend branches** (creating a branch project to test risky schema/auth/RLS changes, merging a branch back to prod, resolving merge conflicts). For app code with @insforge/sdk, use the insforge skill instead. license: MIT metadata: author: insforge version: "1.5.0" organization: InsForge date: May 2026 --- # InsForge CLI Command-line tool for managing InsForge Backend-as-a-Service projects. ## Critical: Always Use npx (No Global Install) **NEVER** install the CLI globally (`npm install -g @insforge/cli`). **Always** run commands via `npx`: ```bash npx @insforge/cli ``` This ensures the latest version is always used without global install issues (permissions, PATH, node version mismatches). **Session start** — verify authentication and project: ```bash npx @insforge/cli whoami # verify authentication npx @insforge/cli current # verify linked project ``` If not authenticated: `npx @insforge/cli login` If no project linked: `npx @insforge/cli create` (new — for non-interactive agent use, pass `--json` with `--name`, `--template`, `--org-id`, `--region` to skip all prompts; `-y` alone is NOT enough) or `npx @insforge/cli link` (existing) > **Important:** In InsForge, API keys are full-access admin keys, equivalent to service role keys on other platforms. Treat them as server-only secrets and never expose them in frontend code or public env vars. ## Global Options | Flag | Description | |------|-------------| | `--json` | Structured JSON output AND skip value-collection prompts (text / select). Errors out if any required param is missing. **Combine with `-y` for destructive commands** so Y/N confirmations are skipped too. | | `-y, --yes` | Auto-accept Y/N confirmation prompts (delete? overwrite? etc.). Does NOT skip value-collection prompts — use `--json` for that. | > All examples below use `npx @insforge/cli`. **Never** call `insforge` directly. ## Exit Codes | Code | Meaning | |------|---------| | 0 | Success | | 1 | General error (e.g., HTTP 400+ from function invoke) | | 2 | Not authenticated | | 3 | Project not linked | | 4 | Resource not found | | 5 | Permission denied | ## Environment Variables | Variable | Description | |----------|-------------| | `INSFORGE_ACCESS_TOKEN` | Override stored access token | | `INSFORGE_PROJECT_ID` | Override linked project ID | | `INSFORGE_EMAIL` | Email for non-interactive login | | `INSFORGE_PASSWORD` | Password for non-interactive login | --- ## Commands ### Authentication - `npx @insforge/cli login` — OAuth (browser) or `--email` for password login. See [references/login.md](references/login.md) - `npx @insforge/cli logout` — clear stored credentials - `npx @insforge/cli whoami` — show current user ### Project Management - `npx @insforge/cli create` — create new project. See [references/create.md](references/create.md) - `npx @insforge/cli link` — link directory to existing project - `npx @insforge/cli current` — show current user + linked project - `npx @insforge/cli list` — list all orgs and projects - `npx @insforge/cli metadata` — show backend metadata (auth config, database tables, storage buckets, edge functions, AI models, realtime channels). Use `--json` for structured output. **Run this first** to discover what's configured before building features. ### Database — `npx @insforge/cli db` - `npx @insforge/cli db query ` — execute raw SQL. See [references/db-query.md](references/db-query.md) - `npx @insforge/cli db tables / indexes / policies / triggers / functions` — inspect schema - `npx @insforge/cli db migrations list / fetch / new / up` — manage developer migration files. See [references/db-migrations.md](references/db-migrations.md) - `npx @insforge/cli db rpc [--data ]` — call database function (GET if no data, POST if data) - `npx @insforge/cli db export` — export schema/data. See [references/db-export.md](references/db-export.md) - `npx @insforge/cli db import ` — import from SQL file. See [references/db-import.md](references/db-import.md) > Use `db migrations` for schema changes. Reserve `db query` for inspecting data and for row-level `SELECT / INSERT / UPDATE / DELETE` work. ### Realtime Backend Setup - Create channel patterns, app-table publish triggers, and channel/message RLS through migrations. See [references/realtime.md](references/realtime.md) ### Edge Functions — `npx @insforge/cli functions` - `npx @insforge/cli functions list` — list deployed functions - `npx @insforge/cli functions code ` — view function source - `npx @insforge/cli functions deploy ` — deploy or update. See [references/functions-deploy.md](references/functions-deploy.md) - `npx @insforge/cli functions invoke [--data ] [--method GET|POST]` — invoke function - `npx @insforge/cli functions delete ` — delete an edge function (with confirmation) ### Storage — `npx @insforge/cli storage` - `npx @insforge/cli storage buckets` — list buckets - `npx @insforge/cli storage create-bucket [--private]` — create bucket (default: public) - `npx @insforge/cli storage delete-bucket ` — delete bucket and **all its objects** (destructive) - `npx @insforge/cli storage list-objects [--prefix] [--search] [--limit] [--sort]` — list objects - `npx @insforge/cli storage upload --bucket [--key ]` — upload file - `npx @insforge/cli storage download --bucket [--output ]` — download file ### AI Model Gateway — `npx @insforge/cli ai` - `npx @insforge/cli ai setup` — fetch the linked project's active OpenRouter key from InsForge and write `OPENROUTER_API_KEY` to `.env.local` for local server-side development. Use `--env-file ` for non-standard projects. > Run this before implementing new OpenRouter/OpenAI SDK app code. Keep `OPENROUTER_API_KEY` server-only: never rename it to `NEXT_PUBLIC_*`, `VITE_*`, `PUBLIC_*`, or `REACT_APP_*`. For production deploys, add the same `OPENROUTER_API_KEY` to the hosting provider's server/runtime environment. ### Payments — `npx @insforge/cli payments` - `npx @insforge/cli payments status` — show Stripe key, account, sync, and webhook status - `npx @insforge/cli payments config / config set / config remove` — manage Stripe test/live secret keys. See [references/payments.md](references/payments.md) - `npx @insforge/cli payments sync [--environment test|live|all]` — sync products, prices, customers, and subscriptions from Stripe - `npx @insforge/cli payments webhooks configure ` — create or recreate the managed Stripe webhook endpoint - `npx @insforge/cli payments catalog --environment ` — inspect mirrored products and prices together - `npx @insforge/cli payments customers --environment ` — admin/debug customer reads - `npx @insforge/cli payments products list/get/create/update/delete` — manage Stripe products - `npx @insforge/cli payments prices list/get/create/update/archive` — manage Stripe prices - `npx @insforge/cli payments subscriptions --environment ` — admin/debug subscription reads - `npx @insforge/cli payments history --environment ` — admin/debug payment history reads > ⚠️ **Private preview.** Payments are a new feature; older backends may not expose `/api/payments`. > **Availability:** If the CLI says `Payments are not available on this backend`, stop and ask the developer/admin to enable payments or upgrade the self-hosted InsForge instance. Do not work around this by storing Stripe secret keys with generic secrets or embedding Stripe secret keys in app code. > Agents should default to `--environment test` while building. Only use `live` after the developer explicitly approves production Stripe changes. ### Frontend Deployments (Vercel) — `npx @insforge/cli deployments` Deploy a frontend application (static site / SPA / Next.js / etc.) to Vercel, managed through InsForge. For backend container workloads see **Backend Compute Services** below. - `npx @insforge/cli deployments deploy [dir]` — deploy frontend app from its source directory. See [references/deployments-deploy.md](references/deployments-deploy.md) - `npx @insforge/cli deployments list` — list deployments - `npx @insforge/cli deployments status [--sync]` — get deployment status (--sync fetches from Vercel) - `npx @insforge/cli deployments cancel ` — cancel running deployment - `npx @insforge/cli deployments env list` — list all deployment environment variables - `npx @insforge/cli deployments env set ` — create or update a deployment environment variable - `npx @insforge/cli deployments env delete ` — delete a deployment environment variable by ID ### Backend Compute Services (Fly.io) — `npx @insforge/cli compute` Deploy and manage backend containerized services (APIs, workers, microservices). Each service runs as a Docker container reachable via a public endpoint — `https://-.fly.dev` for HTTP services (the default), or `-.fly.dev:` raw TCP for services deployed with `--protocol tcp` (Redis, Postgres-protocol, etc.). See **TCP services** below. For frontend hosting see **Frontend Deployments** above. > 🔧 **Implementation note (for agents):** InsForge runs compute on **Fly.io** > under the hood, but **DO NOT use `flyctl` directly** to deploy or manage > these services. The Fly account, org, IP allocation, and machine ownership > all live on the InsForge cloud — `flyctl` invoked with the user's own credentials > will land in the wrong org and fail with `unauthorized`. Always use > `npx @insforge/cli compute …`. The CLI is just an HTTP client that calls the > InsForge backend; the backend talks to Fly. No `flyctl` and no Fly token > are needed locally. > ⚠️ **In progress.** Compute services are still in development; the API and CLI may change. > > **Availability:** Compute requires the backend to have Fly.io configured. If not enabled, the API returns `COMPUTE_SERVICE_NOT_CONFIGURED` with setup instructions in `nextActions`. Follow those instructions. - `npx @insforge/cli compute list` — list all compute services (name, status, image, CPU, memory, endpoint) - `npx @insforge/cli compute get ` — get service details - `npx @insforge/cli compute deploy [dir] --name [--port] [--cpu] [--memory] [--region] [--env | --env-file ]` — **source mode**: requires `flyctl` on PATH; **no local Docker daemon needed**. CLI shells out to `flyctl deploy --remote-only --build-only` using a short-lived per-app deploy token minted by InsForge cloud (the user never sees a Fly token). Build runs on Fly's remote builder; image is pushed to `registry.fly.io`; cloud launches the machine. - `npx @insforge/cli compute deploy --image --name [--port] [--cpu] [--memory] [--region] [--protocol ] [--env | --env-file ]` — **image mode**: deploys a pre-built image from any registry. **Nothing needed locally** beyond the InsForge CLI. Best for CI/CD pipelines and off-the-shelf images like `nginx:alpine`. Prefer `--env-file ` over inline `--env ` for >1 secret. Pass `--protocol tcp` for raw-TCP services like Redis (see TCP services below). - See [references/compute-deploy.md](references/compute-deploy.md) for both modes. - `npx @insforge/cli compute update [--image] [--port] [--cpu] [--memory] [--region] [--env | --env-set KEY=VALUE | --env-unset KEY]` — update service config. `--env-set`/`--env-unset` are **repeatable** and merge with existing env — use these to rotate one secret without restating the rest. `--env ` replaces wholesale and is mutually exclusive with the merge flags. - `npx @insforge/cli compute stop ` — stop a running service - `npx @insforge/cli compute start ` — start a stopped service - `npx @insforge/cli compute events [--limit 50]` — Fly machine **lifecycle events** (start/stop/exit/restart). Container stdout/stderr is NOT surfaced in v1 — that's roadmap work and will reuse the freed-up `compute logs` command name when it lands. To debug a crash-looping container today, reproduce locally with the same image. - `npx @insforge/cli compute delete ` — destroy the service and its Fly.io resources. **Permanent.** Audit log captures the full config (incl. encrypted env blob) on delete for reconstruction. Dashboard adds a type-to-confirm gate; the CLI does not — guard scripted deletes carefully. ### Secrets — `npx @insforge/cli secrets` - `npx @insforge/cli secrets list [--all]` — list secrets (values hidden; `--all` includes deleted) - `npx @insforge/cli secrets get ` — get decrypted value - `npx @insforge/cli secrets add [--reserved] [--expires ]` — create secret - `npx @insforge/cli secrets update [--value] [--active] [--reserved] [--expires]` — update secret - `npx @insforge/cli secrets delete ` — **soft delete** (marks inactive; restore with `--active true`) ### Configuration — `npx @insforge/cli config` Manage supported project settings declaratively via `insforge.toml` (project root). For auth redirect URLs, verification flags, password policy, SMTP, storage upload size, realtime/schedule retention, and cloud deployment subdomain, prefer this over raw admin API calls — the CLI gates on backend version and surfaces a clean skip if the backend predates a field, where a raw write may 200-and-silently-drop. - `npx @insforge/cli config export [--out insforge.toml] [--force]` — pull live config into TOML. Sections the backend doesn't expose are omitted. - `npx @insforge/cli config plan [--file insforge.toml]` — diff TOML vs. live state; shows which changes will apply vs. be skipped on the connected backend. - `npx @insforge/cli config apply [--file insforge.toml] [--dry-run] [--auto-approve]` — apply the TOML. Per-change capability gate: supported changes apply; unsupported go to `skipped[]` with an upgrade message and **no write is issued for them**. `--json` returns `{ plan, applied[], skipped[] }`. > **If `apply` returns `skipped: [...]`, surface verbatim.** The user's backend predates this section. Tell them which sections were skipped and to upgrade; do not retry, do not bypass with `curl` (silent drop). Sample message: _"I tried to set `storage.max_file_size_mb` but your backend is on an older version that doesn't support it yet. Upgrade your backend and re-run `npx @insforge/cli config apply`."_ > **TOML is for knobs only — never embed programs.** SQL → `db migrations`. Function code → `functions deploy`. Compute → `compute deploy`. Frontend → `deployments deploy`. TOML carries booleans, numbers, strings, arrays, and simple nested config — anything bigger lives in its own file managed by a dedicated CLI command. **Scope today:** auth redirects and verification flags, password policy, SMTP, storage upload size, realtime/schedule retention, and cloud deployment subdomain. TOML does not manage external provider resources such as OAuth apps, storage bucket lifecycle, realtime channels, deployment env vars, functions, or secrets. See [references/config.md](references/config.md) for output shapes and a common-mistakes table. ### Schedules — `npx @insforge/cli schedules` - `npx @insforge/cli schedules list` — list all scheduled tasks (shows ID, name, cron, URL, method, active, next run) - `npx @insforge/cli schedules get ` — get schedule details - `npx @insforge/cli schedules create --name --cron --url --method [--headers ] [--body ]` — create a cron job. `--cron` accepts either 5-field cron (`*/5 * * * *`) or pg_cron interval syntax for sub-minute cadence (`30 seconds`) - `npx @insforge/cli schedules update [--name] [--cron] [--url] [--method] [--headers] [--body] [--active]` — update schedule - `npx @insforge/cli schedules delete ` — delete schedule (with confirmation) - `npx @insforge/cli schedules logs [--limit] [--offset]` — view execution logs ### Branching — `npx @insforge/cli branch` Test risky schema, RLS, auth, or function changes in an isolated branch project before applying them to prod. A branch shares the parent's `JWT_SECRET` (so the same users authenticate) but gets a fresh EC2 + database + `API_KEY` / `ANON_KEY`. See [`references/branch.md`](references/branch.md) for the decision guide and lifecycle command details. > ⚠️ **Backend version requirement.** Branching is still in development and only available on InsForge backend **2.1.0 or later**. On older backends, `npx @insforge/cli branch` commands will fail. If you hit an error, contact the InsForge team. | Command | Description | |---------|-------------| | `npx @insforge/cli branch create [--mode full\|schema-only] [--no-switch]` | Create a branch from the linked project. Auto-switches the directory's context to the new branch by default. | | `npx @insforge/cli branch list` | List active branches of the parent project (or the parent of the currently-switched-to branch). | | `npx @insforge/cli branch switch ` / `--parent` | Repoint `.insforge/project.json` at the branch (or back at parent). | | `npx @insforge/cli branch merge [--dry-run] [--save-sql ] [-y]` | Compute (and optionally apply) the 3-way merge to parent. Conflict path exits with code 2. See [branch-merge](references/branch-merge.md). | | `npx @insforge/cli branch reset [-y]` | Wipe all changes on the branch and restore its database to T0 (parent's snapshot at branch creation). Same EC2 / `appkey` / `API_KEY` — only DB content rewinds. Works from `ready` **or** `merged`. See [branch-reset](references/branch-reset.md). | | `npx @insforge/cli branch delete [-y]` | Delete a branch and reclaim its EC2. Auto-switches back to parent if currently on the deleted branch. | **Typical flow:** ```bash npx @insforge/cli branch create feat-rls --mode schema-only # context now points at the branch — re-source .env if your dev server caches it # branch runtime starts empty — redeploy any functions/website/compute you'll exercise # ... apply your schema / RLS / auth changes via db migrations / SQL ... npx @insforge/cli branch merge feat-rls --dry-run --save-sql /tmp/diff.sql # review /tmp/diff.sql; on conflict CLI exits 2 npx @insforge/cli branch merge feat-rls # parent now has the changes — redeploy functions / website / compute as needed npx @insforge/cli branch delete feat-rls ``` > **Got into a bad state on the branch?** `npx @insforge/cli branch reset ` rewinds the branch's database back to T0 (the parent snapshot at branch creation) without touching the EC2 or API keys — cheaper than delete + recreate and the SDK's `INSFORGE_URL` / `ANON_KEY` stay valid. Works from both `ready` and `merged` (a merged branch reset re-opens the same slot for another round of changes). ### Diagnostics — `npx @insforge/cli diagnose` Run with no subcommand for a full health report across all checks. - `npx @insforge/cli diagnose` — full health report (runs all diagnostics) - `npx @insforge/cli diagnose --ai ""` — hand a natural-language problem description (error, failing URL, HTTP status) to the InsForge debug agent; returns a diagnosis plus suggested solutions - `npx @insforge/cli diagnose metrics [--range 1h|6h|24h|7d] [--metrics ]` — EC2 instance metrics (CPU, memory, disk, network). Default range: `1h` - `npx @insforge/cli diagnose advisor [--severity critical|warning|info] [--category security|performance|health] [--limit ]` — latest advisor scan results and issues. Default limit: 50 - `npx @insforge/cli diagnose db [--check ]` — database health checks. Checks: `connections`, `slow-queries`, `bloat`, `size`, `index-usage`, `locks`, `cache-hit` (default: `all`) - `npx @insforge/cli diagnose logs [--source ] [--limit ]` — aggregate error-level logs from all backend sources. Default limit: 100 ### Analytics Integration — `npx @insforge/cli posthog` - `npx @insforge/cli posthog setup` — ensures the InsForge dashboard has a PostHog connection (auto-provisioning / OAuth if missing, no-op if already connected), then prints the official PostHog wizard command (`npx -y @posthog/wizard@latest`) for the user to run themselves to wire PostHog into the app code. The CLI itself does not spawn the wizard. See [references/posthog.md](references/posthog.md). - **For agents:** the printed wizard command is interactive — prompts on stdin, opens a browser, won't work via the agent shell or `!` prefix. Ask the user to switch to their real terminal app and run it there. > ⚠️ **Beta.** PostHog integration is rolling out across InsForge Cloud; older cloud projects and self-hosted backends may not expose `/integrations/posthog/v1/*` yet. If the CLI fails with `PostHog connect flow unavailable (HTTP 404)`, the project doesn't have PostHog enabled yet — wait for the rollout or ask the InsForge team to enable it. Do not work around this by pulling a `phc_` key from a separate PostHog account and embedding it in the app's env: events will flow to PostHog but the InsForge dashboard's Analytics page reads from a server-side OAuth-backed `posthog_connections` row that only `posthog setup` populates — without it the page stays empty even though the integration "looks" wired. ### Logs — `npx @insforge/cli logs` - `npx @insforge/cli logs [--limit ]` — fetch backend container logs (default: 20 entries) | Source | Description | |--------|-------------| | `insforge.logs` | Main backend logs | | `postgREST.logs` | PostgREST API layer logs | | `postgres.logs` | PostgreSQL database logs | | `function.logs` | Edge function execution logs | | `function-deploy.logs` | Edge function deployment logs | > Source names are case-insensitive: `postgrest.logs` works the same as `postgREST.logs`. ### Documentation — `npx @insforge/cli docs` - `npx @insforge/cli docs` — list all topics - `npx @insforge/cli docs instructions` — setup guide - `npx @insforge/cli docs ` — feature docs (`db / storage / functions / auth / ai / realtime` × `typescript / swift / kotlin / rest-api`) > For writing application code with the InsForge SDK, use the insforge (SDK) skill instead, and use the `npx @insforge/cli docs ` to get specific SDK documentation. --- ## Non-Obvious Behaviors **Functions invoke URL**: invoked at `{oss_host}/functions/{slug}` — NOT `/api/functions/{slug}`. Exits with code 1 on HTTP 400+. **Secrets delete is soft**: marks the secret inactive, not destroyed. Restore with `npx @insforge/cli secrets update KEY --active true`. Use `--all` with `secrets list` to see inactive ones. **Storage delete-bucket is hard**: deletes the bucket and every object inside it permanently. **db rpc uses GET or POST**: no `--data` → GET; with `--data` → POST. **db migrations use timestamped files**: migration filenames use `YYYYMMDDHHmmss_name.sql`, for example `20260418091500_create-posts.sql`. **db migrations up supports safe batch modes**: `npx @insforge/cli db migrations up ` applies one explicit local target. `npx @insforge/cli db migrations up --to ` and `npx @insforge/cli db migrations up --all` apply pending files in ascending version order and stop on the first failure. **db migrations run inside a backend-managed transaction**: do not put `BEGIN`, `COMMIT`, or `ROLLBACK` in migration files. **The live database schema is the source of truth**: before writing a migration, and again if a migration fails, inspect the current database state first (`db tables / indexes / policies / triggers / functions`, plus `db migrations list`) and then adjust the migration statements to match reality. Do not assume local files are still current. **Compute deploy has two modes.** `compute deploy [dir]` shells out to `flyctl deploy --remote-only --build-only` against your source dir using a short-lived per-app token the cloud mints for that one deploy — **requires `flyctl` on PATH** but **no local Docker daemon** (the build runs remotely on Fly's builder). The token is attenuated to one app + builder/wg with `else: deny` so it cannot reach any other app or org-level endpoint, and it auto-expires after ~20 min. `compute deploy --image ` deploys a pre-built image from any registry — **nothing needed locally**, best for CI or off-the-shelf images like `nginx:alpine`. Don't use `flyctl` outside this CLI flow with your own credentials — the Fly account is InsForge's, you'd 401. **Compute endpoints use .fly.dev**: Services get a public URL at `https://{name}-{projectId}.fly.dev`. Custom domains require DNS configuration. **Schedules accept two cron formats**: 5-field cron (`minute hour day month day-of-week`, e.g. `*/5 * * * *`) **or** pg_cron interval syntax for sub-minute cadence (e.g. `30 seconds`). 6-field cron with seconds (Quartz/Spring's `*/2 * * * * *`) is **not** supported — use the interval form for sub-minute work. Headers can reference secrets with `${{secrets.KEY_NAME}}`. **Payments use Stripe as source of truth**: use `payments config set` for Stripe keys, `payments sync` before relying on existing catalog data, and create a new Stripe price instead of editing amount/currency. Runtime checkout and customer portal integration belongs in the `insforge` SDK skill. **`config apply` is version-aware**: per-project backends drift in version. The CLI probes backend metadata/config endpoints and gates each TOML key on whether the backend exposes it; if not, the change lands in `skipped[]` with an upgrade message and **no PUT/PATCH is issued**. Never bypass with `curl` to "force" a skipped field — older backends may 200-and-silently-drop. Surface skips to the user and ask them to upgrade. --- ## Common Workflows ### Configure project settings (insforge.toml) ```bash # 1. Pull current config to insforge.toml (writes in project root) npx @insforge/cli --json config export # 2. Edit supported sections such as [auth], [auth.password], [auth.smtp], # [storage], [realtime], [schedules], or [deployments] # 3. Preview the diff npx @insforge/cli --json config plan # 4. Apply (use --yes for non-interactive — required in --json mode) npx @insforge/cli --json --yes config apply ``` If `apply` returns a non-empty `skipped[]`, the user's backend predates this section — surface the entries verbatim with the upgrade ask. Don't retry, don't fall back to `curl` (older backends may 200-and-silently-drop). See [references/config.md](references/config.md). ### Set up database schema with migrations ```bash # Inspect the current live schema first npx @insforge/cli db tables npx @insforge/cli db indexes npx @insforge/cli db policies npx @insforge/cli db migrations list # Sync applied remote migration history locally npx @insforge/cli db migrations fetch # Create the next schema migration file npx @insforge/cli db migrations new create-posts # Edit migrations/20260418091500_create-posts.sql with CREATE TABLE / ALTER TABLE / policies # Apply pending migrations safely npx @insforge/cli db migrations up --all ``` > `db query` and migrations run as `project_admin`. Use migrations for schema changes and RLS policies, including RLS on documented InsForge-managed tables. Use `db query` for row changes and inspection. In migrations, FK to users with `auth.users(id)` and use `auth.uid()` in RLS policies. ### Manage database migrations ```bash # Inspect remote migration history npx @insforge/cli db migrations list # Sync applied remote migrations into migrations/ npx @insforge/cli db migrations fetch # Create the next local migration file npx @insforge/cli db migrations new create-posts # Apply all pending local migrations npx @insforge/cli db migrations up --all ``` ### Deploy an edge function ```bash # --file is required; point it at your source wherever it lives npx @insforge/cli functions deploy my-handler --file ./my-handler.ts npx @insforge/cli functions invoke my-handler --data '{"action": "test"}' ``` ### Deploy frontend **Always verify the local build succeeds before deploying.** Local builds are faster to debug and don't waste server resources. After the build passes, deploy the project source directory (usually `.`), not `dist/` or other generated build output. **Environment variables are required.** Frontend apps need env vars (API URL, anon key) to connect to InsForge at runtime. Deploying without them produces a broken app. Before deploying, you must ensure env vars are set using one of these two approaches: **Option A — Persistent env vars (recommended):** Set once, applied to every future deployment automatically. Best for projects that will be redeployed. ```bash # Check what's already set npx @insforge/cli deployments env list # Set the vars your app needs (use the correct framework prefix) npx @insforge/cli deployments env set VITE_INSFORGE_URL https://my-app.us-east.insforge.app npx @insforge/cli deployments env set VITE_INSFORGE_ANON_KEY ik_xxx # Deploy the project source — persistent env vars are applied automatically npx @insforge/cli deployments deploy . ``` **Option B — Inline `--env` flag:** Pass env vars as JSON directly on the deploy command. Useful for one-off deploys or overriding persistent vars. ```bash npx @insforge/cli deployments deploy . --env '{"VITE_INSFORGE_URL": "https://my-app.us-east.insforge.app", "VITE_INSFORGE_ANON_KEY": "ik_xxx"}' ``` **Full workflow:** ```bash # 1. Build locally first npm run build # 2. Ensure env vars are set (check existing, add missing) npx @insforge/cli deployments env list npx @insforge/cli deployments env set VITE_INSFORGE_URL https://my-app.us-east.insforge.app npx @insforge/cli deployments env set VITE_INSFORGE_ANON_KEY ik_xxx # 3. Deploy the project source directory npx @insforge/cli deployments deploy . ``` **Environment variable prefix by framework:** | Framework | Prefix | Example | |-----------|--------|---------| | Vite | `VITE_` | `VITE_INSFORGE_URL` | | Next.js | `NEXT_PUBLIC_` | `NEXT_PUBLIC_INSFORGE_URL` | | Create React App | `REACT_APP_` | `REACT_APP_INSFORGE_URL` | | Astro | `PUBLIC_` | `PUBLIC_INSFORGE_URL` | | SvelteKit | `PUBLIC_` | `PUBLIC_INSFORGE_URL` | **Pre-deploy checklist:** - [ ] `npm run build` succeeds locally - [ ] Env vars are set — run `deployments env list` to verify, or pass `--env` on the deploy command - [ ] All env vars use the correct framework prefix - [ ] Deploy the project source directory (usually `.`), not `dist/`, `build/`, or `.next/` - [ ] Edge function directories excluded from frontend build (if applicable) - [ ] Never include `node_modules`, `.git`, `.env`, or `.insforge` in the upload - [ ] Framework build output is configured correctly (`dist/`, `build/`, `.next/`, etc.) ### Deploy a Docker container (compute service) Two modes — pick by what you have. Both deploy to the same Fly.io infrastructure. **Source mode (you have a Dockerfile; needs `flyctl` on PATH but NO local Docker daemon):** ```bash # Install flyctl once: curl -L https://fly.io/install.sh | sh # Project layout: Dockerfile + your app code $ ls Dockerfile app.py requirements.txt # One command: npx @insforge/cli compute deploy . --name my-api --port 8000 # CLI mints a per-app, attenuated Fly deploy token from InsForge cloud # (~20 min TTL, scoped to one app, else: deny blocks org-wide reads), then # shells out to `flyctl deploy --remote-only --build-only` so the build runs # on Fly's remote builder and is pushed to registry.fly.io. Cloud launches # the machine and returns the URL. NO local Docker daemon needed. ``` **Off-the-shelf image (no Docker required):** ```bash npx @insforge/cli compute deploy --image nginx:alpine --name my-api --port 80 --region iad npx @insforge/cli compute list # Service is running with a public https://{name}-{project}.fly.dev endpoint # No flyctl, no FLY_API_TOKEN, no local Docker required. ``` **Pre-built image you pushed yourself (CI/CD, custom registry — no Docker required locally):** ```bash # Built + pushed elsewhere (GitHub Actions, your CI, etc.) npx @insforge/cli compute deploy --image ghcr.io/you/app:v1 --name my-api --port 8000 ``` **TCP services (Redis, Postgres-protocol, etc.):** ```bash # Default is HTTP; pass --protocol tcp for raw TCP pass-through at the Fly edge. npx @insforge/cli compute deploy \ --image redis:7-alpine \ --name cache \ --protocol tcp \ --port 6379 # Endpoint shape is :, e.g. cache-.fly.dev:6379. # Connect with `redis-cli -h -p 6379`. ``` TCP services are reachable from the public internet. Configure auth in your container (e.g. start Redis with `--requirepass ` via `--env`). Storage is ephemeral in v1; AOF/RDB persistence requires volumes (not yet supported by InsForge Compute). **Lifecycle management:** ```bash npx @insforge/cli compute stop # stop the machine npx @insforge/cli compute start # restart it npx @insforge/cli compute events # machine lifecycle events npx @insforge/cli compute delete # destroy everything ``` **CPU tiers:** `shared-1x` (default), `shared-2x`, `performance-1x`, `performance-2x`, `performance-4x` **Memory options:** 256, 512 (default), 1024, 2048, 4096, 8192 MB **Regions:** `iad` (default), `sin`, `lax`, `lhr`, `nrt`, `ams`, `syd` > **Source mode** requires `flyctl` on PATH (no Docker). The CLI never asks the user for `FLY_API_TOKEN` — the cloud mints a short-lived, app-scoped token per deploy (~20 min, `else: deny`) and passes it through env to the flyctl subprocess. Tokens cannot deploy or read any other app, even within InsForge's Fly org. **Image mode** (the examples above) needs neither flyctl nor a token. ### Backup and restore database ```bash npx @insforge/cli db export --output backup.sql npx @insforge/cli db import backup.sql ``` ### Schedule a cron job ```bash # Wall-clock cadence — every 5 minutes (5-field cron) npx @insforge/cli schedules create \ --name "Cleanup Expired" \ --cron "*/5 * * * *" \ --url "https://my-app.us-east.insforge.app/functions/cleanup" \ --method POST \ --headers '{"Authorization": "Bearer ${{secrets.API_TOKEN}}"}' # Sub-minute cadence — every 30 seconds (pg_cron interval syntax) npx @insforge/cli schedules create \ --name "Health Probe" \ --cron "30 seconds" \ --url "https://my-app.us-east.insforge.app/functions/probe" \ --method GET # Check execution history npx @insforge/cli schedules logs ``` #### Cron Expression Format InsForge accepts **two cron formats**: standard 5-field cron expressions, **or** pg_cron interval syntax for sub-minute cadence. 6-field cron expressions with seconds (Quartz/Spring style) are NOT supported — use the interval form below for sub-minute work. **5-field cron format:** ``` ┌─────────────── minute (0-59) │ ┌───────────── hour (0-23) │ │ ┌─────────── day of month (1-31) │ │ │ ┌───────── month (1-12) │ │ │ │ ┌─────── day of week (0-6, Sunday=0) │ │ │ │ │ * * * * * ``` | Expression | Description | |------------|-------------| | `* * * * *` | Every minute | | `*/5 * * * *` | Every 5 minutes | | `0 * * * *` | Every hour (at minute 0) | | `0 9 * * *` | Daily at 9:00 AM | | `0 9 * * 1` | Every Monday at 9:00 AM | | `0 0 1 * *` | First day of every month at midnight | | `30 14 * * 1-5` | Weekdays at 2:30 PM | **Interval syntax (for sub-minute cadence):** Use ` seconds` (e.g. `30 seconds`) — the only thing 5-field cron can't express. > **When to pick which:** use 5-field cron for "wall-clock" cadence (every Monday at 9 AM, daily midnight, every 5 minutes on the dot). Use interval syntax when you need sub-minute cadence or simple "every N seconds" semantics. At very high cadence (e.g. `1 second`), watch `schedules.job_logs` row counts — every fire writes a log row. #### Secret References in Headers Headers can reference secrets stored in InsForge using the syntax `${{secrets.KEY_NAME}}`. ```json { "headers": { "Authorization": "Bearer ${{secrets.API_TOKEN}}", "X-API-Key": "${{secrets.EXTERNAL_API_KEY}}" } } ``` Secrets are resolved at schedule creation/update time. If a referenced secret doesn't exist, the operation fails with a 404 error. #### Best Practices 1. **Pick the right cron format for the cadence** - Wall-clock cadence (daily/hourly/weekly) → 5-field cron (`*/5 * * * *`, `0 9 * * 1-5`) - Sub-minute cadence → pg_cron interval form (e.g. `30 seconds`) - 6-field cron with seconds (`*/2 * * * * *`) is **not** supported — use the interval form 2. **Store sensitive values as secrets** - Use `${{secrets.KEY_NAME}}` in headers for API keys and tokens - Create secrets first via the secrets API before referencing them 3. **Target InsForge functions for serverless tasks** - Use the function URL format: `https://your-project.region.insforge.app/functions/{slug}` - Ensure the target function exists and has `status: "active"` 4. **Monitor execution logs** - Check logs regularly to ensure schedules are running successfully - Look for non-200 status codes and failed executions #### Common Mistakes | Mistake | Solution | |---------|----------| | Using 6-field cron (e.g. `*/2 * * * * *`) | Not supported — use pg_cron interval form (`2 seconds`) for sub-minute, or 5-field cron for everything else | | Referencing non-existent secret | Create the secret first via secrets API | | Targeting non-existent function | Verify function exists and is `active` before scheduling | | Schedule not running | Check `isActive` is `true` and cron expression is valid | #### Recommended Workflow ``` 1. Create secrets if needed -> `npx @insforge/cli secrets add KEY VALUE` 2. Create/verify target function -> `npx @insforge/cli functions list` 3. Create schedule -> `npx @insforge/cli schedules create` 4. Verify schedule is active -> `npx @insforge/cli schedules get ` 5. Monitor execution logs -> `npx @insforge/cli schedules logs ` ``` ### Diagnose backend health ```bash # Full health report (all checks) npx @insforge/cli diagnose # Check specific areas npx @insforge/cli diagnose metrics --range 24h # CPU/memory/disk over last 24h npx @insforge/cli diagnose advisor --severity critical # critical issues only npx @insforge/cli diagnose db --check bloat,slow-queries # specific DB checks npx @insforge/cli diagnose logs # aggregate errors from all sources ``` ### Debug with logs ```bash npx @insforge/cli logs function.logs # function execution issues npx @insforge/cli logs postgres.logs # database query problems npx @insforge/cli logs insforge.logs # API / auth errors npx @insforge/cli logs postgrest.logs --limit 50 ``` #### Best Practices 1. **Start with function.logs for function issues** - Check execution errors, timeouts, and runtime exceptions 2. **Use postgres.logs for query problems** - Debug slow queries, constraint violations, connection issues 3. **Check insforge.logs for API errors** - Authentication failures, request validation, general backend errors #### Common Debugging Scenarios | Problem | Check | |---------|-------| | Function not working | `function.logs` | | Database query failing | `postgres.logs`, `postgREST.logs` | | Auth issues | `insforge.logs` | | API returning 500 errors | `insforge.logs`, `postgREST.logs` | | General health / performance | `diagnose` (full report) or `diagnose metrics` | | Database bloat / slow queries | `diagnose db` | | Security / config issues | `diagnose advisor --category security` | | Compute service not starting | `compute events ` (machine lifecycle events) | | Compute source-mode deploy failed | Verify `flyctl` is on PATH (`flyctl version`); the per-app deploy token has a 20-min TTL — re-run if expired. Use `--image ` with a pre-built image to skip flyctl entirely. | | Compute image-mode deploy failed | Confirm the image is publicly pullable (private registries need per-project credential setup) | ### Non-interactive CI/CD ```bash INSFORGE_EMAIL=$EMAIL INSFORGE_PASSWORD=$PASSWORD npx @insforge/cli login --email -y npx @insforge/cli link --project-id $PROJECT_ID --org-id $ORG_ID -y npx @insforge/cli db query "SELECT 1 AS ok" --json ``` --- ## Project Configuration After `create` or `link`, `.insforge/project.json` is created: ```json { "project_id": "...", "appkey": "...", "region": "us-east", "api_key": "ik_...", "oss_host": "https://{appkey}.{region}.insforge.app" } ``` `oss_host` is the base URL for all SDK and API operations. `api_key` is the full-access admin key for backend API calls, equivalent to a service role key on other platforms. > **Never commit this file to version control or share it publicly**. > Do not edit this file manually. Use `npx @insforge/cli link` to switch projects.