-
Notifications
You must be signed in to change notification settings - Fork 4
CLI Calendar
Your schedule, as the Edith app sees it. The calendar grant belongs to the Edith
bundle rather than to this binary, so ed never reads EventKit itself: it asks
the running menu bar app for the events it holds and prints them. Reach
for it when you want the next few days on stdout, or as JSON for something else
to read.
The group has one verb. If the app is closed, the Calendar extension is off, or macOS has not granted calendar access, it exits 4 and says which of the three it was.
| Command | What it does |
|---|---|
ed calendar |
No subcommand runs ls, so a bare ed calendar is the upcoming events |
ed calendar ls |
Upcoming events from the running app, as a table or as JSON |
ed calendar list is an alias for ed calendar ls.
Prints the events the app is holding whose start falls within the next --days
days.
ed calendar ls [--days <n>] [--json]
| Name | Type / values | Default | What it does |
|---|---|---|---|
--days <n> |
integer, 0 or more | 7 |
Only events starting within this many days. The cutoff is measured from the moment the command runs, not from midnight. A negative value exits 2. |
--json |
flag | off | Emit JSON on stdout. Long form only; there is no -j. |
--help is generated by the parser, prints the usage summary on stdout and
exits 0.
A top level array, one object per event, in the same order the table prints
them. Object keys are sorted, so allDay comes first and title last. null
appears rather than a missing key, so the shape is stable across runs.
[
{
"allDay": true,
"calendar": "Personal",
"end": "2026-08-09T00:00:00Z",
"location": null,
"meetingURL": null,
"start": "2026-08-08T00:00:00Z",
"title": "Sarah's birthday"
},
{
"allDay": false,
"calendar": "Work",
"end": "2026-08-08T11:30:00Z",
"location": "https://meet.google.com/abc-defg-hij",
"meetingURL": "https://meet.google.com/abc-defg-hij",
"start": "2026-08-08T11:00:00Z",
"title": "Standup"
}
]| Key | Type | What it is |
|---|---|---|
allDay |
boolean | The event's all-day flag |
calendar |
string | The name of the calendar the event came from, "" when EventKit does not give one |
end |
string | End instant, ISO 8601 in UTC, for example 2026-08-08T11:30:00Z
|
location |
string or null | The event's location field, verbatim, null when it has none |
meetingURL |
string or null | A detected video call link, null when none was found |
start |
string | Start instant, ISO 8601 in UTC |
title |
string | The event title, or Untitled when the event has none |
No events is an empty array, [], and still exits 0.
ed calendar ls
ed calendar ls --days 1
ed calendar ls --days 14 --json
ed calendar ls --json | jq -r '.[] | select(.meetingURL) | .meetingURL'
The table is four columns. WHEN is all day for an all-day event and
EEE d MMM HH:mm in your own time zone and locale for everything else. LINK
is the detected meeting URL, blank when there is none.
$ ed calendar ls --days 2
WHEN TITLE CALENDAR LINK
all day Sarah's birthday Personal
Sat 8 Aug 11:00 Standup Work https://meet.google.com/abc-defg-hij
Sat 8 Aug 16:30 Dentist Personal
Sun 9 Aug 09:00 Design review Work https://zoom.us/j/98213374412
location is in --json only; the table has no column for it. With nothing to
show the header row is printed on its own:
$ ed calendar ls
WHEN TITLE CALENDAR LINK
Nothing is written. ls reads, and the only side effect is on the app's side:
answering the request makes the app refresh its calendar store first, so what
you get is current rather than whatever the panel last drew, and the panel is
current afterwards too.
The app must be running. ed checks for the menu bar helper before it posts
anything, so a closed app fails immediately rather than after a timeout:
$ ed calendar ls
error: reading the calendar needs the Edith menu bar app to be running
hint: start Edith, then retry
With the app running, ed posts requestCalendarEvents on the app's own
notification bus and waits up to 4 seconds for calendarEvents to come back.
After one second of waiting it prints waiting for Edith to answer... on
stderr, once. Silence past the deadline is diagnosed rather than reported as a
bare timeout, in this order: the app stopped running, the Calendar extension is
off, macOS has not granted calendar access, and only then "Edith did not answer
for the calendar in time" with a hint that the running app may predate this
command. Every one of those exits 4.
The app can also answer with a refusal instead of events, and those get their own wording:
$ ed calendar ls
error: the Calendar extension is off
hint: run `ed extensions enable calendar`
$ ed calendar ls
error: macOS has not granted Edith calendar access
hint: run `ed permissions request calendar`
Both exit 4. The second one is what you get when the grant is missing, denied, or write-only: the app answers only when EventKit reports full access.
--days is checked before anything is posted, so a bad value costs no round
trip, though you have to write --days=-1 to get there: --days -1 is read as
a missing value by the parser and exits 2 for that reason instead.
$ ed calendar ls --days=-1
error: --days cannot be negative
hint: pass 0 or more
| Code | When |
|---|---|
| 0 | Events were printed, including the case where the window holds none |
| 2 |
--days was negative (written as --days=-1), --days was given no value or a value that is not an integer, or the command line carried an unknown flag |
| 4 | The menu bar app is not running, the Calendar extension is off, macOS has not granted calendar access, or the app did not answer within 4 seconds |
Exit 3 has no producer here; ed calendar names nothing that can be missing.
- The app decides the window, not
ed. The store loads from midnight today through 14 days ahead, andedfilters that list down to--days. Asking for more than the app has loaded returns what it has rather than failing, soed calendar ls --days 30usually shows the same 14 days as--days 14. - The only thing that widens the app's window is scrolling to the bottom of a
calendar list in the UI, which loads another 14 days at a time up to 120.
edcannot ask for more, and the window resets to 14 days whenever the app or the extension restarts. - Because the window starts at midnight rather than now, events that already
started today are included.
--days 0therefore means "everything from today that has already started", not "today's schedule", and it is usually the wrong flag to reach for. - Ordering is fixed: all-day events first, then everything else by start time ascending. The JSON array uses the same order as the table.
- Duplicates are collapsed before they are sent. Two events with the same title, start, end and all-day flag count as one, which is what removes the twin rows when the same invitation lands in two calendars. The surviving row keeps whichever calendar EventKit listed first.
- A meeting link is detected, not stored.
edshows the event's own URL when it points at a known conferencing host, and otherwise the first such link found in the location and notes. The hosts arezoom.us,meet.google.com,teams.microsoft.com,teams.live.com,webex.com,whereby.com,meet.jit.si,chime.aws,gotomeeting.com,bluejeans.comand8x8.vc, including their subdomains. A link to anything else is left inlocationandmeetingURLstaysnull. - Times are transported and printed as two different things.
--jsongives ISO 8601 in UTC; the table renders in the local time zone with localised day and month names, so the two can look like different days near midnight. - Filtering happens in
ed, after the whole list has arrived, so a small--daysdoes not make the request cheaper. The cost is one round trip either way. - The extension switch is a setting like any other:
ed config set tabCalendarEnabled trueanded extensions enable calendarwrite the same key. Enabling the extension without the macOS grant leavesed calendar lsexiting 4 on the permission, so request it as well. - Turning the extension on creates the store inside the running app, and a store
with no grant never populates. After granting calendar access,
ed app relaunchis the reliable way to make the app pick the new state up.
-
ed extensionsto turn the Calendar extension on or off -
ed permissionsto request the macOS calendar grant -
ed configfortabCalendarEnabled, the only key in thecalendargroup -
ed appfored app relaunch, which a new grant needs - All command groups
Auto-generated from docs/, edit the docs in the repo, not the wiki.
CLI reference
Companion
- Deploy
- Concepts
- Concepts Memory
- Concepts Ingestion
- Concepts Search
- Concepts Chat
- Concepts Learning
- Concepts Brain
- Concepts Friend
- Hosts
- Stack
- Status
- Doctor
- Search
- Index
- Ingest
- Episodes
- Sync
- Observations
- Reflect
- Beliefs
- Ask
- Extract
- Claims
- Corroborate
- Runs
- Chat
- Conversations
- Forget
- Export
- Import
- Erase
- Wipe
- Episode
- Nightly
- Reason
- Personas
- Council
- Lenses
- Core
- Why
- Hypotheses
- Predictions
- Commitments
- Discrepancies
- Calibration
- Inquire
- Entities
- Eval
- Standup
- Machines
- Baselines
- Connectors
- Facts
- Correct
- Weekly
- Db
Guides