CLI

polign is the command-line client for a running polign_db server. It speaks the same HTTP/JSON API as everything else, so every command here is a curl you didn't have to type. This page is the full reference; the user guide is the walkthrough.

Getting the binary

polign ships in the release archive next to polign-server starting with the release after v0.1.0-rc.9. On earlier releases — or any time — you can build it from a checkout:

go build -tags cloud -o polign ./cmd/polign
./polign -version

The cloud build tag matters for one command only — collections claim writes to your s3:// or gcs:// bucket directly. Everything else is pure HTTP and builds without it. Release binaries are always built with the tag.

Talking to a server

polign [-url http://localhost:23000] [-key plgn_…] <command> …
FlagEnvironmentWhat it does
-url$POLIGN_URLServer base URL. Defaults to http://localhost:23000, the server's HTTP listener.
-key$POLIGN_API_KEYAPI key, sent as Authorization: Bearer. The collection commands need one; the data commands never do.
-versionPrint the version and exit.

Global flags go before the command, per-command flags after it:

export POLIGN_URL=https://db.example.com:23000
polign search articles -text "getting started" -k 5

# or per invocation
polign -url https://db.example.com:23000 search articles -text "getting started"

Data commands

These are the everyday operations — batch put and batch get stay in the client libraries. No API key required — the data plane ignores one if you send it. Collections are auto-created on the first put, inferring their dimension from that vector, so there is nothing to create first.

polign put <collection> <id> -values 0.1,0.2,… [-meta k=v]…
polign get <collection> <id>
polign delete <collection> <id>
polign list <collection> [-limit n] [-offset n]
polign search <collection> [-values …] [-text "…"] [-k 5] [-filter '{"k":"v"}']

put

An upsert: writing the same id twice replaces it. Prints the id on success.

polign put articles guide-1 \
  -values @embedding.json \
  -meta title="Getting started" -meta lang=en

-meta is repeatable and takes key=value. Metadata is string → string; it comes back with every hit and drives filters.

get, delete, list

polign get articles guide-1        # pretty-printed JSON: id, values, metadata
polign delete articles guide-1     # prints "deleted: true" (false if absent — not an error)
polign list articles -limit 100 -offset 0

list prints an ID/METADATA table followed by the collection's total, so it doubles as a "how much is in here?" check. Omit -limit to take the server's page size.

search

One command covers all three search modes — what you pass decides which you get:

# by meaning — vector search
polign search articles -values @query.json -k 5

# by keyword — BM25
polign search articles -text "getting started" -k 5

# both — hybrid, fused server-side
polign search articles -values @query.json -text "getting started" -k 5

# narrowed by metadata
polign search articles -values @query.json -k 5 \
  -filter '{"lang":"en","score":{"$gte":0.5}}'
FlagWhat it does
-valuesThe query vector. Omit it (and set -text) for a pure keyword search.
-textBM25 query. Alone = keyword search; with -values = hybrid.
-kHow many hits to return. Default 5.
-efHow hard the search tries: higher finds slightly better matches, a bit slower. 0 = server default.
-filterMetadata predicate as JSON. Bare values are equality (AND across keys); per-key operators ($eq, $ne, $in, $gt/$gte/$lt/$lte, $exists) and $and/$or/$not express more. Filtering happens during the search, not after it — asking for 5 results still returns the 5 best matching results.
-coldServe straight from object-storage segments instead of the in-memory index. Needs a segment store.
-nprobeHow many index regions a cold search checks; 0 = server default. Higher = more accurate, more object-store reads.
-rescoreOn compressed collections: how many candidates get re-checked exactly; bigger = more accurate, slower. 0 = default, a negative value skips the re-check entirely (fastest, least accurate).

Results print as an ID/DISTANCE/SCORE/METADATA table. distance is the vector metric (smaller = closer); score is relevance (larger = better) and shows - on a pure vector search, where there is no relevance score to report. Keyword and hybrid search read the object-store segment index, so they need a server started with a store — see the install guide.

Passing vectors

Anywhere -values appears, three input forms work:

FormExample
Inline list-values 0.1,0.2,0.3 — commas or spaces
File-values @embedding.json — a JSON array
Stdin-values - — a JSON array on stdin

Stdin is the one that makes the CLI composable: pipe your embedding model straight into a search.

./embed "how do I get started?" | polign search articles -values - -k 5

Collection commands

These manage the collection registry on a server started with -byo-store, where each collection lives in a bucket you own. They need an API key — pass -key or set $POLIGN_API_KEY. The advanced guide walks the whole lifecycle; this is the command surface.

polign setup -bucket s3://bkt/prefix         # print the IAM recipe for that bucket
polign collections create <name> -bucket s3://bkt/prefix [-role arn:…]
polign collections claim <name> <token>      # write the claim token, then verify
polign collections get <name>                # full JSON: status, backend, capabilities
polign collections list                      # NAME / STATUS / BUCKET table
polign collections verify <name>             # re-probe the bucket, refresh status
polign collections delete <name>             # unregister; bucket contents untouched
create flagWhat it does
-bucketRequired. The store URI the collection lives in, e.g. s3://myco-prod-vectors/polign.
-roleIAM role ARN the server assumes for this bucket — cross-account backends.
-regionBucket region, when it differs from the fleet's.
-gcs-saGCS service account to impersonate, for gcs:// backends.

create prints a claim token once and the exact claim command to run next. claim is the ownership proof: it writes the token to .polign/claim in the bucket using your credentials — not the server's — and then asks the server to verify. That's why this one command needs bucket access from wherever you run it, and why a typo'd bucket name fails at claim time instead of silently collecting your vectors.

polign collections create prod-docs -bucket s3://myco-prod-vectors/polign
claim token (shown once): plgnclaim_8d1f0c2ab34e…

polign collections claim prod-docs plgnclaim_8d1f0c2ab34e…
prod-docs: active

Output & exit codes

CommandOutput
list, search, collections listAligned columns on stdout — readable, and fine for awk.
get, collections get, setupIndented JSON, exactly as the server sent it. Pipe to jq.
put, delete, claim, verifyOne short confirmation line.

Errors go to stderr and exit 1; running with no command (or bad flags) prints usage and exits 2. Server errors are reported with the HTTP status and the server's own message, so a failing script says what the API said.

Scripting past the CLI

The CLI covers one vector at a time on the write path. For bulk loads, reach for a client library's batch put — up to 5,000 vectors per request instead of one process per vector. The Python SDK's put_many and the Go client's PutBatch both do this.

Other ways in

Same operations, different doors: the Python SDK, the gRPC API and Go client, and raw HTTP/JSON (curl examples in Install & deploy polign_db).