@lexq/cli 0.1.19 → 0.1.20
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 +123 -105
- package/dist/index.js +26 -8
- package/dist/mcp/register.js +16 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,13 +1,34 @@
|
|
|
1
1
|
# LexQ CLI
|
|
2
2
|
|
|
3
|
-
>
|
|
4
|
-
>
|
|
3
|
+
> **The decision platform for engineering teams.**
|
|
4
|
+
> CLI and MCP server for [LexQ](https://lexq.io) — move business rules out of
|
|
5
|
+
> your deploy pipeline, prove every change with simulation, and ship without
|
|
6
|
+
> a git push.
|
|
5
7
|
|
|
6
8
|
**[Website](https://lexq.io)** · **[Docs](https://docs.lexq.io)** · **[Console](https://console.lexq.io)**
|
|
7
9
|
|
|
8
10
|
[](https://www.npmjs.com/package/@lexq/cli)
|
|
9
11
|
[](LICENSE)
|
|
10
12
|
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Why LexQ?
|
|
16
|
+
|
|
17
|
+
Your business rules — pricing, promotions, fee logic, eligibility checks —
|
|
18
|
+
change often. But every change ships through the same PR → review → staging
|
|
19
|
+
→ deploy cycle as your core application code. A one-line discount rule
|
|
20
|
+
takes two weeks.
|
|
21
|
+
|
|
22
|
+
This is an architectural problem, not a process problem. Business logic
|
|
23
|
+
that changes weekly shouldn't live in code that ships quarterly.
|
|
24
|
+
|
|
25
|
+
**LexQ separates the two.** Rules live outside your application. You change
|
|
26
|
+
them in a visual console or through this CLI. You prove every change with
|
|
27
|
+
batch simulation against real execution data. You deploy without touching
|
|
28
|
+
your codebase.
|
|
29
|
+
|
|
30
|
+
Every decision leaves a full audit trace.
|
|
31
|
+
|
|
11
32
|
## Install
|
|
12
33
|
|
|
13
34
|
```bash
|
|
@@ -55,7 +76,7 @@ lexq rules create --group-id <GROUP_ID> --version-id <VERSION_ID> --json '{
|
|
|
55
76
|
}]
|
|
56
77
|
}'
|
|
57
78
|
|
|
58
|
-
# 6. Test
|
|
79
|
+
# 6. Test against your data before shipping
|
|
59
80
|
lexq analytics dry-run --version-id <VERSION_ID> --debug --mock \
|
|
60
81
|
--json '{"facts":{"customer_tier":"VIP","payment_amount":100000}}'
|
|
61
82
|
|
|
@@ -64,106 +85,16 @@ lexq deploy publish --group-id <GROUP_ID> --version-id <VERSION_ID> --memo "v1"
|
|
|
64
85
|
lexq deploy live --group-id <GROUP_ID> --version-id <VERSION_ID> --memo "Initial deploy"
|
|
65
86
|
```
|
|
66
87
|
|
|
67
|
-
##
|
|
68
|
-
|
|
69
|
-
```
|
|
70
|
-
lexq auth login | logout | whoami
|
|
71
|
-
lexq status API health check
|
|
72
|
-
lexq serve Run as MCP stdio server (--mcp)
|
|
73
|
-
lexq groups list | get | create | update | delete
|
|
74
|
-
lexq groups ab-test start | stop | adjust
|
|
75
|
-
lexq versions list | get | create | update | delete | clone
|
|
76
|
-
lexq rules list | get | create | update | delete | reorder | toggle
|
|
77
|
-
lexq facts list | create | update | delete | action-metadata
|
|
78
|
-
lexq deploy publish | live | rollback | undeploy | history | detail | overview | deployable | diff
|
|
79
|
-
lexq analytics dry-run | dry-run-compare | requirements
|
|
80
|
-
lexq analytics simulation start | status | list | cancel | export
|
|
81
|
-
lexq analytics dataset upload | template
|
|
82
|
-
lexq history list | get | stats
|
|
83
|
-
lexq integrations list | get | save | delete | config-spec
|
|
84
|
-
lexq logs list | get | action | bulk-action
|
|
85
|
-
lexq webhook-subscriptions list | get | save | delete | test
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
## Global Options
|
|
89
|
-
|
|
90
|
-
| Flag | Description |
|
|
91
|
-
|--------------------------|--------------------------------------------|
|
|
92
|
-
| `--format <json\|table>` | Output format (default: `json`) |
|
|
93
|
-
| `--api-key <key>` | Override stored API key |
|
|
94
|
-
| `--base-url <url>` | Override API base URL |
|
|
95
|
-
| `--dry-run` | Preview the HTTP request without executing |
|
|
96
|
-
| `--verbose` | Show request/response details |
|
|
97
|
-
| `--no-color` | Disable colored output |
|
|
98
|
-
|
|
99
|
-
## AI Agent Skills
|
|
100
|
-
|
|
101
|
-
LexQ CLI ships with **AI Agent Skills** — structured documentation that AI coding agents can read to autonomously manage
|
|
102
|
-
policies.
|
|
103
|
-
|
|
104
|
-
```
|
|
105
|
-
skills/
|
|
106
|
-
├── lexq-shared/SKILL.md Core concepts, auth, workflow
|
|
107
|
-
├── lexq-groups/SKILL.md Policy groups, conflict resolution, A/B testing
|
|
108
|
-
├── lexq-rules/SKILL.md Condition syntax, action types, mutex
|
|
109
|
-
├── lexq-simulation/SKILL.md Dry run, batch simulation, compare
|
|
110
|
-
├── lexq-execution/SKILL.md Execution history, stats, failure logs,
|
|
111
|
-
│ integrations, webhook subscriptions
|
|
112
|
-
└── lexq-recipes/SKILL.md End-to-end recipes
|
|
113
|
-
|
|
114
|
-
.claude/CLAUDE.md Claude Code project context
|
|
115
|
-
AGENTS.md Universal agent guide (Cursor, Windsurf, Gemini CLI, Cline)
|
|
116
|
-
CONTEXT.md Platform architecture & glossary
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
### For AI Agent Developers
|
|
120
|
-
|
|
121
|
-
Skills are included in the npm package. After installing `@lexq/cli`, agents can read skills from:
|
|
122
|
-
|
|
123
|
-
```
|
|
124
|
-
node_modules/@lexq/cli/skills/
|
|
125
|
-
node_modules/@lexq/cli/AGENTS.md
|
|
126
|
-
node_modules/@lexq/cli/CONTEXT.md
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
Or reference them directly in your project by copying the `skills/` directory.
|
|
130
|
-
|
|
131
|
-
## Configuration
|
|
132
|
-
|
|
133
|
-
Config is stored at `~/.lexq/config.json`:
|
|
134
|
-
|
|
135
|
-
```json
|
|
136
|
-
{
|
|
137
|
-
"apiKey": "sk_live_xxxxxxxxxxxxx",
|
|
138
|
-
"baseUrl": "https://api.lexq.io/api/v1/partners",
|
|
139
|
-
"format": "json"
|
|
140
|
-
}
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
## Development
|
|
88
|
+
## For AI Agents — 63 MCP Tools
|
|
144
89
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
pnpm build
|
|
150
|
-
pnpm start -- groups list
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
```bash
|
|
154
|
-
pnpm typecheck # Type check
|
|
155
|
-
pnpm lint # ESLint
|
|
156
|
-
bash tests/e2e.sh # CLI E2E tests (requires API key)
|
|
157
|
-
bash tests/test-engine-api.sh # Engine API integration tests
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
## MCP Server Mode
|
|
161
|
-
|
|
162
|
-
LexQ exposes **63 policy engine tools** via MCP. Two connection methods:
|
|
90
|
+
LexQ is designed to be AI-native. The entire policy engine API — all 63 tools
|
|
91
|
+
— is exposed via Model Context Protocol. Claude, Cursor, and other MCP-compatible
|
|
92
|
+
agents can create, simulate, and deploy rules autonomously, with human approval
|
|
93
|
+
before production.
|
|
163
94
|
|
|
164
95
|
### Claude.ai (Cloud — no install)
|
|
165
96
|
|
|
166
|
-
1.
|
|
97
|
+
1. **Settings → Connectors → Add Custom Integration**
|
|
167
98
|
2. Enter: `https://mcp.lexq.io`
|
|
168
99
|
3. Sign in with your LexQ account and select an API key
|
|
169
100
|
4. Done — 63 tools available in every conversation
|
|
@@ -182,7 +113,7 @@ For any MCP client that supports remote servers:
|
|
|
182
113
|
}
|
|
183
114
|
```
|
|
184
115
|
|
|
185
|
-
OAuth 2.1 authentication is
|
|
116
|
+
OAuth 2.1 authentication is handled automatically by your client.
|
|
186
117
|
|
|
187
118
|
### Local (stdio)
|
|
188
119
|
|
|
@@ -192,9 +123,7 @@ Run LexQ CLI as a local MCP server:
|
|
|
192
123
|
lexq serve --mcp
|
|
193
124
|
```
|
|
194
125
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
### Claude Desktop
|
|
126
|
+
#### Claude Desktop
|
|
198
127
|
|
|
199
128
|
Add to `claude_desktop_config.json`:
|
|
200
129
|
|
|
@@ -214,7 +143,7 @@ Add to `claude_desktop_config.json`:
|
|
|
214
143
|
}
|
|
215
144
|
```
|
|
216
145
|
|
|
217
|
-
|
|
146
|
+
#### VS Code / Cursor
|
|
218
147
|
|
|
219
148
|
`.vscode/mcp.json`:
|
|
220
149
|
|
|
@@ -234,7 +163,96 @@ Add to `claude_desktop_config.json`:
|
|
|
234
163
|
}
|
|
235
164
|
```
|
|
236
165
|
|
|
237
|
-
> **Prerequisite:** `lexq auth login` must have been run once to store an
|
|
166
|
+
> **Prerequisite:** `lexq auth login` must have been run once to store an
|
|
167
|
+
> API key in `~/.lexq/config.json`.
|
|
168
|
+
|
|
169
|
+
## AI Agent Skills
|
|
170
|
+
|
|
171
|
+
LexQ CLI ships with **AI Agent Skills** — structured documentation agents
|
|
172
|
+
read to understand *how* to use the tools, not just *what* they are.
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
skills/
|
|
176
|
+
├── lexq-shared/SKILL.md Core concepts, auth, workflow
|
|
177
|
+
├── lexq-groups/SKILL.md Policy groups, conflict resolution, A/B testing
|
|
178
|
+
├── lexq-rules/SKILL.md Condition syntax, action types, mutex
|
|
179
|
+
├── lexq-simulation/SKILL.md Dry run, batch simulation, compare
|
|
180
|
+
├── lexq-execution/SKILL.md Execution history, stats, failure logs
|
|
181
|
+
└── lexq-recipes/SKILL.md End-to-end recipes
|
|
182
|
+
|
|
183
|
+
.claude/CLAUDE.md Claude Code project context
|
|
184
|
+
AGENTS.md Universal agent guide (Cursor, Windsurf, Gemini CLI, Cline)
|
|
185
|
+
CONTEXT.md Platform architecture & glossary
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
After installing `@lexq/cli`, agents can read skills from:
|
|
189
|
+
|
|
190
|
+
```
|
|
191
|
+
node_modules/@lexq/cli/skills/
|
|
192
|
+
node_modules/@lexq/cli/AGENTS.md
|
|
193
|
+
node_modules/@lexq/cli/CONTEXT.md
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Commands
|
|
197
|
+
|
|
198
|
+
```
|
|
199
|
+
lexq auth login | logout | whoami
|
|
200
|
+
lexq status API health check
|
|
201
|
+
lexq serve Run as MCP stdio server (--mcp)
|
|
202
|
+
lexq groups list | get | create | update | delete
|
|
203
|
+
lexq groups ab-test start | stop | adjust
|
|
204
|
+
lexq versions list | get | create | update | delete | clone
|
|
205
|
+
lexq rules list | get | create | update | delete | reorder | toggle
|
|
206
|
+
lexq facts list | create | update | delete | action-metadata
|
|
207
|
+
lexq deploy publish | live | rollback | undeploy | history | detail | overview | deployable | diff
|
|
208
|
+
lexq analytics dry-run | dry-run-compare | requirements
|
|
209
|
+
lexq analytics simulation start | status | list | cancel | export
|
|
210
|
+
lexq analytics dataset upload | template
|
|
211
|
+
lexq history list | get | stats
|
|
212
|
+
lexq integrations list | get | save | delete | config-spec
|
|
213
|
+
lexq logs list | get | action | bulk-action
|
|
214
|
+
lexq webhook-subscriptions list | get | save | delete | test
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Global Options
|
|
218
|
+
|
|
219
|
+
| Flag | Description |
|
|
220
|
+
|--------------------------|--------------------------------------------|
|
|
221
|
+
| `--format <json\|table>` | Output format (default: `json`) |
|
|
222
|
+
| `--api-key <key>` | Override stored API key |
|
|
223
|
+
| `--base-url <url>` | Override API base URL |
|
|
224
|
+
| `--dry-run` | Preview the HTTP request without executing |
|
|
225
|
+
| `--verbose` | Show request/response details |
|
|
226
|
+
| `--no-color` | Disable colored output |
|
|
227
|
+
|
|
228
|
+
## Configuration
|
|
229
|
+
|
|
230
|
+
Config is stored at `~/.lexq/config.json`:
|
|
231
|
+
|
|
232
|
+
```json
|
|
233
|
+
{
|
|
234
|
+
"apiKey": "YOUR_API_KEY",
|
|
235
|
+
"baseUrl": "https://api.lexq.io/api/v1/partners",
|
|
236
|
+
"format": "json"
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Development
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
git clone https://github.com/lexq-io/lexq-cli.git
|
|
244
|
+
cd lexq-cli
|
|
245
|
+
pnpm install
|
|
246
|
+
pnpm build
|
|
247
|
+
pnpm start -- groups list
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
```bash
|
|
251
|
+
pnpm typecheck # Type check
|
|
252
|
+
pnpm lint # ESLint
|
|
253
|
+
bash tests/e2e.sh # CLI E2E tests (requires API key)
|
|
254
|
+
bash tests/test-engine-api.sh # Engine API integration tests
|
|
255
|
+
```
|
|
238
256
|
|
|
239
257
|
## License
|
|
240
258
|
|
package/dist/index.js
CHANGED
|
@@ -222,20 +222,25 @@ function registerAuthCommands(program) {
|
|
|
222
222
|
`
|
|
223
223
|
).action(async () => {
|
|
224
224
|
try {
|
|
225
|
+
const globalOpts = program.opts();
|
|
225
226
|
const config = loadConfig();
|
|
226
|
-
|
|
227
|
+
const apiKey = globalOpts.apiKey ?? config.apiKey;
|
|
228
|
+
const baseUrl = globalOpts.baseUrl ?? config.baseUrl;
|
|
229
|
+
if (!apiKey) {
|
|
227
230
|
console.error('Not authenticated. Run "lexq auth login" first.');
|
|
228
231
|
process.exit(1);
|
|
229
232
|
}
|
|
230
233
|
const info = await apiRequest("GET", "whoami", {
|
|
231
|
-
apiKey
|
|
232
|
-
baseUrl
|
|
234
|
+
apiKey,
|
|
235
|
+
baseUrl,
|
|
236
|
+
dryRun: globalOpts.dryRun,
|
|
237
|
+
verbose: globalOpts.verbose
|
|
233
238
|
});
|
|
234
|
-
const masked =
|
|
239
|
+
const masked = apiKey.length > 8 ? apiKey.substring(0, 4) + "****" + apiKey.substring(apiKey.length - 4) : "****";
|
|
235
240
|
printJson({
|
|
236
241
|
...info,
|
|
237
242
|
apiKey: masked,
|
|
238
|
-
baseUrl
|
|
243
|
+
baseUrl
|
|
239
244
|
});
|
|
240
245
|
} catch (error) {
|
|
241
246
|
printError(error);
|
|
@@ -3437,9 +3442,16 @@ function registerAnalyticsTools(server, callApi) {
|
|
|
3437
3442
|
title: "Dry Run",
|
|
3438
3443
|
description: dedent14`
|
|
3439
3444
|
Execute a single dry run against a version. Tests how rules evaluate given input facts without side effects.
|
|
3445
|
+
|
|
3446
|
+
Returns:
|
|
3447
|
+
inputFacts — normalized input facts
|
|
3448
|
+
mutatedFacts — input facts changed by rule actions (e.g. DISCOUNT mutates payment_amount)
|
|
3449
|
+
generatedVariables — new variables created by rules (e.g. last_discount_amount)
|
|
3450
|
+
executionTraces — per-rule match status
|
|
3451
|
+
decisionTraces — per-rule decision (SELECTED / BLOCKED_MUTEX / etc.)
|
|
3452
|
+
|
|
3440
3453
|
Example input: { "facts": { "payment_amount": 100000, "customer_tier": "VIP" } }
|
|
3441
|
-
Always dry-run before publishing to validate rule behavior
|
|
3442
|
-
`,
|
|
3454
|
+
Always dry-run before publishing to validate rule behavior.`,
|
|
3443
3455
|
inputSchema: {
|
|
3444
3456
|
versionId: z6.string().uuid().describe("Policy version ID to test against"),
|
|
3445
3457
|
facts: z6.string().describe('JSON string of facts object, e.g. {"payment_amount":100000}'),
|
|
@@ -3458,7 +3470,13 @@ function registerAnalyticsTools(server, callApi) {
|
|
|
3458
3470
|
"lexq_dry_run_compare",
|
|
3459
3471
|
{
|
|
3460
3472
|
title: "Dry Run Compare",
|
|
3461
|
-
description:
|
|
3473
|
+
description: dedent14`
|
|
3474
|
+
Compare dry run results between two versions using the same input facts. Useful for validating changes.
|
|
3475
|
+
|
|
3476
|
+
Returns:
|
|
3477
|
+
resultA / resultB — full DryRunResponse for each version
|
|
3478
|
+
diff.mutatedDiff — changes in mutatedFacts between A and B (key → {before, after})
|
|
3479
|
+
diff.generatedDiff — changes in generatedVariables between A and B`,
|
|
3462
3480
|
inputSchema: {
|
|
3463
3481
|
versionIdA: z6.string().uuid().describe("Baseline version ID"),
|
|
3464
3482
|
versionIdB: z6.string().uuid().describe("Candidate version ID"),
|
package/dist/mcp/register.js
CHANGED
|
@@ -611,9 +611,16 @@ function registerAnalyticsTools(server, callApi) {
|
|
|
611
611
|
title: "Dry Run",
|
|
612
612
|
description: dedent2`
|
|
613
613
|
Execute a single dry run against a version. Tests how rules evaluate given input facts without side effects.
|
|
614
|
+
|
|
615
|
+
Returns:
|
|
616
|
+
inputFacts — normalized input facts
|
|
617
|
+
mutatedFacts — input facts changed by rule actions (e.g. DISCOUNT mutates payment_amount)
|
|
618
|
+
generatedVariables — new variables created by rules (e.g. last_discount_amount)
|
|
619
|
+
executionTraces — per-rule match status
|
|
620
|
+
decisionTraces — per-rule decision (SELECTED / BLOCKED_MUTEX / etc.)
|
|
621
|
+
|
|
614
622
|
Example input: { "facts": { "payment_amount": 100000, "customer_tier": "VIP" } }
|
|
615
|
-
Always dry-run before publishing to validate rule behavior
|
|
616
|
-
`,
|
|
623
|
+
Always dry-run before publishing to validate rule behavior.`,
|
|
617
624
|
inputSchema: {
|
|
618
625
|
versionId: z6.string().uuid().describe("Policy version ID to test against"),
|
|
619
626
|
facts: z6.string().describe('JSON string of facts object, e.g. {"payment_amount":100000}'),
|
|
@@ -632,7 +639,13 @@ function registerAnalyticsTools(server, callApi) {
|
|
|
632
639
|
"lexq_dry_run_compare",
|
|
633
640
|
{
|
|
634
641
|
title: "Dry Run Compare",
|
|
635
|
-
description:
|
|
642
|
+
description: dedent2`
|
|
643
|
+
Compare dry run results between two versions using the same input facts. Useful for validating changes.
|
|
644
|
+
|
|
645
|
+
Returns:
|
|
646
|
+
resultA / resultB — full DryRunResponse for each version
|
|
647
|
+
diff.mutatedDiff — changes in mutatedFacts between A and B (key → {before, after})
|
|
648
|
+
diff.generatedDiff — changes in generatedVariables between A and B`,
|
|
636
649
|
inputSchema: {
|
|
637
650
|
versionIdA: z6.string().uuid().describe("Baseline version ID"),
|
|
638
651
|
versionIdB: z6.string().uuid().describe("Candidate version ID"),
|