- New server/google_calendar.mjs wrapping googleapis v3 with auto token refresh - Four new actions: calendar-list-events (auto-accept), calendar-create/update/delete-event (queue) - bin/ccc-gcal-auth.mjs one-time OAuth2 consent flow helper - config.example.json updated with google_calendar block - server/config.mjs, index.mjs wired up following the same pattern as SMTP/mailer - Bump version to 1.2.0 - Add CLAUDE.md and claude-info/ with architecture reference, feature plans, and contributing checklist Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
3.6 KiB
Plan: Google Calendar integration
Status: implemented
Overview
Add Google Calendar read/write support as CCC actions. Follows the same pattern as the SMTP/mail integration: credentials in config, a wrapper module, new actions in actions.mjs.
Listing events is auto-accept (read-only). All mutations are queue — require human approval in the TUI before executing.
Step 1 — Google OAuth2 setup (one-time manual)
- Create a Google Cloud project, enable the Calendar API
- Create an OAuth2 credential (Desktop app type), download the JSON
- Run
ccc-gcal-auth(see Step 7) to do the consent flow and writegoogle-token.json - Point config at both files (see Step 2)
Step 2 — Config extension
Add to config.json (and config.example.json):
"google_calendar": {
"credentials": "../google-credentials.json",
"token": "../google-token.json"
}
Both paths resolved relative to the config file, same as secrets and mail_perms.
Step 3 — New module: server/google_calendar.mjs
Wraps the googleapis npm package. Exports:
export function create_calendar_client(cfg)
- Loads
cfg.credentials_pathandcfg.token_path - Creates an OAuth2 client
- Registers
tokensevent to persist refreshed tokens back to disk automatically - Returns a thin wrapper with methods:
list_events({ calendar_id, time_min, time_max, max_results })create_event({ calendar_id, summary, start, end, description })update_event({ calendar_id, event_id, summary, start, end, description })delete_event({ calendar_id, event_id })
start and end are ISO 8601 strings (e.g. "2026-05-21T14:00:00+02:00").
Step 4 — Config loader update (server/config.mjs)
Extend load_config to resolve google_calendar.credentials and google_calendar.token paths and return them (or null if the block is absent).
Step 5 — Server wiring (server/index.mjs)
import { create_calendar_client } from './google_calendar.mjs';
const calendar = cfg.google_calendar
? create_calendar_client(cfg.google_calendar)
: null;
// In make_ctx():
return { caller, users, mail_perm_store, exec, mailer_send, calendar };
Step 6 — New actions (server/actions.mjs)
| Action | Policy | Required params | Optional params |
|---|---|---|---|
calendar-list-events |
auto-accept |
— | calendar_id (default primary), time_min, time_max, max_results |
calendar-create-event |
queue |
summary, start, end |
calendar_id, description |
calendar-update-event |
queue |
event_id |
calendar_id, summary, start, end, description |
calendar-delete-event |
queue |
event_id |
calendar_id |
All handlers guard with:
if (!ctx.calendar) { throw new Error('Google Calendar not configured'); }
Step 7 — Auth helper: bin/ccc-gcal-auth.mjs
One-time setup script run on the host:
ccc-gcal-auth --credentials google-credentials.json --token google-token.json
- Reads the downloaded OAuth credentials JSON
- Generates an authorization URL, prints it for the user to open
- Starts a local HTTP server to receive the redirect with the auth code
- Exchanges the code for tokens and writes
google-token.json
Add to bin map in package.json.
Step 8 — Dependencies
npm install googleapis
Add to package.json dependencies.
Open questions
- Token storage: separate
google-token.json(current plan) vs folded intosecrets.json? - Should
calendar-create-eventbequeueorauto-accept? (Currentlyqueuefor safety) - Multi-calendar support needed beyond
primary?