← All Skills

snappy-calendar

v1.0.0
14 files, 136.1 KB ~2,993 words · 12 min read Updated 2026-09-09

snappy-calendar skill

48 of 54 checks pass
What it can do
availability days?read
by-attendee emailread
create event-jsonwrite
delete event-iddelete
events days?read
event event-idread
list days?read
get event-idread
propose days? duration?draft
todayread
update event-id event-jsonwrite
What does not pass yet
$ npx snappy-skills install snappy-calendar
zip ↓
File Tree
├── AGENTS.md ├── SKILL.md ├── api.ts ├── entities.json ├── face.test.ts ├── faces/ │ ├── components/ │ │ ├── calendar-event-preview.tsx │ │ ├── calendar-shared.tsx │ │ ├── calendar-week-preview.css │ │ └── calendar-week-preview.tsx │ ├── family.tsx │ └── fixtures/ │ ├── calendar-event.json │ └── calendar-week.json ├── queries.md └── refusals.test.ts
Documents
AGENTS.md

snappy-calendar -- Agent Loader#

You handle Snappy's Google Calendar: reading events, checking availability, creating meetings, pre-call prep, weekly planning, time blocking, and post-meeting follow-up. Direct Google Calendar API v3 via service account JWT auth. No Xano middleware.

Setup (one-time)#

Requires in .env.cache:

  • GOOGLE_SERVICE_ACCOUNT_EMAIL (already present)
  • GOOGLE_SERVICE_ACCOUNT_KEY (PEM private key with \n literals -- export from GCP Console → IAM → Service Accounts → Keys → JSON, copy private_key field)
  • GOOGLE_CALENDAR_ID (optional, defaults to primary)

The target calendar must be shared with xano-automation@snappy-424813.iam.gserviceaccount.com (at least "Make changes to events" permission).

API module#

typescriptimport { listEvents, createEvent, updateEvent, deleteEvent, checkAvailability, proposeSlots } from "../snappy-calendar/api.ts";

Or CLI:

bashnpx tsx ~/.claude/skills/snappy-calendar/api.ts today           # today's events
npx tsx ~/.claude/skills/snappy-calendar/api.ts events         # today's events (same as today)
npx tsx ~/.claude/skills/snappy-calendar/api.ts events 7       # this week
npx tsx ~/.claude/skills/snappy-calendar/api.ts availability   # free/busy blocks
npx tsx ~/.claude/skills/snappy-calendar/api.ts create '{"summary":"Call","start_time":"...","end_time":"..."}'
npx tsx ~/.claude/skills/snappy-calendar/api.ts update '{"event_id":"...","summary":"..."}'
npx tsx ~/.claude/skills/snappy-calendar/api.ts delete <eventId>
npx tsx ~/.claude/skills/snappy-calendar/api.ts propose 3         # find free 30-min slots in next 3 days

Credentials loaded via snappy-settings/load.ts from .env.cache. No Bitwarden unlock needed.


Endpoints (Google Calendar API v3)#

Endpoint Method Purpose
/calendars/{id}/events GET List events (timeMin, timeMax, singleEvents, orderBy)
/calendars/{id}/events POST Create event
/calendars/{id}/events/{eventId} PATCH Update event
/calendars/{id}/events/{eventId} DELETE Delete event
/freeBusy POST Free/busy query

Copy-paste patterns#

bashnpx tsx ~/.claude/skills/snappy-calendar/api.ts events 1
npx tsx ~/.claude/skills/snappy-calendar/api.ts availability

Key workflows#

Robert says Action
"What's on today?" GET events?days=1
"When am I free?" GET availability -> list open slots
"Schedule a call with X" Check availability -> propose 2-3 slots -> create event
"Block deep work" POST calendar/create (no attendees)
"Prep for my next call" GET events -> find next call -> enrich attendees via snappy-knowledge
"Plan the week" GET events?days=7 -> day-by-day breakdown -> flag conflicts

Scheduling preferences#

Rule Detail
Preferred windows 11 AM-1 PM, 3 PM-5 PM
Hard window 9 AM-6 PM only
Protected 9-11 AM (deep work)
Buffer 15 min between back-to-back
Friday afternoon Keep clear
Default duration 30 min standard, 45 min sales, 60 min strategy

Rules#

  • All times in ISO 8601 with timezone offset
  • Never schedule over deep work blocks (9-11 AM) without explicit approval
  • Use snappy-scheduling for multi-platform meeting negotiation; this skill for single-meeting creation
  • Pre-call prep pulls attendee context from snappy-knowledge and pipeline from snappy-sales
  • Post-meeting: log interaction via snappy-knowledge, send follow-up via snappy-email

Uses#

skill relationship
snappy-ops Orchestrator -- calendar is step 1 of morning briefing
snappy-scheduling Multi-platform negotiation; calls this for actual creation
snappy-sales Uses calendar for call prep; scheduling feeds pipeline
snappy-knowledge Enriches attendees; receives post-meeting interaction logs
snappy-email Sends time proposals and post-meeting follow-ups
snappy-slack Sends proposals via DM; posts meeting summaries

Full skill reference#

