maybeai-sheet-cli 0.14.2__tar.gz → 0.16.0__tar.gz

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.
Files changed (66) hide show
  1. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/.gitignore +1 -0
  2. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/PKG-INFO +82 -3
  3. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/README.md +81 -2
  4. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/pyproject.toml +1 -1
  5. maybeai_sheet_cli-0.16.0/src/maybeai_sheet/__init__.py +44 -0
  6. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/client.py +32 -0
  7. maybeai_sheet_cli-0.16.0/src/maybeai_sheet/commands/workbook.py +1541 -0
  8. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/endpoints.py +10 -1
  9. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/tests/test_cli.py +677 -0
  10. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/tests/test_endpoints.py +7 -1
  11. maybeai_sheet_cli-0.16.0/tests/test_version.py +66 -0
  12. maybeai_sheet_cli-0.14.2/src/maybeai_sheet/__init__.py +0 -5
  13. maybeai_sheet_cli-0.14.2/src/maybeai_sheet/commands/workbook.py +0 -608
  14. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/chart_config.py +0 -0
  15. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/chart_style_summary.py +0 -0
  16. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/cli.py +0 -0
  17. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/commands/__init__.py +0 -0
  18. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/commands/_phase2.py +0 -0
  19. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/commands/cell.py +0 -0
  20. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/commands/chart.py +0 -0
  21. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/commands/column.py +0 -0
  22. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/commands/dashboard.py +0 -0
  23. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/commands/db_table.py +0 -0
  24. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/commands/excel_table.py +0 -0
  25. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/commands/excel_worksheet.py +0 -0
  26. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/commands/file.py +0 -0
  27. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/commands/formula.py +0 -0
  28. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/commands/history.py +0 -0
  29. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/commands/image.py +0 -0
  30. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/commands/pivot.py +0 -0
  31. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/commands/range.py +0 -0
  32. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/commands/raw.py +0 -0
  33. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/commands/row.py +0 -0
  34. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/commands/share.py +0 -0
  35. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/commands/sheet.py +0 -0
  36. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/commands/style.py +0 -0
  37. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/commands/table.py +0 -0
  38. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/commands/worksheet.py +0 -0
  39. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/config.py +0 -0
  40. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/dashboard_interactions.py +0 -0
  41. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/dashboard_plan.py +0 -0
  42. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/errors.py +0 -0
  43. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/formatters.py +0 -0
  44. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/models/__init__.py +0 -0
  45. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/models/share.py +0 -0
  46. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/models/sheet.py +0 -0
  47. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/models/workbook.py +0 -0
  48. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/options.py +0 -0
  49. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/protocol.py +0 -0
  50. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/resolver.py +0 -0
  51. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/table_resolver.py +0 -0
  52. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/src/maybeai_sheet/update.py +0 -0
  53. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/tests/fixtures/benchmarks/build_fixtures.py +0 -0
  54. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/tests/fixtures/benchmarks/flat-records.xlsx +0 -0
  55. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/tests/fixtures/benchmarks/mixed-engine.xlsx +0 -0
  56. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/tests/fixtures/benchmarks/multi-table-layout.xlsx +0 -0
  57. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/tests/fixtures/benchmarks/rows.json +0 -0
  58. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/tests/fixtures/benchmarks/simple-grid.xlsx +0 -0
  59. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/tests/fixtures/benchmarks/simple-values.json +0 -0
  60. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/tests/test_benchmark_runner.py +0 -0
  61. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/tests/test_dashboard_plan.py +0 -0
  62. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/tests/test_formatters.py +0 -0
  63. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/tests/test_phase2_cli.py +0 -0
  64. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/tests/test_resolver.py +0 -0
  65. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/tests/test_two_engine_cli.py +0 -0
  66. {maybeai_sheet_cli-0.14.2 → maybeai_sheet_cli-0.16.0}/tests/test_update.py +0 -0
@@ -24,3 +24,4 @@ temp
24
24
  docs_requirement
25
25
  artifacts/
26
26
  .worktrees/
27
+ docs/requirements
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maybeai-sheet-cli
3
- Version: 0.14.2
3
+ Version: 0.16.0
4
4
  Summary: CLI for common MaybeAI spreadsheet operations
