gcal-oauth-bridge
by @danielkillenberger
Interact with the Calendar Bridge — a self-hosted Node.js service that provides a persistent REST API for Google Calendar events. Handles OAuth token auto-re...
clawhub install gcal-oauth-bridge📖 About This Skill
name: calendar-bridge description: Interact with the Calendar Bridge — a self-hosted Node.js service that provides a persistent REST API for Google Calendar events. Handles OAuth token auto-refresh so you never have to re-authenticate. Use when checking upcoming events, listing calendars, setting up Google Calendar access, or troubleshooting calendar auth. homepage: https://github.com/DanielKillenberger/gcal-oauth-bridge version: 1.0.2 read_when: - User asks about upcoming events or calendar - User asks what's scheduled or what meetings they have - Calendar Bridge setup or troubleshooting needed metadata: { "openclaw": { "emoji": "📅", "requires": { "env": ["GOOGLE_CLIENT_ID", "GOOGLE_CLIENT_SECRET"] }, "optional": { "env": ["CALENDAR_BRIDGE_API_KEY"] }, "notes": "GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET are required for initial OAuth setup only — once authenticated, the agent only needs network access to localhost:3000. CALENDAR_BRIDGE_API_KEY is optional; if set, the agent must send it as Authorization: Bearer
Calendar Bridge Skill
Use this skill to interact with the Calendar Bridge service — a local REST API that wraps Google Calendar OAuth with persistent token storage and auto-refresh.
GitHub: https://github.com/DanielKillenberger/gcal-oauth-bridge
What is Calendar Bridge?
A tiny Node.js/Express service running at http://localhost:3000 that:
API Endpoints
| Endpoint | Description |
|----------|-------------|
| GET /health | Service status + auth state |
| GET /auth/url | Get OAuth consent URL |
| GET /events?days=7 | Upcoming events from primary calendar |
| GET /events?days=7&calendar=all | Events from ALL calendars |
| GET /events?days=7&calendar= | Events from a specific calendar |
| GET /calendars | List all available calendars |
| POST /auth/refresh | Force token refresh (normally automatic) |
Events response includes: id, summary, start, end, location, description, htmlLink, status, calendarId, calendarSummary
Checking Events
# Quick event check (7 days, primary calendar)
curl http://localhost:3000/eventsAll calendars, next 14 days
curl http://localhost:3000/events?days=14&calendar=allWith API key (if CALENDAR_BRIDGE_API_KEY is configured)
curl -H "Authorization: Bearer $API_KEY" http://localhost:3000/events?calendar=all
To call from OpenClaw/skill context (no API key needed when running on same host):
GET http://localhost:3000/events?calendar=all&days=7
First-Time Setup
1. Clone and install
git clone https://github.com/DanielKillenberger/gcal-oauth-bridge.git
cd gcal-oauth-bridge
npm install
cp .env.example .env
Edit .env with GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET
2. Get Google OAuth credentials
http://localhost:3000/auth/callback.env3. Start the service
node app.js
or: npm start
4. Authorize (one-time browser flow)
If on a remote VPS, first tunnel port 3000:# From your local machine:
ssh -L 3000:localhost:3000 your-server
Then:
curl http://localhost:3000/auth/url
Open the returned URL in your browser
Complete Google consent → tokens saved automatically
Verify:
curl http://localhost:3000/health
{"status":"ok","authenticated":true,"needsRefresh":false}
5. Keep it running (systemd)
systemctl --user enable calendar-bridge.service
systemctl --user start calendar-bridge.service
Re-authentication
If tokens are ever revoked (rare — auto-refresh prevents expiry):
1. ssh -L 3000:localhost:3000 your-server
2. curl http://localhost:3000/auth/url → open URL → complete consent
3. Done — new tokens overwrite old ones
Troubleshooting
{"error":"Not authenticated"} → Run the OAuth setup flow above401 Unauthorized → CALENDAR_BRIDGE_API_KEY is set; add Authorization: Bearer headersystemctl --user status calendar-bridgePersonal Gmail Users
Works with personal Gmail. Google shows an "unverified app" warning — click Advanced → Go to [app] to proceed. Tokens are stored locally on your server, not shared with anyone.
Files
app.js — main Express server.env (from .env.example)tokens.json (auto-generated, gitignored, never committed)📋 Tips & Best Practices
{"error":"Not authenticated"} → Run the OAuth setup flow above401 Unauthorized → CALENDAR_BRIDGE_API_KEY is set; add Authorization: Bearer headersystemctl --user status calendar-bridge