Get a Google Doc with real headings and bold, not a wall of plain text
“Claude writes the document I asked for, and it comes out as one long block of plain text I then format by hand.”
A Google Doc with a title, real headings that build the outline, bold where it belongs, and bulleted lists, styled through the Docs API rather than by you afterwards.
Tools it uses
What it needs
- Google Workspace connected
- Works with one connected account
- The gateway URL in your Claude client
Turns the document you asked for into one a person would actually read: a title, headings that build the outline, bold where it belongs, real bulleted lists and links. It writes the text first and styles it in one pass, because that is the only order that puts the styles on the right words.
Use it on its own, or alongside any skill that writes a document.
---
name: google-doc-format
description: Write a Google Doc with real headings, bold, bullets and links, styled in one pass
---
# Google Doc formatting
## 1. Write all the text, once
`docs_create` with the title. Then ONE `docs_batch_update` with a single `insertText` at index 1
containing the whole document, headings and lists included as plain lines.
Do not write a section, style it, then write the next. Every insert shifts the position of
everything after it, so styles applied in between land on the wrong text, and the request
still succeeds.
## 2. Read where every line is
`docs_get` with `mode: "index"`. It returns each line with its exact `startIndex` and
`endIndex`. Styling does not move text, so these positions stay valid for the whole of step 3.
## 3. Style everything in ONE batch
One `docs_batch_update` holding every style request, computed from step 2. Every request needs
a `fields` value naming what it sets, or it is rejected.
- Title: `updateParagraphStyle` with `paragraphStyle.namedStyleType: "TITLE"`,
`fields: "namedStyleType"`.
- Section headings: `namedStyleType: "HEADING_1"` (or `HEADING_2` below it). Use real heading
styles, never bold text standing in for one: headings build the document outline, and the
outline is how someone skims it.
- Bold a phrase: `updateTextStyle` with `textStyle: {bold: true}`, `fields: "bold"`.
- Lists: `createParagraphBullets` over the whole paragraphs, newline included, with
`bulletPreset: "BULLET_DISC_CIRCLE_SQUARE"`, or `"NUMBERED_DECIMAL_ALPHA_ROMAN"` for numbers.
- Links: `updateTextStyle` with `textStyle: {link: {url: "..."}}`, `fields: "link"`.
**Never count characters by hand to find where a phrase ends.** Take the line's `startIndex`
from step 2 and add the phrase's length. A range picked by eye lands a few characters off,
the bold ends mid-word, and nothing reports it.
**If a range was wrong, clear it and reapply.** Setting only the correct range leaves any
overshoot still styled.
## 4. Fonts and colours, if you set them
Set the document-wide font FIRST, then re-apply every bold range AFTER it, setting both
properties together:
`textStyle: {bold: true, weightedFontFamily: {fontFamily: "Inter", weight: 700}}`,
`fields: "bold,weightedFontFamily"`.
`weightedFontFamily` carries a weight, so applying a body font at weight 400 across the whole
document removes every bold run already in it. Colours are `rgbColor` values from 0 to 1, not
hex: divide each channel by 255.
## 5. Check it
`docs_get` with `mode: "index"` again. A bold phrase that landed correctly splits its line into
three runs. An empty reply from the batch only means it was accepted, not that it styled what
you meant.
## Rails
Only writes the document you were asked to write. Never edits another document. No secrets,
tokens or other people's mail in the text.Paste this into your Claude client as a skill, then ask for it by name. It calls your connected accounts through the gateway, and every write asks you first.
Notes from running this
The simple write is plain text and nothing else. docs_write puts text at the start of a
document with no headings, no bold and no lists. The batch tool is a pass-through to Google's
full Docs API, which is where all the formatting lives, even though its description lists only
three text requests.
Write once, read once, style once. Inserting text moves everything after it; styling moves nothing. So the text goes in as one insert, the positions are read once, and every style goes in one batch against those positions. The obvious alternative, write a section and style it, puts headings and bold on the wrong lines and reports success while doing it.
We guessed five bold ranges by eye and got all five wrong. Four were off by one character, one by ten. The document rendered without complaint every time, with bold stopping mid-word. Ranges come from the index read plus the phrase's length, never from counting.
Setting the body font removed every bold run in the document. The batch came back as
eighteen empty replies, the document looked better at a glance, and every bold phrase was gone.
Only reading the result caught it. The general rule: a style request replaces everything inside
the property it sets, not just the part you had in mind, so keep fields as narrow as the
change and re-apply what a broad request could have overwritten.
Inserted text takes on the style of where it lands. Text inserted where a heading begins becomes part of that heading. A table inserted next to monospace text came out in a monospace font while an identical table elsewhere did not, so the document read as two documents. One document cost most of a day of rework before this was understood. Know which paragraph you are inserting into, and normalise the inserted range explicitly.
Pick the read mode on purpose. mode: "text" to read, mode: "index" to compute ranges,
and mode: "full" only to debug a style that did not apply: it returns the whole style table
and is enormous.
Look at the finished document. Every call here returns success whether or not it styled what you meant. Reading it back is the only check that can fail.
Change it
Change the heading levels and the list style to your house style, and set your own fonts and colours in step 4. Keep the order: all the text, one read, one styling batch.
Frequently asked questions
Why does the document come out as plain text? #
Why did my bold formatting disappear? #
Can it put an image into the document? #
Run it against your own data
The agent runs this skill for you, on the accounts you connect, and shows you what it did.
Run this skillSign in required. Connects Google Workspace.
By continuing you agree to our Terms of Service and Privacy Policy.
Other skills
Get a morning brief across your mail, calendar and tasks with Claude
One self-addressed brief: today's events across every calendar with the conflicts called out, the mail that needs a human grouped by account, and a task created for each thing you owe someone, with the noise labelled and marked read so it can be audited or undone.
Triage your Gmail inbox with Claude
A clean inbox and one self-addressed digest of what actually needs you, labelled so every action can be audited or undone.