@purveyors/cli 0.8.3 → 0.9.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 CHANGED
@@ -1,12 +1,10 @@
1
- # purvey — The Purveyors CLI
1
+ # purvey
2
2
 
3
- > Coffee intelligence from your terminal.
3
+ Coffee intelligence from your terminal.
4
4
 
5
- `purvey` is the official command-line interface for [purveyors.io](https://purveyors.io). It gives coffee professionals direct terminal access to the Purveyors platform: search green coffee availability, track pricing tiers, monitor inventory, record roasts, log sales, and capture tasting notes all from your terminal or scripts.
5
+ `purvey` is the official CLI for [purveyors.io](https://purveyors.io). It gives coffee professionals and AI agents direct access to the Purveyors platform from the terminal: catalog search, inventory tracking, roast logging, sales records, tasting notes, and Artisan `.alog` import.
6
6
 
7
- **Designed for both humans and AI agents.** Run `purvey context` for instant agent onboarding.
8
-
9
- ---
7
+ Run `purvey context` for the dense agent reference.
10
8
 
11
9
  ## Installation
12
10
 
@@ -14,284 +12,378 @@
14
12
  npm install -g @purveyors/cli
15
13
  ```
16
14
 
17
- Requires **Node.js >= 20**.
15
+ Requirements:
16
+
17
+ - Node.js 20 or newer
18
18
 
19
- Verify:
19
+ Verify the install:
20
20
 
21
21
  ```bash
22
22
  purvey --version
23
23
  ```
24
24
 
25
- ---
26
-
27
25
  ## Quick Start
28
26
 
29
27
  ```bash
30
28
  # 1. Authenticate
31
29
  purvey auth login
32
30
 
33
- # 2. Confirm your session
31
+ # 2. Confirm the session
34
32
  purvey auth status
35
33
 
36
- # 3. Search the catalog (no login required)
34
+ # 3. Search the catalog
37
35
  purvey catalog search --origin "Ethiopia" --stocked --pretty
38
36
 
39
- # 4. Check your inventory
37
+ # 4. Check inventory
40
38
  purvey inventory list --stocked --pretty
41
39
 
42
40
  # 5. Import a roast from Artisan
43
41
  purvey roast import ~/artisan/my-roast.alog --coffee-id 7 --pretty
44
42
  ```
45
43
 
46
- ---
47
-
48
44
  ## Authentication
49
45
 
50
- `purvey` authenticates via Google OAuth, using the same account as your purveyors.io web session.
46
+ `purvey` uses Google OAuth through purveyors.io.
51
47
 
52
- ### Browser Login (interactive)
48
+ Interactive login:
53
49
 
54
50
  ```bash
55
51
  purvey auth login
56
52
  ```
57
53
 
58
- Opens your default browser. Complete Google sign-in, then return to the terminal. Credentials are stored at `~/.config/purvey/credentials.json` (owner-readable only, mode 0600).
59
-
60
- ### Headless Login (agents, CI, servers)
54
+ Headless login for agents, CI, and remote machines:
61
55
 
62
56
  ```bash
63
57
  purvey auth login --headless
64
58
  ```
65
59
 
66
- No browser required. The CLI prints a Google OAuth URL — open it in any browser, sign in, then copy the full callback URL and paste it back at the prompt.
67
-
68
- ### Status
60
+ Status:
69
61
 
70
62
  ```bash
71
63
  purvey auth status
64
+ purvey auth status --json
72
65
  purvey auth status --pretty
73
66
  ```
74
67
 
75
- ```
76
- ✔ Logged in as you@example.com
77
- ℹ Role: member
78
- ℹ Token expires: 2026-04-01T08:00:00.000Z
79
- ```
80
-
81
- ### Token Refresh
82
-
83
- Tokens refresh automatically. No need to re-login between sessions.
84
-
85
- ### Logout
68
+ Logout:
86
69
 
87
70
  ```bash
88
71
  purvey auth logout
89
72
  ```
90
73
 
91
- Clears stored credentials from disk.
74
+ Credentials are stored at `~/.config/purvey/credentials.json`.
92
75
 
93
- ---
76
+ ### Auth roles
94
77
 
95
- ## Output Formats
78
+ `catalog` commands require an authenticated viewer session. Sign in before using:
96
79
 
97
- All `purvey` commands default to **compact JSON** — one line, no colors, machine-readable. This makes `purvey` pipeable into `jq`, `csvkit`, or any script.
80
+ - `purvey catalog search`
81
+ - `purvey catalog get <id>`
82
+ - `purvey catalog stats`
83
+ - `purvey catalog similar <id>`
98
84
 
99
- ### Compact JSON (default)
85
+ `inventory`, `roast`, `sales`, and `tasting` commands require a member role.
100
86
 
101
- ```bash
102
- purvey auth status
103
- # {"authenticated":true,"email":"you@example.com","role":"member","tokenExpires":"..."}
104
- ```
87
+ ## Output and Scripting
88
+
89
+ Most commands write compact JSON to stdout by default.
90
+ Use `--json` if you want to request that mode explicitly.
105
91
 
106
- ### Pretty JSON (`--pretty`)
92
+ Pretty JSON:
107
93
 
108
94
  ```bash
109
- purvey catalog search --origin "Ethiopia" --pretty
110
- # → indented, colorized JSON
95
+ purvey inventory list --pretty
111
96
  ```
112
97
 
113
- ### CSV (`--csv`)
98
+ CSV output for array results:
114
99
 
115
100
  ```bash
116
101
  purvey inventory list --csv > inventory.csv
117
- purvey catalog search --stocked --csv | head -5
102
+ purvey sales list --csv > sales.csv
118
103
  ```
119
104
 
120
- ### Piping with jq
105
+ Pipe JSON into `jq`:
121
106
 
122
107
  ```bash
123
108
  purvey inventory list | jq '.[].id'
124
- purvey catalog search --origin "Colombia" | jq '.[].cost_lb'
125
- purvey auth status | jq -r '.email'
109
+ purvey roast list --limit 5 | jq '.[].roast_id'
110
+ purvey auth status 2>/dev/null | jq -r '.email'
126
111
  ```
127
112
 
128
- User feedback messages (spinners, success/error) go to **stderr** only stdout is always clean data, safe to pipe.
113
+ Operational messages go to stderr, so stdout stays script-friendly.
129
114
 
130
- ---
115
+ ### Output caveats worth knowing
116
+
117
+ - `purvey auth status` prints human-readable output in an interactive terminal unless you pass `--json`, `--pretty`, or `--csv`. When piped or redirected, it emits JSON.
118
+ - `--json` is an explicit alias for the default compact JSON mode, and it forces JSON even in an interactive terminal.
131
119
 
132
120
  ## Command Reference
133
121
 
134
- ### Authentication
122
+ ### auth
135
123
 
136
- | Command | Description |
137
- | ------------------------------ | --------------------------------------------- |
138
- | `purvey auth login` | Log in via Google OAuth (browser) |
139
- | `purvey auth login --headless` | Log in without a browser (paste callback URL) |
140
- | `purvey auth status` | Show current authentication state and role |
141
- | `purvey auth logout` | Clear stored credentials |
124
+ - `purvey auth login`
125
+ - `purvey auth login --headless`
126
+ - `purvey auth status`
127
+ - `purvey auth logout`
142
128
 
143
- ### Catalog (no authentication required)
129
+ ### catalog
144
130
 
145
- | Command | Description |
146
- | ------------------------- | --------------------------------------------------- |
147
- | `purvey catalog search` | Search coffees by origin, process, price, or flavor |
148
- | `purvey catalog get <id>` | Get details for a specific coffee by catalog ID |
149
- | `purvey catalog stats` | Aggregate statistics for the full catalog |
131
+ - `purvey catalog search`
132
+ - `purvey catalog get <id>`
133
+ - `purvey catalog stats`
134
+ - `purvey catalog similar <id>`
150
135
 
151
- **catalog search options:**
136
+ `catalog search` filters:
152
137
 
138
+ - `--origin <text>` -- filter by origin (country, continent, or region)
139
+ - `--process <method>` -- filter by processing method (e.g. natural, washed)
140
+ - `--price-min <n>` -- minimum price per lb (USD)
141
+ - `--price-max <n>` -- maximum price per lb (USD)
142
+ - `--flavor <keywords>` -- flavor keywords, comma-separated
143
+ - `--name <text>` -- filter by coffee name (partial match, case-insensitive)
144
+ - `--supplier <name>` -- filter by supplier/source name (partial match, case-insensitive)
145
+ - `--ids <n,n,...>` -- fetch specific catalog IDs (comma-separated, ignores limit)
146
+ - `--stocked` -- only show currently stocked coffees
147
+ - `--sort <price|price-desc|name|origin|newest>` -- sort results
148
+ - `--offset <n>` -- skip N results for pagination
149
+ - `--limit <n>` -- maximum results to return (default: 10)
150
+
151
+ `catalog similar <id>` options:
152
+
153
+ - `--threshold <0-1>` -- minimum similarity score (default: 0.70)
154
+ - `--limit <n>` -- max results (default: 10)
155
+ - `--stocked-only` -- only show currently stocked beans
156
+
157
+ Examples:
158
+
159
+ ```bash
160
+ purvey catalog search --origin "Ethiopia" --pretty
161
+ purvey catalog search --supplier "Royal Coffee" --stocked --pretty
162
+ purvey catalog search --ids "1182,1183,1200"
163
+ purvey catalog search --stocked --sort price --offset 10 --limit 10
164
+ purvey catalog similar 1182 --threshold 0.85 --stocked-only --pretty
165
+ purvey catalog similar 1182 --json | jq '.[0]'
153
166
  ```
154
- --origin <text> country or region (e.g. "Ethiopia", "Colombia")
155
- --process <method> natural, washed, honey
156
- --price-min <n> min USD/lb
157
- --price-max <n> max USD/lb
158
- --flavor <keywords> comma-separated (e.g. "blueberry,citrus")
159
- --stocked only currently stocked coffees
160
- --limit <n> max results (default: 10)
161
- ```
162
167
 
163
- ### Inventory (member role required)
168
+ ### inventory
169
+
170
+ - `purvey inventory list`
171
+ - `purvey inventory get <id>`
172
+ - `purvey inventory add`
173
+ - `purvey inventory update <id>`
174
+ - `purvey inventory delete <id>`
164
175
 
165
- | Command | Description |
166
- | ------------------------------ | -------------------------------- |
167
- | `purvey inventory list` | List your green coffee inventory |
168
- | `purvey inventory get <id>` | Get a single inventory item |
169
- | `purvey inventory add` | Add a bean to your inventory |
170
- | `purvey inventory update <id>` | Update an inventory item |
171
- | `purvey inventory delete <id>` | Delete an inventory item |
176
+ `inventory list` options:
172
177
 
173
- **inventory add** required flags: `--catalog-id`, `--qty`
178
+ - `--stocked` -- only show currently stocked beans
179
+ - `--limit <n>` -- maximum results (default: 20)
180
+
181
+ `inventory add` flags:
182
+
183
+ - `--catalog-id <id>` -- [REQUIRED] coffee_catalog.catalog_id
184
+ - `--qty <lbs>` -- [REQUIRED] quantity in pounds
185
+ - `--cost <dollars>` -- bean cost in dollars
186
+ - `--tax-ship <dollars>` -- tax and shipping cost in dollars
187
+ - `--notes <text>` -- notes for this inventory item
188
+ - `--purchase-date <YYYY-MM-DD>` -- purchase date (defaults to today)
189
+ - `--form` -- interactive form mode
190
+
191
+ `inventory update <id>` flags:
192
+
193
+ - `--qty <lbs>` -- updated quantity in pounds
194
+ - `--cost <dollars>` -- updated bean cost
195
+ - `--tax-ship <dollars>` -- updated tax/shipping cost
196
+ - `--notes <text>` -- updated notes
197
+ - `--stocked <true|false>` -- mark as stocked or not
198
+
199
+ Examples:
174
200
 
175
201
  ```bash
202
+ purvey inventory list --stocked --pretty
176
203
  purvey inventory add --catalog-id 128 --qty 10 --cost 8.50
177
- purvey inventory add --form # interactive wizard
204
+ purvey inventory add --catalog-id 42 --qty 5 --cost 6.25 --tax-ship 4.00
205
+ purvey inventory update 7 --stocked false
206
+ purvey inventory delete 7 --yes
178
207
  ```
179
208
 
180
- ### Roast Profiles (member role required)
209
+ ### roast
210
+
211
+ - `purvey roast list`
212
+ - `purvey roast get <id>`
213
+ - `purvey roast create`
214
+ - `purvey roast update <id>`
215
+ - `purvey roast delete <id>`
216
+ - `purvey roast import [file]`
217
+ - `purvey roast watch [directory]`
218
+
219
+ `roast list` filters:
220
+
221
+ - `--coffee-id <id>` -- filter by inventory item ID (green_coffee_inv.id)
222
+ - `--roast-id <id>` -- filter by exact roast profile ID
223
+ - `--batch-name <text>` -- filter by batch name (partial match, case-insensitive)
224
+ - `--date-start <YYYY-MM-DD>` -- only show roasts on or after this date
225
+ - `--date-end <YYYY-MM-DD>` -- only show roasts on or before this date
226
+ - `--stocked` -- only show roasts for currently stocked beans
227
+ - `--catalog-id <id>` -- filter by coffee_catalog ID
228
+ - `--limit <n>` -- maximum results (default: 20)
229
+
230
+ `roast get <id>` options:
231
+
232
+ - `--include-temps` -- include temperature curve data
233
+ - `--include-events` -- include roast event markers
234
+
235
+ `roast create` flags:
181
236
 
182
- | Command | Description |
183
- | ---------------------------- | ------------------------------------- |
184
- | `purvey roast list` | List your roast profiles |
185
- | `purvey roast get <id>` | Get a single roast profile |
186
- | `purvey roast create` | Create a new roast profile |
187
- | `purvey roast update <id>` | Update a roast profile |
188
- | `purvey roast delete <id>` | Delete a roast profile |
189
- | `purvey roast import [file]` | Import an Artisan .alog roast file |
190
- | `purvey roast watch [dir]` | Watch a directory for new .alog files |
237
+ - `--coffee-id <id>` -- [REQUIRED] green_coffee_inv ID
238
+ - `--batch-name <name>` -- batch name (defaults to coffee name + today's date)
239
+ - `--oz-in <oz>` -- green weight in ounces
240
+ - `--oz-out <oz>` -- roasted weight in ounces
241
+ - `--roast-date <YYYY-MM-DD>` -- roast date (defaults to today)
242
+ - `--notes <text>` -- roast notes
243
+ - `--form` -- interactive form mode
191
244
 
192
- **roast import** required: `<file>`, `--coffee-id`
245
+ `roast update <id>` fields:
246
+
247
+ - `--notes <text>` -- updated roast notes
248
+ - `--oz-out <oz>` -- updated roasted weight (triggers weight loss recalculation)
249
+ - `--batch-name <name>` -- updated batch name
250
+ - `--targets <text>` -- updated roast targets
251
+
252
+ `roast import [file]` flags:
253
+
254
+ - `--coffee-id <id>` -- [REQUIRED] green_coffee_inv ID
255
+ - `--batch-name <name>` -- batch name (auto-generated if omitted)
256
+ - `--oz-in <oz>` -- green weight (extracted from .alog if present, overridden here)
257
+ - `--roast-notes <text>` -- additional roast notes
258
+ - `--form` -- interactive form mode
259
+
260
+ `roast watch [directory]` options:
261
+
262
+ - `--coffee-id <id>` -- [REQUIRED unless --auto-match] inventory ID for all imports
263
+ - `--batch-prefix <name>` -- batch name prefix for auto-named batches
264
+ - `--prompt-each` -- prompt for bean selection on each new file
265
+ - `--auto-match` -- auto-match beans per file (mutually exclusive with --coffee-id)
266
+ - `--resume` -- resume a previous watch session
267
+ - `--form` -- interactive setup wizard
268
+
269
+ Examples:
193
270
 
194
271
  ```bash
272
+ purvey roast list --catalog-id 128 --pretty
273
+ purvey roast list --batch-name "Ethiopia Guji" --pretty
274
+ purvey roast list --date-start 2026-03-01 --date-end 2026-03-31
275
+ purvey roast create --coffee-id 7 --batch-name "Ethiopia Guji Light" --oz-in 16
276
+ purvey roast update 123 --targets "Aim for FC at 390F, 18% dev"
195
277
  purvey roast import ~/artisan/ethiopia.alog --coffee-id 7
196
- purvey roast import --form # interactive wizard
278
+ purvey roast watch ~/artisan/ --auto-match
197
279
  ```
198
280
 
199
- **roast watch** — required: `<directory>`, `--coffee-id` (or `--auto-match`)
281
+ ### sales
200
282
 
201
- ```bash
202
- purvey roast watch ~/artisan/ --coffee-id 7
203
- purvey roast watch ~/artisan/ --auto-match # AI matches beans per file
204
- purvey roast watch --resume # continue previous session
205
- ```
283
+ - `purvey sales list`
284
+ - `purvey sales record`
285
+ - `purvey sales update <id>`
286
+ - `purvey sales delete <id>`
287
+
288
+ `sales record` flags:
206
289
 
207
- ### Sales (member role required)
290
+ - `--roast-id <id>` -- [REQUIRED] roast_data.roast_id
291
+ - `--oz <amount>` -- [REQUIRED] ounces sold
292
+ - `--price <dollars>` -- [REQUIRED] total sale price in dollars
293
+ - `--buyer <name>` -- buyer name or identifier
294
+ - `--sell-date <YYYY-MM-DD>` -- sale date (defaults to today)
295
+ - `--form` -- interactive form mode
208
296
 
209
- | Command | Description |
210
- | -------------------------- | ----------------------- |
211
- | `purvey sales list` | List your sales records |
212
- | `purvey sales record` | Record a new sale |
213
- | `purvey sales update <id>` | Update a sale record |
214
- | `purvey sales delete <id>` | Delete a sale record |
297
+ `sales update <id>` flags:
215
298
 
216
- **sales record** required flags: `--roast-id`, `--oz`, `--price`
299
+ - `--oz <amount>` -- updated ounces sold
300
+ - `--price <dollars>` -- updated sale price
301
+ - `--buyer <name>` -- updated buyer name
302
+ - `--sell-date <YYYY-MM-DD>` -- updated sale date
303
+
304
+ Examples:
217
305
 
218
306
  ```bash
219
- purvey sales record --roast-id 123 --oz 12 --price 22.00
220
- purvey sales record --form # interactive wizard
307
+ purvey sales record --roast-id 123 --oz 12 --price 22.00 --buyer "Jane Smith"
308
+ purvey sales list --pretty
309
+ purvey sales update 5 --price 24.00
310
+ purvey sales delete 5 --yes
221
311
  ```
222
312
 
223
- ### Tasting Notes (member role required)
313
+ ### tasting
224
314
 
225
- | Command | Description |
226
- | ------------------------------------ | -------------------------------------- |
227
- | `purvey tasting get <catalog-id>` | Get tasting notes for a catalog coffee |
228
- | `purvey tasting rate [inventory-id]` | Rate a coffee with cupping scores |
315
+ - `purvey tasting get <bean-id>`
316
+ - `purvey tasting rate [bean-id]`
229
317
 
230
- **tasting rate** — required (flag mode): `<inventory-id>` + all five score flags
318
+ `purvey tasting get <bean-id>` options:
319
+
320
+ - `--filter <user|supplier|both>` -- which notes to show (default: both)
321
+
322
+ `purvey tasting rate [bean-id]` options:
323
+
324
+ - `--aroma <1-5>` -- [REQUIRED in flag mode]
325
+ - `--body <1-5>` -- [REQUIRED in flag mode]
326
+ - `--acidity <1-5>` -- [REQUIRED in flag mode]
327
+ - `--sweetness <1-5>` -- [REQUIRED in flag mode]
328
+ - `--aftertaste <1-5>` -- [REQUIRED in flag mode]
329
+ - `--brew-method <method>` -- brew method used (e.g. pour_over, espresso)
330
+ - `--notes <text>` -- additional tasting notes
331
+ - `--form` -- interactive form mode
332
+
333
+ Examples:
231
334
 
232
335
  ```bash
336
+ purvey tasting get 128 --filter both --pretty
233
337
  purvey tasting rate 7 --aroma 4 --body 3 --acidity 5 --sweetness 4 --aftertaste 4
234
- purvey tasting rate --form # interactive wizard
338
+ purvey tasting rate 42 --aroma 3 --body 3 --acidity 3 --sweetness 3 --aftertaste 3 --notes "Underextracted"
235
339
  ```
236
340
 
237
- ### Configuration
341
+ ### config
238
342
 
239
- | Command | Description |
240
- | --------------------------------- | ---------------------------- |
241
- | `purvey config list` | Show all config values |
242
- | `purvey config get <key>` | Get a single config value |
243
- | `purvey config set <key> <value>` | Set a config value |
244
- | `purvey config reset` | Reset all config to defaults |
343
+ - `purvey config list`
344
+ - `purvey config get <key>`
345
+ - `purvey config set <key> <value>`
346
+ - `purvey config reset`
245
347
 
246
- **Supported config keys:**
348
+ Current config key:
247
349
 
248
- | Key | Values | Description |
249
- | ----------- | ---------------- | ------------------------------------------------------------------------------------ |
250
- | `form-mode` | `true` / `false` | When true, write commands auto-enter interactive wizard if required args are missing |
350
+ - `form-mode`: when set to `true`, write commands enter interactive mode when required args are missing
351
+
352
+ Examples:
251
353
 
252
354
  ```bash
253
355
  purvey config set form-mode true
254
356
  purvey config get form-mode
255
- purvey config list
256
357
  ```
257
358
 
258
- ---
359
+ ### context
360
+
361
+ - `purvey context`
362
+
363
+ Use this when an agent needs a compact, source-aware CLI reference.
259
364
 
260
365
  ## Common Workflows
261
366
 
262
- ### Buy green coffee, roast it, record a sale
367
+ ### Buy coffee, roast it, rate it, and record a sale
263
368
 
264
369
  ```bash
265
- # Find a coffee
266
370
  purvey catalog search --origin "Ethiopia" --process "natural" --stocked --pretty
267
-
268
- # Add to inventory (catalog-id from search results)
269
371
  purvey inventory add --catalog-id 128 --qty 10 --cost 8.50
270
-
271
- # Get your inventory id
272
372
  purvey inventory list --stocked --pretty
273
-
274
- # Import a roast from Artisan (inventory id = 7)
275
373
  purvey roast import ~/artisan/guji-light.alog --coffee-id 7 --pretty
276
-
277
- # Rate the coffee after brewing
278
374
  purvey tasting rate 7 --aroma 5 --body 3 --acidity 5 --sweetness 4 --aftertaste 4
279
-
280
- # Record a sale (roast_id from import output)
281
375
  purvey sales record --roast-id 123 --oz 12 --price 22.00 --buyer "Jane Smith"
282
376
  ```
283
377
 
284
- ### Continuous watch mode for Artisan
378
+ ### Continuous Artisan watch mode
285
379
 
286
380
  ```bash
287
- # Watch a directory — auto-imports every new .alog file
288
- purvey roast watch ~/Library/Application\ Support/Artisan-Scope/artisan/ --coffee-id 7
289
-
290
- # Resume a watch session after restart
381
+ purvey roast watch ~/artisan/ --coffee-id 7
382
+ purvey roast watch ~/artisan/ --auto-match
291
383
  purvey roast watch --resume
292
384
  ```
293
385
 
294
- ### Export data for spreadsheets
386
+ ### Export records for spreadsheets
295
387
 
296
388
  ```bash
297
389
  purvey inventory list --csv > inventory.csv
@@ -299,66 +391,45 @@ purvey roast list --csv > roasts.csv
299
391
  purvey sales list --csv > sales.csv
300
392
  ```
301
393
 
302
- ---
303
-
304
- ## Environment Variables
394
+ ## ID Reference
305
395
 
306
- | Variable | Description |
307
- | ----------------------------- | ----------------------------------------------- |
308
- | `PURVEYORS_SUPABASE_URL` | Override the Supabase project URL (dev/staging) |
309
- | `PURVEYORS_SUPABASE_ANON_KEY` | Override the Supabase anon key |
310
- | `PURVEY_DEBUG` | Set to any value to enable verbose error output |
396
+ Use the right ID for the right command.
311
397
 
312
- ---
398
+ - `catalog_id`: coffee_catalog rows; used by `catalog get`, `inventory add --catalog-id`, `tasting get`, `roast list --catalog-id`
399
+ - `inventory id`: green_coffee_inv rows; used by `inventory get/update/delete`, `roast --coffee-id`, `tasting rate`, `roast list --coffee-id`
400
+ - `roast_id`: roast_data rows; used by `roast get/delete`, `sales --roast-id`, `roast list --roast-id`
401
+ - `sale id`: coffee_sales rows; used by `sales update/delete`
313
402
 
314
- ## For AI Agents
403
+ ## Environment Variables
315
404
 
316
- `purvey` is built with AI agents in mind. Every command has structured JSON output, clear error messages, and an `--headless` auth flow.
405
+ - `PURVEYORS_SUPABASE_URL`: override the Supabase project URL
406
+ - `PURVEYORS_SUPABASE_ANON_KEY`: override the Supabase anon key
407
+ - `PURVEYORS_BASE_URL`: override the Purveyors web base URL
408
+ - `PURVEY_DEBUG`: enable verbose error output
317
409
 
318
- ### Agent Onboarding
410
+ ## For AI Agents
319
411
 
320
- Run this once to get complete CLI knowledge:
412
+ Start here:
321
413
 
322
414
  ```bash
323
415
  purvey context
324
416
  ```
325
417
 
326
- This outputs a comprehensive, token-efficient reference covering all commands, required vs optional flags, data model relationships, common workflows, and error recovery. Designed for agents to read once and use every command correctly.
327
-
328
- ### Agent Auth Flow
418
+ Recommended flow:
329
419
 
330
420
  ```bash
331
421
  purvey auth login --headless
332
- # prints OAuth URL
333
- # user opens URL, signs in, pastes callback URL back
334
- # Token auto-refreshes; no further auth action needed.
335
- ```
336
-
337
- ### Agent Usage Pattern
338
-
339
- ```bash
340
- # Check auth before any write operations
341
- purvey auth status
342
-
343
- # Always use JSON output (default) for scripting
344
- purvey catalog search --origin "Ethiopia" | jq '.[0].catalog_id'
345
- purvey inventory list | jq '.[] | select(.stocked == true) | .id'
346
-
347
- # Use --yes to skip confirmation prompts in automated flows
348
- purvey inventory delete 7 --yes
349
- purvey sales delete 5 --yes
422
+ purvey auth status 2>/dev/null | jq .
423
+ purvey inventory list | jq '.[].id'
350
424
  ```
351
425
 
352
- ### ID Types (avoid confusion)
426
+ The CLI is designed to be agent-friendly:
353
427
 
354
- | ID | Table | Used with |
355
- | -------------- | ------------------ | ------------------------------------------------------------------ |
356
- | `catalog_id` | `coffee_catalog` | `catalog get`, `inventory add --catalog-id`, `tasting get` |
357
- | `inventory_id` | `green_coffee_inv` | `inventory get/update/delete`, `roast --coffee-id`, `tasting rate` |
358
- | `roast_id` | `roast_data` | `roast get/delete`, `sales --roast-id` |
359
- | `sale_id` | `coffee_sales` | `sales update/delete` |
360
-
361
- ---
428
+ - stable command names
429
+ - structured output on stdout
430
+ - headless auth flow
431
+ - copy-pasteable examples
432
+ - a dedicated `context` command for onboarding
362
433
 
363
434
  ## Development
364
435
 
@@ -366,71 +437,22 @@ purvey sales delete 5 --yes
366
437
  git clone https://github.com/reedwhetstone/purveyors-cli
367
438
  cd purveyors-cli
368
439
  pnpm install
440
+ npm run build
441
+ npm run check
442
+ npm run lint
443
+ npm test
369
444
  ```
370
445
 
371
- Create a `.env` file:
372
-
373
- ```
374
- PURVEYORS_SUPABASE_URL=https://your-project.supabase.co
375
- PURVEYORS_SUPABASE_ANON_KEY=your-anon-key
376
- ```
377
-
378
- Run locally:
379
-
380
- ```bash
381
- pnpm dev -- auth status
382
- pnpm dev -- catalog search --origin Ethiopia --pretty
383
- pnpm dev -- --help
384
- ```
385
-
386
- Build:
387
-
388
- ```bash
389
- pnpm build
390
- ```
391
-
392
- Lint + type check + test:
393
-
394
- ```bash
395
- pnpm lint
396
- pnpm check
397
- pnpm test
398
- ```
399
-
400
- ### Architecture
401
-
402
- ```
403
- src/
404
- index.ts Entry point — registers all subcommands
405
- commands/ One file per command group
406
- auth.ts OAuth login/status/logout
407
- catalog.ts Public coffee catalog search
408
- config.ts CLI configuration
409
- context.ts Agent onboarding reference
410
- inventory.ts Green coffee inventory management
411
- roast.ts Roast profiles + Artisan .alog import
412
- sales.ts Sales recording
413
- tasting.ts Cupping notes and scoring
414
- lib/ Business logic (no Commander dependencies)
415
- supabase.ts Auth client + session management
416
- catalog.ts Catalog query functions
417
- inventory.ts Inventory CRUD
418
- roast.ts Roast profile CRUD + import pipeline
419
- sales.ts Sales CRUD
420
- tasting.ts Tasting notes + cupping score logic
421
- artisan/ Artisan .alog parser
422
- interactive/ Interactive form prompts + watch mode
423
- output.ts JSON/CSV output formatting
424
- errors.ts Error handling + withErrorHandling wrapper
425
- config.ts Local config read/write
426
- ```
427
-
428
- See [AGENTS.md](./AGENTS.md) for the full contributor guide including code conventions and PR requirements.
446
+ Key files:
429
447
 
430
- ---
448
+ - `src/index.ts`: top-level CLI registration and global options
449
+ - `src/commands/`: command definitions and help text
450
+ - `src/lib/`: business logic and Supabase integration
451
+ - `src/commands/context.ts`: dense agent reference
452
+ - `AGENTS.md`: contributor guide
431
453
 
432
454
  ## License
433
455
 
434
456
  Sustainable Use License. See [LICENSE.md](./LICENSE.md).
435
457
 
436
- Copyright © 2026 Reed Whetstone / purveyors.io
458
+ Copyright 2026 Reed Whetstone / purveyors.io