kfa-ai/hermes-timetree-sync
Non-interactive TimeTree calendar bridge for Hermes Agent
hermes-timetree-sync is a Python-based CLI and library that enables Hermes Agents to manage TimeTree calendar events programmatically. Since TimeTree discontinued its official API, this bridge utilizes reverse-engineered web endpoints to perform non-interactive calendar actions via stored session cookies. It allows agents to list calendars, sync events, and perform batch writes for all-day events without requiring manual user intervention or browser interaction. The project includes a local YAML-based label policy for mapping natural language terms to specific calendar categories.
- Enables non-interactive calendar event creation via stored session cookies
- Supports batch writes for efficient multi-event processing
- Maps natural language terms to TimeTree labels using YAML policies
full readme from github
hermes-timetree-sync
Private TimeTree bridge for Hermes Agent calendar automation.
hermes-timetree-sync is a small Python CLI and client library that lets Hermes create and sync TimeTree calendar events without asking a chat user to open TimeTree.
TimeTree discontinued its official third-party API in December 2023. This project therefore uses TimeTree's current web endpoints through a deliberately narrow, tested client boundary. It is an internal bridge, not an official TimeTree integration; upstream web-app changes may require maintenance.
Why this exists
The target interaction is simple:
“Add Day off on May 18.”
Hermes should translate that request into a TimeTree write using locally stored credentials. No browser, TimeTree UI, cookie copying, or OAuth prompt should appear during normal chat usage.
Capabilities
| Area | Current support |
|---|---|
| Auth | Stored TimeTree web session cookie; experimental email/password exchange |
| Discovery | List calendars and labels |
| Reads | Sync calendar events through TimeTree's web sync endpoint |
| Writes | Create, update, and delete events through guarded client methods |
| Hermes UX | Non-interactive all-day event creation, including batch writes |
| Labels | Optional local YAML policy for mapping terms/categories to TimeTree labels |
| Safety | Redacted docs/tests, low-volume API usage, mocked HTTP coverage |
Installation
git clone git@github.com:kfa-ai/hermes-timetree-sync.git
cd hermes-timetree-sync
uv sync --dev
Run the local quality gates:
uv run pytest
uv run ruff check .
Configuration
Provide runtime configuration via .env or environment variables:
TIMETREE_SESSION_COOKIE=...
TIMETREE_CALENDAR_ID=...
TIMETREE_SESSION_COOKIEis the value of TimeTree's_session_idbrowser cookie. Treat it as a bearer secret.TIMETREE_CALENDAR_IDis the target TimeTree calendar ID for writes.
For local email/password TimeTree accounts, an experimental sign-in command can attempt to exchange credentials for a web session:
TIMETREE_EMAIL=you@example.com
TIMETREE_PASSWORD=...
uv run hermes-timetree-sync sign-in
Direct sign-in may fail depending on TimeTree's browser/session checks. Production Hermes usage should rely on a stored, locally refreshed session cookie. See docs/authentication.md.
CLI quickstart
Check configuration:
uv run hermes-timetree-sync doctor
List calendars:
uv run hermes-timetree-sync list-calendars
Create one all-day event:
uv run hermes-timetree-sync create-all-day --title "Day off" --date 2026-05-18
Create several all-day events with one current-user lookup:
uv run hermes-timetree-sync create-all-day-batch \
--event "2026-05-18|Day off" \
--event "2026-05-25|Public holiday"
The batch command was added in v0.1.1 for faster Hermes calendar writes. It also includes regression coverage for TimeTree accounts whose /api/v1/user ID is returned as a number rather than a string.
Hermes integration model
This package is intentionally UI-free at runtime:
- A local setup/bootstrap step stores or refreshes
TIMETREE_SESSION_COOKIEandTIMETREE_CALENDAR_IDoutside chat. - Hermes parses a natural-language calendar request into structured event data.
- Hermes calls this CLI/client directly.
- The TimeTree UI is not opened during the user request.
For multiple requested events, Hermes-facing wrappers should prefer create-all-day-batch so the current TimeTree user is fetched once and reused for all event attendees.
Label policy
Create/update helpers can set label_id from a local YAML policy instead of hard-coding calendar-specific terms in source code.
cp timetree-labels.yaml.example timetree-labels.yaml
Edit timetree-labels.yaml with the target calendar's label IDs and matching terms. The local file is ignored by git.
To use a different policy file:
export TIMETREE_LABEL_POLICY_FILE=/path/to/timetree-labels.yaml
Security
Never commit or paste into chat:
- TimeTree passwords;
_session_id/_timetree_sessioncookies;- raw private calendar payloads;
- Google OAuth tokens or other downstream calendar credentials.
Local .env files are for development/runtime configuration only. Keep examples, docs, tests, logs, and issue comments sanitized.
Documentation
docs/authentication.md— session-cookie, sign-in, and non-interactive runtime guidance.docs/reverse-engineered-api.md— observed TimeTree web endpoints and payload notes.docs/roadmap.md— likely next steps and maintenance considerations.CHANGELOG.md— release history.
Development notes
When adding endpoint coverage:
- keep TimeTree-specific behavior behind
TimeTreeClientor narrow CLI helpers; - prefer mocked HTTP tests over live credentials;
- redact
_session_id, passwords, cookies, and raw private calendar data; - run
uv run pytestanduv run ruff check .before publishing changes.
License
Private/internal project unless a license is added later.