@headband/cli 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +334 -67
- package/dist/index.js +2136 -401
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# @headband/cli
|
|
2
2
|
|
|
3
|
-
Command-line tools for [Headband](https://headband.dev): project setup,
|
|
4
|
-
API
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
Command-line tools for [Headband](https://headband.dev): project setup, login,
|
|
4
|
+
API keys, indexes, documents, search, tasks, dedicated engines, schema
|
|
5
|
+
migrations and Sync. Every command works for a person at a terminal and for a
|
|
6
|
+
script or coding agent with no terminal at all.
|
|
7
7
|
|
|
8
8
|
```bash
|
|
9
9
|
npx @headband/cli --help
|
|
@@ -11,85 +11,213 @@ npx @headband/cli init
|
|
|
11
11
|
npx @headband/cli login
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
## Contents
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
- [Global options](#global-options)
|
|
17
|
+
- [Authentication](#authentication)
|
|
18
|
+
- [Scripts and agents](#scripts-and-agents)
|
|
19
|
+
- [Exit codes](#exit-codes)
|
|
20
|
+
- [Command reference](#command-reference)
|
|
21
|
+
- [What `init` creates](#what-init-creates)
|
|
22
|
+
|
|
23
|
+
## Global options
|
|
24
|
+
|
|
25
|
+
```text
|
|
26
|
+
--token <key> API key for this call. Wins over HEADBAND_API_KEY and stored logins.
|
|
27
|
+
--profile <name> Stored login to use (else HEADBAND_PROFILE, else the current profile)
|
|
28
|
+
--url <url> Headband URL (else HEADBAND_URL, else the profile's, else https://headband.dev)
|
|
29
|
+
--json Print one JSON document on stdout; errors print one JSON object on stderr
|
|
30
|
+
--yes, -y Answer yes to confirmations (required when stdin is not a terminal)
|
|
31
|
+
--help, -h Show help for the CLI or a command
|
|
21
32
|
```
|
|
22
33
|
|
|
23
|
-
|
|
24
|
-
`$XDG_CONFIG_HOME/headband/credentials.json` with file mode `0600`.
|
|
34
|
+
## Authentication
|
|
25
35
|
|
|
26
|
-
|
|
36
|
+
### Interactive login
|
|
27
37
|
|
|
28
|
-
|
|
38
|
+
```bash
|
|
39
|
+
headband login [--url <url>] [--profile <name>] [--json]
|
|
40
|
+
headband logout [--profile <name>] [--yes] [--no-revoke] [--json]
|
|
41
|
+
headband whoami [--json]
|
|
42
|
+
headband profiles list [--json]
|
|
43
|
+
headband profiles use <name>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`login` runs Headband's device flow: it prints a code and a link, opens your
|
|
47
|
+
browser, and waits while you approve it in the dashboard. It saves the key it
|
|
48
|
+
receives as a named profile and makes that profile current. The name defaults
|
|
49
|
+
to `default` for headband.dev and to the host name for any other URL, such as
|
|
50
|
+
`localhost-3000`. The full key is never printed; output shows only its prefix.
|
|
51
|
+
|
|
52
|
+
Log in to several Headband URLs or organizations and switch between them:
|
|
29
53
|
|
|
30
54
|
```bash
|
|
31
|
-
headband
|
|
55
|
+
headband login --profile prod
|
|
56
|
+
headband login --url http://localhost:3000 --profile local
|
|
57
|
+
headband profiles list
|
|
58
|
+
headband profiles use prod
|
|
59
|
+
headband indexes list --profile local # one command, without switching
|
|
32
60
|
```
|
|
33
61
|
|
|
34
|
-
|
|
62
|
+
`logout` revokes the profile's key on the server, then removes it from this
|
|
63
|
+
machine. It asks first at a terminal. `--yes` revokes without asking.
|
|
64
|
+
`--no-revoke` removes the local copy and leaves the key working. If the key is
|
|
65
|
+
already gone on the server, logout still succeeds; any other failure keeps the
|
|
66
|
+
local login so you can retry.
|
|
35
67
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
6. Create `headband.config.ts` with your settings
|
|
42
|
-
7. Create an example `<HeadbandSearch />` component
|
|
68
|
+
Credentials live in `~/.config/headband/credentials.json`, or
|
|
69
|
+
`$XDG_CONFIG_HOME/headband/credentials.json`, with file mode `0600`. A file
|
|
70
|
+
written by CLI 0.2.0 or earlier (profiles keyed by URL) still works: its
|
|
71
|
+
profiles get names on first read, and the file is saved in the new format the
|
|
72
|
+
next time the CLI writes it.
|
|
43
73
|
|
|
44
|
-
|
|
74
|
+
### Tokens and environment variables
|
|
75
|
+
|
|
76
|
+
A script, CI job or agent does not need to log in. Give it a key:
|
|
77
|
+
|
|
78
|
+
| Variable | Flag | Meaning |
|
|
79
|
+
| ------------------ | ----------- | ------------------------------------------------------ |
|
|
80
|
+
| `HEADBAND_API_KEY` | `--token` | The API key to send. Used instead of any stored login. |
|
|
81
|
+
| `HEADBAND_URL` | `--url` | The Headband URL. |
|
|
82
|
+
| `HEADBAND_PROFILE` | `--profile` | Which stored login to use. |
|
|
83
|
+
|
|
84
|
+
Precedence, highest first:
|
|
85
|
+
|
|
86
|
+
- **Key:** `--token`, then `HEADBAND_API_KEY`, then the stored profile.
|
|
87
|
+
- **URL:** `--url`, then `HEADBAND_URL`, then the profile's URL, then
|
|
88
|
+
`https://headband.dev`. With a token, the profile's URL counts only when you
|
|
89
|
+
name the profile with `--profile`.
|
|
90
|
+
- **Profile:** `--profile`, then `HEADBAND_PROFILE`, then the current profile,
|
|
91
|
+
then the only stored profile when there is one.
|
|
92
|
+
|
|
93
|
+
A stored key is only ever sent to the URL it was issued for. `--url` with no
|
|
94
|
+
`--profile` picks the stored profile for that URL; `--url` with a `--profile`
|
|
95
|
+
for a different URL is a usage error. A `--profile` name that does not exist is
|
|
96
|
+
an error, never a silent fallback.
|
|
45
97
|
|
|
46
98
|
```bash
|
|
47
|
-
|
|
48
|
-
|
|
99
|
+
export HEADBAND_API_KEY=hb_adm_...
|
|
100
|
+
export HEADBAND_URL=https://headband.dev
|
|
101
|
+
headband indexes list --json
|
|
49
102
|
```
|
|
50
103
|
|
|
51
|
-
|
|
104
|
+
Which key to use: an admin key from `headband keys create <name> --type admin`
|
|
105
|
+
covers indexes, documents, search, engines and Sync. Managing keys, projects
|
|
106
|
+
and schema state needs a key minted by `headband login`, because only those
|
|
107
|
+
carry `keys.manage`, `projects.manage` and `schema.manage`.
|
|
108
|
+
|
|
109
|
+
## Scripts and agents
|
|
110
|
+
|
|
111
|
+
The CLI never waits for input it cannot get.
|
|
112
|
+
|
|
113
|
+
- **No hanging prompts.** A command that would ask for confirmation fails at
|
|
114
|
+
once with exit code `2` and code `confirmation_required` when stdin is not a
|
|
115
|
+
terminal. Pass `--yes` to confirm. `headband init` does the same without
|
|
116
|
+
`--yes`.
|
|
117
|
+
- **One JSON document.** With `--json`, stdout carries exactly one JSON
|
|
118
|
+
document and progress lines go to stderr, so `headband ... --json | jq` is
|
|
119
|
+
safe. `docs export` is the exception by design: its output is the documents.
|
|
120
|
+
- **JSON errors.** With `--json`, a failure prints one line to stderr:
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{ "error": "Index not found", "code": "index_not_found", "status": 404, "exitCode": 5 }
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
`code` is the API's error code when there is one, else a CLI code such as
|
|
127
|
+
`usage_error`, `not_authenticated`, `confirmation_required` or
|
|
128
|
+
`network_error`. `status` is the HTTP status, or `null` when no request was
|
|
129
|
+
made.
|
|
130
|
+
|
|
131
|
+
- **Branch on exit codes**, not on message text. See the table below.
|
|
132
|
+
|
|
133
|
+
## Exit codes
|
|
134
|
+
|
|
135
|
+
| Code | Meaning | Typical cause |
|
|
136
|
+
| ----- | ---------------- | --------------------------------------------------------------------------------------------------------------- |
|
|
137
|
+
| `0` | Success | |
|
|
138
|
+
| `1` | Error | Anything not listed below; also `schema diff` when changes are pending |
|
|
139
|
+
| `2` | Usage | Unknown command or option, missing or malformed value, HTTP 400/413/422, confirmation needed without a terminal |
|
|
140
|
+
| `3` | Authentication | No key found, a `--profile` that does not exist, HTTP 401 |
|
|
141
|
+
| `4` | Permission | HTTP 403, or 402 (the plan does not allow it) |
|
|
142
|
+
| `5` | Not found | HTTP 404 or 410, `profiles use` with an unknown name |
|
|
143
|
+
| `6` | Conflict | HTTP 409, such as deleting a project that still has indexes |
|
|
144
|
+
| `7` | Rate limited | HTTP 429 |
|
|
145
|
+
| `8` | Server or engine | HTTP 5xx, or the URL could not be reached |
|
|
146
|
+
| `130` | Interrupted | Ctrl+C |
|
|
147
|
+
|
|
148
|
+
## Command reference
|
|
149
|
+
|
|
150
|
+
### Setup
|
|
52
151
|
|
|
53
152
|
```bash
|
|
54
|
-
headband
|
|
55
|
-
headband logout [--url <url>] [--yes]
|
|
56
|
-
headband whoami [--url <url>] [--json]
|
|
153
|
+
headband init [--yes]
|
|
57
154
|
```
|
|
58
155
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
156
|
+
Asks for your Headband URL, a browser-safe search key (`hb_src_...` only) and
|
|
157
|
+
a default index, installs `@headband/react`, and writes `headband.config.ts`
|
|
158
|
+
plus an example `<HeadbandSearch />` component. `--yes` skips the questions and
|
|
159
|
+
uses defaults. Running `headband` with no command runs `init`.
|
|
63
160
|
|
|
64
161
|
### Projects
|
|
65
162
|
|
|
66
163
|
```bash
|
|
67
164
|
headband projects list [--json]
|
|
68
|
-
headband projects create <name> --engine <meilisearch|typesense|elasticsearch>
|
|
165
|
+
headband projects create <name> --engine <meilisearch|typesense|elasticsearch|visor> [--json]
|
|
166
|
+
headband projects delete <id> [--force] [--yes] [--json]
|
|
69
167
|
```
|
|
70
168
|
|
|
169
|
+
`projects delete` refuses a project that still has indexes (exit `6`, code
|
|
170
|
+
`project_has_indexes`). `--force` deletes the project's indexes on its shared
|
|
171
|
+
engine along with it. Even with `--force`, a project with an index on a
|
|
172
|
+
dedicated engine, or an index being moved to one, is refused: delete or move
|
|
173
|
+
those indexes first. Deleting a project also deletes the API keys scoped to it.
|
|
174
|
+
|
|
71
175
|
### Keys
|
|
72
176
|
|
|
73
177
|
```bash
|
|
74
178
|
headband keys list [--json]
|
|
75
|
-
headband keys create <name> --type <admin|search> [--project <id>]
|
|
76
|
-
|
|
179
|
+
headband keys create <name> --type <admin|search> [--project <id>]
|
|
180
|
+
[--permissions <a,b,...>] [--expires <30d|ISO date>] [--json]
|
|
181
|
+
headband keys revoke <id> [--yes] [--json]
|
|
77
182
|
```
|
|
78
183
|
|
|
79
184
|
`keys create` is the only command that prints a raw API key. Store it when it is
|
|
80
|
-
shown
|
|
185
|
+
shown: Headband returns raw keys only once.
|
|
186
|
+
|
|
187
|
+
`--permissions` limits the new key to the permissions you list. You can grant
|
|
188
|
+
only permissions your own key holds, and only ones that fit the key type:
|
|
189
|
+
|
|
190
|
+
| Type | Grantable permissions |
|
|
191
|
+
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
192
|
+
| `search` | `search`, `analytics.write` |
|
|
193
|
+
| `admin` | `search`, `documents.read`, `documents.add`, `documents.delete`, `indexes.create`, `indexes.delete`, `settings.update`, `analytics.write`, `connectors.write`, `instances.manage`, `sync.manage` |
|
|
194
|
+
|
|
195
|
+
Anything else is refused with exit `4` and the names it refused. Without
|
|
196
|
+
`--permissions`, the key gets the type's defaults, cut down to what your key
|
|
197
|
+
holds. `keys.manage`, `projects.manage` and `schema.manage` are never
|
|
198
|
+
grantable here; only `headband login` mints them.
|
|
199
|
+
|
|
200
|
+
`--expires` sets when the key stops working: a duration from now (`12h`,
|
|
201
|
+
`30d`, `2w`, `1y`) or an ISO date (`2027-01-31`). It must be in the future and
|
|
202
|
+
at most one year away. Without it, the key does not expire.
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
headband keys create ci-reader --type admin --permissions search,documents.read --expires 30d --json
|
|
206
|
+
```
|
|
81
207
|
|
|
82
208
|
### Indexes
|
|
83
209
|
|
|
84
210
|
```bash
|
|
85
211
|
headband indexes list [--json]
|
|
86
212
|
headband indexes create <uid> [--primary-key <pk>] [--engine <engine>] [--instance <id>] [--json]
|
|
87
|
-
headband indexes delete <uid> [--yes]
|
|
88
|
-
headband indexes settings get <uid>
|
|
89
|
-
headband indexes settings set <uid> --file <settings.json>
|
|
90
|
-
headband indexes stats <uid>
|
|
213
|
+
headband indexes delete <uid> [--yes] [--json]
|
|
214
|
+
headband indexes settings get <uid>
|
|
215
|
+
headband indexes settings set <uid> --file <settings.json>
|
|
216
|
+
headband indexes stats <uid>
|
|
91
217
|
```
|
|
92
218
|
|
|
219
|
+
`settings get`, `settings set` and `stats` always print JSON.
|
|
220
|
+
|
|
93
221
|
`--instance <id>` creates the index on one of your dedicated engines (ids from
|
|
94
222
|
`headband instances list`). The index takes that engine's type, so `--engine` is
|
|
95
223
|
optional; if you pass it, it must match.
|
|
@@ -98,6 +226,57 @@ On the engine, the index has a longer name (`engineIndexUid`, such as
|
|
|
98
226
|
`hbo_<org>_products`). `indexes create` and `indexes list` show it. Use that name,
|
|
99
227
|
not the uid, with the engine's own client on the instance endpoint.
|
|
100
228
|
|
|
229
|
+
### Documents
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
headband docs push <file.json|file.jsonl> --index <uid> [--json]
|
|
233
|
+
headband docs export --index <uid> [--out <file>] [--format <jsonl|json>] [--batch <n>] [--json]
|
|
234
|
+
headband docs delete <docId> --index <uid> [--json]
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
`docs push` accepts a JSON array or a JSONL file and sends documents to
|
|
238
|
+
`/v1/bulk` in batches of 1000.
|
|
239
|
+
|
|
240
|
+
`docs export` pages through `GET /v1/documents` and writes every document in
|
|
241
|
+
the index, one page in memory at a time:
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
headband docs export --index products > products.jsonl
|
|
245
|
+
headband docs export --index products --out products.json
|
|
246
|
+
headband docs export --index products | head -5
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
- Without `--out`, documents stream to stdout and nothing else is printed
|
|
250
|
+
there. Progress for `--out` goes to stderr.
|
|
251
|
+
- `--format` is `jsonl` (one document per line, the default) or `json` (one
|
|
252
|
+
array). With `--out`, a `.json` file name picks `json`.
|
|
253
|
+
- `--out` writes to `<file>.partial` and renames it when the export finishes,
|
|
254
|
+
so a failed export never leaves a truncated file under the real name.
|
|
255
|
+
`--json` with `--out` prints a summary: `{index, out, format, exported}`.
|
|
256
|
+
- `--batch` is the page size. The default is 1000, or 250 for an index on
|
|
257
|
+
Typesense, which refuses larger pages.
|
|
258
|
+
- Elasticsearch serves at most the first 10,000 documents by paging, so a
|
|
259
|
+
larger Elasticsearch index fails partway with exit `8`.
|
|
260
|
+
- Export needs an admin key with `documents.read`.
|
|
261
|
+
|
|
262
|
+
### Search
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
headband search <index> <query> [--limit N] [--filter <expr>] [--json]
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Plain output shows a compact table. `--json` prints the raw API response.
|
|
269
|
+
|
|
270
|
+
### Tasks
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
headband tasks list [--json]
|
|
274
|
+
headband tasks get <id>
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
`tasks list` prints a table, or the raw response with `--json`. `tasks get`
|
|
278
|
+
prints JSON.
|
|
279
|
+
|
|
101
280
|
### Engines
|
|
102
281
|
|
|
103
282
|
Dedicated engines are private Meilisearch, Elasticsearch or Typesense servers for
|
|
@@ -106,50 +285,137 @@ gradually. Until your organization has access, these commands say so.
|
|
|
106
285
|
|
|
107
286
|
```bash
|
|
108
287
|
headband instances list [--json]
|
|
109
|
-
headband instances create <meilisearch|elasticsearch|typesense> [--name <name>]
|
|
288
|
+
headband instances create <meilisearch|elasticsearch|typesense|visor> [--name <name>]
|
|
289
|
+
[--lane <serverless|always_on>] [--memory <512m|1g|...>]
|
|
290
|
+
[--region <region>] [--idle-timeout <seconds>] [--json]
|
|
110
291
|
headband instances show <id> [--json]
|
|
292
|
+
headband instances update <id> [--name <name>] [--lane <serverless|always_on>]
|
|
293
|
+
[--memory <512m|1g|...>] [--idle-timeout <seconds>] [--json]
|
|
111
294
|
headband instances wake <id> [--json]
|
|
112
295
|
headband instances park <id> [--json]
|
|
113
|
-
headband instances
|
|
114
|
-
headband instances
|
|
296
|
+
headband instances wakes <id> [--limit <n>] [--json]
|
|
297
|
+
headband instances delete <id> [--yes] [--json]
|
|
298
|
+
headband instances connect <id> [--client <node|curl>] [--json]
|
|
115
299
|
```
|
|
116
300
|
|
|
117
|
-
`
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
Project keys do not work on engine endpoints. Serverless engines are available for
|
|
122
|
-
Meilisearch only for now. If a command says the key cannot manage engines, run
|
|
123
|
-
`headband login` again.
|
|
301
|
+
`update` changes only the settings you pass; `--size` is an alias for
|
|
302
|
+
`--memory`. The engine and region cannot change. A resize applies in the
|
|
303
|
+
background: `instances show` reports the state as "applying changes" until it
|
|
304
|
+
is done. Always-on engines need a paid plan (exit `4` otherwise).
|
|
124
305
|
|
|
125
|
-
|
|
306
|
+
`wakes` lists recent wake-ups, newest first: when each was requested, how it
|
|
307
|
+
woke, the outcome and how long it took to be ready. `--limit` takes up to 200;
|
|
308
|
+
the default is 50.
|
|
309
|
+
|
|
310
|
+
`connect` prints the endpoint and a snippet for the engine's own client.
|
|
311
|
+
Authenticate with an organization-wide key. The snippets create an index and add
|
|
312
|
+
a document, so run them with an admin key (`headband keys create <name> --type
|
|
313
|
+
admin`); a search key can only search. Project keys do not work on engine
|
|
314
|
+
endpoints. Serverless engines are available for Meilisearch, and for Typesense
|
|
315
|
+
in early access; Elasticsearch runs always on. If a command says the key cannot
|
|
316
|
+
manage engines, run `headband login` again.
|
|
317
|
+
|
|
318
|
+
### Schema migrations
|
|
319
|
+
|
|
320
|
+
For projects that define their indexes in `headband.config.ts` with
|
|
321
|
+
`@headband/sync`. These commands read that file from the current directory.
|
|
126
322
|
|
|
127
323
|
```bash
|
|
128
|
-
headband
|
|
129
|
-
headband
|
|
324
|
+
headband schema diff [--allow-destructive] [--json]
|
|
325
|
+
headband schema generate [--slug <slug>] [--dir <dir>] [--allow-destructive] [--json]
|
|
326
|
+
headband schema apply [--allow-destructive] [--dir <dir>] [--yes] [--json]
|
|
327
|
+
headband schema status [--dir <dir>] [--json]
|
|
130
328
|
```
|
|
131
329
|
|
|
132
|
-
|
|
133
|
-
|
|
330
|
+
- `diff` compares the config with the schema state on the server. Like
|
|
331
|
+
`git diff --exit-code`, it exits `1` when changes are pending and `0` when
|
|
332
|
+
in sync. `--json` prints `{inSync, ops}`.
|
|
333
|
+
- `generate` writes a migration file for the pending changes into `--dir`
|
|
334
|
+
(default `headband/migrations`). `--json` prints `{path}`, with `null` when
|
|
335
|
+
there was nothing to generate.
|
|
336
|
+
- `apply` runs the migration files not yet applied, in order, backfilling
|
|
337
|
+
documents through your config's `adapter` when a change needs a reindex.
|
|
338
|
+
Removing an index needs `--allow-destructive`. `--json` prints
|
|
339
|
+
`{appliedFiles, appliedOps}`.
|
|
340
|
+
- `status` shows each index's applied version and any drift. `--json` prints
|
|
341
|
+
`{indexes, localApplied, localHead}`.
|
|
134
342
|
|
|
135
|
-
|
|
343
|
+
Schema commands need a key with `schema.manage`, which only `headband login`
|
|
344
|
+
mints.
|
|
345
|
+
|
|
346
|
+
### Sync
|
|
347
|
+
|
|
348
|
+
Sync keeps search indexes in step with a Postgres database. There are two ways
|
|
349
|
+
to run it.
|
|
350
|
+
|
|
351
|
+
**Managed Sync** runs on Headband. You register a source database and define
|
|
352
|
+
synced indexes; Headband reads the database's changes and keeps the indexes
|
|
353
|
+
current.
|
|
136
354
|
|
|
137
355
|
```bash
|
|
138
|
-
headband
|
|
356
|
+
headband sync source add <name> [--db-url <url>] [--tls-mode verify-full|require] [--ca-file <pem>] [--json]
|
|
357
|
+
headband sync source add <name> --kind batadb --batadb-project <id> --batadb-branch <id> --batadb-compute <id> --accept-broad-role
|
|
358
|
+
headband sync source list [--json]
|
|
359
|
+
headband sync source show <id> [--json]
|
|
360
|
+
headband sync source test <id> [--json]
|
|
361
|
+
headband sync source setup-sql <id> [--provider generic|rds|batadb] [--json]
|
|
362
|
+
headband sync source setup <id> [--owner-url <url>] [--provider generic|rds|batadb] [--yes] [--json]
|
|
363
|
+
headband sync source set-ca <id> (--ca-file <pem> | --none) [--tls-mode verify-full|require] [--json]
|
|
364
|
+
headband sync source remove <id> [--yes] [--json]
|
|
365
|
+
|
|
366
|
+
headband sync index create -f <file.sync.json> [--json]
|
|
367
|
+
headband sync index list [--source <id>] [--instance <id>] [--json]
|
|
368
|
+
headband sync index show <id> [--version <n>] [--json]
|
|
369
|
+
headband sync index update <id> -f <file.sync.json> [--rebuild] [--json]
|
|
370
|
+
headband sync index validate -f <file.sync.json> [--index <id>] [--json]
|
|
371
|
+
headband sync index preview <id> [--ids <id,id,...>] [-f <file.sync.json>] [--json]
|
|
372
|
+
headband sync index rebuild|pause|resume|check <id> [--yes] [--json]
|
|
373
|
+
headband sync index remove <id> [--drop-index] [--yes] [--json]
|
|
374
|
+
|
|
375
|
+
headband sync status [--json]
|
|
139
376
|
```
|
|
140
377
|
|
|
141
|
-
|
|
378
|
+
Keep connection strings out of shell history: the source URL can come from
|
|
379
|
+
`HEADBAND_SYNC_DB_URL`, the owner URL from `HEADBAND_SYNC_OWNER_URL`, and a
|
|
380
|
+
BataDB API key from `HEADBAND_BATADB_API_KEY` only. `sync source setup` runs
|
|
381
|
+
Headband's setup SQL on your machine as the tables' owner, in one transaction;
|
|
382
|
+
the owner URL never leaves your machine. Run `headband sync source --help` and
|
|
383
|
+
`headband sync index --help` for the details.
|
|
142
384
|
|
|
143
|
-
|
|
385
|
+
**Self-hosted Sync** runs a worker in your own infrastructure. Your app writes
|
|
386
|
+
changes to an outbox table, and the worker pushes them to Headband.
|
|
144
387
|
|
|
145
388
|
```bash
|
|
146
|
-
headband
|
|
147
|
-
headband
|
|
389
|
+
headband sync init [--table <name>] [--write] [--json]
|
|
390
|
+
headband sync worker [--loop] [--budget-ms <ms>] [--batch-size <n>] [--reconcile-every <n>] [--json]
|
|
391
|
+
headband sync worker --scaffold docker [--force] [--json]
|
|
392
|
+
headband sync reconcile [--fix] [--json]
|
|
393
|
+
headband sync retry-dead-letters [--json]
|
|
148
394
|
```
|
|
149
395
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
396
|
+
- `init` prints the outbox table's DDL; `--write` also saves it to
|
|
397
|
+
`headband/outbox.sql`. `--json` prints `{ddl, path}`.
|
|
398
|
+
- `worker` drains the outbox. Without `--budget-ms` it loops until stopped
|
|
399
|
+
(Ctrl+C or SIGTERM finish the current batch first). With `--budget-ms` it
|
|
400
|
+
stops after that long; `--json` then prints the run report. In a loop,
|
|
401
|
+
`--json` sends progress to stderr and prints the report when the worker
|
|
402
|
+
stops.
|
|
403
|
+
- `worker --scaffold docker` writes `Dockerfile.headband-sync` and prints a
|
|
404
|
+
compose service for it.
|
|
405
|
+
- `reconcile` compares each index's document count with its source table and
|
|
406
|
+
reports drift; `--fix` resends a drifted index in full. `--json` prints
|
|
407
|
+
`{indexes}`.
|
|
408
|
+
- `retry-dead-letters` requeues rows that failed too many times. `--json`
|
|
409
|
+
prints `{requeued}`.
|
|
410
|
+
|
|
411
|
+
The worker and `retry-dead-letters` read the outbox database URL from
|
|
412
|
+
`DATABASE_URL`, falling back to `HEADBAND_DATABASE_URL`. The worker and
|
|
413
|
+
`reconcile` need `headband.config.ts` to export an `adapter`.
|
|
414
|
+
|
|
415
|
+
## What `init` creates
|
|
416
|
+
|
|
417
|
+
**`headband.config.ts`**: search configuration that reads from the
|
|
418
|
+
`NEXT_PUBLIC_HEADBAND_KEY` env var with a fallback:
|
|
153
419
|
|
|
154
420
|
```typescript
|
|
155
421
|
export const headbandConfig = {
|
|
@@ -164,7 +430,8 @@ by a browser component, so the CLI only accepts scoped `hb_src_` search keys.
|
|
|
164
430
|
Keep admin keys in server-only environments for indexing, settings, and sync
|
|
165
431
|
jobs.
|
|
166
432
|
|
|
167
|
-
**`components/headband-search.tsx`** (or `src/components/` if your project uses
|
|
433
|
+
**`components/headband-search.tsx`** (or `src/components/` if your project uses
|
|
434
|
+
a `src/` directory): a ready-to-use search component:
|
|
168
435
|
|
|
169
436
|
```tsx
|
|
170
437
|
"use client";
|