| name | gdoc-control |
| description | Command Line Tool for retrieving, creating, and editing Google Docs. |
gdoc-control — Google Docs CLI Skill
A command-line tool for reading and writing Google Docs. All output is JSON on stdout. Errors are JSON on stderr with a non-zero exit code.
Invocation: gdoc-control <command> [args]
Commands
search — find documents
gdoc-control search <query> [--limit <n>]
query — full-text search string (searches document content and title)
--limit — max results, default 10
Output:
{
"files": [
{
"id": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms",
"name": "Q3 Status Report",
"modifiedTime": "2024-11-01T14:32:00.000Z",
"url": "https://docs.google.com/document/d/1BxiM.../edit"
}
]
}
get — read a document
gdoc-control get <document-id>
gdoc-control get <document-id> --structured
- Default output:
body is extracted plain text with headings prefixed #, ##, etc.
--structured: body is the raw Google Docs API body JSON (includes character indices — use this when you need precise locations for editing, not for normal reading).
Output (default):
{
"documentId": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms",
"title": "Q3 Status Report",
"revisionId": "AOV_f48abc123...",
"body": "# Q3 Status Report\nSome intro text.\n\n## Status\nAll good.\n\n## Next Steps\nDo things."
}
Important: The revisionId is used by the update commands for optimistic concurrency. You do not need to pass it manually — the update commands fetch it automatically. It is shown in get output for informational purposes.
create — create a document from markdown
gdoc-control create <title> --content <markdown>
gdoc-control create <title> --stdin # read markdown from stdin
Markdown is converted to HTML via Markdig (advanced extensions enabled), then uploaded to Google Drive as a Google Doc.
Output:
{
"documentId": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms",
"title": "My New Doc",
"url": "https://docs.google.com/document/d/1BxiM.../edit"
}
update append — add text at the end
gdoc-control update append <document-id> --text <text>
Appends a newline followed by text at the very end of the document body.
Output:
{
"documentId": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms",
"revisionId": "AOV_f48def456..."
}
update replace-text — find and replace all occurrences
gdoc-control update replace-text <document-id> --search <text> --replacement <text>
- Replaces all occurrences of
--search with --replacement across the entire document.
- Match is case-sensitive.
Output: same shape as append.
update replace-section — replace content under a heading
gdoc-control update replace-section <document-id> --heading <heading> --content <text>
gdoc-control update replace-section <document-id> --heading <heading> --stdin
- Finds the first heading paragraph whose text exactly matches
--heading (case-sensitive, trimmed).
- Deletes all content between that heading and the next heading at the same or higher level (or end of document).
- Inserts
--content in its place.
- The heading paragraph itself is preserved.
Output: same shape as append.
Error response
All errors are written to stderr with exit code 1:
{ "error": "Concurrent edit conflict — re-read the document and retry", "status": 412 }
{ "error": "Heading not found: \"Status\"" }
{ "error": "The caller does not have permission", "status": 403 }
Workflow guidance
Reading a document
Use get to read content. The plain-text body field uses markdown-style heading markers (#, ##, etc.) so you can identify sections by name for use with replace-section.
Editing safely
All update commands internally call get first to fetch the current revisionId, then submit the edit with WriteControl.RequiredRevisionId. If someone else edits the document between the read and write, the API returns 412 and the write is rejected — nothing is silently overwritten.
On a 412 error: retry the entire operation (re-read, then re-apply the edit).
Finding a document ID
- From
search output: use the id field.
- From a Google Docs URL:
https://docs.google.com/document/d/<ID>/edit — the <ID> segment.
Using replace-section correctly
Run get first. The heading text to pass to --heading is the heading line from body without the # prefix. For example, if body contains ## Next Steps, pass --heading "Next Steps".
Multi-line content in --text / --content
Use --stdin and pipe text in, or use shell $'...' syntax for embedded newlines. Example:
printf "Line one\nLine two\n" | gdoc-control update append <id> --stdin
(Note: append does not have --stdin; use replace-section --stdin or create --stdin for multi-line content. For append, embed \n directly in the --text value.)