Metadata-Version: 2.1
Name: maybeai-sheet-cli
Version: 0.29.0
Summary: CLI for common MaybeAI spreadsheet operations
Project-URL: Homepage, https://github.com/OmniMCP-AI/maybeai-sheet-cli
Project-URL: Repository, https://github.com/OmniMCP-AI/maybeai-sheet-cli
Project-URL: Issues, https://github.com/OmniMCP-AI/maybeai-sheet-cli/issues
Author: OmniMCP-AI
License: Proprietary
Keywords: cli,excel,maybeai,spreadsheet
Classifier: Environment :: Console
Classifier: License :: Other/Proprietary License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Topic :: Office/Business :: Financial :: Spreadsheet
Requires-Python: >=3.10
Requires-Dist: httpx<1,>=0.27
Requires-Dist: pyarrow<19,>=16
Requires-Dist: pydantic<3,>=2.7
Requires-Dist: pyyaml<7,>=6
Requires-Dist: rich<14,>=13.7
Requires-Dist: typer<1,>=0.12
Description-Content-Type: text/markdown

# maybeai-sheet-cli

`mbs` is the command-line interface for MaybeAI workbook operations.

This README documents the final canonical resource-first interface and its
contract 1.0 behavior. Compatibility-only command paths are intentionally not
listed.

## Install

For Debian, Ubuntu, and other PEP 668 systems, install the CLI with `pipx`:

```bash
sudo apt install -y pipx python3-venv
pipx ensurepath
pipx install maybeai-sheet-cli
mbs --version
```

For a virtual environment or a development checkout:

```bash
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -U pip
python -m pip install maybeai-sheet-cli
```

Upgrade or remove the package:

```bash
mbs update
pipx upgrade maybeai-sheet-cli
pipx uninstall maybeai-sheet-cli
```

## Requirements

- Python 3.10 or newer.
- `MAYBEAI_API_TOKEN` for API operations.

`mbs --help`, `mbs --version`, and `mbs update --check` do not require a token.

## Configure

```bash
export MAYBEAI_API_TOKEN="YOUR_TOKEN"
export MAYBEAI_BASE_URL="https://a-play-be.maybeai.cn"
```

Global options are accepted before the command:

- `--token` overrides `MAYBEAI_API_TOKEN`.
- `--base-url` overrides `MAYBEAI_BASE_URL`.
- `--output json|table|yaml` selects the renderer.
- `--timeout SECONDS` sets the HTTP timeout.
- `--verbose` writes diagnostic details to stderr.

Canonical commands use `--target` and stable MaybeAI workbook URLs. A target
must identify exactly one resource; conflicting selectors, missing metadata,
and ambiguous names fail before a mutation is sent.

During the compatibility releases, retained 0.27 paths (`workbook list`,
`workbook delete`, `workbook calculate`, `workbook create`, `workbook copy`,
`workbook import`, `worksheet import`, the `worksheet` lifecycle commands
`list`, `create`, `rename`, `copy`, `move`, `delete`, `convert-to-base`, and
`history list` / `history read` / `history restore`) select canonical contract
1.0 semantics with `--contract-version 1.0` (or `--target`); without either
they keep their locked 0.27 behavior and output. New canonical
commands (`workbook inspect`, `worksheet inspect`, `worksheet calculate`,
`worksheet config`, `worksheet beautify`) always emit contract 1.0 and do not
need the flag.

For `workbook import`, `--worksheet-name` is the source-selection flag in every
mode and `--target-worksheet-name` names the imported worksheet.
`--source-worksheet-name` is a deprecated alias for `--worksheet-name` and
cannot be combined with it.

## Resource Model

```text
workbook
|- worksheet (Sheet grid or Base worksheet)
|  `- table (Sheet table region or Base table)
`- file, history, sharing, and workflow metadata
```

Canonical target examples:

