Skip to content

semos-labs/aion

Repository files navigation

Aion

Aion

Terminal calendar client with vim-style keybindings
Google Calendar & CalDAV. Beautiful. Fast. Keyboard-driven.

Aion App

Quick StartKeybindingsCommandsConfiguration

Latest Release Downloads Bun MIT License Built with Glyph


Table of Contents


Why Aion?

Most calendar apps are mouse-driven, slow, and cluttered. Aion takes a different approach:

Vim-style navigation. Terminal-native. Zero distractions.

Comparison

Feature Aion calcurse khal gcalcli calcure
TUI (visual interface)
Google Calendar sync ✅ Native 🔧 vdirsyncer ✅ Native
CalDAV support ✅ Native 🔧 vdirsyncer
Multi-account 🔧
Vim keybindings Partial Partial
Multi-day view ✅ 1/3/5 cols
Free/busy scheduling
Google Meet generation
Natural language input
Event search
Recurring events
Timezone support
Theming ✅ TOML
Offline mode ✅ SQLite
Dependencies None ncurses Python Python Python

🔧 = Requires additional setup/tools

TL;DR: Aion is the only terminal calendar with native Google Calendar sync, CalDAV support, multi-account support, Meet link generation, free/busy scheduling, and a proper visual TUI — all in one package.

Features

Feature Description
⌨️ Vim Keybindings Navigate with j/k, gg/G, h/l — feels like home
📅 Visual Timeline Day view with 15-minute precision and overlap handling
🔗 Google Calendar Sync Multi-account OAuth with PKCE, background sync every 30s
🗓️ CalDAV Support iCloud, Fastmail, Nextcloud, Radicale, and any CalDAV server
👥 Meet With Find free slots across multiple people's calendars
📹 Google Meet Auto-generate Meet links when creating events
📁 Multi-Calendar Toggle calendars on/off, each with its own color
🌍 Timezone Support Events display in local time, toggle to see original timezone
🎨 Themeable Customize every color via TOML configuration
💾 Local-First SQLite database, your data stays yours
🔔 Notifications Track pending invites at a glance
📝 Command Palette Quick access to all actions with fuzzy search
🔍 Event Search Find events by title or description with /
🗓️ Natural Language Dates Type "tomorrow 3pm" or "next friday for 2 hours"
🔁 Recurring Events Create and edit events with daily/weekly/monthly/yearly recurrence
❓ Context Help Press ? anywhere to see available keybindings
🚀 Fast Built with Bun and React — instant startup

Quick Start

Option 1: Homebrew (macOS/Linux)

brew tap semos-labs/tap
brew install aion

Option 2: Download Binary

Download the latest release for your platform from the Releases page:

Platform Binary
macOS (Apple Silicon) aion-darwin-arm64
macOS (Intel) aion-darwin-x64
Linux (x64) aion-linux-x64
Linux (ARM64) aion-linux-arm64
# Make executable (macOS/Linux)
chmod +x aion-darwin-arm64

# Move to PATH
sudo mv aion-darwin-arm64 /usr/local/bin/aion

# Run
aion

Option 3: Build from Source

git clone https://github.com/semos-labs/aion.git
cd aion
bun install

# Run in development
bun dev

# Build binary for current platform
bun run build

# Binary will be at ./dist/aion

2. Connect a Calendar

Aion supports Google Calendar and CalDAV (iCloud, Fastmail, Nextcloud, Radicale, etc.). You can use both at the same time with multiple accounts.

Option A: Google Calendar

Set up Google Cloud credentials

Aion requires your own Google Cloud credentials to access Google Calendar:

  1. Go to Google Cloud Console
  2. Create a new project (or select an existing one)
  3. Enable the Google Calendar API:
    • Go to "APIs & Services" → "Library"
    • Search for "Google Calendar API"
    • Click "Enable"
  4. Go to "APIs & Services" → "Credentials"
  5. Click "Create Credentials" → "OAuth client ID"
  6. If prompted, configure the OAuth consent screen:
    • User Type: External (or Internal for Workspace)
    • Add your email as a test user
    • Add the following scopes:
      • https://www.googleapis.com/auth/calendar.events (read/write events)
      • https://www.googleapis.com/auth/calendar.readonly (read calendars list)
      • https://www.googleapis.com/auth/userinfo.email (get user email)
      • https://www.googleapis.com/auth/userinfo.profile (get user name/picture)
  7. Create OAuth client ID:
    • Application type: Desktop app
    • Name: "Aion" (or anything you like)
  8. Copy the Client ID and Client Secret

