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.
- Shared API mapping
calendars,eventsanditemsto 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 agendaview highlighting days that carry a VEVENT - HTTP auth support: basic, bearer
- TLS support:
- Rustls with ring crypto
- Rustls with aws crypto (requires
rustls-awsfeature) - Native TLS (requires
native-tlsfeature)
- Discovery support:
- TOML configuration with multi-account support
- Interactive wizard on first run
- JSON output via
--json
As root:
curl -sSL https://raw.githubusercontent.com/pimalaya/calendula/master/install.sh | sudo shAs a regular user:
curl -sSL https://raw.githubusercontent.com/pimalaya/calendula/master/install.sh | PREFIX=~/.local shThese 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 install --locked --git https://github.com/pimalaya/calendula.gitWith only vdir support:
cargo install --locked --git https://github.com/pimalaya/calendula.git \
--no-default-features \
--features vdir,rustls-ringIf you have the Flakes feature enabled:
nix profile install github:pimalaya/calendulaOr run without installing:
nix run github:pimalaya/calendulagit clone https://github.com/pimalaya/calendula
cd calendula
nix runThe 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 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 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"Not supported yet: Microsoft offers no CalDAV for calendars, only the Graph API. Native Graph support is planned.
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.
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.
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"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).
This project is licensed under either of:
at your option.
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
- Chat on Matrix
- News on Mastodon or RSS
- Mail at pimalaya.org@posteo.net
Special thanks to the NLnet foundation and the European Commission that have been financially supporting the project for years:
- 2022 → 2023: NGI Assure
- 2023 → 2024: NGI Zero Entrust
- 2024 → 2026: NGI Zero Core
- 2027 in preparation…
If you appreciate the project, feel free to donate using one of the following providers:
