Skip to main content

Spider CLI

The Spider CLI (spider) is a standalone command-line tool for querying Spider-captured network traffic data and managing capture lifecycle. It is designed for both humans and AI agents, and follows a kubectl-style verb-first command structure (spider <verb> <resource>).

Install

Binaries are published for Linux, macOS and Windows on both amd64 and arm64 architectures at https://repository.floocus.com/bin/spider-cli-<os>-<arch>/<version>/spider.xz (or spider.exe.xz on Windows). Use latest for the most recent version, or a specific tag like 1.0.0 to pin.

Linux / macOS

Auto-detects OS and architecture:

OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m); [ "$ARCH" = "x86_64" ] && ARCH=amd64; [ "$ARCH" = "aarch64" ] && ARCH=arm64
curl -fL "https://repository.floocus.com/bin/spider-cli-${OS}-${ARCH}/latest/spider.xz" | unxz > /usr/local/bin/spider
chmod +x /usr/local/bin/spider

Requires xz-utils (Debian/Ubuntu: apt install xz-utils; macOS: brew install xz).

Windows

PowerShell, Windows 10+ (uses the bundled tar which handles .xz):

$arch = if ($Env:PROCESSOR_ARCHITECTURE -eq 'ARM64') { 'arm64' } else { 'amd64' }
Invoke-WebRequest "https://repository.floocus.com/bin/spider-cli-windows-$arch/latest/spider.exe.xz" -OutFile spider.exe.xz
tar -xf spider.exe.xz
# Then move spider.exe to a directory on your PATH.

Available platforms

OSamd64arm64
Linuxspider-cli-linux-amd64/<v>/spider.xzspider-cli-linux-arm64/<v>/spider.xz
macOSspider-cli-darwin-amd64/<v>/spider.xzspider-cli-darwin-arm64/<v>/spider.xz
Windowsspider-cli-windows-amd64/<v>/spider.exe.xzspider-cli-windows-arm64/<v>/spider.exe.xz

Binaries are statically linked (built with CGO_ENABLED=0) and have no runtime dependencies — the Linux builds run on glibc and musl (Alpine) alike.

Quick start

# Interactive setup (prompts for all fields; password/secret are hidden,
# arrow keys supported for line editing)
spider add profile prod

# Or non-interactive with a service account
spider add profile prod \
--api-url https://your-spider-instance \
--auth-type service_account \
--client-id <client_id> \
--client-secret <client_secret> \
--whisperer <whisperer_id> \
--controller <controller_id>

# Or with a human login
spider add profile prod \
--api-url https://your-spider-instance \
--auth-type human \
--email <email> \
--password <password> \
--whisperer <whisperer_id>

# Search last hour of HTTP errors
spider search http --query "stats.statusCode:[400 TO 599]" --pretty

# Get HTTP stats grouped by URL template
spider stats http --group-by template --pretty

# Detect duration outliers
spider outliers http --pretty

Authentication

Three auth types are supported:

Auth typeCredentialsUse case
service_account (default)--client-id + --client-secretAutomation, CI, AI agents
human--email + --passwordInteractive use with local accounts
oidcnone stored — browser sessionspider login browser flow (any user)

Credentials are stored in ~/.spider/profiles.json (mode 0600). Tokens are cached in ~/.spider/tokens.json and refreshed automatically when they expire.

service_account and human profiles authenticate automatically from their stored credentials — no explicit login step is needed, but the client secret / password sits in profiles.json in clear text. oidc profiles store no credentials at all and authenticate with spider login (below).

spider login completes the login in your browser and hands the resulting session back to the CLI automatically — no DevTools, no cookie copying. Only the session tokens are stored; your password or client secret never touches disk.

This is not OIDC-specific — it works for any user who can sign in to the Spider web interface, whether your organization uses OIDC or local Spider accounts. It captures whichever web session you already have. Create the profile with --auth-type oidc (which here just means "browser session, no stored credential"):

# Profile with no stored credentials
spider add profile prod \
--api-url https://your-spider-instance \
--auth-type oidc \
--team <team_id> \
--whisperer <whisperer_id>

# Authenticate — opens the browser
spider login prod # profile name optional; defaults to the active profile

# Clear session
spider logout [<profile>]

How it works:

  1. The CLI starts a temporary local server on 127.0.0.1 and opens <api_url>/customer/v1/sessions/token/cli in your browser.
  2. If you are not already signed in, you complete the normal web login there (OIDC or local account). Spider then mints a fresh session, stores a 60-second one-time code, and redirects back to the local server.
  3. The CLI exchanges the one-time code for the Spider tokens and stores them. The browser tab shows a success message; you can close it.
Does not work behind an SSO proxy

