Description
sheets-cli has no command to create a new sheet (tab) inside an existing spreadsheet. The destination tab must already exist before any write command will work, so any agent flow that wants to materialize a new tab from data has to fall back to the Sheets UI or a separate Google API call.
Use Case
Concrete flow that hit the gap:
I had three existing tabs in one spreadsheet (Prospect, Adversarial, Existing Customer) and wanted to combine the "problematic" rows from each into a new tab called Need Review in the same spreadsheet. OAuth was already configured, and I had prepared a batch of 47 append ops as the payload.
Workflow I wanted:
- Create the
Need Review tab (with sheetId).
batch append the 47 rows.
Step 1 isn't expressible in the CLI today, so I had to ask the human to add the tab manually in the Sheets UI before continuing. For an agent-oriented tool this is the one manual step that breaks an otherwise clean read -> decide -> dry-run -> apply loop.
Current Gap
Verified by running --help on each command group:
sheets-cli --help -> top-level: auth, sheets, sheet, header, read, append, update, set, batch, install-skill, help
sheets-cli sheets --help -> list, find
sheets-cli sheet --help -> info
sheets-cli batch --help -> ops: append, updateRow, updateKey, setRange
No addSheet / create / add anywhere. Reading the README confirms write commands all assume the destination sheet exists.
The README's For Agents section lists as best practice #9:
Empty sheets: append can bootstrap by writing a header row from JSON keys
That bootstrap promise is only half-fulfilled: append can populate an empty sheet, but the CLI provides no way to get to an empty sheet in the first place.
Proposed API
A new subcommand under sheets:
sheets-cli sheets add --spreadsheet <id> --name "Need Review" [--index <n>] [--dry-run]
Returns the new sheetId and title in the standard JSON envelope, e.g.:
{
"ok": true,
"cmd": "sheets add",
"spreadsheetId": "1abc...",
"result": { "sheetId": 1234567890, "title": "Need Review", "index": 3 }
}
And a matching addSheet op in batch so a new tab can be created and populated atomically in a single batch call:
[
{"op": "addSheet", "name": "Need Review"},
{"op": "append", "sheet": "Need Review", "values": {"Name": "Acme", "Reason": "..."}},
{"op": "append", "sheet": "Need Review", "values": {"Name": "Beta", "Reason": "..."}}
]
Useful flags worth considering:
--index <n> — position of the new tab
--if-not-exists — no-op (still ok=true) when a tab with that name already exists, returning the existing sheetId; makes the command safely retryable
--rows <n> / --cols <n> — initial grid size
Note
The Google Sheets API already supports this directly via spreadsheets.batchUpdate with an addSheet request (returns replies[0].addSheet.properties.sheetId), so this is purely a CLI surface gap, not an API limitation. Once it lands, the README's "empty sheets: append can bootstrap" guidance becomes fully usable end-to-end from the CLI.
Alternatives Considered
- Create the tab manually in the Sheets UI — current workaround; breaks agent autonomy and is the only manual step in an otherwise scriptable pipeline.
- Shell out to a separate Google Sheets API call (curl / gcloud / a one-off script) — works but duplicates the auth/token-store setup that
sheets-cli already owns, and defeats the point of a single composable CLI.
Environment
- sheets-cli v1.0.1
- Linux (x86_64)
Description
sheets-clihas no command to create a new sheet (tab) inside an existing spreadsheet. The destination tab must already exist before any write command will work, so any agent flow that wants to materialize a new tab from data has to fall back to the Sheets UI or a separate Google API call.Use Case
Concrete flow that hit the gap:
I had three existing tabs in one spreadsheet (
Prospect,Adversarial,Existing Customer) and wanted to combine the "problematic" rows from each into a new tab calledNeed Reviewin the same spreadsheet. OAuth was already configured, and I had prepared a batch of 47appendops as the payload.Workflow I wanted:
Need Reviewtab (with sheetId).batchappend the 47 rows.Step 1 isn't expressible in the CLI today, so I had to ask the human to add the tab manually in the Sheets UI before continuing. For an agent-oriented tool this is the one manual step that breaks an otherwise clean read -> decide -> dry-run -> apply loop.
Current Gap
Verified by running
--helpon each command group:sheets-cli --help-> top-level:auth,sheets,sheet,header,read,append,update,set,batch,install-skill,helpsheets-cli sheets --help->list,findsheets-cli sheet --help->infosheets-cli batch --help-> ops:append,updateRow,updateKey,setRangeNo
addSheet/create/addanywhere. Reading the README confirms write commands all assume the destination sheet exists.The README's For Agents section lists as best practice #9:
That bootstrap promise is only half-fulfilled:
appendcan populate an empty sheet, but the CLI provides no way to get to an empty sheet in the first place.Proposed API
A new subcommand under
sheets:Returns the new
sheetIdandtitlein the standard JSON envelope, e.g.:{ "ok": true, "cmd": "sheets add", "spreadsheetId": "1abc...", "result": { "sheetId": 1234567890, "title": "Need Review", "index": 3 } }And a matching
addSheetop inbatchso a new tab can be created and populated atomically in a single batch call:[ {"op": "addSheet", "name": "Need Review"}, {"op": "append", "sheet": "Need Review", "values": {"Name": "Acme", "Reason": "..."}}, {"op": "append", "sheet": "Need Review", "values": {"Name": "Beta", "Reason": "..."}} ]Useful flags worth considering:
--index <n>— position of the new tab--if-not-exists— no-op (still ok=true) when a tab with that name already exists, returning the existing sheetId; makes the command safely retryable--rows <n>/--cols <n>— initial grid sizeNote
The Google Sheets API already supports this directly via
spreadsheets.batchUpdatewith anaddSheetrequest (returnsreplies[0].addSheet.properties.sheetId), so this is purely a CLI surface gap, not an API limitation. Once it lands, the README's "empty sheets: append can bootstrap" guidance becomes fully usable end-to-end from the CLI.Alternatives Considered
sheets-clialready owns, and defeats the point of a single composable CLI.Environment