```bash
WORKBOOK="https://www.maybe.ai/docs/spreadsheets/d/DOC"
SHEET="https://www.maybe.ai/docs/spreadsheets/d/DOC?gid=7"
BASE_TABLE="https://www.maybe.ai/docs/spreadsheets/d/DOC?tid=tbl_orders"
SHEET_TABLE="https://www.maybe.ai/docs/spreadsheets/d/DOC?gid=7&tid=tbl_orders"
```

`gid` identifies a worksheet. `tid` identifies a stable table. A workbook URL
without either selector identifies the workbook itself.

## Command Tree

The following is the documented public command surface. It is kept in sync with
commands shown by `mbs --help`; `worksheet style` is intentionally documented
as a group-level canonical entry rather than expanding its legacy nested
subcommands:

```text
mbs
|- update
|- workbook
|  |- export
|  |- create
|  |- create-from-file
|  |- copy
|  |- import
|  |- calculate
|  |- list
|  |- delete
|  |- search
|  `- inspect
|- worksheet
|  |- import
|  |- list
|  |- create
|  |- convert-to-base
|  |- rename
|  |- delete
|  |- copy
|  |- move
|  |- inspect
|  |- calculate
|  |- check-error
|  |- config
|  |- beautify
|  `- style
|- range
|  |- sort
|  |- read
|  |- write
|  |- clear
|  |- search
|  |- merge
|  |- unmerge
|  |- lineage
|  |- inspect
|  |- style
|  `- note
|     |- read
|     |- set
|     `- clear
|- row
|  |- insert
|  |- delete
|  |- move
|  |- inspect
|  |- config
|  |- style
|  |- lineage
|  `- note
|     |- list
|     |- add
|     |- update
|     `- delete
|- column
|  |- insert
|  |- delete
|  |- move
|  |- inspect
|  |- rename
|  |- config
|  |- style
|  |- batch-update
|  `- lineage
|- chart
|  |- examples
|  |- get
|  |- list
|  |- create-config
|  |- update
|  `- delete
|- pivot
|  |- read
|  |- preview
|  |- upsert
|  `- delete
|- dashboard
|  |- validate
|  |- export-template
|  |- refresh
|  |- create-config
|  |- verify-interactions
|  |- render-probe
|  |- manifest-lite
|  `- manifest
|- formula
|  |- read
|  |- set
|  |- recalculate
|  |- calculate
|  |- lineage
|  `- validate
|- image
|  |- list
|  |- insert
|  |- replace
|  |- set
|  |- read
|  `- delete
|- media
|  `- check
|- history
|  |- list
|  |- read
|  `- restore
|- file
|  |- export
|  |- list
|  `- search
|- table
|  |- sort
|  |- list
|  |- inspect
|  |- schema
|  |- sample
|  |- read
|  |- create
|  |- insert
|  |- update
|  |- clear
|  |- delete
|  |- config
|  `- style
|- sql
|  |- compile
|  |- preview
|  |- query
|  |- materialize
|  |- overwrite
|  |- config
|  |  |- get
|  |  |- set
|  |  `- delete
|  `- migration
|     |- preview
|     `- commit
|- share
|  |- visibility
|  |- grant
|  |- permission
|  |- remove
|  `- list
`- raw
   `- post
```

Compatibility commands remain directly callable for existing integrations, but
are intentionally hidden from help and excluded from this tree. This includes
the legacy root groups (`excel-worksheet`, `excel-table`, `base-table`,
`db-table`, `cell`, `style`, and `sheet`) plus `worksheet image`.

Use `mbs image ...` for image operations in new automation. Do not generate the
hidden `worksheet image ...` alias. For new table writes, use `table insert` or
`table update` according to the required write semantics.


Style operations are resource-local: use `worksheet config` / `worksheet
beautify` for worksheet-level work and `range style`, `row style`, `column
style`, or `table style` for targeted styling. Worksheet behavior such as
filters, frozen panes, headings, and zoom belongs to `worksheet config`, not to
a style operation. Media has no canonical v1 mutation command.

## Command Examples

### Workbook

