Liking cljdoc? Tell your friends :D

com.blockether.spel.daemon

Background daemon that keeps a Playwright browser alive between CLI calls.

Listens on a Unix domain socket for JSON commands, executes them against the browser, and returns JSON responses. Each command is one JSON line; each response is one JSON line.

Usage: (start-daemon! {:session "default" :headless true}) ;; blocks (daemon-running? "default") ;; check (stop-daemon!) ;; cleanup

Background daemon that keeps a Playwright browser alive between CLI calls.

Listens on a Unix domain socket for JSON commands, executes them against
the browser, and returns JSON responses. Each command is one JSON line;
each response is one JSON line.

Usage:
  (start-daemon! {:session "default" :headless true})   ;; blocks
  (daemon-running? "default")                           ;; check
  (stop-daemon!)                                         ;; cleanup
raw docstring

*command-deadline-ms*clj

Absolute System/currentTimeMillis by which the command now running must answer, bound by run-guarded-command! from that command's budget. nil when no budget governs the call — control actions, and handlers called directly.

Absolute `System/currentTimeMillis` by which the command now running must
answer, bound by `run-guarded-command!` from that command's budget. nil when
no budget governs the call — control actions, and handlers called directly.
sourceraw docstring

auto-launch-browser!clj

(auto-launch-browser! {:keys [channel session headless]
                       :or {channel "chrome" session "default" headless true}})

Launches a browser with --remote-debugging-port on a free port. Uses a temp user-data-dir so the user's existing browser stays untouched.

Params: channel - Browser channel (e.g. 'chrome', 'msedge'). Defaults to 'chrome'. session - Session name, used for lock file ownership. headless - Boolean, whether to launch headless.

