Commands
The navigera command line: sessions, flags and output, with the command list by topic.
The commands by topic: sessions, tabs and the browser, read the page, act on the page, state, emulation and audit.
navigera [GLOBAL FLAGS] <command> [ARGS] [GLOBAL FLAGS]
| global flag | meaning |
|---|---|
-s, --session <name|path> | named session. A bare name lives in a directory only you can enter: $XDG_RUNTIME_DIR/navigera/<name>.sock, else $TMPDIR/navigera-<uid>/<name>.sock (mode 0700; navigera refuses one that is a symlink, someone else’s or open to others), %TEMP%\navigera\ on Windows; a value with a path separator is used as the path. $NAVIGERA_SESSION sets a default for client calls |
--output compact|raw|json | what a command prints. compact, the default: an action that moved the page prints only its own fields and what changed ({"title":"Saved"}); one that left it on the same document, after an ax of it, prints the lines of that tree that changed (+ new, - gone, ~ the same element reading differently; at most 40, then a count), read again the way that ax read it, waiting as ax does for data the action fetches, and ok when no line changed (after a fill, the field’s own new value is not a change). On a large page (past 2,500 DOM nodes) a text entry (fill, type, insert-text) that changed nothing else is not read again: a journal kept in the page since the last read (its DOM, frames, shadow roots, form values, and the style rules that follow :focus, :hover, :invalid, :has() and the like) shows it, and the report is the same ok; a check, uncheck or select that moved only checkboxes, radios or single selects reports their lines rewritten as a read prints them; anything it can’t watch (a style sheet of another origin) means a read, as before. $NAVIGERA_CHANGE_JOURNAL=0 reads after every entry; a read prints its value (strings unquoted, the ax tree as text). raw: the result only, as it is. json: one JSON line per command, {"ok":true,"result":…} or {"ok":false,"error":…}, for programs. Outside json, errors go to stderr as error: … (exit code 1) and notes as note: …. $NAVIGERA_OUTPUT sets the mode for every command of a shell; a flag wins. The session remembers the state it last reported. --compact: --output compact; --raw: --output raw |
--pretty | pretty-print the JSON |
--timeout-ms <ms> | before the command: navigation/command timeout (default 35000). After an element command: that op’s element wait (default 5000) |
--wait-ms <ms> | element ops’ wait when they name no timeout, and on one wait for a condition, its timeout (default 5000; $NAVIGERA_WAIT_MS). On start/serve/mcp it holds for the whole session |
--download-dir <dir> | where downloaded files go ($NAVIGERA_DOWNLOAD_DIR; default a directory of the session’s own in navigera-<uid> under the system temp directory, which only you can enter) |
--chromium <path> | browser binary (also $NAVIGERA_CHROMIUM, $CHROME_BIN) |
--engine chrome|lightpanda ($NAVIGERA_ENGINE), --headed | engine; visible window |
--idle-timeout-s <s> | a session server shuts down after this idle time (default 600, 0 = never; also start --idle <s>). status and sessions don’t count as use |
--own-browser | with start (or mcp): a browser of the session’s own instead of a context on the shared browser ($NAVIGERA_SHARED_BROWSER=0) |
--parent <pid> | with start: the session quits when that process exits (checked twice a second; $NAVIGERA_PARENT_PID) |
--allow-domains <list> | with start/serve/mcp: hostnames this session may navigate to or request from (comma-separated; *.example.com covers its subdomains, not itself; $NAVIGERA_ALLOW_DOMAINS, a flag wins). Everything else is refused at the Fetch request stage, before any route rule, on every redirect hop; a refused navigation’s error names the denied host and the flag, and status lists refused hosts. An entry is a hostname only (no scheme, port, path or userinfo); malformed or empty lists are refused at startup, never silently disabled. --allow-domains-docs-only checks top-level navigation only: a navigation restriction, not exfiltration protection (subresources, iframes included, still go out). Requests are paused at the browser too, so a popup (window.open, target=_blank) is refused before its first request goes out, and on a browser of the session’s own (serve, start --own-browser) a service worker’s fetches are checked in strict mode. Limits, measured: this is a hostname policy, not an origin policy (scheme and port are ignored); WebSocket handshakes are NOT intercepted by Fetch in Chrome, so neither mode stops exfiltration over them, nor over a service worker of a shared browser; file:, about:, blob: and data: URLs carry no host to check and pass through. A session that cannot install the interception fails to start rather than running unenforced; reset keeps the policy, reset --all drops it, a fork starts without one |
-V, --version, -h, --help, help <command> | info |
Every command prints one JSON object: {"id":…, "ok":true, "result":…, "elapsed_ms":…} or {"ok":false, "error":"…"}. Two optional fields report
side effects: dialogs (dialogs the page opened and how they were answered)
and new_tabs (tabs the page opened, now in the tab list). The exit code is
0 on success, 1 on a failed op and 2 on bad arguments.
Targets. Element commands take exactly one target:
-
a ref from
axas the first argument (click 12;@12,e12,ref12andref=12also work) or--ref 12; -
--selector <css>: the first match a user could reach (when the first one is parked off the page and another isn’t, the other).host >>> innercrosses shadow roots:innerinside the open shadow root of an elementhostmatches (or a shadow root under it), as in"#app >>> x-card:nth-of-type(2) >>> button";locatewrites one for an element in a shadow root; -
--text "<visible text>": the best match by accessible label, text or value. An exact match beats a partial one, actionable elements beat plain ones, and a<label>stands for its control. -
--role <role> [--name <accessible name>],--label <form label>,--placeholder <text>,--testid <data-testid>: semantic locators (case-insensitive, exact before contains, visible first, open shadow roots included);--nth <i>picks among their matches or--selector’s (0-based,-1= the last). -
--near <text>with any of them: the match whose own part of the page (its card, row or section: the largest ancestor holding no other match) shows the text:click --role button --name "Add to cart" --near "Brass Widget". It holds when items reorder, where--nthdoesn’t;locatewrites it when a role and name match more than one element. -
--frame <css>with any of them: look only inside that iframe or frame ("#outer >> #inner"for one inside another), of this origin or another, when two frames hold the same element (two address forms, two payment frames).wait --selector/--text/--gone --frame …too. When the CSS matches several frames, the first in document order is the one; when it matches none, the error says so.
Selector, text and locator targets auto-wait (default 5 s, --wait-ms) for
the element to appear. They search the top document first, then its open
shadow roots and the documents of same-origin frames (iframes, framesets,
srcdoc), so a form inside an iframe or a button inside a web component is
reached the same way. When the element isn’t there, frames of another
origin (a card form from a payment provider, a sign-in frame) are searched
too, from an isolated world navigera makes in each, which the page can’t
see. A single wait --text or wait --selector looks there as well. In a
browser navigera launched, cross-site frames share the page’s process, so
all of them are reachable; with --attach to your own browser, frames in
another process are reachable by ref only.
Made from docs/navigera.md.