@marcfargas/go-easy
Google APIs made easy โ Gmail, Drive, Calendar for AI agents and humans
Package details
Install @marcfargas/go-easy from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@marcfargas/go-easy- Package
@marcfargas/go-easy- Version
0.4.0- Published
- Feb 27, 2026
- Downloads
- 87/mo ยท 15/wk
- Author
- marcfargas
- License
- MIT
- Types
- skill
- Size
- 430.3 KB
- Dependencies
- 7 dependencies ยท 0 peers
Pi manifest JSON
{
"skills": [
"./skills"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
go-easy ๐ข
Google APIs made easy โ Gmail, Drive & Calendar. For AI agents and humans.
Thin TypeScript wrappers over Google's individual @googleapis/* packages with:
- Own auth โ unified OAuth2 with combined tokens, agent-compatible two-phase flow
- Agent-friendly types โ structured
GmailMessage,DriveFile,CalendarEvent - Safety guards โ destructive operations (send, share, delete) require explicit confirmation
- JSON gateways โ CLI tools that always output structured JSON
- File-based body โ email bodies read from files, not CLI args (no shell escaping issues)
Installation
# As a library
npm install @marcfargas/go-easy
# As CLI tools (no install needed)
npx go-gmail you@example.com search "is:unread"
npx go-drive you@example.com ls
npx go-calendar you@example.com events primary
Requires Node.js โฅ 20.
Auth Setup
go-easy manages its own OAuth2 tokens in ~/.go-easy/.
Prerequisites
- Create a project in Google Cloud Console
- Enable the Gmail, Drive, and Calendar APIs
- Create OAuth2 credentials (Desktop application type)
- Save credentials to
~/.go-easy/credentials.json:
{
"clientId": "YOUR_CLIENT_ID.apps.googleusercontent.com",
"clientSecret": "YOUR_CLIENT_SECRET"
}
Add an account
npx go-easy auth add you@example.com
# โ { "status": "started", "authUrl": "https://accounts.google.com/..." }
# Open the URL, authorize, then poll:
npx go-easy auth add you@example.com
# โ { "status": "complete", "email": "you@example.com", "scopes": ["gmail", "drive", "calendar"] }
One combined token covers Gmail + Drive + Calendar. The flow is agent-compatible โ two separate CLI calls (start + poll), no streaming stdout needed.
Manage accounts
npx go-easy auth list # List configured accounts
npx go-easy auth add you@example.com # Add or upgrade account
npx go-easy auth remove you@example.com --confirm # Remove account
Quick Start
import { getAuth } from '@marcfargas/go-easy/auth';
import { search, send } from '@marcfargas/go-easy/gmail';
import { setSafetyContext } from '@marcfargas/go-easy';
const auth = await getAuth('gmail', 'you@example.com');
// Search (READ โ no safety gate)
const results = await search(auth, { query: 'is:unread from:client' });
console.log(results.items);
// Send (DESTRUCTIVE โ requires safety context)
setSafetyContext({
confirm: async (op) => {
console.log(`โ ๏ธ ${op.description}`);
return true; // or prompt the user
},
});
await send(auth, {
to: 'client@example.com',
subject: 'Invoice attached',
markdown: '# Invoice\n\nPlease find attached.',
attachments: ['./invoice.pdf'],
});
Gateway CLIs
All gateway CLIs output JSON to stdout and work via npx:
# Gmail
npx go-gmail you@example.com search "is:unread" --max=10
npx go-gmail you@example.com get <messageId>
npx go-gmail you@example.com reply <messageId> --body-text-file=reply.txt --confirm
npx go-gmail you@example.com send --to=x@y.com --subject="Hi" --body-text-file=body.txt --confirm
# Drive
npx go-drive you@example.com ls
npx go-drive you@example.com search "quarterly report"
npx go-drive you@example.com upload ./file.pdf --folder=<folderId>
# Calendar
npx go-calendar you@example.com events primary --from=2026-02-01T00:00:00Z
npx go-calendar you@example.com create primary --summary="Meeting" --start=... --end=...
npx go-calendar you@example.com freebusy primary --from=... --to=...
Body content is always read from files (--body-text-file, --body-html-file, --body-md-file), never passed inline.
Destructive operations require --confirm. Without it, they show what would happen and exit with code 2.
Services
| Service | Module | Gateway | Status |
|---|---|---|---|
| Gmail | @marcfargas/go-easy/gmail |
npx go-gmail |
โ Ready |
| Drive | @marcfargas/go-easy/drive |
npx go-drive |
โ Ready |
| Calendar | @marcfargas/go-easy/calendar |
npx go-calendar |
โ Ready |
Gmail
| Function | Safety | Description |
|---|---|---|
search |
READ | Search messages by Gmail query |
getMessage |
READ | Get a single message with parsed fields |
getThread |
READ | Get a full conversation thread |
listLabels |
READ | List all labels |
getAttachmentContent |
READ | Download an attachment as Buffer |
getProfile |
READ | Get the authenticated email address |
createDraft |
WRITE | Create a draft (no send) |
listDrafts |
READ | List existing drafts |
batchModifyLabels |
WRITE | Add/remove labels on multiple messages |
markdownToHtml |
โ | Convert Markdown to email-safe HTML |
send |
โ ๏ธ DESTRUCTIVE | Send a new email (supports markdown option) |
reply |
โ ๏ธ DESTRUCTIVE | Reply / reply-all to a message |
forward |
WRITE / โ ๏ธ DESTRUCTIVE | Forward as draft (default) or send (sendNow). Attachment filtering. |
sendDraft |
โ ๏ธ DESTRUCTIVE | Send an existing draft |
Drive
| Function | Safety | Description |
|---|---|---|
listFiles |
READ | List folder contents or query by metadata |
searchFiles |
READ | Full-text search inside file contents |
getFile |
READ | Get file metadata by ID |
downloadFile |
READ | Download binary files as Buffer |
exportFile |
READ | Export Workspace files (Docs โ pdf/docx, Sheets โ xlsx/csv, etc.) |
listPermissions |
READ | List sharing permissions on a file |
uploadFile |
WRITE | Upload a local file |
createFolder |
WRITE | Create a folder |
moveFile |
WRITE | Move a file to a different folder |
renameFile |
WRITE | Rename a file |
copyFile |
WRITE | Copy a file |
trashFile |
โ ๏ธ DESTRUCTIVE | Trash a file |
shareFile |
โ ๏ธ DESTRUCTIVE* | Share a file (*public sharing only; user/group is WRITE) |
unshareFile |
โ ๏ธ DESTRUCTIVE | Remove a sharing permission |
Calendar
| Function | Safety | Description |
|---|---|---|
listCalendars |
READ | List all calendars for the account |
listEvents |
READ | List events with time range, search, pagination |
getEvent |
READ | Get a single event by ID |
queryFreeBusy |
READ | Check availability across calendars |
createEvent |
WRITE | Create an event (with attendees, all-day, location, OOO, focus time) |
updateEvent |
WRITE | Update an existing event (full replace) |
deleteEvent |
โ ๏ธ DESTRUCTIVE | Delete an event (warns about attendee cancellation) |
Safety Model
Operations are classified into three levels:
| Level | Gate | Examples |
|---|---|---|
| READ | None | search, getMessage, listLabels |
| WRITE | Logged | createDraft, batchModifyLabels, upload |
| DESTRUCTIVE | Blocked unless confirmed | send, reply, forward, share, delete |
Set up a SafetyContext at startup to handle confirmation prompts.
Without one, all destructive operations are blocked by default.
Module Structure
go-easy uses subpath exports โ import only what you need:
import { getAuth } from '@marcfargas/go-easy/auth';
import { search, send } from '@marcfargas/go-easy/gmail';
import { listFiles, uploadFile } from '@marcfargas/go-easy/drive';
import { listEvents, createEvent } from '@marcfargas/go-easy/calendar';
import { setSafetyContext } from '@marcfargas/go-easy';
| Import path | What's in it |
|---|---|
@marcfargas/go-easy |
Safety context, errors, plus gmail/drive/calendar as namespaces |
@marcfargas/go-easy/auth |
getAuth, listAccounts, listAllAccounts, clearAuthCache |
@marcfargas/go-easy/auth-store |
readAccountStore, writeAccountStore, findAccount, etc. |
@marcfargas/go-easy/scopes |
SCOPES, ALL_SCOPES, scopeToService |
@marcfargas/go-easy/gmail |
All Gmail operations |
@marcfargas/go-easy/drive |
All Drive operations |
@marcfargas/go-easy/calendar |
All Calendar operations |
Development
npm install # install deps
npm run build # compile TypeScript
npm test # run tests (vitest)
npm run lint # type-check without emitting
npm run dev # watch mode
License
MIT