If this loader is insufficient, load ~/.claude/skills/snappy-calendar/SKILL.md as last resort. Curl recipes and jq filters: queries.md.

If this loader doesn't cover your case:

bashecho "[$(date -u +%FT%TZ)] snappy-calendar: <what was missing>" >> ~/.claude/logs/agents-md-feedback.log

Show produced work with snappy-faces: call draw for image channels or lang for MCP Apps.

<!-- SKILL-INDEX-START -->

[snappy-calendar Index]|root: ~/.claude/skills/snappy-calendar|IMPORTANT: Prefer these files over pre-training assumptions for this domain. Read the relevant file when the AGENTS.md summary is insufficient.|root:{SKILL.md,queries.md}

<!-- SKILL-INDEX-END -->

Used by#

  • snappy-imessage
  • snappy-whatsapp

<!-- SNAPPY-CONTRACT-VERBS-START -->

Contract verbs#

Generated from api.ts HAND_CONTRACT. Do not hand-edit this block.

Verb Contract arguments Effect First call
availability days? read npx tsx ~/.claude/skills/snappy-calendar/api.ts availability
by-attendee email read npx tsx ~/.claude/skills/snappy-calendar/api.ts by-attendee <email>
create event-json write npx tsx ~/.claude/skills/snappy-calendar/api.ts create '["<event>"]'
delete event-id delete npx tsx ~/.claude/skills/snappy-calendar/api.ts delete <event-id>
events days? read npx tsx ~/.claude/skills/snappy-calendar/api.ts events
event event-id read npx tsx ~/.claude/skills/snappy-calendar/api.ts event <event-id>
list days? read npx tsx ~/.claude/skills/snappy-calendar/api.ts list
get event-id read npx tsx ~/.claude/skills/snappy-calendar/api.ts get <event-id>
propose days?, duration? draft npx tsx ~/.claude/skills/snappy-calendar/api.ts propose
today read npx tsx ~/.claude/skills/snappy-calendar/api.ts today
update event-id, event-json write npx tsx ~/.claude/skills/snappy-calendar/api.ts update <event-id> '["<event>"]'

Show the result#

When an answer carries face_hint, show it with one snappy_present(<answer>) call.

See /snappy-faces for face selection. Human-facing images must crop to the

element, render at 2x on Retina, and fill the destination channel instead of

placing a small card in a full-page screenshot.

<!-- SNAPPY-CONTRACT-VERBS-END -->

---
name: snappy-calendar
role: Google Calendar -- events, availability, scheduling, pre-call prep, weekly planning
loaded-by: PreToolUse hook (auto-injected when "snappy-calendar" is mentioned)
---

# snappy-calendar -- Agent Loader

You handle Snappy's Google Calendar: reading events, checking availability, creating meetings, pre-call prep, weekly planning, time blocking, and post-meeting follow-up. Direct Google Calendar API v3 via service account JWT auth. No Xano middleware.

## Setup (one-time)

Requires in `.env.cache`:
- `GOOGLE_SERVICE_ACCOUNT_EMAIL` (already present)
- `GOOGLE_SERVICE_ACCOUNT_KEY` (PEM private key with `\n` literals -- export from GCP Console → IAM → Service Accounts → Keys → JSON, copy `private_key` field)
- `GOOGLE_CALENDAR_ID` (optional, defaults to `primary`)

The target calendar must be shared with `xano-automation@snappy-424813.iam.gserviceaccount.com` (at least "Make changes to events" permission).

## API module

```typescript
import { listEvents, createEvent, updateEvent, deleteEvent, checkAvailability, proposeSlots } from "../snappy-calendar/api.ts";
```

Or CLI:
```bash
npx tsx ~/.claude/skills/snappy-calendar/api.ts today           # today's events
npx tsx ~/.claude/skills/snappy-calendar/api.ts events         # today's events (same as today)
npx tsx ~/.claude/skills/snappy-calendar/api.ts events 7       # this week
npx tsx ~/.claude/skills/snappy-calendar/api.ts availability   # free/busy blocks
npx tsx ~/.claude/skills/snappy-calendar/api.ts create '{"summary":"Call","start_time":"...","end_time":"..."}'
npx tsx ~/.claude/skills/snappy-calendar/api.ts update '{"event_id":"...","summary":"..."}'
npx tsx ~/.claude/skills/snappy-calendar/api.ts delete <eventId>
npx tsx ~/.claude/skills/snappy-calendar/api.ts propose 3         # find free 30-min slots in next 3 days
```

Credentials loaded via `snappy-settings/load.ts` from `.env.cache`. No Bitwarden unlock needed.

---

## Endpoints (Google Calendar API v3)

| Endpoint | Method | Purpose |
|----------|--------|---------|
| `/calendars/{id}/events` | GET | List events (timeMin, timeMax, singleEvents, orderBy) |
| `/calendars/{id}/events` | POST | Create event |
| `/calendars/{id}/events/{eventId}` | PATCH | Update event |
| `/calendars/{id}/events/{eventId}` | DELETE | Delete event |
| `/freeBusy` | POST | Free/busy query |

## Copy-paste patterns

