Skip to content

Google APIs made easy — Gmail, Drive, Calendar for AI agents and humans

License

Notifications You must be signed in to change notification settings

marcfargas/go-easy

Repository files navigation

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

  1. Create a project in Google Cloud Console
  2. Enable the Gmail, Drive, and Calendar APIs
  3. Create OAuth2 credentials (Desktop application type)
  4. 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

About

Google APIs made easy — Gmail, Drive, Calendar for AI agents and humans

Resources

License

Stars

Watchers

Forks

Sponsor this project

 

Packages

No packages published

Contributors 2

  •  
  •