Blog
Feb 18, 2026 - 8 MIN READ
Automating Google Docs with Claude Code: Build a CLI That Pulls, Edits, and Pushes

Automating Google Docs with Claude Code: Build a CLI That Pulls, Edits, and Pushes

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

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.


The Problem with Markdown Round-Trips

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.


Architecture

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

Authentication

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.

Pulling a Document

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.

Editing with python-docx

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

Pushing Back

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.


Real-World Examples

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 (minumumminimum) 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)

2. Styling Table Headers

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.

4. Reading Google Docs Comments

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.


Setup Guide

Prerequisites

  • Python 3.11+
  • Poetry
  • pandoc (optional, for initial MD conversion)

1. Create a Google Cloud Project

Go to Google Cloud Console, create a project, and enable the Google Drive API.

2. Create OAuth Credentials

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.

3. Install the Tool

poetry init
poetry add google-api-python-client google-auth-oauthlib google-auth-httplib2 click python-docx

4. Authenticate

poetry run gdoc auth
# Opens browser → authorize → token saved

5. Use It

# 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

Key Takeaway

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.