Files
gbrain/recipes/calendar-to-brain.md
Garry Tan ce15062694 feat: GBrain v0.7.0 — Integration Recipes + SKILLPACK Breakout (#39)
* docs: break SKILLPACK into 17 individual guides

The 1,281-line SKILLPACK monolith is now 17 individually linkable guides
in docs/guides/, organized by category: core patterns, data pipelines,
operations, search, and administration.

GBRAIN_SKILLPACK.md becomes a structured index with categorized tables
linking to each guide. The URL stays stable for backward compatibility.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: add integration guides, architecture docs, and ethos

New documentation directories:
- docs/integrations/ — "Getting Data In" landing page, credential gateway,
  meeting webhooks. Includes recipe format documentation.
- docs/architecture/ — Infrastructure layer doc (import, chunk, embed, search)
- docs/ethos/ — "Thin Harness, Fat Skills" essay with agent decision guide
- docs/designs/ — "Homebrew for Personal AI" 10-star vision document

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add gbrain integrations command + voice-to-brain recipe

New CLI command: gbrain integrations (list/show/status/doctor/stats/test)
- Standalone command, no database connection needed
- Uses gray-matter directly for recipe parsing (not parseMarkdown)
- --json flag on every subcommand for agent-parseable output
- Bare command shows senses/reflexes dashboard
- Health heartbeat via ~/.gbrain/integrations/<id>/heartbeat.jsonl

First recipe: recipes/twilio-voice-brain.md
- Phone calls create brain pages via Twilio + OpenAI Realtime
- Opinionated defaults: caller screening, brain-first lookup, quiet hours
- Outbound call smoke test (GBrain calls the user to prove it works)
- Validate-as-you-go credential testing
- Twilio signature validation for webhook security

Migration file for v0.7.0 with agent-readable changelog.
13 unit tests covering parseRecipe, CLI routing, and recipe validation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: add Getting Data In to README, update CLAUDE.md and manifest

README: voice calls in intro bullet list, new "Getting Data In" section
with integration table (voice, email, X, calendar) and recipe philosophy.

CLAUDE.md: reference new files (integrations.ts, recipes/, docs/guides/,
docs/integrations/, docs/architecture/, docs/ethos/).

manifest.json: bump to v0.7.0, add recipes_dir field.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: v0.7.0 CHANGELOG, TODOS, VERSION bump

CHANGELOG: v0.7.0 entry covering integration recipes, voice-to-brain,
gbrain integrations command, SKILLPACK breakout, and new documentation.

TODOS: 3 new items from CEO/DX reviews (constrained health_check DSL,
community recipe submission, always-on deployment recipes).

VERSION + package.json: bump to 0.7.0.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: rewrite voice recipe with agent instructions and verified links

Major improvements to recipes/twilio-voice-brain.md:

- Agent preamble: explains WHY sequential execution matters (each step
  depends on the previous), defines 4 stop points where the agent MUST
  pause and verify, tells agent to never say "something went wrong"
  but instead explain the exact error and fix

- User actions are now specific: exact URLs for every credential
  (Twilio console, OpenAI API keys page, ngrok dashboard), what
  buttons to click, what fields to copy, common failure modes

- All URLs verified via web search against current 2026 documentation:
  Twilio SID/token at twilio.com/console, OpenAI keys at
  platform.openai.com/api-keys, ngrok token at
  dashboard.ngrok.com/get-started/your-authtoken

- Cost estimate corrected: OpenAI Realtime is $0.06/min input +
  $0.24/min output (was understated), total ~$20-22/mo for 100 min

- Validate-as-you-go: each credential tested immediately with exact
  curl commands, failure messages explain what went wrong and how to fix

- Smoke test flow: tells user exactly what to say, verifies ALL
  three outputs (messaging notification + brain page + search result)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: add "Homebrew for Personal AI" essay (markdown is code)

New essay at docs/ethos/MARKDOWN_SKILLS_AS_RECIPES.md — the distribution
corollary to "Thin Harness, Fat Skills." Argues that markdown skill files
are simultaneously documentation, specification, package, and source code.
The agent is the package manager. The git repo is the app store.

Referenced from SKILLPACK index and CLAUDE.md.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: rewrite agent instructions as command language, promote skills

The OpenClaw/Hermes install block is now a drill sergeant, not a tour guide.
Every step is an imperative command with exact verification criteria and
explicit stop-on-failure behavior. No FYI, no suggestions, just rails.

Key changes:
- 11-step setup with STOP points after each step
- Exact user instructions for Supabase connection string (what to click,
  what NOT to give the agent, what the string looks like)
- "Verify: run X. You must see Y. If not: Z" after every step
- Skills table now links to both skill files AND guide docs
- Integration recipes table simplified (no "coming soon" placeholders)
- Docs section reorganized: for agents / for humans / reference

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: 4 codex findings + add email-to-brain recipe

Codex review found 4 issues, all fixed:

1. getStatus() returned "configured" if ANY secret was set (e.g. just
   OPENAI_API_KEY). Now requires ALL required secrets before marking
   configured. Prevents false "configured" status and spurious doctor runs.

2. Twilio health check hit unauthenticated endpoint (always 401). Now
   uses authenticated curl with SID:token, matching the setup validation.

3. README anchor docs/GBRAIN_SKILLPACK.md#the-dream-cycle broken after
   SKILLPACK rewrite. Updated to point to docs/guides/cron-schedule.md.

4. Compiled binary can't find recipes/ via import.meta.dir. Added
   GBRAIN_RECIPES_DIR env var override + global bun install path fallback.

Also adds recipes/email-to-brain.md: Gmail deterministic collector pattern
with ClawVisor credential gateway, validate-as-you-go, agent instructions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add email, X, calendar, and meeting sync recipes

Four new integration recipes extracted from production wintermute patterns:

- recipes/email-to-brain.md: Gmail via ClawVisor, deterministic collector
  pattern (code pulls emails with baked-in links, agent does judgment),
  noise filtering, signature detection, digest generation

- recipes/x-to-brain.md: X API v2, timeline + mentions + keyword search,
  deletion detection (diffs previous run, verifies 404), engagement
  velocity tracking, rate limit awareness

- recipes/calendar-to-brain.md: Google Calendar via ClawVisor, historical
  backfill (years of data), daily markdown files with attendees + locations,
  attendee enrichment for brain pages

- recipes/meeting-sync.md: Circleback API, transcript import with speaker
  labels, attendee detection + filtering, entity propagation to people/
  company pages, action item extraction, idempotent by source_id

All recipes follow the same format: agent preamble with sequential execution
rules, validate-as-you-go credentials, exact URLs for API key setup,
stop-on-failure verification, and heartbeat logging.

Updated README, SKILLPACK index, and integrations landing page with all 5 recipes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: add Google OAuth as alternative to ClawVisor in email + calendar recipes

Both recipes now offer two auth options:
- Option A: ClawVisor (recommended, handles OAuth + token refresh)
- Option B: Google OAuth2 directly (no extra service, you manage tokens)

Option B includes step-by-step instructions for Google Cloud Console:
exact URLs, which buttons to click, which scopes to add, how to enable
the API, and the OAuth flow for token exchange.

This removes ClawVisor as a hard dependency for getting started.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: add implementation guides with pseudocode and test suggestions

Every recipe now includes an "Implementation Guide" section with:

- Production-tested pseudocode the agent can follow to build each collector
- Edge cases and failure modes discovered in real deployment
- Non-obvious implementation details (why the 48h staleness heuristic,
  why Gmail links need authuser, why SSE responses need double-parsing)
- Test suggestions: what the agent should verify after setup

email-to-brain: noise filtering algorithm, signature detection patterns,
  Gmail link generation (authuser is critical), sent-mail dedup

x-to-brain: deletion detection with 3 heuristics (7-day, 48h staleness,
  API verification), engagement velocity thresholds (50 min for 2x, 100
  absolute jump), atomic writes, stdout contract, rate limit handling

calendar-to-brain: smart chunking (monthly for sparse years, weekly for
  dense), attendee filtering (rooms, groups, distros), merge-with-existing
  (only replace ## Calendar section), date/time parsing edge cases

meeting-sync: SSE double-JSON parsing, idempotency double-check (grep +
  filename), auto-tagging from meeting names, git commit after sync

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: 6 new guides from production patterns (wintermute extraction)

New guides extracted and generalized from production deployment:

- repo-architecture.md: Two-repo pattern (agent behavior vs world knowledge).
  Strict boundary rules, decision tree, hard rule: never write knowledge
  to the agent repo.

- sub-agent-routing.md: Model routing table by task type. Signal detector
  pattern (spawn Sonnet on every message). Research pipeline pattern
  (Opus plans, DeepSeek executes, Opus synthesizes). Cost optimization.

- skill-development.md: 5-step cycle (concept, prototype, evaluate, codify,
  cron). MECE discipline (no overlapping skills). Quality bar checklist.
  "If you ask twice, it should already be a skill."

- idea-capture.md: Originality distribution rating (0-100 across 4
  populations). Depth test ("could someone unfamiliar understand WHY?").
  Deep cross-linking mandate. Notability filtering.

- quiet-hours.md: Hold notifications 11pm-8am local time. Held messages
  directory pattern. Timezone-aware delivery. Morning briefing pickup.

- diligence-ingestion.md: 9-step pipeline for data room materials. Detection
  patterns (PDF filenames, spreadsheet tabs, user language). Index.md
  template with bull/bear case. Company page enrichment.

All PII scrubbed. Patterns generalized for any user.
SKILLPACK index updated with 6 new entries. CLAUDE.md references added.
All 37 SKILLPACK links verified.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: upgrade all guides to operational playbooks with pseudocode

Every guide now follows the playbook structure:
- Goal: one sentence, what this achieves
- What the User Gets: without this / with this
- Implementation: pseudocode with actual gbrain commands
- Tricky Spots: production-tested gotchas
- How to Verify: test steps the agent runs after setup

Guides upgraded (15 files):
- brain-agent-loop: on_message() loop with read/write/sync pseudocode
- brain-first-lookup: 4-step lookup cascade with exact commands
- brain-vs-memory: routing algorithm for 3 knowledge layers
- compiled-truth: page structure + rewrite vs append rules
- content-media: 3 ingest patterns (YouTube, social, PDFs)
- cron-schedule: full schedule table + dream cycle pseudocode
- enrichment-pipeline: 7-step protocol with tier classification
- entity-detection: spawn pattern + detection prompt + notability filter
- executive-assistant: 3 workflow algorithms (triage, prep, post-inbox)
- meeting-ingestion: 6-step transcript-to-brain flow
- operational-disciplines: 5 executable discipline blocks
- originals-folder: detection + exact-phrasing capture + cross-linking
- search-modes: decision tree for keyword vs hybrid vs direct
- source-attribution: citation format + hierarchy + conflict resolution
- Plus Goal/What User Gets headers on 6 newer guides

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: add WebRTC to voice recipe + ngrok Hobby setup guide

Voice recipe updates:
- Added WebRTC endpoint (POST /session, GET /call, POST /tool) for
  browser-based calling with RNNoise noise suppression
- WebRTC pseudocode with the 4 non-obvious gotchas from production
  (voice under audio.output.voice, no turn_detection, no session.update
  on connect, trigger greeting via data channel)
- Recommend ngrok Hobby ($8/mo) for fixed domain instead of free tier
- Fixed domain means URLs never change, Twilio never breaks

New guide: docs/mcp/NGROK_SETUP.md
- How to set up ngrok Hobby for both MCP and voice agent
- Fixed domain setup, watchdog pattern, AI client configuration
- Claude Desktop requires Settings > Integrations (not JSON config)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add dependency graph + ngrok-tunnel + credential-gateway recipes

Recipes now have real dependencies via the `requires` field:
- voice-to-brain requires ngrok-tunnel (needs public URL for Twilio)
- email-to-brain requires credential-gateway (needs Gmail access)
- calendar-to-brain requires credential-gateway (needs Calendar access)
- x-to-brain and meeting-sync are standalone (direct API keys)

Two new infrastructure recipes:
- ngrok-tunnel: fixed public URL for MCP + voice. Recommends Hobby
  ($8/mo) for a domain that never changes. Includes watchdog pattern.
- credential-gateway: secure Google service access via ClawVisor
  (recommended) or direct OAuth2. One setup, all Google recipes use it.

Moved ngrok from docs/mcp/ to recipes/ — it's shared infrastructure,
not MCP-specific.

README and integrations landing page show dependency chains.
When agent installs voice-to-brain, it sets up ngrok-tunnel first.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: add infra category, fix dashboard alignment, show dependencies

DX audit found two bugs in gbrain integrations dashboard:

1. Column alignment broken — IDs > 18 chars ran into descriptions
   with no space. Fixed: pad to 22 chars.

2. ngrok-tunnel and credential-gateway showed as SENSES but they're
   infrastructure. Added 'infra' category. Dashboard now shows three
   sections: INFRASTRUCTURE (set up first), SENSES, REFLEXES.

3. Dependencies now shown inline: "AVAILABLE (needs credential-gateway)"

Also added 'requires' field to JSON output for agent consumption.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: add frontier model requirement disclaimer to README

GBrain's markdown-is-code approach requires models capable of
interpreting intent and implementing from architecture descriptions.
Tested with Claude Opus 4.6 and GPT-5.4 Thinking. Smaller models
will struggle with the recipe format.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: add PGLite → Supabase upgrade path to README

Clarify the database progression: start with PGLite (Postgres as WASM,
zero infrastructure, pgvector built in, nothing to install). Graduate
to Supabase or self-hosted Postgres when you need connection pooling,
concurrency, and remote MCP access from Claude Desktop, Cowork,
ChatGPT, Perplexity Computer, or any MCP-compatible agent.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: revert PGLite mention (coming in next branch)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: make all 23 guides consistent (Goal/Impl/Tricky/Verify)

Every guide now has exactly these sections in this order:
- ## Goal (one sentence)
- ## What the User Gets (without this / with this)
- ## Implementation (pseudocode with gbrain commands)
- ## Tricky Spots (3-5 numbered gotchas)
- ## How to Verify (3-5 numbered test steps)

11 guides restructured from non-standard headings:
- deterministic-collectors, live-sync, upgrades-auto-update (full rewrites)
- entity-detection, diligence-ingestion, idea-capture, quiet-hours,
  repo-architecture, skill-development, sub-agent-routing (restructured)

23/23 guides now pass consistency audit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: restructure README around the #1 blocker (getting data in)

The README was leading with Postgres and database architecture. Most
users are stuck at step zero: "I have an agent but it doesn't know
anything about my life."

New structure:
1. The Problem — your agent doesn't know your life
2. Getting Data In — integration recipes, front and center
3. The Compounding Thesis — why this matters
4. How this happened — credibility, origin story
5. When you need Postgres — scale, not starting point

Postgres is de-emphasized from a full section to two paragraphs:
"You don't need Postgres to start" and "When you need Postgres"
(1,000+ files, remote MCP access, multiple AI clients).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: move Install to top of README, remove duplicate section

Install now appears right after Getting Data In (line 38), not buried
at line 295. The user sees: Problem → Getting Data In → Install.

Removed the duplicate Install section (262 lines) that was lower in
the README. The agent instructions block, CLI quickstart, and all
content is now in the single Install section near the top.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: move agent install block to first thing in README

"Start here: paste this into your agent" is now the first section,
right after the one-line pitch. No scrolling, no context, no preamble.
User opens the README, sees the paste block, copies it into OpenClaw
or Hermes, and the agent takes over.

Flow: pitch → paste block → Getting Data In → Compounding Thesis → origin story

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: compress install block from 11 steps to 5

The agent install block was 102 lines and 11 steps. Now it's 40 lines
and 5 steps. Same coverage, half the text.

Changes:
- Merged "prove keyword search" + "embed" + "prove hybrid search"
  into one SEARCH step (the user doesn't care about the intermediate)
- Merged skillpack, sync, auto-update, integrations, verification
  into one GO LIVE step with sub-items (post-install polish, not install)
- Shortened database instructions (one line instead of 5 sub-steps)
- Removed redundant preamble ("YOU MUST COMPLETE EVERY STEP" is now
  just "Do not skip steps. Verify each step.")

The 5 steps: INSTALL → DATABASE → IMPORT → SEARCH → GO LIVE

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* security: gitignore all .env files, not just specific ones

CSO audit found .gitignore covered .env.testing and .env.production
but not bare .env. A user creating .env with database credentials
could accidentally commit it.

Fix: .env and .env.* are now gitignored. .env.*.example files are
explicitly un-ignored so templates remain tracked.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* security: scrub PII from essay and recipe examples

- 510-MY-GARRY phone mnemonic → "Your Phone Number"
- "Garry → Authenticated Mode" → "Owner → Authenticated Mode"
- "Telegram" → "secure channel" in auth example
- @garrytan → @yourhandle in X recipe example

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 23:39:06 -10:00

14 KiB

id, name, version, description, category, requires, secrets, health_checks, setup_time, cost_estimate
id name version description category requires secrets health_checks setup_time cost_estimate
calendar-to-brain Calendar-to-Brain 0.7.0 Google Calendar events become searchable brain pages. Daily files with attendees, locations, and meeting prep context. sense
credential-gateway
name description where
CLAWVISOR_URL ClawVisor gateway URL (Option A — recommended, handles OAuth for you) https://clawvisor.com — create an agent, activate Google Calendar service
name description where
CLAWVISOR_AGENT_TOKEN ClawVisor agent token (Option A) https://clawvisor.com — agent settings, copy the agent token
name description where
GOOGLE_CLIENT_ID Google OAuth2 client ID (Option B — direct API access, you manage tokens) https://console.cloud.google.com/apis/credentials — create OAuth 2.0 Client ID
name description where
GOOGLE_CLIENT_SECRET Google OAuth2 client secret (Option B) https://console.cloud.google.com/apis/credentials — same page as client ID
[ -n "$CLAWVISOR_URL" ] && curl -sf $CLAWVISOR_URL/health > /dev/null && echo 'ClawVisor: OK' || [ -n "$GOOGLE_CLIENT_ID" ] && echo 'Google OAuth: configured' || echo 'No calendar auth configured'
20 min $0 (both options are free)

Calendar-to-Brain: Your Schedule Becomes Searchable Memory

Every calendar event becomes a searchable brain page. Your agent knows who you're meeting tomorrow, what you discussed last time, and what context matters. Meeting prep happens automatically because the brain already has the history.

IMPORTANT: Instructions for the Agent

You are the installer. Follow these steps precisely.

Why this matters: Calendar data is the richest source of relationship history. 13 years of calendar data tells you who you've met with, how often, where, and with whom. When someone emails you, the brain already knows your meeting history. When you have a meeting tomorrow, the agent pulls attendee dossiers automatically.

The output is daily markdown files: One file per day at brain/daily/calendar/{YYYY}/{YYYY-MM-DD}.md with all events, attendees, and locations. These files are the foundation for meeting prep, relationship tracking, and pattern detection.

Do not skip steps. Verify after each step.

Architecture

Google Calendar (multiple accounts)
  ↓ (ClawVisor credential gateway, paginated)
Calendar Sync Script (deterministic Node.js)
  ↓ Outputs:
  ├── brain/daily/calendar/{YYYY}/{YYYY-MM-DD}.md   (daily event files)
  ├── brain/daily/calendar/.raw/events-{range}.json  (raw API responses)
  └── brain/daily/calendar/INDEX.md                  (date ranges + monthly summary)
  ↓
Agent reads daily files
  ↓ Judgment calls:
  ├── Attendee enrichment (create/update brain pages for people)
  ├── Meeting prep (pull context before tomorrow's meetings)
  └── Pattern detection (meeting frequency, relationship temperature)

Opinionated Defaults

Multiple calendar accounts:

  • Work calendar (company domain)
  • Personal calendar (gmail.com)
  • Previous company calendars (if still accessible)

Daily file format:

# 2026-04-10 (Thursday)

- 09:00-09:30 **Team standup** (Work) — with Alice, Bob, Carol
- 10:00-11:00 **Board meeting** (Work) 📍 Office — with Diana, Eduardo, Fiona
- 12:00-13:00 **Lunch with Pedro** (Personal) 📍 Chez Panisse — with Pedro Franceschi
- 14:00-14:30 **1:1 with Jordan** (Work) — with Jordan Lee

All-day events listed first. Timed events sorted by start time. Cancelled events are skipped. Attendee names extracted (no email addresses in output). Calendar label in parentheses. Location with 📍 emoji.

Historical backfill: Sync years of calendar data, not just recent. Common ranges:

  • Work: 2020-present
  • Personal: 2014-present This builds the full relationship graph from day one.

Prerequisites

  1. GBrain installed and configured (gbrain doctor passes)
  2. Node.js 18+ (for the sync script)
  3. Google Calendar access via ONE of:
    • Option A: ClawVisor (recommended, handles OAuth for you, no token management)
    • Option B: Google OAuth2 directly (you manage tokens, no extra service needed)

Setup Flow

Step 1: Choose and Configure Calendar Access

Ask the user: "How do you want to connect to Google Calendar?

Option A: ClawVisor (recommended) ClawVisor handles OAuth, token refresh, and encryption. You never touch Google credentials directly. If you already use ClawVisor for email, this uses the same setup.

Option B: Google OAuth2 directly Connect to Google Calendar API directly. No extra service needed, but you manage OAuth tokens yourself. Good if you don't want another dependency."

Option A: ClawVisor Setup

Tell the user: "I need your ClawVisor URL and agent token.

  1. Go to https://clawvisor.com
  2. Create an agent (or use existing)
  3. Activate the Google Calendar service
  4. Create a standing task with purpose: 'Full calendar access for historical backfill and ongoing sync. List events, read event details, search across all calendars.' IMPORTANT: Be EXPANSIVE in the task purpose. Narrow purposes block requests.
  5. Copy the gateway URL and agent token"

Validate:

curl -sf "$CLAWVISOR_URL/health" && echo "PASS: ClawVisor reachable" || echo "FAIL"

STOP until ClawVisor validates.

Option B: Google OAuth2 Setup

Tell the user: "I need Google OAuth2 credentials. Here's exactly how to set them up:

  1. Go to https://console.cloud.google.com/apis/credentials (create a Google Cloud project if you don't have one)
  2. Click '+ CREATE CREDENTIALS' at the top, select 'OAuth client ID'
  3. If prompted, configure the OAuth consent screen first:
    • User type: External (or Internal if you have Google Workspace)
    • App name: anything (e.g., 'GBrain Calendar')
    • Scopes: add 'Google Calendar API .../auth/calendar.readonly'
    • Test users: add your own email
  4. Back on Credentials, create the OAuth client ID:
    • Application type: Desktop app
    • Name: anything (e.g., 'GBrain')
  5. Click 'Create'. You'll see the Client ID and Client Secret.
  6. Copy both and paste them to me.

Also enable the Calendar API: 7. Go to https://console.cloud.google.com/apis/library/calendar-json.googleapis.com 8. Click 'Enable'"

Validate the credentials are set:

[ -n "$GOOGLE_CLIENT_ID" ] && [ -n "$GOOGLE_CLIENT_SECRET" ] \
  && echo "PASS: Google OAuth credentials set" \
  || echo "FAIL: Missing GOOGLE_CLIENT_ID or GOOGLE_CLIENT_SECRET"

Then run the OAuth flow to get an access token:

# The sync script should handle the OAuth flow:
# 1. Open browser to Google auth URL with calendar.readonly scope
# 2. User grants access
# 3. Script receives auth code, exchanges for access + refresh token
# 4. Stores tokens in ~/.gbrain/google-tokens.json
# 5. Auto-refreshes on expiry

STOP until OAuth flow completes and tokens are stored.

Step 2: Identify Calendar Accounts

Ask the user: "Which Google Calendar accounts should I sync? Common setup:

For each account, note:

  • Email address
  • Start year (how far back to sync)
  • Label (Work, Personal, etc.)

Step 3: Set Up the Calendar Sync Script

Create the sync directory:

mkdir -p calendar-sync
cd calendar-sync
npm init -y

The sync script needs these capabilities:

  1. Paginated event retrieval — Google Calendar API returns max 50 events per request. The script must paginate through large date ranges. Use monthly chunks for sparse periods, weekly for dense ones.
  2. Daily markdown generation — group events by date, format as markdown with times, attendees, locations, calendar labels
  3. Merge with existing files — if a daily file already has manual notes, preserve them when updating calendar data
  4. Index generation — create INDEX.md with date ranges, event counts, monthly summary
  5. Raw JSON preservation — save raw API responses to .raw/ for provenance

Step 4: Run Historical Backfill

This is the big initial sync. It may take 10-30 minutes depending on how many years of calendar data you have.

node calendar-sync.mjs --start 2020-01-01 --end $(date +%Y-%m-%d)

Tell the user: "Syncing calendar history from [start year]. This creates one markdown file per day. For 4 years of data, expect ~1,400 daily files."

Verify:

ls brain/daily/calendar/2026/ | head -10

Should show daily files like 2026-04-01.md, 2026-04-02.md, etc.

Step 5: Import Calendar Data to GBrain

gbrain import brain/daily/calendar/ --no-embed
gbrain embed --stale

Verify:

gbrain search "meeting" --limit 3

Should return calendar pages with event details.

Step 6: Attendee Enrichment

This is YOUR job (the agent). For each person who appears in calendar events:

  1. Check brain: gbrain search "attendee name" — do they have a page?
  2. Create page if missing: notable attendees (appears 3+ times) get a brain page
  3. Update existing pages: add meeting history to timeline: - YYYY-MM-DD | Meeting: {event title} [Source: Google Calendar]
  4. Relationship tracking: note meeting frequency in compiled truth: "Met 12 times in last 6 months. Regular 1:1 cadence."

Step 7: Set Up Weekly Sync

The calendar should sync weekly to stay current:

# Cron: every Sunday at 10 AM
0 10 * * 0 cd /path/to/calendar-sync && node calendar-sync.mjs --start $(date -v-7d +%Y-%m-%d) --end $(date +%Y-%m-%d)

After sync, import new data:

gbrain sync --no-pull --no-embed && gbrain embed --stale

Step 8: Log Setup Completion

mkdir -p ~/.gbrain/integrations/calendar-to-brain
echo '{"ts":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","event":"setup_complete","source_version":"0.7.0","status":"ok","details":{"accounts":"ACCOUNT_COUNT","start_year":"YYYY"}}' >> ~/.gbrain/integrations/calendar-to-brain/heartbeat.jsonl

Tell the user: "Calendar-to-brain is set up. You have [N] days of calendar history indexed. I can now prep you for meetings by pulling attendee context from the brain. Weekly sync keeps it current."

Implementation Guide

These are production-tested patterns from syncing 13 years of calendar data.

Smart Chunking (Monthly vs Weekly)

generate_chunks(start, end, dense_after='2023-01-01'):
  chunks = []
  current = start

  while current < end:
    if current < dense_after:
      next = current + 1_MONTH    // sparse period: monthly
    else:
      next = current + 7_DAYS     // dense period: weekly

    chunks.append({from: current, to: min(next, end)})
    current = next

  return chunks

Why: Monthly chunks for sparse years (2014-2023) = ~96 API calls for 8 years. Weekly for everything would be ~600+ calls. Per-calendar startYear avoids pulling empty months (e.g., don't query 2014-2020 for a calendar created in 2020).

Attendee Filtering

filter_attendees(attendees):
  return attendees.filter(a =>
    !a.email?.includes('@resource.calendar.google.com') AND  // conference rooms
    !a.email?.includes('@group.calendar.google.com') AND     // mailing lists
    !a.name?.startsWith('YC-SF-')                            // internal distros
  )

Without this, your attendee list is polluted with "Conference Room A" and "engineering-all@company.com". You want actual people.

Merge with Existing Files (Preserve Manual Notes)

write_daily_file(date, events, dir):
  path = f'{dir}/{date}.md'
  calendar_md = format_events(events)

  if file_exists(path):
    existing = read(path)
    if '## Calendar' in existing:
      // Replace ONLY the calendar section, keep everything else
      before = existing.split('## Calendar')[0]
      after_match = regex_search(existing, /## [A-Z](?!alendar)/)  // next section
      after = after_match ? existing[match_index:] : ''
      write(path, f'{before}## Calendar\n\n{calendar_md}\n{after}')
    else:
      write(path, f'## Calendar\n\n{calendar_md}\n---\n\n{existing}')
  else:
    write(path, calendar_md)

Critical: Only touch ## Calendar. Everything else is preserved. If you manually added ## Notes to a daily file, it survives re-sync.

Date/Time Parsing Edge Cases

parse_event_date(event):
  // All-day: event.start = "2024-01-15" (no T)
  // Timed: event.start = "2024-01-15T10:00:00-08:00" (with T)
  if 'T' in event.start:
    return event.start[0:10]    // extract date from datetime
  return event.start            // already a date

format_time(iso_str):
  if not iso_str or 'T' not in iso_str: return 'all-day'
  // Extract hours:minutes, convert to 12-hour
  // Edge: 00:00 = 12:00 AM, 12:00 = 12:00 PM, 13:00 = 1:00 PM

What the Agent Should Test After Setup

  1. Monthly vs weekly: Run from 2014 with dense_after=2023. Verify pre-2023 makes ~12 API calls per year, post-2023 makes ~4 per month.
  2. Attendee filtering: Create a meeting with a conference room and a mailing list. Sync. Verify neither appears in the daily file.
  3. Merge preservation: Add ## Notes to a daily file manually. Sync calendar. Verify notes are preserved.
  4. All-day events: Create an all-day event and a timed event on the same day. Verify all-day appears first, timed events sorted by start time.
  5. Cancelled events: Cancel a meeting. Sync. Verify it doesn't appear.
  6. Per-calendar startYear: Sync a calendar created in 2022 with startYear=2022. Verify no API calls for years before 2022.

Cost Estimate

Component Monthly Cost
ClawVisor (free tier) $0
Google Calendar API $0 (within free quota)
Total $0

Troubleshooting

No events returned:

  • Check the calendar account email is correct
  • Check ClawVisor has Google Calendar service activated
  • Check the standing task purpose is expansive enough
  • Some calendars may be empty for the requested date range

Attendee names missing:

  • Google Calendar sometimes returns email addresses instead of display names
  • The sync script should extract the display name from the attendee object
  • If no display name, use the email prefix (before @)

Duplicate events:

  • The sync script should be idempotent (same date range = same output)
  • If running multiple times, existing daily files are overwritten (not appended)