Skip to content

pimalaya/calendula

Repository files navigation

📅 Calendula crates.io Matrix Mastodon

CLI to manage calendars.

Important

This README documents Calendula v0.2.0. If you are running v0.1.0, refer to the v0.1.0 README. The MIGRATION.md guide walks v0.1 users through the breaking changes.

Table of contents

Features

  • Shared API mapping calendars, events and items to the active backend
  • Protocol-specific APIs exposing each backend's full surface (calendula vdir/caldav)
  • Remote backend: CalDAV (RFC 4791)
  • Local (filesystem) backend: vdir specs
  • ncal-style event agenda view highlighting days that carry a VEVENT
  • HTTP auth support: basic, bearer
  • TLS support:
    • Rustls with ring crypto
    • Rustls with aws crypto (requires rustls-aws feature)
    • Native TLS (requires native-tls feature)
  • Discovery support:
  • TOML configuration with multi-account support
  • Interactive wizard on first run
  • JSON output via --json

Installation

Pre-built binary

As root:

curl -sSL https://raw.githubusercontent.com/pimalaya/calendula/master/install.sh | sudo sh

As a regular user:

curl -sSL https://raw.githubusercontent.com/pimalaya/calendula/master/install.sh | PREFIX=~/.local sh

These commands install the latest binary from the GitHub releases section.

For a more up-to-date version than the latest release, check out the releases GitHub workflow and look for the Artifacts section. These pre-built binaries are built from the master branch.

Note

Such binaries are built with the default cargo features. If you need specific features, please use another installation method.

Cargo

cargo install --locked --git https://github.com/pimalaya/calendula.git

With only vdir support:

cargo install --locked --git https://github.com/pimalaya/calendula.git \
  --no-default-features \
  --features vdir,rustls-ring

Nix

If you have the Flakes feature enabled:

nix profile install github:pimalaya/calendula

Or run without installing:

nix run github:pimalaya/calendula

Sources

git clone https://github.com/pimalaya/calendula
cd calendula
nix run

Configuration

The configuration is loaded from the first existing path among:

  • $XDG_CONFIG_HOME/calendula/config.toml
  • $HOME/.config/calendula/config.toml
  • $HOME/.calendularc

Override with calendula -c <PATH>. Multiple paths can be passed at once, separated by :; the first is the base and the rest are deep-merged on top.

Run calendula once with no config file to launch the wizard. The wizard prompts for an account name, lets you pick a backend, then walks you through the vdir or CalDAV setup (CalDAV also asks for an email and tests the connection before saving). To edit (or add) an account later, use calendula account configure --account <name>.

A documented sample lives at config.sample.toml.

Apple

Apple exposes calendars via CalDAV, but you cannot use your regular password. You need to generate an app-specific password (required once two-factor authentication is on):

[accounts.example]
caldav.discover = "icloud.com"
caldav.server = "https://caldav.icloud.com/"
# The home URL is usually of this shape:
#caldav.home = "https://caldav.icloud.com/<id>/calendars/"

caldav.auth.basic.username = "example@icloud.com"
caldav.auth.basic.password.raw = "***"

calendar.default = "home"

Google

Google exposes calendars via CalDAV, but only behind OAuth 2.0. Once set up, you can use any tool to manage token refreshing (for example using Ortie).

Google's CalDAV layout is non-standard: each calendar lives at https://apidata.googleusercontent.com/caldav/v2/<CALENDAR-ID>/events, and it does not enumerate the home-set the way caldav discover expects. So set caldav.home to the base URL and make the calendar id the <CALENDAR-ID>/events segment. <CALENDAR-ID> is your email for the primary calendar, or the ...@group.calendar.google.com value from Google Calendar's Settings and sharing > Integrate calendar > Calendar ID for secondary ones.

[accounts.example]
caldav.home = "https://apidata.googleusercontent.com/caldav/v2"
caldav.auth.bearer.token.command = ["ortie", "token", "show"]

# Primary calendar: "<your-email>/events".
calendar.default = "example@gmail.com/events"

Microsoft

Not supported yet: Microsoft offers no CalDAV for calendars, only the Graph API. Native Graph support is planned.

Proton

Not supported: Proton exposes no calendar API, neither CalDAV nor through Proton Bridge (which proxies mail only). Calendars are reachable only from Proton's own web and mobile apps.

Fastmail

Standard CalDAV with the mailbox address and its app password. If caldav.discover / caldav.server return a 404, point caldav.home straight at the calendar home-set to skip the discovery walk:

[accounts.example]
caldav.home = "https://caldav.fastmail.com/dav/calendars/user/example@fastmail.com/"
caldav.auth.basic.username = "example@fastmail.com"
caldav.auth.basic.password.raw = "***"

Run calendula calendar list once connected to read the calendar ids (the ID column), then set calendar.default to the one you want.

Posteo

Standard CalDAV with the mailbox address and its password.

[accounts.posteo]
caldav.discover = "posteo.de"
caldav.server = "https://posteo.de:8443/"
# The home URL is usually of this shape:
#caldav.home = "https://posteo.de:8443/calendars/<username>/"

caldav.auth.basic.username = "example@posteo.net"
caldav.auth.basic.password.raw = "***"

calendar.default = "default"

Usage

Run calendula --help for the full command tree, and calendula <command> --help for any subcommand's arguments and its JSON output shape (printed when the global --json flag is set).

License

This project is licensed under either of:

at your option.

AI disclosure

This project is developed with AI assistance. This section documents how, so users and downstream packagers can make informed decisions.

  • Tools: Claude Code (Anthropic), Opus 4.8, invoked locally with a persistent project-scoped memory and a small set of repo-specific rules.
  • Used for: Refactors, mechanical multi-file edits, boilerplate (feature gates, error enums, derive macros, trait impls), test scaffolding, doc polish, exploratory design conversations.
  • Not used for: Engineering, critical code, git manipulation (commit, merge, rebase…), real-world tests.
  • Verification: Every AI-assisted change is read, compiled, tested, and formatted before commit (nix develop --command cargo check / cargo test / cargo fmt). Behavioural correctness is verified against the relevant RFC or upstream spec, not assumed from the model output. Tests are never adjusted to fit AI-generated code; the code is adjusted to fit correct behaviour.
  • Limitations: AI models occasionally produce code that compiles and passes tests but is subtly wrong: off-by-one errors, missed edge cases, plausible but nonexistent APIs, stale RFC references. The verification workflow catches most of this; it does not catch all of it. Bug reports are welcome and taken seriously.
  • Last reviewed: 16/06/2026

Social

Sponsoring

nlnet

Special thanks to the NLnet foundation and the European Commission that have been financially supporting the project for years:

If you appreciate the project, feel free to donate using one of the following providers:

GitHub Ko-fi Buy Me a Coffee Liberapay thanks.dev PayPal

About

CLI to manage calendars

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Contributing

Security policy

Stars

Watchers

Forks

Contributors