The browser flow does not work when the Spider API is behind an SSO proxy (e.g. Apache mod_auth_openidc). The browser carries the proxy session, but the CLI's back-channel token exchange is a separate request with no proxy session, so the proxy blocks it. On proxy-protected deployments, use the manual flow below — you copy the proxy cookies from the browser, and the CLI replays them on every request.

Manual login (proxy-protected deployments, or no browser)

When the browser handoff can't be used — an SSO proxy guards the API, or there's no browser available — copy the cookies from the browser yourself:

spider login oidc [<profile>] # paste refresh_token (+ proxy cookies) from DevTools
spider login proxy [<profile>] # non-OIDC instance behind an SSO proxy — paste session cookies

spider login oidc opens <api_url>/login/, then prompts for the refresh_token cookie (DevTools → Application → Cookies → refresh_token row → full value) and, optionally, the SSO proxy cookies (DevTools → Network → any request other than sessions/token → Request Headers → Cookie). Do not copy from the GET /sessions/token request — Spider rotates refresh tokens, so that one is already spent. spider login proxy captures only the proxy session cookies and validates them immediately; on expiry, commands fail with proxy session expired — run: spider login proxy.

Post login actions

Automatic team scoping: if the profile has a team_id, the CLI automatically exchanges the base user JWT for a team-scoped one (via GET /teams/v1/teams/:id/user-token) that carries whisperer access grants. This happens transparently on every token refresh.

Silent refresh: the CLI uses the stored refresh token to renew the Spider JWT in the background when it expires. No re-login is needed until the refresh token itself expires or is consumed by a concurrent browser session.

Command tree

Data search and retrieval

CommandDescription
spider search l7Search all L7 communications at once (HTTP, PostgreSQL, Redis, gRPC, Kafka)
spider search http|redis|grpc|kafka|psql|tcp|packetsSearch captured communications
spider search hostsSearch captured hosts (IP → hostname history per whisperer, merged)
spider get http|redis|grpc|kafka|psql|tcp|packets <id>Fetch a single communication by ID
spider get http <id> req|res bodyFetch and decompress a request/response body (gzip, deflate, brotli handled client-side)
spider stats http|redis|grpc|kafka|psql|tcp|packets|l7Aggregated statistics with optional --group-by
spider outliers http|redis|grpc|kafka|psql|l7IQR-based duration/size outliers + z-score status anomalies
spider aggs http|redis|grpc|kafka|psql|tcp|packets|l7Run raw Elasticsearch aggregations

spider search l7 queries all layer-7 communications at once — HTTP, PostgreSQL, Redis, Kafka and gRPC — in a single command, instead of one search per protocol. Each result carries an @type field identifying its protocol (HttpCommunication, PgCommunication, RedisCom, GrpcCom). TCP sessions and packets are not L7 communications and are not included.

# Newest L7 communications across every protocol in the last hour
spider search l7 --start -1h --pretty

# Restrict to specific protocols (repeatable or comma-separated)
spider search l7 --type http,redis --query "stats.dst.name:api.example.com" --pretty

# Break a protocol-mix down by protocol over the last 24h
spider stats l7 --start -24h --group-by protocol --pretty

l7 is also available on stats, aggs and outliers. The --type filter (http, pg/psql, redis, grpc) is combined with any --query, and the search defaults to newest-first by communication start time.

Hosts

spider search hosts returns the host (IP → hostname) history captured per whisperer. It queries the hosts service with aggregated: true, paginates the whole time window, then merges the overlapping per-time-range snapshots into one timeline per (whisperer, ip) — the same merge the Network-View "Hosts" panel applies. Output is a flat JSON array of {whisperer, ip, name, customName, firstSeen, lastSeen, type} records, sorted by (whisperer, ip, firstSeen) and capped by --size. A user --query is combined with the aggregated filter as (aggregated: true) AND (<query>). Like the other data commands it accepts --start, --stop, --whisperer, --query, --size, and --pretty, and requires whisperer scope (from the profile or --whisperer).

CommandDescription
spider search hostsMerged IP → hostname history per whisperer over the time window

Cluster-wide network usage

Per-minute aggregated traffic between Kubernetes actors, captured by Gocipher and enriched by the Controller. Two views share the same underlying records:

  • Logical (network-logical) — actors are namespace+kind+name (e.g. default:deployments:api). Best for "which workloads talk to which?".
  • Physical (network-physical) — actors include the node and the pod instance (e.g. node-1:default:Pod:api-7c5f8). Best for "which pod on which node sends what?".