Returns a map: :cdp-url - CDP endpoint URL (http://127.0.0.1:<port>) :port - The allocated port :browser-pid - PID of the launched browser process :tmp-dir - Path to the temp user-data-dir (for cleanup)

Launches a browser with --remote-debugging-port on a free port.
Uses a temp user-data-dir so the user's existing browser stays untouched.

Params:
  `channel`  - Browser channel (e.g. 'chrome', 'msedge'). Defaults to 'chrome'.
  `session`  - Session name, used for lock file ownership.
  `headless` - Boolean, whether to launch headless.

Returns a map:
  :cdp-url      - CDP endpoint URL (http://127.0.0.1:<port>)
  :port         - The allocated port
  :browser-pid  - PID of the launched browser process
  :tmp-dir      - Path to the temp user-data-dir (for cleanup)
sourceraw docstring

client-timeout-msclj

(client-timeout-ms action)
(client-timeout-ms action ios?)

Transport budget a client must allow for action: the daemon's own budget plus slack. ios? mirrors command-budget-ms — a CLI process cannot read the daemon's state, so it says so from its own flags.

The invariant is client timeout > daemon budget. Violating it (a flat 30s client against the 900s budget for sci_eval/ios*) made the CLI walk away from commands the daemon was still executing: the work continued unwatched, the reply landed on a closed socket, and the session log filled with handle-connection: Broken pipe instead of an answer.

Transport budget a client must allow for `action`: the daemon's own budget
plus slack. `ios?` mirrors `command-budget-ms` — a CLI process cannot read
the daemon's state, so it says so from its own flags.

The invariant is client timeout > daemon budget. Violating it (a flat 30s
client against the 900s budget for `sci_eval`/`ios*`) made the CLI walk away
from commands the daemon was still executing: the work continued unwatched,
the reply landed on a closed socket, and the session log filled with
`handle-connection: Broken pipe` instead of an answer.
sourceraw docstring

command-budget-msclj

(command-budget-ms action)
(command-budget-ms action ios?)

Budget for action: at least default-command-budget-ms, always at least 2x the configured action timeout, and minutes for open-ended work.

ios? says the session is driven by the iOS provider, where EVERY command is open-ended — a snapshot is a WDA page-source dump of the whole native tree and a click waits on that tree — so the browser's 25s ceiling interrupted healthy commands mid-flight. Matching on an ios action NAME was never enough: the iOS backend answers the ordinary snapshot, click and type actions, and only the daemon's own state knows which backend they reach. The single-argument arity asks that state, which is empty in the CLI process — clients pass ios? explicitly.

Public because the CLI must size its transport timeout from the same number — see client-timeout-ms.

Budget for `action`: at least `default-command-budget-ms`, always at least
2x the configured action timeout, and minutes for open-ended work.

`ios?` says the session is driven by the iOS provider, where EVERY command
is open-ended — a `snapshot` is a WDA page-source dump of the whole native
tree and a `click` waits on that tree — so the browser's 25s ceiling
interrupted healthy commands mid-flight. Matching on an `ios` action NAME
was never enough: the iOS backend answers the ordinary `snapshot`, `click`
and `type` actions, and only the daemon's own state knows which backend
they reach. The single-argument arity asks that state, which is empty in
the CLI process — clients pass `ios?` explicitly.

Public because the CLI must size its transport timeout from the same number —
see `client-timeout-ms`.
sourceraw docstring

daemon-running?clj

(daemon-running? session)

Checks if a daemon is running for the given session.

Checks if a daemon is running for the given session.
sourceraw docstring

discover-cdp-endpointclj

(discover-cdp-endpoint)

Finds a running Chromium-family CDP endpoint without starting authorization. Prefers DevToolsActivePort advertisements, including WSL-projected paths, then checks common HTTP ports. Closed advertisements are skipped. A cached WebSocket target id is validated only by the actual bounded attachment.

Finds a running Chromium-family CDP endpoint without starting authorization.
Prefers DevToolsActivePort advertisements, including WSL-projected paths,
then checks common HTTP ports. Closed advertisements are skipped. A cached
WebSocket target id is validated only by the actual bounded attachment.
sourceraw docstring

discover-external-cdp-endpointsclj

(discover-external-cdp-endpoints excluded-ports)

Lists running CDP endpoint candidates, excluding spel-owned ports. DevToolsActivePort WebSocket advertisements use TCP liveness only: listing must not request browser authorization. Their cached target ids may be stale; only an actual attachment verifies them. Other listeners get one bounded /json/version request, also supplying their browser label. WSL-projected advertisements try loopback then the Windows gateway.

Lists running CDP endpoint candidates, excluding spel-owned ports.
DevToolsActivePort WebSocket advertisements use TCP liveness only: listing
must not request browser authorization. Their cached target ids may be stale;
only an actual attachment verifies them. Other listeners get one bounded
/json/version request, also supplying their browser label. WSL-projected
advertisements try loopback then the Windows gateway.
sourceraw docstring

discover-session-filesclj

(discover-session-files)

Single source of truth for enumerating spel session state on disk. Scans the tmpdir for spel-<name>.sock files and returns a seq of {:name :socket :alive?} maps — :alive? is true when the owning PID file points to a running process. Pure; does NOT start any daemon.

Single source of truth for enumerating spel session state on disk.
Scans the tmpdir for `spel-<name>.sock` files and returns a seq of
`{:name :socket :alive?}` maps — `:alive?` is true when the owning PID
file points to a running process. Pure; does NOT start any daemon.
sourceraw docstring

find-free-cdp-portclj

(find-free-cdp-port)

Finds an available CDP port starting from 9222. Checks both the OS-level port availability and spel auto-launch lock files to avoid collisions with other sessions. Returns the port number or throws if none found.

Finds an available CDP port starting from 9222. Checks both the OS-level port
availability and spel auto-launch lock files to avoid collisions with other
sessions. Returns the port number or throws if none found.
sourceraw docstring

flags-file-pathclj

(flags-file-path session)

Returns the launch flags persistence file path for a session.

Returns the launch flags persistence file path for a session.
sourceraw docstring

kill-auto-launched-browser!clj

(kill-auto-launched-browser! {:keys [port browser-pid tmp-dir]})

Kills an auto-launched browser process and cleans up its lock file and temp dir.

Kills an auto-launched browser process and cleans up its lock file and temp dir.
sourceraw docstring

launch-lightpanda!clj

(launch-lightpanda! {:keys [session] :or {session "default"}})

Spawns a Lightpanda subprocess in CDP-server mode and returns a map with the CDP URL and child process info, parallel to auto-launch-browser! but scoped to the Lightpanda binary.

Lightpanda is a Zig-based lightweight headless browser that speaks a subset of the CDP. The user must have lightpanda on PATH; if not, we throw a clear ex-info with install hints instead of blowing up inside ProcessBuilder.

Returns: :cdp-url — WebSocket CDP endpoint (ws://127.0.0.1:<port>) :port — Allocated port :process — java.lang.Process for the subprocess :browser-pid — PID of the child

Spawns a Lightpanda subprocess in CDP-server mode and returns a map with
the CDP URL and child process info, parallel to `auto-launch-browser!` but
scoped to the Lightpanda binary.

Lightpanda is a Zig-based lightweight headless browser that speaks a
subset of the CDP. The user must have `lightpanda` on PATH; if not, we
throw a clear ex-info with install hints instead of blowing up inside
ProcessBuilder.

Returns:
  :cdp-url     — WebSocket CDP endpoint (ws://127.0.0.1:<port>)
  :port        — Allocated port
  :process     — java.lang.Process for the subprocess
  :browser-pid — PID of the child
sourceraw docstring

list-active-cdp-endpointsclj

(list-active-cdp-endpoints)

Scans /tmp/spel-auto-launch-*.json for active CDP endpoints owned by spel sessions. For each lock whose owning daemon is still alive and whose port responds to a CDP /json/version probe, returns {:session :port :cdp_url}. Stale entries are filtered out silently.

Scans /tmp/spel-auto-launch-*.json for active CDP endpoints owned by spel
sessions. For each lock whose owning daemon is still alive and whose port
responds to a CDP /json/version probe, returns {:session :port :cdp_url}.
Stale entries are filtered out silently.
sourceraw docstring

log-file-pathclj

(log-file-path session)

Returns the log file path for a session.

Delegates to logging/log-file-path so the daemon, the CLI, and spel logs can never disagree about where a session's log lives.

Returns the log file path for a session.

Delegates to `logging/log-file-path` so the daemon, the CLI, and `spel logs`
can never disagree about where a session's log lives.
sourceraw docstring

pid-file-pathclj

(pid-file-path session)

Returns the PID file path for a session.

Returns the PID file path for a session.
sourceraw docstring

read-session-flagsclj

(read-session-flags session)

Reads persisted launch flags for a session from the flags file. Returns a map of flag-name->value, or empty map if file doesn't exist. Used by CLI to recover flags like --cdp without requiring them on every command.

Reads persisted launch flags for a session from the flags file.
Returns a map of flag-name->value, or empty map if file doesn't exist.
Used by CLI to recover flags like --cdp without requiring them on every command.
sourceraw docstring

resolve-browser-binaryclj

(resolve-browser-binary channel)

Resolves the filesystem path to a Chrome/Edge binary based on the channel name. Supports: chrome, msedge, chrome-beta, chrome-canary, msedge-beta, msedge-dev. Falls back to 'chrome' if channel is nil. Returns the binary path string, or throws if not found.

Resolves the filesystem path to a Chrome/Edge binary based on the channel name.
Supports: chrome, msedge, chrome-beta, chrome-canary, msedge-beta, msedge-dev.
Falls back to 'chrome' if channel is nil.
Returns the binary path string, or throws if not found.
sourceraw docstring

socket-pathclj

(socket-path session)

Returns the Unix socket path for a session.

Returns the Unix socket path for a session.
sourceraw docstring

start-daemon!clj

(start-daemon! opts)

Starts the daemon server. Blocks until shutdown.

One session NAME is served by one daemon. The PID file is the ownership record and claim-session! picks the winner, so a start that loses the race exits without launching a browser instead of stealing the socket from the daemon already serving that name.

Params: opts - Map: :session - String (default 'default') :headless - Boolean (default true) :browser - String (optional, e.g. 'firefox', 'webkit') :cdp - String (optional, CDP endpoint URL)

Starts the daemon server. Blocks until shutdown.

One session NAME is served by one daemon. The PID file is the ownership
record and `claim-session!` picks the winner, so a start that loses the race
exits without launching a browser instead of stealing the socket from the
daemon already serving that name.

Params:
`opts` - Map:
  :session  - String (default 'default')
  :headless - Boolean (default true)
  :browser  - String (optional, e.g. 'firefox', 'webkit')
  :cdp      - String (optional, CDP endpoint URL)
sourceraw docstring

stop-daemon!clj

(stop-daemon!)
(stop-daemon! reason)
(stop-daemon! reason {:keys [force?]})

Stops the daemon server and cleans up browser resources. Closes server socket first so new CLI invocations fail fast and start a fresh daemon. Only deletes PID/socket files if they still belong to THIS process (prevents nuking a replacement daemon's files).

reason is recorded in the session log as daemon stopping … reason=…. A client that finds the daemon gone reads that line back and tells the user WHY it went away instead of a bare 'could not connect'.

opts may carry :force? — skip the graceful page/context/browser closes and go straight for the driver. Cleanup is time-boxed either way (SPEL_STOP_TIMEOUT, default 5s): a wedged Chromium must never keep alive a daemon that was asked to stop.

Stops the daemon server and cleans up browser resources.
Closes server socket first so new CLI invocations fail fast and start
a fresh daemon. Only deletes PID/socket files if they still belong to
THIS process (prevents nuking a replacement daemon's files).

`reason` is recorded in the session log as `daemon stopping … reason=…`.
A client that finds the daemon gone reads that line back and tells the
user WHY it went away instead of a bare 'could not connect'.

`opts` may carry `:force?` — skip the graceful page/context/browser closes
and go straight for the driver. Cleanup is time-boxed either way
(`SPEL_STOP_TIMEOUT`, default 5s): a wedged Chromium must never keep alive a
daemon that was asked to stop.
sourceraw docstring

wsl-default-gateway-ipclj

(wsl-default-gateway-ip)

Delegates to platform/wsl-default-gateway-ip. Kept as a public wrapper for call-site compatibility (tests, diagnostic script, etc.).

Delegates to platform/wsl-default-gateway-ip. Kept as a public wrapper
for call-site compatibility (tests, diagnostic script, etc.).
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close