The terminal
In a terminal, firenook emulators:start draws its own screen: how the
start-up went, where everything listens, and a line for every function
call. This page explains what each part means, the keys it answers, and the
plain output you get instead in a pipe or in CI. firenook init draws the
same kind of screen for a new project.
The screen
Section titled “The screen”This is the screen of a start that picks up kept data, in a window 76
columns wide, after three function calls, one of which failed, and a press
of ?. The empty rows above the footer are left out.
╭──────────────────────────────────────────────────────────────────────╮ │ │ │ ▄█ │ │ ▄███▀ ▄ firenook 0.2.0 │ │ ▄███▀ ███▄ demo-shop · picking up the data saved 1 minute ago │ │ ▀██▀ ███▀ Node 24.20.0 · data in .firenook/state │ │ █▀▀ │ │ │ ├─ Start-up ────────────────────────────────────────────────── 577 ms ─┤ │ │ │ Firestore ✓ 31 ms 2 documents │ │ Auth ✓ 31 ms 0 users │ │ Storage ✓ 31 ms 0 objects │ │ Functions ✓ 507 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 ────────────────────────────────────────────────────────────────
19:37:56 ✓ checkout 189 ms http · POST / · 201 19:37:56 ✓ sendReceipt 6 ms firestore · orders/oZ839UsiaAI… │ receipt queued order oZ839UsiaAIAgVCocxmS · total 36 19:37:58 ✕ stripeWebhook 2 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 19:37:59 ? keys o open the console in your browser r reload your functions e export a snapshot of the data w list the start-up warnings ? show these keys q stop Firenook, keeping your data (Ctrl-C does the … coding agent: run npx firenook mcp add in the project …
──────────────────────────────────────────────────────────────────────── ● running 6s · 3 calls · 1 failed o console r reload ? keys q quitThe banner
Section titled “The banner”The card opens with the version and three facts about this start:
- The project. A project id that does not start with
demo-is marked(a real project id). - Where the data comes from. It reads
a fresh start, orfirst start, importing the seed "<folder>"when you pass--import, orpicking up the data saved <time> agowhen kept data is resumed. - Node and the data folder. With
--keep-data, the data is in.firenook/state. Without it, every start gets its own folder under.firenook/runs/, markedfor this run, which no later start reads.
Start-up
Section titled “Start-up”One row for each emulator you start, filled in as it gets ready, with how
long it took and what it holds: documents, users, objects, functions,
schedules. A step that takes longer than 400 ms shows a progress bar.
Functions shows the codebase it is loading. A start that resumes kept data
has a Saved data row first, while it checks the seed the data came from.
An import runs Firestore, then Auth, then Storage, so the later rows say
waits for Firestore. With --build, a Build row comes first, for the
first compile:
│ Build ✓ 547 ms functions · build:watch │ │ Firestore ✓ 105 ms 0 documents │All emulators ready
Section titled “All emulators ready”| Row | Shows |
|---|---|
| Console | The console’s address, or off when firebase.json turns the UI off |
| Ports | The port of each emulator that runs, and the hub’s |
| Warning or Warnings | How many start-up warnings there are, such as 1 start-up warning · press w to show it |
| Update | A newer release, with the command that installs it (see Release check) |
A tool that watches the terminal for the words All emulators ready, such
as a VS Code task or a process manager, finds them in this heading.
Each function call is one line when it ends:
19:37:56 ✓ sendReceipt 6 ms firestore · orders/oZ839UsiaAI… │ receipt queued order oZ839UsiaAIAgVCocxmS · total 36From left to right: the time, ✓ for success or ✕ for failure, the
function, how long it took, and what caused it. For an HTTP or callable
function that is the method, the path and the status, which is yellow for
4xx and red for 5xx. For a background function it is the trigger and what
changed.
What the function logged during the call follows under the │, in its
level’s colour, with your logger’s fields after the message. Output longer
than 30 screen lines shows its start and + N more lines; the whole of it
is in the console. A thrown error shows its message, the first three stack
frames from your own code, and a link that opens the call in the console. A
call that runs for more than two seconds shows a first line marked
still running, its output as it comes, and a finished line at the end.
Lines that belong to no call show the time, a marker (· for information,
! for a warning) and the service they come from: Auth’s sign-in links
and phone codes, a Storage request that failed in the rules, a Cloud Tasks
warning. In a window 100 columns wide:
19:39:07 · auth To sign in as ada@example.com, follow this link: http://127.0.0.1:9099/emulator/action?mode=signIn&lang= en&oobCode=8QmTcBWBfsY-UIdUvaChazaoGV9KCptgtDuPmFZqagVo 0Ghb7vW6BQ&apiKey=fake-api-key&continueUrl=http%3A%2F%2 Flocalhost%3A5173%2Ffinish 19:39:07 · auth To verify the phone number +15555550100, use the code 283916. 19:39:07 ! storage get on gs://demo-shop.appspot.com/report.pdf failed in the rules: field "token" is not available on this value 19:39:08 ! tasks Tried to queue a task into a non-existent queueWhen you save a file in a Functions codebase, Firenook reloads it and says so:
19:37:28 ↻ reloaded 274 ms 4 functions · defaultWith --build, each compile adds a line, with the compiler’s errors and
where they are. TypeScript still writes its output when a file has errors,
so the codebase reloads with it:
19:52:07 ✕ build 2 errors · functions │ src/index.ts:7:9 Type 'string' is not assignable to type 'number'. │ src/index.ts:7:9 'count' is declared but its value is never read. 19:52:08 ↻ reloaded 215 ms 1 function · default 19:52:11 ✓ build no errors · functions 19:52:12 ↻ reloaded 153 ms 1 function · defaultThe footer
Section titled “The footer”The last two lines stay at the bottom of the window: how long Firenook has
run, how many calls there were and how many failed, and the keys. The keys
o and r appear only when the console is on, and r only when Functions
runs.
| Key | Does |
|---|---|
o |
Opens the console in your browser. If no browser opens, prints the address. |
r |
Reloads every Functions codebase of yours, as a save does. |
e |
Exports Firestore, Auth and Storage to .firenook/exports/<date>-<time>, in the format --import reads. |
w |
Lists the start-up warnings, or says there were none. |
? or h |
Shows the keys, and the command that gives a coding agent the MCP server. |
q or Ctrl-C |
Stops Firenook. It saves the data first. |
The keys work once the emulators are ready. q and Ctrl-C work at any
time: a stop during the start-up closes the data cleanly before Firenook
exits.
w lists every warning of the start, such as a codebase that asks for
another Node, or a schedule that cannot run on its own:
19:39:09 ! schedule of us-central1-cleanup not run automatically (time zone Mars/Olympus_Mons is not in this engine's time-zone database); run it from the console or through the Functions trigger routeWith none, it says so:
19:38:06 ✓ warnings none at start-upPressing e adds a line such as:
19:39:10 ✓ exported 32 ms .firenook/exports/2026-10-22-193910A stop ends with a line that says where the data is:
19:39:42 ✓ stopped 81 ms everything is kept in .firenook/stateWhen your functions do not load
Section titled “When your functions do not load”What happens depends on when.
At the start, a project whose firebase.json has a Functions codebase
needs at least one function. When no codebase loads any, Firenook does not
start: the card says Functions runtime discovered 0 functions; at least 1 required, with the error from your code under it. Fix it and start again,
or pass --minimum-functions 0 to run the rest without them. Every other
emulator then starts, and the card names the error with the code around it
(trimmed):
├─ Start-up ────────────────────────────────────────────────────────────── 210 ms ─┤ │ │ │ Firestore ✓ 87 ms 0 documents │ │ Auth ✓ 87 ms 0 users │ │ Storage ✓ 87 ms 0 objects │ │ Functions ✕ 97 ms your functions did not load · 0 functions │ │ Pub/Sub ✓ 0 ms 0 schedules │ │ │ ├─ ✕ Your functions did not load ──────────────────────────────────────────────────┤ │ │ │ Error SyntaxError: Unexpected token ';' │ │ Where functions/index.js:14 │ │ │ │ const x = ; │ │ ^ │ │ │ │ Next fix it and save: Firenook loads it again by itself. Every │ │ emulator keeps running │ │ │ ├─ ! All emulators ready, except your functions ───────────────────────────────────┤When some functions do load, from another codebase or an Extension, a codebase that does not is shown on the card with its error in the same way, every emulator runs, and the next save loads it again.
Once the emulators run, a save that breaks a codebase does not stop anything. The log shows the error where it is, and the version from before the save keeps answering:
19:37:32 ✕ reload failed 106 ms default │ SyntaxError: Unexpected token ';' functions/index.js:14 │ const x = ; │ ^ │ still running the version loaded at 19:37:28 · open in consoleFix it and save again, and the reloaded line follows.
When Firenook cannot start
Section titled “When Firenook cannot start”The card says what went wrong, how to fix it, and what became of the data,
and the command exits with code 1. A port in use names the program that
holds it, with the command that stops it and a free port to put in
firebase.json:
├─ Start-up ───────────────────────────────────────────────────────────── stopped ─┤ │ │ │ Firestore ✓ 90 ms 0 documents │ │ Auth ✕ 90 ms port 38212 is taken │ │ Storage ✓ 90 ms 0 objects │ │ Functions · not started │ │ Pub/Sub · not started │ │ │ ├─ ✕ Firenook could not start ─────────────────────────────────────────────────────┤ │ │ │ Problem port 38212 for Auth is held by firenook (PID 94724): another │ │ Firenook │ │ │ │ Fix stop it: kill 94724 │ │ or give Auth a free port in firebase.json: │ │ "emulators": { "auth": { "port": 38218 } } │ │ │ │ Data nothing of yours was changed │ │ │ ╰──────────────────────────────────────────────────────────────────────────────────╯The other failures work the same way. Kept data whose seed changed names
the files that changed and gives the firenook state:adopt-seed command
that keeps the data (see Seeds and imports). Data that
another Firenook is using says so. A repair after an unclean stop shows how
far it has got (see Recovery after a crash). The
card says nothing was changed only when nothing could have been.
When the engine stops unexpectedly
Section titled “When the engine stops unexpectedly”If the engine is killed or crashes while it runs, the screen ends with a card that says so, and the command exits with code 1:
├─ ✕ Firenook stopped unexpectedly ─────────────────── signal SIGKILL ─┤ │ │ │ Data the next start checks .firenook/state first, and │ │ repairs it if it needs to │ │ │ ╰──────────────────────────────────────────────────────────────────────╯Killing the firenook command itself, by closing its terminal pane or with
kill -9, is different: the engine notices, saves the data and stops, and
frees the ports.
Plain output
Section titled “Plain output”Firenook prints plain lines, with no screen, when:
- the output goes to a pipe or a file, or input does not come from a terminal;
CIis set, as it is in GitHub Actions and most CI services (CI=false,CI=0and an emptyCIdo not count);TERM=dumb;FIRENOOK_PLAIN=1;- you pass
--plain; - the command is
emulators:exec, whose test command shares the terminal.
The plain lines look like this (trimmed):
Firenook 0.2.0; engine 7a9614bea49f8208f96d2126b29ef11ee2f2810b; disk/WAL state ~/demo-shop/.firenook/stateServices: firestore, auth, storage, functions, pubsub; Emulator UI on; host localhostfirenook: Starting emulators: auth, functions, firestore, pubsub, storagefirenook functions: Loaded functions definitions from source: checkout, sendReceipt, stripeWebhook, nightlyReport.firenook functions[us-central1-checkout]: http function initialized (http://127.0.0.1:5001/demo-shop/us-central1/checkout).All emulators readyfirenook functions: Beginning execution of "us-central1-checkout"firenook functions: Beginning execution of "us-central1-sendReceipt"firenook functions: Finished "us-central1-checkout" in 192msfirenook functions: {"order":"NxAqPmHBZnvlq03g9ZVi","total":36,"severity":"INFO","message":"receipt queued"}firenook functions: Finished "us-central1-sendReceipt" in 6.4msAll emulators ready stands alone on its line, so a script can wait for it.
There are no keys in plain output: Ctrl-C (or SIGINT) stops Firenook and
saves the data, as q does. An engine that ends without being asked to
adds a line that says so, and the command exits with code 1:
firenook: the engine was ended (SIGKILL) while it was running; the next start checks the data first, and repairs it if it needs toColours, symbols and links
Section titled “Colours, symbols and links”NO_COLORkeeps the screen and drops the colours.- Colours use 24-bit colour when
COLORTERMsays the terminal has it, 256 colours whenTERMnames a 256-colour terminal, and 16 otherwise. - Terminals that cannot draw the symbols get plain characters (
+,x,|,=) and no flame: the Linux text console (TERM=linux), the Windows console outside Windows Terminal, and any terminal withFIRENOOK_ASCII=1. - Addresses are clickable links in terminals that support them, unless colours or symbols are off.
Terminal size
Section titled “Terminal size”Firenook starts at the top of the window, like a full-screen app, but your earlier output stays in the scrollback above it. The footer stays on the window’s last line, and the log scrolls above it.
The card is as wide as what it holds, at least 72 columns, and never wider
than the window. In a narrow window, long text is cut with …, the footer
splits into two lines, and below 64 columns the banner drops the flame:
+------------------------------------------------------+ | | | firenook 0.2.0 | | demo-shop - a fresh start | | Node 24.20.0 - data in .firenook/... | | | +- Start-up ---------------------------------- 468 ms -+ | | | Firestore + 88 ms 0 documents |This one is 60 columns wide with FIRENOOK_ASCII=1. A window 36 or more
rows tall gets a blank line around each part of the card; a shorter one
gives that space to the log. When you resize the window, Firenook draws the
part that is on screen again at the new width. Lines already in the
scrollback keep the width they were printed at.
firenook init
Section titled “firenook init”In a terminal, firenook init draws the same card: the mark, then the new
project’s choices as rows, each already made: the project id, the
emulators with their ports, the Functions language, the coding agents and
the set-up. ↑ and ↓ (or Tab) move between rows, ← and → change a
choice, Space turns one of several on or off, letters edit the project id,
Enter creates the project and Esc leaves without writing anything. The row
in focus shows its hint under it.
The set-up then runs as rows of the card, like the start-up, and a yes to
starting the emulators hands the same terminal to the start screen. In a
folder that already has a firebase.json, the card shows what
init --adopt would add and asks before adding it. See
Start a new project.
Release check
Section titled “Release check”Once a day at most, in the background, Firenook asks the npm registry for
its latest version tags. The answer shows on the next start, as the Update
row of the ready summary, so the check never slows a start down. It follows
the channel of the version you have: latest for a release such as 0.2.0,
and next for a preview, which also hears of a later release on latest.
It gives the install command for your package manager, from your lockfile.
It never runs in plain output, in CI, or with
FIRENOOK_NO_UPDATE_CHECK=1 or NO_UPDATE_NOTIFIER=1. As everywhere, a
variable set to nothing, 0 or false is not set: CI=false is not CI.
The console is one key away, and
CLI commands lists every flag of emulators:start.