@lahat-group/cli 1.1.8 → 2.0.1
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/dist/index.js +66 -12168
- package/package.json +1 -2
- package/skill/SKILL.md +57 -17
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lahat-group/cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "CLI + Claude Skill to build, validate, price, and save wardrobe designs.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -30,7 +30,6 @@
|
|
|
30
30
|
"test": "vitest run"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@wardrobe/shared": "*",
|
|
34
33
|
"commander": "^12.0.0",
|
|
35
34
|
"ky": "^1.14.3",
|
|
36
35
|
"tsup": "^8.0.0",
|
package/skill/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: wardrobe-configurator
|
|
3
|
-
description: Use when the user wants to build, configure, validate, price, or order a wardrobe/closet design from the terminal — phrases like "configure a wardrobe", "price a design", "build a closet layout", "validate my wardrobe config" — OR wants to look up existing wardrobe data: projects, customers, designers, orders and their PDFs, e.g. "which projects does this designer have", "find the customer with phone 05x", "who is on this project", "what is the status of this order", "download the order PDF". Drives the `wardrobe` CLI (HTTP client over the configurator API); a WardrobeConfig JSON file on disk is the unit of work for design verbs, and every lookup verb is read-only.
|
|
3
|
+
description: Use when the user wants to build, configure, validate, price, or order a wardrobe/closet design from the terminal — phrases like "configure a wardrobe", "price a design", "build a closet layout", "validate my wardrobe config" — OR wants to look up existing wardrobe data: projects, customers, designers, orders, quotations and their PDFs, or (staff only) registered users across the whole system, e.g. "which projects does this designer have", "find the customer with phone 05x", "who is on this project", "what is the status of this order", "download the order PDF", "who signed up recently", "which account owns this phone number", "what's the latest quote we generated". Drives the `wardrobe` CLI (HTTP client over the configurator API); a WardrobeConfig JSON file on disk is the unit of work for design verbs, and every lookup verb is read-only.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Wardrobe Configurator CLI
|
|
@@ -12,8 +12,13 @@ agent loop is: **init → edit → validate → price → plan → apply**.
|
|
|
12
12
|
## Prerequisites
|
|
13
13
|
|
|
14
14
|
- Install the CLI: `npm install -g @lahat-group/cli` (or run ad-hoc via `npx @lahat-group/cli <verb>`).
|
|
15
|
-
It ships as a self-contained binary — no build step, no extra dependencies.
|
|
16
|
-
|
|
15
|
+
It ships as a self-contained binary — no build step, no extra dependencies. It holds
|
|
16
|
+
no domain logic of its own; the rules live in the API.
|
|
17
|
+
- **Authenticate first — every verb needs it.** The CLI is a thin HTTP client: `init`,
|
|
18
|
+
`validate` and `describe` are served by the API just as `price` and `apply` are, so
|
|
19
|
+
none of them work offline. `Not authenticated. Run \`wardrobe login\` first.` means
|
|
20
|
+
exactly that.
|
|
21
|
+
- `wardrobe login` runs the OAuth device flow — it prints a
|
|
17
22
|
user code, opens `/activate` in the browser, and stores a scoped agent key at
|
|
18
23
|
`~/.config/wardrobe/config.json` (chmod 600). Confirm with `wardrobe whoami`.
|
|
19
24
|
- The CLI targets the **production** API by default. Set `WARDROBE_API_URL` to override
|
|
@@ -26,7 +31,8 @@ agent loop is: **init → edit → validate → price → plan → apply**.
|
|
|
26
31
|
emits a fresh, valid `WardrobeConfig` (full-width, split into optimal columns).
|
|
27
32
|
2. **edit** — modify `wardrobe.json` directly (see shape below).
|
|
28
33
|
3. **validate** — `wardrobe validate wardrobe.json` (or `-` for stdin). Runs the
|
|
29
|
-
**
|
|
34
|
+
**live** constraint pipeline server-side — the same rules `wardrobe price` enforces,
|
|
35
|
+
so a config `validate` approves can never be one `price` rejects.
|
|
30
36
|
Exit 0 = valid; exit 1 + structured errors otherwise. Do this after every edit.
|
|
31
37
|
4. **price** — `wardrobe price wardrobe.json` → authoritative total in **NIS** from
|
|
32
38
|
the API's unified area×rate engine.
|
|
@@ -65,7 +71,7 @@ or a saved design id.
|
|
|
65
71
|
## Reading what exists
|
|
66
72
|
|
|
67
73
|
Every read the key can reach has a verb. **All of them are GETs** — the CLI can read
|
|
68
|
-
customers and
|
|
74
|
+
customers, orders and quotations but never create or change them (`customers:write`,
|
|
69
75
|
`orders:write` and `quotations:write` are not on the CLI's key, so those routes
|
|
70
76
|
answer `403 insufficient_scope` whoever signed in).
|
|
71
77
|
|
|
@@ -80,32 +86,67 @@ answer `403 insufficient_scope` whoever signed in).
|
|
|
80
86
|
| `wardrobe customers get <id>` | One customer |
|
|
81
87
|
| `wardrobe customers projects <id>` | That customer's projects |
|
|
82
88
|
| `wardrobe designs list --project <id>` | Designs saved in a project |
|
|
89
|
+
| `wardrobe designs list` | The newest designs across every project you can see (all yours, or the whole tenant with `staff:read`) |
|
|
90
|
+
| `wardrobe designs list --limit <n>` `--since <ISO>` | Same, paged — `--limit` caps rows (default 20, max 100), `--since` filters by `updatedAt >=` |
|
|
83
91
|
| `wardrobe designs thumbnail <id> --out f.jpg` | The design's rendered thumbnail |
|
|
84
92
|
| `wardrobe orders list --project <id>` | Every order the project has had |
|
|
85
93
|
| `wardrobe orders list --project <id> --open` | Only its active (non-cancelled) order |
|
|
94
|
+
| `wardrobe orders list` | The newest-**updated** orders across every project you can see — "what moved", not "what's new": a status change or a revision surfaces an old order here too |
|
|
95
|
+
| `wardrobe orders list --limit <n>` `--since <ISO>` | Same, paged (`--since` filters by `updatedAt >=`) |
|
|
86
96
|
| `wardrobe orders pdf <id> --out f.pdf` | The order PDF |
|
|
97
|
+
| `wardrobe quotations list --project <id>` | That project's quote number + full revision history |
|
|
98
|
+
| `wardrobe quotations list` | Every quotation you can see, **newest-generated first** — this is "latest quotes generation" |
|
|
99
|
+
| `wardrobe quotations list --limit <n>` `--since <ISO>` | Same, paged (`--since` filters by `updatedAt >=`, i.e. last generated at/after) |
|
|
100
|
+
| `wardrobe users list` | Registered accounts, **newest-registered first** — staff only, see below |
|
|
101
|
+
| `wardrobe users list --limit <n>` `--since <ISO>` | Same, paged (`--since` filters by `createdAt >=`) — `--limit 5` with no `--since` is "the latest registered users"; omit both, paging with `--since` off the last row's timestamp, for "every user in the system" |
|
|
102
|
+
| `wardrobe users by-phone <number>` | The account(s) tied to that phone number: the linked client account plus every designer who owns a project for a customer with it — staff only |
|
|
87
103
|
| `wardrobe help-texts` | The help-text table |
|
|
88
104
|
|
|
89
105
|
`projects list` already returns each project's **customer and owning designer inline** —
|
|
90
106
|
so "who is the customer on each of this designer's projects" is one call plus a filter,
|
|
91
107
|
never one call per project. Prefer `--phone` / `--designer` over fetching and grepping.
|
|
92
108
|
|
|
109
|
+
Every cross-project/cross-tenant list (`designs`, `orders`, `quotations`, `users`) takes
|
|
110
|
+
`--limit` (1–100, default 20) and a `--since` cursor — pass the last row's timestamp
|
|
111
|
+
back as `--since` to page further instead of guessing an offset. A malformed `--since` or
|
|
112
|
+
an out-of-range `--limit` is a `400`, not a silently-ignored filter — read the error
|
|
113
|
+
rather than retrying blind.
|
|
114
|
+
|
|
93
115
|
### What you can see is not what exists
|
|
94
116
|
|
|
95
117
|
The list is bounded by the key, so an empty result is as often a **visibility** answer as
|
|
96
118
|
a data one. `wardrobe whoami --json` reports the truth under `agent.scopes` and `role`:
|
|
97
119
|
|
|
98
|
-
- An ordinary designer or client sees **their own** projects
|
|
99
|
-
to. A project belonging to someone else
|
|
120
|
+
- An ordinary designer or client sees **their own** projects, designs, orders and
|
|
121
|
+
quotations, plus ones they were invited to. A project belonging to someone else
|
|
122
|
+
answers `403 Forbidden`, not `404`. `wardrobe users list` and `users by-phone` answer
|
|
123
|
+
`403 Forbidden` outright — there is no per-row visibility to fall back to; the whole
|
|
124
|
+
surface is staff-only (see below).
|
|
100
125
|
- A key approved by an **admin or support** user *and* carrying **`staff:read`** sees
|
|
101
|
-
**every** project, customer and
|
|
126
|
+
**every** project, customer, order and quotation in the system — and can use
|
|
127
|
+
`wardrobe users list` / `users by-phone` at all. That scope is granted only to
|
|
102
128
|
staff, only for GETs, and is listed by name on the consent screen. The same approver
|
|
103
129
|
also receives **`staff:write`**, which lets `designs create` / `designs update` land in
|
|
104
|
-
a project the admin does not own. A key logged in before 2026-09-05 lacks
|
|
105
|
-
|
|
130
|
+
a project the admin does not own. A key logged in before 2026-09-05 lacks `staff:read`
|
|
131
|
+
and before 2026-09-12 lacks `quotations:read` — a `403 insufficient_scope` on
|
|
132
|
+
`quotations list`, or a `403 Forbidden` on a write to someone else's project, means
|
|
133
|
+
`wardrobe login` again.
|
|
106
134
|
|
|
107
135
|
Never tell a user something does not exist when you only know your key cannot see it.
|
|
108
|
-
Say which it is: `403 Forbidden` means the row is someone else's, `
|
|
136
|
+
Say which it is: `403 Forbidden` means the row is someone else's (or, for `users`, that
|
|
137
|
+
your key isn't staff at all), `404` means it is gone.
|
|
138
|
+
|
|
139
|
+
### `wardrobe users` is a directory lookup, not a customer lookup
|
|
140
|
+
|
|
141
|
+
`users list` / `users by-phone` read the `User` **account** table — designers, admins,
|
|
142
|
+
support and self-serve clients who can sign in — not the per-project `Customer` contact
|
|
143
|
+
card `wardrobe customers` reads. A phone number usually resolves to a **designer**
|
|
144
|
+
(whoever owns the project for the customer with that number), occasionally to a
|
|
145
|
+
**client** account too (if that customer accepted a project invitation and has their own
|
|
146
|
+
login). It is normal for `users by-phone` to return more than one account, or to return
|
|
147
|
+
zero when the number belongs to a customer nobody has invited to sign in — that is not
|
|
148
|
+
an error, and it does not mean the phone number is unknown; check `wardrobe projects list
|
|
149
|
+
--phone <number>` for the project/customer side of the same question.
|
|
109
150
|
|
|
110
151
|
### Not available here
|
|
111
152
|
|
|
@@ -113,8 +154,6 @@ Don't reach for these; they are not CLI verbs and not agent-reachable:
|
|
|
113
154
|
|
|
114
155
|
- **Anything under `/admin`**, plus commissions and invitations — barred to every agent
|
|
115
156
|
key at the mount (`403 agent_not_permitted`). No scope unlocks them.
|
|
116
|
-
- **Quotation history.** `POST /quotations/pdf` is open to other clients, but reading a
|
|
117
|
-
project's past quotes is JWT-only — a human in the web app.
|
|
118
157
|
- **Manufacturing-files export.** Staff-only, through the web app.
|
|
119
158
|
|
|
120
159
|
## WardrobeConfig shape (top-level)
|
|
@@ -141,10 +180,11 @@ Prefer generating the skeleton with `wardrobe init` rather than hand-writing it
|
|
|
141
180
|
|
|
142
181
|
- **The CLI can read orders but never place one.** Its key carries `profile:read`,
|
|
143
182
|
`projects:read`, `customers:read`, `designs:read`, `designs:write`, `orders:read`,
|
|
144
|
-
`price:read` (+ `staff:read` and `staff:write` for staff) —
|
|
145
|
-
and so is every admin scope. `wardrobe
|
|
146
|
-
|
|
147
|
-
Don't attempt it, and
|
|
183
|
+
`price:read`, `quotations:read` (+ `staff:read` and `staff:write` for staff) —
|
|
184
|
+
**every write beyond designs is absent**, and so is every admin scope. `wardrobe
|
|
185
|
+
orders list`, `orders pdf` and `quotations list` work; creating or changing an order,
|
|
186
|
+
a customer or a quotation answers `403 insufficient_scope`. Don't attempt it, and
|
|
187
|
+
don't attempt admin/catalog operations.
|
|
148
188
|
- To turn a saved design into an order, direct the **human** to the web app: they
|
|
149
189
|
open the project, review the design, and complete the **verify-details** flow —
|
|
150
190
|
which computes the final price, freezes the PDF, and advances the order. Only a
|