lql-cli 0.2.0__py3-none-any.whl
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.
- lql/__init__.py +1 -0
- lql/_opts.py +7 -0
- lql/api.py +69 -0
- lql/cli.py +93 -0
- lql/commands/__init__.py +0 -0
- lql/commands/annotations.py +69 -0
- lql/commands/auth.py +162 -0
- lql/commands/buckets.py +190 -0
- lql/commands/datasets.py +398 -0
- lql/commands/edits.py +95 -0
- lql/commands/evals.py +285 -0
- lql/commands/highlights.py +89 -0
- lql/commands/instructions.py +248 -0
- lql/commands/issues.py +56 -0
- lql/commands/reports.py +92 -0
- lql/commands/skills.py +116 -0
- lql/commands/spec.py +165 -0
- lql/commands/workspaces.py +147 -0
- lql/config.py +103 -0
- lql/output.py +29 -0
- lql/sessions.py +27 -0
- lql/util.py +11 -0
- lql_cli-0.2.0.dist-info/METADATA +320 -0
- lql_cli-0.2.0.dist-info/RECORD +26 -0
- lql_cli-0.2.0.dist-info/WHEEL +4 -0
- lql_cli-0.2.0.dist-info/entry_points.txt +2 -0
lql/util.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from urllib.parse import quote
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def q(value: object) -> str:
|
|
5
|
+
"""Percent-encode a single URL path segment.
|
|
6
|
+
|
|
7
|
+
Mirrors the TS `encodeURIComponent`: user-supplied IDs are escaped so that
|
|
8
|
+
`/`, `..`, `?`, `#` etc. cannot change the effective request path (and thus
|
|
9
|
+
where the bearer token is sent).
|
|
10
|
+
"""
|
|
11
|
+
return quote(str(value), safe="")
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: lql-cli
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: lql — CLI for the Liquid DataViewer platform
|
|
5
|
+
Project-URL: Homepage, https://github.com/Liquid4All/lql
|
|
6
|
+
Author: Liquid AI
|
|
7
|
+
License: MIT
|
|
8
|
+
Requires-Python: >=3.9
|
|
9
|
+
Requires-Dist: httpx>=0.27
|
|
10
|
+
Requires-Dist: huggingface-hub>=0.24
|
|
11
|
+
Requires-Dist: rich>=13.0
|
|
12
|
+
Requires-Dist: typer>=0.12
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
|
|
15
|
+
# lql — Liquid Query Language CLI
|
|
16
|
+
|
|
17
|
+
Scriptable CLI for the [Liquid DataViewer](https://dataviewer.liquid.ai) platform. Designed for both humans and AI agents (Claude Code, Codex, etc.) to automate datasets, eval analysis, spec docs, annotations, and more.
|
|
18
|
+
|
|
19
|
+
## Quick start
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
uv tool install lql-cli # install the CLI (or: pipx install lql-cli); the command is `lql`
|
|
23
|
+
lql login # authenticate (opens a browser)
|
|
24
|
+
lql skills install # teach Claude Code + Codex how to use lql
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Install
|
|
28
|
+
|
|
29
|
+
`lql` is a Python package (requires Python ≥ 3.9), distributed on PyPI as **`lql-cli`** (the
|
|
30
|
+
command it installs is `lql`). Install it as a standalone CLI tool with
|
|
31
|
+
[uv](https://docs.astral.sh/uv/):
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
uv tool install lql-cli
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Or with pipx / pip:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pipx install lql-cli
|
|
41
|
+
# or
|
|
42
|
+
pip install lql-cli
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Run it without installing:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
uvx --from lql-cli lql instructions
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Or build from source:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
git clone https://github.com/Liquid4All/lql
|
|
55
|
+
cd lql
|
|
56
|
+
uv tool install . # or: pip install -e .
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Update to the latest version with `uv tool upgrade lql-cli` (or `pipx upgrade lql-cli` / `pip install -U lql-cli`).
|
|
60
|
+
|
|
61
|
+
## Authentication
|
|
62
|
+
|
|
63
|
+
### Interactive login (browser)
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
lql login
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Opens a browser window. After authorizing, credentials are saved to `~/.lql/config.json`.
|
|
70
|
+
|
|
71
|
+
### Non-interactive (API key)
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
export LQL_API_KEY=ak_live_...
|
|
75
|
+
lql login # stores key in config
|
|
76
|
+
# or skip config entirely — just set the env var
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Logout
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
lql logout
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Environment variables
|
|
86
|
+
|
|
87
|
+
| Variable | Description |
|
|
88
|
+
|---|---|
|
|
89
|
+
| `LQL_API_KEY` | API token (bypasses config file) |
|
|
90
|
+
| `LQL_API_URL` | Override API base URL |
|
|
91
|
+
| `LQL_HF_TOKEN` | HuggingFace token (required for `datasets upload`) |
|
|
92
|
+
| `LQL_EVAL_WORKSPACE` | Default workspace for `eval list` |
|
|
93
|
+
|
|
94
|
+
## Command reference
|
|
95
|
+
|
|
96
|
+
### Auth
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
lql login Authenticate (browser or LQL_API_KEY)
|
|
100
|
+
lql logout Revoke key and clear profile
|
|
101
|
+
lql whoami Show current user
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Workspaces
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
lql workspaces list List all workspaces
|
|
108
|
+
lql workspaces create <name> Create a workspace
|
|
109
|
+
lql workspaces show <id> Show workspace details
|
|
110
|
+
lql workspaces update <id> --name <n> Rename a workspace
|
|
111
|
+
lql workspaces delete <id> Delete a workspace
|
|
112
|
+
lql workspaces members list <id> List members
|
|
113
|
+
lql workspaces members add <id> <email> Add member by email
|
|
114
|
+
lql workspaces members remove <id> <uid> Remove member by user ID
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Datasets
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
lql datasets list [--workspace <id>] List datasets
|
|
121
|
+
lql datasets show <id> Show dataset details
|
|
122
|
+
lql datasets create --workspace <id> --hf-repo <repo> [--name <n>] [--split <s>]
|
|
123
|
+
lql datasets create --workspace <id> --hf-bucket <org/bucket> --key <path-or-glob> [--name <n>]
|
|
124
|
+
From an HF storage bucket (e.g. --key 'data/*.parquet')
|
|
125
|
+
lql datasets sync <id> Trigger sync (HF repo, S3, or HF bucket)
|
|
126
|
+
lql datasets schema <id> Show column schema
|
|
127
|
+
lql datasets rows <id> [--limit N] [--offset N] Fetch rows
|
|
128
|
+
lql datasets delete <id> Delete dataset
|
|
129
|
+
lql datasets push <id> Push to HuggingFace
|
|
130
|
+
lql datasets push-status <id> [--job <id>] Check push job status
|
|
131
|
+
lql datasets upload <file> --workspace <id> --name <repo-name> [--split <s>]
|
|
132
|
+
Upload local file → HF → dataset
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
`datasets upload` requires `LQL_HF_TOKEN`.
|
|
136
|
+
|
|
137
|
+
### Evals (dataset analysis)
|
|
138
|
+
|
|
139
|
+
Eval datasets are evaluation-run output — each row a sample with a model
|
|
140
|
+
`response` and a `correct` verdict. They're detected automatically. These
|
|
141
|
+
commands are the data primitives for error analysis: they slice and summarize
|
|
142
|
+
the dataset, and you do the reasoning over what they return.
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
lql eval list [--workspace <id>] List eval datasets only
|
|
146
|
+
Defaults to LQL_EVAL_WORKSPACE; without a
|
|
147
|
+
workspace, lists only evals you own.
|
|
148
|
+
lql eval correctness <id> Fast accuracy + correct/incorrect/missing counts
|
|
149
|
+
lql eval stats <id> Accuracy + error-type distribution + token stats
|
|
150
|
+
lql eval samples <id> [--filter correct|incorrect|missing|all]
|
|
151
|
+
[--search <text>] [--error-type <value>]
|
|
152
|
+
[--columns a,b] [--limit N] [--offset N]
|
|
153
|
+
Slice the dataset for error analysis. Filters
|
|
154
|
+
AND together; prints an `index` column per row.
|
|
155
|
+
lql eval sample <id> --row <index> Read one full sample (the conversation) by the
|
|
156
|
+
`index` returned from `eval samples`
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Notes:
|
|
160
|
+
|
|
161
|
+
- `--search` matches a substring on the prompt **or** response column (either hit counts). Override the searched columns with `--search-columns a,b`.
|
|
162
|
+
- `--error-type` values come from the `error_field` / `error_distribution` reported by `eval stats`.
|
|
163
|
+
- Use the `index` from `eval samples` directly as `eval sample --row <index>`.
|
|
164
|
+
|
|
165
|
+
Typical analysis loop:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
lql eval list --workspace <id> # find the eval dataset
|
|
169
|
+
lql eval stats <id> # accuracy + where the errors cluster
|
|
170
|
+
lql eval samples <id> --filter incorrect --limit 20 # pull the misses
|
|
171
|
+
lql eval sample <id> --row 42 # read one failure in full
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Edits
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
lql edits list <dataset_id> [--limit N] List edits
|
|
178
|
+
lql edits count <dataset_id> Count edits
|
|
179
|
+
lql edits add <dataset_id> --row <ext_id> --column <col> --value <json>
|
|
180
|
+
lql edits delete <dataset_id> <edit_id> Delete an edit
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Spec docs
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
lql spec show --workspace <id> Show current spec doc
|
|
187
|
+
lql spec pull --workspace <id> [-o <file>] [--stdout]
|
|
188
|
+
Pull markdown (writes SPEC.md by default)
|
|
189
|
+
lql spec push --workspace <id> [--file <f>] --message <m> [--base-version-id <id>]
|
|
190
|
+
Defaults --file to SPEC.md; --message required
|
|
191
|
+
lql spec history --workspace <id> Version history
|
|
192
|
+
lql spec diff --workspace <id> --version-id <id> [--compare-to <id>]
|
|
193
|
+
lql spec generate --workspace <id> AI-generate a spec from the workspace's datasets
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
`push` auto-detects create-vs-update: with no existing doc it creates v1, otherwise it commits on
|
|
197
|
+
top of the current HEAD (auto-resolved unless `--base-version-id` is given). On conflict (409),
|
|
198
|
+
`spec push` exits with code 4 — pull again, re-apply, and push.
|
|
199
|
+
|
|
200
|
+
### Review (annotations, highlights, issues, reports)
|
|
201
|
+
|
|
202
|
+
These act directly on a **dataset** — the CLI resolves the dataset's review session for you, so you
|
|
203
|
+
never manage sessions by hand. Advanced: pass `--session <id>` to target a specific session for
|
|
204
|
+
multi-pass review (a session id is returned in the JSON of any annotation/highlight/report).
|
|
205
|
+
|
|
206
|
+
#### Annotations
|
|
207
|
+
|
|
208
|
+
```
|
|
209
|
+
lql annotations list <dataset_id> [--session <id>]
|
|
210
|
+
lql annotations add <dataset_id> --row <ext_id> [--rating <n>] [--note <str>] [--session <id>]
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
#### Highlights
|
|
214
|
+
|
|
215
|
+
Highlights mark a text span (`--start`/`--end` are character offsets into the row's `--column` value).
|
|
216
|
+
|
|
217
|
+
```
|
|
218
|
+
lql highlights list <dataset_id> [--session <id>]
|
|
219
|
+
lql highlights add <dataset_id> --row <ext_id> --column <col> --start <n> --end <n> --text <str>
|
|
220
|
+
[--issue <id>] [--color <hex>] [--note <text>] [--session <id>]
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
#### Issues
|
|
224
|
+
|
|
225
|
+
A per-dataset taxonomy (name/color) used to tag highlights via `highlights add --issue <id>`.
|
|
226
|
+
|
|
227
|
+
```
|
|
228
|
+
lql issues list <dataset_id>
|
|
229
|
+
lql issues create <dataset_id> --name <str> [--description <str>] [--color <hex>]
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
#### Reports
|
|
233
|
+
|
|
234
|
+
```
|
|
235
|
+
lql reports list <dataset_id> [--session <id>]
|
|
236
|
+
lql reports show <report_id> Show a report
|
|
237
|
+
lql reports create <dataset_id> --title <title> [--summary <text>] [--session <id>]
|
|
238
|
+
Publish a report (bundles annotations + LLM analysis)
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Buckets
|
|
242
|
+
|
|
243
|
+
S3-compatible:
|
|
244
|
+
|
|
245
|
+
```
|
|
246
|
+
lql buckets list List S3 buckets
|
|
247
|
+
lql buckets show <id> Show bucket details
|
|
248
|
+
lql buckets probe <id> Test bucket connectivity + credentials
|
|
249
|
+
lql buckets objects <id> [--prefix <str>] List objects
|
|
250
|
+
lql buckets attach <bucket_id> --workspace <id> Attach bucket to workspace
|
|
251
|
+
lql buckets detach <bucket_id> --workspace <id> Detach bucket from workspace
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Hugging Face buckets (connect → add datasets; auth is your HF token):
|
|
255
|
+
|
|
256
|
+
```
|
|
257
|
+
lql buckets list-hf List HF bucket connections
|
|
258
|
+
lql buckets connect-hf <owner/bucket> --workspace <id> [--label <l>] [--hf-key <id>]
|
|
259
|
+
Connect an HF bucket and attach it to a workspace
|
|
260
|
+
lql buckets create-dataset <bucket_id> --workspace <id> --key <path-or-glob> [--name <display>]
|
|
261
|
+
Create a dataset from a connected HF bucket
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### Skills (agent setup)
|
|
265
|
+
|
|
266
|
+
Install the `lql` agent skill so coding agents (Claude Code, Codex) know how to use lql. The skill
|
|
267
|
+
is a thin pointer that tells the agent to run `lql instructions`, so it never goes stale.
|
|
268
|
+
|
|
269
|
+
```
|
|
270
|
+
lql skills install [--tool claude|codex|both] [--project] [--force]
|
|
271
|
+
Install to ~/.claude and ~/.codex (both, by default)
|
|
272
|
+
lql skills uninstall [--tool claude|codex|both] [--project]
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
`--project` installs into `./.claude` and `./.codex` in the current directory instead of the home dir.
|
|
276
|
+
|
|
277
|
+
### Instructions
|
|
278
|
+
|
|
279
|
+
```
|
|
280
|
+
lql instructions Print the full agent reference (all commands,
|
|
281
|
+
flags, examples, and workflows) in one read
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## Global flags
|
|
285
|
+
|
|
286
|
+
All commands accept:
|
|
287
|
+
|
|
288
|
+
| Flag | Description |
|
|
289
|
+
|---|---|
|
|
290
|
+
| `--json` | Output raw JSON to stdout |
|
|
291
|
+
| `--profile <name>` | Use a named config profile |
|
|
292
|
+
| `--api-url <url>` | Override the API base URL |
|
|
293
|
+
|
|
294
|
+
## Exit codes
|
|
295
|
+
|
|
296
|
+
| Code | Meaning |
|
|
297
|
+
|---|---|
|
|
298
|
+
| 0 | Success |
|
|
299
|
+
| 1 | General error |
|
|
300
|
+
| 2 | Unauthenticated / forbidden |
|
|
301
|
+
| 3 | Not found |
|
|
302
|
+
| 4 | Conflict (e.g. spec push version conflict) |
|
|
303
|
+
| 5 | Server error |
|
|
304
|
+
|
|
305
|
+
## Config file
|
|
306
|
+
|
|
307
|
+
`~/.lql/config.json` (mode 0600):
|
|
308
|
+
|
|
309
|
+
```json
|
|
310
|
+
{
|
|
311
|
+
"current_profile": "default",
|
|
312
|
+
"profiles": {
|
|
313
|
+
"default": {
|
|
314
|
+
"token": "ak_live_...",
|
|
315
|
+
"key_id": "uuid",
|
|
316
|
+
"api_url": "https://api.dataviewer.liquid.ai"
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
```
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
lql/__init__.py,sha256=Zn1KFblwuFHiDRdRAiRnDBRkbPttWh44jKa5zG2ov0E,22
|
|
2
|
+
lql/_opts.py,sha256=m1pxvK9K7oKdcYsVyR1zZwoEikArsphR-xxL4liXffs,310
|
|
3
|
+
lql/api.py,sha256=gIbuUmPnYirakQTeJAOZ3Cam-RFuF2WgoBmD8TadVhg,2610
|
|
4
|
+
lql/cli.py,sha256=mbTouzVeRWiawgbpMRCGPE_U5z3nD99Ks-1nCT05eG4,2626
|
|
5
|
+
lql/config.py,sha256=8kCv6W7e8s3Yp_-bIS5vD7nbPjQ-5Bf571_SDr31anw,3689
|
|
6
|
+
lql/output.py,sha256=mkIABp9OE790hhgVkZQbGp9v6DYt2n0MbgNE6d4mpBo,826
|
|
7
|
+
lql/sessions.py,sha256=1dgLbOnmnNL-dAfEsQ6rotSezAbWTqRLIDCnZviycw4,826
|
|
8
|
+
lql/util.py,sha256=DPMSW-DTkuXisXr3yNsxmntNpV8vJEeePCB8QmrtUco,354
|
|
9
|
+
lql/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
lql/commands/annotations.py,sha256=J30Vxx79PB7KoOFLx3Nm5JDe3MnXdVLiWiSQ1qGYXkw,2425
|
|
11
|
+
lql/commands/auth.py,sha256=zx0XBdy4uOk6VV5kn3ZCA2YnukDHFfsNugyUnc2vjuY,5753
|
|
12
|
+
lql/commands/buckets.py,sha256=N67gCRpMs4pDUfIORszMN4ci5Nhr0BJh-Un-yFG_izs,6735
|
|
13
|
+
lql/commands/datasets.py,sha256=ss-XyteqxAib3oc2oiMZI-H1n60rhL4u4P1x1FEjTwY,14120
|
|
14
|
+
lql/commands/edits.py,sha256=OsAjXpd5vxgOdxnmjXDHVQrC9y6UGAfQOvjkZkmj_tY,3017
|
|
15
|
+
lql/commands/evals.py,sha256=2Ofh8H0YE6ofbj-DDNX7cxgwDvYQ8K2gg6zedR-izrQ,10946
|
|
16
|
+
lql/commands/highlights.py,sha256=1H1w_lDiIKXrTjUOXOkSIlskg4T_-FeWCXJpE7g7kZ0,3249
|
|
17
|
+
lql/commands/instructions.py,sha256=eMc0wrLS0h8_G_TeiWiA9u5KgWjJlQZ3W4ziniuYJoc,10783
|
|
18
|
+
lql/commands/issues.py,sha256=uQvPY9JTAU3Xu6-s4JC9-SeJarztFL665WEQKSdrfJ8,1820
|
|
19
|
+
lql/commands/reports.py,sha256=Xjx68M7V6mNNfm3vqARX8XL3qJ-1mRTxoXk4Ab3JHdM,2994
|
|
20
|
+
lql/commands/skills.py,sha256=J2G8MVuLSjsJ4frRULpGUglYn4gko3T0c8oE6-TK49o,4847
|
|
21
|
+
lql/commands/spec.py,sha256=OLsnBT-uiabnU_gAKteuBg2g_-CqyfpSfc44lxDYKpg,5860
|
|
22
|
+
lql/commands/workspaces.py,sha256=8GquMfOaWhrTRf2pJeb7OSA70tq4szg5OOW6lif2WPI,4552
|
|
23
|
+
lql_cli-0.2.0.dist-info/METADATA,sha256=umFjjsJcjcDKDSd2vnISfMN88TksAOGUC74mHS03SMc,11198
|
|
24
|
+
lql_cli-0.2.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
25
|
+
lql_cli-0.2.0.dist-info/entry_points.txt,sha256=UdkNviQzfLOoNBtTsrFJJPtDcNQNE89oc7pPowcoFQI,37
|
|
26
|
+
lql_cli-0.2.0.dist-info/RECORD,,
|