🎁 Get the FREE AI Skills Starter Guide β€” Subscribe β†’
BytesAgainBytesAgain
πŸ¦€ ClawHub

Calendar Hold Sync

by @tdewitt

Sync one or more source Google calendars into private Busy hold events in one or more target calendars using gog. Use when users need idempotent double-booki...

Versionv1.0.1
Downloads1,545
Stars⭐ 2
TERMINAL
clawhub install calendar-hold-sync

πŸ“– About This Skill


name: calendar-hold-sync description: Sync one or more source Google calendars into private Busy hold events in one or more target calendars using gog. Use when users need idempotent double-booking prevention, backfill of legacy holds, drift reconcile, or safe scheduled sync.

Calendar Hold Sync

Implement hold mirroring from source Google calendars into target calendars to prevent double-booking.

Dependency

  • Require gog CLI in PATH.
  • Require user OAuth already configured for each account used in mappings.
  • Do not hardcode account emails, calendar IDs, or event IDs in code.
  • If gog is not configured, use this setup flow:

    1. Run gog auth credentials /path/to/client_secret.json. 2. Run gog auth add you@gmail.com --services calendar. 3. Verify with gog auth list.

    Only add additional Google services if you explicitly need them for another workflow.

    Official gog references:

  • Homepage: https://gogcli.sh/
  • Source: https://github.com/steipete/gogcli
  • Config Contract

    Use a user-provided JSON config file with this shape:

  • mappings[]
  • mappings[].name
  • mappings[].targetAccount
  • mappings[].targetCalendarId (default primary)
  • mappings[].sources[] with { account, calendarId }
  • mappings[].lookaheadDays (default 30)
  • mappings[].allDayMode: ignore|mirror
  • mappings[].overlapPolicy: skip|allow
  • hold.summary (default Busy)
  • hold.visibility (private)
  • hold.transparency (busy)
  • hold.notifications (none)
  • hold.reminders (none)
  • metadata.format (SYNCV1)
  • metadata.encoding (base64url(json))
  • metadata.fields: srcAccount,srcCalendar,eventId,start,end,title
  • scheduling.reconcileCron
  • scheduling.daytimeCron (optional)
  • scheduling.driftWindowDays (optional)
  • scheduling.watchIntervalSeconds (optional, default 20)
  • safety.dryRun
  • safety.maxChangesPerRun
  • safety.excludeIfSummaryMatches[]
  • safety.excludeIfDescriptionPrefix[]
  • gog.listEventsCmd|createEventCmd|updateEventCmd|deleteEventCmd (optional template overrides)
  • gog.allowCustomCommands (must be true to enable any gog.*Cmd override)
  • Custom Command Template Safety

    When custom commands are enabled:

  • Only gog command templates are accepted.
  • Templates are rendered by replacing placeholders like {account} and {calendarId}.
  • Rendered commands are executed as argv tokens (no shell interpolation).
  • Keep gog.allowCustomCommands=false unless you fully trust and audit the config file.
  • Metadata Encoding

    Store source linkage in hold description as:

  • SYNCV1:
  • JSON fields:

  • srcAccount
  • srcCalendar
  • eventId
  • start
  • end
  • title
  • Behavior

    For each mapping:

    1. Read source events in the active window. 2. Build desired hold events (private, busy, no reminders). 3. Detect existing managed holds by SYNCV1: prefix. 4. Reconcile idempotently:

  • Create missing holds.
  • Update drifted holds.
  • Delete stale holds.
  • 5. If overlap policy is skip, do not create a hold when a non-managed target event overlaps. 6. Enforce maxChangesPerRun. 7. Respect dryRun.

    Backfill

    Backfill mode upgrades legacy hold events (matching expected hold signature but lacking SYNCV1) by attaching encoded metadata when a unique source match exists.

    Command Surface

  • hold-sync validate-config
  • hold-sync reconcile --mapping |--all [--dry-run]
  • hold-sync backfill --mapping |--all [--dry-run]
  • hold-sync status --mapping |--all
  • hold-sync install-cron --mapping |--all
  • hold-sync watch --mapping |--all [--dry-run] [--interval-seconds ]
  • Watch Cadence

    Require watch cadence to be configurable from user config:

  • scheduling.watchIntervalSeconds controls watch poll frequency.
  • mappings[].lookaheadDays controls rolling watch/reconcile window.
  • Recommend baseline values:

  • watchIntervalSeconds: 900 (15 minutes)
  • lookaheadDays: 1 (24 hours)
  • Working Model

  • Use polling-based watch mode (hold-sync watch) for fast updates.
  • Expect update latency approximately equal to watchIntervalSeconds.
  • Treat this as self-hosted/operator-run automation.
  • Known Limits

  • Do not assume webhook/push subscriptions are present; current fast sync path is polling.
  • Keep periodic scheduled reconcile as fallback even when watch mode is enabled.
  • Required Tests

  • metadata encode/decode round-trip
  • overlap detection correctness
  • idempotent reconcile upsert/delete behavior
  • Attribution: gog setup flow adapted from:

  • https://clawhub.ai/steipete/gog
  • https://github.com/steipete/gogcli
  • https://gogcli.sh/
  • Provider Notes (openclaw)

    Use this variant when publishing to ClawHub/OpenClaw.

  • Keep instructions implementation-focused and command-oriented.
  • Keep dependency explicit: gog must be preconfigured by user.
  • Prefer deterministic script execution over speculative edits.
  • Avoid provider-specific APIs; treat the CLI as the boundary.