Add your credentials to ~/.config/aion/config.toml:

[google]
clientId = "your-client-id.apps.googleusercontent.com"
clientSecret = "your-client-secret"

Or use environment variables:

export AION_GOOGLE_CLIENT_ID="your-client-id.apps.googleusercontent.com"
export AION_GOOGLE_CLIENT_SECRET="your-client-secret"

Then connect your account:

:login

Follow the OAuth flow in your browser. Aion supports multiple Google accounts.

Option B: CalDAV

Add your CalDAV account to ~/.config/aion/config.toml:

[[caldav]]
name = "iCloud"
email = "me@icloud.com"
serverUrl = "https://caldav.icloud.com"
username = "me@icloud.com"
password_command = "security find-generic-password -a me@icloud.com -s aion-caldav -w"

Or use the interactive dialog:

:caldav

See CalDAV configuration for more details and provider-specific URLs.

3. Run

bun dev

4. Navigate

Use j/k to move through events, h/l to switch panes, Enter to view details.


Keybindings

Navigation

Key Action
j / Move down / Next item
k / Move up / Previous item
h / Previous day / column
l / Next day / column
Tab Cycle focus between panes
` Cycle focus (Calendars → Days → Timeline)
gg Jump to first item
G Jump to last item
n Jump to now (timeline only)
Ctrl+G Go to date (natural language)

Events

Key Action
Enter / Space Open event details
e Edit event
D Delete event
Ctrl+N Create new event
Ctrl+M Meet with... (find free slots)

Event Details

Key Action
y Accept invitation
n Decline invitation
m Maybe / Tentative
o Open meeting link (Meet, Zoom, Teams, etc.)
e Edit event
D Delete event
t Toggle timezone (local ↔ original)

Calendars & Accounts

Key Action
Shift+C Toggle calendars sidebar
A Toggle all-day events section

View

Key Action
3 Toggle between 1 and 3 column view
` Cycle focus (Calendars → Days → Timeline)

General

Key Action
/ Search events
: Open command palette
? Show help (context-aware)
N Open notifications
Esc Close overlay / Go back
q Quit

Commands

Open the command palette with : and type a command:

Event Management

Command Action
new Create new event
new <title> Create event with title
edit Edit selected event
delete Delete selected event

Navigation

Command Action
goto <date> Jump to date (e.g., goto tomorrow, goto march 15)
now Jump to current time
today Jump to today

Accounts & Sync

Command Action
login Add Google account (OAuth)
caldav Add CalDAV account
logout Remove all accounts
sync Force sync all calendars
accounts Manage connected accounts
calendars Toggle calendars sidebar

Scheduling

Command Action
meet Find free slots with other people

Search

Command Action
search Search events by title/description

View

Command Action
columns <n> Set column count (1, 3, or 5)

General

Command Action
help Show keybindings
notifications Open notifications panel
quit Exit application

Navigate with / or Ctrl+P/Ctrl+N, auto-fill with Ctrl+Y, select with Enter.


Natural Language Dates

When creating or editing events, you can use natural language for dates and times:

Input Result
tomorrow 3pm Tomorrow at 3:00 PM
next friday at 10am Next Friday at 10:00 AM
in 2 hours 2 hours from now
today at 5pm for 30 minutes Today 5:00-5:30 PM
from march 5 for 2 weeks All-day event, March 5-19
between march 6 and 12 All-day event, March 6-12

Configuration

Create ~/.config/aion/config.toml to customize Aion.

Google Calendar

[google]
clientId = "your-client-id.apps.googleusercontent.com"
clientSecret = "your-client-secret"

CalDAV

Add one or more CalDAV accounts using [[caldav]] array syntax. Each account must have either password or passwordCommand (command takes precedence).

# iCloud
[[caldav]]
name = "iCloud"
email = "me@icloud.com"
serverUrl = "https://caldav.icloud.com"
username = "me@icloud.com"
passwordCommand = "security find-generic-password -a me@icloud.com -s aion-caldav -w"

