ServicesKV Store

Search and Discovery

Three distinct tools, each answering a different question. Picking the wrong one is the most common KV mistake:

  • list browses key names - by prefix, tag, owner, or a substring of the key path.
  • search runs full-text search over values - but only values that were written with indexed.
  • stats aggregates counts and sizes under a prefix.

Listing keys

snug kv list --prefix config/
snug kv list --prefix config/ --depth 0          # immediate children only
snug kv list --tags ui --owner me --private
snug kv list --prefix logs/ --sort-by updated_at --sort-order desc
snug kv list -q "session" --prefix cache/        # substring on key NAMES

The JSON payload is a keys array of metadata (no values) plus the standard pagination object; captured live:

{
  "keys": [
    {
      "key": "docs/indexed",
      "content_type": "application/json",
      "size_bytes": 33,
      "owner": "docs-writer",
      "private": false,
      "tags": [],
      "created_at": "2026-08-28T03:48:16.356982Z",
      "updated_at": "2026-08-28T03:48:16.356982Z"
    }
  ],
  "pagination": { "total": 1, "page": 1, "page_size": 25, "has_more": false }
}

Sort fields are created_at, updated_at, or key; pages default to 25 entries. Other users' private keys simply do not appear.

Full-text search over values

Only values written with --indexed are searchable, and indexing is not retroactive - re-set a key to index it. Verified: two keys with identical content, one indexed, and search returns only the indexed one.

snug kv set docs/indexed '{"content":"searchable words here"}' --indexed
snug kv search "searchable words" --prefix docs/
{
  "results": [
    {
      "key": "docs/indexed",
      "snippet": "searchable words here",
      "score": 1.0,
      "content_type": "application/json",
      "tags": [],
      "updated_at": "2026-08-28T03:48:16.356982Z"
    }
  ],
  "pagination": { "total": 1, "page": 1, "page_size": 25, "has_more": false }
}

Remember the split: list -q "dark" will not find {"theme":"dark"} - it looks at key paths, not value bodies. That is what search is for.

Aggregate stats

snug --output json kv stats --prefix docs/
{
  "total_keys": 5,
  "total_size_bytes": 132,
  "keys_by_namespace": { "docs": 5 },
  "keys_by_content_type": { "application/json": 5 },
  "keys_with_ttl": 0,
  "private_keys": 1,
  "indexed_keys": 1
}

A scripting pattern

List, review, then batch-delete - JSON mode prints the bare payload, so fields are addressed directly:

snug --output json kv list --tags deprecated --owner me \
  | jq -r '.keys[].key' | tee /tmp/to-delete.txt
# review, then:
snug kv batch-delete "$(paste -sd, /tmp/to-delete.txt)" --force

Note that these endpoints take KV-specific parameters (prefix, tags, q), not the shared search grammar used by entity list endpoints - the exact parameters are in the KV Store API reference.

On this page