Both views are scoped to a single controller (taken from the active profile's controller_id or --controller); they accept --start, --stop, --query, --size, and --pretty like the other data commands.

The network-usage index stores no document _source, so search network-logical / network-physical returns aggregated rows — one per (client × server) pair within the time window, with structured client / server actor (namespace / kind / name, plus node + instance for physical), ingress / egress / total bytes & messages, and the list of server ports observed. This matches the Network-View grid output. --size caps the number of rows returned, sorted by total.bytes desc.

CommandDescription
spider search network-logical|network-physicalSearch per-minute traffic records
spider stats network-logical|network-physicalBytes & message totals (ingress/egress/total), with optional --group-by
spider outliers network-logical|network-physicalIQR outlier detection on bytes & messages
spider aggs network-logical|network-physicalRun raw Elasticsearch aggregations on the network-usage index

Group-by dimensions for stats / outliers:

  • logical: client, client_namespace, client_kind, client_name, client_ip, server, server_namespace, server_kind, server_name, server_ip, server_port
  • physical: above + client_node, client_actor, client_instance_name, client_instance_kind, server_node, server_actor, server_instance_name, server_instance_kind

Management resources

CommandDescription
spider search whisperers|controllers|gociphers|teams|usersSearch management resources
spider search attachmentsSearch ephemeral whisperer attachments for a controller
spider show sidecarsList sidecar / statically-deployed whisperers (live)
spider get whisperer|controller|gocipher|team|user <id>Fetch a single resource by ID
spider show whisperer|controller|teamShow the resource referenced by the active profile

Coverage check — to know whether a workload already has a whisperer (attached on demand or deployed as a sidecar) before proposing a new attach:

# Ephemeral attachments currently bound to the workload
spider search attachments \
--query 'status:"ATTACHED" AND namespace:"<ns>" AND collection:"<kind>" AND item:"<name>"' \
--pretty

# Statically-deployed sidecars (filter by namespace/kind/name in the result)
spider show sidecars --pretty

If a whisperer is found, reuse its ID with --whisperer <id> on search http|psql|tcp|packets. Only run spider attach if no coverage exists.

Capture control

CommandDescription
spider show namespacesList Kubernetes namespaces visible to the profile's controller
spider show collection -n <ns> -c <type>List workloads in a namespace (types: pods, statefulsets, deployments, daemonsets, cronjobs)
spider attach -n <ns> -c <type> -t <name>Attach a whisperer to a workload and drive it to RECORDING

Sharing

CommandDescription
spider add linkCreate a private or public shareable link

Profile management

CommandDescription
spider add profile <name>Create or update a profile (interactive if no flags)
spider list profilesList all saved profiles
spider show profile [name]Show a profile (secrets redacted)
spider use profile <name>Set the default profile
spider delete profile <name>Remove a profile

Common flags

All data commands (search, stats, outliers, aggs) accept:

  • --start — start time (ISO 8601 or relative like -1h, -24h, or now)
  • --stop — stop time (default: now)
  • --query / -q — Lucene query string
  • --size — max results (default: 100)
  • --pretty — human-readable JSON output

Scope (mutually exclusive depending on the command):

  • --whisperer / -w — whisperer IDs for http, psql, tcp, packets (overrides profile, repeatable)
  • --controller — controller ID for network-logical and network-physical (overrides profile)

Global:

  • --profile <name> — use a specific profile instead of the default

Fetching request/response bodies

spider get http <id> req|res body fetches the raw body from the server and decompresses it client-side based on the Content-Encoding header. Supported encodings: gzip, deflate, br (brotli).

spider get http <id> res body > response.json

Spider has two link types:

Private link — requires a Spider account to open. Created by default.

spider add link \
[--view http|psql|tcp|packets|network-logical|network-physical] \
[--query "<lucene>"] \
[--start <t>] [--stop <t>] \
[--whisperer <id>] [--controller <id>]

Public link — anyone can open; an OTP is emailed to the recipient (or fully open if no email/domain restriction is set).

spider add link --public --expiry 72h \
[--emails analyst@example.com] \
[--domains @example.com] \
[--view http] [--query "<lucene>"] \
[--start <t>] [--stop <t>]

Both link types open Network-View pre-loaded with the selected scope (whisperers for the data views, controller for the network-usage views), team, time window, view, and optional Lucene filter.
Public links also restrict visible data via accessFilters — the same --query limits what the recipient can see.

Attaching whisperers to Kubernetes workloads

Discover targets first (requires controller_id in profile), then attach:

# List namespaces visible to the controller
spider show namespaces

# List workloads in a namespace
spider show collection -n my-namespace -c deployments

# Attach a whisperer to a target workload
spider attach -n my-namespace -c deployments -t my-service
# Uses the profile's whisperer_id and controller_id by default.
# Waits up to 30s for the whisperer to reach RECORDING state.

Repository

Gitlab