zyx1121/today-mod
today-mod
`/today` for Claude Code: your calendar, E3 deadlines and Reminders in one line above the prompt, and in Claude's context, so it knows your day before you say a word.
About this mod
A Claude Code mod plugin whose behaviour lives in a TypeScript hooks module. It reads macOS Calendar and Reminders plus NYCU E3 deadlines through child-process scripts, renders a one-line band above the prompt with a countdown to the next event, and adds the agenda as a Markdown context block. Commands: /today, /today on, /today off.
Installation
Check the author's README for the marketplace and plugin name first. Commands may change as the repository evolves.
claude plugin marketplace add zyx1121/today-mod claude plugin install today-mod
Original text / README
today-mod
/todayfor Claude Code: your calendar, E3 deadlines and Reminders in one line above the prompt, and in Claude's context, so it knows your day before you say a word.
claude-code · mod · function-hooks · macos · nycu · agenda
📅 13:20 3D遊戲程式 · ED102 · in 3h 20m 📝 1 due (1 within 3d) ☑ 1 overdue
<sub>The band directly above the prompt: the running or next event with a countdown, deadlines ahead, reminders due. It ticks every minute and re-reads every five, one read shared by every open session.</sub>
Sessions start with "what was I supposed to do today?" and end with a missed class. This mod reads the day once at start, keeps the next thing in view, and hands the whole agenda to Claude as a context block, so "do I have time for this before class?" gets a real answer.
It is a Claude Code mod: a plugin whose behaviour lives in a TypeScript hooks module. The data comes from macos and nycu scripts run as child processes (calendar.py, reminders.py, e3p.py), nothing else.
Install
Function hooks are early access, so the engine loads a mod only with the flag on. Put it in your shell profile or in settings.json under env:
export CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1
Then install it as a plugin, from GitHub or from a local clone:
/plugin marketplace add zyx1121/today-mod
/plugin install today-mod@today-mod
It needs macos@zyx1121 and nycu@zyx1121 installed at user scope (or explicit macosScriptsDir and nycuScriptsDir settings), uv at /opt/homebrew/bin/uv, Full Access to Calendars and Reminders for your terminal (System Settings > Privacy & Security; macos reads both through EventKit, so neither app opens), and an E3 login configured through nycu for deadlines. A source that is missing or denied is reported on the line and in /today; the others still show.
In the session:
/today the whole agenda as Markdown
/today off hide the line (remembered)
/today on show it again
What it shows
| Part | Content |
|------|---------|
| 📅 | The event running now (now) or the next to start today with a countdown (in 1h 12m); no more events today; nothing on the calendar today |
| 📝 | E3 deadlines within dueDays, and how many fall within 3 days |
| ☑ | Reminders overdue, and due later today |
| ⚠️ | How many sources failed; /today names them |
The today context block carries the same agenda as Markdown: today's events with times and rooms, E3 deadlines with due times and course, open reminders. It is added to the conversation's first message, after the engine's own blocks.
Configuration
| Field | Type | Default | What it does |
|-------|------|---------|--------------|
| macosScriptsDir | string | current macos@zyx1121 user installation | Optional directory for calendar.py and reminders.py |
| nycuScriptsDir | string | current nycu@zyx1121 user installation | Optional directory for e3p.py |
| scriptsDir | string | empty | Legacy explicit shared directory; separate overrides take precedence |
| refreshMs | number | 300000 | Milliseconds between re-reads. Every open session shares one read per interval. Floored at 60000. |
| dueDays | number | 7 | Days ahead to list E3 deadlines |
| remindersList | string | TODO | The Reminders list to read |
| showOnStart | boolean | true | Show the line as soon as an interactive session starts. /today on|off, once used, wins. |
How it is built
hooks/register.tsexportsregister(on, options). Onsession.startit registers/today, reads the three sources in parallel and starts two timers: a re-read everyrefreshMs, a redraw every minute for the countdown.command.runanswers/today.ui.renderonAbovePromptdraws the line.prompt.contextadds thetodayblock, waiting up to 8 seconds for a first read still in flight.hooks/shared-read.tsis the reading every session shares: a JSON file at$TMPDIR/today-mod/agenda.json, keyed by the three scripts' argv so another day never matches. A session takes the reading there when it is younger thanrefreshMs; while another session's read is under way it waits for that one (up to 35 seconds) instead of walking Calendar again./todayanswers from a shared reading under a minute old, else reads the sources itself.hooks/agenda.tsbuilds each script's argv, parses the JSON envelope (success and failure alike), and turns the scripts' AppleScript-form dates (Monday, September 21, 2026 at 1:20:00 PM) into local Dates. Only an event's time of day is used: the calendar argv covers one day, and utils before 0.24.1 gave a recurring event its series' first date.hooks/views/text.tsformats the line and the Markdown;hooks/views/band-view.tsxdraws the line withBoxandText.types/claude-code.d.tsis the engine contract, copied fromanthropics/claude-code/mods/types.
bunx -p typescript tsc -p tsconfig.json # typecheck
CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1 claude plugin test . # 24 tests, the engine's own harness
Contributing
Issues and PRs are welcome. Ground rules live in CONTRIBUTING.md.
License
MIT · the class is at 13:20, you have time