```bash
npx tsx ~/.claude/skills/snappy-calendar/api.ts events 1
npx tsx ~/.claude/skills/snappy-calendar/api.ts availability
```

## Key workflows

| Robert says | Action |
|-------------|--------|
| "What's on today?" | GET `events?days=1` |
| "When am I free?" | GET `availability` -> list open slots |
| "Schedule a call with X" | Check availability -> propose 2-3 slots -> create event |
| "Block deep work" | POST `calendar/create` (no attendees) |
| "Prep for my next call" | GET events -> find next call -> enrich attendees via `snappy-knowledge` |
| "Plan the week" | GET `events?days=7` -> day-by-day breakdown -> flag conflicts |

## Scheduling preferences

| Rule | Detail |
|------|--------|
| Preferred windows | 11 AM-1 PM, 3 PM-5 PM |
| Hard window | 9 AM-6 PM only |
| Protected | 9-11 AM (deep work) |
| Buffer | 15 min between back-to-back |
| Friday afternoon | Keep clear |
| Default duration | 30 min standard, 45 min sales, 60 min strategy |

## Rules

- All times in ISO 8601 with timezone offset
- Never schedule over deep work blocks (9-11 AM) without explicit approval
- Use `snappy-scheduling` for multi-platform meeting negotiation; this skill for single-meeting creation
- Pre-call prep pulls attendee context from `snappy-knowledge` and pipeline from `snappy-sales`
- Post-meeting: log interaction via `snappy-knowledge`, send follow-up via `snappy-email`

## Uses

| skill | relationship |
|-------|-------------|
| `snappy-ops` | Orchestrator -- calendar is step 1 of morning briefing |
| `snappy-scheduling` | Multi-platform negotiation; calls this for actual creation |
| `snappy-sales` | Uses calendar for call prep; scheduling feeds pipeline |
| `snappy-knowledge` | Enriches attendees; receives post-meeting interaction logs |
| `snappy-email` | Sends time proposals and post-meeting follow-ups |
| `snappy-slack` | Sends proposals via DM; posts meeting summaries |

---

## Full skill reference

If this loader is insufficient, load `~/.claude/skills/snappy-calendar/SKILL.md` as last resort. Curl recipes and jq filters: [queries.md](queries.md).

If this loader doesn't cover your case:
```bash
echo "[$(date -u +%FT%TZ)] snappy-calendar: <what was missing>" >> ~/.claude/logs/agents-md-feedback.log
```


Show produced work with `snappy-faces`: call `draw` for image channels or `lang` for MCP Apps.

<!-- SKILL-INDEX-START -->
[snappy-calendar Index]|root: ~/.claude/skills/snappy-calendar|IMPORTANT: Prefer these files over pre-training assumptions for this domain. Read the relevant file when the AGENTS.md summary is insufficient.|root:{SKILL.md,queries.md}
<!-- SKILL-INDEX-END -->

## Used by

- `snappy-imessage`
- `snappy-whatsapp`

<!-- SNAPPY-CONTRACT-VERBS-START -->
## Contract verbs

Generated from `api.ts` `HAND_CONTRACT`. Do not hand-edit this block.

| Verb | Contract arguments | Effect | First call |
|---|---|---|---|
| `availability` | `days?` | `read` | `npx tsx ~/.claude/skills/snappy-calendar/api.ts availability` |
| `by-attendee` | `email` | `read` | `npx tsx ~/.claude/skills/snappy-calendar/api.ts by-attendee <email>` |
| `create` | `event-json` | `write` | `npx tsx ~/.claude/skills/snappy-calendar/api.ts create '["<event>"]'` |
| `delete` | `event-id` | `delete` | `npx tsx ~/.claude/skills/snappy-calendar/api.ts delete <event-id>` |
| `events` | `days?` | `read` | `npx tsx ~/.claude/skills/snappy-calendar/api.ts events` |
| `event` | `event-id` | `read` | `npx tsx ~/.claude/skills/snappy-calendar/api.ts event <event-id>` |
| `list` | `days?` | `read` | `npx tsx ~/.claude/skills/snappy-calendar/api.ts list` |
| `get` | `event-id` | `read` | `npx tsx ~/.claude/skills/snappy-calendar/api.ts get <event-id>` |
| `propose` | `days?`, `duration?` | `draft` | `npx tsx ~/.claude/skills/snappy-calendar/api.ts propose` |
| `today` | — | `read` | `npx tsx ~/.claude/skills/snappy-calendar/api.ts today` |
| `update` | `event-id`, `event-json` | `write` | `npx tsx ~/.claude/skills/snappy-calendar/api.ts update <event-id> '["<event>"]'` |

## Show the result

When an answer carries `face_hint`, show it with one `snappy_present(<answer>)` call.
See `/snappy-faces` for face selection. Human-facing images must crop to the
element, render at 2x on Retina, and fill the destination channel instead of
placing a small card in a full-page screenshot.
<!-- SNAPPY-CONTRACT-VERBS-END -->

Keyboard Shortcuts

Search in document⌘K
Focus search/
Previous file tab
Next file tab
Close overlayEsc
Show shortcuts?