Keep your firebase.json, SDKs and ports, and change one word in your script. No Java to install, and your data survives restarts.
40Ãfaster writes5.1 ms against 208.2 ms, median
10Ãless memory2.11 GiB against 22.57 GiB at peak
0.59 sto restart with your dataagainst 30.8 s
demo-shoprecorded from firenook 0.2.0
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ® â â â ââ â â âââââ â firenook 0.2.0 â â âââââ ââââ demo-shop · picking up the data saved just now â â ââââ ââââ Node 24.20.0 · data in .firenook/state â â âââ â â â ââ Start-up ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 796 ms â⤠â â â Firestore â 255 ms 1,207,802 documents â â Auth â 255 ms 64,000 users â â Storage â 255 ms 5,400 objects â â Functions â 423 ms 4 functions â â Pub/Sub â 0 ms 1 schedule â â â ââ â All emulators ready ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ⤠â â â Console http://127.0.0.1:4000/console â â Ports Firestore 8080 Auth 9099 Storage 9199 Functions 5001 Pub/Sub 8085 Hub 4400 â â â â°ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ⯠ââ Logs ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 21:05:40 â checkout 117 ms http · POST / · 201 21:05:40 â sendReceipt 6 ms firestore · orders/qXoV1oOgJ0IILQs5psZP created â receipt queued order qXoV1oOgJ0IILQs5psZP · total 36 21:05:42 â checkout 4 ms http · POST / · 201 21:05:42 â sendReceipt 1 ms firestore · orders/ZskDC6u3kTKSGalf4o5L created â receipt queued order ZskDC6u3kTKSGalf4o5L · total 32 21:05:43 â stripeWebhook 1 ms http · POST / · 500 â Unhandled error Error: No signatures found matching the expected signature for payload â at functions/index.js:24:11 â + 9 more lines · open in console ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â running 6s · 5 calls · 1 failed o console r reload ? keys q quit
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ® â â â ââ â â âââââ â firenook 0.2.0 â â âââââ ââââ demo-shop · picking up the data saved jus⦠â â ââââ ââââ Node 24.20.0 · data in .firenook/state â â âââ â â â ââ Start-up ââââââââââââââââââââââââââââââââââââââââ 602 ms â⤠â â â Firestore â 240 ms 1,207,804 documents â â Auth â 240 ms 64,000 users â â Storage â 240 ms 5,400 objects â â Functions â 299 ms 4 functions â â Pub/Sub â 0 ms 1 schedule â â â ââ â All emulators ready ââââââââââââââââââââââââââââââââââââ⤠â â â Console http://127.0.0.1:4000/console â â Ports Firestore 8080 Auth 9099 Storage 9199 â â Functions 5001 Pub/Sub 8085 Hub 4400 â â â â°ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ⯠ââ Logs ââââââââââââââââââââââââââââââââââââââââââââââââââââââ 21:05:49 â checkout 115 ms http · POST / · 201 21:05:49 â sendReceipt 6 ms firestore · orders/E⦠â receipt queued â order EYi9LKG7xQ53eLrWktHm · total 36 21:05:50 â checkout 6 ms http · POST / · 201 21:05:50 â sendReceipt 2 ms firestore · orders/C⦠â receipt queued â order CU0LwsLgczq054BqsEuH · total 32 21:05:51 â stripeWebhook 1 ms http · POST / · 500 â Unhandled error Error: No signatures found â matching the expected signature for payload â at functions/index.js:24:11 â + 9 more lines · open in console ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â running 6s · 5 calls · 1 failed o console r reload ? keys q quit
$ npx firebase emulators:start
Change one word
Same flags, same ports, same export format. Your project stays as it is, and firebase-tools stays for deploying.
- "emulators": "firebase emulators:start --import ./data"+ "emulators": "firenook emulators:start --import ./data"
firebase.json and .firebaserc
Read the way the Firebase CLI reads them.
Rules, indexes, Functions
Your code and config stay as they are.
Your SDKs
connectFirestoreEmulator, FIRESTORE_EMULATOR_HOST and the rest connect unchanged.
Your data
Imports and exports the official format, both ways.
Eight emulators, on the ports you already use
Your SDKs connect to them as they connect to Googleâs: the same hosts, the same ports, the same environment variables.
Firestore
8080Native and web SDKs, realtime listeners, Security Rules, named databases, and the official import and export.
orders12 documents
- XXfs8ZLaWvmMOeaVAcw8
- 5XSNbW90qkxiTbqQilu1
- mqr7wc5Vjb6d5y75tfKy
- ijO11GokICQ0ki9Ta4p9
- c0yT9Jkt9NGpiX7HMV9r
createdAt2026-10-23 13:06:17.872 UTC
items[{ price: 54, qty: 1, sku: "hoodie" }, { price: 28, qty: 1, sku: "tee" }]
total82
Authentication
9099Every operation of the official Auth emulator: password, email link, phone, MFA, passkeys, tenants and blocking functions.
Users12
- AAmara Abaraamara@example.compassword
- EElif Demirelif@example.compassword
- IInes Duarteines@example.compassword
Cloud Storage
9199The Firebase and Cloud Storage APIs, with Security Rules evaluated natively, firestore.get() included.
demo-shop.appspot.com / products8 files
- cap.svgimage/svg+xml404 B
- hoodie.svgimage/svg+xml408 B
- mug.svgimage/svg+xml404 B
Cloud Functions
5001HTTP, callable and streaming functions, and every trigger: Firestore, Storage, Auth, Pub/Sub, Eventarc, schedules and task queues. Code reloads on save.
Function calls25
| Time | Function | Trigger | Summary | Status | Duration |
|---|---|---|---|---|---|
| 13:06:19 | stripeWebhook | http | POST / | 500 | 1.1 ms |
| 13:06:18 | sendReceipt | firestore | orders/mzbnHY1n79leG5ioi2nD created | 200 | 1.8 ms |
| 13:06:18 | checkout | http | POST / | 201 | 6.3 ms |
| 13:06:18 | sendReceipt | firestore | orders/c0yT9Jkt9NGpiX7HMV9r created | 200 | 1.7 ms |
| 13:06:18 | checkout | http | POST / | 201 | 5.0 ms |
Pub/Sub
8085Every RPC over gRPC and HTTP/JSON: push, ordering, filters, dead-letter topics, seek, snapshots and schemas.
nightlyReport, every day 02:00: next run 2026-10-24 02:00 UTCCloud Tasks
9499Queues for onTaskDispatched, with the official retry and rate-limit behaviour.
Eventarc
9299Custom events delivered to onCustomEventPublished, and the Firebase servicesâ own.
Extensions
5001Extensions from local, vendored or registry sources, offline once vendored.
The orders, users, files and calls above are from a run of the demo project, as Firenook returned them. Realtime Database, Hosting, App Hosting and Data Connect are not emulated; a firebase.json that configures them still starts, with a warning. What each service covers.
Measured on a real application
Two hours of a production appâs traffic against each emulator in turn, every operation timed by the client.
Memory at peak
10Ã less
Official22.6 GiB
Firenook2.11 GiB
Write, median
40Ã faster
Official208 ms
Firenook5.1 ms
Listener update, median
19Ã faster
Official209 ms
Firenook11 ms
Restart with data kept
52Ã sooner
Official30.8 s
Firenook0.59 s
orderBy, limit 20
8Ã faster
Official96.3 ms
Firenook12.0 ms
CPU over two hours
61% less
Official1,586 s
Firenook616 s
The app holds 211,205 Firestore documents and 6.7 GB in Storage; both emulators ran on one server. Firenook answered 25 of 26 query shapes faster and tied on the last. How it was measured.
Your data stays where you left it
Add --keep-data and Firestore, Auth and Storage come back with all your data in about half a second, even with millions of documents. No export at every stop, no import at every start.
A crash loses at most the last second of writes, where the official emulator loses everything since its last export. A stop always closes the data cleanly.
$npx firenook emulators:start --keep-data
Official emulator
Stop: export, 50â57 sStart: import, 21.6â23.6 s
Firenook
Stop, 0.04â0.30 sStart, 0.54â0.57 s
0 s20 s40 s60 s80 s
demo-shop7 of its 35 lines
$ npx firenook emulators:exec "node --test checkout.test.mjs" firenook: Starting emulators: auth, functions, firestore, pubsub, storagefirenook functions: Loaded functions definitions from source: checkout, sendReceipt, stripeWebhook, nightlyReport.All emulators readyâ checkout takes an order (173.227708ms)â¹ pass 1â¹ fail 0firenook suite stopped cleanly
Run your tests against it
emulators:exec starts the suite, runs your command once everything is ready, with the emulator variables set, then stops and passes on the exit code.
CI gets plain lines, the same ones the official emulator prints, and there is no Java to set up first. Firenook needs only Node 24.
$npx firenook emulators:exec "npm test"
The console the Firebase emulators should have had
Googleâs Emulator UI has no page for your Functions, Pub/Sub, Cloud Tasks or Eventarc, only a log. Firenookâs console covers every service it runs, live, on the Emulator UIâs port.
Every call, with what triggered it, its outcome, its duration and its logs.
Every call, with what triggered it, its outcome, its duration and its logs.

