forge-idiomatic-engineer

Forge-focused engineering workflow for Rust applications with generated frontend bindings. Activate this skill for repositories containing a `forge.toml` file,…

INSTALLATION
npx skills add https://github.com/isala404/forge --skill forge-idiomatic-engineer
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

$27

Always read references/pitfalls.md and references/resilience.md once per session — the script doesn't print them.

Fallback when the script is unavailable (older checkout, sandboxed env): read forge.toml, Cargo.toml, src/main.rs, src/functions/mod.rs, and the most recent file under migrations/.

These files change only when you write to them — re-reading mid-session is almost always wasted context.

After auto-compaction, trust the summary's file inventory. Don't re-read main.rs / mod.rs to confirm something the summary already documented — only re-read if you're about to write to them and need exact current content. If a compaction attaches a file as an <attachment>, treat it as already in context; don't issue a fresh Read.

When you do need to read a file, read it fully in one call. Don't issue overlapping ranges (offset 200 then offset 1) — combine into a single read at offset 1 with a wide limit. Forge handler files are rarely larger than 600 lines.

Handler Types

Concept

Macro

Struct suffix

Registration

Read-only query

#[forge::query]

Query

.register_query::<FnNameQuery>()

Data mutation

#[forge::mutation]

Mutation

.register_mutation::<FnNameMutation>()

Background job

#[forge::job]

Job

.register_job::<FnNameJob>()

Scheduled task

#[forge::cron]

Cron

.register_cron::<FnNameCron>()

Durable workflow

#[forge::workflow]

Workflow

.register_workflow::<FnNameWorkflow>()

Long-running process

#[forge::daemon]

Daemon

.register_daemon::<FnNameDaemon>()

External HTTP event

#[forge::webhook]

Webhook

.register_webhook::<FnNameWebhook>()

AI agent tool

#[forge::mcp_tool]

McpTool

.register_mcp_tool::<FnNameMcpTool>()

Or use .auto_register() to pick up all handlers via inventory.

Naming Rules

  • pub async fn handlers only — private functions fail codegen.
  • snake_case fn names → macro generates PascalCase + type suffix. Do not include the type in the fn name (heartbeat, not heartbeat_daemon, or you get HeartbeatDaemonDaemon).
  • #[forge::model] must be the first attribute on a struct.

Context API at a Glance

Memorize so you don't reach into the forge-core source mid-implementation:

  • ctx.db()ForgeDb (a sqlx::Executor). Pass directly to query macros: sqlx::query_as!(...).fetch_one(ctx.db()).await?.
  • ctx.conn().await?ForgeConn<'_> (transactional, mutations only). Pass &#x26;mut conn to query macros.
  • ctx.user_id()Result<Uuid> on QueryContext and MutationContext. Returns ForgeError::Unauthorized if no principal. **There is no ctx.auth() method on MutationContext.**
  • ctx.db_conn()DbConn<'_> for shared helpers that must work in both queries and mutations. DbConn has an inverted convention (call .fetch_* on the DbConn, passing the query) — see references/patterns.md.
  • Let type inference name the bindings (let mut conn = ctx.conn().await?). Don't import ForgeConn / ForgeDb / DbConn and write explicit types unless a helper signature requires it.

Workflow

  • Orient — read the session-start file list above plus references/pitfalls.md and references/resilience.md. Detect frontend via frontend/package.json (Svelte) or frontend/Cargo.toml (Dioxus).
  • Plan the slice — decide which handlers, migrations, and frontend changes belong in this PR before writing code. Surgical, vertical, one feature.
  • Checkpoint loop, one handler at a time:
  • Run forge new <kind> <name> instead of writing the file by hand. It scaffolds the right macro defaults, appends pub mod <name>; to src/functions/mod.rs, and inserts mod functions; in src/main.rs if missing. Kinds: query, mutation, job, cron, workflow, daemon, webhook, mcp_tool, model, enum.
  • Edit the scaffolded file: replace placeholder SQL/business logic with the real implementation.
  • forge check. It auto-prepares the .sqlx/ cache when sources are newer, so you don't need a separate forge migrate prepare step in the common case.
  • If it fails, fix the root cause and re-run only the failing step. Do not write the next handler with errors outstanding.
  • Move to the next handler.
  • **forge generate** after backend changes settle. Never edit generated files.
  • Frontend — wire the UI against the generated bindings. forge test for Playwright E2E.
  • Final passforge check clean, forge test green, write a brief change summary.

When the user says "fix it" / "can you fix it" after you've diagnosed a problem, fix it — don't ask for re-confirmation. Only pause to confirm for destructive actions (data deletion, schema drops, force pushes).

Architectural Defaults (choose upfront)

  • Auth: Social OAuth, password + HS256, or RS256 — pick before coding (see patterns.md). Social logins must link via the user_identities table.
  • Env: ctx.env_require() / ctx.env_or(), never std::env::var().
  • HTTP: ctx.http() for RPC, ctx.raw_http() when you need bytes_stream() or custom redirect policy.
  • SQL: sqlx::query!() / query_as!() bang-macros only. Run forge migrate prepare after schema or query changes — see Compile-Loop Hard Rules.
  • Jobs/workflows: dispatch only inside mutations (transactions are on by default). Never set transactional = false on a mutation that dispatches.
  • Shared logic: extract to src/utils/ the moment two handlers need it.

Reference Selection Guide

Task

Reference

Any new handler (mandatory read)

references/resilience.md

Macros, context, errors, configuration, CLI

references/api.md

Backend patterns: jobs, workflows, auth, webhooks, compile loop

references/patterns.md

Copy-paste recipes (user fetch, plan gating, email, S3, payments, AI)

references/recipes.md

Frontend principles (reactivity, subscriptions, errors, uploads)

references/frontend.md

SvelteKit specifics (runes, stores, auth helper)

references/frontend/svelte.md

Dioxus specifics (hooks, signals, auth keying)

references/frontend/dioxus.md

Writing tests (backend builders + Playwright scenarios)

references/testing.md

Debugging build or runtime errors

references/pitfalls.md

Engineering Principles

  • Design for failure: auth drops, entities vanish, networks fail. See resilience.md.
  • Zero dead code: delete unused code and replaced patterns entirely. Workspace lints deny dead_code, unwrap_used, panic, indexing_slicing, unsafe_code.
  • Surgical diffs: thin vertical slice per PR.
  • Boundary validation: validate at handler entry, return ForgeError variants (never unwrap/expect/panic!).
  • Scope enforcement (compile-time enforced by the macro): private queries must filter by user_id / owner_id. ctx.user_id() for the principal. Opt out with #[query(unscoped)] only for shared/admin data.
  • Transactional dispatch (compile-time enforced): dispatch_job and start_workflow require a transactional mutation. Since transactions are on by default, just don't set transactional = false on mutations that dispatch.
  • System tables are off-limits (forge check enforced): never INSERT/UPDATE/DELETE on forge_* tables. Use dispatch_job, start_workflow, record_signal.
  • Migrations: -- @up / -- @down markers. Enable reactivity with SELECT forge_enable_reactivity('table_name');. No IF NOT EXISTS.
  • Not-found handling: fetch_optional().await?.ok_or_else(|| ForgeError::NotFound(format!(...))).

Output Contract

On completion, report:

  • Changes: files touched, failure modes handled, tests added (include failure paths).
  • Verification: commands run, blockers, final forge check result.
  • Review: resilience gaps, assumptions.

Every handler must survive revoked auth, deleted entities, concurrent modification, and network drops.

BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card