```bash
mbs workbook list --limit 20
mbs workbook inspect --target "$WORKBOOK"
mbs workbook create --title "Board Pack"
mbs workbook import ./report.xlsx
mbs workbook import "https://static.example.com/report.xlsx"
mbs workbook copy --target "$WORKBOOK" --title "Board Pack Copy"
mbs workbook calculate --target "$WORKBOOK"
mbs workbook delete --target "$WORKBOOK" --yes          # physical purge by default
mbs workbook delete --target "$WORKBOOK" --mode mark --yes  # recoverable for 7 days
```

### Worksheet

```bash
mbs worksheet list --doc-id "$DOC_ID"
mbs worksheet inspect --target "$SHEET"
mbs worksheet calculate --target "$SHEET"
mbs worksheet calculate --target "$BASE_TABLE" --worksheet-name "Orders"
mbs worksheet check-error --target "$SHEET" --range A1:Z100
mbs worksheet create --target "$WORKBOOK" --name "Scenario" --engine sheet
mbs worksheet rename --target "$SHEET" --new-name "Actuals"
mbs worksheet copy --target "$SHEET" --new-name "Actuals Copy"
mbs worksheet move --target "$SHEET" --index 0
mbs worksheet convert-to-base --target "$SHEET" --yes
mbs worksheet delete --target "$SHEET" --yes
```

`worksheet inspect` with a `--gid` (or a `?gid=N` target) returns only that
worksheet's metadata instead of the whole workbook. `worksheet create` accepts
`--engine sheet|base` to create an empty worksheet of the requested engine;
omitting `--engine` uses the backend default (sheet).
`worksheet calculate` recalculates the selected worksheet through the shared
`/api/v1/excel/recalculate_formulas` endpoint. Base targets require the stable
table target (`?tid=...`) and `--worksheet-name`; Sheet targets use `gid` or
`--worksheet-name`.
`worksheet check-error` reads the selected Sheet/SheetTable range and returns
formula error cells plus warnings for formula cells with no cached result. It
is the canonical replacement for `excel-worksheet check-error`; Base targets
are rejected because Base has field formulas rather than a cell grid.

Apply appearance, behavior, or a named preset through the owning worksheet:

```bash
mbs worksheet style \
  --target "$SHEET" \
  --scope used-region \
  --spec worksheet-style.json \
  --verify

mbs worksheet config \
  --target "$SHEET" \
  --freeze-rows 1 \
  --freeze-columns 2 \
  --gridlines hidden \
  --zoom 100

mbs worksheet beautify \
  --target "$SHEET" \
  --preset finance-default \
  --verify
```

For `--spec`, use the canonical configuration keys below. The legacy
`auto_filter`, `freeze_panes`, `gridlines`, `headings`, `zoom`, `view_id`,
`field_order`, and `hidden_field_ids` keys remain accepted as compatibility
input, but command output is normalized to this form:

```json
{
  "layout": {
    "freeze": {"rows": 1, "columns": 0},
    "gridlines": {"visible": false},
    "headings": {"visible": true},
    "zoom": 110
  },
  "filter": {
    "enabled": true,
    "range": "A1:H100",
    "conditions": [{"field_id": "col_status", "op": "in", "value": ["open"]}]
  },
  "view": {
    "id": "optional-view-id",
    "name": "Grid view",
    "fields": {"order": ["col_status"], "hidden": ["col_internal"]},
    "sorts": [{"field_id": "col_status", "direction": "asc"}]
  }
}
```

`layout.*` and `filter.range` are Sheet-only. `filter.conditions` and
`view.*` are Base-only and use `--doc-id` plus `--table-id`; a `gid` is not
required. Requests containing unsupported properties fail before mutation.

### Table