5
5
  Project-URL: Homepage, https://github.com/OmniMCP-AI/maybeai-sheet-cli
6
6
  Project-URL: Repository, https://github.com/OmniMCP-AI/maybeai-sheet-cli
@@ -148,6 +148,49 @@ mbs workbook import ./mixed-workbook.xlsx --engine auto
148
148
  mbs workbook import ./mixed-workbook.xlsx --engine "postgres,excel,excel,postgres"
149
149
  ```
150
150
 
151
+ Import CSV, TSV, or a public Google Sheet through the import-source preview flow:
152
+
153
+ ```bash
154
+ mbs workbook import ./orders.csv
155
+ mbs workbook import ./orders.tsv
156
+ mbs workbook import ./orders.csv --engine postgres
157
+ mbs workbook import ./orders.tsv --engine excelize
158
+ mbs workbook import "https://docs.google.com/spreadsheets/d/SPREADSHEET_ID/edit#gid=0"
159
+ mbs workbook import "https://docs.google.com/spreadsheets/d/SPREADSHEET_ID/edit#gid=0" --engine postgres
160
+ mbs workbook import "https://docs.google.com/spreadsheets/d/SPREADSHEET_ID/edit#gid=0" --source-worksheet-name "1店" --worksheet-name "Store 1" --engine excelize
161
+ mbs workbook import ./orders.csv --preview-only --output json
162
+ ```
163
+
164
+ Append a worksheet from a local Excel file, CSV/TSV file, or public Google Sheet into an existing workbook:
165
+
166
+ ```bash
167
+ mbs workbook import ./report.xlsx --doc-id target123 --worksheet-name "联盟" --engine excelize
168
+ mbs workbook import ./report.xlsx --doc-id target123 --worksheet-name "联盟" --target-worksheet-name "联盟导入" --engine postgres
169
+ mbs workbook import ./orders.csv --doc-id target123 --worksheet-name "orders" --target-worksheet-name "Orders Imported" --engine postgres
170
+ mbs workbook import "https://docs.google.com/spreadsheets/d/SPREADSHEET_ID/edit#gid=0" --doc-id target123 --worksheet-name "1店" --engine excelize
171
+ ```
172
+
173
+ Import one source worksheet from another workbook into a raw PG/db-table surface:
174
+
175
+ ```bash
176
+ mbs workbook import \
177
+ --doc-id target123 \
178
+ --engine postgres \
179
+ --source-doc-id source123 \
180
+ --worksheet-name "1店" \
181
+ --name R_order_lines_store_1 \
182
+ --verify \
183
+ --output json
184
+ ```
185
+
186
+ After a successful raw worksheet import, trust `workbook import` stdout and
187
+ `--verify` as the table-creation evidence. If you need a spot check, sample one
188
+ representative created table instead of looping over every `R_*` table:
189
+
190
+ ```bash
191
+ mbs db-table sample --doc-id target123 --name R_order_lines_store_1 --limit 2 --output json
192
+ ```
193
+
151
194
  Append rows and verify:
152
195
 
153
196
  ```bash
@@ -241,7 +284,7 @@ mbs
241
284
  │ ├── source PLAN Similar to NotebookLM source (menu on the left).
242
285
  │ ├── create NOW Create a new workbook.
243
286
  │ ├── create-from-file NOW Import an .xlsx file.
244
- │ ├── import NOW Preferred alias for create-from-file.
287
+ │ ├── import NOW File import or cross-workbook worksheet -> raw PG surface import.
245
288
  │ ├── list-user-workbooks API List user workbooks with bounded output.
246
289
  │ ├── list-worksheets API List worksheets, including engine.
247
290
  │ ├── search NOW Search user workbooks with bounded output.
@@ -329,6 +372,12 @@ mbs
329
372
  │ ├── validate NOW Validate dashboard layout, worksheet target, and chart source fields locally.
330
373
  │ └── refresh NOW Upsert dashboard charts from one spec and re-verify chart inventory.
331
374
 
375
+ ├── pivot
376
+ │ ├── read API Read a pivot result from a JSON spec.
377
+ │ ├── preview API Preview pivot output without writing cells.
378
+ │ ├── upsert API Write or overwrite a persisted pivot table at an anchor cell.
379
+ │ └── delete API Delete a persisted pivot table by worksheet and anchor cell.
380
+
332
381
 
