From 3d3e2c7f10ca0a2ef020cd7eceacada9e437b4c5 Mon Sep 17 00:00:00 2001 From: xiongyuanwen-byted Date: Wed, 20 May 2026 17:46:49 +0800 Subject: [PATCH] refactor(sheets): build shortcut flags generically from flag-defs.json MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace flag-descriptions.en.json with the richer flag-defs.json (full flag definitions: type / default / enum / input / hidden / required / kind) synced from sheet-skill-spec. Add flagsFor(command) to materialize each shortcut's []common.Flag straight from the JSON, skipping system-kind flags the framework injects. Migrate every sheets shortcut (including the CRUD/list/dim/merge/ visibility factories) to Flags: flagsFor("+command"), dropping all hand-written flag literals plus the now-dead publicTokenFlags / publicSheetFlags / styleFlatFlags helpers and enum vars. A coverage test locks the Go-flags-match-JSON contract. Align Go with the new spec where they diverged: +cells-get --ranges → --range, font-size int → float64, +filter-view-create --range now required, +sheet-create row/col-count defaults 200/20. --- shortcuts/sheets/data/flag-defs.json | 4598 +++++++++++++++++ .../sheets/data/flag-descriptions.en.json | 634 --- shortcuts/sheets/execute_paths_test.go | 2 +- shortcuts/sheets/flag_defs.go | 94 + shortcuts/sheets/flag_defs_test.go | 142 + shortcuts/sheets/flag_desc.go | 71 - shortcuts/sheets/flag_desc_test.go | 112 - shortcuts/sheets/flag_schema.go | 6 +- shortcuts/sheets/helpers.go | 53 +- shortcuts/sheets/lark_sheet_batch_update.go | 29 +- shortcuts/sheets/lark_sheet_object_crud.go | 130 +- .../sheets/lark_sheet_object_crud_test.go | 2 +- shortcuts/sheets/lark_sheet_object_list.go | 15 +- .../sheets/lark_sheet_range_operations.go | 75 +- shortcuts/sheets/lark_sheet_read_data.go | 32 +- shortcuts/sheets/lark_sheet_read_data_test.go | 2 +- shortcuts/sheets/lark_sheet_search_replace.go | 21 +- .../sheets/lark_sheet_sheet_structure.go | 62 +- shortcuts/sheets/lark_sheet_workbook.go | 44 +- shortcuts/sheets/lark_sheet_workbook_test.go | 8 +- shortcuts/sheets/lark_sheet_write_cells.go | 38 +- shortcuts/sheets/shortcuts.go | 1 - .../references/lark-sheets-batch-update.md | 63 +- .../references/lark-sheets-chart.md | 10 +- .../lark-sheets-conditional-format.md | 20 +- .../references/lark-sheets-filter-view.md | 20 +- .../references/lark-sheets-filter.md | 10 +- .../references/lark-sheets-float-image.md | 62 +- .../references/lark-sheets-pivot-table.md | 18 +- .../lark-sheets-range-operations.md | 54 +- .../references/lark-sheets-read-data.md | 24 +- .../references/lark-sheets-search-replace.md | 29 +- .../references/lark-sheets-sheet-structure.md | 58 +- .../references/lark-sheets-sparkline.md | 10 +- .../references/lark-sheets-workbook.md | 38 +- .../references/lark-sheets-write-cells.md | 66 +- 36 files changed, 5162 insertions(+), 1491 deletions(-) create mode 100644 shortcuts/sheets/data/flag-defs.json delete mode 100644 shortcuts/sheets/data/flag-descriptions.en.json create mode 100644 shortcuts/sheets/flag_defs.go create mode 100644 shortcuts/sheets/flag_defs_test.go delete mode 100644 shortcuts/sheets/flag_desc.go delete mode 100644 shortcuts/sheets/flag_desc_test.go diff --git a/shortcuts/sheets/data/flag-defs.json b/shortcuts/sheets/data/flag-defs.json new file mode 100644 index 000000000..7e8a0d2f1 --- /dev/null +++ b/shortcuts/sheets/data/flag-defs.json @@ -0,0 +1,4598 @@ +{ + "+workbook-info": { + "risk": "read", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet locator" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet locator" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+sheet-create": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "title", + "kind": "own", + "type": "string", + "required": "required", + "desc": "New sheet title" + }, + { + "name": "index", + "kind": "own", + "type": "int", + "required": "optional", + "desc": "Insert position; appended to the end when omitted", + "default": "-1" + }, + { + "name": "row-count", + "kind": "own", + "type": "int", + "required": "optional", + "desc": "Initial row count (default 200, max 50000)", + "default": "200" + }, + { + "name": "col-count", + "kind": "own", + "type": "int", + "required": "optional", + "desc": "Initial column count (default 20, max 200)", + "default": "20" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+sheet-delete": { + "risk": "high-risk-write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "yes", + "kind": "system", + "type": "bool", + "required": "required", + "desc": "Confirm high-risk write (exit code 10 without this flag)" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+sheet-rename": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "title", + "kind": "own", + "type": "string", + "required": "required", + "desc": "New title" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+sheet-move": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "index", + "kind": "own", + "type": "int", + "required": "required", + "desc": "Target position (0-based)" + }, + { + "name": "source-index", + "kind": "own", + "type": "int", + "required": "optional", + "desc": "Source position (0-based); optional. If omitted, the CLI runtime derives it from the current workbook index of `--sheet-id` / `--sheet-name`", + "default": "-1" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+sheet-copy": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "title", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Copy title; auto-generated by the server when omitted" + }, + { + "name": "index", + "kind": "own", + "type": "int", + "required": "optional", + "desc": "Insert position for the copy (0-based); appended to the end when omitted", + "default": "-1" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+sheet-hide": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+sheet-unhide": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+sheet-set-tab-color": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "color", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Hex color like `#FF0000`; pass empty string `\"\"` to clear" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+workbook-create": { + "risk": "write", + "flags": [ + { + "name": "title", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Spreadsheet title" + }, + { + "name": "folder-token", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Target folder token; placed at the drive root when omitted" + }, + { + "name": "headers", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Header row as a JSON array: `[\"Col A\",\"Col B\"]`", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "values", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Initial data as a 2D JSON array: `[[\"alice\",95]]`", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+workbook-export": { + "risk": "read", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "file-extension", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Export file format; `csv` mode requires `--sheet-id`", + "default": "xlsx", + "enum": [ + "xlsx", + "csv" + ] + }, + { + "name": "sheet-id", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Required only in csv mode: the sheet reference_id to export" + }, + { + "name": "output-path", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Local save path; export is triggered but not downloaded when omitted" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+sheet-info": { + "risk": "read", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "include", + "kind": "own", + "type": "string_slice", + "required": "optional", + "desc": "Comma-separated structure info categories to return", + "enum": [ + "merges", + "row_heights", + "col_widths", + "hidden_rows", + "hidden_cols", + "groups", + "frozen" + ] + }, + { + "name": "range", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Limit structure info to this A1 range; whole sheet when omitted" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+dim-insert": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "dimension", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Dimension (row or column)", + "enum": [ + "row", + "column" + ] + }, + { + "name": "start", + "kind": "own", + "type": "int", + "required": "required", + "desc": "Insert start position (0-based)" + }, + { + "name": "end", + "kind": "own", + "type": "int", + "required": "required", + "desc": "Insert end position (exclusive)" + }, + { + "name": "inherit-style", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Style inheritance for the new row/column: `before` (from preceding) / `after` (from following) / `none` (default)", + "default": "none", + "enum": [ + "before", + "after", + "none" + ] + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+dim-delete": { + "risk": "high-risk-write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "dimension", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Dimension (row or column)", + "enum": [ + "row", + "column" + ] + }, + { + "name": "start", + "kind": "own", + "type": "int", + "required": "required", + "desc": "Start position (0-based)" + }, + { + "name": "end", + "kind": "own", + "type": "int", + "required": "required", + "desc": "End position (exclusive)" + }, + { + "name": "yes", + "kind": "system", + "type": "bool", + "required": "required", + "desc": "Confirm destructive write (exit code 10 without this flag); row/column deletion is irreversible" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+dim-hide": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "dimension", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Dimension (row or column)", + "enum": [ + "row", + "column" + ] + }, + { + "name": "start", + "kind": "own", + "type": "int", + "required": "required", + "desc": "Start position (0-based, inclusive)" + }, + { + "name": "end", + "kind": "own", + "type": "int", + "required": "required", + "desc": "End position (0-based, inclusive)" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+dim-unhide": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "dimension", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Dimension (row or column)", + "enum": [ + "row", + "column" + ] + }, + { + "name": "start", + "kind": "own", + "type": "int", + "required": "required", + "desc": "Start position (0-based, inclusive)" + }, + { + "name": "end", + "kind": "own", + "type": "int", + "required": "required", + "desc": "End position (0-based, inclusive)" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+dim-freeze": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "dimension", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Dimension (row or column)", + "enum": [ + "row", + "column" + ] + }, + { + "name": "count", + "kind": "own", + "type": "int", + "required": "required", + "desc": "Freeze the first N rows/columns; pass 0 to unfreeze" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+dim-group": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "dimension", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Dimension (row or column)", + "enum": [ + "row", + "column" + ] + }, + { + "name": "start", + "kind": "own", + "type": "int", + "required": "required", + "desc": "Start position (0-based, inclusive)" + }, + { + "name": "end", + "kind": "own", + "type": "int", + "required": "required", + "desc": "End position (0-based, inclusive)" + }, + { + "name": "depth", + "kind": "own", + "type": "int", + "required": "optional", + "desc": "Nesting level (used by `+dim-group`); default 1", + "default": "1" + }, + { + "name": "group-state", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Initial group expand state", + "default": "expand", + "enum": [ + "expand", + "fold" + ] + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+dim-ungroup": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "dimension", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Dimension (row or column)", + "enum": [ + "row", + "column" + ] + }, + { + "name": "start", + "kind": "own", + "type": "int", + "required": "required", + "desc": "Start position (0-based, inclusive)" + }, + { + "name": "end", + "kind": "own", + "type": "int", + "required": "required", + "desc": "End position (0-based, inclusive)" + }, + { + "name": "depth", + "kind": "own", + "type": "int", + "required": "optional", + "desc": "Nesting level (used by `+dim-group`); default 1", + "default": "1" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+dim-move": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "dimension", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Dimension (row or column)", + "enum": [ + "row", + "column" + ] + }, + { + "name": "start", + "kind": "own", + "type": "int", + "required": "required", + "desc": "Source range start position (0-based, inclusive)" + }, + { + "name": "end", + "kind": "own", + "type": "int", + "required": "required", + "desc": "Source range end position (0-based, inclusive)" + }, + { + "name": "target", + "kind": "own", + "type": "int", + "required": "required", + "desc": "Destination position (move target inserts before this index; 0-based)" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+cells-get": { + "risk": "read", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "range", + "kind": "own", + "type": "string_array", + "required": "required", + "desc": "A1 range, e.g. `Sheet1!A1:F10`" + }, + { + "name": "include", + "kind": "own", + "type": "string_slice", + "required": "optional", + "desc": "Comma-separated info categories to include", + "enum": [ + "value", + "formula", + "style", + "comment", + "data_validation" + ] + }, + { + "name": "cell-limit", + "kind": "own", + "type": "int", + "required": "optional", + "desc": "Safety cap; default 5000", + "default": "5000", + "hidden": true + }, + { + "name": "max-chars", + "kind": "own", + "type": "int", + "required": "optional", + "desc": "Safety cap; default 200000", + "default": "200000", + "hidden": true + }, + { + "name": "skip-hidden", + "kind": "own", + "type": "bool", + "required": "optional", + "desc": "Skip hidden rows and columns; default `false`" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+dropdown-get": { + "risk": "read", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "range", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Target range (A1 notation; must include the sheet prefix, e.g. `sheet1!A2:A100`)" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+csv-get": { + "risk": "read", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "range", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "A1 range; reads the whole sheet's `current_region` when omitted" + }, + { + "name": "value-render-option", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Cell value render mode", + "default": "formatted_value", + "enum": [ + "formatted_value", + "raw_value", + "formula" + ] + }, + { + "name": "max-rows", + "kind": "own", + "type": "int", + "required": "optional", + "desc": "Safety cap; default 100000", + "default": "100000", + "hidden": true + }, + { + "name": "max-chars", + "kind": "own", + "type": "int", + "required": "optional", + "desc": "Safety cap; default 200000", + "default": "200000", + "hidden": true + }, + { + "name": "include-row-prefix", + "kind": "own", + "type": "bool", + "required": "optional", + "desc": "Whether to prefix each row with `[row=N]`; default `true`", + "default": "true" + }, + { + "name": "skip-hidden", + "kind": "own", + "type": "bool", + "required": "optional", + "desc": "Skip hidden rows and columns; default `false`" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "Print the request path and parameters without executing" + } + ] + }, + "+cells-search": { + "risk": "read", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "find", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Text to find (interpreted as regex when `--regex` is set)" + }, + { + "name": "range", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Search range (A1 notation); whole sheet when omitted" + }, + { + "name": "match-case", + "kind": "own", + "type": "bool", + "required": "optional", + "desc": "Case-sensitive match" + }, + { + "name": "match-entire-cell", + "kind": "own", + "type": "bool", + "required": "optional", + "desc": "Match the entire cell content" + }, + { + "name": "regex", + "kind": "own", + "type": "bool", + "required": "optional", + "desc": "Interpret `--find` as a regex pattern" + }, + { + "name": "include-formulas", + "kind": "own", + "type": "bool", + "required": "optional", + "desc": "Also search within formula text" + }, + { + "name": "max-matches", + "kind": "own", + "type": "int", + "required": "optional", + "desc": "Safety cap; default 5000", + "default": "5000", + "hidden": true + }, + { + "name": "offset", + "kind": "own", + "type": "int", + "required": "optional", + "desc": "Skip the first N matches (for pagination); default 0", + "default": "0" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+cells-replace": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "find", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Text to find for replacement" + }, + { + "name": "replacement", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Replacement text; pass empty string `\"\"` to delete matched content" + }, + { + "name": "range", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Replace range (A1 notation); whole sheet when omitted" + }, + { + "name": "match-case", + "kind": "own", + "type": "bool", + "required": "optional", + "desc": "Case-sensitive match" + }, + { + "name": "match-entire-cell", + "kind": "own", + "type": "bool", + "required": "optional", + "desc": "Match the entire cell content" + }, + { + "name": "regex", + "kind": "own", + "type": "bool", + "required": "optional", + "desc": "Interpret `--find` as a regex pattern" + }, + { + "name": "include-formulas", + "kind": "own", + "type": "bool", + "required": "optional", + "desc": "Also replace within formula text" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "Required preflight: outputs `would_replace_count` for user confirmation before the actual replace" + } + ] + }, + "+cells-set": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "range", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Write range (A1 notation)" + }, + { + "name": "cells", + "kind": "own", + "type": "string", + "required": "required", + "desc": "JSON 2D array `[[{cell},...],...]`, dimensions must match `--range`; each cell may carry `value` / `formula` / `cell_styles` / `note` / `rich_text` (incl. `type=\"embed-image\"` in-cell image); run `--print-schema` for full fields", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "allow-overwrite", + "kind": "own", + "type": "bool", + "required": "optional", + "desc": "Allow overwriting non-empty cells (default true); set false to error if any target cell is non-empty", + "default": "true" + }, + { + "name": "max-cells", + "kind": "own", + "type": "int", + "required": "optional", + "desc": "Safety cap; default 50000", + "default": "50000", + "hidden": true + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+cells-set-style": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "range", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Target range (A1 notation, e.g. `A1:B2`)" + }, + { + "name": "background-color", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Background color (hex, e.g. `#ffffff`)" + }, + { + "name": "font-color", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Font color (hex, e.g. `#000000`)" + }, + { + "name": "font-size", + "kind": "own", + "type": "float64", + "required": "optional", + "desc": "Font size in px (e.g. 10, 12, 14)" + }, + { + "name": "font-style", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Font style", + "enum": [ + "normal", + "italic" + ] + }, + { + "name": "font-weight", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Font weight", + "enum": [ + "normal", + "bold" + ] + }, + { + "name": "font-line", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Font line style", + "enum": [ + "none", + "underline", + "line-through" + ] + }, + { + "name": "horizontal-alignment", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Horizontal alignment", + "enum": [ + "left", + "center", + "right" + ] + }, + { + "name": "vertical-alignment", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Vertical alignment", + "enum": [ + "top", + "middle", + "bottom" + ] + }, + { + "name": "word-wrap", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Word-wrap strategy", + "enum": [ + "overflow", + "auto-wrap", + "word-clip" + ] + }, + { + "name": "number-format", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Number format pattern (e.g. text `@`, number `0.00`, currency `$#,##0.00`, date `mm/dd/yyyy`)" + }, + { + "name": "border-styles", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Border config JSON: `{ top: {style,color,weight}, bottom: ..., left: ..., right: ... }`; same shape for all 4 sides", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+cells-set-image": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "range", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Target cell (A1 notation; must be a single cell, e.g. `A1`; start and end must be identical)" + }, + { + "name": "image", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Local image path (PNG / JPEG / JPG / GIF / BMP / JFIF / EXIF / TIFF / BPG / HEIC)" + }, + { + "name": "name", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Image file name (with extension); defaults to the basename of `--image`" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+dropdown-set": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "range", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Target range (A1 notation, e.g. `A2:A100`)" + }, + { + "name": "options", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Options as a JSON array, e.g. `[\"opt1\",\"opt2\"]`; up to 500 items, each ≤100 chars, no commas", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "colors", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "RGB hex color array (e.g. `[\"#1FB6C1\",\"#F006C2\"]`); length must equal `--options`", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "multiple", + "kind": "own", + "type": "bool", + "required": "optional", + "desc": "Enable multi-select; default `false`" + }, + { + "name": "highlight", + "kind": "own", + "type": "bool", + "required": "optional", + "desc": "Color-highlight options; default `false`" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+csv-put": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "start-cell", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Top-left A1 anchor (e.g. `Sheet1!A1`); the bottom-right is inferred from CSV row/column counts", + "default": "A1" + }, + { + "name": "csv", + "kind": "own", + "type": "string", + "required": "required", + "desc": "RFC 4180 CSV text; plain values only (no formulas / styles / comments)", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "allow-overwrite", + "kind": "own", + "type": "bool", + "required": "optional", + "desc": "Allow overwriting (default true); set false to error if any target cell is non-empty", + "default": "true" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+cells-clear": { + "risk": "high-risk-write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "range", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Range to clear (A1 notation)" + }, + { + "name": "scope", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Clear scope: `content` (default, values only) / `formats` (formats only) / `all` (values and formats)", + "default": "content", + "enum": [ + "content", + "formats", + "all" + ] + }, + { + "name": "yes", + "kind": "system", + "type": "bool", + "required": "required", + "desc": "Confirm destructive write (exit code 10 without this flag); clear is irreversible" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+cells-merge": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "range", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Range to merge / unmerge (A1 notation)" + }, + { + "name": "merge-type", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Merge direction (`+cells-merge` only)", + "default": "all", + "enum": [ + "all", + "rows", + "columns" + ] + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+cells-unmerge": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "range", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Range to merge / unmerge (A1 notation)" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+rows-resize": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "start", + "kind": "own", + "type": "int", + "required": "required", + "desc": "Start row (0-based, inclusive)" + }, + { + "name": "end", + "kind": "own", + "type": "int", + "required": "required", + "desc": "End row (0-based, inclusive)" + }, + { + "name": "type", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Sizing mode: `pixel` (explicit px value, requires `--size`) / `standard` (reset to default row height) / `auto` (fit content)", + "enum": [ + "pixel", + "standard", + "auto" + ] + }, + { + "name": "size", + "kind": "own", + "type": "int", + "required": "optional", + "desc": "Row height in pixels (e.g. 30 / 40 / 60); required when `--type pixel`, ignored otherwise", + "default": "0" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+cols-resize": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "start", + "kind": "own", + "type": "int", + "required": "required", + "desc": "Start column (0-based, inclusive)" + }, + { + "name": "end", + "kind": "own", + "type": "int", + "required": "required", + "desc": "End column (0-based, inclusive)" + }, + { + "name": "type", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Sizing mode: `pixel` (explicit px value, requires `--size`) / `standard` (reset to default column width)", + "enum": [ + "pixel", + "standard" + ] + }, + { + "name": "size", + "kind": "own", + "type": "int", + "required": "optional", + "desc": "Column width in pixels (e.g. 80 / 120 / 200); required when `--type pixel`, ignored otherwise", + "default": "0" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+range-move": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "source-range", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Source A1 range" + }, + { + "name": "target-sheet-id", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Destination sub-sheet id; defaults to the same sheet as the source" + }, + { + "name": "target-range", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Destination A1 range (anchor cell is enough; size inferred from the source)" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+range-copy": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "source-range", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Source A1 range" + }, + { + "name": "target-sheet-id", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Destination sub-sheet id; defaults to the same sheet as the source" + }, + { + "name": "target-range", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Destination A1 range (anchor cell is enough; size inferred from the source)" + }, + { + "name": "paste-type", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Paste content type (`+range-copy` only)", + "default": "all", + "enum": [ + "values", + "formulas", + "formats", + "all" + ] + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+range-fill": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "source-range", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Fill template range (seed cells for the series)" + }, + { + "name": "target-range", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Destination fill range (A1 notation)" + }, + { + "name": "series-type", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Fill series type", + "default": "auto", + "enum": [ + "auto", + "linear", + "growth", + "date", + "copy" + ] + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+range-sort": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "range", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Sort range (A1 notation; whether the header is included depends on `--has-header`)" + }, + { + "name": "sort-keys", + "kind": "own", + "type": "string", + "required": "required", + "desc": "JSON array: `[{\"column\":\"\",\"ascending\":}, ...]`", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "has-header", + "kind": "own", + "type": "bool", + "required": "optional", + "desc": "Treat the first row as a header and exclude from sort; default `false`" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+batch-update": { + "risk": "high-risk-write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet locator (independent from per-operation sheet locator)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet locator (independent from per-operation sheet locator)" + }, + { + "name": "operations", + "kind": "own", + "type": "string", + "required": "required", + "desc": "JSON array: `[{\"tool_name\":\"set_cell_range\",\"input\":{...}}, ...]`, executed serially; `tool_name` is the underlying tool name (e.g. `set_cell_range` / `clear_cell_range` / `modify_sheet_structure`)", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "continue-on-error", + "kind": "own", + "type": "bool", + "required": "optional", + "desc": "Continue with remaining operations when a sub-operation fails; default false (abort on first failure)" + }, + { + "name": "yes", + "kind": "system", + "type": "bool", + "required": "required", + "desc": "Confirm high-risk write (exit code 10 without this flag)" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "Print the request template for each sub-operation; no network side effects" + } + ] + }, + "+cells-batch-set-style": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "ranges", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Target ranges as a JSON array (e.g. `[\"sheet1!A1:B2\",\"sheet1!D1:D10\"]`); each item must include the sheet prefix; the same style is applied to all ranges", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "background-color", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Background color (hex, e.g. `#ffffff`)" + }, + { + "name": "font-color", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Font color (hex, e.g. `#000000`)" + }, + { + "name": "font-size", + "kind": "own", + "type": "float64", + "required": "optional", + "desc": "Font size in px (e.g. 10, 12, 14)" + }, + { + "name": "font-style", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Font style", + "enum": [ + "normal", + "italic" + ] + }, + { + "name": "font-weight", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Font weight", + "enum": [ + "normal", + "bold" + ] + }, + { + "name": "font-line", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Font line style", + "enum": [ + "none", + "underline", + "line-through" + ] + }, + { + "name": "horizontal-alignment", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Horizontal alignment", + "enum": [ + "left", + "center", + "right" + ] + }, + { + "name": "vertical-alignment", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Vertical alignment", + "enum": [ + "top", + "middle", + "bottom" + ] + }, + { + "name": "word-wrap", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Word-wrap strategy", + "enum": [ + "overflow", + "auto-wrap", + "word-clip" + ] + }, + { + "name": "number-format", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Number format pattern (e.g. text `@`, number `0.00`, currency `$#,##0.00`, date `mm/dd/yyyy`)" + }, + { + "name": "border-styles", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Border config JSON (same shape as in +cells-set-style)", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+dropdown-update": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "ranges", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Target ranges as a JSON array (e.g. `[\"sheet1!A2:A100\"]`); each item must include the sheet prefix", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "options", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Options as a JSON array (e.g. `[\"opt1\",\"opt2\"]`)", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "colors", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Color array (same length as `--options`)", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "multiple", + "kind": "own", + "type": "bool", + "required": "optional", + "desc": "Enable multi-select" + }, + { + "name": "highlight", + "kind": "own", + "type": "bool", + "required": "optional", + "desc": "Color-highlight options" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+dropdown-delete": { + "risk": "high-risk-write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "ranges", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Target ranges as a JSON array (up to 100 items; each must include the sheet prefix)", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "yes", + "kind": "system", + "type": "bool", + "required": "required", + "desc": "Confirm high-risk write (exit code 10 without this flag)" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+chart-list": { + "risk": "read", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "chart-id", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Filter to a single chart reference_id" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+chart-create": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "properties", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Full chart config JSON (`position` / `data` / `properties` etc.); deeply nested, must be passed as JSON", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "Print the request template; no side effects" + } + ] + }, + "+chart-update": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "chart-id", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Target chart reference_id" + }, + { + "name": "properties", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Full or sufficiently complete chart config JSON (read back with `+chart-list` first, then patch)", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+chart-delete": { + "risk": "high-risk-write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "chart-id", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Target chart reference_id" + }, + { + "name": "yes", + "kind": "system", + "type": "bool", + "required": "required", + "desc": "Confirm destructive write (exit code 10 without this flag)" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+pivot-list": { + "risk": "read", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "pivot-table-id", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Filter by id" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+pivot-create": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "properties", + "kind": "own", + "type": "string", + "required": "required", + "desc": "JSON: `{\"data_range\":\"Sheet1!A1:F1000\",\"rows\":[...],\"columns\":[...],\"values\":[...],\"filters\":[...],\"show_row_grand_total\":true,\"show_col_grand_total\":true}`", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "target-sheet-id", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Destination sub-sheet id for the pivot table; auto-creates a new sub-sheet when omitted (recommended)" + }, + { + "name": "target-position", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Destination anchor cell (A1 notation, e.g. `A1`); default `A1`", + "default": "A1" + }, + { + "name": "source", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Pivot table source range (A1 notation; format `SheetName!StartCell:EndCell`, e.g. `Sheet1!A1:D100`)" + }, + { + "name": "range", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Pivot table placement (single A1 anchor for the top-left, e.g. `F1`); placed at the top-left of a newly created sub-sheet when omitted" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+pivot-update": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "pivot-table-id", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Target pivot table id" + }, + { + "name": "properties", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Full or sufficiently complete pivot config (read back with `+pivot-list --pivot-table-id ` first, then patch)", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+pivot-delete": { + "risk": "high-risk-write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "pivot-table-id", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Target pivot table id" + }, + { + "name": "yes", + "kind": "system", + "type": "bool", + "required": "required", + "desc": "Confirm destructive write (exit code 10 without this flag); delete is irreversible" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+cond-format-list": { + "risk": "read", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "rule-id", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Filter by rule id" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+cond-format-create": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "properties", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Rule config JSON: `style` (required, applied on match), `attrs?` (rule-type-dependent params), `has_ref?`. `rule_type` and `ranges` are separate flags", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "rule-type", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Conditional format rule type; takes precedence over the same-named field inside `--properties`", + "enum": [ + "cellValue", + "formula", + "duplicate", + "unique", + "topBottom", + "aboveBelowAverage", + "dataBar", + "colorScale", + "iconSet", + "textContains", + "dateOccurring", + "blankCell", + "errorCell" + ] + }, + { + "name": "ranges", + "kind": "own", + "type": "string", + "required": "required", + "desc": "A1 ranges where the conditional format applies, as a JSON array (e.g. `[\"A1:A100\",\"C2:C50\"]`); takes precedence over the same-named field inside `--properties`", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+cond-format-update": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "rule-id", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Target rule id" + }, + { + "name": "properties", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Rule config JSON, same shape as `+cond-format-create --properties`; update overwrites the entire rule", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "rule-type", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Conditional format rule type; takes precedence over the same-named field inside `--properties`", + "enum": [ + "cellValue", + "formula", + "duplicate", + "unique", + "topBottom", + "aboveBelowAverage", + "dataBar", + "colorScale", + "iconSet", + "textContains", + "dateOccurring", + "blankCell", + "errorCell" + ] + }, + { + "name": "ranges", + "kind": "own", + "type": "string", + "required": "required", + "desc": "A1 ranges where the conditional format applies, as a JSON array (e.g. `[\"A1:A100\",\"C2:C50\"]`); takes precedence over the same-named field inside `--properties`", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+cond-format-delete": { + "risk": "high-risk-write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "rule-id", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Target rule id" + }, + { + "name": "yes", + "kind": "system", + "type": "bool", + "required": "required", + "desc": "Confirm destructive write (exit code 10 without this flag); delete is irreversible" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+filter-list": { + "risk": "read", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+filter-create": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "range", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Filter range (A1 notation, including header row, e.g. `A1:F1000`); do not duplicate the range field inside `--properties`" + }, + { + "name": "properties", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Filter rule JSON: `rules` (required, per-column rule array), `filtered_columns?` (active column index hint). `range` is a separate flag (do not duplicate inside this JSON)", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+filter-update": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "properties", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Filter rule JSON: `rules` and `filtered_columns?`; update overwrites the entire rule set (pass `rules: []` to clear). `range` is a separate flag", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "range", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Range the filter applies to (A1 notation, e.g. `A1:F1000`); takes precedence over the same-named field inside `--properties`" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+filter-delete": { + "risk": "high-risk-write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "yes", + "kind": "system", + "type": "bool", + "required": "required", + "desc": "Confirm destructive write (exit code 10 without this flag); delete is irreversible" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+filter-view-list": { + "risk": "read", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "view-id", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Filter by filter-view reference_id (returns the matching single view)" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+filter-view-create": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "properties", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Filter-view rule JSON: `rules?` (per-column rule array), `filtered_columns?`. `range` and `view_name` are separate flags", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "range", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Range the filter view applies to (A1 notation, e.g. `A1:F1000`); takes precedence over the same-named field inside `--properties`; required on create and must cover the header row" + }, + { + "name": "view-name", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Filter-view name; auto-assigned by the server when omitted on create, kept unchanged when omitted on update; takes precedence over the same-named field inside `--properties`" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+filter-view-update": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "view-id", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Target filter-view reference_id" + }, + { + "name": "properties", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Filter-view rule JSON: `rules?`, `filtered_columns?`. `range` and `view_name` are separate flags; pass at least one of `--properties.rules` / `--range` / `--view-name`", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "range", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Range the filter view applies to (A1 notation, e.g. `A1:F1000`); takes precedence over the same-named field inside `--properties`; omit to keep the current range on update" + }, + { + "name": "view-name", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Filter-view name; auto-assigned by the server when omitted on create, kept unchanged when omitted on update; takes precedence over the same-named field inside `--properties`" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+filter-view-delete": { + "risk": "high-risk-write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "view-id", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Target filter-view reference_id" + }, + { + "name": "yes", + "kind": "system", + "type": "bool", + "required": "required", + "desc": "Confirm high-risk write (exit code 10 without this flag)" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+sparkline-list": { + "risk": "read", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "group-id", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Filter by group_id" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+sparkline-create": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "properties", + "kind": "own", + "type": "string", + "required": "required", + "desc": "JSON: `{config (shared style), sparklines (array of mini-charts)}`; run `--print-schema` for the full structure", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+sparkline-update": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "group-id", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Target group id" + }, + { + "name": "properties", + "kind": "own", + "type": "string", + "required": "required", + "desc": "JSON: `{config, sparklines}`; read back with `+sparkline-list --group-id ` first, then patch; run `--print-schema` for the full structure", + "input": [ + "file", + "stdin" + ] + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+sparkline-delete": { + "risk": "high-risk-write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "group-id", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Target group id" + }, + { + "name": "yes", + "kind": "system", + "type": "bool", + "required": "required", + "desc": "Confirm destructive write (exit code 10 without this flag); delete is irreversible" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+float-image-list": { + "risk": "read", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "float-image-id", + "kind": "own", + "type": "string", + "required": "optional", + "desc": "Filter by id; lists all float images on the sheet when omitted" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+float-image-create": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "image-name", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Image name, including extension (e.g. `logo.png`)" + }, + { + "name": "image-token", + "kind": "own", + "type": "string", + "required": "xor", + "desc": "Image file_token (XOR with `--image-uri`). Common source: `image_token` returned by `+float-image-list`" + }, + { + "name": "image-uri", + "kind": "own", + "type": "string", + "required": "xor", + "desc": "Image reference_id (XOR with `--image-token`); a prefixed string like `<|image|>:abcdef`" + }, + { + "name": "position-row", + "kind": "own", + "type": "int", + "required": "required", + "desc": "Row anchor of the image's top-left corner (0-based)" + }, + { + "name": "position-col", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Column anchor of the image's top-left corner (column letter, e.g. `A` / `B`)" + }, + { + "name": "size-width", + "kind": "own", + "type": "int", + "required": "required", + "desc": "Image width in pixels" + }, + { + "name": "size-height", + "kind": "own", + "type": "int", + "required": "required", + "desc": "Image height in pixels" + }, + { + "name": "offset-row", + "kind": "own", + "type": "int", + "required": "optional", + "desc": "Pixel offset within the anchor row, on top of `--position-row`" + }, + { + "name": "offset-col", + "kind": "own", + "type": "int", + "required": "optional", + "desc": "Pixel offset within the anchor column, on top of `--position-col`" + }, + { + "name": "z-index", + "kind": "own", + "type": "int", + "required": "optional", + "desc": "Image z-index controlling stacking order" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+float-image-update": { + "risk": "write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "float-image-id", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Target float image id" + }, + { + "name": "image-name", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Image name, including extension (e.g. `logo.png`)" + }, + { + "name": "image-token", + "kind": "own", + "type": "string", + "required": "xor", + "desc": "Image file_token (XOR with `--image-uri`). Common source: `image_token` returned by `+float-image-list`" + }, + { + "name": "image-uri", + "kind": "own", + "type": "string", + "required": "xor", + "desc": "Image reference_id (XOR with `--image-token`); a prefixed string like `<|image|>:abcdef`" + }, + { + "name": "position-row", + "kind": "own", + "type": "int", + "required": "required", + "desc": "Row anchor of the image's top-left corner (0-based)" + }, + { + "name": "position-col", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Column anchor of the image's top-left corner (column letter, e.g. `A` / `B`)" + }, + { + "name": "size-width", + "kind": "own", + "type": "int", + "required": "required", + "desc": "Image width in pixels" + }, + { + "name": "size-height", + "kind": "own", + "type": "int", + "required": "required", + "desc": "Image height in pixels" + }, + { + "name": "offset-row", + "kind": "own", + "type": "int", + "required": "optional", + "desc": "Pixel offset within the anchor row, on top of `--position-row`" + }, + { + "name": "offset-col", + "kind": "own", + "type": "int", + "required": "optional", + "desc": "Pixel offset within the anchor column, on top of `--position-col`" + }, + { + "name": "z-index", + "kind": "own", + "type": "int", + "required": "optional", + "desc": "Image z-index controlling stacking order" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + }, + "+float-image-delete": { + "risk": "high-risk-write", + "flags": [ + { + "name": "url", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet URL (XOR with `--spreadsheet-token`)" + }, + { + "name": "spreadsheet-token", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Spreadsheet token (XOR with `--url`)" + }, + { + "name": "sheet-id", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet reference_id (XOR with `--sheet-name`)" + }, + { + "name": "sheet-name", + "kind": "public", + "type": "string", + "required": "xor", + "desc": "Sheet name (XOR with `--sheet-id`)" + }, + { + "name": "float-image-id", + "kind": "own", + "type": "string", + "required": "required", + "desc": "Target float image id" + }, + { + "name": "yes", + "kind": "system", + "type": "bool", + "required": "required", + "desc": "Confirm destructive write (exit code 10 without this flag); delete is irreversible" + }, + { + "name": "dry-run", + "kind": "system", + "type": "bool", + "required": "optional", + "desc": "" + } + ] + } +} diff --git a/shortcuts/sheets/data/flag-descriptions.en.json b/shortcuts/sheets/data/flag-descriptions.en.json deleted file mode 100644 index 22e25ce10..000000000 --- a/shortcuts/sheets/data/flag-descriptions.en.json +++ /dev/null @@ -1,634 +0,0 @@ -{ - "+workbook-info": { - "--url": "Spreadsheet locator", - "--spreadsheet-token": "Spreadsheet locator", - "--include-properties": "Whether to include each sheet's extended properties; default `true`" - }, - "+sheet-create": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--title": "New sheet title", - "--index": "Insert position; appended to the end when omitted", - "--row-count": "Initial row count; default 100", - "--col-count": "Initial column count; default 26" - }, - "+sheet-delete": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--yes": "Confirm high-risk write (exit code 10 without this flag)" - }, - "+sheet-rename": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--title": "New title" - }, - "+sheet-move": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--index": "Target position (0-based)", - "--source-index": "Source position (0-based); optional. If omitted, the CLI runtime derives it from the current workbook index of `--sheet-id` / `--sheet-name`" - }, - "+sheet-copy": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--title": "Copy title; auto-generated by the server when omitted", - "--index": "Insert position for the copy (0-based); appended to the end when omitted" - }, - "+sheet-hide": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)" - }, - "+sheet-unhide": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)" - }, - "+sheet-set-tab-color": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--color": "Hex color like `#FF0000`; pass empty string `\"\"` to clear" - }, - "+workbook-create": { - "--title": "Spreadsheet title", - "--folder-token": "Target folder token; placed at the drive root when omitted", - "--headers": "Header row as a JSON array: `[\"Col A\",\"Col B\"]`", - "--values": "Initial data as a 2D JSON array: `[[\"alice\",95]]`" - }, - "+workbook-export": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--file-extension": "`xlsx` / `csv`; default `xlsx`. `csv` mode requires `--sheet-id`", - "--sheet-id": "Required only in csv mode: the sheet reference_id to export", - "--output-path": "Local save path; export is triggered but not downloaded when omitted" - }, - "+sheet-info": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--include": "Comma-separated subset of `merges` / `row_heights` / `col_widths` / `hidden_rows` / `hidden_cols` / `groups` / `frozen`" - }, - "+dim-insert": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--dimension": "`row` / `column`", - "--start": "Insert start position (0-based)", - "--end": "Insert end position (exclusive)", - "--inherit-style": "Style inheritance for the new row/column: `before` (from preceding) / `after` (from following) / `none` (default)" - }, - "+dim-delete": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--dimension": "`row` / `column`", - "--start": "Start position (0-based)", - "--end": "End position (exclusive)", - "--yes": "Confirm destructive write (exit code 10 without this flag); row/column deletion is irreversible" - }, - "+dim-hide": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--dimension": "`row` / `column`", - "--start": "End position (0-based, inclusive)", - "--end": "End position (0-based, inclusive)" - }, - "+dim-unhide": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--dimension": "`row` / `column`", - "--start": "End position (0-based, inclusive)", - "--end": "End position (0-based, inclusive)" - }, - "+dim-freeze": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--dimension": "`row` / `column`", - "--count": "Freeze the first N rows/columns; pass 0 to unfreeze" - }, - "+dim-group": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--dimension": "`row` / `column`", - "--start": "End position (0-based, inclusive)", - "--end": "End position (0-based, inclusive)", - "--depth": "Nesting level (used by `+dim-group`); default 1" - }, - "+dim-ungroup": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--dimension": "`row` / `column`", - "--start": "End position (0-based, inclusive)", - "--end": "End position (0-based, inclusive)", - "--depth": "Nesting level (used by `+dim-group`); default 1" - }, - "+dim-move": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--dimension": "`row` / `column`", - "--start": "Source range start position (0-based, inclusive)", - "--end": "Source range end position (0-based, inclusive)", - "--target": "Destination position (move target inserts before this index; 0-based)" - }, - "+cells-get": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--range": "A1 range, e.g. `Sheet1!A1:F10`", - "--include": "Comma-separated subset of `value` / `formula` / `style` / `comment` / `data_validation`", - "--cell-limit": "Safety cap; default 5000", - "--max-chars": "Safety cap; default 200000", - "--skip-hidden": "Skip hidden rows and columns; default `false`" - }, - "+dropdown-get": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--range": "Target range (A1 notation; must include the sheet prefix, e.g. `sheet1!A2:A100`)" - }, - "+csv-get": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--range": "A1 range; reads the whole sheet's `current_region` when omitted", - "--value-render-option": "Cell value render mode: `ToString` / `FormattedValue` / `Formula` / `UnformattedValue`", - "--max-rows": "Safety cap; default 100000", - "--max-chars": "Safety cap; default 200000", - "--include-row-prefix": "Whether to prefix each row with `[row=N]`; default `true`", - "--skip-hidden": "Skip hidden rows and columns; default `false`", - "--dry-run": "Print the request path and parameters without executing" - }, - "+cells-search": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--find": "Text to find (interpreted as regex when `--regex` is set)", - "--range": "Search range (A1 notation); whole sheet when omitted", - "--match-case": "Case-sensitive match", - "--match-entire-cell": "Match the entire cell content", - "--regex": "Interpret `--find` as a regex pattern", - "--include-formulas": "Also search within formula text", - "--max-matches": "Safety cap; default 5000" - }, - "+cells-replace": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--find": "Text to find for replacement", - "--replacement": "Replacement text; pass empty string `\"\"` to delete matched content", - "--range": "Replace range (A1 notation); whole sheet when omitted", - "--match-case": "Also replace within formula text", - "--match-entire-cell": "Also replace within formula text", - "--regex": "Also replace within formula text", - "--include-formulas": "Also replace within formula text", - "--dry-run": "Required preflight: outputs `would_replace_count` for user confirmation before the actual replace" - }, - "+cells-set": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--range": "Write range (A1 notation)", - "--cells": "JSON: `{\"values\": [[...], ...]}`; may include `formula` / `cell_styles` / `comments` / `embed_image` rich-cell fields", - "--allow-overwrite": "Allow overwriting non-empty cells; with default `false`, error if any target cell is non-empty", - "--max-cells": "Safety cap; default 50000" - }, - "+cells-set-style": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--range": "Target range (A1 notation, e.g. `A1:B2`)", - "--background-color": "Background color (hex, e.g. `#ffffff`)", - "--font-color": "Font color (hex, e.g. `#000000`)", - "--font-size": "Font size in px (e.g. 10, 12, 14)", - "--font-style": "Font style enum: `normal` / `italic`", - "--font-weight": "Font weight enum: `normal` / `bold`", - "--font-line": "Font line style enum: `none` / `underline` / `line-through`", - "--horizontal-alignment": "Horizontal alignment enum: `left` / `center` / `right`", - "--vertical-alignment": "Vertical alignment enum: `top` / `middle` / `bottom`", - "--word-wrap": "Word-wrap strategy: `overflow` / `auto-wrap` / `word-clip`; default `overflow`", - "--number-format": "Number format pattern (e.g. text `@`, number `0.00`, currency `$#,##0.00`, date `mm/dd/yyyy`)", - "--border-styles": "Border config JSON: `{ top: {style,color,weight}, bottom: ..., left: ..., right: ... }`; same shape for all 4 sides" - }, - "+cells-set-image": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--range": "Target cell (A1 notation; must be a single cell, e.g. `A1`; start and end must be identical)", - "--image": "Local image path (PNG / JPEG / JPG / GIF / BMP / JFIF / EXIF / TIFF / BPG / HEIC)", - "--name": "Image file name (with extension); defaults to the basename of `--image`" - }, - "+dropdown-set": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--range": "Target range (A1 notation, e.g. `A2:A100`)", - "--options": "Options as a JSON array, e.g. `[\"opt1\",\"opt2\"]`; up to 500 items, each ≤100 chars, no commas", - "--colors": "RGB hex color array (e.g. `[\"#1FB6C1\",\"#F006C2\"]`); length must equal `--options`", - "--multiple": "Enable multi-select; default `false`", - "--highlight": "Color-highlight options; default `false`" - }, - "+csv-put": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--range": "Top-left A1 anchor (e.g. `Sheet1!A1`); the bottom-right is inferred from CSV row/column counts", - "--csv": "RFC 4180 CSV text; plain values only (no formulas / styles / comments)", - "--allow-overwrite": "Allow overwriting; with default `false`, error if any target cell is non-empty" - }, - "+cells-clear": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--range": "Range to clear (A1 notation)", - "--scope": "Clear scope: `content` (default, values only) / `formats` (formats only) / `all` (values and formats)", - "--yes": "Confirm destructive write (exit code 10 without this flag); clear is irreversible" - }, - "+cells-merge": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--range": "Range to merge / unmerge (A1 notation)", - "--merge-type": "Merge direction (`+cells-merge` only): `all` / `rows` / `columns`; default `all`" - }, - "+cells-unmerge": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--range": "Range to merge / unmerge (A1 notation)", - "--merge-type": "Merge direction (`+cells-merge` only): `all` / `rows` / `columns`; default `all`" - }, - "+rows-resize": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--start": "Start row (0-based, inclusive)", - "--end": "End row (0-based, inclusive)", - "--type": "Sizing mode: `pixel` (explicit px value, requires `--size`) / `standard` (reset to default row height) / `auto` (fit content)", - "--size": "Row height in pixels (e.g. 30 / 40 / 60); required when `--type pixel`, ignored otherwise" - }, - "+cols-resize": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--start": "Start column (0-based, inclusive)", - "--end": "End column (0-based, inclusive)", - "--type": "Sizing mode: `pixel` (explicit px value, requires `--size`) / `standard` (reset to default column width)", - "--size": "Column width in pixels (e.g. 80 / 120 / 200); required when `--type pixel`, ignored otherwise" - }, - "+range-move": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--source-range": "Source A1 range", - "--target-sheet-id": "Destination sub-sheet id; defaults to the same sheet as the source", - "--target-range": "Destination A1 range (anchor cell is enough; size inferred from the source)", - "--paste-type": "Paste content type (`+range-copy` only): `values` / `formulas` / `formats` / `all`; default `all`" - }, - "+range-copy": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--source-range": "Source A1 range", - "--target-sheet-id": "Destination sub-sheet id; defaults to the same sheet as the source", - "--target-range": "Destination A1 range (anchor cell is enough; size inferred from the source)", - "--paste-type": "Paste content type (`+range-copy` only): `values` / `formulas` / `formats` / `all`; default `all`" - }, - "+range-fill": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--source-range": "Fill template range (seed cells for the series)", - "--target-range": "Destination fill range (A1 notation)", - "--series-type": "Fill series type: `auto` / `linear` / `growth` / `date` / `copy`; default `auto`" - }, - "+range-sort": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--range": "Sort range (A1 notation; whether the header is included depends on `--has-header`)", - "--sort-keys": "Sort keys JSON: `[{\"col\":\"B\",\"order\":\"asc\"},{\"col\":\"D\",\"order\":\"desc\"}]`", - "--has-header": "Treat the first row as a header and exclude from sort; default `false`" - }, - "+batch-update": { - "--url": "Spreadsheet locator (independent from per-operation sheet locator)", - "--spreadsheet-token": "Spreadsheet locator (independent from per-operation sheet locator)", - "--operations": "JSON: `{\"operations\":[{\"tool\":\"set_cell_range\",\"params\":{...}}, ...]}`; executed serially in array order", - "--yes": "Confirm high-risk write (exit code 10 without this flag)", - "--dry-run": "Print the request template for each sub-operation; no network side effects" - }, - "+cells-batch-set-style": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--ranges": "Target ranges as a JSON array (e.g. `[\"sheet1!A1:B2\",\"sheet1!D1:D10\"]`); each item must include the sheet prefix; the same style is applied to all ranges", - "--background-color": "Background color (hex, e.g. `#ffffff`)", - "--font-color": "Font color (hex, e.g. `#000000`)", - "--font-size": "Font size in px (e.g. 10, 12, 14)", - "--font-style": "Font style enum: `normal` / `italic`", - "--font-weight": "Font weight enum: `normal` / `bold`", - "--font-line": "Font line style enum: `none` / `underline` / `line-through`", - "--horizontal-alignment": "Horizontal alignment enum: `left` / `center` / `right`", - "--vertical-alignment": "Vertical alignment enum: `top` / `middle` / `bottom`", - "--word-wrap": "Word-wrap strategy: `overflow` / `auto-wrap` / `word-clip`; default `overflow`", - "--number-format": "Number format pattern (e.g. text `@`, number `0.00`, currency `$#,##0.00`, date `mm/dd/yyyy`)", - "--border-styles": "Border config JSON (same shape as in +cells-set-style)" - }, - "+dropdown-update": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--ranges": "Target ranges as a JSON array (e.g. `[\"sheet1!A2:A100\"]`); each item must include the sheet prefix", - "--options": "Options as a JSON array (e.g. `[\"opt1\",\"opt2\"]`)", - "--colors": "Color array (same length as `--options`)", - "--multiple": "Enable multi-select", - "--highlight": "Color-highlight options" - }, - "+dropdown-delete": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--ranges": "Target ranges as a JSON array (up to 100 items; each must include the sheet prefix)", - "--yes": "Confirm high-risk write (exit code 10 without this flag)" - }, - "+chart-list": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--chart-id": "Filter to a single chart reference_id" - }, - "+chart-create": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--properties": "Full chart config JSON (`position` / `data` / `properties` etc.); deeply nested, must be passed as JSON", - "--dry-run": "Print the request template; no side effects" - }, - "+chart-update": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--chart-id": "Target chart reference_id", - "--properties": "Full or sufficiently complete chart config JSON (read back with `+chart-list` first, then patch)" - }, - "+chart-delete": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--chart-id": "Target chart reference_id", - "--yes": "Confirm destructive write (exit code 10 without this flag)" - }, - "+pivot-list": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--pivot-table-id": "Filter by id" - }, - "+pivot-create": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--properties": "JSON: `{\"data_range\":\"Sheet1!A1:F1000\",\"rows\":[...],\"columns\":[...],\"values\":[...],\"filters\":[...],\"show_row_grand_total\":true,\"show_col_grand_total\":true}`", - "--target-sheet-id": "Destination sub-sheet id for the pivot table; auto-creates a new sub-sheet when omitted (recommended)", - "--target-position": "Destination anchor cell (A1 notation, e.g. `A1`); default `A1`", - "--source": "Pivot table source range (A1 notation; format `SheetName!StartCell:EndCell`, e.g. `Sheet1!A1:D100`)", - "--range": "Pivot table placement (single A1 anchor for the top-left, e.g. `F1`); placed at the top-left of a newly created sub-sheet when omitted" - }, - "+pivot-update": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--pivot-table-id": "Target pivot table id", - "--properties": "Full or sufficiently complete pivot config (read back with `+pivot-list --pivot-table-id ` first, then patch)" - }, - "+pivot-delete": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--pivot-table-id": "Target pivot table id", - "--yes": "Confirm destructive write (exit code 10 without this flag); delete is irreversible" - }, - "+cond-format-list": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--rule-id": "Filter by rule id" - }, - "+cond-format-create": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--properties": "Rule config JSON: `style` (required, applied on match), `attrs?` (rule-type-dependent params), `has_ref?`. `rule_type` and `ranges` are separate flags", - "--rule-type": "Conditional format rule type (13 values): `cellValue` / `formula` / `duplicate` / `unique` / `topBottom` / `aboveBelowAverage` / `dataBar` / `colorScale` / `iconSet` / `textContains` / `dateOccurring` / `blankCell` / `errorCell`; takes precedence over the same-named field inside `--properties`", - "--ranges": "A1 ranges where the conditional format applies, as a JSON array (e.g. `[\"A1:A100\",\"C2:C50\"]`); takes precedence over the same-named field inside `--properties`" - }, - "+cond-format-update": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--rule-id": "Target rule id", - "--properties": "Rule config JSON, same shape as `+cond-format-create --properties`; update overwrites the entire rule", - "--rule-type": "Conditional format rule type (13 values): `cellValue` / `formula` / `duplicate` / `unique` / `topBottom` / `aboveBelowAverage` / `dataBar` / `colorScale` / `iconSet` / `textContains` / `dateOccurring` / `blankCell` / `errorCell`; takes precedence over the same-named field inside `--properties`", - "--ranges": "A1 ranges where the conditional format applies, as a JSON array (e.g. `[\"A1:A100\",\"C2:C50\"]`); takes precedence over the same-named field inside `--properties`" - }, - "+cond-format-delete": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--rule-id": "Target rule id", - "--yes": "Confirm destructive write (exit code 10 without this flag); delete is irreversible" - }, - "+filter-list": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)" - }, - "+filter-create": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--range": "Filter range (A1 notation, including header row, e.g. `A1:F1000`); do not duplicate the range field inside `--properties`", - "--properties": "Filter rule JSON: `rules` (required, per-column rule array), `filtered_columns?` (active column index hint). `range` is a separate flag (do not duplicate inside this JSON)" - }, - "+filter-update": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--properties": "Filter rule JSON: `rules` and `filtered_columns?`; update overwrites the entire rule set (pass `rules: []` to clear). `range` is a separate flag", - "--range": "Range the filter applies to (A1 notation, e.g. `A1:F1000`); takes precedence over the same-named field inside `--properties`" - }, - "+filter-delete": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--yes": "Confirm destructive write (exit code 10 without this flag); delete is irreversible" - }, - "+filter-view-list": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--view-id": "Filter by filter-view reference_id (returns the matching single view)" - }, - "+filter-view-create": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--properties": "Filter-view rule JSON: `rules?` (per-column rule array), `filtered_columns?`. `range` and `view_name` are separate flags", - "--range": "Range the filter view applies to (A1 notation, e.g. `A1:F1000`); takes precedence over the same-named field inside `--properties`; required on create and must cover the header row", - "--view-name": "Filter-view name; auto-assigned by the server when omitted on create, kept unchanged when omitted on update; takes precedence over the same-named field inside `--properties`" - }, - "+filter-view-update": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--view-id": "Target filter-view reference_id", - "--properties": "Filter-view rule JSON: `rules?`, `filtered_columns?`. `range` and `view_name` are separate flags; pass at least one of `--properties.rules` / `--range` / `--view-name`", - "--range": "Range the filter view applies to (A1 notation, e.g. `A1:F1000`); takes precedence over the same-named field inside `--properties`; omit to keep the current range on update", - "--view-name": "Filter-view name; auto-assigned by the server when omitted on create, kept unchanged when omitted on update; takes precedence over the same-named field inside `--properties`" - }, - "+filter-view-delete": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--view-id": "Target filter-view reference_id", - "--yes": "Confirm high-risk write (exit code 10 without this flag)" - }, - "+sparkline-list": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--group-id": "Filter by group_id" - }, - "+sparkline-create": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--properties": "JSON: `{\"type\":\"line|column|winLoss\",\"data_range\":\"A2:F10\",\"target_range\":\"G2:G10\",\"style\":{...},\"special_points\":{...}}`; `type` is a 3-value enum; row/column counts of `data_range` must match `target_range`" - }, - "+sparkline-update": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--group-id": "Target group id", - "--properties": "Full or sufficiently complete sparkline config (read back with `+sparkline-list --group-id ` first, then patch); supports updating `type` / `data_range` / `target_range` / `style` / `special_points` etc." - }, - "+sparkline-delete": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--group-id": "Target group id", - "--yes": "Confirm destructive write (exit code 10 without this flag); delete is irreversible" - }, - "+float-image-list": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--float-image-id": "Filter by id; lists all float images on the sheet when omitted" - }, - "+float-image-create": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--image-name": "Image name, including extension (e.g. `logo.png`)", - "--image-token": "Image file_token (XOR with `--image-uri`). Common source: `image_token` returned by `+float-image-list`", - "--image-uri": "Image reference_id (XOR with `--image-token`); a prefixed string like `<|image|>:abcdef`", - "--position-row": "Row anchor of the image's top-left corner (0-based)", - "--position-col": "Column anchor of the image's top-left corner (column letter, e.g. `A` / `B`)", - "--size-width": "Image width in pixels", - "--size-height": "Image height in pixels", - "--offset-row": "Pixel offset within the anchor row, on top of `--position-row`", - "--offset-col": "Pixel offset within the anchor column, on top of `--position-col`", - "--z-index": "Image z-index controlling stacking order" - }, - "+float-image-update": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--float-image-id": "Target float image id", - "--image-name": "Image name, including extension (e.g. `logo.png`)", - "--image-token": "Image file_token (XOR with `--image-uri`). Common source: `image_token` returned by `+float-image-list`", - "--image-uri": "Image reference_id (XOR with `--image-token`); a prefixed string like `<|image|>:abcdef`", - "--position-row": "Row anchor of the image's top-left corner (0-based)", - "--position-col": "Column anchor of the image's top-left corner (column letter, e.g. `A` / `B`)", - "--size-width": "Image width in pixels", - "--size-height": "Image height in pixels", - "--offset-row": "Pixel offset within the anchor row, on top of `--position-row`", - "--offset-col": "Pixel offset within the anchor column, on top of `--position-col`", - "--z-index": "Image z-index controlling stacking order" - }, - "+float-image-delete": { - "--url": "Spreadsheet URL (XOR with `--spreadsheet-token`)", - "--spreadsheet-token": "Spreadsheet token (XOR with `--url`)", - "--sheet-id": "Sheet reference_id (XOR with `--sheet-name`)", - "--sheet-name": "Sheet name (XOR with `--sheet-id`)", - "--float-image-id": "Target float image id", - "--yes": "Confirm destructive write (exit code 10 without this flag); delete is irreversible" - } -} diff --git a/shortcuts/sheets/execute_paths_test.go b/shortcuts/sheets/execute_paths_test.go index b484d1b79..4de3b2997 100644 --- a/shortcuts/sheets/execute_paths_test.go +++ b/shortcuts/sheets/execute_paths_test.go @@ -99,7 +99,7 @@ func TestExecute_CellsGet(t *testing.T) { t.Parallel() stub := toolOutputStub(testToken, "read", `{"ranges":[{"range":"A1:B2","cells":[[{"value":1}]]}]}`) out, err := runShortcutWithStubs(t, CellsGet, - []string{"--url", testURL, "--sheet-id", testSheetID, "--ranges", "A1:B2"}, stub) + []string{"--url", testURL, "--sheet-id", testSheetID, "--range", "A1:B2"}, stub) if err != nil { t.Fatalf("execute failed: %v\nout=%s", err, out) } diff --git a/shortcuts/sheets/flag_defs.go b/shortcuts/sheets/flag_defs.go new file mode 100644 index 000000000..f16f19eb8 --- /dev/null +++ b/shortcuts/sheets/flag_defs.go @@ -0,0 +1,94 @@ +// Copyright (c) 2026 Lark Technologies Pte. Ltd. +// SPDX-License-Identifier: MIT + +package sheets + +import ( + _ "embed" + "encoding/json" + "fmt" + "sync" + + "github.com/larksuite/cli/shortcuts/common" +) + +// ─── flag definitions, sourced from sheet-skill-spec ─────────────────── +// +// data/flag-defs.json is the canonical, full definition of every CLI flag +// (name, type, default, desc, enum, input, hidden, required, kind), +// generated by sheet-skill-spec's sync script. We embed it and build each +// shortcut's []common.Flag from it at assembly time, so flag metadata never +// has to be hand-written in Go. +// +// Flags with kind == "system" (--dry-run, --yes, ...) are NOT materialized +// here: the framework auto-injects them based on Risk / DryRun / HasFormat. +// Do not hand-edit data/flag-defs.json; regenerate via the sync script. + +//go:embed data/flag-defs.json +var flagDefsJSON []byte + +type flagDef struct { + Name string `json:"name"` + Kind string `json:"kind"` // "public" | "own" | "system" + Type string `json:"type"` // string | bool | int | int64 | float64 | string_array | string_slice + Required string `json:"required"` // "required" | "optional" | "xor" + Desc string `json:"desc"` + Default string `json:"default"` + Hidden bool `json:"hidden"` + Enum []string `json:"enum"` + Input []string `json:"input"` +} + +type commandDef struct { + Risk string `json:"risk"` + Flags []flagDef `json:"flags"` +} + +var ( + flagDefsOnce sync.Once + flagDefs map[string]commandDef + flagDefsErr error +) + +func loadFlagDefs() (map[string]commandDef, error) { + flagDefsOnce.Do(func() { + flagDefs = make(map[string]commandDef) + if err := json.Unmarshal(flagDefsJSON, &flagDefs); err != nil { + flagDefsErr = fmt.Errorf("flag-defs.json: %w", err) + } + }) + return flagDefs, flagDefsErr +} + +// flagsFor builds the []common.Flag for a shortcut command directly from +// flag-defs.json. System-kind flags are skipped (the framework injects +// them). Panics if the command is absent or the JSON is malformed — this +// is a build-time data contract, so a missing entry is a programming error +// surfaced loudly at startup rather than a silent empty flag set. +func flagsFor(command string) []common.Flag { + defs, err := loadFlagDefs() + if err != nil { + panic(fmt.Sprintf("sheets: %v", err)) + } + spec, ok := defs[command] + if !ok { + panic(fmt.Sprintf("sheets: no flag-defs.json entry for %q", command)) + } + out := make([]common.Flag, 0, len(spec.Flags)) + for _, df := range spec.Flags { + if df.Kind == "system" { + continue + } + out = append(out, common.Flag{ + Name: df.Name, + Type: df.Type, + Default: df.Default, + Desc: df.Desc, + Hidden: df.Hidden, + Required: df.Required == "required", + Enum: df.Enum, + Input: df.Input, + }) + } + return out +} diff --git a/shortcuts/sheets/flag_defs_test.go b/shortcuts/sheets/flag_defs_test.go new file mode 100644 index 000000000..a4c47fdf3 --- /dev/null +++ b/shortcuts/sheets/flag_defs_test.go @@ -0,0 +1,142 @@ +// Copyright (c) 2026 Lark Technologies Pte. Ltd. +// SPDX-License-Identifier: MIT + +package sheets + +import ( + "testing" + + "github.com/larksuite/cli/shortcuts/common" +) + +// TestFlagDefs_EmbedParses asserts the embedded flag-defs.json blob is valid +// JSON with at least one command entry. +func TestFlagDefs_EmbedParses(t *testing.T) { + t.Parallel() + defs, err := loadFlagDefs() + if err != nil { + t.Fatalf("loadFlagDefs error: %v", err) + } + if len(defs) == 0 { + t.Fatal("flag-defs.json has no command entries") + } +} + +// TestFlagsFor_SkipsSystemFlags verifies system-kind flags (--dry-run, --yes) +// are never materialized into a shortcut's Flags slice — the framework injects +// those based on Risk / DryRun. +func TestFlagsFor_SkipsSystemFlags(t *testing.T) { + t.Parallel() + for _, cmd := range []string{"+sheet-delete", "+batch-update", "+csv-get"} { + for _, f := range flagsFor(cmd) { + if f.Name == "dry-run" || f.Name == "yes" { + t.Errorf("%s: system flag --%s leaked into Flags", cmd, f.Name) + } + } + } +} + +// TestFlagsFor_MapsAllFields spot-checks that name/type/default/enum/input/ +// required/hidden are carried over from the JSON correctly. +func TestFlagsFor_MapsAllFields(t *testing.T) { + t.Parallel() + byName := func(cmd, name string) *common.Flag { + flags := flagsFor(cmd) + for i := range flags { + if flags[i].Name == name { + return &flags[i] + } + } + return nil + } + + // enum + default + rt := byName("+dim-insert", "inherit-style") + if rt == nil || len(rt.Enum) != 3 || rt.Default != "none" { + t.Errorf("+dim-insert --inherit-style not mapped: %+v", rt) + } + // required + title := byName("+sheet-create", "title") + if title == nil || !title.Required { + t.Errorf("+sheet-create --title should be required: %+v", title) + } + // xor is NOT cobra-required (enforced by Validate hooks) + url := byName("+sheet-create", "url") + if url == nil || url.Required { + t.Errorf("+sheet-create --url should not be cobra-required: %+v", url) + } + // hidden + int default + cap := byName("+cells-get", "cell-limit") + if cap == nil || !cap.Hidden || cap.Default != "5000" { + t.Errorf("+cells-get --cell-limit not mapped: %+v", cap) + } + // input sources + cells := byName("+cells-set", "cells") + if cells == nil || len(cells.Input) != 2 { + t.Errorf("+cells-set --cells should support file+stdin: %+v", cells) + } + // float64 type + fs := byName("+cells-set-style", "font-size") + if fs == nil || fs.Type != "float64" { + t.Errorf("+cells-set-style --font-size should be float64: %+v", fs) + } +} + +// TestFlagsFor_EveryRegisteredCommandHasDefs ensures every shortcut returned by +// Shortcuts() has a flag-defs.json entry and that its flags match the JSON's +// non-system flags exactly (name + type + required + default + hidden). This is +// the contract that lets shortcuts drop hand-written flag literals. +func TestFlagsFor_EveryRegisteredCommandHasDefs(t *testing.T) { + t.Parallel() + defs, err := loadFlagDefs() + if err != nil { + t.Fatal(err) + } + for _, s := range Shortcuts() { + spec, ok := defs[s.Command] + if !ok { + t.Errorf("%s has no flag-defs.json entry", s.Command) + continue + } + want := map[string]flagDef{} + for _, df := range spec.Flags { + if df.Kind != "system" { + want[df.Name] = df + } + } + got := map[string]bool{} + for _, f := range s.Flags { + got[f.Name] = true + df, ok := want[f.Name] + if !ok { + t.Errorf("%s --%s present in Go but not in JSON (non-system)", s.Command, f.Name) + continue + } + ft := f.Type + if ft == "" { + ft = "string" + } + jt := df.Type + if jt == "" { + jt = "string" + } + if ft != jt { + t.Errorf("%s --%s type: go=%s json=%s", s.Command, f.Name, ft, jt) + } + if f.Required != (df.Required == "required") { + t.Errorf("%s --%s required: go=%v json=%s", s.Command, f.Name, f.Required, df.Required) + } + if f.Default != df.Default { + t.Errorf("%s --%s default: go=%q json=%q", s.Command, f.Name, f.Default, df.Default) + } + if f.Hidden != df.Hidden { + t.Errorf("%s --%s hidden: go=%v json=%v", s.Command, f.Name, f.Hidden, df.Hidden) + } + } + for name := range want { + if !got[name] { + t.Errorf("%s --%s in JSON but missing from Go Flags", s.Command, name) + } + } + } +} diff --git a/shortcuts/sheets/flag_desc.go b/shortcuts/sheets/flag_desc.go deleted file mode 100644 index 863af7dae..000000000 --- a/shortcuts/sheets/flag_desc.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) 2026 Lark Technologies Pte. Ltd. -// SPDX-License-Identifier: MIT - -package sheets - -import ( - _ "embed" - "encoding/json" - "fmt" - "sync" - - "github.com/larksuite/cli/shortcuts/common" -) - -//go:embed data/flag-descriptions.en.json -var flagDescsJSON []byte - -var ( - flagDescsOnce sync.Once - flagDescs map[string]map[string]string - flagDescsErr error -) - -func loadFlagDescs() (map[string]map[string]string, error) { - flagDescsOnce.Do(func() { - flagDescs = make(map[string]map[string]string) - flagDescsErr = json.Unmarshal(flagDescsJSON, &flagDescs) - if flagDescsErr != nil { - flagDescsErr = fmt.Errorf("flag-descriptions.en.json: %w", flagDescsErr) - } - }) - return flagDescs, flagDescsErr -} - -// flagDesc returns the description for a flag from the embedded -// flag-descriptions.en.json. command is e.g. "+workbook-info", -// flagName is e.g. "url" (without "--" prefix). Returns "" when -// no entry exists. -func flagDesc(command, flagName string) string { - descs, err := loadFlagDescs() - if err != nil || descs == nil { - return "" - } - cmd, ok := descs[command] - if !ok { - return "" - } - return cmd["--"+flagName] -} - -// applyFlagDescs patches all Flag.Desc fields in the given shortcut -// slice with values from flag-descriptions.en.json. Flags without a -// JSON entry keep their existing Desc unchanged. -func applyFlagDescs(shortcuts []common.Shortcut) { - descs, err := loadFlagDescs() - if err != nil || descs == nil { - return - } - for i := range shortcuts { - cmd, ok := descs[shortcuts[i].Command] - if !ok { - continue - } - for j := range shortcuts[i].Flags { - key := "--" + shortcuts[i].Flags[j].Name - if desc, found := cmd[key]; found { - shortcuts[i].Flags[j].Desc = desc - } - } - } -} diff --git a/shortcuts/sheets/flag_desc_test.go b/shortcuts/sheets/flag_desc_test.go deleted file mode 100644 index e30d02bc6..000000000 --- a/shortcuts/sheets/flag_desc_test.go +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) 2026 Lark Technologies Pte. Ltd. -// SPDX-License-Identifier: MIT - -package sheets - -import ( - "testing" -) - -func TestFlagDescs_EmbedParses(t *testing.T) { - t.Parallel() - descs, err := loadFlagDescs() - if err != nil { - t.Fatalf("loadFlagDescs error: %v", err) - } - if len(descs) == 0 { - t.Fatal("flag-descriptions.en.json has no entries") - } -} - -func TestFlagDescs_SpotCheck(t *testing.T) { - t.Parallel() - cases := []struct { - command string - flagName string - }{ - {"+workbook-info", "url"}, - {"+cells-set", "range"}, - {"+csv-get", "range"}, - {"+batch-update", "operations"}, - {"+chart-create", "properties"}, - } - for _, tc := range cases { - desc := flagDesc(tc.command, tc.flagName) - if desc == "" { - t.Errorf("flagDesc(%q, %q) = empty; want a description", tc.command, tc.flagName) - } - } -} - -func TestFlagDescs_UnknownReturnsEmpty(t *testing.T) { - t.Parallel() - if got := flagDesc("+no-such-cmd", "no-flag"); got != "" { - t.Errorf("expected empty for unknown command; got %q", got) - } -} - -func TestApplyFlagDescs_OverridesHardcodedDesc(t *testing.T) { - t.Parallel() - all := Shortcuts() - descs, err := loadFlagDescs() - if err != nil { - t.Fatalf("loadFlagDescs: %v", err) - } - for _, s := range all { - cmd, ok := descs[s.Command] - if !ok { - continue - } - for _, f := range s.Flags { - key := "--" + f.Name - want, exists := cmd[key] - if !exists { - continue - } - if f.Desc != want { - t.Errorf("%s %s: Desc=%q, want=%q", s.Command, key, f.Desc, want) - } - } - } -} - -func TestApplyFlagDescs_Coverage(t *testing.T) { - t.Parallel() - all := Shortcuts() - descs, err := loadFlagDescs() - if err != nil { - t.Fatalf("loadFlagDescs: %v", err) - } - - // Framework-injected flags are not in the Flags slice but may - // appear in the JSON as documentation. Skip them. - frameworkFlags := map[string]bool{ - "--yes": true, - "--dry-run": true, - } - - // Every non-framework flag in the JSON should appear in the shortcut list. - for cmd, flags := range descs { - for flagKey := range flags { - if frameworkFlags[flagKey] { - continue - } - found := false - for _, s := range all { - if s.Command != cmd { - continue - } - for _, f := range s.Flags { - if "--"+f.Name == flagKey { - found = true - break - } - } - break - } - if !found { - t.Logf("JSON has %s %s but no matching flag in shortcut list (naming mismatch or not yet implemented)", cmd, flagKey) - } - } - } -} diff --git a/shortcuts/sheets/flag_schema.go b/shortcuts/sheets/flag_schema.go index b61abd8f7..03bf0b65d 100644 --- a/shortcuts/sheets/flag_schema.go +++ b/shortcuts/sheets/flag_schema.go @@ -96,9 +96,9 @@ func printFlagSchemaFor(command string) func(flagName string) ([]byte, error) { } sort.Strings(flags) return json.MarshalIndent(map[string]interface{}{ - "shortcut": command, - "introspectable_flags": flags, - "hint": "run again with --flag-name to dump the JSON Schema for that flag", + "shortcut": command, + "introspectable_flags": flags, + "hint": "run again with --flag-name to dump the JSON Schema for that flag", }, "", " ") } schema, ok := entry[flagName] diff --git a/shortcuts/sheets/helpers.go b/shortcuts/sheets/helpers.go index 931f3eb5c..53e53be95 100644 --- a/shortcuts/sheets/helpers.go +++ b/shortcuts/sheets/helpers.go @@ -57,26 +57,6 @@ func extractSpreadsheetToken(input string) string { return input } -// publicTokenFlags is the leading pair of every canonical sheets shortcut. -// Shortcuts targeting a single sheet append the public sheet-id / sheet-name -// XOR pair on top of this; workbook-level shortcuts use this pair only. -func publicTokenFlags() []common.Flag { - return []common.Flag{ - {Name: "url", Desc: "spreadsheet URL (XOR --spreadsheet-token)"}, - {Name: "spreadsheet-token", Desc: "spreadsheet token (XOR --url)"}, - } -} - -// publicSheetFlags extends publicTokenFlags with the sheet selector pair. -// Use for any +sheet-* / +cells-* / +dim-* / object shortcut that operates -// on an existing single sub-sheet. -func publicSheetFlags() []common.Flag { - return append(publicTokenFlags(), - common.Flag{Name: "sheet-id", Desc: "sheet reference_id (XOR --sheet-name)"}, - common.Flag{Name: "sheet-name", Desc: "sheet title (XOR --sheet-id)"}, - ) -} - // resolveSheetSelector validates the --sheet-id / --sheet-name XOR and // returns whichever was supplied. Network-free. // @@ -169,35 +149,6 @@ func requireJSONArray(runtime *common.RuntimeContext, name string) ([]interface{ // ─── style flags (shared by +cells-set-style and +cells-batch-set-style) ─ -var ( - fontStyleEnum = []string{"normal", "italic"} - fontWeightEnum = []string{"normal", "bold"} - fontLineEnum = []string{"none", "underline", "line-through"} - hAlignEnum = []string{"left", "center", "right"} - vAlignEnum = []string{"top", "middle", "bottom"} - wordWrapEnum = []string{"overflow", "auto-wrap", "word-clip"} -) - -// styleFlatFlags returns the 11 flat style flags + --border-styles that both -// +cells-set-style and +cells-batch-set-style expose. Keeping them in one -// place stops the two shortcuts from drifting apart. -func styleFlatFlags() []common.Flag { - return []common.Flag{ - {Name: "background-color", Desc: "hex background color (e.g. #ffffff)"}, - {Name: "font-color", Desc: "hex font color (e.g. #000000)"}, - {Name: "font-size", Type: "int", Desc: "font size in pixels (e.g. 10, 12, 14)"}, - {Name: "font-style", Enum: fontStyleEnum, Desc: "normal / italic"}, - {Name: "font-weight", Enum: fontWeightEnum, Desc: "normal / bold"}, - {Name: "font-line", Enum: fontLineEnum, Desc: "none / underline / line-through"}, - {Name: "horizontal-alignment", Enum: hAlignEnum, Desc: "left / center / right"}, - {Name: "vertical-alignment", Enum: vAlignEnum, Desc: "top / middle / bottom"}, - {Name: "word-wrap", Enum: wordWrapEnum, Desc: "overflow (default) / auto-wrap / word-clip"}, - {Name: "number-format", Desc: "number format string (e.g. @, 0.00, $#,##0.00, mm/dd/yyyy)"}, - {Name: "border-styles", Input: []string{common.File, common.Stdin}, - Desc: "border JSON: { top, bottom, left, right } each = { color, style, weight }"}, - } -} - // buildCellStyleFromFlags reads the 11 flat style flags and returns the // cell_styles map expected by set_cell_range. Skips any flag the user // didn't set so partial styles work. @@ -209,8 +160,8 @@ func buildCellStyleFromFlags(runtime *common.RuntimeContext) map[string]interfac if v := runtime.Str("font-color"); v != "" { style["font_color"] = v } - if runtime.Changed("font-size") && runtime.Int("font-size") > 0 { - style["font_size"] = runtime.Int("font-size") + if runtime.Changed("font-size") && runtime.Float64("font-size") > 0 { + style["font_size"] = runtime.Float64("font-size") } if v := runtime.Str("font-style"); v != "" { style["font_style"] = v diff --git a/shortcuts/sheets/lark_sheet_batch_update.go b/shortcuts/sheets/lark_sheet_batch_update.go index d91d34cee..364a11ddd 100644 --- a/shortcuts/sheets/lark_sheet_batch_update.go +++ b/shortcuts/sheets/lark_sheet_batch_update.go @@ -40,11 +40,7 @@ var BatchUpdate = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicTokenFlags(), - common.Flag{Name: "operations", Input: []string{common.File, common.Stdin}, Required: true, - Desc: "operations JSON array: [{tool_name, input}, ...] (or an envelope object with operations / continue_on_error)"}, - common.Flag{Name: "continue-on-error", Type: "bool", Desc: "flip the default strict transaction off; partial success is kept on disk"}, - ), + Flags: flagsFor("+batch-update"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err @@ -142,12 +138,7 @@ var CellsBatchSetStyle = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append( - append(publicTokenFlags(), - common.Flag{Name: "ranges", Input: []string{common.File, common.Stdin}, Required: true, - Desc: "JSON array of sheet-prefixed A1 ranges (e.g. [\"sheet1!A1:B2\", \"sheet1!D1:E2\"])"}), - styleFlatFlags()..., - ), + Flags: flagsFor("+cells-batch-set-style"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err @@ -240,16 +231,7 @@ var DropdownUpdate = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicTokenFlags(), - common.Flag{Name: "ranges", Input: []string{common.File, common.Stdin}, Required: true, - Desc: "JSON array of sheet-prefixed A1 ranges (e.g. [\"sheet1!A2:A100\"])"}, - common.Flag{Name: "options", Input: []string{common.File, common.Stdin}, Required: true, - Desc: "options JSON array (e.g. [\"alpha\",\"beta\"])"}, - common.Flag{Name: "colors", Input: []string{common.File, common.Stdin}, - Desc: "optional RGB hex color array (must equal --options length)"}, - common.Flag{Name: "multiple", Type: "bool", Desc: "enable multi-select"}, - common.Flag{Name: "highlight", Type: "bool", Desc: "color-highlight options"}, - ), + Flags: flagsFor("+dropdown-update"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err @@ -294,10 +276,7 @@ var DropdownDelete = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicTokenFlags(), - common.Flag{Name: "ranges", Input: []string{common.File, common.Stdin}, Required: true, - Desc: "JSON array of sheet-prefixed A1 ranges (max 100)"}, - ), + Flags: flagsFor("+dropdown-delete"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err diff --git a/shortcuts/sheets/lark_sheet_object_crud.go b/shortcuts/sheets/lark_sheet_object_crud.go index 96910fa59..4457188b2 100644 --- a/shortcuts/sheets/lark_sheet_object_crud.go +++ b/shortcuts/sheets/lark_sheet_object_crud.go @@ -33,14 +33,10 @@ import ( // idFlag / idField empty → no per-object id flag (only filter uses that // today, and it has its own bespoke shortcuts further down). type objectCRUDSpec struct { - commandPrefix string // e.g. "+chart" → +chart-create / -update / -delete - toolName string // e.g. "manage_chart_object" - idFlag string // e.g. "chart-id" - idField string // e.g. "chart_id" - createDataDesc string // help text for --properties on create - updateDataDesc string // help text for --properties on update - createExtraFlags []common.Flag - updateExtraFlags []common.Flag + commandPrefix string // e.g. "+chart" → +chart-create / -update / -delete + toolName string // e.g. "manage_chart_object" + idFlag string // e.g. "chart-id" + idField string // e.g. "chart_id" // enhanceCreateInput / enhanceUpdateInput, when set, mutate the tool // input after the standard fields are written. Used to inject // shortcut-specific flat flags into the input (typically into the @@ -51,10 +47,7 @@ type objectCRUDSpec struct { } func newObjectCreateShortcut(spec objectCRUDSpec) common.Shortcut { - flags := append(publicSheetFlags(), - common.Flag{Name: "properties", Input: []string{common.File, common.Stdin}, Required: true, Desc: spec.createDataDesc}, - ) - flags = append(flags, spec.createExtraFlags...) + flags := flagsFor(spec.commandPrefix + "-create") return common.Shortcut{ Service: "sheets", Command: spec.commandPrefix + "-create", @@ -121,18 +114,7 @@ func objectCreateInput(runtime *common.RuntimeContext, token, sheetID, sheetName } func newObjectUpdateShortcut(spec objectCRUDSpec) common.Shortcut { - flags := publicSheetFlags() - if spec.idFlag != "" { - flags = append(flags, common.Flag{ - Name: spec.idFlag, Required: true, - Desc: "target object reference_id (maps to " + spec.idField + " on the wire)", - }) - } - flags = append(flags, common.Flag{ - Name: "properties", Input: []string{common.File, common.Stdin}, Required: true, - Desc: spec.updateDataDesc, - }) - flags = append(flags, spec.updateExtraFlags...) + flags := flagsFor(spec.commandPrefix + "-update") return common.Shortcut{ Service: "sheets", Command: spec.commandPrefix + "-update", @@ -205,13 +187,7 @@ func objectUpdateInput(runtime *common.RuntimeContext, token, sheetID, sheetName } func newObjectDeleteShortcut(spec objectCRUDSpec) common.Shortcut { - flags := publicSheetFlags() - if spec.idFlag != "" { - flags = append(flags, common.Flag{ - Name: spec.idFlag, Required: true, - Desc: "target object reference_id (maps to " + spec.idField + " on the wire)", - }) - } + flags := flagsFor(spec.commandPrefix + "-delete") return common.Shortcut{ Service: "sheets", Command: spec.commandPrefix + "-delete", @@ -273,12 +249,10 @@ func objectDeleteInput(runtime *common.RuntimeContext, token, sheetID, sheetName // chart var chartSpec = objectCRUDSpec{ - commandPrefix: "+chart", - toolName: "manage_chart_object", - idFlag: "chart-id", - idField: "chart_id", - createDataDesc: "chart properties JSON (position / data / properties etc.); see lark-sheets-chart.md for the shape", - updateDataDesc: "full or partial chart properties JSON (`+chart-list --chart-id ` first, then patch)", + commandPrefix: "+chart", + toolName: "manage_chart_object", + idFlag: "chart-id", + idField: "chart_id", } var ChartCreate = newObjectCreateShortcut(chartSpec) var ChartUpdate = newObjectUpdateShortcut(chartSpec) @@ -287,18 +261,10 @@ var ChartDelete = newObjectDeleteShortcut(chartSpec) // pivot — create exposes --target-sheet-id / --target-position (top-level // of the tool input) plus --source / --range hoisted from properties. var pivotSpec = objectCRUDSpec{ - commandPrefix: "+pivot", - toolName: "manage_pivot_table_object", - idFlag: "pivot-table-id", - idField: "pivot_table_id", - createDataDesc: "pivot table properties JSON: { rows, columns, values, filters, show_row_grand_total, ... }; --source / --range cover the common scalar fields", - updateDataDesc: "full or partial pivot properties JSON (`+pivot-list --pivot-table-id ` first, then patch)", - createExtraFlags: []common.Flag{ - {Name: "target-sheet-id", Desc: "destination sheet id for the pivot table; omit to auto-create a fresh sheet (recommended)"}, - {Name: "target-position", Default: "A1", Desc: "destination start cell, default A1"}, - {Name: "source", Required: true, Desc: "pivot source range, e.g. Sheet1!A1:D100 (--source overrides any properties.source)"}, - {Name: "range", Desc: "destination top-left A1 cell, e.g. F1 (--range overrides any properties.range)"}, - }, + commandPrefix: "+pivot", + toolName: "manage_pivot_table_object", + idFlag: "pivot-table-id", + idField: "pivot_table_id", enhanceCreateInput: func(rt *common.RuntimeContext, input map[string]interface{}) { if v := strings.TrimSpace(rt.Str("target-sheet-id")); v != "" { input["target_sheet_id"] = v @@ -325,17 +291,6 @@ var PivotDelete = newObjectDeleteShortcut(pivotSpec) // conditional format — CLI surface uses --rule-id (short), wired to the // tool's conditional_format_id on the wire. --rule-type and --ranges are // hoisted out of properties (both required, set on every CRUD write). -var condFormatRuleTypeEnum = []string{ - "cellValue", "formula", "duplicate", "unique", - "topBottom", "aboveBelowAverage", "dataBar", "colorScale", - "iconSet", "textContains", "dateOccurring", "blankCell", "errorCell", -} -var condFormatExtraFlags = []common.Flag{ - {Name: "rule-type", Required: true, Enum: condFormatRuleTypeEnum, - Desc: "rule type enum (cellValue / formula / duplicate / ...); merged into properties.rule.type"}, - {Name: "ranges", Input: []string{common.File, common.Stdin}, Required: true, - Desc: "A1 ranges JSON array (e.g. [\"A1:A100\",\"C2:C50\"]); merged into properties.ranges"}, -} var condFormatEnhance = func(rt *common.RuntimeContext, input map[string]interface{}) { props, _ := input["properties"].(map[string]interface{}) if props == nil { @@ -361,10 +316,6 @@ var condFormatSpec = objectCRUDSpec{ toolName: "manage_conditional_format_object", idFlag: "rule-id", idField: "conditional_format_id", - createDataDesc: "rule JSON: { rule: { operator, value, style, ... }, ... }; --rule-type and --ranges cover the common scalar fields", - updateDataDesc: "full or partial rule JSON (`+cond-format-list --rule-id ` first, then patch); --rule-type and --ranges still required", - createExtraFlags: condFormatExtraFlags, - updateExtraFlags: condFormatExtraFlags, enhanceCreateInput: condFormatEnhance, enhanceUpdateInput: condFormatEnhance, } @@ -374,12 +325,10 @@ var CondFormatDelete = newObjectDeleteShortcut(condFormatSpec) // sparkline — CLI uses --group-id (higher level) as the object selector. var sparklineSpec = objectCRUDSpec{ - commandPrefix: "+sparkline", - toolName: "manage_sparkline_object", - idFlag: "group-id", - idField: "group_id", - createDataDesc: "sparkline group JSON: { type: line|column|winLoss, source_range, target_range, ... }", - updateDataDesc: "full or partial sparkline group JSON (`+sparkline-list --group-id ` first, then patch)", + commandPrefix: "+sparkline", + toolName: "manage_sparkline_object", + idFlag: "group-id", + idField: "group_id", } var SparklineCreate = newObjectCreateShortcut(sparklineSpec) var SparklineUpdate = newObjectUpdateShortcut(sparklineSpec) @@ -389,19 +338,6 @@ var SparklineDelete = newObjectDeleteShortcut(sparklineSpec) // the tool's properties is composed entirely from the position / size / // offset / image_token / image_uri / z_index flat flags. -var floatImageFlatFlags = []common.Flag{ - {Name: "image-name", Required: true, Desc: "image file name with extension (e.g. logo.png)"}, - {Name: "image-token", Desc: "image file_token (XOR --image-uri); commonly returned by +float-image-list"}, - {Name: "image-uri", Desc: "image reference_id (XOR --image-token); upstream-supplied like \"<|image|>:abcdef\""}, - {Name: "position-row", Type: "int", Required: true, Desc: "top-left row index (0-based)"}, - {Name: "position-col", Required: true, Desc: "top-left column letter (e.g. A, B)"}, - {Name: "size-width", Type: "int", Required: true, Desc: "image width in pixels"}, - {Name: "size-height", Type: "int", Required: true, Desc: "image height in pixels"}, - {Name: "offset-row", Type: "int", Desc: "in-cell row offset in pixels (optional)"}, - {Name: "offset-col", Type: "int", Desc: "in-cell column offset in pixels (optional)"}, - {Name: "z-index", Type: "int", Desc: "z-order layer for overlapping images (optional)"}, -} - // floatImageProperties assembles the tool's properties object from the // 10 flat flags. Caller is responsible for marking required flags via // cobra Required:true; this function only enforces the image_token XOR @@ -452,11 +388,7 @@ func newFloatImageWriteShortcut(command, description, op string, withIDFlag, isH if isHighRisk { risk = "high-risk-write" } - flags := publicSheetFlags() - if withIDFlag { - flags = append(flags, common.Flag{Name: "float-image-id", Required: true, Desc: "target image reference_id"}) - } - flags = append(flags, floatImageFlatFlags...) + flags := flagsFor(command) return common.Shortcut{ Service: "sheets", Command: command, @@ -550,10 +482,6 @@ var FloatImageDelete = newObjectDeleteShortcut(floatImageDeleteSpec) // it dispatches via the same One-OpenAPI endpoint as every other shortcut. // --view-name and --range are hoisted out of properties (optional on both // create and update; they always win over properties.{view_name, range}). -var filterViewExtraFlags = []common.Flag{ - {Name: "range", Desc: "filter view range (A1 covering the header, e.g. A1:F1000); overrides properties.range"}, - {Name: "view-name", Desc: "view title; create omits → server-generated, update omits → keep current. Overrides properties.view_name"}, -} var filterViewEnhance = func(rt *common.RuntimeContext, input map[string]interface{}) { props, _ := input["properties"].(map[string]interface{}) if props == nil { @@ -572,10 +500,6 @@ var filterViewSpec = objectCRUDSpec{ toolName: "manage_filter_view_object", idFlag: "view-id", idField: "view_id", - createDataDesc: "filter view JSON: { rules?: [...] , filtered_columns?: [...] }; --range / --view-name cover the scalar fields", - updateDataDesc: "partial update JSON: any of { rules, filtered_columns }; `+filter-view-list --view-id ` first", - createExtraFlags: filterViewExtraFlags, - updateExtraFlags: filterViewExtraFlags, enhanceCreateInput: filterViewEnhance, enhanceUpdateInput: filterViewEnhance, } @@ -600,11 +524,7 @@ var FilterCreate = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicSheetFlags(), - common.Flag{Name: "range", Required: true, Desc: "filter range including the header row (e.g. A1:F1000)"}, - common.Flag{Name: "properties", Input: []string{common.File, common.Stdin}, - Desc: "optional rules JSON: { rules: [...], filtered_columns?: [...] }; empty filter when omitted"}, - ), + Flags: flagsFor("+filter-create"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err @@ -686,11 +606,7 @@ var FilterUpdate = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicSheetFlags(), - common.Flag{Name: "properties", Input: []string{common.File, common.Stdin}, Required: true, - Desc: "patch JSON: { rules: [...], filtered_columns?: [...] } — read with +filter-list first"}, - common.Flag{Name: "range", Required: true, Desc: "filter range A1 (e.g. A1:F1000); overrides properties.range"}, - ), + Flags: flagsFor("+filter-update"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err @@ -757,7 +673,7 @@ var FilterDelete = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: publicSheetFlags(), + Flags: flagsFor("+filter-delete"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err diff --git a/shortcuts/sheets/lark_sheet_object_crud_test.go b/shortcuts/sheets/lark_sheet_object_crud_test.go index 933da4a38..88c610159 100644 --- a/shortcuts/sheets/lark_sheet_object_crud_test.go +++ b/shortcuts/sheets/lark_sheet_object_crud_test.go @@ -152,7 +152,7 @@ func TestObjectCRUDShortcuts_DryRun(t *testing.T) { { name: "+filter-view-create", sc: FilterViewCreate, - args: []string{"--url", testURL, "--sheet-id", testSheetID, "--properties", `{"view_name":"v1","range":"A1:Z100"}`}, + args: []string{"--url", testURL, "--sheet-id", testSheetID, "--range", "A1:Z100", "--properties", `{"view_name":"v1"}`}, toolName: "manage_filter_view_object", wantInput: map[string]interface{}{ "excel_id": testToken, diff --git a/shortcuts/sheets/lark_sheet_object_list.go b/shortcuts/sheets/lark_sheet_object_list.go index cb2bc0d82..7c3b442ca 100644 --- a/shortcuts/sheets/lark_sheet_object_list.go +++ b/shortcuts/sheets/lark_sheet_object_list.go @@ -31,17 +31,10 @@ type objectListSpec struct { // Optional id filter. Empty filterFlag → no filter flag exposed. filterFlag string // CLI flag name (without leading --), e.g. "chart-id" filterField string // tool input key, e.g. "chart_id" - filterDesc string // flag help text } func newObjectListShortcut(spec objectListSpec) common.Shortcut { - flags := publicSheetFlags() - if spec.filterFlag != "" { - flags = append(flags, common.Flag{ - Name: spec.filterFlag, - Desc: spec.filterDesc, - }) - } + flags := flagsFor(spec.command) return common.Shortcut{ Service: "sheets", Command: spec.command, @@ -102,7 +95,6 @@ var ChartList = newObjectListShortcut(objectListSpec{ toolName: "get_chart_objects", filterFlag: "chart-id", filterField: "chart_id", - filterDesc: "optional chart reference_id; returns just that chart when set", }) // PivotList — list pivot tables on a sheet. @@ -112,7 +104,6 @@ var PivotList = newObjectListShortcut(objectListSpec{ toolName: "get_pivot_table_objects", filterFlag: "pivot-table-id", filterField: "pivot_table_id", - filterDesc: "optional pivot table reference_id; returns just that pivot when set", }) // CondFormatList — list conditional format rules. CLI's --rule-id maps to @@ -123,7 +114,6 @@ var CondFormatList = newObjectListShortcut(objectListSpec{ toolName: "get_conditional_format_objects", filterFlag: "rule-id", filterField: "conditional_format_id", - filterDesc: "optional rule reference_id (maps to conditional_format_id server-side)", }) // FilterList — list active sheet-level filters. No id filter because each @@ -143,7 +133,6 @@ var FilterViewList = newObjectListShortcut(objectListSpec{ toolName: "get_filter_view_objects", filterFlag: "view-id", filterField: "view_id", - filterDesc: "optional filter-view reference_id; returns just that view when set", }) // SparklineList — list sparkline groups on a sheet. The tool also accepts @@ -155,7 +144,6 @@ var SparklineList = newObjectListShortcut(objectListSpec{ toolName: "get_sparkline_objects", filterFlag: "group-id", filterField: "group_id", - filterDesc: "optional sparkline group reference_id; returns all sparklines in that group", }) // FloatImageList — list floating images on a sheet (vs. embedded @@ -166,5 +154,4 @@ var FloatImageList = newObjectListShortcut(objectListSpec{ toolName: "get_float_image_objects", filterFlag: "float-image-id", filterField: "float_image_id", - filterDesc: "optional floating-image reference_id; returns just that image when set", }) diff --git a/shortcuts/sheets/lark_sheet_range_operations.go b/shortcuts/sheets/lark_sheet_range_operations.go index f249f317a..2910712a1 100644 --- a/shortcuts/sheets/lark_sheet_range_operations.go +++ b/shortcuts/sheets/lark_sheet_range_operations.go @@ -35,11 +35,7 @@ var CellsClear = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicSheetFlags(), - common.Flag{Name: "range", Required: true, Desc: "A1 range to clear (e.g. A1:C10 / D3:D / 3:3)"}, - common.Flag{Name: "scope", Enum: []string{"content", "formats", "all"}, Default: "content", - Desc: "what to clear: content (values+formulas only, default) / formats / all"}, - ), + Flags: flagsFor("+cells-clear"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err @@ -107,15 +103,7 @@ var CellsUnmerge = newMergeShortcut( ) func newMergeShortcut(command, desc, op string, withMergeType bool) common.Shortcut { - flags := append(publicSheetFlags(), - common.Flag{Name: "range", Required: true, Desc: "A1 range to merge / unmerge (e.g. A1:C3)"}, - ) - if withMergeType { - flags = append(flags, common.Flag{ - Name: "merge-type", Enum: []string{"all", "rows", "columns"}, Default: "all", - Desc: "merge strategy: all (one cell) / rows / columns", - }) - } + flags := flagsFor(command) return common.Shortcut{ Service: "sheets", Command: command, @@ -191,9 +179,6 @@ func mergeInput(runtime *common.RuntimeContext, token, sheetID, sheetName, op st // Both shortcuts share the underlying resize_range tool; --end is inclusive // in the new CLI surface (was exclusive in the legacy +dim-resize). -var rowsResizeTypeEnum = []string{"pixel", "standard", "auto"} -var colsResizeTypeEnum = []string{"pixel", "standard"} - // RowsResize wraps resize_range for row heights. --type auto enables // auto-fit (rows only); --type pixel requires --size. var RowsResize = common.Shortcut{ @@ -204,14 +189,8 @@ var RowsResize = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicSheetFlags(), - common.Flag{Name: "start", Type: "int", Required: true, Desc: "0-based start row (inclusive)"}, - common.Flag{Name: "end", Type: "int", Required: true, Desc: "0-based end row (inclusive)"}, - common.Flag{Name: "type", Required: true, Enum: rowsResizeTypeEnum, - Desc: "sizing mode: `pixel` (needs --size) / `standard` (reset to default) / `auto` (auto-fit row height)"}, - common.Flag{Name: "size", Type: "int", Default: "0", Desc: "row height in pixels (e.g. 30); required with --type pixel, ignored otherwise"}, - ), - Validate: validateResize("row"), + Flags: flagsFor("+rows-resize"), + Validate: validateResize("row"), DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { token, _ := resolveSpreadsheetToken(runtime) sheetID, sheetName, _ := resolveSheetSelector(runtime) @@ -245,14 +224,8 @@ var ColsResize = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicSheetFlags(), - common.Flag{Name: "start", Type: "int", Required: true, Desc: "0-based start column (inclusive)"}, - common.Flag{Name: "end", Type: "int", Required: true, Desc: "0-based end column (inclusive)"}, - common.Flag{Name: "type", Required: true, Enum: colsResizeTypeEnum, - Desc: "sizing mode: `pixel` (needs --size) / `standard` (reset to default); `auto` is rows-only"}, - common.Flag{Name: "size", Type: "int", Default: "0", Desc: "column width in pixels (e.g. 120); required with --type pixel, ignored otherwise"}, - ), - Validate: validateResize("column"), + Flags: flagsFor("+cols-resize"), + Validate: validateResize("column"), DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { token, _ := resolveSpreadsheetToken(runtime) sheetID, sheetName, _ := resolveSheetSelector(runtime) @@ -358,11 +331,7 @@ var RangeMove = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicSheetFlags(), - common.Flag{Name: "source-range", Required: true, Desc: "source A1 range (e.g. A1:C5)"}, - common.Flag{Name: "target-range", Required: true, Desc: "target A1 starting cell (size derived from source)"}, - common.Flag{Name: "target-sheet-id", Desc: "destination sheet id (cross-sheet); omit for same sheet"}, - ), + Flags: flagsFor("+range-move"), Validate: validateRangeMoveOrCopy, DryRun: transformDryRunFn("move", false, false), Execute: transformExecuteFn("move", false, false), @@ -378,13 +347,7 @@ var RangeCopy = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicSheetFlags(), - common.Flag{Name: "source-range", Required: true, Desc: "source A1 range"}, - common.Flag{Name: "target-range", Required: true, Desc: "target A1 starting cell"}, - common.Flag{Name: "target-sheet-id", Desc: "destination sheet id (cross-sheet); omit for same sheet"}, - common.Flag{Name: "paste-type", Enum: []string{"values", "formulas", "formats", "all"}, Default: "all", - Desc: "what to copy: values / formulas / formats / all (default)"}, - ), + Flags: flagsFor("+range-copy"), Validate: validateRangeMoveOrCopy, DryRun: transformDryRunFn("copy", true, false), Execute: transformExecuteFn("copy", true, false), @@ -402,12 +365,7 @@ var RangeFill = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicSheetFlags(), - common.Flag{Name: "source-range", Required: true, Desc: "template A1 range with seed cells"}, - common.Flag{Name: "target-range", Required: true, Desc: "target fill range (must be disjoint from source)"}, - common.Flag{Name: "series-type", Enum: []string{"auto", "linear", "growth", "date", "copy"}, Default: "auto", - Desc: "auto / linear / growth / date → tool fillSeries; copy → tool copyCells"}, - ), + Flags: flagsFor("+range-fill"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err @@ -455,12 +413,7 @@ var RangeSort = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicSheetFlags(), - common.Flag{Name: "range", Required: true, Desc: "A1 range to sort"}, - common.Flag{Name: "sort-keys", Input: []string{common.File, common.Stdin}, Required: true, - Desc: "sort keys JSON, e.g. [{\"col\":\"B\",\"order\":\"asc\"},{\"col\":\"D\",\"order\":\"desc\"}]"}, - common.Flag{Name: "has-header", Type: "bool", Desc: "treat first row as header (excluded from sort); default false"}, - ), + Flags: flagsFor("+range-sort"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err @@ -613,10 +566,10 @@ func rangeSortInput(runtime *common.RuntimeContext, token, sheetID, sheetName st return nil, err } input := map[string]interface{}{ - "excel_id": token, - "operation": "sort", - "range": strings.TrimSpace(runtime.Str("range")), - "sort_conditions": keys, + "excel_id": token, + "operation": "sort", + "range": strings.TrimSpace(runtime.Str("range")), + "sort_conditions": keys, } sheetSelectorForToolInput(input, sheetID, sheetName) if runtime.Bool("has-header") { diff --git a/shortcuts/sheets/lark_sheet_read_data.go b/shortcuts/sheets/lark_sheet_read_data.go index 428c209ab..4c87c5f1b 100644 --- a/shortcuts/sheets/lark_sheet_read_data.go +++ b/shortcuts/sheets/lark_sheet_read_data.go @@ -19,8 +19,6 @@ import ( // The sandbox tool (export_sheet_to_sandbox) is Sheet-Tool-only and has no // CLI surface here. -var cellsGetIncludeEnum = []string{"value", "formula", "style", "comment", "data_validation"} - // CellsGet wraps get_cell_ranges: read multiple A1 ranges and return per-cell // values, formulas, styles, and other metadata as requested via --include. var CellsGet = common.Shortcut{ @@ -31,13 +29,7 @@ var CellsGet = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:read"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicSheetFlags(), - common.Flag{Name: "ranges", Type: "string_array", Required: true, Desc: "A1 ranges (repeat: --ranges A1:B2 --ranges D1:E5)"}, - common.Flag{Name: "include", Type: "string_slice", Enum: cellsGetIncludeEnum, Desc: "categories to include (default: value+style). value|formula|style|comment|data_validation"}, - common.Flag{Name: "skip-hidden", Type: "bool", Desc: "skip hidden rows/cols"}, - common.Flag{Name: "cell-limit", Type: "int", Default: "5000", Hidden: true, Desc: "anti-burst cell scan cap"}, - common.Flag{Name: "max-chars", Type: "int", Default: "200000", Hidden: true, Desc: "anti-burst response char cap"}, - ), + Flags: flagsFor("+cells-get"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err @@ -45,8 +37,8 @@ var CellsGet = common.Shortcut{ if _, _, err := resolveSheetSelector(runtime); err != nil { return err } - if len(runtime.StrArray("ranges")) == 0 { - return common.FlagErrorf("--ranges is required") + if len(runtime.StrArray("range")) == 0 { + return common.FlagErrorf("--range is required") } return nil }, @@ -76,7 +68,7 @@ var CellsGet = common.Shortcut{ func cellsGetInput(runtime *common.RuntimeContext, token, sheetID, sheetName string) map[string]interface{} { input := map[string]interface{}{ "excel_id": token, - "ranges": runtime.StrArray("ranges"), + "ranges": runtime.StrArray("range"), } sheetSelectorForToolInput(input, sheetID, sheetName) applyIncludeToCellsGet(input, runtime.StrSlice("include")) @@ -129,17 +121,7 @@ var CsvGet = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:read"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicSheetFlags(), - common.Flag{Name: "range", Desc: "A1 range; omit for the sheet's current_region"}, - common.Flag{ - Name: "value-render-option", Enum: []string{"formatted_value", "raw_value", "formula"}, - Desc: "value rendering: formatted_value (default) / raw_value / formula", - }, - common.Flag{Name: "include-row-prefix", Type: "bool", Default: "true", Desc: "keep [row=N] line prefix; pass --include-row-prefix=false to strip"}, - common.Flag{Name: "skip-hidden", Type: "bool", Desc: "skip hidden rows/cols"}, - common.Flag{Name: "max-rows", Type: "int", Default: "100000", Hidden: true, Desc: "anti-burst row cap"}, - common.Flag{Name: "max-chars", Type: "int", Default: "200000", Hidden: true, Desc: "anti-burst char cap"}, - ), + Flags: flagsFor("+csv-get"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err @@ -228,9 +210,7 @@ var DropdownGet = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:read"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicTokenFlags(), - common.Flag{Name: "range", Required: true, Desc: "A1 range with sheet prefix (e.g. sheet1!A2:A100)"}, - ), + Flags: flagsFor("+dropdown-get"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err diff --git a/shortcuts/sheets/lark_sheet_read_data_test.go b/shortcuts/sheets/lark_sheet_read_data_test.go index c59441417..ea57d1762 100644 --- a/shortcuts/sheets/lark_sheet_read_data_test.go +++ b/shortcuts/sheets/lark_sheet_read_data_test.go @@ -23,7 +23,7 @@ func TestReadDataShortcuts_DryRun(t *testing.T) { { name: "+cells-get multi-range + include=style,formula", sc: CellsGet, - args: []string{"--url", testURL, "--sheet-id", testSheetID, "--ranges", "A1:B2", "--ranges", "D1:E5", "--include", "style,formula"}, + args: []string{"--url", testURL, "--sheet-id", testSheetID, "--range", "A1:B2", "--range", "D1:E5", "--include", "style,formula"}, toolName: "get_cell_ranges", wantInput: map[string]interface{}{ "excel_id": testToken, diff --git a/shortcuts/sheets/lark_sheet_search_replace.go b/shortcuts/sheets/lark_sheet_search_replace.go index a6d94db98..3c6f79ebd 100644 --- a/shortcuts/sheets/lark_sheet_search_replace.go +++ b/shortcuts/sheets/lark_sheet_search_replace.go @@ -27,16 +27,7 @@ var CellsSearch = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:read"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicSheetFlags(), - common.Flag{Name: "find", Required: true, Desc: "text to search for (regex when --regex is set)"}, - common.Flag{Name: "range", Desc: "optional A1 range to scope the search"}, - common.Flag{Name: "match-case", Type: "bool", Desc: "case-sensitive match"}, - common.Flag{Name: "match-entire-cell", Type: "bool", Desc: "match the entire cell content only"}, - common.Flag{Name: "regex", Type: "bool", Desc: "treat --find as a regular expression"}, - common.Flag{Name: "include-formulas", Type: "bool", Desc: "also search inside formula text"}, - common.Flag{Name: "offset", Type: "int", Default: "0", Desc: "pagination offset (use next_offset from previous page)"}, - common.Flag{Name: "max-matches", Type: "int", Default: "5000", Hidden: true, Desc: "anti-burst match cap"}, - ), + Flags: flagsFor("+cells-search"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err @@ -122,15 +113,7 @@ var CellsReplace = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicSheetFlags(), - common.Flag{Name: "find", Required: true, Desc: "text to find (regex when --regex is set)"}, - common.Flag{Name: "replacement", Required: true, Desc: "replacement text (empty string deletes the match)"}, - common.Flag{Name: "range", Desc: "optional A1 range to scope the replace"}, - common.Flag{Name: "match-case", Type: "bool", Desc: "case-sensitive match"}, - common.Flag{Name: "match-entire-cell", Type: "bool", Desc: "match the entire cell content only"}, - common.Flag{Name: "regex", Type: "bool", Desc: "treat --find as a regular expression"}, - common.Flag{Name: "include-formulas", Type: "bool", Desc: "also replace inside formula text"}, - ), + Flags: flagsFor("+cells-replace"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err diff --git a/shortcuts/sheets/lark_sheet_sheet_structure.go b/shortcuts/sheets/lark_sheet_sheet_structure.go index acfe1feeb..2b10f0819 100644 --- a/shortcuts/sheets/lark_sheet_sheet_structure.go +++ b/shortcuts/sheets/lark_sheet_sheet_structure.go @@ -33,15 +33,7 @@ var SheetInfo = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:read"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicSheetFlags(), - common.Flag{Name: "range", Desc: "optional A1-style range to scope the query (e.g. A1:C20 / 3:6 / C:E); omit for whole sheet"}, - common.Flag{ - Name: "include", - Type: "string_slice", - Enum: []string{"merges", "row_heights", "col_widths", "hidden_rows", "hidden_cols", "groups", "frozen"}, - Desc: "filter returned categories (comma-separated). Omit for all.", - }, - ), + Flags: flagsFor("+sheet-info"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err @@ -121,9 +113,6 @@ func infoTypeFromInclude(include []string) string { // ─── +dim-* (modify_sheet_structure) ────────────────────────────────── -// dimEnum bounds the allowed values for --dimension across every +dim-* shortcut. -var dimEnum = []string{"row", "column"} - // DimInsert inserts blank rows / columns and optionally inherits style from // the adjacent dimension. var DimInsert = common.Shortcut{ @@ -134,13 +123,8 @@ var DimInsert = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicSheetFlags(), - common.Flag{Name: "dimension", Required: true, Enum: dimEnum, Desc: "`row` or `column`"}, - common.Flag{Name: "start", Type: "int", Required: true, Desc: "0-based start position (inclusive)"}, - common.Flag{Name: "end", Type: "int", Required: true, Desc: "0-based end position (exclusive)"}, - common.Flag{Name: "inherit-style", Enum: []string{"before", "after", "none"}, Default: "none", Desc: "inherit cell style from the row/column before, after, or neither"}, - ), - Validate: validateDimRange, + Flags: flagsFor("+dim-insert"), + Validate: validateDimRange, DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { token, _ := resolveSpreadsheetToken(runtime) sheetID, sheetName, _ := resolveSheetSelector(runtime) @@ -193,12 +177,8 @@ var DimDelete = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicSheetFlags(), - common.Flag{Name: "dimension", Required: true, Enum: dimEnum, Desc: "`row` or `column`"}, - common.Flag{Name: "start", Type: "int", Required: true, Desc: "0-based start position (inclusive)"}, - common.Flag{Name: "end", Type: "int", Required: true, Desc: "0-based end position (exclusive)"}, - ), - Validate: validateDimRange, + Flags: flagsFor("+dim-delete"), + Validate: validateDimRange, DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { token, _ := resolveSpreadsheetToken(runtime) sheetID, sheetName, _ := resolveSheetSelector(runtime) @@ -251,10 +231,7 @@ var DimFreeze = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicSheetFlags(), - common.Flag{Name: "dimension", Required: true, Enum: dimEnum, Desc: "`row` or `column`"}, - common.Flag{Name: "count", Type: "int", Required: true, Desc: "number of leading rows/columns to freeze; 0 unfreezes the chosen dimension"}, - ), + Flags: flagsFor("+dim-freeze"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err @@ -363,12 +340,8 @@ func newDimRangeOpShortcut(command, desc, op, risk string) common.Shortcut { Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicSheetFlags(), - common.Flag{Name: "dimension", Required: true, Enum: dimEnum, Desc: "`row` or `column`"}, - common.Flag{Name: "start", Type: "int", Required: true, Desc: "0-based start position (inclusive)"}, - common.Flag{Name: "end", Type: "int", Required: true, Desc: "0-based end position (exclusive)"}, - ), - Validate: validateDimRange, + Flags: flagsFor(command), + Validate: validateDimRange, DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { token, _ := resolveSpreadsheetToken(runtime) sheetID, sheetName, _ := resolveSheetSelector(runtime) @@ -397,17 +370,7 @@ func newDimRangeOpShortcut(command, desc, op, risk string) common.Shortcut { // --depth (currently unused server-side — accepted for forward-compat per // the canonical spec) and --group-state (group only, defaults to expand). func newDimGroupShortcut(command, desc, op string) common.Shortcut { - flags := append(publicSheetFlags(), - common.Flag{Name: "dimension", Required: true, Enum: dimEnum, Desc: "`row` or `column`"}, - common.Flag{Name: "start", Type: "int", Required: true, Desc: "0-based start position (inclusive)"}, - common.Flag{Name: "end", Type: "int", Required: true, Desc: "0-based end position (exclusive)"}, - common.Flag{Name: "depth", Type: "int", Default: "1", Desc: "nesting level (currently honored only when the server-side endpoint supports it)"}, - ) - if op == "group" { - flags = append(flags, - common.Flag{Name: "group-state", Enum: []string{"expand", "fold"}, Default: "expand", Desc: "initial state of the new group"}, - ) - } + flags := flagsFor(command) return common.Shortcut{ Service: "sheets", Command: command, @@ -512,12 +475,7 @@ var DimMove = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only", "sheets:spreadsheet:read"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicSheetFlags(), - common.Flag{Name: "dimension", Required: true, Enum: dimEnum, Desc: "`row` or `column`"}, - common.Flag{Name: "start", Type: "int", Required: true, Desc: "source start (0-indexed, inclusive)"}, - common.Flag{Name: "end", Type: "int", Required: true, Desc: "source end (0-indexed, inclusive)"}, - common.Flag{Name: "target", Type: "int", Required: true, Desc: "destination index (0-indexed); rows/cols move to land BEFORE this index"}, - ), + Flags: flagsFor("+dim-move"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err diff --git a/shortcuts/sheets/lark_sheet_workbook.go b/shortcuts/sheets/lark_sheet_workbook.go index cdfe6bcd6..17fd39e72 100644 --- a/shortcuts/sheets/lark_sheet_workbook.go +++ b/shortcuts/sheets/lark_sheet_workbook.go @@ -46,7 +46,7 @@ var WorkbookInfo = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:read"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: publicTokenFlags(), + Flags: flagsFor("+workbook-info"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { _, err := resolveSpreadsheetToken(runtime) return err @@ -88,12 +88,7 @@ var SheetCreate = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicTokenFlags(), - common.Flag{Name: "title", Desc: "new sheet title", Required: true}, - common.Flag{Name: "index", Type: "int", Default: "-1", Desc: "insertion position (0-based); omit to append"}, - common.Flag{Name: "row-count", Type: "int", Default: "0", Desc: "initial row count; omit for tool default (200)"}, - common.Flag{Name: "col-count", Type: "int", Default: "0", Desc: "initial column count; omit for tool default (20)"}, - ), + Flags: flagsFor("+sheet-create"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err @@ -155,7 +150,7 @@ var SheetDelete = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: publicSheetFlags(), + Flags: flagsFor("+sheet-delete"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err @@ -202,9 +197,7 @@ var SheetRename = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicSheetFlags(), - common.Flag{Name: "title", Desc: "new sheet title", Required: true}, - ), + Flags: flagsFor("+sheet-rename"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err @@ -269,10 +262,7 @@ var SheetMove = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:read", "sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicSheetFlags(), - common.Flag{Name: "index", Type: "int", Required: true, Desc: "target position (0-based)"}, - common.Flag{Name: "source-index", Type: "int", Default: "-1", Desc: "source position (0-based); omitted → auto-derived from --sheet-id/--sheet-name's current workbook position"}, - ), + Flags: flagsFor("+sheet-move"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err @@ -367,10 +357,7 @@ var SheetCopy = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicSheetFlags(), - common.Flag{Name: "title", Desc: "title for the duplicated sheet (server-generated when omitted)"}, - common.Flag{Name: "index", Type: "int", Default: "-1", Desc: "insertion position for the copy (0-based); omit to append"}, - ), + Flags: flagsFor("+sheet-copy"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err @@ -432,7 +419,7 @@ func newSheetVisibilityShortcut(command, desc, op string) common.Shortcut { Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: publicSheetFlags(), + Flags: flagsFor(command), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err @@ -477,9 +464,7 @@ var SheetSetTabColor = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicSheetFlags(), - common.Flag{Name: "color", Desc: "hex color like #FF0000; pass empty string to clear"}, - ), + Flags: flagsFor("+sheet-set-tab-color"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err @@ -545,12 +530,7 @@ var WorkbookCreate = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:create", "sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: []common.Flag{ - {Name: "title", Required: true, Desc: "spreadsheet title"}, - {Name: "folder-token", Desc: "destination folder token; omit to land at the drive root"}, - {Name: "headers", Input: []string{common.File, common.Stdin}, Desc: "header row JSON array, e.g. [\"列A\",\"列B\"]"}, - {Name: "values", Input: []string{common.File, common.Stdin}, Desc: "initial data JSON 2D array, e.g. [[\"alice\",95]]"}, - }, + Flags: flagsFor("+workbook-create"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if strings.TrimSpace(runtime.Str("title")) == "" { return common.FlagErrorf("--title is required") @@ -707,11 +687,7 @@ var WorkbookExport = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:read", "docs:document:export", "drive:drive.metadata:readonly"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicTokenFlags(), - common.Flag{Name: "file-extension", Enum: []string{"xlsx", "csv"}, Default: "xlsx", Desc: "xlsx (whole workbook) or csv (one sheet via --sheet-id)"}, - common.Flag{Name: "sheet-id", Desc: "csv mode only: target sheet reference_id to export"}, - common.Flag{Name: "output-path", Desc: "local file path to save into; omit to just trigger and report the file_token"}, - ), + Flags: flagsFor("+workbook-export"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err diff --git a/shortcuts/sheets/lark_sheet_workbook_test.go b/shortcuts/sheets/lark_sheet_workbook_test.go index eaa49d16c..f7b257fc2 100644 --- a/shortcuts/sheets/lark_sheet_workbook_test.go +++ b/shortcuts/sheets/lark_sheet_workbook_test.go @@ -159,10 +159,10 @@ func TestSheetMove_DryRunResolvePlaceholders(t *testing.T) { t.Parallel() cases := []struct { - name string - args []string - wantSheetID string - wantSourceIdx interface{} + name string + args []string + wantSheetID string + wantSourceIdx interface{} }{ { name: "id only, no source-index → both literal + placeholder", diff --git a/shortcuts/sheets/lark_sheet_write_cells.go b/shortcuts/sheets/lark_sheet_write_cells.go index 7d61f5a95..527d6d5f8 100644 --- a/shortcuts/sheets/lark_sheet_write_cells.go +++ b/shortcuts/sheets/lark_sheet_write_cells.go @@ -42,13 +42,7 @@ var CellsSet = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicSheetFlags(), - common.Flag{Name: "range", Required: true, Desc: "target A1 range (e.g. A1:C10); cells dimensions must match"}, - common.Flag{Name: "cells", Input: []string{common.File, common.Stdin}, Required: true, - Desc: "JSON 2D matrix of cell objects, e.g. [[{\"value\":\"a\"},{\"value\":\"b\"}],[{\"value\":1},{\"value\":2}]]; dimensions must match --range"}, - common.Flag{Name: "allow-overwrite", Type: "bool", Default: "true", Desc: "allow overwriting non-empty cells (default true)"}, - common.Flag{Name: "max-cells", Type: "int", Default: "50000", Hidden: true, Desc: "anti-burst cells write cap"}, - ), + Flags: flagsFor("+cells-set"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err @@ -123,11 +117,7 @@ var CellsSetStyle = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append( - append(publicSheetFlags(), - common.Flag{Name: "range", Required: true, Desc: "target A1 range (e.g. A1:B2)"}), - styleFlatFlags()..., - ), + Flags: flagsFor("+cells-set-style"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err @@ -223,13 +213,7 @@ var CsvPut = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicSheetFlags(), - common.Flag{Name: "csv", Input: []string{common.File, common.Stdin}, Required: true, - Desc: "CSV text (RFC 4180); supports @file or stdin via -"}, - common.Flag{Name: "start-cell", Default: "A1", Required: true, Desc: "single A1 anchor cell, e.g. A1 / B5"}, - common.Flag{Name: "allow-overwrite", Type: "bool", Default: "true", - Desc: "allow overwriting non-empty cells (default true); false errors if any target cell is non-empty"}, - ), + Flags: flagsFor("+csv-put"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err @@ -300,15 +284,7 @@ var DropdownSet = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicSheetFlags(), - common.Flag{Name: "range", Required: true, Desc: "target A1 range (e.g. A2:A100)"}, - common.Flag{Name: "options", Input: []string{common.File, common.Stdin}, Required: true, - Desc: "options JSON array (e.g. [\"opt1\",\"opt2\"]); ≤500 items, ≤100 chars each, no commas"}, - common.Flag{Name: "colors", Input: []string{common.File, common.Stdin}, - Desc: "optional RGB hex array (e.g. [\"#1FB6C1\",\"#F006C2\"]); length must equal --options"}, - common.Flag{Name: "multiple", Type: "bool", Desc: "enable multi-select; default false"}, - common.Flag{Name: "highlight", Type: "bool", Desc: "color-highlight options; default false"}, - ), + Flags: flagsFor("+dropdown-set"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err @@ -551,11 +527,7 @@ var CellsSetImage = common.Shortcut{ Scopes: []string{"sheets:spreadsheet:write_only", "drive:file:upload"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, - Flags: append(publicSheetFlags(), - common.Flag{Name: "range", Required: true, Desc: "single target cell (e.g. A1; start/end must equal)"}, - common.Flag{Name: "image", Required: true, Desc: "local image path (PNG/JPEG/JPG/GIF/BMP/JFIF/EXIF/TIFF/BPG/HEIC)"}, - common.Flag{Name: "name", Desc: "uploaded file name (with extension); defaults to basename(--image)"}, - ), + Flags: flagsFor("+cells-set-image"), Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if _, err := resolveSpreadsheetToken(runtime); err != nil { return err diff --git a/shortcuts/sheets/shortcuts.go b/shortcuts/sheets/shortcuts.go index 8c7a5c708..c71ef5572 100644 --- a/shortcuts/sheets/shortcuts.go +++ b/shortcuts/sheets/shortcuts.go @@ -14,7 +14,6 @@ import "github.com/larksuite/cli/shortcuts/common" // `--print-schema --flag-name ` locally. func Shortcuts() []common.Shortcut { all := shortcutList() - applyFlagDescs(all) withSchema := commandsWithFlagSchema() for i := range all { if _, ok := withSchema[all[i].Command]; ok { diff --git a/skills/lark-sheets/references/lark-sheets-batch-update.md b/skills/lark-sheets/references/lark-sheets-batch-update.md index 0590be694..1fdd28a73 100644 --- a/skills/lark-sheets/references/lark-sheets-batch-update.md +++ b/skills/lark-sheets/references/lark-sheets-batch-update.md @@ -37,7 +37,8 @@ _公共:URL/token(无 sheet 定位) · 系统:`--yes`、`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--operations` | string + File + Stdin(复合 JSON) | 是 | JSON:`{"operations":[{"tool":"`+cells-set`","params":{...}}, ...]}`;按数组顺序串行执行 | +| `--operations` | string + File + Stdin(复合 JSON) | required | JSON 数组:`[{"tool_name":"`+cells-set`","input":{...}}, ...]`,按声明顺序串行执行;`tool_name` 为底层工具名(如 `+cells-set` / `+cells-clear` / `+dim-{insert|delete|hide|unhide|freeze|group|ungroup}`),`input` 结构与单独调用该工具一致 | +| `--continue-on-error` | bool | optional | 遇子操作失败时继续执行剩余操作;默认 false(首个失败即整批中断) | ### `+cells-batch-set-style` @@ -45,18 +46,18 @@ _公共:URL/token(无 sheet 定位) · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--ranges` | string + File + Stdin(简单 JSON) | 是 | 目标范围 JSON 数组,每项必须带 sheet 前缀(如 `["sheet1!A1:B2","sheet1!D1:D10"]`);所有 range 应用同一组 style | -| `--background-color` | string | 否 | 背景颜色(十六进制,如 `#ffffff`) | -| `--font-color` | string | 否 | 字体颜色(十六进制,如 `#000000`) | -| `--font-size` | number | 否 | 字体大小(px,例:10、12、14) | -| `--font-style` | string + Enum | 否 | 字体样式 enum:`normal` / `italic` | -| `--font-weight` | string + Enum | 否 | 字重 enum:`normal` / `bold` | -| `--font-line` | string + Enum | 否 | 字体线条样式 enum:`none` / `underline` / `line-through` | -| `--horizontal-alignment` | string + Enum | 否 | 水平对齐 enum:`left` / `center` / `right` | -| `--vertical-alignment` | string + Enum | 否 | 垂直对齐 enum:`top` / `middle` / `bottom` | -| `--word-wrap` | string + Enum | 否 | 换行策略 enum:`overflow` / `auto-wrap` / `word-clip`,默认 `overflow` | -| `--number-format` | string | 否 | 数字格式(例:文本 `@`、数字 `0.00`、货币 `$#,##0.00`、日期 `mm/dd/yyyy`) | -| `--border-styles` | string + File + Stdin(复合 JSON) | 否 | 边框配置 JSON(结构同 +cells-set-style) | +| `--ranges` | string + File + Stdin(简单 JSON) | required | 目标范围 JSON 数组,每项必须带 sheet 前缀(如 `["sheet1!A1:B2","sheet1!D1:D10"]`);所有 range 应用同一组 style | +| `--background-color` | string | optional | 背景颜色(十六进制,如 `#ffffff`) | +| `--font-color` | string | optional | 字体颜色(十六进制,如 `#000000`) | +| `--font-size` | float64 | optional | 字体大小(px,例:10、12、14) | +| `--font-style` | string | optional | 字体样式(可选值:`normal` / `italic`) | +| `--font-weight` | string | optional | 字重(可选值:`normal` / `bold`) | +| `--font-line` | string | optional | 字体线条样式(可选值:`none` / `underline` / `line-through`) | +| `--horizontal-alignment` | string | optional | 水平对齐(可选值:`left` / `center` / `right`) | +| `--vertical-alignment` | string | optional | 垂直对齐(可选值:`top` / `middle` / `bottom`) | +| `--word-wrap` | string | optional | 换行策略(可选值:`overflow` / `auto-wrap` / `word-clip`) | +| `--number-format` | string | optional | 数字格式(例:文本 `@`、数字 `0.00`、货币 `$#,##0.00`、日期 `mm/dd/yyyy`) | +| `--border-styles` | string + File + Stdin(复合 JSON) | optional | 边框配置 JSON(结构同 +cells-set-style) | ### `+dropdown-update` @@ -64,11 +65,11 @@ _公共:URL/token(无 sheet 定位) · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--ranges` | string + File + Stdin(简单 JSON) | 是 | 目标范围 JSON 数组(如 `["sheet1!A2:A100"]`),每项必须带 sheet 前缀 | -| `--options` | string + File + Stdin(复合 JSON) | 是 | 选项 JSON 数组(如 `["opt1","opt2"]`) | -| `--colors` | string + File + Stdin(简单 JSON) | 否 | 颜色数组(与 `--options` 等长) | -| `--multiple` | bool | 否 | 启用多选 | -| `--highlight` | bool | 否 | 选项配色 | +| `--ranges` | string + File + Stdin(简单 JSON) | required | 目标范围 JSON 数组(如 `["sheet1!A2:A100"]`),每项必须带 sheet 前缀 | +| `--options` | string + File + Stdin(复合 JSON) | required | 选项 JSON 数组(如 `["opt1","opt2"]`) | +| `--colors` | string + File + Stdin(简单 JSON) | optional | 颜色数组(与 `--options` 等长) | +| `--multiple` | bool | optional | 启用多选 | +| `--highlight` | bool | optional | 选项配色 | ### `+dropdown-delete` @@ -76,7 +77,7 @@ _公共:URL/token(无 sheet 定位) · 系统:`--yes`、`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--ranges` | string + File + Stdin(简单 JSON) | 是 | 目标范围 JSON 数组(最多 100 个,每项必须带 sheet 前缀) | +| `--ranges` | string + File + Stdin(简单 JSON) | required | 目标范围 JSON 数组(最多 100 个,每项必须带 sheet 前缀) | ## Schemas @@ -102,16 +103,10 @@ _单元格边框配置,含 top/bottom/left/right 四个方向,每个方向 ### `+dropdown-update` `--options` -_数据验证配置_ +_列表选项(type='list' 时必填)_ -**顶层字段**: -- `help_text` (string?) — 验证失败时显示的提示文本 -- `items` (array?) — 列表选项(type='list' 时必填) -- `operator` (enum?) — 比较运算符(type='number'/'date'/'textLength' 时必填) [equal / notEqual / greaterThan / greaterThanOrEqual / lessThan / lessThanOrEqual / between / notBetween] -- `range` (string?) — 源数据区域(type='listFromRange' 时必填,格式:'SheetName!A1:A10') -- `support_multiple_values` (boolean?) — 列表验证是否支持多选(type='list'/'listFromRange' 时可选,默认 false) -- `type` (enum) — 数据验证类型:list(下拉列表)、listFromRange(引用范围下拉列表)、number(数字)、date(日期)、textLength(文本长度)、… [list / listFromRange / number / date / textLength / checkbox] -- `values` (array?) — 比较值(operator 为 'between'/'notBetween' 时需要两个值,其它运算符需要一个值) +**数组项**(类型 string): +- 标量:string ## Examples @@ -125,10 +120,10 @@ _数据验证配置_ lark-cli sheets +batch-update --url "https://example.feishu.cn/sheets/shtXXX" --yes \ --operations @ops.json -# ops.json (array<{tool_name, input}>): +# ops.json (array<{tool_name, input}>,tool_name 是 CLI shortcut 名): # [ -# {"tool_name": "modify_sheet_structure", "input": {"sheet_id":"...","operation":"insert","dimension":"row","start":10,"end":12}}, -# {"tool_name": "set_cell_range", "input": {"sheet_id":"...","range":"A11:B12","cells":[[{"value":"a"},{"value":"b"}],[{"value":"c"},{"value":"d"}]]}} +# {"tool_name": "+dim-insert", "input": {"sheet_id":"...","dimension":"row","start":10,"end":12}}, +# {"tool_name": "+cells-set", "input": {"sheet_id":"...","range":"A11:B12","cells":[[{"value":"a"},{"value":"b"}],[{"value":"c"},{"value":"d"}]]}} # ] ``` @@ -137,9 +132,9 @@ lark-cli sheets +batch-update --url "https://example.feishu.cn/sheets/shtXXX" -- > ```jsonc > // 在 C 列前插入新列 → 写表头 C1 → 回填 C2:C100 共 99 行 > [ -> {"tool_name": "`+dim-{insert|delete|hide|unhide|freeze|group|ungroup}`", -> "input": {"sheet_id": "...", "operation": "insert", "dimension": "column", "start": 3, "end": 4}}, -> {"tool_name": "`+cells-set`", +> {"tool_name": "+dim-insert", +> "input": {"sheet_id": "...", "dimension": "column", "start": 3, "end": 4}}, +> {"tool_name": "+cells-set", > "input": {"sheet_id": "...", "range": "C1:C100", > "cells": [[{"value":"score"}], [{"value":95}], [{"value":87}], /* ... 97 more rows ... */ ]}} > ] diff --git a/skills/lark-sheets/references/lark-sheets-chart.md b/skills/lark-sheets/references/lark-sheets-chart.md index 3b7012a7c..4ea612bed 100644 --- a/skills/lark-sheets/references/lark-sheets-chart.md +++ b/skills/lark-sheets/references/lark-sheets-chart.md @@ -111,7 +111,7 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--chart-id` | string | 否 | 指定单个图表 reference_id 过滤 | +| `--chart-id` | string | optional | 指定单个图表 reference_id 过滤 | ### `+chart-create` @@ -119,7 +119,7 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--properties` | string + File + Stdin(复合 JSON) | 是 | 图表完整配置 JSON(`position` / `data` / `properties` 等);结构嵌套深,统一走 JSON 注入 | +| `--properties` | string + File + Stdin(复合 JSON) | required | 图表完整配置 JSON(`position` / `data` / `properties` 等);结构嵌套深,统一走 JSON 注入 | ### `+chart-update` @@ -127,8 +127,8 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--chart-id` | string | 是 | 目标图表 reference_id | -| `--properties` | string + File + Stdin(复合 JSON) | 是 | 完整或足够完整的图表配置 JSON(先 `+chart-list` 回读再 patch) | +| `--chart-id` | string | required | 目标图表 reference_id | +| `--properties` | string + File + Stdin(复合 JSON) | required | 完整或足够完整的图表配置 JSON(先 `+chart-list` 回读再 patch) | ### `+chart-delete` @@ -136,7 +136,7 @@ _公共四件套 · 系统:`--yes`、`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--chart-id` | string | 是 | 目标图表 reference_id | +| `--chart-id` | string | required | 目标图表 reference_id | ## Schemas diff --git a/skills/lark-sheets/references/lark-sheets-conditional-format.md b/skills/lark-sheets/references/lark-sheets-conditional-format.md index d305f5564..b8c69eb1b 100644 --- a/skills/lark-sheets/references/lark-sheets-conditional-format.md +++ b/skills/lark-sheets/references/lark-sheets-conditional-format.md @@ -87,7 +87,7 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--rule-id` | string | 否 | 按规则 id 过滤 | +| `--rule-id` | string | optional | 按规则 id 过滤 | ### `+cond-format-create` @@ -95,9 +95,9 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--properties` | string + File + Stdin(复合 JSON) | 是 | 规则配置 JSON,含 `style`(命中样式,必填)和 `attrs?`(规则参数列表,因 `rule_type` 不同结构而异)/ `has_ref?`。`rule_type` 和 `ranges` 已拎为独立 flag | -| `--rule-type` | string + Enum | 是 | 条件格式规则类型 enum:`cellValue` / `formula` / `duplicate` / `unique` / `topBottom` / `aboveBelowAverage` / `dataBar` / `colorScale` / `iconSet` / `textContains` / `dateOccurring` / `blankCell` / `errorCell`(共 13 项);优先级高于 `--properties` 中同名字段 | -| `--ranges` | string + File + Stdin(简单 JSON) | 是 | 应用条件格式的 A1 范围 JSON 数组(如 `["A1:A100","C2:C50"]`);优先级高于 `--properties` 中同名字段 | +| `--properties` | string + File + Stdin(复合 JSON) | required | 规则配置 JSON,含 `style`(命中样式,必填)和 `attrs?`(规则参数列表,因 `rule_type` 不同结构而异)/ `has_ref?`。`rule_type` 和 `ranges` 已拎为独立 flag | +| `--rule-type` | string | required | 条件格式规则类型;优先级高于 `--properties` 中同名字段(可选值:`cellValue` / `formula` / `duplicate` / `unique` / `topBottom` / `aboveBelowAverage` / `dataBar` / `colorScale` / `iconSet` / `textContains` / `dateOccurring` / `blankCell` / `errorCell`) | +| `--ranges` | string + File + Stdin(简单 JSON) | required | 应用条件格式的 A1 范围 JSON 数组(如 `["A1:A100","C2:C50"]`);优先级高于 `--properties` 中同名字段 | ### `+cond-format-update` @@ -105,10 +105,10 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--rule-id` | string | 是 | 目标规则 id | -| `--properties` | string + File + Stdin(复合 JSON) | 是 | 规则配置 JSON,结构同 `+cond-format-create` 的 `--properties`;update 是整组覆盖式 | -| `--rule-type` | string + Enum | 是 | 条件格式规则类型 enum:`cellValue` / `formula` / `duplicate` / `unique` / `topBottom` / `aboveBelowAverage` / `dataBar` / `colorScale` / `iconSet` / `textContains` / `dateOccurring` / `blankCell` / `errorCell`(共 13 项);优先级高于 `--properties` 中同名字段 | -| `--ranges` | string + File + Stdin(简单 JSON) | 是 | 应用条件格式的 A1 范围 JSON 数组(如 `["A1:A100","C2:C50"]`);优先级高于 `--properties` 中同名字段 | +| `--rule-id` | string | required | 目标规则 id | +| `--properties` | string + File + Stdin(复合 JSON) | required | 规则配置 JSON,结构同 `+cond-format-create` 的 `--properties`;update 是整组覆盖式 | +| `--rule-type` | string | required | 条件格式规则类型;优先级高于 `--properties` 中同名字段(可选值:`cellValue` / `formula` / `duplicate` / `unique` / `topBottom` / `aboveBelowAverage` / `dataBar` / `colorScale` / `iconSet` / `textContains` / `dateOccurring` / `blankCell` / `errorCell`) | +| `--ranges` | string + File + Stdin(简单 JSON) | required | 应用条件格式的 A1 范围 JSON 数组(如 `["A1:A100","C2:C50"]`);优先级高于 `--properties` 中同名字段 | ### `+cond-format-delete` @@ -116,7 +116,7 @@ _公共四件套 · 系统:`--yes`、`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--rule-id` | string | 是 | 目标规则 id | +| `--rule-id` | string | required | 目标规则 id | ## Schemas @@ -147,7 +147,7 @@ _创建/更新的条件格式属性_ # 重复值高亮 lark-cli sheets +cond-format-create --url "..." --sheet-id "$SID" \ --rule-type duplicate --ranges '["A1:A100"]' \ - --properties '{"style":{"background_color":"#FFD7D7"}}' + --properties '{"style":{"back_color":"#FFD7D7"}}' # 数据条 lark-cli sheets +cond-format-create --url "..." --sheet-id "$SID" \ diff --git a/skills/lark-sheets/references/lark-sheets-filter-view.md b/skills/lark-sheets/references/lark-sheets-filter-view.md index d35ed4cee..6da48d78a 100644 --- a/skills/lark-sheets/references/lark-sheets-filter-view.md +++ b/skills/lark-sheets/references/lark-sheets-filter-view.md @@ -40,7 +40,7 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--view-id` | string | 否 | 按筛选视图 reference_id 过滤(命中即只返回单个视图) | +| `--view-id` | string | optional | 按筛选视图 reference_id 过滤(命中即只返回单个视图) | ### `+filter-view-create` @@ -48,9 +48,9 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--properties` | string + File + Stdin(复合 JSON) | 是 | 筛选视图规则 JSON,含 `rules?`(列级筛选规则数组)和 `filtered_columns?`。`range` 和 `view_name` 是独立 flag | -| `--range` | string | 是 | 筛选视图作用的单元格范围(A1 表示法,如 `A1:F1000`);优先级高于 `--properties` 中同名字段;create 必填,必须覆盖表头行 | -| `--view-name` | string | 否 | 筛选视图名称;create 不传时系统自动分配,update 不传时保留原名;优先级高于 `--properties` 中同名字段 | +| `--properties` | string + File + Stdin(复合 JSON) | required | 筛选视图规则 JSON,含 `rules?`(列级筛选规则数组)和 `filtered_columns?`。`range` 和 `view_name` 是独立 flag | +| `--range` | string | required | 筛选视图作用的单元格范围(A1 表示法,如 `A1:F1000`);优先级高于 `--properties` 中同名字段;create 必填,必须覆盖表头行 | +| `--view-name` | string | optional | 筛选视图名称;create 不传时系统自动分配,update 不传时保留原名;优先级高于 `--properties` 中同名字段 | ### `+filter-view-update` @@ -58,10 +58,10 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--view-id` | string | 是 | 目标筛选视图 reference_id | -| `--properties` | string + File + Stdin(复合 JSON) | 是 | 筛选视图规则 JSON,含 `rules?` 和 `filtered_columns?`。`range` 和 `view_name` 是独立 flag;至少传 `--properties.rules` / `--range` / `--view-name` 之一 | -| `--range` | string | 否 | 筛选视图作用的单元格范围(A1 表示法,如 `A1:F1000`);优先级高于 `--properties` 中同名字段;update 时省略表示保留当前 range | -| `--view-name` | string | 否 | 筛选视图名称;create 不传时系统自动分配,update 不传时保留原名;优先级高于 `--properties` 中同名字段 | +| `--view-id` | string | required | 目标筛选视图 reference_id | +| `--properties` | string + File + Stdin(复合 JSON) | required | 筛选视图规则 JSON,含 `rules?` 和 `filtered_columns?`。`range` 和 `view_name` 是独立 flag;至少传 `--properties.rules` / `--range` / `--view-name` 之一 | +| `--range` | string | optional | 筛选视图作用的单元格范围(A1 表示法,如 `A1:F1000`);优先级高于 `--properties` 中同名字段;update 时省略表示保留当前 range | +| `--view-name` | string | optional | 筛选视图名称;create 不传时系统自动分配,update 不传时保留原名;优先级高于 `--properties` 中同名字段 | ### `+filter-view-delete` @@ -69,7 +69,7 @@ _公共四件套 · 系统:`--yes`、`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--view-id` | string | 是 | 目标筛选视图 reference_id | +| `--view-id` | string | required | 目标筛选视图 reference_id | ## Schemas @@ -108,7 +108,7 @@ lark-cli sheets +filter-view-list --url "..." --sheet-id "$SID" --view-id vAbcde ```bash lark-cli sheets +filter-view-create --url "..." --sheet-id "$SID" \ --view-name "活跃用户" --range "A1:F1000" \ - --properties '{"rules":[{"col":"C","filter_type":"number","compare":"greater","expected":[100]}]}' + --properties '{"rules":[{"column_index":"C","conditions":[{"type":"number","compare_type":"greaterThan","values":[100]}]}]}' ``` > `--range` **必须覆盖表头行**(如 `A1:F1000`),不能只包含数据行;`--view-name` 重名时服务端自动改名。 diff --git a/skills/lark-sheets/references/lark-sheets-filter.md b/skills/lark-sheets/references/lark-sheets-filter.md index 055e42d17..04bef892e 100644 --- a/skills/lark-sheets/references/lark-sheets-filter.md +++ b/skills/lark-sheets/references/lark-sheets-filter.md @@ -50,8 +50,8 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--range` | string | 是 | 筛选范围(A1 表示法,含表头行,如 `A1:F1000`);不要重复写入 `--properties` 中的 range 字段 | -| `--properties` | string + File + Stdin(复合 JSON) | 否 | 筛选规则 JSON,含 `rules`(列级筛选规则数组,必填)和 `filtered_columns?`(激活列索引提示)。`range` 是独立 flag(不要再放此 JSON 里) | +| `--range` | string | required | 筛选范围(A1 表示法,含表头行,如 `A1:F1000`);不要重复写入 `--properties` 中的 range 字段 | +| `--properties` | string + File + Stdin(复合 JSON) | optional | 筛选规则 JSON,含 `rules`(列级筛选规则数组,必填)和 `filtered_columns?`(激活列索引提示)。`range` 是独立 flag(不要再放此 JSON 里) | ### `+filter-update` @@ -59,8 +59,8 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--properties` | string + File + Stdin(复合 JSON) | 是 | 筛选规则 JSON,含 `rules` 和 `filtered_columns?`;update 是整组覆盖式(传空 `rules: []` 清空)。`range` 已拎为独立 flag | -| `--range` | string | 是 | 筛选作用的单元格范围(A1 表示法,如 `A1:F1000`);优先级高于 `--properties` 中同名字段 | +| `--properties` | string + File + Stdin(复合 JSON) | required | 筛选规则 JSON,含 `rules` 和 `filtered_columns?`;update 是整组覆盖式(传空 `rules: []` 清空)。`range` 已拎为独立 flag | +| `--range` | string | required | 筛选作用的单元格范围(A1 表示法,如 `A1:F1000`);优先级高于 `--properties` 中同名字段 | ### `+filter-delete` @@ -94,7 +94,7 @@ _创建/更新的筛选器属性_ ```bash lark-cli sheets +filter-create --url "..." --sheet-id "$SID" \ --range "A1:F1000" \ - --properties '{"rules":[{"col":"B","filter_type":"multiValue","expected":["北京","上海"]}]}' + --properties '{"rules":[{"column_index":"B","conditions":[{"type":"multiValue","compare_type":"equal","values":["北京","上海"]}]}]}' ``` ### `+filter-update` diff --git a/skills/lark-sheets/references/lark-sheets-float-image.md b/skills/lark-sheets/references/lark-sheets-float-image.md index 25d23b4cc..83cb373fd 100644 --- a/skills/lark-sheets/references/lark-sheets-float-image.md +++ b/skills/lark-sheets/references/lark-sheets-float-image.md @@ -51,7 +51,7 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--float-image-id` | string | 否 | 按 id 过滤;省略时列工作表全部 | +| `--float-image-id` | string | optional | 按 id 过滤;省略时列工作表全部 | ### `+float-image-create` @@ -59,16 +59,16 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--image-name` | string | 是 | 图片名称,含扩展名(如 `logo.png`) | -| `--image-token` | string | XOR | 图片 file_token(与 `--image-uri` 二选一)。常见来源:`+float-image-list` 返回的 `image_token` | -| `--image-uri` | string | XOR | 图片 reference_id(与 `--image-token` 二选一);形如 `<\|image\|>:abcdef` 这种带前缀的字符串 | -| `--position-row` | int | 是 | 图片左上角所在行(0-based) | -| `--position-col` | string | 是 | 图片左上角所在列(列字母,如 `A` / `B`) | -| `--size-width` | int | 是 | 图片宽度(像素) | -| `--size-height` | int | 是 | 图片高度(像素) | -| `--offset-row` | int | 否 | 在 `--position-row` 基础上的行内偏移(像素) | -| `--offset-col` | int | 否 | 在 `--position-col` 基础上的列内偏移(像素) | -| `--z-index` | int | 否 | 图片 Z 轴层级,控制重叠顺序 | +| `--image-name` | string | required | 图片名称,含扩展名(如 `logo.png`) | +| `--image-token` | string | xor | 图片 file_token(与 `--image-uri` 二选一)。常见来源:`+float-image-list` 返回的 `image_token` | +| `--image-uri` | string | xor | 图片 reference_id(与 `--image-token` 二选一);形如 `<\|image\|>:abcdef` 这种带前缀的字符串 | +| `--position-row` | int | required | 图片左上角所在行(0-based) | +| `--position-col` | string | required | 图片左上角所在列(列字母,如 `A` / `B`) | +| `--size-width` | int | required | 图片宽度(像素) | +| `--size-height` | int | required | 图片高度(像素) | +| `--offset-row` | int | optional | 在 `--position-row` 基础上的行内偏移(像素) | +| `--offset-col` | int | optional | 在 `--position-col` 基础上的列内偏移(像素) | +| `--z-index` | int | optional | 图片 Z 轴层级,控制重叠顺序 | ### `+float-image-update` @@ -76,17 +76,17 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--float-image-id` | string | 是 | 目标图片 id | -| `--image-name` | string | 是 | 图片名称,含扩展名(如 `logo.png`) | -| `--image-token` | string | XOR | 图片 file_token(与 `--image-uri` 二选一)。常见来源:`+float-image-list` 返回的 `image_token` | -| `--image-uri` | string | XOR | 图片 reference_id(与 `--image-token` 二选一);形如 `<\|image\|>:abcdef` 这种带前缀的字符串 | -| `--position-row` | int | 是 | 图片左上角所在行(0-based) | -| `--position-col` | string | 是 | 图片左上角所在列(列字母,如 `A` / `B`) | -| `--size-width` | int | 是 | 图片宽度(像素) | -| `--size-height` | int | 是 | 图片高度(像素) | -| `--offset-row` | int | 否 | 在 `--position-row` 基础上的行内偏移(像素) | -| `--offset-col` | int | 否 | 在 `--position-col` 基础上的列内偏移(像素) | -| `--z-index` | int | 否 | 图片 Z 轴层级,控制重叠顺序 | +| `--float-image-id` | string | required | 目标图片 id | +| `--image-name` | string | required | 图片名称,含扩展名(如 `logo.png`) | +| `--image-token` | string | xor | 图片 file_token(与 `--image-uri` 二选一)。常见来源:`+float-image-list` 返回的 `image_token` | +| `--image-uri` | string | xor | 图片 reference_id(与 `--image-token` 二选一);形如 `<\|image\|>:abcdef` 这种带前缀的字符串 | +| `--position-row` | int | required | 图片左上角所在行(0-based) | +| `--position-col` | string | required | 图片左上角所在列(列字母,如 `A` / `B`) | +| `--size-width` | int | required | 图片宽度(像素) | +| `--size-height` | int | required | 图片高度(像素) | +| `--offset-row` | int | optional | 在 `--position-row` 基础上的行内偏移(像素) | +| `--offset-col` | int | optional | 在 `--position-col` 基础上的列内偏移(像素) | +| `--z-index` | int | optional | 图片 Z 轴层级,控制重叠顺序 | ### `+float-image-delete` @@ -94,7 +94,7 @@ _公共四件套 · 系统:`--yes`、`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--float-image-id` | string | 是 | 目标图片 id | +| `--float-image-id` | string | required | 目标图片 id | ## Examples @@ -120,12 +120,24 @@ lark-cli sheets +float-image-create --url "..." --sheet-id "$SID" \ ### `+float-image-update` -> 必须先 `+float-image-list --float-image-id ` 回读当前完整属性,再通过 `--image-name` / `--position-*` / `--size-*` 等独立 flag 改对应字段。 +> **patch 模式**:除了 `--float-image-id`(必填,定位目标图片)外,其它字段都可选——只传你需要改的那几个,未传的字段保持原值不变。至少传一个改动字段。 +> +> 推荐流程:先 `+float-image-list --float-image-id ` 回读当前完整属性,再针对要改的字段调一次 `+float-image-update`。 + +```bash +# 只改位置,保留其它属性 +lark-cli sheets +float-image-update --url "..." --sheet-id "$SID" \ + --float-image-id "$IMG_ID" --position-row 5 --position-col C + +# 只换图,位置/尺寸不变 +lark-cli sheets +float-image-update --url "..." --sheet-id "$SID" \ + --float-image-id "$IMG_ID" --image-name "new-logo.png" --image-token "$NEW_TOKEN" +``` ### `+float-image-delete` ### Validate / DryRun / Execute 约束 -- `Validate`:XOR 公共四件套;`+float-image-create` 校验 `--image-name` 非空,`--image-token` 与 `--image-uri` 互斥且至少一个非空,`--position-row/col` 与 `--size-width/height` 必填且为合法整数;`+float-image-update` 必须 `--float-image-id`;`+float-image-delete` 强制 `--yes` 或 `--dry-run`。 +- `Validate`:XOR 公共四件套;`+float-image-create` 校验 `--image-name` 非空,`--image-token` 与 `--image-uri` 互斥且至少一个非空,`--position-row/col` 与 `--size-width/height` 必填且为合法整数;`+float-image-update` 必须 `--float-image-id`,其余 `--image-name` / `--image-token` / `--image-uri` / `--position-*` / `--size-*` / `--offset-*` / `--z-index` 至少传 1 个(patch 模式:未传字段保持原值);`+float-image-delete` 强制 `--yes` 或 `--dry-run`。 - `DryRun`:写操作输出"将要 POST/PATCH/DELETE 的 float_image 请求模板"。 - `Execute`:写后调用 `+float-image-list --float-image-id ` 回读,envelope.meta.verification 给出新位置 / 尺寸对比。 diff --git a/skills/lark-sheets/references/lark-sheets-pivot-table.md b/skills/lark-sheets/references/lark-sheets-pivot-table.md index 531a0de53..c30b3a8df 100644 --- a/skills/lark-sheets/references/lark-sheets-pivot-table.md +++ b/skills/lark-sheets/references/lark-sheets-pivot-table.md @@ -53,7 +53,7 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--pivot-table-id` | string | 否 | 按 id 过滤 | +| `--pivot-table-id` | string | optional | 按 id 过滤 | ### `+pivot-create` @@ -61,11 +61,11 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--properties` | string + File + Stdin(复合 JSON) | 是 | JSON:`{"data_range":"Sheet1!A1:F1000","rows":[...],"columns":[...],"values":[...],"filters":[...],"show_row_grand_total":true,"show_col_grand_total":true}` | -| `--target-sheet-id` | string | 否 | 透视表落点子表 id;省略时自动新建子表(推荐) | -| `--target-position` | string | 否 | 落点起始 cell(A1 格式,如 `A1`),默认 `A1` | -| `--source` | string | 是 | 透视表源数据区域(A1 表示法,格式 `SheetName!StartCell:EndCell`,如 `Sheet1!A1:D100`) | -| `--range` | string | 否 | 透视表放置位置(左上角 A1 单值,如 `F1`);省略时放在新建子表的左上角 | +| `--properties` | string + File + Stdin(复合 JSON) | required | JSON:`{"data_range":"Sheet1!A1:F1000","rows":[...],"columns":[...],"values":[...],"filters":[...],"show_row_grand_total":true,"show_col_grand_total":true}` | +| `--target-sheet-id` | string | optional | 透视表落点子表 id;省略时自动新建子表(推荐) | +| `--target-position` | string | optional | 落点起始 cell(A1 格式,如 `A1`),默认 `A1` | +| `--source` | string | required | 透视表源数据区域(A1 表示法,格式 `SheetName!StartCell:EndCell`,如 `Sheet1!A1:D100`) | +| `--range` | string | optional | 透视表放置位置(左上角 A1 单值,如 `F1`);省略时放在新建子表的左上角 | ### `+pivot-update` @@ -73,8 +73,8 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--pivot-table-id` | string | 是 | 目标透视表 id | -| `--properties` | string + File + Stdin(复合 JSON) | 是 | 完整或足够完整的配置(先 `+pivot-list --pivot-table-id ` 回读再 patch) | +| `--pivot-table-id` | string | required | 目标透视表 id | +| `--properties` | string + File + Stdin(复合 JSON) | required | 完整或足够完整的配置(先 `+pivot-list --pivot-table-id ` 回读再 patch) | ### `+pivot-delete` @@ -82,7 +82,7 @@ _公共四件套 · 系统:`--yes`、`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--pivot-table-id` | string | 是 | 目标透视表 id | +| `--pivot-table-id` | string | required | 目标透视表 id | ## Schemas diff --git a/skills/lark-sheets/references/lark-sheets-range-operations.md b/skills/lark-sheets/references/lark-sheets-range-operations.md index 0d3918c13..b6733b18d 100644 --- a/skills/lark-sheets/references/lark-sheets-range-operations.md +++ b/skills/lark-sheets/references/lark-sheets-range-operations.md @@ -101,8 +101,8 @@ _公共四件套 · 系统:`--yes`、`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--range` | string | 是 | 清除范围(A1 格式) | -| `--scope` | string + Enum | 否 | 清除范围 enum:`content`(默认,仅清内容)/ `formats`(仅清格式)/ `all`(清内容 + 格式) | +| `--range` | string | required | 清除范围(A1 格式) | +| `--scope` | string | optional | 清除范围 enum:`content`(默认,仅清内容)/ `formats`(仅清格式)/ `all`(清内容 + 格式)(可选值:`content` / `formats` / `all`) | ### `+cells-merge` @@ -110,8 +110,8 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--range` | string | 是 | 待合并 / 取消合并的范围(A1 格式) | -| `--merge-type` | string + Enum | 否 | 合并方向 enum(仅 `+cells-merge`):`all` / `rows` / `columns`,默认 `all` | +| `--range` | string | required | 待合并 / 取消合并的范围(A1 格式) | +| `--merge-type` | string | optional | 合并方向(仅 `+cells-merge`)(可选值:`all` / `rows` / `columns`) | ### `+cells-unmerge` @@ -119,8 +119,7 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--range` | string | 是 | 待合并 / 取消合并的范围(A1 格式) | -| `--merge-type` | string + Enum | 否 | 合并方向 enum(仅 `+cells-merge`):`all` / `rows` / `columns`,默认 `all` | +| `--range` | string | required | 待合并 / 取消合并的范围(A1 格式) | ### `+rows-resize` @@ -128,10 +127,10 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--start` | int | 是 | 起始行(0-based, inclusive) | -| `--end` | int | 是 | 结束行(0-based, inclusive) | -| `--type` | string + Enum | 是 | 尺寸方式 enum:`pixel`(指定 px 像素值,需配 `--size`)/ `standard`(重置为默认标准行高)/ `auto`(自动适应内容) | -| `--size` | int | 否 | 行高(像素,例:30 / 40 / 60);`--type pixel` 时必填,其它 type 忽略 | +| `--start` | int | required | 起始行(0-based, inclusive) | +| `--end` | int | required | 结束行(0-based, inclusive) | +| `--type` | string | required | 尺寸方式 enum:`pixel`(指定 px 像素值,需配 `--size`)/ `standard`(重置为默认标准行高)/ `auto`(自动适应内容)(可选值:`pixel` / `standard` / `auto`) | +| `--size` | int | optional | 行高(像素,例:30 / 40 / 60);`--type pixel` 时必填,其它 type 忽略 | ### `+cols-resize` @@ -139,10 +138,10 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--start` | int | 是 | 起始列(0-based, inclusive) | -| `--end` | int | 是 | 结束列(0-based, inclusive) | -| `--type` | string + Enum | 是 | 尺寸方式 enum:`pixel`(指定 px 像素值,需配 `--size`)/ `standard`(重置为默认标准列宽) | -| `--size` | int | 否 | 列宽(像素,例:80 / 120 / 200);`--type pixel` 时必填,其它 type 忽略 | +| `--start` | int | required | 起始列(0-based, inclusive) | +| `--end` | int | required | 结束列(0-based, inclusive) | +| `--type` | string | required | 尺寸方式 enum:`pixel`(指定 px 像素值,需配 `--size`)/ `standard`(重置为默认标准列宽)(可选值:`pixel` / `standard`) | +| `--size` | int | optional | 列宽(像素,例:80 / 120 / 200);`--type pixel` 时必填,其它 type 忽略 | ### `+range-move` @@ -150,10 +149,9 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--source-range` | string | 是 | 源 A1 范围 | -| `--target-sheet-id` | string | 否 | 目标子表 id;省略时同源 sheet | -| `--target-range` | string | 是 | 目标 A1 范围(传起点 cell 即可,按源尺寸自动推断) | -| `--paste-type` | string + Enum | 否 | 粘贴内容 enum(仅 `+range-copy`):`values` / `formulas` / `formats` / `all`,默认 `all` | +| `--source-range` | string | required | 源 A1 范围 | +| `--target-sheet-id` | string | optional | 目标子表 id;省略时同源 sheet | +| `--target-range` | string | required | 目标 A1 范围(传起点 cell 即可,按源尺寸自动推断) | ### `+range-copy` @@ -161,10 +159,10 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--source-range` | string | 是 | 源 A1 范围 | -| `--target-sheet-id` | string | 否 | 目标子表 id;省略时同源 sheet | -| `--target-range` | string | 是 | 目标 A1 范围(传起点 cell 即可,按源尺寸自动推断) | -| `--paste-type` | string + Enum | 否 | 粘贴内容 enum(仅 `+range-copy`):`values` / `formulas` / `formats` / `all`,默认 `all` | +| `--source-range` | string | required | 源 A1 范围 | +| `--target-sheet-id` | string | optional | 目标子表 id;省略时同源 sheet | +| `--target-range` | string | required | 目标 A1 范围(传起点 cell 即可,按源尺寸自动推断) | +| `--paste-type` | string | optional | 粘贴内容(仅 `+range-copy`)(可选值:`values` / `formulas` / `formats` / `all`) | ### `+range-fill` @@ -172,9 +170,9 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--source-range` | string | 是 | 填充模板范围(系列起始 cells) | -| `--target-range` | string | 是 | 目标填充范围(A1 格式) | -| `--series-type` | string + Enum | 否 | 填充序列类型 enum:`auto` / `linear` / `growth` / `date` / `copy`,默认 `auto` | +| `--source-range` | string | required | 填充模板范围(系列起始 cells) | +| `--target-range` | string | required | 目标填充范围(A1 格式) | +| `--series-type` | string | optional | 填充序列类型(可选值:`auto` / `linear` / `growth` / `date` / `copy`) | ### `+range-sort` @@ -182,9 +180,9 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--range` | string | 是 | 排序范围(A1 格式;含或不含表头由 `--has-header` 决定) | -| `--sort-keys` | string + File + Stdin(复合 JSON) | 是 | JSON:`[{"col":"B","order":"asc"},{"col":"D","order":"desc"}]` | -| `--has-header` | bool | 否 | 第一行是表头不参与排序,默认 false | +| `--range` | string | required | 排序范围(A1 格式;含或不含表头由 `--has-header` 决定) | +| `--sort-keys` | string + File + Stdin(复合 JSON) | required | JSON 数组:`[{"column":"<列字母>","ascending":}, ...]` | +| `--has-header` | bool | optional | 第一行是表头不参与排序,默认 false | ## Schemas diff --git a/skills/lark-sheets/references/lark-sheets-read-data.md b/skills/lark-sheets/references/lark-sheets-read-data.md index 11315f579..4471d62c1 100644 --- a/skills/lark-sheets/references/lark-sheets-read-data.md +++ b/skills/lark-sheets/references/lark-sheets-read-data.md @@ -88,11 +88,11 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--range` | string | 是 | A1 范围,如 `Sheet1!A1:F10` | -| `--include` | string_slice + Enum | 否 | `value` / `formula` / `style` / `comment` / `data_validation`,逗号分隔 | -| `--cell-limit` | int + Hidden | 否 | 防爆,默认 5000 | -| `--max-chars` | int + Hidden | 否 | 防爆,默认 200000 | -| `--skip-hidden` | bool | 否 | 跳过隐藏行列,默认 `false` | +| `--range` | string_array | required | A1 范围,如 `Sheet1!A1:F10` | +| `--include` | string_slice | optional | 要返回的信息类别,逗号分隔多个(可选值:`value` / `formula` / `style` / `comment` / `data_validation`) | +| `--cell-limit` | int | optional | 防爆,默认 5000 | +| `--max-chars` | int | optional | 防爆,默认 200000 | +| `--skip-hidden` | bool | optional | 跳过隐藏行列,默认 `false` | ### `+dropdown-get` @@ -100,7 +100,7 @@ _公共:URL/token(无 sheet 定位) · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--range` | string | 是 | 目标范围(A1 格式,必须带 sheet 前缀,如 `sheet1!A2:A100`) | +| `--range` | string | required | 目标范围(A1 格式,必须带 sheet 前缀,如 `sheet1!A2:A100`) | ### `+csv-get` @@ -108,12 +108,12 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--range` | string | 否 | A1 范围;省略时读整表的 `current_region` | -| `--value-render-option` | string + Enum | 否 | 单元格取值模式 enum:`ToString` / `FormattedValue` / `Formula` / `UnformattedValue` | -| `--max-rows` | int + Hidden | 否 | 防爆,默认 100000 | -| `--max-chars` | int + Hidden | 否 | 防爆,默认 200000 | -| `--include-row-prefix` | bool | 否 | 是否在每行前加 `[row=N]` 前缀,默认 `true` | -| `--skip-hidden` | bool | 否 | 跳过隐藏行列,默认 `false` | +| `--range` | string | optional | A1 范围;省略时读整表的 `current_region` | +| `--value-render-option` | string | optional | 单元格取值模式(可选值:`formatted_value` / `raw_value` / `formula`) | +| `--max-rows` | int | optional | 防爆,默认 100000 | +| `--max-chars` | int | optional | 防爆,默认 200000 | +| `--include-row-prefix` | bool | optional | 是否在每行前加 `[row=N]` 前缀,默认 `true` | +| `--skip-hidden` | bool | optional | 跳过隐藏行列,默认 `false` | ## Examples diff --git a/skills/lark-sheets/references/lark-sheets-search-replace.md b/skills/lark-sheets/references/lark-sheets-search-replace.md index 7bc07bd2d..f0813bb9a 100644 --- a/skills/lark-sheets/references/lark-sheets-search-replace.md +++ b/skills/lark-sheets/references/lark-sheets-search-replace.md @@ -37,13 +37,14 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--find` | string | 是 | 待查找文本(与 `--regex` 配合时按正则解释) | -| `--range` | string | 否 | 查找范围(A1 格式);省略时整表 | -| `--match-case` | bool | 否 | 大小写敏感 | -| `--match-entire-cell` | bool | 否 | 完全匹配整个单元格 | -| `--regex` | bool | 否 | 把 `--find` 按正则解释 | -| `--include-formulas` | bool | 否 | 也在公式文本中搜索 | -| `--max-matches` | int + Hidden | 否 | 防爆,默认 5000 | +| `--find` | string | required | 待查找文本(与 `--regex` 配合时按正则解释) | +| `--range` | string | optional | 查找范围(A1 格式);省略时整表 | +| `--match-case` | bool | optional | 大小写敏感 | +| `--match-entire-cell` | bool | optional | 完全匹配整个单元格 | +| `--regex` | bool | optional | 把 `--find` 按正则解释 | +| `--include-formulas` | bool | optional | 也在公式文本中搜索 | +| `--max-matches` | int | optional | 防爆,默认 5000 | +| `--offset` | int | optional | 跳过前 N 个匹配(分页用),默认 0 | ### `+cells-replace` @@ -51,13 +52,13 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--find` | string | 是 | 待替换文本 | -| `--replacement` | string | 是 | 替换为;传空字符串 `""` 等价于「删除内容」 | -| `--range` | string | 否 | 替换范围(A1 格式);省略时整表 | -| `--match-case` | bool | 否 | 也在公式文本中替换 | -| `--match-entire-cell` | bool | 否 | 也在公式文本中替换 | -| `--regex` | bool | 否 | 也在公式文本中替换 | -| `--include-formulas` | bool | 否 | 也在公式文本中替换 | +| `--find` | string | required | 待替换文本 | +| `--replacement` | string | required | 替换为;传空字符串 `""` 等价于「删除内容」 | +| `--range` | string | optional | 替换范围(A1 格式);省略时整表 | +| `--match-case` | bool | optional | 大小写敏感 | +| `--match-entire-cell` | bool | optional | 完全匹配整个单元格 | +| `--regex` | bool | optional | 把 `--find` 按正则解释 | +| `--include-formulas` | bool | optional | 也在公式文本中替换 | ## Examples diff --git a/skills/lark-sheets/references/lark-sheets-sheet-structure.md b/skills/lark-sheets/references/lark-sheets-sheet-structure.md index b35440e46..2567e37d3 100644 --- a/skills/lark-sheets/references/lark-sheets-sheet-structure.md +++ b/skills/lark-sheets/references/lark-sheets-sheet-structure.md @@ -57,7 +57,8 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--include` | string_slice + Enum | 否 | `merges` / `row_heights` / `col_widths` / `hidden_rows` / `hidden_cols` / `groups` / `frozen`,逗号分隔 | +| `--include` | string_slice | optional | 要返回的结构信息类别,逗号分隔多个(可选值:`merges` / `row_heights` / `col_widths` / `hidden_rows` / `hidden_cols` / `groups` / `frozen`) | +| `--range` | string | optional | 限定只返回该 A1 范围的结构信息;省略时返回整表 | ### `+dim-insert` @@ -65,10 +66,10 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--dimension` | string + Enum | 是 | `row` / `column` | -| `--start` | int | 是 | 插入起始位置(0-based) | -| `--end` | int | 是 | 插入结束位置(exclusive) | -| `--inherit-style` | string + Enum | 否 | 新行/列样式继承策略 enum:`before`(继承前一行/列)/ `after`(继承后一行/列)/ `none`(默认) | +| `--dimension` | string | required | 维度方向(行或列)(可选值:`row` / `column`) | +| `--start` | int | required | 插入起始位置(0-based) | +| `--end` | int | required | 插入结束位置(exclusive) | +| `--inherit-style` | string | optional | 新行/列样式继承策略 enum:`before`(继承前一行/列)/ `after`(继承后一行/列)/ `none`(默认)(可选值:`before` / `after` / `none`) | ### `+dim-delete` @@ -76,9 +77,9 @@ _公共四件套 · 系统:`--yes`、`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--dimension` | string + Enum | 是 | `row` / `column` | -| `--start` | int | 是 | 起始位置(0-based) | -| `--end` | int | 是 | 结束位置(exclusive) | +| `--dimension` | string | required | 维度方向(行或列)(可选值:`row` / `column`) | +| `--start` | int | required | 起始位置(0-based) | +| `--end` | int | required | 结束位置(exclusive) | ### `+dim-hide` @@ -86,9 +87,9 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--dimension` | string + Enum | 是 | `row` / `column` | -| `--start` | int | 是 | 结束位置(0-based, inclusive) | -| `--end` | int | 是 | 结束位置(0-based, inclusive) | +| `--dimension` | string | required | 维度方向(行或列)(可选值:`row` / `column`) | +| `--start` | int | required | 起始位置(0-based, inclusive) | +| `--end` | int | required | 结束位置(0-based, inclusive) | ### `+dim-unhide` @@ -96,9 +97,9 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--dimension` | string + Enum | 是 | `row` / `column` | -| `--start` | int | 是 | 结束位置(0-based, inclusive) | -| `--end` | int | 是 | 结束位置(0-based, inclusive) | +| `--dimension` | string | required | 维度方向(行或列)(可选值:`row` / `column`) | +| `--start` | int | required | 起始位置(0-based, inclusive) | +| `--end` | int | required | 结束位置(0-based, inclusive) | ### `+dim-freeze` @@ -106,8 +107,8 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--dimension` | string + Enum | 是 | `row` / `column` | -| `--count` | int | 是 | 冻结前 N 行/列;传 0 解除冻结 | +| `--dimension` | string | required | 维度方向(行或列)(可选值:`row` / `column`) | +| `--count` | int | required | 冻结前 N 行/列;传 0 解除冻结 | ### `+dim-group` @@ -115,10 +116,11 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--dimension` | string + Enum | 是 | `row` / `column` | -| `--start` | int | 是 | 结束位置(0-based, inclusive) | -| `--end` | int | 是 | 结束位置(0-based, inclusive) | -| `--depth` | int | 否 | 嵌套层级(`+dim-group` 用),默认 1 | +| `--dimension` | string | required | 维度方向(行或列)(可选值:`row` / `column`) | +| `--start` | int | required | 起始位置(0-based, inclusive) | +| `--end` | int | required | 结束位置(0-based, inclusive) | +| `--depth` | int | optional | 嵌套层级(`+dim-group` 用),默认 1 | +| `--group-state` | string | optional | 分组初始展开状态(可选值:`expand` / `fold`) | ### `+dim-ungroup` @@ -126,10 +128,10 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--dimension` | string + Enum | 是 | `row` / `column` | -| `--start` | int | 是 | 结束位置(0-based, inclusive) | -| `--end` | int | 是 | 结束位置(0-based, inclusive) | -| `--depth` | int | 否 | 嵌套层级(`+dim-group` 用),默认 1 | +| `--dimension` | string | required | 维度方向(行或列)(可选值:`row` / `column`) | +| `--start` | int | required | 起始位置(0-based, inclusive) | +| `--end` | int | required | 结束位置(0-based, inclusive) | +| `--depth` | int | optional | 嵌套层级(`+dim-group` 用),默认 1 | ### `+dim-move` @@ -137,10 +139,10 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--dimension` | string + Enum | 是 | `row` / `column` | -| `--start` | int | 是 | 源起止区间的起始位置(0-based, inclusive) | -| `--end` | int | 是 | 源起止区间的结束位置(0-based, inclusive) | -| `--target` | int | 是 | 目标位置(move 到该 index 之前;0-based) | +| `--dimension` | string | required | 维度方向(行或列)(可选值:`row` / `column`) | +| `--start` | int | required | 源起止区间的起始位置(0-based, inclusive) | +| `--end` | int | required | 源起止区间的结束位置(0-based, inclusive) | +| `--target` | int | required | 目标位置(move 到该 index 之前;0-based) | ## Examples diff --git a/skills/lark-sheets/references/lark-sheets-sparkline.md b/skills/lark-sheets/references/lark-sheets-sparkline.md index a416715c4..0d12b0ffe 100644 --- a/skills/lark-sheets/references/lark-sheets-sparkline.md +++ b/skills/lark-sheets/references/lark-sheets-sparkline.md @@ -37,7 +37,7 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--group-id` | string | 否 | 按 group_id 过滤 | +| `--group-id` | string | optional | 按 group_id 过滤 | ### `+sparkline-create` @@ -45,7 +45,7 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--properties` | string + File + Stdin(复合 JSON) | 是 | JSON:`{"type":"line\|column\|winLoss","data_range":"A2:F10","target_range":"G2:G10","style":{...},"special_points":{...}}`;type 三种 enum;data_range 与 target_range 行/列数需对齐 | +| `--properties` | string + File + Stdin(复合 JSON) | required | JSON:`{config(共享样式配置), sparklines(迷你图数组)}`;完整字段结构跑 `--print-schema` | ### `+sparkline-update` @@ -53,8 +53,8 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--group-id` | string | 是 | 目标组 id | -| `--properties` | string + File + Stdin(复合 JSON) | 是 | 完整或足够完整的配置(先 `+sparkline-list --group-id ` 回读再 patch);可改 `type` / `data_range` / `target_range` / `style` / `special_points` 等字段 | +| `--group-id` | string | required | 目标组 id | +| `--properties` | string + File + Stdin(复合 JSON) | required | JSON:`{config, sparklines}`;先 `+sparkline-list --group-id ` 回读再 patch;完整字段结构跑 `--print-schema` | ### `+sparkline-delete` @@ -62,7 +62,7 @@ _公共四件套 · 系统:`--yes`、`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--group-id` | string | 是 | 目标组 id | +| `--group-id` | string | required | 目标组 id | ## Schemas diff --git a/skills/lark-sheets/references/lark-sheets-workbook.md b/skills/lark-sheets/references/lark-sheets-workbook.md index 4f9f8928d..eda7e525e 100644 --- a/skills/lark-sheets/references/lark-sheets-workbook.md +++ b/skills/lark-sheets/references/lark-sheets-workbook.md @@ -50,9 +50,7 @@ _公共:URL/token(无 sheet 定位) · 系统:`--dry-run`_ -| Flag | Type | 必填 | 说明 | -| --- | --- | --- | --- | -| `--include-properties` | bool | 否 | 是否返回每个 sheet 的扩展属性(默认 true) | +_仅含公共 / 系统 flag。_ ### `+sheet-create` @@ -60,10 +58,10 @@ _公共:URL/token(无 sheet 定位) · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--title` | string | 是 | 新工作表名称 | -| `--index` | int | 否 | 插入位置;省略时附加到末尾 | -| `--row-count` | int | 否 | 初始行数,默认 100 | -| `--col-count` | int | 否 | 初始列数,默认 26 | +| `--title` | string | required | 新工作表名称 | +| `--index` | int | optional | 插入位置;省略时附加到末尾 | +| `--row-count` | int | optional | 初始行数(默认 200,上限 50000) | +| `--col-count` | int | optional | 初始列数(默认 20,上限 200) | ### `+sheet-delete` @@ -77,7 +75,7 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--title` | string | 是 | 新名称 | +| `--title` | string | required | 新名称 | ### `+sheet-move` @@ -85,8 +83,8 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--index` | int | 是 | 目标位置(0-based) | -| `--source-index` | int | 否 | 源位置(0-based);可选,未传时由 CLI runtime 根据 `--sheet-id` / `--sheet-name` 当前在工作簿中的 index 自动派生 | +| `--index` | int | required | 目标位置(0-based) | +| `--source-index` | int | optional | 源位置(0-based);可选,未传时由 CLI runtime 根据 `--sheet-id` / `--sheet-name` 当前在工作簿中的 index 自动派生 | ### `+sheet-copy` @@ -94,8 +92,8 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--title` | string | 否 | 副本名称;省略时由服务端生成 | -| `--index` | int | 否 | 副本插入位置(0-based);省略时附加到末尾 | +| `--title` | string | optional | 副本名称;省略时由服务端生成 | +| `--index` | int | optional | 副本插入位置(0-based);省略时附加到末尾 | ### `+sheet-hide` @@ -115,7 +113,7 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--color` | string | 是 | Hex 色值如 `#FF0000`,传空 `""` 清除 | +| `--color` | string | required | Hex 色值如 `#FF0000`,传空 `""` 清除 | ### `+workbook-create` @@ -123,10 +121,10 @@ _系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--title` | string | 是 | 新 spreadsheet 标题 | -| `--folder-token` | string | 否 | 目标文件夹 token;省略时放在云空间根目录 | -| `--headers` | string + File + Stdin(简单 JSON) | 否 | 表头行 JSON 数组:`["列A","列B"]` | -| `--values` | string + File + Stdin(简单 JSON) | 否 | 初始数据 JSON 二维数组:`[["alice",95]]` | +| `--title` | string | required | 新 spreadsheet 标题 | +| `--folder-token` | string | optional | 目标文件夹 token;省略时放在云空间根目录 | +| `--headers` | string + File + Stdin(简单 JSON) | optional | 表头行 JSON 数组:`["列A","列B"]` | +| `--values` | string + File + Stdin(简单 JSON) | optional | 初始数据 JSON 二维数组:`[["alice",95]]` | ### `+workbook-export` @@ -134,9 +132,9 @@ _公共:URL/token(无 sheet 定位) · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--file-extension` | string + Enum | 否 | `xlsx` / `csv`,默认 `xlsx`;csv 模式必须配 `--sheet-id` | -| `--sheet-id` | string | 否 | 仅 csv 模式必填:指定要导出的 sheet reference_id | -| `--output-path` | string | 否 | 本地保存路径;省略时只触发导出不下载 | +| `--file-extension` | string | optional | 导出文件格式;`csv` 模式必须配 `--sheet-id`(可选值:`xlsx` / `csv`) | +| `--sheet-id` | string | optional | 仅 csv 模式必填:指定要导出的 sheet reference_id | +| `--output-path` | string | optional | 本地保存路径;省略时只触发导出不下载 | ## Examples diff --git a/skills/lark-sheets/references/lark-sheets-write-cells.md b/skills/lark-sheets/references/lark-sheets-write-cells.md index 331fc4526..7b40657b8 100644 --- a/skills/lark-sheets/references/lark-sheets-write-cells.md +++ b/skills/lark-sheets/references/lark-sheets-write-cells.md @@ -184,10 +184,10 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--range` | string | 是 | 写入区域(A1 格式) | -| `--cells` | string + File + Stdin(复合 JSON) | 是 | JSON:`{"values": [[...], ...]}`;可含 `formula` / `cell_styles` / `comments` / `embed_image` 富信息 | -| `--allow-overwrite` | bool | 否 | 允许覆盖非空 cell;默认 false 时遇非空 cell 报错 | -| `--max-cells` | int + Hidden | 否 | 防爆,默认 50000 | +| `--range` | string | required | 写入区域(A1 格式) | +| `--cells` | string + File + Stdin(复合 JSON) | required | JSON:2D 数组 `[[{cell},...],...]`,维度与 `--range` 完全一致;每个 cell 可含 `value` / `formula` / `cell_styles` / `note` / `rich_text`(含 `type="embed-image"` 单元格嵌图)等,完整字段跑 `--print-schema` | +| `--allow-overwrite` | bool | optional | 允许覆盖非空 cell(默认 true);设为 false 时遇非空 cell 报错 | +| `--max-cells` | int | optional | 防爆,默认 50000 | ### `+cells-set-style` @@ -195,18 +195,18 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--range` | string | 是 | 目标范围(A1 格式,如 `A1:B2`) | -| `--background-color` | string | 否 | 背景颜色(十六进制,如 `#ffffff`) | -| `--font-color` | string | 否 | 字体颜色(十六进制,如 `#000000`) | -| `--font-size` | number | 否 | 字体大小(px,例:10、12、14) | -| `--font-style` | string + Enum | 否 | 字体样式 enum:`normal` / `italic` | -| `--font-weight` | string + Enum | 否 | 字重 enum:`normal` / `bold` | -| `--font-line` | string + Enum | 否 | 字体线条样式 enum:`none` / `underline` / `line-through` | -| `--horizontal-alignment` | string + Enum | 否 | 水平对齐 enum:`left` / `center` / `right` | -| `--vertical-alignment` | string + Enum | 否 | 垂直对齐 enum:`top` / `middle` / `bottom` | -| `--word-wrap` | string + Enum | 否 | 换行策略 enum:`overflow` / `auto-wrap` / `word-clip`,默认 `overflow` | -| `--number-format` | string | 否 | 数字格式(例:文本 `@`、数字 `0.00`、货币 `$#,##0.00`、日期 `mm/dd/yyyy`) | -| `--border-styles` | string + File + Stdin(复合 JSON) | 否 | 边框配置 JSON:`{ top: {style,color,weight}, bottom: ..., left: ..., right: ... }`;4 方向结构相同 | +| `--range` | string | required | 目标范围(A1 格式,如 `A1:B2`) | +| `--background-color` | string | optional | 背景颜色(十六进制,如 `#ffffff`) | +| `--font-color` | string | optional | 字体颜色(十六进制,如 `#000000`) | +| `--font-size` | float64 | optional | 字体大小(px,例:10、12、14) | +| `--font-style` | string | optional | 字体样式(可选值:`normal` / `italic`) | +| `--font-weight` | string | optional | 字重(可选值:`normal` / `bold`) | +| `--font-line` | string | optional | 字体线条样式(可选值:`none` / `underline` / `line-through`) | +| `--horizontal-alignment` | string | optional | 水平对齐(可选值:`left` / `center` / `right`) | +| `--vertical-alignment` | string | optional | 垂直对齐(可选值:`top` / `middle` / `bottom`) | +| `--word-wrap` | string | optional | 换行策略(可选值:`overflow` / `auto-wrap` / `word-clip`) | +| `--number-format` | string | optional | 数字格式(例:文本 `@`、数字 `0.00`、货币 `$#,##0.00`、日期 `mm/dd/yyyy`) | +| `--border-styles` | string + File + Stdin(复合 JSON) | optional | 边框配置 JSON:`{ top: {style,color,weight}, bottom: ..., left: ..., right: ... }`;4 方向结构相同 | ### `+cells-set-image` @@ -214,9 +214,9 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--range` | string | 是 | 目标单元格(A1 格式,必须单 cell,如 `A1`;起止 cell 须相同) | -| `--image` | string | 是 | 本地图片路径(支持 PNG / JPEG / JPG / GIF / BMP / JFIF / EXIF / TIFF / BPG / HEIC) | -| `--name` | string | 否 | 图片文件名(含扩展名);省略时取 `--image` 的 basename | +| `--range` | string | required | 目标单元格(A1 格式,必须单 cell,如 `A1`;起止 cell 须相同) | +| `--image` | string | required | 本地图片路径(支持 PNG / JPEG / JPG / GIF / BMP / JFIF / EXIF / TIFF / BPG / HEIC) | +| `--name` | string | optional | 图片文件名(含扩展名);省略时取 `--image` 的 basename | ### `+dropdown-set` @@ -224,11 +224,11 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--range` | string | 是 | 目标范围(A1 格式,如 `A2:A100`) | -| `--options` | string + File + Stdin(复合 JSON) | 是 | 选项 JSON 数组 `["opt1","opt2"]`;最多 500 项,每项 ≤100 字符,不含逗号 | -| `--colors` | string + File + Stdin(简单 JSON) | 否 | RGB hex 颜色数组(如 `["#1FB6C1","#F006C2"]`),长度必须与 `--options` 一致 | -| `--multiple` | bool | 否 | 启用多选;默认 `false` | -| `--highlight` | bool | 否 | 选项配色显示;默认 `false` | +| `--range` | string | required | 目标范围(A1 格式,如 `A2:A100`) | +| `--options` | string + File + Stdin(复合 JSON) | required | 选项 JSON 数组 `["opt1","opt2"]`;最多 500 项,每项 ≤100 字符,不含逗号 | +| `--colors` | string + File + Stdin(简单 JSON) | optional | RGB hex 颜色数组(如 `["#1FB6C1","#F006C2"]`),长度必须与 `--options` 一致 | +| `--multiple` | bool | optional | 启用多选;默认 `false` | +| `--highlight` | bool | optional | 选项配色显示;默认 `false` | ### `+csv-put` @@ -236,9 +236,9 @@ _公共四件套 · 系统:`--dry-run`_ | Flag | Type | 必填 | 说明 | | --- | --- | --- | --- | -| `--range` | string | 是 | 目标区域起点 A1(如 `Sheet1!A1`);终点按 CSV 实际行列数自动推断 | -| `--csv` | string + File + Stdin(非 JSON 文本) | 是 | RFC 4180 CSV 文本;只写纯值,不带公式/样式/批注 | -| `--allow-overwrite` | bool | 否 | 允许覆盖;默认 false 时若目标非空报错 | +| `--start-cell` | string | required | 目标区域起点 A1(如 `Sheet1!A1`);终点按 CSV 实际行列数自动推断 | +| `--csv` | string + File + Stdin(非 JSON 文本) | required | RFC 4180 CSV 文本;只写纯值,不带公式/样式/批注 | +| `--allow-overwrite` | bool | optional | 允许覆盖(默认 true);设为 false 时若目标非空报错 | ## Schemas @@ -269,16 +269,10 @@ _单元格边框配置,含 top/bottom/left/right 四个方向,每个方向 ### `+dropdown-set` `--options` -_数据验证配置_ +_列表选项(type='list' 时必填)_ -**顶层字段**: -- `help_text` (string?) — 验证失败时显示的提示文本 -- `items` (array?) — 列表选项(type='list' 时必填) -- `operator` (enum?) — 比较运算符(type='number'/'date'/'textLength' 时必填) [equal / notEqual / greaterThan / greaterThanOrEqual / lessThan / lessThanOrEqual / between / notBetween] -- `range` (string?) — 源数据区域(type='listFromRange' 时必填,格式:'SheetName!A1:A10') -- `support_multiple_values` (boolean?) — 列表验证是否支持多选(type='list'/'listFromRange' 时可选,默认 false) -- `type` (enum) — 数据验证类型:list(下拉列表)、listFromRange(引用范围下拉列表)、number(数字)、date(日期)、textLength(文本长度)、… [list / listFromRange / number / date / textLength / checkbox] -- `values` (array?) — 比较值(operator 为 'between'/'notBetween' 时需要两个值,其它运算符需要一个值) +**数组项**(类型 string): +- 标量:string ## Examples