gdoc-vim
Edit Google Docs as Markdown in your terminal editor.
Google Docs speaks Markdown natively (both export and import), so a document can
be round-tripped through a local .md file. gdoc-vim makes that one command:
gdoc-vim https://docs.google.com/document/d/FILE_ID/edit
It pulls the doc as Markdown, opens it in vim (or your $EDITOR), and on save
converts it back and pushes it to the same document — preserving its link,
sharing settings, and revision history.
Background and a short walkthrough: Editing Google Docs Directly in vim (中文)
Install
pipx install gdoc-vim
Or straight from source:
pipx install git+https://github.com/gmajian/gdoc-vim
Either way you get a gdoc-vim command on your PATH. pipx keeps the tool in
its own virtualenv and links the executable into ~/.local/bin; if that
directory isn't on your PATH yet, run pipx ensurepath once and restart your
shell.
pip install works as well, but pipx is preferred for command-line tools since
it avoids polluting your Python environment.
The first time you run a command, gdoc-vim checks whether it can reach your Google account and walks you through anything that's missing:
- No OAuth client configured? It prints step-by-step setup instructions, naming the exact path to save the file to.
- Not signed in yet? A browser opens once to authorize, and the token is
cached at
~/.config/gdoc-vim/token.json.
There is no separate login step — just run the tool and follow the prompts.
While setting up your OAuth client, also set its publishing status to In production. Clients left in Testing get refresh tokens that expire after 7 days, which means signing in again every week. See Avoid the 7-day re-authorization trap.
Usage
# Edit an existing doc (URL or bare id; extra URL params like ?tab=t.0 are fine)
gdoc-vim https://docs.google.com/document/d/FILE_ID/edit?tab=t.0
# Create a new doc and start editing it immediately
gdoc-vim -n "Meeting notes"
# Rename a doc (no editor)
gdoc-vim <url> -t "Better title"
# Rename and edit in one go
gdoc-vim <url> -t "Better title" -e
# Review a diff and confirm before uploading
gdoc-vim <url> -c
# Non-interactive: export to / import from a local file
gdoc-vim <url> -o notes.md # export only
gdoc-vim <url> -p notes.md # overwrite the doc from notes.md
# Sign in as a different account
gdoc-vim <url> --reauth
Saving in the editor uploads immediately. Pass -c/--confirm if you'd rather
see a diff and approve it first.
Signing in over ssh
On a remote machine there is no browser to open. gdoc-vim notices a remote
session ($SSH_CONNECTION, $SSH_TTY, or Linux with no $DISPLAY) and
switches to a copy-and-paste flow instead — no port forwarding, no tunnel.
It prints a sign-in URL. Open that in a browser anywhere and approve access.
Google then sends the browser to http://localhost:8080/?code=..., which shows
a "site can't be reached" page — that is expected, nothing is listening
there. The code you need is sitting in the address bar. Copy the whole address,
paste it back into the terminal, and sign-in completes.
Pass --no-browser to force this mode if the detection guesses wrong, or
--port N if something on your machine already answers on 8080.
If you use many machines, it can be easier to authorize once somewhere with a browser and copy the cached token across:
scp ~/.config/gdoc-vim/token.json you@remote-host:~/.config/gdoc-vim/
Choosing the editor
gdoc-vim uses, in order: $GDOC_VIM_EDITOR, $VISUAL, $EDITOR, then vim.
The value may include arguments, e.g. export GDOC_VIM_EDITOR="code --wait".
Why you create your own OAuth client
Talking to the Drive API requires an OAuth client — an app identity issued by Google. gdoc-vim asks you to create one rather than shipping a shared one, and that is a deliberate trade-off worth explaining.
gdoc-vim needs the full drive scope, because it opens and overwrites documents
the app did not create (any doc you paste a URL for). Google classifies drive
as a restricted scope, the most tightly controlled tier. Shipping a shared
client that anyone could use would require the app to pass Google's
restricted scope verification,
which mandates a third-party CASA security assessment, repeated at least
every 12 months. That is aimed at commercial services handling user data at
scale, and is not a reasonable burden for a free command-line tool.
Creating your own client takes about three minutes, and gdoc-vim walks you through it the first time you run it. Your credentials stay yours: your data is never routed through anyone else's Google project.
Avoid the 7-day re-authorization trap
By default a new OAuth client has publishing status Testing, and Google issues refresh tokens that expire after 7 days for clients in that state. You would have to sign in again every week.
To fix it, open the Google Cloud Console, go to the OAuth consent screen (newer console: Google Auth Platform → Audience) and set the publishing status to In production.
This does not require verification. Because the app is unverified, you will see a warning screen at sign-in — click Advanced → Go to gdoc-vim (unsafe) once. In exchange, your login stops expiring. Unverified apps are subject to a user cap (around 100), which is ample for personal use.
Optional: bundling a client for a small group
If you want a handful of people — a team, a few friends — to install and run gdoc-vim with no setup at all, you can ship a client with the package.
gdoc-vim resolves client credentials in this order:
$GDOC_VIM_CLIENT_SECRETS— path to a client secrets JSON~/.config/gdoc-vim/credentials.json— per-user overridesrc/gdoc_vim/client_secret.json— bundled with the package
Place the downloaded JSON at src/gdoc_vim/client_secret.json before building.
It is .gitignored, so inject it at release time (e.g. from a CI secret) rather
than committing it:
cp /path/to/downloaded.json src/gdoc_vim/client_secret.json
python -m build
twine upload dist/*
A Desktop-app client secret is not a confidential secret — Google's own docs note that installed apps cannot keep one, which is why the flow does not depend on it staying private. Keeping it out of git just makes it easy to rotate.
Every person who signs in must be added to your client's user list, and the cap still applies. This works well for a known group; it does not scale to strangers installing from PyPI, which is why the default path is for each user to create their own client.
Limitations
Markdown is a lossy representation of a Google Doc. Plain prose round-trips cleanly — headings, lists, bold/italic, links, code blocks, blockquotes, and simple tables all survive — and repeated syncing is stable: export, import, and export again gives you a byte-identical file.
What does not survive is anything Markdown has no way to express. Two cases are worth knowing before you point this at a document written in the web editor:
- Multiple tabs are flattened into one. A document with several tabs comes
back as a single tab holding all the content. Nothing is deleted, but the
structure is gone, so gdoc-vim refuses to upload to a multi-tab document.
(
-ostill exports one, and--forceoverrides the refusal.) The check needs the Google Docs API enabled in your Cloud project; without it the tool says so once and carries on unprotected. - Smart chips become plain links. Date chips, people chips, and file chips all degrade to ordinary text or links on the way back.
Also lost or simplified: comments and suggested edits, embedded drawings, charts, equations, and fine-grained styling (fonts, colors, spacing). Image handling depends on Google's converter.
A push replaces the document's entire body, so these losses apply to the whole document, not only the part you edited. Google keeps full revision history, so File → Version history in the Docs UI will get you back if a conversion surprises you — but try the tool on a copy of anything important first.
In short: this works best on text-first documents you mostly write in Markdown anyway. The richer a document is, the less it suits this workflow.
Development
The package lives under src/, so an editable install is the easiest way to
work on it:
python3 -m venv .venv
./.venv/bin/pip install -e ".[dev]"
./.venv/bin/gdoc-vim --help
Tests
./.venv/bin/python -m pytest
The suite runs offline against an in-memory stand-in for the Drive API, so it
needs no credentials and makes no network calls. tests/conftest.py provides
that fake service plus a scriptable fake editor, which together cover the
export → edit → upload round trip end to end.
License
GNU General Public License v3.0 or later — see LICENSE.
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. It is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Release files for gdoc-vim 0.1.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| gdoc_vim-0.1.3.tar.gz | 32.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| gdoc_vim-0.1.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 60.7 kB
Release files / gdoc_vim-0.1.3.tar.gz
| Download URL | gdoc_vim-0.1.3.tar.gz |
|---|---|
| Size | 32.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3745d710406016b1110229c64b638ca10af9f18f42bc63f4eabf40ade6602c1c
|
|
BLAKE2b-256 checksum How to use checksums |
d7de967aa2e0cf944313526aef160f8e22c3b621672e95aef4261ef47a5c0a50
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 11, 2026.
Transparency logRelease files / gdoc_vim-0.1.3-py3-none-any.whl
| Download URL | gdoc_vim-0.1.3-py3-none-any.whl |
|---|---|
| Size | 28.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
955616427c09c81d4b7a0110b0effadf49d36302eb126e3dca07e437f48ec804
|
|
BLAKE2b-256 checksum How to use checksums |
bf0d5aeabbeb5f7ad990200ab0c3ff622cae692046334ba7da0df30bb9161fc4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 11, 2026.
Transparency log