Belfry
Apple Calendar and Reminders integration for Claude Code — a Swift EventKit CLI with slash commands, proactive scheduling, and session-start context injection.
Problem
Claude Code has no awareness of your calendar or reminders. It can't tell you what meetings are coming up, schedule a reminder for a deadline, or factor your availability into planning. Every time you want that context, you have to leave the terminal, check your calendar, and relay the information manually.
The missing piece isn't intelligence — it's access. macOS already has a robust calendar and reminders system through EventKit. The challenge was bridging that native capability into Claude Code's plugin model in a way that felt like a natural extension of the conversation rather than a clunky integration.
How It Works
The Swift CLI
Belfry is a single-file Swift CLI — 651 lines, compiled from source with no external dependencies. It talks directly to Apple's EventKit framework to read and write calendar events and reminders. Every subcommand accepts structured arguments and returns JSON to stdout, with errors as JSON to stderr.
The design constraint was deliberate: one file, no package manager, no build system beyond swiftc. The binary compiles in under two seconds and ships as part of the plugin. If the binary is missing at session start, it auto-compiles from source — zero manual setup.
Nine subcommands cover the full surface: cal-list, cal-create, cal-edit, cal-delete, cal-free for calendar operations, and remind-list, remind-create, remind-complete, remind-delete for reminders.
The Plugin Layer
The Swift CLI is the engine. The plugin layer — slash commands, a proactive skill, and a session-start hook — is what makes it usable inside Claude Code.
Each slash command maps to a CLI subcommand with argument parsing handled in the command's markdown definition. The skill is where the real integration lives: it's proactive, meaning Claude invokes it automatically when the conversation touches scheduling, time management, or daily planning. When you say "remind me to push that repo tomorrow," the skill fires without being asked.
The session-start hook injects today's calendar and pending reminders into the conversation context. Every session opens with Claude already knowing what's on your schedule — no "check my calendar" required.
Morning Briefings
Belfry's most visible feature is the morning briefing system. At session start, if the time falls within the briefing window, Claude reads your calendar, pulls pending reminders, checks project tracker state, and presents a structured summary: what's due today, what's on the calendar, which projects need attention, and a suggested focus for the session.
This replaced a manual REMINDERS.md file that had to be maintained by hand. The reminders now live in Apple Reminders — editable from any Apple device, synced via iCloud, surfaced automatically in Claude Code.
What I Learned
The hardest part wasn't the EventKit integration — Apple's framework is well-documented and the API is straightforward. The hard part was the session-start hook.
Claude Code hooks run shell scripts that return context as stdout. But the hook needs to call a Swift binary that requests EventKit permissions, which requires a TCC (Transparency, Consent, and Control) grant from macOS. The first time Belfry runs, macOS prompts for calendar and reminder access. If that prompt happens inside a hook — which runs non-interactively — the permission dialog may not surface correctly. The solution was to trigger the permission request during the build step, before the hook ever fires, so the grant is already in place by the time the session starts.
The JSON-everywhere constraint turned out to be a significant design advantage. Every subcommand returns structured data that Claude can parse without ambiguity. No regex over human-readable output, no fragile string matching. When cal-list returns an array of event objects with ISO timestamps, Claude can reason about time conflicts, duration, and gaps programmatically. The structured output is what makes the proactive skill reliable — it's working with data, not prose.
Building a single-file CLI also forced an interesting discipline. With no module system, no dependency injection, no abstractions — just functions and a switch statement — every decision about code organization had to earn its place through clarity alone. The result is a file that any developer can read top to bottom in fifteen minutes and understand completely. That's a feature, not a limitation.
Outcome
v0.3.0, 12 commits, open source under MIT. Published to the alexshaddy-plugins marketplace. The plugin demonstrates native macOS system integration via Swift, Claude Code plugin architecture, and the design thinking required to make an AI assistant feel like it lives inside your operating system rather than beside it.
View Belfry on GitHub