How I built a Python CLI tool that lets Claude Code read and write Google Docs directly — editing DOCX files programmatically, fixing typos, styling tables, and reading comments, all from the terminal.
Mariusz Smenzyk
AI Developer ✨ MusicTech ✨ SportTech
I had a problem: legal documents and IP valuations living in Google Docs, and Claude Code living in my terminal. Every time I wanted AI help editing a contract or fixing typos in a valuation document, I had to copy-paste between the browser and the CLI. It was slow, error-prone, and broke formatting.
So I built gdoc — a 200-line Python CLI that bridges Google Docs and Claude Code. Now my workflow looks like this:
# Pull a Google Doc as DOCX
gdoc pull "https://docs.google.com/document/d/1abc.../edit"
# Claude edits the DOCX directly (python-docx)
# Push it back
gdoc push "https://docs.google.com/document/d/1abc.../edit" ip/my-doc.docx
No formatting loss. No copy-paste. Full round-trip.
My first attempt used pandoc to convert Google Docs to Markdown, edit in Markdown, then convert back to DOCX. It sounded clean in theory:
Google Doc → DOCX → Markdown → (edit) → DOCX → Google Doc
The result? Tables got mangled. Images disappeared. Custom formatting was lost. The 1.6 MB document came back as a 22 KB skeleton.
Lesson learned: if you want lossless editing, skip the Markdown step entirely and work on the DOCX directly.
The tool has four modules:
gdoc/
├── auth.py # OAuth2 flow + token management
├── drive.py # Google Drive API: download/upload DOCX
├── convert.py # pandoc wrapper (optional, for initial reads)
└── cli.py # Click CLI: pull / push / auth commands
Google's OAuth2 for desktop apps uses InstalledAppFlow — it opens your browser, you authorize, and the token is saved locally:
from google_auth_oauthlib.flow import InstalledAppFlow
SCOPES = ["https://www.googleapis.com/auth/drive"]
flow = InstalledAppFlow.from_client_secrets_file(
"credentials.json", SCOPES
)
creds = flow.run_local_server(port=0)
# Save token for future use
One-time setup, then it auto-refreshes.
The Google Drive API exports Google Docs as DOCX natively:
from googleapiclient.http import MediaIoBaseDownload
request = service.files().export_media(
fileId=doc_id,
mimeType="application/vnd.openxmlformats-officedocument.wordprocessingml.document"
)
This gives you a real DOCX file — complete with tables, images, styles, and formatting.
This is where the magic happens. Instead of converting to Markdown, we manipulate the DOCX directly:
from docx import Document
doc = Document("my-document.docx")
# Fix a typo across the entire document
for p in doc.paragraphs:
for run in p.runs:
if "minumum" in run.text:
run.text = run.text.replace("minumum", "minimum")
doc.save("my-document.docx")
You can do much more — add table rows, style headers, insert hyperlinks, change fonts:
from docx.shared import RGBColor
from docx.oxml.ns import qn
from docx.oxml import OxmlElement
# Style a table header with dark background + white text
def set_cell_bg(cell, color_hex):
shd = OxmlElement("w:shd")
shd.set(qn("w:fill"), color_hex)
shd.set(qn("w:val"), "clear")
cell._tc.get_or_add_tcPr().append(shd)
for cell in table.rows[0].cells:
set_cell_bg(cell, "0F172B") # dark navy
for run in cell.paragraphs[0].runs:
run.font.color.rgb = RGBColor(255, 255, 255) # white text
Upload the modified DOCX, replacing the Google Doc content:
from googleapiclient.http import MediaFileUpload
media = MediaFileUpload(
"my-document.docx",
mimetype="application/vnd.openxmlformats-officedocument.wordprocessingml.document"
)
service.files().update(fileId=doc_id, media_body=media).execute()
The Google Doc is updated in place — revision history preserved.
Here's what I've actually used this for in a single session:
I pulled a framework agreement (Umowa Ramowa), asked Claude to scan for typos, and it found 11 issues — from simple misspellings (minumum → minimum) to a completely truncated legal clause. All fixed programmatically:
fixes = {
"alby": "aby",
"minumum": "minimum",
"mogłby": "mogły",
"tyś": "tys.",
"pcb": "PCB",
}
for p in doc.paragraphs:
for run in p.runs:
for old, new in fixes.items():
if old in run.text:
run.text = run.text.replace(old, new)
One command to style all table headers with the BeatBuddy brand color:
# oklch(20.8% .042 265.755) → #0F172B
Claude converted the oklch color to hex RGB, then applied dark background + white font to all 10 table header rows.
The IP valuation document lists 20 software components. Claude scanned the local beatbuddy-platform/ directory, extracted GitHub remote URLs from each repo, and added clickable hyperlinks directly into the DOCX table cells.
Google Docs comments aren't in the DOCX — they're only accessible via the Drive API:
comments = service.comments().list(
fileId=doc_id,
fields="comments(author/displayName,content,quotedFileContent/value,resolved)"
).execute()
This let Claude read reviewer comments, summarize them in a table, and suggest specific contract clause amendments — all without opening a browser.
Go to Google Cloud Console, create a project, and enable the Google Drive API.
Under APIs & Services → Credentials, create an OAuth 2.0 Client ID with type Desktop app. Download the JSON file as credentials.json.
Important: you need a Desktop app client, not a Web application. The CLI uses localhost redirect for the OAuth flow.
poetry init
poetry add google-api-python-client google-auth-oauthlib google-auth-httplib2 click python-docx
poetry run gdoc auth
# Opens browser → authorize → token saved
# Pull
poetry run gdoc pull "https://docs.google.com/document/d/1abc.../edit"
# Push
poetry run gdoc push "https://docs.google.com/document/d/1abc.../edit" path/to/file.docx
The combination of Claude Code + Google Docs API + python-docx creates a workflow where you can treat Google Docs as editable files in your terminal. No browser tab-switching, no copy-paste, no formatting loss.
The tool is intentionally minimal — ~200 lines across 4 files. It doesn't try to be a full Google Docs client. It just bridges the gap between "AI assistant in the terminal" and "documents my team collaborates on in Google Docs."
What surprised me most: once the pipeline existed, the use cases multiplied — typo checking, contract review, table styling, adding hyperlinks, reading comments, suggesting legal clauses. Each task that would have been 15 minutes of manual copy-paste became a 30-second command.
Built with Claude Code, Google Drive API v3, and python-docx.