Light and dark, works offline, sends nothing anywhere. Bookmarks to the official UIâs pages open the matching console page. Every page of the console.
Give your agent the emulator, not production
firenook mcp gives a coding agent 54 tools over the running suite. It reads the log and each function call with its error, asks the Security Rules why a request is denied, and works with your data. Nothing leaves your machine.
Sets it up for Claude Code, Cursor and VS Code in the projectâs own files. Other agents run npx firenook mcp. How agents use it.
firenook mcpdemo-shop
- You
The Stripe webhook answers 500 on my machine. Why?
functions_list_calls outcome: "failed"
failed500 stripeWebhook http POST /, 1.15 ms at 13:06:19
functions_get_call id: "e72ca3-25"
errorError: No signatures found matching the expected signature for payload
atfunctions/index.js:24:11
headershost, connection, content-type, accept, accept-language, sec-fetch-mode, user-agent, accept-encoding, content-length
body{"type":"checkout.session.completed"}
rules_evaluate service: "storage", method: "create", path: "products/mug.svg"
verdictdeny as unauthenticated
line 9allow read, write: if false;
FirestoreRead, query, count, write and delete documents
AuthenticationManage users, read sign-in codes, mint ID tokens, set claims
StorageList, read, upload, copy, move and delete files
Functions and logsInvoke a function, read each call and the log, replay a call after a fix
Security RulesAsk why a request is denied, test a draft, list denials
Pub/Sub, Tasks, EventarcPublish, peek, run tasks and schedules now, replay events
Yes, for deploying and everything else the Firebase CLI does. Firenook replaces only the emulators: install it next to firebase-tools and run your emulators with it.
Does Firenook need Java?No. Its services are native code in one npm package, with an engine for macOS, Linux and Windows, and nothing else is downloaded at install or start. Node 22, 24 or 26 runs your Functions, as it does in production.
Can I go back to the official emulator?Yes. Firenook imports and exports the official format. While Firenook runs, export with npx firenook emulators:export ./export, then start the official emulator with --import ./export.
Which services does it emulate?Firestore, Authentication, Cloud Storage, Cloud Functions, Extensions, Pub/Sub, Cloud Tasks and Eventarc. Realtime Database, Hosting, App Hosting and Data Connect are not emulated; a firebase.json that configures them still starts, with a warning.
0.2.0 is the first release for public use. Every release passes conformance replays against the official emulator and packed installs on all five platforms, and Firenook passed a two-hour benchmark against the official emulator on a real application. Commit your lockfile and upgrade on purpose.
Is it free?Yes. Firenook is open source under the Apache License 2.0.
Is Firenook made by Google?No. Firenook is an independent open-source project, not affiliated with or endorsed by Google. Firebase is a trademark of Google LLC.
Switch in three steps
One package, nothing else to install: Node 22, 24 or 26 on macOS, Linux with glibc 2.28 or newer, or Windows x64. Starting a new project instead? npx firenook init sets one up.
- 1
Install it next to firebase-tools
Keep firebase-tools for deploying: Firenook has no deploy or login command.
$npm install --save-dev firenook - 2
Check your project
This reads firebase.json the way the Firebase CLI does, and changes nothing.
$npx firenook init --adopt --dry-run - 3
Swap the command
Same flags and ports, so your app connects as before and your data imports as it is.
$npx firenook emulators:start