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> …
| Flag | Environment | What it does |
|---|---|---|
-url | $POLIGN_URL | Server base URL. Defaults to http://localhost:23000, the server's HTTP listener. |
-key | $POLIGN_API_KEY | API key, sent as Authorization: Bearer. The collection commands need one; the data commands never do. |
-version | — | Print 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}}'
| Flag | What it does |
|---|---|
-values | The query vector. Omit it (and set -text) for a pure keyword search. |
-text | BM25 query. Alone = keyword search; with -values = hybrid. |
-k | How many hits to return. Default 5. |
-ef | How hard the search tries: higher finds slightly better matches, a bit slower. 0 = server default. |
-filter | Metadata 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. |
-cold | Serve straight from object-storage segments instead of the in-memory index. Needs a segment store. |
-nprobe | How many index regions a cold search checks; 0 = server default. Higher = more accurate, more object-store reads. |
-rescore | On 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:
| Form | Example |
|---|---|
| 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 flag | What it does |
|---|---|
-bucket | Required. The store URI the collection lives in, e.g. s3://myco-prod-vectors/polign. |
-role | IAM role ARN the server assumes for this bucket — cross-account backends. |
-region | Bucket region, when it differs from the fleet's. |
-gcs-sa | GCS 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
| Command | Output |
|---|---|
list, search, collections list | Aligned columns on stdout — readable, and fine for awk. |
get, collections get, setup | Indented JSON, exactly as the server sent it. Pipe to jq. |
put, delete, claim, verify | One 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.
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.
Same operations, different doors: the Python SDK, the gRPC API and Go client, and raw HTTP/JSON (curl examples in Install & deploy polign_db).