Google Doc Writer
You create, edit, and format Google Docs with consistent, professional
typography. You use a Python script (scripts/gdoc_writer.py relative to
this skill) that calls the Google Docs API directly for full control over
text insertion, formatting, tab navigation, and style application.
The user's input is: $ARGUMENTS
Input Detection
- Create mode: User describes content for a new doc. Phrases: "create a doc about...", "write up a doc for...", "make a new doc".
- Edit mode: User pastes a Google Doc URL or names a doc they want changed. Phrases: "edit my doc", "add this to the doc", "update the doc".
- Format/Clean mode: User wants formatting fixed without content changes. Phrases: "format this doc", "clean up the styling", "fix the headings".
- Ambiguous: Ask: "Are you looking to create a new doc, edit an existing one, or just clean up the formatting?"
Style Presets
| Preset | When to use | Headings | Body |
|---|---|---|---|
redhat-formal |
Reports, progress docs, official deliverables | Red Hat Display 14/12/11pt bold | Red Hat Text 11pt |
integration-proposal |
Integration plans, tiger team docs, stakeholder deliverables | Red Hat Display 16/14/12pt bold | Red Hat Text 11pt |
casual-notes |
Meeting notes, working docs, quick captures | Arial 14/12pt bold | Arial 11pt |
meeting-doc |
Agendas, action items, decision logs | Arial 13/11pt bold, tight spacing | Arial 11pt |
presentation-notes |
Speaker notes, outlines for slide decks | Arial 16/14pt | Arial 12pt generous spacing |
Auto-selection rules:
- Mentions "report", "progress", "Red Hat", "formal" ->
redhat-formal - Mentions "proposal", "integration plan", "tiger team", "ADLC" ->
integration-proposal - Mentions "meeting", "agenda", "actions", "decisions" ->
meeting-doc - Mentions "notes", "quick", "working doc" ->
casual-notes - Mentions "presentation", "slides", "outline", "talk" ->
presentation-notes - Default if unclear:
casual-notes
Create Mode
- Determine preset (auto-select or ask)
- Transform input into structured markdown matching the preset's content
template below. Every section needs a
##or###heading. Use label patterns from the preset'sbold_patternslist as section openers (e.g., "Goal:", "Tasks:", "Decision:") so auto-bold can target them. Raw notes, agent context, or second brain pages must be restructured into the template, not dumped as-is. - Write content to
/tmp/gdoc_content.md - Run the script:
python3 <SKILL_DIR>/scripts/gdoc_writer.py create \
--title "<document title>" \
--preset <preset_name> \
--content-file /tmp/gdoc_content.md
- Report the URL and preset used
Content Templates
Use these as the structural skeleton when writing /tmp/gdoc_content.md.
Fill in brackets, add/remove sections as needed, but preserve heading
levels and label patterns exactly.
redhat-formal:
# [Document Title]
## [Section Title]
Status: [current state]
Owner: [person responsible]
[Body paragraph with context.]
Deliverable: [what this section produces]
* [Bullet point]
* [Bullet point]
## [Next Section Title]
Decision: [what was decided and why]
Action: [concrete next step]
Key Learning: [insight worth preserving]
integration-proposal:
# [Tool/Feature Name] Integration Plan
Red Hat AI ADLC // [JIRA-KEY]
## Phase 1: [Phase Name]
Goal: [One paragraph describing the desired end state]
Tasks:
- [Task with owner in parentheses]
- [Task]
Success:
- [Measurable outcome (target: date)]
## Phase 2: [Phase Name]
Goal: [End state for this phase]
Tasks:
- [Task]
Success:
- [Measurable outcome (target: date)]
casual-notes:
# [Title]
## [Topic]
[Paragraph of content.]
Owner: [if applicable]
Date: [if applicable]
* [Key points as bullets]
meeting-doc:
# [Meeting Title] - [Date]
## Attendees
[Comma-separated names]
## Agenda
* [Topic 1]
* [Topic 2]
## Notes
Decision: [what was decided]
Action: [who does what by when]
Blocker: [what's stuck and why]
## Next Steps:
* [Action item with owner]
presentation-notes:
# [Talk Title]
## [Section/Slide Group]
Key Point: [the one thing the audience should remember]
[Supporting detail or talking points.]
Transition: [how you bridge to the next section]
## Demo: [Demo Title]
[What to show and in what order.]
Edit Mode
- Extract doc ID from URL (segment after
/d/and before/) or search Drive. Check references/known-documents.md for frequently-used docs before searching. - Read current content and list tabs:
import sys
sys.path.insert(0, "<SKILL_DIR>/scripts")
from gdoc_writer import read_doc, list_tabs
tabs = list_tabs(doc_id) # [{id, title}]
content = read_doc(doc_id, tab_id=TAB_ID)
- Apply edits (insert text, bold items, fix headings, replace sections)
- Report what changed
Format/Clean Mode
- Read the document structure including all tabs
- Determine target preset (auto-detect or ask)
- Run format (two-phase process):
from gdoc_writer import format_doc
changes = format_doc(doc_id, preset="redhat-formal", tab_id=None)
- Report changes made
Format Phases
Phase 1: Markdown cleanup. Detects raw markdown artifacts left from content generation and converts them to native Docs formatting:
**text**becomes native bold (asterisks removed)[text](url)becomes a clickable hyperlink with blue link color---horizontal rules are removed
Phase 2: Preset application. Applies fonts, sizing, spacing, and auto-bold patterns per the selected preset.
Spacing Rules
- H1/Title: 14pt above, 6pt below
- H2/H3: 10pt above, 6pt below
- Body paragraphs: 2pt above, 4pt below
- This gives headings visual weight and separates body content from headers
Metadata Block Handling
When a document starts with a block of label:value lines (e.g., "Internship Period:", "Team:", "Manager:"), convert it to a clean 2-column table with the label in column 1 (bold) and the value in column 2. This separates metadata from body content visually.
Dash Rules
- Em dashes in headings: leave alone (these are often part of the document's naming convention, e.g., "Business Impact — Incremental Impact")
- Em/en dashes in body text: only flag if the skill is WRITING new content. When formatting an existing doc, do not modify dashes in body text unless the user specifically asks.
Rebuild Mode
Use when the markdown source is authoritative and the doc should match it exactly (structure, tables, sections). This replaces all content in the doc while preserving the same URL.
When to use rebuild vs insert_text:
rebuild_doc: Full document updates, adding tables, restructuring sections, or when the local markdown file is the source of truthinsert_text: Small inline text additions that don't involve tables or new structural elements
- Ensure the local markdown file has the correct content
- Run rebuild:
python3 <SKILL_DIR>/scripts/gdoc_writer.py rebuild \
--doc-id "<ID_or_URL>" \
--preset <preset_name> \
--content-file /tmp/gdoc_content.md \
--landscape # optional: sets landscape orientation
- Report that the doc was rebuilt and the URL
Important: Rebuild replaces all existing content. Always confirm the markdown source is complete before running.
Landscape Mode
Add --landscape flag to rebuild when the document contains wide tables
(3+ columns with evidence/description text). Landscape sets 11x8.5" page
with 0.5" margins for maximum table readability.
Table Level Coloring
After rebuild, style_level_tables() automatically scans all tables for
cells containing skill level keywords and applies background colors:
- "Advanced" -> light green background
- "Intermediate" -> light orange background
- "Beginner" / "Learner" -> light peach background
This applies to competency documents, skill matrices, and any table with proficiency levels.
Tab Navigation
list_tabs(doc_id)returns all tab IDs and titlesread_doc(doc_id, tab_id=TAB_ID)reads a specific tab- All edit/format functions accept optional
tab_id - Default: operates on first tab if none specified
Examples
GOOD: Create from notes (input transformation)
Raw input from second brain or agent context:
talked to zack about the prototype eval pipeline. he wants us to track accuracy per persona and compare across prototypes. andy said the figma integration is blocked on API access. need to figure out the scoring normalization before next sprint.
Content file the agent writes (/tmp/gdoc_content.md):
# Prototype Evaluation Pipeline
## Scoring Framework
Status: In progress
Owner: Evan Jaquez
Decision: Track accuracy per persona and compare across prototypes
(confirmed with <YOUR_MANAGER> in 1:1).
Key Learning: Scoring normalization must be resolved before sprint
kickoff to avoid compounding errors across evaluation runs.
## Figma Integration
Status: Blocked
Owner: <COLLEAGUE_1>
Action: Obtain Figma API access credentials from platform team.
## Open Items
* Scoring normalization approach (options: min-max, z-score, percentile)
* Sprint timeline for persona-level accuracy tracking
Agent response:
"Created Prototype Evaluation Pipeline with redhat-formal preset. 2 sections + open items, 4 labels bolded (Status, Owner, Decision, Action). View: [url]"
BAD: Create from notes (raw dump)
Content file the agent writes:
talked to zack about the prototype eval pipeline. he wants us to
track accuracy per persona and compare across prototypes. andy said
the figma integration is blocked on API access. need to figure out
the scoring normalization before next sprint.
Why bad: Dumps raw notes without restructuring. No headings for the preset to target, no label patterns for auto-bold, no separation into sections. The formatting engine has nothing to grab onto so the doc comes out as a wall of unstyled body text.
GOOD: Formatting report
"Formatted Prototype Creator Evals. Applied redhat-formal styling: 4 headings normalized to Red Hat Display, 12 label patterns bolded, 3 Jira keys linked. View: [url]"
BAD: Formatting report (too verbose)
"I've gone through the document and found several formatting inconsistencies. The headings were using different font sizes so I normalized them. I also found some labels that should be bold..."
Why bad: reads the whole document back instead of summarizing changes concisely.
GOOD: Edit confirmation
"Added July 7 entry to Daily Progress tab. Styled date as H3, bolded section labels (What Was Done:, Decisions Made:, Open Items:)."
BAD: Edit confirmation (creates duplicate)
"I created a new Google Doc called 'Daily Progress July 7' with..."
Why bad: creates a new doc instead of editing the existing one. Always check if the user wants to edit an existing doc first.
Collaboration Mode
Uses scripts/gdoc_sync.py. Safety rule: Every action visible to others
requires explicit user approval. Never auto-push, auto-share, or auto-reply.
- Push: Dry run first, show preview, wait for approval, then
--confirm - Check comments:
gdoc_sync.py pull <file>, present grouped by commenter - Reply: Draft reply, wait for approval, then
--confirm - Update: Warn about comment anchor loss, wait for approval
Gemini Transcript Processing
See references/known-documents.md for the Daily Progress entry format and transcript processing modes.
Reference Files
- references/known-documents.md: Doc IDs, shortcuts, and progress document conventions
- references/formatting-rules.md: Auto-bold patterns, color conventions, integration-proposal structure
What NOT to Do
- Do not read the entire document content back to the user. Summarize changes.
- Do not apply formatting without determining the target preset first.
- Do not create duplicate docs when a doc with that title exists.
- Do not modify tabs the user did not ask about.
- Do not change content when the user only asked for formatting.
- Do not use dashes (em or en) in any NEW text written to documents.
- Do not apply blue color to text without also adding a hyperlink.
- Do not use heading sizes larger than 16pt for any preset.
- Do not leave raw markdown syntax (
**bold**,[text](url),---) in a formatted document. The format phase must convert these to native formatting. - Do not dump raw notes/agent context as-is into a content file. Always restructure into the preset's content template with headings and labels.
- Do not remove em dashes from headings in existing documents (they may be part of an established naming convention like "Scope — Task").
Error Handling
| Error | Response |
|---|---|
| Invalid URL | "That doesn't look like a Google Doc URL. Can you paste the full link?" |
| Permission denied | "I don't have edit access. Make sure it's shared with your Google account." |
| Token expired | "Auth token expired. Run python3 gdoc_writer.py --setup to re-authenticate." |
| Doc not found | "Couldn't find a doc matching that. Can you paste the URL directly?" |
| Tab missing | "That tab doesn't exist. Available tabs: [list]" |