```bash
mbs table list --doc-id "$DOC_ID"
mbs table list --doc-id "$DOC_ID" --gid "$GID"
mbs table inspect --target "$SHEET_TABLE"
mbs table schema --target "$SHEET_TABLE"
mbs table sample --target "$SHEET_TABLE" --limit 20
mbs table read \
  --target "$SHEET_TABLE" \
  --all \
  --order-by order_id \
  --frame-out /tmp/orders.parquet

mbs table create \
  --target "$WORKBOOK" \
  --table-name Orders \
  --engine base \
  --frame-in orders.parquet

mbs table create \
  --target "$WORKBOOK" \
  --table-name Orders \
  --sql-file orders.sql

mbs table create \
  --target "$WORKBOOK" \
  --table-name Orders \
  --source-target "$SOURCE_WORKBOOK" \
  --worksheet-name Sheet1 \
  --range A1:D100

mbs table insert \
  --target "$BASE_TABLE" \
  --frame-in new_orders.csv \
  --idempotency-key import-20260820

mbs table update \
  --target "$BASE_TABLE" \
  --frame-in corrected_orders.json \
  --key order_id \
  --expected-revision 7

mbs table style \
  --target "$SHEET_TABLE" \
  --section header \
  --spec table-style.json

mbs table delete --target "$BASE_TABLE" --yes

# Clear Base table records while keeping fields/schema
mbs table clear --target "$BASE_TABLE" --yes --verify
```

`table update` is strict and update-only. Every key must resolve to exactly one
existing row; a missing or duplicate key rejects the complete batch. It never
silently inserts a row. `table delete` removes the table object, not selected
rows. `table clear` removes all Base table records/content while preserving the
table fields/schema; it is destructive and requires `--yes` (or `--dry-run`).

The discovery commands `workbook list`, `worksheet list`, and `table list` use
their own identity and filter options and do not accept `--target`. `table list`
can be scoped with `--gid` or `--worksheet-name`.

`table list` always returns a worksheet-first result. Every returned worksheet
has a `tables` array, including an empty array when the worksheet has no table:

```json
{
  "worksheet_count": 2,
  "table_count": 1,
  "worksheets": [
    {
      "gid": 19,
      "worksheet_name": "Data",
      "engine": "sheet",
      "index": 3,
      "worksheet_url": "https://www.maybe.ai/docs/spreadsheets/d/DOC_ID?gid=19",
      "tables": [{"table_id": "tbl_123", "range_address": "A1:D9"}]
    },
    {
      "gid": 20,
      "worksheet_name": "Notes",
      "engine": "sheet",
      "index": 4,
      "worksheet_url": "https://www.maybe.ai/docs/spreadsheets/d/DOC_ID?gid=20",
      "tables": []
    }
  ]
}
```

Common mutation controls are `--expected-revision`, `--idempotency-key`,
`--dry-run`, and `--verify/--no-verify`. Canonical mutations verify by default.

Table frame files use their extension: `.parquet`, `.csv`, or `.json`. JSON is
an array of objects, CSV uses its first row as the header, and Parquet uses
Arrow scalar columns. `table read --all` follows backend cursors and writes one
combined frame; `--order-by` is sent to the backend and returns a capability
error when the selected driver cannot order table reads. The deprecated hidden
`--rows` option remains only as a JSON migration alias; new scripts should use
`--frame-in`.

### Range, row, and column

```bash
mbs range inspect --target "$SHEET" --range A1:H20
mbs range read --target "$SHEET" --range A1:H100
mbs range write --target "$SHEET" --range A1:H100 --values values.json
mbs range clear --target "$SHEET" --range A2:H100 --yes
mbs range note read --target "$SHEET" --range B2
mbs range note set --target "$SHEET" --range B2 --text "Reviewed"
mbs range note clear --target "$SHEET" --range B2
mbs range search --target "$SHEET" --range A1:Z1000 --query revenue
mbs range style --target "$SHEET" --range C2:F100 --spec range-style.json
mbs range lineage --target "$SHEET" --range B2:G20 --max-cells 100

# The CLI currently emits a 1x1 note matrix for set and clear, so those
# commands require a single A1 cell. The update_note API itself supports a
# range-sized note matrix; read supports an A1 range. Legacy `mbs cell
# note-get`, `mbs cell note-set`, and `mbs cell note-clear` remain
# compatibility-only.

