FireWurx automates firefly.adobe.com with your own Adobe account — no API key. Feed it a CSV of prompts and it selects the model, aspect ratio, and content type, generates, and saves every image locally. A web dashboard and a CLI share the same engine.
Last verified against Firefly: 2026-07-12. Firefly's UI and model lineup change without notice; see Keeping the model catalog current when something drifts.
New here? Read the User Guide (also available as PDF) — setup, the bulk workflow, prompt files, the Prompt Builder, speech, and troubleshooting in one document. Regenerate both with npm run guide:build after UI or catalog changes.
FireWurx drives the real Firefly website with your official Adobe account. That has real consequences:
- Generations are not free. Each generation can deduct generative credits from your Adobe account, and the cost varies per model — on current plans some Firefly models are included ("unlimited"), while partner models cost anywhere from 10 to 60 credits per generate click.
- You are responsible for your balance. Check that your account has enough credits before running a batch, and verify what a run will cost — the dashboard shows a per-run estimate before you press Start Generation, using rates read live from Firefly.
- Failed runs still bill. Adobe charges when the generation runs; a run that fails after the Generate click is still charged (FireWurx's failure reports state whether the click happened).
- Rates change. Credit costs and plan inclusions are Adobe's and can change at any time; the catalog's stored rates are a snapshot.
Both interfaces enforce a one-time acknowledgment of this notice before any generation: the dashboard shows it on first visit and the server refuses unacknowledged requests; the CLI asks on first run (set FIREWURX_ACK_CREDITS=1 for unattended use).
- Batch generation from CSV/JSON prompt files — hundreds of prompts, per-prompt model/aspect/style
- All 17 current Firefly models, including partner models (GPT Image, Gemini, FLUX, Runway)
- Verified selection: every model, aspect-ratio, and content-type choice is read back from the UI after clicking — mismatches fail loudly instead of silently generating the wrong thing
- Credit-aware failure reporting: every failure states whether it happened before the Generate click (no credits spent) or after (image may exist in your Firefly gallery and be charged)
- Session-challenge recovery: if Adobe re-authenticates mid-run, headed runs pause and wait for you; headless runs stop with recovery instructions
- Three capture paths: full-resolution download → screenshot fallback → network-response recovery
- Web dashboard (
npm run ui): prompt import with validation, Global Style Prompt + AI Image Prompt Builder, live progress, output gallery, background removal (rembg), run history. Aspect ratio is set per prompt in the CSV (aspect_ratiocolumn) — not globally, so one batch can mix sizes - Speech generation for Firefly text-to-speech batches
Requires Node.js 18+ (tested on Node 24 / Windows 11; macOS and Linux work too — all npm scripts are cross-platform via cross-env).
git clone https://github.com/uh60lblackhawk/FireWurx.git
cd FireWurx
npm install
npx playwright install chromium
# Optional: pre-fill your Adobe email for logins
copy .env.example .env # then edit FIREFLY_EMAILWorkers default to headless, so refresh the Adobe session in a visible browser first:
npm run auth:refreshA browser opens on Firefly; sign in (approve 2FA in the Adobe Access app if prompted). The session is saved to ./data/storageState.json and reused by all later headless runs.
Dashboard — npm run ui, then open http://localhost:3000. Import a prompt file, pick model/content type (aspect ratio comes from each prompt's aspect_ratio column), watch progress, browse outputs. Use npm run ui:debug (or untick "Run hidden") to watch the browser work.
CLI —
# Batch from a CSV
npm run generate:images -- --prompts examples/prompts/debug-test.csv
# Global model/aspect override, 2 variants per prompt, keep all debug artifacts
npm run generate:images -- --prompts prompts.csv --model firefly-image-4 --aspect-ratio 16:9 --variants 2 --save-artifacts all
# Speech
npm run generate:speech -- --prompts examples/prompts/speech-example.csvAll CLI commands and options
node src/cli.mjs images --prompts <path> [options]
node src/cli.mjs speech --prompts <path> [options]
node src/cli.mjs plan-batches --prompts <path> [options] # split prompts into per-model jobs (dry run)
node src/cli.mjs submit-batches --prompts <path> [options] # plan and submit to a running dashboard
node src/cli.mjs refresh-session [options]
--prompts <path> Prompts file (CSV or JSON)
--output <dir> Output directory (default: ./output)
--email <email> Adobe email (default: FIREFLY_EMAIL from .env)
--model <value> Model label, alias, or modelId
--aspect-ratio <value> Global aspect ratio override
--style <value> Global content type override (auto | photo | art)
--variants <n> Variants per prompt (default: 1)
--capture-mode <value> download | screenshot
--headless <bool> Default: true (refresh-session defaults to false)
--save-artifacts <mode> failures | all | none (default: failures)
--debug-run-dir <dir> Directory for run artifacts
--server <url> Dashboard URL for submit-batches (default: http://localhost:3000)
prompt_id,prompt_text,aspect_ratio,style,modelId
hero_01,"editorial product photo of a ceramic mug",16:9,photo,firefly-image-4
icon_01,"minimal flat illustration of a paper boat",1:1,art,firefly-image-4
banner_01,"wide banner of rolling hills at dawn",21:9,,gemini-2-5prompt_idandprompt_textare required (promptandidare accepted aliases). Everything else is optional.modelIdaccepts the id, the UI label, or a legacy alias. There is no default model: every row needs a model — from its ownmodelIdcolumn or the dashboard's Model selector — and rows without one are rejected before anything runs.styleis Firefly's content type:auto,photo, orart— and only Firefly Image 3/4/4 Ultra have that control. On any other model a non-blank style is a row-level validation error. Legacy values likePhotographicare mapped;graphicno longer exists in Firefly.aspect_ratiomust be one the chosen model supports — see the table below. Invalid combinations are rejected before anything is clicked, so they never cost credits.
Example files live in examples/prompts.
Verified live on 2026-07-12 (17 models). auto means the model offers an automatic aspect option.
| Model id | Label | Aspect ratios | Content type | Resolutions |
|---|---|---|---|---|
firefly-image-5 |
Firefly Image 5 | auto, 16:9, 4:3, 1:1, 3:4, 9:16 | — | 1K, 2K |
firefly-image-4-ultra |
Firefly Image 4 Ultra | 16:9, 4:3, 1:1, 3:4, 9:16 | Yes | — |
firefly-image-4 |
Firefly Image 4 | 16:9, 4:3, 1:1, 3:4, 9:16 | Yes | — |
firefly-image-3 |
Firefly Image 3 | 16:9, 4:3, 1:1, 3:4 | Yes | — |
gpt-image-2 |
GPT Image 2 | auto, 21:9, 16:9, 5:4, 4:3, 3:2, 1:1, 4:5, 3:4, 2:3, 9:16 | — | — |
gpt-image-1-5 |
GPT Image 1.5 | 3:2, 1:1, 2:3 | — | — |
gpt-image-1 |
GPT Image 1 | 3:2, 1:1, 2:3 | — | — |
gemini-3-1 |
Gemini 3.1 (w/ Nano Banana 2) | auto, 8:1, 4:1, 21:9, 16:9, 5:4, 4:3, 3:2, 1:1, 4:5, 3:4, 2:3, 9:16, 1:4, 1:8 | — | 512, 1K, 2K, 4K |
gemini-3 |
Gemini 3 (w/ Nano Banana Pro) | auto, 21:9, 16:9, 5:4, 4:3, 3:2, 1:1, 4:5, 3:4, 2:3, 9:16 | — | 1K, 2K, 4K |
gemini-2-5 |
Gemini 2.5 (w/ Nano Banana) | 21:9, 16:9, 5:4, 4:3, 3:2, 1:1, 4:5, 3:4, 2:3, 9:16 | — | — |
flux-2-pro |
FLUX.2 [pro] | 21:9, 16:9, 5:4, 4:3, 3:2, 1:1, 4:5, 3:4, 2:3, 9:16 | — | — |
flux-1-kontext-max |
FLUX.1 Kontext [max] | 16:9, 4:3, 1:1, 3:4, 9:16 | — | — |
flux-1-kontext-pro |
FLUX.1 Kontext [pro] | 16:9, 4:3, 1:1, 3:4, 9:16 | — | — |
flux1-1-pro-ultra-raw |
FLUX1.1 [pro] Ultra Raw | 16:9, 4:3, 1:1, 3:4, 9:16 | — | — |
flux1-1-pro-ultra |
FLUX1.1 [pro] Ultra | 16:9, 4:3, 1:1, 3:4, 9:16 | — | — |
flux1-1-pro |
FLUX1.1 [pro] | 16:9, 4:3, 1:1, 3:4, 9:16 | — | — |
runway-gen-4-image |
Runway Gen-4 Image | 16:9, 4:3, 1:1, 3:4, 9:16 | — | — |
Imagen and Ideogram models were removed from Firefly and are no longer supported. Old FireWerk (v1) ids/labels (e.g. Firefly Image 5 (Vorschau)) still resolve via legacy aliases.
The catalog lives in src/models/firefly-model-catalog.json and is generated, not hand-written. When Firefly adds/removes models or changes options, regenerate it (read-only, spends no credits):
node tools/inspect-firefly-models.mjs # iterate the live model picker -> output/dom-inspection/model-matrix.json
node tools/build-model-catalog.mjs # convert the matrix -> src/models/firefly-model-catalog.json
git diff src/models/firefly-model-catalog.json # review, then committools/inspect-firefly-dom.mjs dumps the current generate-page DOM and controls for debugging selector drift. Curated legacy aliases live in tools/build-model-catalog.mjs.
Shortcuts: npm run models:update runs the inspect → build chain; npm run models:check is a fast read-only drift check (loads the page once, diffs the live picker against the catalog, exits nonzero on drift — 0 credits). The dashboard shows a "Model catalog verified " badge and warns when the catalog is older than 30 days.
Firefly text-to-speech, with the same safety contract as images: every selection (voice, language, speed/pitch) is verified by read-back and the run refuses to generate rather than bill with the wrong setup.
Billing (live-verified 2026-07-14): 1 credit per 100 characters of script, spaces included, minimum 1 credit — e.g. 60 chars = 1 credit, 399 chars = 3, 1,043 chars = 10. Deducted from your Adobe account; rates are Adobe's and can change. FireWurx reads Firefly's own "N credits" label before each Generate click and aborts if it exceeds the estimate.
Dashboard (Type = Speech): type or dictate the script directly (or pick a CSV), choose from 45 Firefly voices (grouped by gender, searchable) and 13 languages, optionally set speed/pitch. A live character counter shows the credit estimate, and FireWurx warns when combining or splitting paragraphs across a 100-character boundary would change the cost.
CSV format (examples/prompts/speech-example.csv):
prompt_id,text,voice,language
greeting_001,"Welcome to our service!",Brittney,English (US)voice/language are validated against the catalog before anything runs; unknown names are rejected with the full list of valid options — rejections are free. Dashboard-selected voice/language/speed/pitch fill in only where a CSV row doesn't set its own (they never override the CSV).
The voice catalog lives in src/models/firefly-speech-catalog.json; regenerate it with node tools/inspect-speech-voices.mjs (read-only). node tools/dry-run-speech.mjs rehearses the entire automation against the live page without clicking Generate (0 credits) — useful before big batches. Only the Firefly Speech model is supported; partner-billed TTS models (e.g. ElevenLabs) may be added later.
Set in .env (see .env.example):
| Variable | Default | Purpose |
|---|---|---|
FIREFLY_EMAIL |
— | Adobe account email, pre-filled at login |
OUTPUT_DIR |
./output |
Where generated files land |
STORAGE_STATE |
./data/storageState.json |
Saved Adobe session |
PW_HEADLESS |
true |
Run browser hidden |
CAPTURE_MODE |
screenshot |
download (full res) or screenshot (fast) |
VARIANTS_PER_PROMPT |
1 |
Images per prompt |
ACTION_DELAY_MIN_MS / ACTION_DELAY_MAX_MS |
600 / 2200 |
Human-like jitter between UI actions |
OPERATOR_AUTH_TIMEOUT_MS |
300000 |
How long a paused headed run waits for you to re-authenticate |
Adobe periodically re-verifies sessions. In a headed run (ui:debug, --headless false, or "Run hidden" unticked) FireWurx pauses, lets you complete the sign-in in the open browser window, then resumes and re-saves the session. In a headless run it stops with AuthChallengeError — run npm run auth:refresh, then restart the batch. Prompts already completed are on disk; re-run only what's missing.
Every per-prompt failure (CLI summary, dashboard, run.json artifacts) carries a creditRisk flag:
creditRisk: false— the failure happened before the Generate button was clicked (validation, selection mismatch, page not ready). No credits were spent.creditRisk: true— the failure happened after Generate was clicked (capture failed, timeout, session drop). The image may exist in your Firefly gallery and generative credits may have been charged. Check the gallery before re-running those prompts.
- Delete
./data/storageState.jsonand runnpm run auth:refreshagain. - Note: Firefly's header shows a "Sign in" pill even when you are signed in — FireWurx ignores it and detects auth from the actual sign-in dialog, so trust FireWurx's state over the header.
The error lists the supported values, e.g. Model "Firefly Image 5" does not support the style/content-type control. Fix the CSV row (see Prompt files) — rejections are free.
FireWurx detects Firefly's credit-gate dialog and stops the run rather than burning through failed generations.
Run with --save-artifacts all and check the run directory under output/ — it contains page state snapshots, event logs, and any network-recovered images (*_recovered_*.png).
src/
cli.mjs CLI entry point
generators/ Playwright automation (Base/Image/Speech + page-state & selectors)
models/ Generated model catalog + validation API
batch/imageBatchPlanner.mjs Splits mixed prompt files into per-model jobs
ui/ Express dashboard (server.mjs + public/)
lib/utils/promptLoader.mjs CSV/JSON prompt loading
tools/ Catalog-drift + DOM inspection tools
tests/ Offline Playwright suite (fixtures mirror the real Firefly DOM)
tests/live/ Opt-in live suites (FIREFLY_LIVE=1 — spends credits)
examples/prompts/ Ready-to-run prompt files
Run the offline test suite with npm test (no credits, no login needed).
- Use your own Adobe account and respect Adobe's Terms of Service. FireWurx paces its UI actions with human-like jitter; for very large batches, run overnight or split into smaller jobs.
./data/storageState.jsoncontains your live Adobe session — keep it private.
MIT — see LICENSE. Copyright (c) 2025 FireWerk Contributors. Based on FireWerk by Yxanu.
Change 1 — Model-specific prompt format added (2026-07-17) Upon further testing it was determined that each model uses slightly different prompt styles, and therefore the Get Model Format Prompt was updated to reflect the user-chosen model. The model must therefore be chosen before creating the prompt.
