calendar
Calendar operations with CalDAV
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Menú
Calendar operations with CalDAV
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Git repository management, GitLab merge requests, and GitHub pull requests
Location tracking, place recognition, visit history, and calendar attendance
Persistent memory writes — USER.md (behavioral) and the knowledge graph (facts).
Accounting operations (ledger, invoicing, transactions, work log, investment portfolio) — runs in-process via the vendored money package
Send a push notification to the user's configured ntfy device(s). One-way (bot to phone), no reply channel.
Briefing formatting guidelines for chat messages
Basado en la clasificación ocupacional SOC
| name | calendar |
| triggers | ["calendar","cal","event","meeting","schedule","appointment","caldav"] |
| description | Calendar operations with CalDAV |
| cli | true |
| source_types | ["briefing"] |
| companion_skills | ["untrusted_input"] |
| dependencies | ["caldav","icalendar"] |
| env | [{"var":"CALDAV_URL","from":"config","config_path":"caldav_url","when":"caldav_url","gate_has_discovered_calendars":true},{"var":"CALDAV_USERNAME","from":"config","config_path":"caldav_username","when":"caldav_url","gate_has_discovered_calendars":true},{"var":"CALDAV_PASSWORD","from":"config","config_path":"caldav_password","when":"caldav_url","gate_has_discovered_calendars":true,"sensitive":true}] |
Calendar operations use CalDAV. Credentials are available via environment variables:
CALDAV_URL: CalDAV server URL (e.g., https://nextcloud.example.com/remote.php/dav)CALDAV_USERNAME: Username for CalDAV authenticationCALDAV_PASSWORD: Password/app token for CalDAV authenticationThe simplest way to interact with calendars is via the CLI:
# List today's events from all calendars (`agenda` is an alias for `list`)
istota-skill calendar list --tz "America/Los_Angeles"
# List tomorrow's events
istota-skill calendar list --date tomorrow --tz "America/Los_Angeles"
# List events for a specific date
istota-skill calendar list --date 2026-02-15 --tz "America/Los_Angeles"
# List from a specific calendar
istota-skill calendar list --calendar "https://..." --date today
# List events for the next 7 days
istota-skill calendar list --week --tz "America/Los_Angeles"
# Create an event (floating time — use when the time is local regardless of timezone)
istota-skill calendar create \
--calendar "https://..." \
--summary "Team Meeting" \
--start "2026-02-15 14:00" \
--end "2026-02-15 15:00" \
--location "Conference Room A"
# Create an event with explicit timezone (use for travel/flights)
istota-skill calendar create \
--calendar "https://..." \
--summary "Flight JFK→LHR" \
--start "2026-04-26 19:10" \
--end "2026-04-27 19:05" \
--tz "America/Los_Angeles" \
--description "SAS SK932"
# Update an event
istota-skill calendar update \
--calendar "https://..." \
--uid "event-uid-here" \
--summary "Updated Title" \
--start "2026-02-15 15:00" \
--end "2026-02-15 16:00"
# Update: clear optional fields
istota-skill calendar update \
--calendar "https://..." \
--uid "event-uid-here" \
--clear-location --clear-description
# Delete an event
istota-skill calendar delete --calendar "https://..." --uid "event-uid-here"
Always pass --tz with the user's timezone (from prompt metadata) to ensure correct date boundaries.
Always pass --tz when creating events with specific timezone semantics (flights, meetings across timezones). Omit --tz for local events where the wall-clock time is what matters.
Output is JSON:
{
"status": "ok",
"date": "today",
"event_count": 2,
"events": [
{
"calendar": "Work",
"uid": "abc123",
"summary": "Team Meeting",
"start": "2026-02-15T14:00:00",
"end": "2026-02-15T15:00:00",
"location": "Conference Room A",
"description": null,
"all_day": false,
"timezone": "America/Los_Angeles"
}
]
}
The timezone field shows the original TZID from the iCalendar data. "floating" means the event has no timezone — the time is interpreted as-is regardless of the viewer's timezone.
The istota.skills.calendar module also provides functions for programmatic access:
| Function | Description | Returns |
|---|---|---|
get_caldav_client(url, username, password) | Create CalDAV client | caldav.DAVClient |
list_calendars(client) | List all accessible calendars | list[(name, url)] |
get_calendars_for_user(client, username) | Get calendars owned by a user | list[(name, url, writable)] |
get_events(client, calendar_url, start, end) | Get events in date range | list[CalendarEvent] |
get_today_events(client, calendar_url, tz) | Get today's events | list[CalendarEvent] |
get_tomorrow_events(client, calendar_url, tz) | Get tomorrow's events | list[CalendarEvent] |
get_week_events(client, calendar_url, tz) | Get next 7 days' events | list[CalendarEvent] |
get_event_by_uid(client, calendar_url, uid) | Get single event by UID | CalendarEvent | None |
create_event(client, calendar_url, ...) | Create new event | str (event UID) |
update_event(client, calendar_url, uid, ...) | Update existing event | bool |
delete_event(client, calendar_url, uid) | Delete event by UID | bool |
format_event_for_display(event) | Format event for human display | str |
format_day_schedule(events, date_label) | Format day's events | str |
@dataclass
class CalendarEvent:
uid: str # Unique identifier
summary: str # Event title
start: datetime # Start time
end: datetime # End time
location: str | None
description: str | None
all_day: bool
timezone: str | None # Original TZID, None = floating
Calendars can be shared with read-only or edit permissions:
When attempting to modify a read-only calendar, update_event() and create_event() will raise caldav.error.AuthorizationError.
from istota.skills.calendar import get_caldav_client, get_today_events
import os
client = get_caldav_client(
url=os.environ["CALDAV_URL"],
username=os.environ["CALDAV_USERNAME"],
password=os.environ["CALDAV_PASSWORD"],
)
# Get today's events (always pass user's timezone)
calendar_url = "https://nextcloud.example.com/remote.php/dav/calendars/alice/personal/"
for event in get_today_events(client, calendar_url, tz="America/Los_Angeles"):
print(f"{event.start.strftime('%H:%M')} - {event.summary}")