333
382
  ├── excel-worksheet style
334
383
  │ ├── cell batch-set NOW Apply cell style batches from JSON.
@@ -376,6 +425,13 @@ mbs update --check
376
425
  mbs workbook metadata --doc-id abc123 # API
377
426
  mbs workbook list-user-workbooks --limit 20 # API
378
427
  mbs workbook list-worksheets --doc-id abc123 # API
428
+ mbs workbook import ./report.xlsx # NOW
429
+ mbs workbook import ./orders.csv --engine postgres # NOW
430
+ mbs workbook import "https://docs.google.com/spreadsheets/d/SPREADSHEET_ID/edit#gid=0" --engine excelize # NOW
431
+ mbs workbook import ./report.xlsx --doc-id target123 --worksheet-name "联盟" --target-worksheet-name "联盟导入" --engine postgres # NOW
432
+ mbs workbook import ./orders.csv --doc-id target123 --worksheet-name "orders" --target-worksheet-name "Orders Imported" --engine postgres # NOW
433
+ mbs workbook import "https://docs.google.com/spreadsheets/d/SPREADSHEET_ID/edit#gid=0" --doc-id target123 --worksheet-name "1店" --target-worksheet-name "Store 1" --engine excelize # NOW
434
+ mbs workbook import --doc-id target123 --engine postgres --source-doc-id source123 --worksheet-name "1店" --name R_order_lines_store_1 --verify --output json # NOW
379
435
  mbs workbook export --doc-id abc123 --out workbook.xlsx # API
380
436
  mbs workbook copy --doc-id abc123 --name "Budget Copy" # API
381
437
  mbs workbook delete --doc-id abc123 --dry-run # API
@@ -406,7 +462,7 @@ mbs excel-table style columns-width --doc-id abc123 --worksheet-name Orders --ta
406
462
  # db-table
407
463
  mbs db-table metadata --doc-id abc123 --name orders-large # API
408
464
  mbs db-table schema --doc-id abc123 --name orders-large # API
409
- mbs db-table sample --doc-id abc123 --name orders-large --limit 50 # API
465
+ mbs db-table sample --doc-id target123 --name R_order_lines_store_1 --limit 2 --output json # API, representative post-import spot check
410
466
  mbs db-table read --doc-id abc123 --name orders-large --limit 100 --offset 200 # API
411
467
  mbs db-table insert --doc-id abc123 --name orders-large --rows rows.json # API
412
468
  mbs db-table create --doc-id abc123 --name Orders --rows orders.json # API
@@ -479,6 +535,26 @@ mbs excel-worksheet dashboard refresh --doc-id abc123 --spec dashboard.json # N
479
535
  # ]
480
536
  # }
481
537
 
538
+ # pivot
539
+ mbs pivot preview --doc-id abc123 --gid 1 --spec pivot.json # API
540
+ mbs pivot read --doc-id abc123 --spec pivot.json # API
541
+ mbs pivot upsert --doc-id abc123 --target-worksheet-name PivotResult --anchor-cell A1 --spec pivot.json # API
542
+ mbs pivot delete --doc-id abc123 --worksheet-name PivotResult --anchor-cell A1 --dry-run # API
543
+ mbs pivot delete --doc-id abc123 --worksheet-name PivotResult --anchor-cell A1 --yes # API
544
+
545
+ # recommended pivot.json shape
546
+ # {
547
+ # "worksheet_name": "SourceData",
548
+ # "range_address": "A1:C100",
549
+ # "row_fields": ["Region"],
550
+ # "column_fields": ["Category"],
551
+ # "metrics": [
552
+ # { "aggregate": "sum", "value_field": "Amount", "label": "Total Amount" }
553
+ # ],
554
+ # "show_row_totals": true,
555
+ # "show_column_totals": true
556
+ # }
557
+
482
558
  # style
483
559
  mbs excel-worksheet style freeze-panes --doc-id abc123 --worksheet-name Actuals --cell B2 # NOW
484
560
  mbs excel-worksheet style cell batch-set --doc-id abc123 --worksheet-name Actuals --range A1:G1 --style header_style.json # NOW
