
Insforge Debug
- 277 installs
- 36 repo stars
- Updated August 4, 2026
- insforge/insforge-skills
This is a copy of insforge-debug by insforge - installs and ranking accrue to the original listing.
Diagnose Insforge platform failures, trace error sources, and guide fixes so agents can resolve production issues and broken integrations faster.
About
Insforge-debug skill helps Claude investigate errors, trace failures, and recommend fixes within the Insforge platform, supporting faster root-cause analysis when APIs, deployments, or integrations break in live environments.
- Targets Insforge-specific failure diagnosis
- Traces errors across platform integrations
- Guides root-cause analysis for live issues
- Speeds recovery from broken deployments
- Pairs agent reasoning with platform debug patterns
Insforge Debug by the numbers
- 277 all-time installs (skills.sh)
- +10 installs in the week ending Aug 2, 2026 (Skillselion tracking)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/insforge/insforge-skills --skill insforge-debugAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 277 |
|---|---|
| repo stars | ★ 36 |
| Last updated | August 4, 2026 |
| Repository | insforge/insforge-skills ↗ |
What it does
Diagnose Insforge platform failures, trace error sources, and guide fixes so agents can resolve production issues and broken integrations faster.
Files
InsForge Debug
Diagnose problems in InsForge projects by combining the backend's observability primitives — logs, metrics, db-health, advisor, policies, metadata, error objects, deploy state, and AI assist. This skill provides:
1. A reference per debug primitive (one observability surface each — under references/) 2. Symptom Recipes (below) that name the primitive sequence for known reactive symptoms and proactive audits
Always use `npx @insforge/cli` — never install the CLI globally.
Fastest Path: AI-Assisted Triage
When the user gives a concrete description (error message, failing URL, HTTP status), hand it to the InsForge debug agent. Unlike the other primitives, this one returns suggestions, not just observations — verify the diagnosis against the primitives it cites before acting on it.
npx @insforge/cli diagnose --ai "<issue description>"See references/ai-assisted.md for when to use this first vs when to skip, and how to verify the output.
Debug Primitives
Each primitive is one independently-queryable observability surface backed by a distinct underlying data source. Real diagnoses are compositions of primitives.
All commands run via npx @insforge/cli .... The (command) shown next to each primitive is the actual CLI command — primitive names are concept labels, not CLI subcommand names (e.g., "DB health" is diagnose db, not diagnose db-health; "Policies" is db policies, not diagnose policies).
| Primitive (command) | What you see | Reference |
|---|---|---|
Logs (logs <source>; diagnose logs for cross-source aggregate) | Time-stream of events from 5 backend sources (insforge.logs / postgREST.logs / postgres.logs / function.logs / function-deploy.logs) | references/logs.md |
Metrics (diagnose metrics) | EC2 instance time-series (CPU / memory / disk / network) over 1h / 6h / 24h / 7d | references/metrics.md |
DB health (diagnose db) | Current Postgres state via 7 named checks (connections / slow-queries / bloat / size / index-usage / locks / cache-hit) | references/db-health.md |
Advisor (diagnose advisor --json) | Static-scan issues across 3 categories (security / performance / health) with ruleId / affectedObject / recommendation | references/advisor.md |
Policies (db policies) | Active RLS rules from pg_policies (USING / WITH CHECK per cmd per role) — returns all policies as a dump | references/policies.md |
Metadata (metadata --json) | Declarative backend state dump (auth config / tables / buckets / functions / AI models / realtime channels) | references/metadata.md |
| Error objects (no command — read SDK / HTTP response) | SDK error envelope + HTTP status — the routing table from a client-visible error to the right log source | references/error-objects.md |
Deploy state (deployments list + deployments status <id> --json + logs function-deploy.logs) | Frontend (Vercel) deployment history + per-deploy metadata, plus edge function deploy logs | references/deploy-state.md |
AI assist (diagnose --ai "<description>") | LLM agent that combines the other primitives — returns a diagnosis with suggestions | references/ai-assisted.md |
Symptom Recipes
Each recipe is a primitive call sequence with one-line "look for X" at each step. Command syntax, flags, and deep interpretation are in the per-primitive references above.
Recipe: SDK returned { data: null, error: { code, message } }
1. error-objects — read code/message/details. If code starts with PGRST*, route by prefix using the table in the reference. 2. logs (matching source per error-objects routing) — find the error timestamp, get the full backend-side context. 3. db-health (connections, locks, slow-queries) — only if the error suggests DB issue (PostgREST timeout, lock conflict).
Recipe: HTTP 4xx/5xx response on a specific request
1. error-objects — use the HTTP status routing table to pick the log source (each status has a distinct path; 429 is special). 2. logs (right source for that status) — find the failing request line and error. 3. metrics — only for 5xx patterns spanning multiple endpoints, to confirm system-wide load issue.
Recipe: RLS access issue (403 on write, or empty result on read)
Same bug, two surfacings. Writes (INSERT / UPDATE / DELETE) fail loudly with 403. Reads (SELECT) fail silently with an empty array — PostgREST filters denied rows out instead of returning 403, so the request looks successful with zero rows. Diagnosis path is the same except step 1 only applies to the 403 variant.
1. logs (postgREST.logs) — 403 variant only: find the policy violation event with table and role context. Empty-result variant: skip — no error is logged for silently-filtered rows. 2. policies — list policies for that table; walk USING / WITH CHECK against the actual request and the JWT claim used. 3. metadata — verify auth config (which claim feeds auth.uid() / requesting_user_id(); for third-party auth like Clerk/Auth0, is the provider registered as a JWT issuer?). 4. db query (db query "<sql>") — empty-result variant only: confirm rows that should be visible actually exist by querying as service role (not as the user): npx @insforge/cli db query "SELECT id, user_id FROM <table>". Distinguishes "RLS filtered everything" from "no matching data exists".
Recipe: Login fails / OAuth callback errors / token expired
1. logs (insforge.logs) — find auth errors with timestamp and provider context. 2. metadata — verify the provider is enabled, redirect URLs match the callback URL exactly (protocol + host + path).
Recipe: Edge function runtime error / timeout
1. logs (function.logs) — get the error stack and execution context. 2. metadata — confirm the function exists and status: "active". 3. (If needed) npx @insforge/cli functions code <slug> — inspect the source for obvious issues.
Recipe: functions deploy failed
1. deploy-state (function-deploy.logs) — find the build/push error. 2. metadata — confirm whether the function ended up in the active list (partial-deploy detection).
Recipe: deployments deploy failed (Vercel)
1. deploy-state (deployments list + status <id> --json) — read status, metadata.webhookEventType, and envVarKeys. 2. Local npm run build — reproduce the same error locally for faster iteration.
Recipe: Single slow query / one endpoint slow
1. logs (postgres.logs) — find the query text and timestamp. 2. db-health (slow-queries, index-usage) — confirm it's in pg_stat_statements; check for missing index. 3. policies — if it's an RLS-gated table, verify the policy isn't adding hidden joins.
Recipe: All responses slow / high CPU/memory (active incident)
1. metrics (--range 1h) — confirm system-wide pressure (CPU / memory / disk). 2. db-health — DB is the most common bottleneck; check connections, locks, slow-queries. 3. logs (diagnose logs aggregate) — error patterns across sources at the spike timestamp. 4. advisor (--severity critical) — pre-existing known issues that may explain the degradation.
Recipe: Realtime channel won't connect / messages missing
1. logs (insforge.logs) — WebSocket errors and subscription failures. 2. metadata — verify the channel pattern matches what the client subscribes to, enabled: true. 3. policies — RLS on the underlying table (realtime delivers row changes; RLS gates which rows the subscriber sees).
Recipe: 429 rate limit
1. error-objects — confirm 429 status. No logs are recorded for 429s; no `Retry-After` header is returned. Don't waste time grepping logs. 2. metrics (--range 1h) — overall backend load context. 3. Fix is always client-side: debounce, batch, exponential backoff, eliminate retry loops.
Recipe: Gateway timeout (502 / 503 / 504) on a specific URL
Route by URL subsystem before drilling:
| URL pattern | Drill into |
|---|---|
/api/database/records/... | logs (postgREST.logs → postgres.logs) + db-health (locks, slow-queries) |
/functions/<slug> | logs (function.logs) — function may be crash-looping |
/api/auth/... | logs (insforge.logs) |
| Any path during system-wide spike | metrics (--range 1h) |
Recipe: Pre-launch / proactive audit
Requires Platform login (npx @insforge/cli login). Not available when the project is linked via `--api-key` — fall back todb-health+policies+metadatafor a manual audit in that case.
1. advisor — full scan, then --severity critical first, then warnings. 2. advisor (--category security) — focus on security issues; cross-verify with policies (RLS coverage) and metadata (auth config, public buckets, secret presence). 3. advisor (--category performance) — cross-verify with db-health (slow-queries, index-usage, bloat). 4. advisor (--category health) — cross-verify with metrics (resource trends over 7d). 5. After fixes, re-run advisor and confirm isResolved: true for each addressed ruleId.
Recipe: Don't know where to start
1. ai-assisted (diagnose --ai "<error or URL>") — get a starting hypothesis. 2. Verify by re-checking the primitives the diagnosis names. Trust the primitive observations over the suggestion.
Advisor
Static-scan engine that audits the project against a rule catalog and returns issue rows. The primary primitive for proactive audits — security misconfigurations, performance regressions, and system health concerns surfaced without a specific failing request.
Command
npx @insforge/cli diagnose advisor [--severity critical|warning|info] [--category security|performance|health] [--limit <n>] [--json]Default limit: 50. Requires Platform login — not available on backends linked via `--api-key`.
Add `--json` when you need the full issue payload. Human-readable output is a 4-column table (severity / category / affectedObject / title). Fields like ruleId, description, recommendation, isResolved are only emitted by --json — without the flag, you can't read or act on the recommendation programmatically.
What you see
Each scan returns:
Scan summary — scanId, scannedAt, status, and counts by severity (critical / warning / info).
Issue rows — each issue has:
| Field | Meaning |
|---|---|
ruleId | Stable identifier of the rule that fired (e.g., security.rls.missing-policy) |
severity | critical / warning / info |
category | security / performance / health |
affectedObject | The specific schema object (table, function, policy, secret name) the issue applies to |
title | Short human label |
description | What the rule detected |
recommendation | Suggested fix, often a concrete SQL/CLI step |
isResolved | true after a re-scan confirms the fix |
Categories
| Category | Typical rules | Fix in |
|---|---|---|
security | RLS missing/permissive on a table, expired/exposed secrets, weak JWT config, public bucket on sensitive data | db migrations (RLS), secrets (key rotation), metadata (auth/bucket config) |
performance | Missing index on heavy filter column, bloat over threshold, sequential scans on large tables, slow recurring query | db migrations (indexes), query rewrite, vacuum tuning |
health | Connection pool near limit, EC2 disk filling, deprecated feature in use, version drift | Infra resize, code change, version upgrade |
How to read
1. Start with severity: --severity critical first; critical issues block launch. 2. Group by category to keep the fix mode coherent (don't context-switch between RLS edits and index migrations). 3. `affectedObject` tells you where to fix — it names the concrete schema object. 4. `recommendation` is usually actionable as-is. Verify it makes sense (the recommendation may be generic), then apply via the appropriate primitive's tooling.
Iteration workflow
1. Scan: diagnose advisor --severity critical --json
2. Triage: pick one issue, read affectedObject + recommendation
3. Verify: inspect the affected object (db query / db policies / metadata)
4. Fix: apply the change (migration / RLS edit / secret rotation / config update)
5. Re-scan: diagnose advisor --json — confirm isResolved=true for that ruleId
6. Repeat with next critical, then warnings, then infoBoundaries
- Scans are not real-time. A new scan triggers when the platform schedules it; recommendations lag behind very recent changes. Force a fresh scan if needed.
- Recommendations are static suggestions, not auto-fixes. Always validate against current schema state before applying.
- `affectedObject` is a string, not a typed reference. It names the object but doesn't link to it — combine with metadata / policies to inspect.
- Not available when linked via `--api-key`. Requires
insforge login(Platform auth).
Example
Pre-launch audit:
# Full scan, critical only first
npx @insforge/cli diagnose advisor --severity critical
# Security focus
npx @insforge/cli diagnose advisor --category security
# Performance focus (often pairs with db-health to verify)
npx @insforge/cli diagnose advisor --category performance
npx @insforge/cli diagnose db --check slow-queries,index-usage
# Re-scan after fixes
npx @insforge/cli diagnose advisor --severity criticalFrequently paired with
- policies — security category issues often name a table with missing/broken RLS policy
- metadata — security/health issues often name a configured object (bucket, secret, auth provider) whose state needs inspecting
- db-health — performance category overlaps with
slow-queries/index-usage/bloat; cross-verify - metrics — health category issues (pool exhaustion, disk fill) line up with metric trends
AI assist
The meta-primitive: hand a natural-language problem description to a backend-side LLM agent that combines the other primitives (logs, metrics, db-health, advisor, policies, metadata) on its own and returns a diagnosis plus suggested solutions.
Unlike every other primitive in this skill, `diagnose --ai` returns suggestions, not just observations. Verify before acting.
Command
npx @insforge/cli diagnose --ai "<issue description>"The description should include: the error / failing URL / HTTP status / function slug — whatever concrete signal the user has.
When to use first
- User pasted an error, request URL, or status code and asks "why?"
- You want a fast first pass before deciding which primitive to drill into
- The problem spans multiple subsystems (frontend + backend + database) and the right starting primitive isn't obvious
When to skip
- The symptom clearly maps to one primitive (e.g., "Vercel deploy failed" → go straight to deploy-state)
- You're doing a proactive audit (no concrete error — that's advisor)
- You already know exactly which log source has the error
How to verify the output
The agent's diagnosis names primitives and observations. Re-check each:
| If the diagnosis says... | Verify with... |
|---|---|
| "An RLS policy is blocking the request" | policies — read the actual policy on that table |
| "Slow query on table X" | db-health slow-queries + logs postgres.logs for the actual query |
| "Function is timing out" | logs function.logs — read the actual timeout/error stack |
| "Connection pool exhausted" | db-health connections — confirm the count and idle-in-transaction state |
| "Missing index on column Y" | db-health index-usage + advisor performance — both should agree |
If the verification disagrees with the diagnosis, trust the primitive observation, not the suggestion. Suggestions can be plausible-sounding but wrong (LLM may pattern-match on similar errors); raw pg_stat numbers and log lines can't lie.
Boundaries
- Returns suggestions, not just data. Different from every other primitive — treat the output as a starting hypothesis, not a verdict.
- Doesn't replace [advisor](advisor.md). Advisor surfaces issues based on a static rule catalog;
--aireasons about a specific reported symptom. They serve different goals. - Consumes the other primitives. When this fails or seems off, fall back to the primitives directly.
Example
User pastes: "I invoked https://kttprzh4.functions.insforge.app/newton and got 508: Loop Detected (LOOP_DETECTED). Recursive requests to the same deployment cannot be processed."
npx @insforge/cli diagnose --ai "I invoked edge function https://kttprzh4.functions.insforge.app/newton, got error: 508: Loop Detected (LOOP_DETECTED)\n\nRecursive requests to the same deployment cannot be processed."Read the diagnosis and suggestions, then verify with:
# Verify with function logs
npx @insforge/cli logs function.logs --limit 50
# Verify the function code doesn't actually call itself
npx @insforge/cli functions code newtonFrequently paired with
- All other primitives —
--aiconsumes them and you verify back against them. Treat AI assist as a router that points at primitives; the primitives are the ground truth.
DB health
Postgres system views (pg_stat_*, pg_locks, pg_class) exposed as named checks. The primary primitive for current database state — connection pool, query performance, lock contention, storage, index efficacy.
Command
npx @insforge/cli diagnose db [--check <checks>]--check accepts comma-separated names. Default all. Run no-arg first when triaging unknown DB issues.
Checks
| Check | Underlying view | What it tells you |
|---|---|---|
connections | pg_stat_activity | Active vs idle vs idle-in-transaction count; how close to pool limit |
slow-queries | pg_stat_statements | Queries by total/mean exec time; which queries dominate load |
bloat | pg_class, pg_stats | Table/index dead-row bloat (vacuum lag, write-heavy tables) |
size | pg_class size functions | Table and index disk footprint |
index-usage | pg_stat_user_indexes | Indexes that are never scanned (unused) vs heavy hitters |
locks | pg_locks + pg_stat_activity | Lock contention, blocking queries, deadlock candidates |
cache-hit | pg_statio_* | Buffer cache hit ratio (low = working set exceeds RAM) |
How to read
| Reading | Likely problem | Next step |
|---|---|---|
connections near pool limit + many idle-in-transaction | Connection leak in client code | Find client missing release() or transaction not committing |
slow-queries top entry called frequently | Missing index or bad plan | Check index-usage for that table; consider migration |
bloat high on actively-written table | Vacuum not keeping up | Schedule vacuum tighter or rewrite query pattern |
index-usage shows unused indexes | Wasted write cost | Drop unused indexes (after confirming they're truly unused) |
locks with blocker/blocked pairs | Long transactions or deadlocks | Kill blocking PID after investigation, fix the lock-holding query |
cache-hit < 0.99 | Working set exceeds RAM | Tune queries to reduce buffer churn, or scale |
Boundaries
- Current snapshot, not history.
pg_stat_*resets on Postgres restart; numbers are cumulative since last reset, not a time series. - Doesn't show query text inline.
slow-queriesshows hashed query templates — get the actual SQL from logs (postgres.logs) orpg_stat_statements.querydirectly viadb query. - Doesn't evaluate RLS. For "which policy is making this query slow," use policies.
Example
User reports: "this one query is slow — SELECT * FROM orders WHERE user_id = ... ORDER BY created_at DESC".
# 1. Confirm it's in the slow-query log and check index usage on the table
npx @insforge/cli diagnose db --check slow-queries,index-usage
# 2. Verify no lock contention from a concurrent writer
npx @insforge/cli diagnose db --check locks
# 3. Cross-reference postgres.logs for the actual query plan / errors
npx @insforge/cli logs postgres.logs --limit 100Frequently paired with
- logs —
postgres.logshas the query text, plans, and error context behindslow-queries/locksaggregates - policies — when slow queries are RLS-gated, the policy may be adding hidden joins
- metrics — DB pressure usually shows as EC2 CPU/memory pressure; cross-reference timestamps
- advisor — performance category often pre-flags the same issues
slow-queries/index-usagewould surface
Deploy state
History and per-deploy metadata for both frontend deployments (Vercel) and edge function deploys. The primary primitive for debugging what happened during a deploy — separate from runtime logs because deploy failures often never leave a runtime trace.
Commands
# Frontend (Vercel)
npx @insforge/cli deployments list
npx @insforge/cli deployments status <id> [--sync] [--json]
# Edge function deploys
npx @insforge/cli logs function-deploy.logs [--limit <n>]
npx @insforge/cli functions listFrontend deployments
deployments list returns recent deploys with status. deployments status <id> --json returns per-deploy metadata:
| Field | Meaning |
|---|---|
status | pending / building / ready / error / canceled |
metadata.target | Vercel deploy target (production / preview) |
metadata.fileCount | Number of files uploaded |
metadata.projectId | Vercel project ID |
metadata.startedAt | Build start time |
metadata.envVarKeys | Env var keys baked into the build (values redacted) |
metadata.webhookEventType | e.g., deployment.succeeded, deployment.error |
--sync re-fetches from Vercel (use when the local cached status looks stale).
Edge function deploys
function-deploy.logs captures backend deploy events (compile errors, push failures, registration errors). functions list confirms the final state — if the function isn't there or status != active, the deploy didn't fully take.
How to read
For "frontend deploy failed":
1. deployments list — find the failing deploy id 2. deployments status <id> --json — read status and the metadata block; webhookEventType usually names the failure stage 3. Reproduce locally: npm run build — server deploys often surface the same error that local build would (faster to debug locally) 4. Verify envVarKeys matches what the app needs at runtime
For "function deploy failed":
1. npx @insforge/cli logs function-deploy.logs --limit 50 — find the build/push error 2. npx @insforge/cli functions list — confirm the function did or didn't make it into the active list 3. Re-run npx @insforge/cli functions deploy <slug> if needed and capture stdout for the explicit error
Boundaries
- Doesn't surface Vercel build logs inline. Detailed Vercel build output lives in the Vercel dashboard or via
vercel logs; this primitive surfaces the deploy event metadata. - Doesn't include compute service (Fly) deploy errors. For compute services use
npx @insforge/cli compute events <id>(machine lifecycle); container stdout/stderr is not yet exposed. - Distinct from runtime errors. A function with a successful deploy can still error at invoke time — that's logs
function.logs, not this primitive.
Example
User reports: "I ran deployments deploy and got an error."
# 1. Get the most recent deploy id and status
npx @insforge/cli deployments list
# 2. Full metadata on the failed one
npx @insforge/cli deployments status <id> --json
# 3. Reproduce locally to see the actual build error
npm run buildUser reports: "functions deploy my-handler failed."
# 1. Re-run to capture the explicit error
npx @insforge/cli functions deploy my-handler
# 2. Backend-side deploy log
npx @insforge/cli logs function-deploy.logs --limit 50
# 3. Confirm the function isn't half-deployed
npx @insforge/cli functions listFrequently paired with
- logs —
function-deploy.logsis the source;function.logsis separate (runtime, not deploy) - metadata — verify the function ended up
activeafter deploy
Error objects
The error envelope returned by SDK calls and HTTP responses. The entry-point primitive — almost every reactive debug starts by reading the error and routing to the right log source / primitive.
This primitive isn't a command; it's the protocol for reading what the client got back, plus the routing tables that turn an error into "look here next."
SDK error envelope
const { data, error } = await client.database.from('posts').select('*')
// error: { code: string, message: string, details?: string }Read all three fields. code routes to the right log source; message and details provide context.
Error code → log source
| Code prefix | Source | Look in |
|---|---|---|
PGRST* (PostgREST errors: PGRST204, PGRST301, etc.) | PostgREST API layer | logs postgREST.logs |
SQL state codes (23505 unique violation, 42P01 undefined table, etc.) | Postgres | logs postgres.logs |
AUTH_* / OAuth errors | Backend auth | logs insforge.logs |
| Generic 500 / no code | Server error in backend | logs — start with diagnose logs aggregate, then drill |
HTTP status routing
| Status | What it means | Where to look |
|---|---|---|
| 400 | Request payload/params malformed | logs postgREST.logs for validation error |
| 401 | Auth token missing / invalid / expired | logs insforge.logs + metadata auth config |
| 403 | RLS policy or permission denied | logs postgREST.logs + policies + metadata |
| 404 | Endpoint or resource doesn't exist | metadata — verify the table/function/bucket exists |
| 429 | Rate limit hit | No logs — see 429 note below |
| 500 | Server-side error | logs diagnose logs (aggregate) → drill into specific source |
| 502 / 503 / 504 | Gateway / upstream timeout | Route by URL subsystem — see 5xx gateway note |
429 — special case
429 responses are not logged in any source and the backend does not return Retry-After or X-RateLimit-* headers. Checking logs is useless.
What to do:
1. Read the client code that issued the request. Look for: loops without throttling, missing debounce, retry-on-failure without exponential backoff, parallel calls that could be batched. 2. Check metrics for overall backend load context — is the system being slammed? 3. The fix is always client-side: reduce frequency, add backoff/debounce, batch operations.
5xx gateway timeout (502 / 503 / 504) — route by URL subsystem
The status alone doesn't tell you which subsystem timed out. Route by the URL path:
| URL pattern | Subsystem | Look in |
|---|---|---|
/api/database/records/... or /api/database/... | PostgREST → Postgres | logs postgREST.logs then postgres.logs; db-health locks, slow-queries |
/functions/<slug> | Edge function | logs function.logs; check function isn't crash-looping |
/api/auth/... | Auth backend | logs insforge.logs |
/api/storage/... | Storage | logs insforge.logs |
| Any path during a system-wide spike | EC2 saturation | metrics --range 1h |
Example
User pastes: POST /api/database/records/posts returned { code: "PGRST204", message: "Column not found" }.
1. Read code: PGRST* → PostgREST source. PGRST204 specifically means column not found — a select / columns / order / filter parameter references a column that doesn't exist on the table. 2. Read message / details to identify the offending column name. Verify the table schema with npx @insforge/cli db tables or npx @insforge/cli metadata --json. 3. Drop into postgREST.logs for the full error context if details is empty:
npx @insforge/cli logs postgREST.logs --limit 50Frequently paired with
- logs — every code routes to a log source for the actual error context
- policies — 403 always needs policy inspection
- metadata — 404 / config-related codes need metadata to confirm the configured state
- ai-assisted — when the code is unfamiliar or the error spans subsystems, hand it to
diagnose --ai
Logs
Time-stream of events emitted by each backend service. The primary primitive for finding when something failed and what the backend was doing at that moment.
Command
npx @insforge/cli logs <source> [--limit <n>]Default limit: 20. Source names are case-insensitive (postgrest.logs works the same as postgREST.logs).
Sources
| Source | What it contains | Reach for when |
|---|---|---|
insforge.logs | Main backend (auth, API gateway, realtime, edge function dispatcher, deploy controller) | Auth/OAuth errors, realtime WS errors, generic 5xx, signup/login failures |
postgREST.logs | PostgREST API layer (REST/CRUD over the database) | 400 (payload), 403 (RLS denied), PGRST* error codes |
postgres.logs | PostgreSQL itself | SQL errors, query warnings, slow query log, deadlock, constraint violations |
function.logs | Edge function execution (per-invocation runtime) | Function threw / timed out / unhandled rejection |
function-deploy.logs | Edge function deploy (build + push) | functions deploy failed; function isn't in functions list |
Cross-source aggregate
npx @insforge/cli diagnose logs [--source <name>] [--limit <n>]Aggregates error-level only rows across all sources. Use first when you don't know which source the error lives in.
How to read
Each line has timestamp + source + level + message. When chasing a known-time symptom:
1. Get the approximate timestamp from the user (when did the request fail?) 2. Increase --limit until the window covers it (start 50, bump to 200 if needed) 3. Look for the level (ERROR / WARN) and message — the message usually names the failing component
For request-correlated symptoms (single failing URL), look for the request line in postgREST.logs (REST calls) or insforge.logs (auth/realtime/function dispatch) — both include the URL path.
Boundaries
- Logs are streamed, not retained forever. If the user reports something from days ago, you may not find it. State this explicitly instead of guessing.
- 429 responses are NOT logged. Rate limit hits don't appear in any source — confirm via error-objects status code and check metrics for backend load context.
- `diagnose logs` filters to errors only. For warnings or info-level activity, query the specific source directly.
Example
User reports: POST /api/database/records/posts returned 500 around 14:32.
# Aggregate first to see if the error surfaces anywhere
npx @insforge/cli diagnose logs --limit 100
# If it's a CRUD path, postgREST is the likely source
npx @insforge/cli logs postgREST.logs --limit 100
# If postgREST log shows "SQL error", drop into postgres
npx @insforge/cli logs postgres.logs --limit 100Frequently paired with
- error-objects — start there to pick the right source from the error code/HTTP status
- db-health — when postgres.logs shows slow/locked queries, confirm with
pg_stat_* - policies — when postgREST.logs shows RLS denial, inspect which policy fired
- metadata — when logs show auth/function/channel errors, verify the configured state
Metadata
Declarative dump of the backend's configured state: auth provider config, database tables, storage buckets, edge functions, AI models, realtime channels. The primary primitive for what the project is set up to do — used to confirm configuration matches expectations, find misconfiguration, and detect drift.
Command
npx @insforge/cli metadata [--json]--json for structured output (preferred when extracting fields for follow-up commands).
What you see
| Section | Contains |
|---|---|
| Auth | Configured providers (email/password, OAuth providers, third-party JWT), JWT config, allowed redirect URLs |
| Database | Tables with schema (columns, types), indexes, triggers |
| Storage | Buckets with public flag and size limits |
| Functions | Edge functions with slug, status (active / inactive), runtime |
| AI | Configured models, OpenRouter key presence |
| Realtime | Channel patterns and enabled flag |
How to read
For "is this thing configured the way I think?":
| Symptom | Section to check | What to look for |
|---|---|---|
| OAuth callback errors | Auth | Provider enabled? Redirect URLs match the callback in the request? |
| 401 / token-expired everywhere | Auth | JWT secret rotation, third-party provider integration mismatch |
404 on /api/database/records/<name> | Database | Table exists in the dump? Spelling? |
| Storage upload silently public | Storage | Bucket public: true when it should be false |
| Edge function returns 404 | Functions | Function in list with status: "active"? |
functions deploy succeeded but invoke fails | Functions | Function status — may be inactive |
| Realtime channel "doesn't exist" | Realtime | Channel pattern matches what client subscribes to? enabled: true? |
Boundaries
- Configuration state, not runtime state. Tells you what's declared, not what's currently broken. A function with
status: activemay still be crashing on every invocation — pair with logs (function.logs). - Doesn't show RLS policies. For RLS use policies; metadata only confirms the table exists.
- Snapshot at query time. Just-applied migrations or deploys may not yet be reflected — wait a moment and re-query if you suspect staleness.
Example
User reports: "OAuth login with Google redirects but then errors out."
# 1. Pull current auth config
npx @insforge/cli metadata --json
# 2. In the auth section, confirm:
# - google provider enabled: true
# - redirect URLs include the exact callback the app uses
# (e.g., https://myapp.com/auth/callback — protocol + host + path must match)
# 3. If config looks right, check insforge.logs for the OAuth error
npx @insforge/cli logs insforge.logs --limit 50Frequently paired with
- logs — metadata says "configured" but logs say "actually broken"; pair to distinguish config drift vs runtime failure
- policies — metadata confirms the table; policies show the RLS gating it
- advisor — security/health issues often name a configured object (bucket, secret, function) for inspection
Metrics
EC2 instance time-series telemetry: CPU, memory, disk, network. The primary primitive for confirming system-wide resource pressure vs an isolated request issue.
Command
npx @insforge/cli diagnose metrics [--range 1h|6h|24h|7d] [--metrics <list>]Default range: 1h.
What you see
| Metric family | Indicates |
|---|---|
| CPU | Compute saturation (sustained >80% = trouble; spike & recover = normal) |
| Memory | Memory pressure (rising over time → leak; near limit + OOM kills → resize) |
| Disk | Storage fill rate, IO saturation (read/write throughput, queue depth) |
| Network | Inbound/outbound bandwidth, packet rate (sudden spike = traffic surge or attack) |
Range selection
| Symptom | Range | Why |
|---|---|---|
| Active incident ("everything is slow right now") | 1h | High-resolution to catch the spike |
| "It was slow ~6 hours ago, what happened?" | 6h | Cover the window with reasonable resolution |
| "Has performance degraded this week?" | 24h or 7d | Trend analysis, not point-in-time |
| Pre-launch baseline | 7d | Establish normal range before traffic |
How to read
1. Start from baseline: what does the normal range look like for this metric? Always look at the trend, not a single point. 2. Correlate to events: spike at a specific timestamp → cross-reference logs for what was happening then. 3. Distinguish saturation vs spike:
- Sustained high = saturation → scale up or fix the load source
- Brief spike + recovery = normal burst → not actionable on its own
Boundaries
- Instance-level only. Metrics show the EC2 box's resource use, not per-request latency or per-query cost. For request-specific perf, combine with logs (
postgres.logsfor slow queries) and db-health. - Doesn't explain causes. Metrics show symptoms (CPU high), not causes (which query, which function). Pair with logs or db-health for root cause.
- Edge function execution is separate. Functions run in their own runtime; their resource use isn't in EC2 metrics.
Example
User reports: "API has been slow for the last 2 hours."
# 1. Check resource pressure over the right window
npx @insforge/cli diagnose metrics --range 6h
# 2. If CPU/memory spiked at a timestamp, line it up with errors
npx @insforge/cli diagnose logs --limit 200
# 3. If DB is the bottleneck (Postgres-heavy CPU patterns)
npx @insforge/cli diagnose dbFrequently paired with
- db-health — DB is the most common bottleneck behind CPU/memory pressure
- logs — correlate metric spikes to log events at the same timestamp
- advisor —
--severity criticalmay already flag the underlying cause (e.g., missing index)
Policies
Active RLS (Row-Level Security) rules pulled from Postgres's pg_policies system view. The primary primitive for what RLS is currently allowing or denying — distinct from "what config we meant to deploy" (that lives in metadata / migration history).
Command
npx @insforge/cli db policiesReturns every policy: table, schema, policy name, command (SELECT / INSERT / UPDATE / DELETE / ALL), target role, USING expression, WITH CHECK expression.
Only specific InsForge-managed tables allow developer RLS changes. Check the relevant module skill or CLI reference before writing policy SQL for a managed table. If that table is listed as allowing RLS changes, normal RLS operations are allowed and should go in migrations.
Policy anatomy
| Field | Meaning |
|---|---|
tablename | Which table the policy applies to |
cmd | Which operation it gates (read/write/all) |
roles | Which DB roles the policy applies to (typically authenticated, anon, public) |
qual (USING) | Filter expression: which existing rows the role can see/modify. Applied to SELECT, UPDATE, DELETE. |
with_check | Validation expression: which new/modified rows are allowed. Applied to INSERT, UPDATE. |
permissive / restrictive | Permissive policies OR together; restrictive AND. Most InsForge projects use permissive. |
How to read
For "why was this request denied?":
1. Identify the table from the request URL (/api/database/records/<table>). 2. List policies for that table — note cmd and roles. 3. Walk the USING / WITH CHECK expressions against the actual request:
- No policy for that role+cmd combo → denied by default. Need to add a policy.
- `USING` evaluates false for this row → row is invisible / not modifiable. Confirm the helper (e.g.,
auth.uid()returns the expected user_id). - `WITH CHECK` evaluates false on insert → the new row's columns violate the policy. The insert payload is wrong, or the policy is too strict.
Common RLS bug shapes
| Symptom | Likely cause |
|---|---|
| All authenticated users see all rows (no isolation) | Policy is USING (true) — too permissive; restrict by user_id column |
| Authenticated user gets empty result on own data | Wrong helper function (auth.uid() returns UUID; if user_id column is TEXT from third-party auth, use requesting_user_id() instead) |
| Insert fails for owner with "new row violates RLS policy" | Missing WITH CHECK matching the USING, or WITH CHECK references columns not in payload |
| Third-party auth (Clerk/Auth0/etc.) users get blanket deny | Wrong helper (auth.uid() expects InsForge-issued JWT; third-party providers need requesting_user_id() with the right claim extraction) |
| Anonymous user can read sensitive table | RLS not enabled on the table (forgot ALTER TABLE ... ENABLE ROW LEVEL SECURITY), or a policy applies to public / anon role without filter, or the connection is using a role with BYPASSRLS |
Boundaries
- Lists active policies, doesn't simulate. Doesn't tell you "this specific request would be allowed" — combine with logs (
postgREST.logs) to see the actual denial event. - Doesn't include the helper function bodies.
auth.uid()/requesting_user_id()are SQL functions; inspect viadb queryif you need to verify they return what you expect. - Only listed managed tables allow RLS changes. Check the relevant module skill or CLI reference before changing RLS on a managed table. If the table is listed, put normal RLS operations in migrations; keep normal schema changes in
public.
Example
User reports: "logged-in user gets 403 trying to GET /api/database/records/posts".
# 1. See the denial event
npx @insforge/cli logs postgREST.logs --limit 50
# 2. List policies on the posts table
npx @insforge/cli db policies
# 3. If the project uses third-party auth, verify the helper
npx @insforge/cli db query "SELECT requesting_user_id()"
# 4. Confirm the user's JWT contains the expected claim (auth config in metadata)
npx @insforge/cli metadata --jsonFrequently paired with
- logs —
postgREST.logsshows the actual RLS denial events; pair with policies to identify which rule fired - metadata — auth config determines which claim feeds
auth.uid()/requesting_user_id() - advisor — security category often flags missing/overly-permissive RLS policies