mbs row insert --target "$SHEET" --rows 10 --count 2
mbs row delete --target "$SHEET" --rows 10:11 --yes
mbs row move --target "$SHEET" --rows 10:11 --destination 20
mbs row style --target "$SHEET" --rows 1:3 --spec header-rows.json
mbs row note list --target "$BASE_TABLE" --record-id rec_123
mbs row note add --target "$BASE_TABLE" --record-id rec_123 --text "Follow up"
mbs row note update --target "$BASE_TABLE" --record-id rec_123 --note-id note_123 --text "Updated"
mbs row note delete --target "$BASE_TABLE" --record-id rec_123 --note-id note_123 --yes

mbs column insert --target "$SHEET" --columns C --count 2
mbs column delete --target "$SHEET" --columns C:D --yes
mbs column move --target "$SHEET" --columns C:F --destination H
mbs column rename --target "$BASE_TABLE" --column amount --new-name "Gross Amount"
mbs column rename --target "$SHEET" --column C --new-name "Gross Amount" --header-row 1
mbs column config --target "$BASE_TABLE" --column status --required --unique
mbs column config --target "$SHEET" --column C --width 140px --number-format "#,##0.00"
mbs column style --target "$SHEET" --columns C:F --spec amount-columns.json

# `base-field-updates.json` is a JSON array of existing Base field update objects.
# Use stable `field_id` values returned by `mbs table schema` when available.
mbs column batch-update \
  --target "$BASE_TABLE" \
  --updates base-field-updates.json \
  --expected-revision "$REVISION" \
  --verify

# Unified explicit style write: ranges in Sheet mode, fields in Base mode.
mbs worksheet style format --target "$SHEET" --range A1:F1 --style header-style.json --verify
mbs worksheet style format --target "$BASE_TABLE" --field amount --formatter "0.00" --verify
```

Range, row, and column operations require a Sheet grid or Sheet table target
where the requested capability exists. Unsupported Base operations fail before
any mutation.

`range note` reads or changes the note attached to one Sheet cell: `--range`
must identify exactly one A1 cell, such as `B2`. Base notes use `row note` and
are attached to a Base record ID. The `cell` group remains a hidden compatibility
group for legacy scripts, not a new command recommendation.

`column rename` and `column config` are engine-aware canonical adapters. Base
accepts `--column NAME` as a friendly exact field-name selector (with
`--field NAME` and `--field-id ID` also supported); the adapter resolves names
to stable field IDs before writing native field metadata. Sheet and SheetTable
use `--column` with an A1 column selector. Rename changes only the Sheet header
cell, while config changes supported display properties (`--width`,
`--autofit`, `--hidden`, `--number-format`). Base config supports typed field
properties (`--field-type`, `--required`, `--unique`, `--default`, and
`--options`); type changes require `--allow-type-change`.

### Formula and lineage

```bash
mbs formula read --target "$SHEET" --cell G2
mbs formula validate --target "$BASE_TABLE" --field gross_margin --expression 'revenue - cost'
mbs formula set --target "$BASE_TABLE" --field gross_margin --expression 'revenue - cost'
mbs formula validate --target "$SHEET" --cell G2 --expression '=E2-F2'
mbs formula set --target "$SHEET" --range G2:G100 --expression '=E2-F2'
mbs formula calculate --target "$SHEET" --cell G2
mbs formula recalculate --target "$WORKBOOK"
mbs formula lineage --target "$SHEET" --cell G2
mbs column lineage --target "$SHEET" --columns C:F --within A1:Z100
```

Base formulas use a field selector and the Base expression language. Sheet
formulas use a cell or range selector and the Excel expression language. The CLI
does not translate expressions between engines.

### File, SQL, sharing, and escape hatch

```bash
mbs file export --target "$WORKBOOK" --out workbook.xlsx
mbs file list --target "$WORKBOOK"

# Validate SQL and inspect its rewritten query/source references without writing results.
mbs sql compile --target "$WORKBOOK" --sql-file result.sql --output json
mbs sql query --target "$WORKBOOK" --sql-file result.sql --limit 100 --output table
mbs sql query --target "$WORKBOOK" --sql-file result.sql --all \
  --order-by order_id --frame-out /tmp/query.parquet
# A table selector is resolved to its worksheet before SQL runs via the workbook endpoint.
mbs sql query --target "$WORKBOOK?table=Sheet6" --sql-file result.sql --all
mbs sql preview --target "$WORKBOOK" --sql-file result.sql --output table
mbs sql materialize --target "$WORKBOOK?table=S_orders" \
  --sql-file result.sql --mode create --schema schema.json --verify
mbs sql overwrite --target "$SHEET" --sql-file result.sql --verify

mbs history list --target "$WORKBOOK" --limit 10
mbs history read --target "$WORKBOOK" --version v42 --range A1:D20
mbs history restore --target "$WORKBOOK" --version 42 --yes --reason "rollback"
mbs share grant --target "$WORKBOOK" --email teammate@example.com --permission viewer

mbs raw post /api/v1/excel/read_sheet --body request.json
```

Chart, pivot, dashboard, and image workflows use their own typed JSON
specifications and the resource targets shown above. They remain separate from
table-driver semantics; they do not introduce alternate worksheet or table
command prefixes.

## Input Rules

- Use a stable `--target` URI for canonical resource operations. Discovery
  commands (`workbook list`, `worksheet list`, and `table list`) use their
  explicit identity options instead.
- A workbook target has only the document identifier.
- A worksheet target has `gid` or a metadata-resolved unique worksheet name.
- A table target has a stable `tid`, optionally combined with its worksheet `gid`.
- Conflicting selectors are errors; there is no precedence rule that hides a
  conflict.
- A mutation must resolve exactly one existing target before it starts.
- A create operation must resolve one parent workbook and prove the proposed
  destination absent.
- JSON files passed to `--rows`, `--values`, `--spec`, or `--body` must be valid
  JSON with the shape required by that operation.

## Output and Reliability

Canonical commands emit one versioned result envelope with
`contract_version: "1.0"`. JSON is the default output; `table` and `yaml` render
the same operation result. Diagnostics and warnings go to stderr.

Canonical mutations verify by default. Idempotency keys, expected revisions,
bounded retries, and post-transmission reconciliation are handled by the
execution session. An uncertain mutation is never silently reported as a
success.

## Development

```bash
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -e .
python -m unittest discover -s tests -v
```

The canonical interface is defined in
`docs/superpowers/specs/2026-08-19-mbs-table-driver-cli-design.md`.

### Sorting

```bash
mbs range sort --target "$SHEET" --range A1:D100 --by B:asc --by C:desc
mbs range sort --target "$SHEET" --range A2:D100 --by B:desc --no-header
mbs table sort --target "$BASE_TABLE" --by fld_priority:desc --by fld_name:asc
mbs table sort --doc-id "$DOC_ID" --table-id "$TABLE_ID" --view-id "$VIEW_ID" --clear
```

`range sort` uses native, stable Sheet sorting within the bounded A1 rectangle.
Keys are absolute worksheet column letters, in priority order. The first row is
kept in place by default; `--no-header` includes it. It works on Sheet grids and
Sheet tables. No client-side read/rewrite is performed. Native sort requires the
backend `/api/v1/excel/sort_range` route. The result reports verification as
unavailable; read the range afterward for independent verification. Blanks sort
last in both directions. The Sheet workbook path requires cached results for
formula-valued keys and rejects unsupported structures (including merged cells,
comments/hyperlinks, array literals, and implicit `@` formulas) before mutation.

`table sort` changes a Base view's sort criteria, using stable field IDs. Omitting
`--view-id` selects the default view. It reads the view, preserves its name, type,
filters, field order, and hidden fields, and saves with the read revision to detect
concurrent changes. Default verification reads back both sort criteria and
preserved settings. `--clear` removes all criteria and cannot be combined with
`--by`. Both commands support `--dry-run` and `--verify/--no-verify`.
If the verification read fails after a Base view save, the command reports that
the sort was saved and does not retry the mutation.