@@ -552,6 +628,9 @@ Relationship guide:
552
628
  source-backed visualizations.
553
629
  - Use `excel-worksheet dashboard` for local validation and worksheet-level chart
554
630
  orchestration such as manifest, create-config, and refresh.
631
+ - Use `pivot` for persisted pivot tables. Prefer `pivot preview` before writing,
632
+ then `pivot upsert` with an explicit `--anchor-cell`; use `pivot delete`
633
+ instead of manually clearing a pivot spill range.
555
634
  - Use `excel-worksheet image` for list/read/insert/replace/delete image
556
635
  workflows.
557
636
  - Use `version` for workbook history inspection and restore.
@@ -124,6 +124,49 @@ mbs workbook import ./mixed-workbook.xlsx --engine auto
124
124
  mbs workbook import ./mixed-workbook.xlsx --engine "postgres,excel,excel,postgres"
125
125
  ```
126
126
 
127
+ Import CSV, TSV, or a public Google Sheet through the import-source preview flow:
128
+
129
+ ```bash
130
+ mbs workbook import ./orders.csv
131
+ mbs workbook import ./orders.tsv
132
+ mbs workbook import ./orders.csv --engine postgres
133
+ mbs workbook import ./orders.tsv --engine excelize
134
+ mbs workbook import "https://docs.google.com/spreadsheets/d/SPREADSHEET_ID/edit#gid=0"
135
+ mbs workbook import "https://docs.google.com/spreadsheets/d/SPREADSHEET_ID/edit#gid=0" --engine postgres
136
+ mbs workbook import "https://docs.google.com/spreadsheets/d/SPREADSHEET_ID/edit#gid=0" --source-worksheet-name "1店" --worksheet-name "Store 1" --engine excelize
137
+ mbs workbook import ./orders.csv --preview-only --output json
138
+ ```
139
+
140
+ Append a worksheet from a local Excel file, CSV/TSV file, or public Google Sheet into an existing workbook:
141
+
142
+ ```bash
143
+ mbs workbook import ./report.xlsx --doc-id target123 --worksheet-name "联盟" --engine excelize
144
+ mbs workbook import ./report.xlsx --doc-id target123 --worksheet-name "联盟" --target-worksheet-name "联盟导入" --engine postgres
145
+ mbs workbook import ./orders.csv --doc-id target123 --worksheet-name "orders" --target-worksheet-name "Orders Imported" --engine postgres
146
+ mbs workbook import "https://docs.google.com/spreadsheets/d/SPREADSHEET_ID/edit#gid=0" --doc-id target123 --worksheet-name "1店" --engine excelize
147
+ ```
148
+
149
+ Import one source worksheet from another workbook into a raw PG/db-table surface:
150
+
151
+ ```bash
152
+ mbs workbook import \
153
+ --doc-id target123 \
154
+ --engine postgres \
155
+ --source-doc-id source123 \
156
+ --worksheet-name "1店" \
157
+ --name R_order_lines_store_1 \
158
+ --verify \
159
+ --output json
160
+ ```
161
+
162
+ After a successful raw worksheet import, trust `workbook import` stdout and
163
+ `--verify` as the table-creation evidence. If you need a spot check, sample one
164
+ representative created table instead of looping over every `R_*` table:
165
+
166
+ ```bash
167
+ mbs db-table sample --doc-id target123 --name R_order_lines_store_1 --limit 2 --output json
168
+ ```
169
+
127
170
  Append rows and verify:
128
171
 
129
172
  ```bash
@@ -217,7 +260,7 @@ mbs
217
260
  │ ├── source PLAN Similar to NotebookLM source (menu on the left).
218
261
  │ ├── create NOW Create a new workbook.
219
262
  │ ├── create-from-file NOW Import an .xlsx file.
220
- │ ├── import NOW Preferred alias for create-from-file.
263
+ │ ├── import NOW File import or cross-workbook worksheet -> raw PG surface import.
221
264
  │ ├── list-user-workbooks API List user workbooks with bounded output.
222
265
  │ ├── list-worksheets API List worksheets, including engine.
223
266
  │ ├── search NOW Search user workbooks with bounded output.
