Skip to content

Concepts ​

Mental model for gform: contracts, live metadata, execution, and artifacts.

Form contract ​

A form is a YAML file (name, url, options, steps) validated by Zod. Unknown keys are rejected.

  • Library home: $GFORM_HOME/forms/<name>.yaml
  • Optional cwd override: ./forms/ when that directory exists
  • Scaffold: gform init · edit: gform edit · check: gform verify

The contract is portable — not tied to one machine’s hard-coded script. Full field map: schema.

Resolved configuration ​

What actually runs is the merged result of:

  1. Explicit CLI flags (highest)
  2. Named --policy (safe / demo / load / watch)
  3. Form YAML options starters (headed, repeat, …)
  4. Engine defaults

Run intro shows provenance so you can see which layer set headed/repeat/concurrency. Details: policies · commands/run.

Live form metadata ​

gform inspect (and the preflight on run unless --skip-inspect) reads public Forms HTML / FB_PUBLIC_LOAD_DATA_:

  • title, questions, types, options, required
  • risk flags: login wall, closed, already-responded, captcha, file upload, collect-email, …
  • branching / grid metadata (fill still follows your YAML next steps)

Authenticated inspect (--auth / --profile) is available when the public fetch is gated (common for file-upload forms). See inspect & verify.

Steps ​

Ordered actions: text, radio, checkbox, select, file, next, back, submit, pause, wait.

Questions match by exact visible labels (as inspected). File steps use nested source: — file-uploads.

Pools and variant modes ​

Pools supply alternate answers across --repeat runs.

options.variantModeBehavior
rotate (default)pool[i % length] by run index
randomPick randomly each run
zipShared index across equal-length pools (persona rows)

Without pools, --repeat + --skip-duplicates mostly skips identical fingerprints. See repeat.

Repeat and concurrency ​

  • --repeat N / -r — N child runs (batch parent + r01… children)
  • --concurrency N / -C — parallel workers, capped at 16 and at repeat
  • --delay / -D — pause between sequential runs only (-C 1; ignored when parallel). Formats: 500ms, 2s, 1m; bare number = seconds
  • --continue-on-error — keep going after child failures

Live TTY shows a worker panel; --no-live / -nl is print-and-go.

Uniqueness and fingerprints ​

MechanismScope
--onceSkip if this payload fingerprint already succeeded
--skip-duplicates / -sdSame, across a repeat wave using resolved answers
options.uniqueField-level: scope: history or batch on named questions

Skipped runs still get a small manifest (status: skipped) so history and unique ledgers stay honest.

Policies ​

Named presets that only set run behavior — they do not rewrite YAML answers:

PolicyIntent
safe1× headless, once + skip-duplicates + strict
demo1× headed (watch / assist)
load10× headless, concurrency 5, skip-duplicates, continue-on-error
watch1× headed + keep-open

List: gform policies (pol).

Auth profiles ​

Optional Google sessions under $GFORM_HOME/auth/profiles/<name>/. Opt-in per run with --auth / -A or --profile / -pr. No flag → no session loaded. auth.

Browser targets ​

Playwright launches a discovered Chromium-family browser. Prefer system Chrome for auth create. Preference: $GFORM_HOME/browsers/default.json. browsers.

Artifacts ​

Every run/batch gets a 16-hex id under $GFORM_HOME/artifacts/:

  • manifest.json / batch.json
  • config.yaml snapshot
  • run.log, screenshots, optional pw-trace.zip, content/
  • Stable reason + message on finish/skip

Browse: gform run list · run view · run last. Restore YAML: gform restore. artifacts.

Batches and child runs ​

A batch is a parent directory with child rNN/ runs. List labels single vs batch. Parent rollup shows ✓ / ✗ / ⊘ / ■ counts; child statuses and reasons stay inspectable.

Human assist ​

Soft walls (CAPTCHA, login, validation, some file UIs, pause) need headed + TTY. You complete the hard bit in the window, press Enter, continue. Headless never pauses — it fails with a tip (assist-headed-required, …). Disable pauses with --no-assist / -na. limitations.

Core SDK ​

The same engine powers the CLI:

ts
import { /* … */ } from "@zamdevio/gform-core";
// or from the root package:
import { /* … */ } from "gform/core";

Host supplies adapters; CLI stays thin. architecture.