SignalK CLI
Query and explore NMEA and other boat data from SignalK APIs using the command line, and export data as CSV, Apache Arrow Feather, or JSON.
APIs supported:
- SignalK v2 History API. Commands available:
- list-paths
- list-providers
- list-contexts
- query
- cardinality
- SignalK v1 Streaming API. Commands available:
- deltas
Installation
signalk-cli is published to PyPi at https://pypi.org/project/signalk-cli/
Python is required to run this, version 3.13 or above. uv is the recommended way to install the package ( and can install Python ) but is not required.
PyPi
pip install signalk-cli or uv pip install signalk-cli
For Apache Arrow Feather export, use the optional dependency: pip install 'signalk-cli[feather]'
Local Copy
Requires Python 3.13+ and uv.
git clone https://github.com/rhizomatics/signalk-cli
cd signalk-cli
uv sync
Temporary Installation
Use uv to run without installing the module permanently, for example:
uv run --with signalk-cli signalk_cli.history list-providers
Running
Run via python -m signalk_cli.history <command> or python -m signalk_cli.stream <command> or without installing the module with uv run --with signalk-cli signalk_cli.history <command>.
Determining SignalK host name
If no host name is set as an argument, the CLI will look for a SIGNALK_HOST environment variable, and failing that attempt to automatically discover the host using mDNS (aka Bonjour) and locally cached (see Default Caching).
export SIGNALK_HOST=192.168.6.99 # http:// is added automatically if omitted
Built-in Help
Run with no arguments to list available commands:
$ python -m signalk_cli.history
Usage: signalk_cli.history [OPTIONS] COMMAND [ARGS]...
SignalK v2 history CLI.
Commands:
cardinality Compute per-path value statistics for the given time range.
list-contexts List contexts that have historical data for the given time range.
list-paths List paths that have data for the given time range.
list-providers List registered history providers.
query Query history and write results as CSV, Feather, or JSON.
Commands
query
Fetch historical values for one or more paths and write to stdout (default) or a file. Aggregation can be controlled in the same way as the History API itself
or a default form where min_value,avg_value and max_value are returned for every period.
python -m signalk_cli.history query [OPTIONS] PATH...
PATH arguments may be:
- Literal paths — e.g.
navigation.speedOverGround - Regex / glob patterns — any argument containing metacharacters (
*,.,[,(, etc.) is matched against the server's/pathsendpoint. Bare*is treated as a glob wildcard. - Inline path specs —
path:methodorpath:method:param, e.g.navigation.speedOverGround:sma:5. These pass through to the server unchanged.
Options
| Option | Default | Description |
|---|---|---|
--host |
$SIGNALK_HOST |
Server base URL. http:// added if scheme omitted. |
--from DATETIME |
— | Start of range (ISO 8601, e.g. 2026-05-26T00:00:00Z) |
--to DATETIME |
now | End of range (ISO 8601) |
--duration DURATION |
— | Duration as seconds (3600) or ISO 8601 duration (PT1H, P1D, P1W). Combined with --from or --to, or alone for a window ending now. |
--resolution RESOLUTION |
server default | Sample window size: seconds or time expression (1s, 1m, 1h, 1d). |
-c, --context TEXT |
vessels.self |
SignalK context |
--provider TEXT |
fetched & cached | History provider plugin name, for example signalk-parquet |
--no-cache |
— | Ignore the cached default provider |
--aggregation / --agg |
— | Aggregation method: average, min, max, first, last, mid, middle_index, sma, ema. Omit for wide mode (see below). |
--samples N |
server default | Sample count for --agg sma |
--alpha FLOAT |
server default | Alpha (0–1) for --agg ema |
--format [csv|feather|json|raw] |
from extension, else csv | Output format. Auto-detected from .feather/.arrow/.fea and .json extensions. feather requires pip install 'signalk-cli[feather]'. |
--no-header |
— | Suppress the CSV header row |
-o / --output [FILE] |
stdout | Write to a file. Omit the filename (--output alone) to auto-name as signalk-history-<server>-<timestamp>.<ext>. Use - for stdout explicitly. Feather cannot be written to stdout. |
--pretty |
— | Pretty-print JSON output with indentation. Warning: disables streaming; the full response is buffered in memory before writing. |
--bare |
— | Print to stdout with no informational messages (server, provider, progress, row count). Ideal for piping to other tools. Not supported with feather. |
If no time range is given, the tool defaults to the hour ending now.
Duration normalisation
SignalK only accepts time-only ISO 8601 durations (PT1H, PT30M, etc.). Durations with date components (P1D, P1W, P1Y, P1M) are automatically expanded to explicit --from/--to timestamps:
--duration P1Dalone →from = now − 1 day,to = now--from T --duration P1D→to = T + 1 day--to T --duration P1W→from = T − 1 week
Integer seconds (3600) are passed through unchanged.
Output formats
csv (default): tabular output as comma-separated values.
feather: Apache Arrow Feather binary format, readable with pandas, Polars, R, pyarrow, etc. Requires pip install 'signalk-cli[feather]'. Cannot be written to stdout.
json: tabular records as JSON objects — same columns as CSV, formatted as a JSON array. Extension .json auto-selects this format.
raw: exact API response body as received from the server — no Python JSON parse/re-serialize. Streamed directly to stdout unless --pretty is used.
Output columns
Wide mode (default — no --aggregation and no inline specs): fetches min, average, and max for each scalar path and writes them as separate columns:
timestamp, path, min_value, avg_value, max_value
Array-valued paths in wide mode: paths whose values are arrays (non-scalar) cannot be meaningfully aggregated with min/max/average. They are requested with a single passthrough method instead and the array elements are expanded into named columns. The column names depend on the path:
| Path pattern | Array length | Columns |
|---|---|---|
navigation.*.position or navigation.position |
2 | longitude, latitude |
| any other array path | N | value_0, value_1, …, value_N-1 |
Example for navigation.position:
timestamp, path, latitude, longitude
Narrow mode (explicit --aggregation or inline path specs): single value column:
timestamp, path, value
Structured values (positions, arrays) are JSON-encoded in the value column.
Examples
# Last hour of speed — wide mode (min/max/avg columns), printed to stdout
python -m signalk_cli.history query --host 10.36.10.21 --duration PT1H \
navigation.speedOverGround
# Write to auto-named file
python -m signalk_cli.history query --host 10.36.10.21 --duration PT1H --output \
navigation.speedOverGround
# Write to named file
python -m signalk_cli.history query --host 10.36.10.21 --duration PT1H \
--output may26.csv navigation.speedOverGround
# Last day (date-component duration, auto-expanded to from/to)
python -m signalk_cli.history query --host 10.36.10.21 --duration P1D \
navigation.speedOverGround
# Simple moving average (5 samples), narrowed to one value column
python -m signalk_cli.history query --host 10.36.10.21 --duration PT1H \
--agg sma --samples 5 \
navigation.speedOverGround
# EMA with alpha 0.2
python -m signalk_cli.history query --host 10.36.10.21 --duration PT1H \
--agg ema --alpha 0.2 \
navigation.speedOverGround
# Inline spec — path:method, multiple paths with different methods
python -m signalk_cli.history query --host 10.36.10.21 --duration PT1H \
'navigation.speedOverGround:max' 'navigation.courseOverGroundTrue:average'
# Multiple literal paths, 1-minute resolution
python -m signalk_cli.history query --host 10.36.10.21 --duration PT1H --resolution 1m \
navigation.speedOverGround navigation.courseOverGroundTrue
# All navigation paths, specific date range, write to named file
python -m signalk_cli.history query --host 10.36.10.21 \
--from 2026-05-26T00:00:00Z --to 2026-05-27T00:00:00Z \
--output may26.csv \
'navigation\..*'
# Glob wildcard — all paths for the last 30 minutes as Feather (auto-named)
python -m signalk_cli.history query --host 10.36.10.21 --duration PT30M \
--format feather --output '*'
# Extension auto-selects feather format
python -m signalk_cli.history query --host 10.36.10.21 --duration PT1H \
-o out.feather navigation.speedOverGround
# Exact API response body to stdout (streamed, no informational noise)
python -m signalk_cli.history query --host 10.36.10.21 --duration PT1H --format raw --bare \
navigation.speedOverGround
# Pretty-printed raw JSON (buffered — avoid for large responses)
python -m signalk_cli.history query --host 10.36.10.21 --duration PT1H \
--format raw --pretty navigation.speedOverGround
# Extension auto-selects JSON format
python -m signalk_cli.history query --host 10.36.10.21 --duration PT1H \
-o out.json navigation.speedOverGround
# Suppress header, pipe to another tool
python -m signalk_cli.history query --host 10.36.10.21 --duration 3600 --no-header \
navigation.speedOverGround | cut -d, -f1,3
# --bare: pure CSV output, no informational noise — pipe-friendly
python -m signalk_cli.history query --host 10.36.10.21 --duration PT1H --bare \
navigation.speedOverGround | awk -F, 'NR>1 {print $2, $3}'
# Different context
python -m signalk_cli.history query --host 10.36.10.21 --duration PT1H \
-c vessels.urn:mrn:imo:mmsi:123456789 navigation.speedOverGround
cardinality
Fetch raw values for one or more paths and compute per-path statistics. Useful for exploring a dataset before querying it.
python -m signalk_cli.history cardinality [OPTIONS] PATH...
PATH arguments follow the same rules as query (literal paths, regex/glob patterns, inline specs).
Output columns
| Column | Description |
|---|---|
path |
SignalK path |
distinct_values |
Count of unique values (by string representation) |
min |
Minimum value (scalar numeric only; blank otherwise) |
max |
Maximum value (scalar numeric only; blank otherwise) |
average |
Mean value (scalar numeric only; blank otherwise) |
distinct_values_2_decimal_places |
Distinct count after rounding to 2 dp (scalar only; blank otherwise) |
nulls |
Count of null/missing values |
For non-scalar paths (e.g. navigation.position which returns a lat/lon pair), min, max, average, and distinct_values_2_decimal_places are left blank; distinct_values still counts unique array representations.
Options
Accepts the same --host, --from/--to/--duration, --resolution, --context, --provider/--no-cache, --format [csv|json], --no-header, and --bare options as query.
# Statistics for speed over the last hour
python -m signalk_cli.history cardinality --host 10.36.10.21 --duration PT1H \
navigation.speedOverGround
# All navigation paths, last 24 hours
python -m signalk_cli.history cardinality --host 10.36.10.21 --duration P1D \
'navigation\..*'
# JSON output
python -m signalk_cli.history cardinality --host 10.36.10.21 --duration PT1H \
--format json navigation.speedOverGround navigation.position
list-paths
List all SignalK paths that have recorded data in a given time range.
python -m signalk_cli.history list-paths [OPTIONS]
Outputs one path per line to stdout by default. Defaults to the last hour if no time range is given. Accepts the same --from/--to/--duration, --provider/--no-cache, -c/--context, and --bare options as query.
Options
| Option | Default | Description |
|---|---|---|
--format [csv|json|raw] |
csv |
csv: one item per line with path header. json: [{"path": ...}]. raw: exact API response body. |
# Paths recorded in the last hour
python -m signalk_cli.history list-paths --host 10.36.10.21
# Paths available on a specific day
python -m signalk_cli.history list-paths --host 10.36.10.21 \
--from 2026-05-26T00:00:00Z --to 2026-05-27T00:00:00Z
# Pipe into grep
python -m signalk_cli.history list-paths --host 10.36.10.21 --duration PT24H | grep navigation
# Exact API response body, no informational noise
python -m signalk_cli.history list-paths --host 10.36.10.21 --format raw --bare
list-providers
List all registered history provider plugins and identify the default. Supports --bare to suppress the "Server:" and provider-count lines.
python -m signalk_cli.history list-providers --host 10.36.10.21
Example output:
provider,isDefault
signalk-parquet,True
kip,False
2 provider(s)
The default provider is used automatically when --provider is not specified on other commands. It is fetched once and cached in ~/.cache/signalk-cli/.
Options
| Option | Default | Description |
|---|---|---|
--format [csv|json|raw] |
csv |
csv: provider,isDefault rows. json: [{"provider": ..., "isDefault": ...}]. raw: exact API response body. |
# Exact API response body, no informational noise
python -m signalk_cli.history list-providers --host 10.36.10.21 --format raw --bare
list-contexts
List SignalK contexts (vessels, aircraft, etc.) that have recorded data in a given time range.
python -m signalk_cli.history list-contexts [OPTIONS]
Defaults to the last hour if no time range is given.
Options
| Option | Default | Description |
|---|---|---|
--format [csv|json|raw] |
csv |
csv: one item per line with context header. json: [{"context": ...}]. raw: exact API response body. |
python -m signalk_cli.history list-contexts --host 10.36.10.21
python -m signalk_cli.history list-contexts --host 10.36.10.21 \
--from 2026-05-26T00:00:00Z --to 2026-05-27T00:00:00Z
# Exact API response body, no informational noise
python -m signalk_cli.history list-contexts --host 10.36.10.21 --format raw --bare
SignalK v1 Streaming API
The signalk_cli.stream module connects to a running SignalK server's live delta
WebSocket feed (as opposed to signalk_cli.history, which queries recorded history).
deltas
Stream live delta updates from the SignalK v1 Streaming API.
python -m signalk_cli.stream deltas [OPTIONS] [PATH...]
By default, prints the next delta message and exits — useful for a quick check.
Use --follow to keep tailing until interrupted with Ctrl-C, optionally capped
with --count.
PATH arguments are sent verbatim to the server as an explicit subscription,
one per path. They may be literal SignalK paths (e.g. navigation.speedOverGround)
or use the SignalK subscription wildcard *, matched server-side per the
Subscription Protocol
— unlike history's PATH patterns, which the client resolves by matching
against the server's enumerated /paths list:
*at the end of a path matches any suffix, e.g.navigation.**as a middle segment matches any single segment there, e.g.propulsion.*.oilTemperature- a bare
*subscribes to every path in the context
Quote wildcarded paths (e.g. 'navigation.*') so the shell doesn't expand them
against local filenames first.
deltas always sends its own explicit subscribe message for --context,
covering PATH arguments if given, otherwise every path (*). --policy,
--period, and --min-period control that subscription per the
Subscription Protocol's
policy/period/minPeriod fields:
--policy(instant/ideal/fixed, defaultideal):instantsends every change (throttled by--min-period);idealbehaves likeinstantbut resends the last value if nothing changes within--period;fixedalways sends the last known value every--period, regardless of changes.--period(seconds, default60): the resend interval forideal/fixed. Converted to milliseconds on the wire.--min-period(seconds): fastest allowed transmission rate, only meaningful with--policy instant.
The protocol also defines a per-path format field (delta/full), but
this CLI doesn't expose it: signalk-server rejects full outright ("Only
delta format supported, using it") and always sends delta messages
regardless, so the choice would be misleading.
--subscribe is separate: it's the connection-level subscribe query
parameter (none/self/all, default none), controlling only whether the
server additionally auto-subscribes the connection at its own default
policy/period — useful with --subscribe all to also receive other vessels'
default-policy updates alongside your explicit subscription.
Options
| Option | Default | Description |
|---|---|---|
--host |
$SIGNALK_HOST |
Server base URL. http:// added if scheme omitted; converted to ws:///wss:// for the stream connection. |
--no-cache |
— | Ignore the cached host |
-c, --context TEXT |
vessels.self |
SignalK context |
--subscribe [none|self|all] |
none |
Connection-level subscribe policy (SignalK's own subscribe query parameter); see above |
--policy [instant|ideal|fixed] |
ideal |
Per-path subscribe policy field; see above |
--period SECONDS |
60 |
Per-path subscribe period field, in seconds (converted to ms) |
--min-period SECONDS |
— | Per-path subscribe minPeriod field, in seconds (converted to ms); only meaningful with --policy instant |
--format [csv|json|raw|feather] |
from extension, else csv | Output format. json is JSON Lines (one row object per line, suitable for a live stream). raw is the exact delta message text, one per line. feather requires pip install 'signalk-cli[feather]' and --output (cannot stream to stdout). |
--no-header |
— | Suppress the CSV header row |
-o, --output [FILE] |
stdout | Write to a file. Omit the filename (--output alone) to auto-name as signalk-stream-<server>-<timestamp>.<ext>. Required for --format feather. |
-f, --follow |
— | Keep streaming until interrupted (Ctrl-C) or --count is reached. Without this, print the next message then exit. |
-n, --count N |
1 without --follow, unlimited with it |
Number of delta messages to output |
--bare |
— | Print to stdout with no informational messages. Ideal for piping to other tools. |
Output formats
csv / json: timestamp, context, source, path, value — one row per path/value pair in each delta's updates, written incrementally as messages arrive. Structured values (e.g. navigation.position) are JSON-encoded in the value column.
raw: the exact delta message JSON as received from the server, one message per line.
feather: Apache Arrow Feather binary format, same columns as csv/json. Requires pip install 'signalk-cli[feather]'. Unlike the other formats, rows are buffered in memory across all received messages and written once the session ends (--count reached, or Ctrl-C with --follow) — cannot be streamed to stdout.
Examples
# Next update for one path, then exit
python -m signalk_cli.stream deltas --host 10.36.10.21 navigation.speedOverGround
# Tail all navigation updates until Ctrl-C
python -m signalk_cli.stream deltas --host 10.36.10.21 --follow 'navigation.*'
# Tail oil temperature across every engine (mid-path wildcard)
python -m signalk_cli.stream deltas --host 10.36.10.21 --follow 'propulsion.*.oilTemperature'
# Next 20 messages across all subscribed paths, as JSON Lines
python -m signalk_cli.stream deltas --host 10.36.10.21 --format json --count 20
# Tail two specific paths, piping raw deltas to another tool
python -m signalk_cli.stream deltas --host 10.36.10.21 --follow --format raw --bare \
navigation.speedOverGround navigation.courseOverGroundTrue
# Everything the server has (equivalent to ?subscribe=all), following
python -m signalk_cli.stream deltas --host 10.36.10.21 --subscribe all --follow
# Faster resend interval (5s instead of the 60s default)
python -m signalk_cli.stream deltas --host 10.36.10.21 --follow --period 5 'navigation.*'
# Send every change immediately, no more than 5 times/second
python -m signalk_cli.stream deltas --host 10.36.10.21 --follow \
--policy instant --min-period 0.2 navigation.speedOverGround
# Capture 500 messages to an auto-named Feather file
python -m signalk_cli.stream deltas --host 10.36.10.21 --count 500 --format feather --output 'navigation.*'
# Capture until Ctrl-C to a named Feather file
python -m signalk_cli.stream deltas --host 10.36.10.21 --follow -o capture.feather 'navigation.*'
Time range
All commands that query data accept the same three time parameters. At least one of --from or --duration must be provided (or the tool supplies a one-hour default).
| Parameter | Format | Examples |
|---|---|---|
--from |
ISO 8601 timestamp | 2026-05-26T00:00:00Z |
--to |
ISO 8601 timestamp | 2026-05-27T00:00:00Z |
--duration |
ISO 8601 duration or integer seconds | PT1H, PT15M, P1D, P1W, 3600 |
Typical combinations:
--duration PT1H— last hour ending now--from T --duration PT1H— hour starting at T--from T1 --to T2— explicit range--duration PT1H --to T— hour ending at T--duration P1D— last 24 hours (expanded to from/to automatically)
Default caching
The default history provider is fetched from the server once and cached per host in ~/.cache/signalk-history-cli/. Pass --no-cache to force a fresh lookup, or --provider <id> to target a specific provider explicitly.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file signalk_cli-2.0.1.tar.gz.
File metadata
- Download URL: signalk_cli-2.0.1.tar.gz
- Upload date:
- Size: 26.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d2156958b4c337a3c2a3aaf0217f94b81d2ccd56fdfa764e194db5680f6b4fbe
|
|
| MD5 |
57042247c7e0d3e5b78c1ca8083d21d8
|
|
| BLAKE2b-256 |
8cfa55d9714d49a5c33b7e91e0b3173cf89d09f7cb38916954129f7d573167a5
|
Provenance
The following attestation bundles were made for signalk_cli-2.0.1.tar.gz:
Publisher:
pypi-publish.yml on rhizomatics/signalk-cli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
signalk_cli-2.0.1.tar.gz -
Subject digest:
d2156958b4c337a3c2a3aaf0217f94b81d2ccd56fdfa764e194db5680f6b4fbe - Sigstore transparency entry: 2305072314
- Sigstore integration time:
-
Permalink:
rhizomatics/signalk-cli@3f855bc1191b5ff083ef9c491378d0eb5be8259e -
Branch / Tag:
refs/tags/v2.0.1 - Owner: https://github.com/rhizomatics
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@3f855bc1191b5ff083ef9c491378d0eb5be8259e -
Trigger Event:
release
-
Statement type:
File details
Details for the file signalk_cli-2.0.1-py3-none-any.whl.
File metadata
- Download URL: signalk_cli-2.0.1-py3-none-any.whl
- Upload date:
- Size: 30.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
acad0f0530470b1ddabe918a7419f3f0051569cb5fa5452e03a53c364c019b3a
|
|
| MD5 |
85533942684f81a5935654c08be7f00a
|
|
| BLAKE2b-256 |
63e7b598cdbdd443e2df7d09f43ae7bf26d23eb8f674c3cdabafbc06d127bab6
|
Provenance
The following attestation bundles were made for signalk_cli-2.0.1-py3-none-any.whl:
Publisher:
pypi-publish.yml on rhizomatics/signalk-cli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
signalk_cli-2.0.1-py3-none-any.whl -
Subject digest:
acad0f0530470b1ddabe918a7419f3f0051569cb5fa5452e03a53c364c019b3a - Sigstore transparency entry: 2305072573
- Sigstore integration time:
-
Permalink:
rhizomatics/signalk-cli@3f855bc1191b5ff083ef9c491378d0eb5be8259e -
Branch / Tag:
refs/tags/v2.0.1 - Owner: https://github.com/rhizomatics
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@3f855bc1191b5ff083ef9c491378d0eb5be8259e -
Trigger Event:
release
-
Statement type: