# tock **The fast terminal calendar. Written in Rust.** ![Rust](https://img.shields.io/badge/language-Rust-f74c00) ![License](https://img.shields.io/badge/license-Unlicense-green) ![Platform](https://img.shields.io/badge/platform-Linux%20%7C%20macOS-blue) ![Stay Amazing](https://img.shields.io/badge/Stay-Amazing-important) Terminal calendar with week view, event management, astronomy, and weather. Built on [Crust](https://github.com/isene/crust). Feature clone of [Timely](https://github.com/isene/Timely) rewritten in Rust for speed and single-binary distribution. ![Tock screenshot](img/screenshot.png) ## Features - **5-pane TUI**: info bar, mini-month strip, week view grid, event details, status bar - **Week view**: 7-column layout with half-hour time slots, all-day event rows, weather per day; events that overlap sit side by side in lanes - **Mini-month calendars**: horizontal strip with event indicators, week numbers, today highlight - **Calendar sources**: Google Calendar (OAuth2), Outlook/365 (device auth), CalDAV (iCloud, Fastmail, Nextcloud, Radicale), local events - **ICS import**: parse and import .ics files with RRULE expansion for recurring events - **Background sync**: automatic polling with configurable intervals - **Ephemeris engine**: full planetary position calculator ported from [ruby-ephemeris](https://github.com/isene/ephemeris) - Moon phase with emoji symbols, illumination percentage - Moon rise/set times - Sunrise/sunset times - Visible planets (Mercury, Venus, Mars, Jupiter, Saturn) with rise/set - Solstices, equinoxes, 11 meteor shower peaks - **Weather**: 7-day forecast from Met.no (free, no API key) - **Desktop notifications**: configurable alarms via notify-send - **Event management**: create, edit, delete, accept invites (RSVP) - **Preferences**: 15 configurable settings with inline color picker (256-color grid) - **Calendar manager**: enable/disable calendars, change colors, remove - **Kastrup integration**: reply to events via Kastrup (r key), jump to Kastrup (Z key) - **Database**: [ferrite](https://github.com/isene/ferrite) in ~/.tock/tock.ferrite/, or SQLite with `database: sqlite` in the config ## Install Download the prebuilt binary from [Releases](https://github.com/isene/tock/releases), or build from source: ```bash cargo build --release cp target/release/tock ~/.local/bin/ ``` ## Key Bindings | Key | Action | |-----|--------| | d/RIGHT, D/LEFT | Next/prev day | | w/W | Next/prev week | | m/M | Next/prev month | | y/Y | Next/prev year | | UP/DOWN | Navigate time slots | | PgUp/PgDn | Jump 10 slots | | HOME/END | Top/bottom of day | | j/k | Cycle events on day | | e/E | Jump to next/prev event | | t | Go to today | | g | Go to date | | n | New event | | Enter | Edit event | | x/DEL | Delete event | | v | View event details | | a | Accept invite (RSVP) | | Ctrl+Y | Copy event to clipboard | | Ctrl+A | A Claude session about the screen and the seven days from the selected one (`claude` on the PATH); `/exit` comes back | | i | Import ICS file | | G | Setup Google Calendar | | K | Setup CalDAV (iCloud, Fastmail, Nextcloud, …) | | O | Sign in to Outlook/365: opens the sign-in page in your browser with the code on the clipboard | | S | Manual sync | | C | Calendar manager | | P | Preferences | | Ctrl+R | Clear caches | | Ctrl+L | Redraw | | ? | Help | | q | Quit | ## Configuration Config file: `~/.tock/config.yml` Settings include location (for astronomy/weather), work hours, calendar colors, sync intervals, and notification preferences. tock keeps its calendars in [ferrite](https://github.com/isene/ferrite), the Fe₂O₃ database that keeps its tables in memory. Every commit is forced to the disk before it returns. Coming from a tock that used SQLite? The first start copies everything out of `tock.db` into `~/.tock/tock.ferrite/` and leaves the SQLite file as it was. `database: sqlite` in the config takes you back to the data as of that copy. ## Google Calendar Google wants an OAuth client of your own, made once in Google Cloud Console: 1. Make a project, enable the Google Calendar API, and fill in the OAuth consent screen. While it is in "Testing", add yourself as a test user. 2. Under Credentials, create an OAuth client ID of the type **Desktop app** and download its JSON file. Then press `G` in tock and give your Google email. tock offers the newest `client_secret_*.json` in your download folder; Enter takes it, and a copy goes into `~/.config/tock/credentials` (set by `google.safe_dir`), readable by you alone. The browser opens on Google's sign-in. Allow tock, and the page comes back to tock on a local port; nothing is pasted. Every calendar of the account is added. The main one is on and syncs at once; `C` turns on the others. A web-type client works too. If it lists a return address on this machine (`http://localhost:8080/`, say), tock listens there. If it lists one elsewhere, tock asks you to paste the address the browser ends on, or just the code. A client still in "Testing" gets a sign-in that lapses after a week. Press `G` again with the same email: tock signs in anew and leaves the calendars as they are. Publishing the consent screen ends the weekly sign-in. ## CalDAV: iCloud, Fastmail, Nextcloud and more Press `K` and give the server, your user name and a password: | Service | Server | User name | Password | |---|---|---|---| | iCloud | `https://caldav.icloud.com` | your Apple ID | an app-specific password from account.apple.com | | Fastmail | `https://caldav.fastmail.com` | your address | an app password | | Nextcloud | `https:///remote.php/dav` | your user | your password or an app password | | Radicale | `http://:5232` | your user | your password | tock finds the account's calendars and adds every one that takes events, all on; `C` turns any off. A task list is left out. The password is kept in a file only you can read, beside the Google credentials. Events come down with the rest of the sync. tock first asks the server whether a calendar changed at all, and fetches its events only when it has, or once a day. A repeating event arrives as its dates, each its own row. Events you make or change in tock go up to the server, and so do the ones dropped into `~/.tock/incoming/`. One date of a repeating series is changed on the server, not in tock. If the password changes, press `K` again with the same server and user. Outlook needs none of this: `O` runs the whole device-code flow. A company sign-in policy can expire that sign-in after some weeks; tock then shows a red ⚠ line in the status bar and `S` says which calendar it is. Press `O` and sign in again; the calendar and its events stay as they are. ## Dependencies Runtime: SQLite (bundled) or ferrite (built in). Optional: `notify-send` (notifications), `xclip` (clipboard). ## Part of the Rust Terminal Suite See the [Fe₂O₃ suite overview](https://github.com/isene/fe2o3) and the [landing page](https://isene.org/fe2o3/) for the full list of projects. | Tool | Clones | Description | |------|--------|-------------| | [rush](https://github.com/isene/rush) | [rsh](https://github.com/isene/rsh) | Shell | | [crust](https://github.com/isene/crust) | [rcurses](https://github.com/isene/rcurses) | TUI library | | [kastrup](https://github.com/isene/kastrup) | [Heathrow](https://github.com/isene/heathrow) | Messaging hub | | [tock](https://github.com/isene/tock) | [Timely](https://github.com/isene/timely) | Calendar | | [pointer](https://github.com/isene/pointer) | [RTFM](https://github.com/isene/RTFM) | File manager | | [scroll](https://github.com/isene/scroll) | [brrowser](https://github.com/isene/brrowser) | Web browser | | [crush](https://github.com/isene/crush) | - | Rush config helper | ## License [Unlicense](https://unlicense.org/) - public domain. ## Credits Created by Geir Isene (https://isene.org) with extensive pair-programming with Claude Code.