@@ -305,6 +348,12 @@ mbs
305
348
  │ ├── validate NOW Validate dashboard layout, worksheet target, and chart source fields locally.
306
349
  │ └── refresh NOW Upsert dashboard charts from one spec and re-verify chart inventory.
307
350
 
351
+ ├── pivot
352
+ │ ├── read API Read a pivot result from a JSON spec.
353
+ │ ├── preview API Preview pivot output without writing cells.
354
+ │ ├── upsert API Write or overwrite a persisted pivot table at an anchor cell.
355
+ │ └── delete API Delete a persisted pivot table by worksheet and anchor cell.
356
+
308
357
 
309
358
  ├── excel-worksheet style
310
359
  │ ├── cell batch-set NOW Apply cell style batches from JSON.
@@ -352,6 +401,13 @@ mbs update --check
352
401
  mbs workbook metadata --doc-id abc123 # API
353
402
  mbs workbook list-user-workbooks --limit 20 # API
354
403
  mbs workbook list-worksheets --doc-id abc123 # API
404
+ mbs workbook import ./report.xlsx # NOW
405
+ mbs workbook import ./orders.csv --engine postgres # NOW
406
+ mbs workbook import "https://docs.google.com/spreadsheets/d/SPREADSHEET_ID/edit#gid=0" --engine excelize # NOW
407
+ mbs workbook import ./report.xlsx --doc-id target123 --worksheet-name "联盟" --target-worksheet-name "联盟导入" --engine postgres # NOW
408
+ mbs workbook import ./orders.csv --doc-id target123 --worksheet-name "orders" --target-worksheet-name "Orders Imported" --engine postgres # NOW
409
+ mbs workbook import "https://docs.google.com/spreadsheets/d/SPREADSHEET_ID/edit#gid=0" --doc-id target123 --worksheet-name "1店" --target-worksheet-name "Store 1" --engine excelize # NOW
410
+ mbs workbook import --doc-id target123 --engine postgres --source-doc-id source123 --worksheet-name "1店" --name R_order_lines_store_1 --verify --output json # NOW
355
411
  mbs workbook export --doc-id abc123 --out workbook.xlsx # API
356
412
  mbs workbook copy --doc-id abc123 --name "Budget Copy" # API
357
413
  mbs workbook delete --doc-id abc123 --dry-run # API
@@ -382,7 +438,7 @@ mbs excel-table style columns-width --doc-id abc123 --worksheet-name Orders --ta
382
438
  # db-table
383
439
  mbs db-table metadata --doc-id abc123 --name orders-large # API
384
440
  mbs db-table schema --doc-id abc123 --name orders-large # API
385
- mbs db-table sample --doc-id abc123 --name orders-large --limit 50 # API
441
+ mbs db-table sample --doc-id target123 --name R_order_lines_store_1 --limit 2 --output json # API, representative post-import spot check
386
442
  mbs db-table read --doc-id abc123 --name orders-large --limit 100 --offset 200 # API
387
443
  mbs db-table insert --doc-id abc123 --name orders-large --rows rows.json # API
388
444
  mbs db-table create --doc-id abc123 --name Orders --rows orders.json # API
@@ -455,6 +511,26 @@ mbs excel-worksheet dashboard refresh --doc-id abc123 --spec dashboard.json # N
455
511
  # ]
456
512
  # }
457
513
 
514
+ # pivot
515
+ mbs pivot preview --doc-id abc123 --gid 1 --spec pivot.json # API
516
+ mbs pivot read --doc-id abc123 --spec pivot.json # API
517
+ mbs pivot upsert --doc-id abc123 --target-worksheet-name PivotResult --anchor-cell A1 --spec pivot.json # API
518
+ mbs pivot delete --doc-id abc123 --worksheet-name PivotResult --anchor-cell A1 --dry-run # API
519
+ mbs pivot delete --doc-id abc123 --worksheet-name PivotResult --anchor-cell A1 --yes # API
520
+
521
+ # recommended pivot.json shape
522
+ # {
523
+ # "worksheet_name": "SourceData",
524
+ # "range_address": "A1:C100",
525
+ # "row_fields": ["Region"],
526
+ # "column_fields": ["Category"],
527
+ # "metrics": [
528
+ # { "aggregate": "sum", "value_field": "Amount", "label": "Total Amount" }
529
+ # ],
530
+ # "show_row_totals": true,
531
+ # "show_column_totals": true
532
+ # }
533
+
458
534
  # style
