CLI client for the spel daemon.
Parses command-line arguments into JSON commands, sends them to the daemon over a Unix domain socket, and pretty-prints the results.
If the daemon isn't running, it auto-starts one in the background.
Usage: spel open https://example.org spel snapshot spel click @ref spel fill @ref "search text" spel screenshot shot.png spel close
CLI client for the spel daemon. Parses command-line arguments into JSON commands, sends them to the daemon over a Unix domain socket, and pretty-prints the results. If the daemon isn't running, it auto-starts one in the background. Usage: spel open https://example.org spel snapshot spel click @ref spel fill @ref "search text" spel screenshot shot.png spel close
Help text for each CLI command. Keys are primary command names.
Help text for each CLI command. Keys are primary command names.
(daemon-failure-report session e attempts)Multi-line explanation for a command that never got a daemon response.
Params:
session - String session name
e - Throwable from the last transport attempt, or nil on EOF
attempts - Number of reconnect attempts already spent
Returns a String for stderr: what failed on the wire, why the daemon went away (read back from its own log), what it cost, and what to do next.
Multi-line explanation for a command that never got a daemon response. Params: `session` - String session name `e` - Throwable from the last transport attempt, or nil on EOF `attempts` - Number of reconnect attempts already spent Returns a String for stderr: what failed on the wire, why the daemon went away (read back from its own log), what it cost, and what to do next.
(daemon-health session probe)Health of the daemon for session, WITHOUT ever starting one.
Cross-checks the PID file against the live process command line. A reused PID
is stale; a real daemon missing its state files is orphaned. Neither can
masquerade as healthy or disappear as down.
Health of the daemon for `session`, WITHOUT ever starting one. Cross-checks the PID file against the live process command line. A reused PID is `stale`; a real daemon missing its state files is `orphaned`. Neither can masquerade as healthy or disappear as `down`.
(daemon-process-at-pid pid)Returns the command-line-verified spel daemon entry for pid, or nil.
Returns the command-line-verified spel daemon entry for `pid`, or nil.
(daemon-process-entry pid cmd){:pid :session} when cmd is the command line of a spel DAEMON, else nil.
The match has to be tight in both directions: miss a daemon and it stays
unkillable, match too widely and kill --all-sessions destroys an unrelated
process. A spel CLIENT invocation carries --session too, so the daemon
subcommand is what separates them.
`{:pid :session}` when `cmd` is the command line of a spel DAEMON, else nil.
The match has to be tight in both directions: miss a daemon and it stays
unkillable, match too widely and `kill --all-sessions` destroys an unrelated
process. A spel CLIENT invocation carries `--session` too, so the `daemon`
subcommand is what separates them.(daemon-process-for-session session)Finds the live, verified spel daemon for session.
Prefers a valid PID file, then scans processes so deleted daemon state never makes the daemon unkillable.
Finds the live, verified spel daemon for `session`. Prefers a valid PID file, then scans processes so deleted daemon state never makes the daemon unkillable.
(ensure-daemon! session opts)Ensures a daemon is running and responsive for the given session. Starts one if needed. Handles:
Ensures a daemon is running and responsive for the given session. Starts one if needed. Handles: - No daemon running → start fresh - Daemon running headless but --interactive requested → restart headed - Daemon already headed and --interactive requested → no-op (skip restart) - Stale daemon (process alive but socket broken) → kill and restart - Dead daemon (PID file exists but process gone) → clean up and restart
(force-kill-daemon! session)Ends the command-line-verified daemon for session NOW.
If its PID file names an unrelated live process, removes stale session files but refuses to signal that process.
Ends the command-line-verified daemon for `session` NOW. If its PID file names an unrelated live process, removes stale session files but refuses to signal that process.
(health-report h)Renders daemon-health for a terminal: one status line plus the few facts
that decide what to do next — what the daemon is stuck on, whether its
browser is still there, and where to look.
Renders `daemon-health` for a terminal: one status line plus the few facts that decide what to do next — what the daemon is stuck on, whether its browser is still there, and where to look.
(orphan-daemon-processes)Every running spel daemon process the OS knows about, as {:pid :session}.
Session discovery is file-based, so a daemon whose socket or PID file is gone
— deleted by hand, wiped by a -9, or lost to a crash — becomes unreachable:
session list cannot show it and kill --all-sessions cannot kill it, while
it still holds a browser, a port and hundreds of MB. Asking ProcessHandle
instead is the only way to find those, and behaves the same on macOS, Linux
and Windows.
A full allProcesses scan costs one .info syscall per process, and a single
CLI invocation asks for it several times (health, kill, session resolution),
so the result is cached for orphan-scan-ttl-ms — short enough that a process
that just exited is not reported as live.
Every running spel daemon process the OS knows about, as `{:pid :session}`.
Session discovery is file-based, so a daemon whose socket or PID file is gone
— deleted by hand, wiped by a `-9`, or lost to a crash — becomes unreachable:
`session list` cannot show it and `kill --all-sessions` cannot kill it, while
it still holds a browser, a port and hundreds of MB. Asking `ProcessHandle`
instead is the only way to find those, and behaves the same on macOS, Linux
and Windows.
A full `allProcesses` scan costs one `.info` syscall per process, and a single
CLI invocation asks for it several times (health, kill, session resolution),
so the result is cached for `orphan-scan-ttl-ms` — short enough that a process
that just exited is not reported as live.(parse-args args)Parses CLI argv into a command map suitable for sending to the daemon.
Returns a map with :command and :flags. :command is the action map to send to the daemon. :flags contains global options like :session, :json.
Parses CLI argv into a command map suitable for sending to the daemon. Returns a map with :command and :flags. :command is the action map to send to the daemon. :flags contains global options like :session, :json.
(run-cli! args)Main CLI entry point. Parses args, ensures daemon, sends command, prints result.
Returns the response map (for programmatic use) or nil on error.
Main CLI entry point. Parses args, ensures daemon, sends command, prints result. Returns the response map (for programmatic use) or nil on error.
(send-command! session command-map)(send-command! session command-map timeout-ms)Sends a JSON command to the daemon and returns the parsed response.
Connects to the daemon's Unix domain socket, writes one JSON line, reads one JSON response line, and closes the connection.
timeout-ms controls how long to wait for a response:
default-client-timeout-ms, 30000, overridable via SPEL_CLIENT_TIMEOUT_MS)Sends a JSON command to the daemon and returns the parsed response. Connects to the daemon's Unix domain socket, writes one JSON line, reads one JSON response line, and closes the connection. `timeout-ms` controls how long to wait for a response: - positive long: wait up to that many milliseconds (default `default-client-timeout-ms`, 30000, overridable via SPEL_CLIENT_TIMEOUT_MS) - nil: block indefinitely until the daemon responds or throws. Use nil for eval-sci mode where each Playwright action has its own timeout — the transport layer should not race against it.
(top-level-help)Returns the top-level help string shown by spel --help.
Returns the top-level help string shown by `spel --help`.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |