---
slug: cli/vectors
title: afy collections, index, and points — Aetherfy vector commands
kind: reference
surface: cli
summary: Reference for the Aetherfy CLI's vector commands — afy collections list, get, create and delete, afy index create and delete (which waits until the index is built), and afy points count, get and search — with --json output, exit codes, and how the endpoint and workspace are chosen.
sources:
  - aetherfy-cli:cmd/vectors.go
  - aetherfy-cli:cmd/collections.go
  - aetherfy-cli:cmd/index.go
  - aetherfy-cli:cmd/points.go
  - aetherfy-cli:internal/vectors/client.go
  - aetherfy-cli:internal/vectors/resolve.go
  - aetherfy-cli:internal/vectors/index.go
  - aetherfy-cli:internal/vectors/ops.go
  - aetherfy-vectors-python-sdk:aetherfy_vectors/client.py
  - vectordb:backend/routes/proxy.js
  - vectordb:backend/services/proxy.js
---

# afy collections, index, and points

## The Aetherfy CLI's vector commands

Three command groups of the Aetherfy CLI read and manage the Aetherfy vector
database, with the same API key as every other `afy` command. They cover
inspecting collections, creating and deleting them, managing payload indexes,
and reading points. Loading points is not among them: the Python and JavaScript
SDKs do that, with the chunking and retries a bulk load needs (see
[/vectors/sdk](/vectors/sdk)).

| Command | Purpose |
|---|---|
| `afy collections list` | List the collections in a workspace |
| `afy collections get <name>` | Show one collection |
| `afy collections create <name>` | Create a collection |
| `afy collections delete <name>` | Delete a collection and every point in it |
| `afy index create <collection> <field>` | Index one payload field, and wait until the index is built |
| `afy index delete <collection> <field>` | Drop the payload index on one field |
| `afy points count <collection>` | Count the points, or those a filter matches |
| `afy points get <collection> <id>...` | Read points by id, with their payloads |
| `afy points search <collection>` | Find the points nearest to a vector |

The `collections` group also answers to `collection`.

## Flags every Aetherfy vector command takes

Each of the nine commands takes these four flags, in addition to the global
flags on [/cli](/cli).

| Flag | Type | Default | Description |
|---|---|---|---|
| `--json` | bool | false | Print one JSON object with stable field names. `-o json` does the same |
| `--workspace` | string | `AETHERFY_WORKSPACE`, else none | Workspace the collection names belong to |
| `--vectors-url` | string | see below | Aetherfy vectors API endpoint |
| `--api-region` | string | `AETHERFY_VECTORS_API_REGION` | API region to connect to: `us-east-1`, `eu-central-1` or `ap-southeast-1` |

## How the Aetherfy CLI chooses the vectors endpoint

The Aetherfy CLI picks the endpoint in the same order as the Aetherfy SDKs:

1. `--vectors-url`, when given.
2. `AETHERFY_VECTORS_URL`, when set. It also wins over an API region, with a
   warning on stderr: Aetherfy sets this variable on every agent machine.
3. `--api-region`, else `AETHERFY_VECTORS_API_REGION`. The region is turned into
   a URL by asking `GET /api/v1/regions` on `https://vectors.aetherfy.com`.
4. `https://vectors.aetherfy.com`.

An API region outside the three above is refused before any request, with exit
code 2. The API region only chooses which Aetherfy endpoint answers; it is not
where a collection's data lives, which `afy collections create --regions` sets.

## How the Aetherfy CLI chooses the workspace

Aetherfy collection names are scoped to a workspace: `articles` in workspace
`research` and `articles` outside any workspace are two different collections.
The Aetherfy CLI uses `--workspace` when it is given, else `AETHERFY_WORKSPACE`,
else no workspace, which is the SDKs' `workspace="auto"` default. Aetherfy sets
`AETHERFY_WORKSPACE` only on an agent that belongs to a workspace.
`--workspace ""` forces no workspace even where the variable is set.

Every `--json` object says which endpoint and workspace the command used:

```json
{
  "endpoint": "https://vectors.aetherfy.com",
  "workspace": "research",
  "collections": []
}
```

`workspace` is `null` when no workspace was used.

## Listing and inspecting Aetherfy collections

`afy collections list` lists the collections in the chosen workspace, or the
collections outside any workspace when none is chosen. The two are separate:
neither list includes the other.

```bash
afy collections list
afy collections list --workspace research --json
```

Each entry of `collections` in the `--json` output carries `name`,
`description` (or `null`), `size`, `distance`, `status`, `points_count` and
`created_at`. An empty result is `"collections": []`.

`afy collections get <name>` shows one collection. Its `--json` output holds
one `collection` object with the same fields plus `regions` and `updated_at`.

```bash
afy collections get articles --json
```

## Creating and deleting Aetherfy collections

`afy collections create <name>` creates a collection for vectors of one size,
compared with one distance.

| Flag | Type | Default | Description |
|---|---|---|---|
| `--size` | int | none, required | Vector size in dimensions, above 0 |
| `--distance` | string | none, required | `cosine`, `dot`, `euclid` or `manhattan` |
| `--regions` | strings | every region your plan or workspace covers | Comma-separated regions to place the collection in, a subset of your plan's regions |

```bash
afy collections create articles --size 1536 --distance cosine
afy collections create articles --size 768 --distance dot --regions us-east-1,eu-central-1 --json
```

The `--json` output's `collection` holds `name`, `size`, `distance` and the
`regions` Aetherfy placed the collection in. Creating a collection that already
exists with the same settings succeeds and changes nothing.

`afy collections delete <name>` deletes a collection and every point in it. It
asks you to type the collection's name first.

| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
| `--yes` | `-y` | bool | false | Delete without asking |

When stdin is not a terminal, nobody can answer the question, so without
`--yes` the Aetherfy CLI deletes nothing and exits 2. A script passes `--yes`:

```bash
afy collections delete articles --yes --json
```

## Aetherfy payload indexes: afy index create waits until the index is built

`afy index create <collection> <field>` creates a payload index on one field
and exits 0 only once the index is built, so a filter or an ordered scroll on
the field works as soon as it returns.

| Flag | Type | Default | Description |
|---|---|---|---|
| `--type` | string | none, required | `keyword`, `integer`, `float`, `bool`, `geo`, `datetime`, `uuid`, `text`, or a JSON object for a parameterised index |
| `--timeout` | number | 600 | Seconds to wait for the build before giving up |

The default wait is ten minutes; these two commands wait the same way:

```bash
afy index create articles thread_id --type keyword
afy index create articles thread_id --type keyword --timeout 600
```

```bash
afy index create articles ts --type integer --timeout 300 --json
afy index create articles body --type '{"type":"text","tokenizer":"word","lowercase":true}'
```

This is the Aetherfy SDKs' `create_field_index` behaviour, step for step:

| Step | What happens |
|---|---|
| The server holds the create | Aetherfy waits a while for the build before answering |
| `completed` | The index is built; the command exits 0 |
| `acknowledged` | The build outlived that wait and carries on; the command sends the same create again, which waits for the running build |
| An `acknowledged` that came back at once | The server did not hold it, so the next create waits first, a little longer each time |
| Any other answer | An error, exit 1; the index is not confirmed built |
| The `--timeout` passes | Exit 1 with "is still building"; the build carries on, and running the same command again waits for it |

A `--timeout` that is not a number of seconds above 0 is refused before any
request, naming the value, with exit code 2.

`afy index delete <collection> <field>` drops the index on one field in a
single request, allowed as long as a create, because Aetherfy may hold a
delete the same way. Dropping an index the field does not have succeeds; a
collection that does not exist is an error.

```bash
afy index delete articles thread_id
```

## Reading Aetherfy points: count, get, and search

The Aetherfy CLI's points commands only read. `--filter` takes a filter as a
JSON object, in the shape the SDKs send (see [/vectors/filtering](/vectors/filtering)).

`afy points count <collection>` counts the points exactly. Without `--json` it
prints the bare number, so `$(afy points count articles)` is the count.

```bash
afy points count articles
afy points count articles --filter '{"must":[{"key":"lang","match":{"value":"en"}}]}' --json
```

`afy points get <collection> <id>...` reads points by id, with their payloads
and without their vectors. An id made only of digits is sent as a number,
anything else as a string, such as a UUID. An id that does not exist is left
out of the answer rather than reported.

```bash
afy points get articles 17 42 --json
```

`afy points search <collection>` returns the points nearest to a vector.

| Flag | Type | Default | Description |
|---|---|---|---|
| `--vector` | string | none, required | A JSON array of numbers, or `@path` to read one from a file |
| `--limit` | int | 10 | How many points to return |
| `--filter` | string | none | Only return points this filter matches |

```bash
afy points search articles --vector '[0.12, -0.03, 0.88]' --limit 5
afy points search articles --vector @query.json --json
```

In `--json` output each entry of `points` carries `id` and `payload`, and a
search hit carries `score` as well.

## Aetherfy vector command errors and exit codes

| Code | When |
|---|---|
| 0 | Success |
| 1 | The request failed: the Aetherfy vectors API refused it, it got no answer, or an index was still building at the deadline |
| 2 | The input was refused before any request: a bad `--size`, `--distance`, `--timeout`, `--vector`, `--filter`, `--limit`, `--type` or `--api-region`, a delete nobody confirmed, or a command line that does not parse (an unknown flag, a value of the wrong type, the wrong number of arguments) |
| 3 | Not logged in |

Nothing goes to stdout on a failure. On stderr, the Aetherfy vectors API's own
status, code and message are copied through unchanged. With `--json` stderr
holds one object, for every failure except a command line that does not
parse, which is a plain `Error:` line because parsing stopped before `--json`
was necessarily read:

```json
{"error": {"status": 404, "code": "NOT_FOUND", "message": "Collection 'articles' not found"}}
```

Without `--json` it is one line, `Error: Collection 'articles' not found (NOT_FOUND)`.
A failure that got no answer from the API has no `status` or `code`. The codes
themselves are listed on [/vectors/errors](/vectors/errors).