459
535
  mbs excel-worksheet style freeze-panes --doc-id abc123 --worksheet-name Actuals --cell B2 # NOW
460
536
  mbs excel-worksheet style cell batch-set --doc-id abc123 --worksheet-name Actuals --range A1:G1 --style header_style.json # NOW
@@ -528,6 +604,9 @@ Relationship guide:
528
604
  source-backed visualizations.
529
605
  - Use `excel-worksheet dashboard` for local validation and worksheet-level chart
530
606
  orchestration such as manifest, create-config, and refresh.
607
+ - Use `pivot` for persisted pivot tables. Prefer `pivot preview` before writing,
608
+ then `pivot upsert` with an explicit `--anchor-cell`; use `pivot delete`
609
+ instead of manually clearing a pivot spill range.
531
610
  - Use `excel-worksheet image` for list/read/insert/replace/delete image
532
611
  workflows.
533
612
  - Use `version` for workbook history inspection and restore.
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "maybeai-sheet-cli"
7
- version = "0.14.2"
7
+ version = "0.16.0"
8
8
  description = "CLI for common MaybeAI spreadsheet operations"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -0,0 +1,44 @@
1
+ """MaybeAI Sheet CLI package."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from importlib.metadata import PackageNotFoundError, version as metadata_version
6
+ from pathlib import Path
7
+
8
+ __all__ = ["__version__"]
9
+
10
+ _PACKAGE_NAME = "maybeai-sheet-cli"
11
+
12
+
13
+ def _version_from_pyproject() -> str | None:
14
+ pyproject = Path(__file__).resolve().parents[2] / "pyproject.toml"
15
+ if not pyproject.is_file():
16
+ return None
17
+
18
+ in_project_section = False
19
+
20
+ for line in pyproject.read_text(encoding="utf-8").splitlines():
21
+ stripped = line.strip()
22
+ if stripped == "[project]":
23
+ in_project_section = True
24
+ continue
25
+ if in_project_section and stripped.startswith("["):
26
+ break
27
+ if in_project_section and stripped.startswith("version"):
28
+ return stripped.split("=", 1)[1].strip().strip('"')
29
+
30
+ raise RuntimeError(f"Could not determine {_PACKAGE_NAME} version from {pyproject}.")
31
+
32
+
33
+ def _resolve_version() -> str:
34
+ source_version = _version_from_pyproject()
35
+ if source_version is not None:
36
+ return source_version
37
+
38
+ try:
39
+ return metadata_version(_PACKAGE_NAME)
40
+ except PackageNotFoundError:
41
+ return "0+unknown"
42
+
43
+
44
+ __version__ = _resolve_version()
@@ -126,3 +126,35 @@ class MaybeAIClient:
126
126
  files["file"][1].close()
127
127
  self._raise_for_error(response, endpoint=endpoint)
128
128
  return response.json()
129
+
130
+ def post_multipart(
131
+ self,
132
+ path: str,
133
+ *,
134
+ data: dict[str, str],
135
+ file_path: Path | None = None,
136
+ file_field: str = "file",
137
+ content_type: str | None = None,
138
+ ) -> dict[str, Any]:
139
+ endpoint = self._endpoint(path)
140
+ files: dict[str, tuple[str, Any] | tuple[str, Any, str]] | None = None
141
+ file_handle = None
142
+ if file_path is not None:
143
+ file_handle = file_path.open("rb")
144
+ if content_type:
145
+ files = {file_field: (file_path.name, file_handle, content_type)}
146
+ else:
147
+ files = {file_field: (file_path.name, file_handle)}
148
+ try:
149
+ with self._client() as client:
150
+ response = client.post(
151
+ endpoint,
152
+ headers=self._headers(content_type=False),
153
+ files=files,
154
+ data=data,
155
+ )
156
+ finally:
157
+ if file_handle is not None:
158
+ file_handle.close()
159
+ self._raise_for_error(response, endpoint=endpoint)
160
+ return response.json()