/gmail/.
For Google OAuth setup, see Google Workspace Setup.
Config
Fields marked secret are redacted in snapshots.
VFS.md
The VFS.md an agent reads with Gmail mounted at/<path>.
- Rendered
- Raw
INBOX, SENT, STARRED). User-created labels
use their label name as is.
Date Directories
Inside each label, messages are grouped into date subdirectories formatted asYYYY-MM-DD. The date is derived from the message’s
internalDate (epoch milliseconds) converted to a calendar date.
Message Files
Each message is stored as a.gmail.json file. The filename shape is:
__ and before
.gmail.json.
Attachments
Messages that have attachments get a companion subdirectory with the same base name (without.gmail.json). Decoded attachment
files are placed inside:
Cache
The Gmail VFS usesIndexCacheStore (same as Slack, Discord,
and other mounts). Index entries store label IDs, message IDs,
and message metadata. File bytes go through the workspace
file cache.
Example
examples/python/vfs/gmail/gmail.py for the full working example.
Finding IDs
VFS-specific commands require message IDs. These can be extracted from the filesystem:Working with Large Labels
Labels with many messages are split into date directories. A barels of a label lists the days of its 50 most recent messages; a glob
over the date names (ls /gmail/INBOX/2026-03-*) or a date directory
by name reaches older days. Tips for efficient access:
Shell Commands
Standard commands available on the mounted Gmail tree:
Acting on Gmail (send, reply, forward, triage, raw API calls) goes
through the gws CLI when installed.
Integration
What Gmail answers through its own API, so fewer files are read. Integration explains each command.
The listing keeps
each message’s text, and
grep -r and rg read only the messages whose text
holds the pattern’s text in any case, printing what reading every message
would. Listing a label already fetches its messages in full, so this asks Gmail
nothing more and saves the second fetch of each message it rules out. Gmail’s
own search is not used: it reads the HTML part of a message and can miss a word
of the plain-text body a .gmail.json holds, such as one inside a link.
Attachments are always read, and so is every message for a text that is not
ASCII, or that may be part of the labels field (inbox, STARRED, Label_1,
abel), since a message’s labels change after the listing kept its text. With
walk_limit: -1 in the mount’s "@all" command limit, the listing keeps no message text, and every message
is read.