# Fastmail
[[caldav]]
name = "Work"
email = "me@fastmail.com"
serverUrl = "https://caldav.fastmail.com/dav/calendars"
username = "me@fastmail.com"
passwordCommand = "pass show calendar/fastmail"

# Nextcloud (with plain password)
[[caldav]]
name = "Nextcloud"
email = "me@example.com"
serverUrl = "https://cloud.example.com/remote.php/dav"
username = "me"
password = "app-password-here"

Provider URLs

Provider Server URL
iCloud https://caldav.icloud.com
Fastmail https://caldav.fastmail.com/dav/calendars
Nextcloud https://your-server.com/remote.php/dav
Radicale https://your-server.com/radicale
Google (via CalDAV) https://apidata.googleusercontent.com/caldav/v2

Tip: For iCloud, use an app-specific password — not your Apple ID password.

Password commands

passwordCommand runs via sh -c and uses the trimmed stdout as the password. Examples:

# macOS Keychain
passwordCommand = "security find-generic-password -a me@icloud.com -s aion-caldav -w"

# pass (GPG)
passwordCommand = "pass show calendar/icloud"

# 1Password CLI
passwordCommand = "op read op://Personal/iCloud/password"

# Bitwarden CLI
passwordCommand = "bw get password icloud-caldav"

# Environment variable
passwordCommand = "echo $CALDAV_PASSWORD"

Theme

[theme]
# Accent colors
[theme.accent]
primary = "cyan"
secondary = "blue"
success = "green"
warning = "yellow"
error = "red"

# Text colors
[theme.text]
primary = "white"
secondary = "gray"
dim = "darkGray"

# Selection highlight
[theme.selection]
background = "blue"
text = "white"
indicator = "cyan"

# Event type colors
[theme.eventType]
default = "cyan"
focusTime = "blue"
outOfOffice = "magenta"
birthday = "yellow"

# Attendance status colors
[theme.status]
accepted = "green"
declined = "red"
tentative = "yellow"

# UI elements
[theme.modal]
background = "black"

[theme.input]
background = "black"

[theme.statusBar]
background = "black"

Data Storage

Aion supports two directory layouts:

Legacy Layout (~/.aion/)

If ~/.aion/ exists, Aion uses it for backward compatibility. All files are stored in this single directory.

XDG Layout (new installations)

New installations follow the XDG Base Directory Specification:

Configuration (~/.config/aion/):

File Description
config.toml User configuration (Google credentials, CalDAV accounts, theme)
contacts.json Optional manual contacts for name lookup

Data (~/.local/share/aion/):

File Description
aion.db SQLite database with all events
accounts.json OAuth tokens and account info
calendar-settings.json Calendar visibility preferences
account-settings.json Custom account names
sync-tokens.json Incremental sync tokens
logs/ Application logs (daily rotation)

You can override XDG paths with environment variables:

  • XDG_CONFIG_HOME (default: ~/.config)
  • XDG_DATA_HOME (default: ~/.local/share)

Tech Stack

Component Technology
Runtime Bun
UI Framework Glyph (React for terminals)
State Management Jotai
Database SQLite via Drizzle ORM
Date/Time Luxon
NLP Dates chrono-node
CalDAV tsdav + ical.js
Validation Zod

Roadmap

✅ Completed

  • Google Calendar sync (OAuth with PKCE)
  • Multi-account support
  • Multiple calendars per account
  • Calendar toggle sidebar
  • Meet With (free/busy scheduling)
  • Google Meet link generation
  • Natural language date input
  • Timezone handling
  • Background sync (30s interval)
  • Accounts management dialog
  • Recurring event creation/editing
  • Search events by title/description
  • Multi-column day view (1, 3, or 5 columns)
  • Column navigation with h/l arrows
  • Persistent view settings
  • Command auto-fill (Ctrl+Y)
  • Built-in credentials for distributed binaries
  • Homebrew distribution
  • XDG Base Directory support
  • CalDAV support (iCloud, Fastmail, Nextcloud, Radicale, etc.)
  • password_command for secure credential storage

🚧 In Progress

  • Month view

📋 Planned

  • Import/export (ICS)
  • Offline mode improvements
  • Custom notifications/reminders
  • Agenda view (list of upcoming events)
  • Event templates

License

MIT © 2025


Built with ⌨️ for terminal lovers

Packages

 
 
 

Contributors