calctl 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- calctl-0.1.0/PKG-INFO +370 -0
- calctl-0.1.0/README.md +342 -0
- calctl-0.1.0/pyproject.toml +121 -0
- calctl-0.1.0/src/calctl/__init__.py +5 -0
- calctl-0.1.0/src/calctl/calendar.py +880 -0
- calctl-0.1.0/src/calctl/cli.py +336 -0
- calctl-0.1.0/src/calctl/errors.py +35 -0
- calctl-0.1.0/src/calctl/formatting.py +153 -0
- calctl-0.1.0/src/calctl/py.typed +0 -0
calctl-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: calctl
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: macOS Calendar CLI using EventKit
|
|
5
|
+
Author: Durmus Karatay
|
|
6
|
+
Author-email: Durmus Karatay <durmus@karatay.me>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Classifier: Development Status :: 4 - Beta
|
|
9
|
+
Classifier: Environment :: Console
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Operating System :: MacOS
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Topic :: Office/Business :: Scheduling
|
|
18
|
+
Classifier: Typing :: Typed
|
|
19
|
+
Requires-Dist: pyobjc-framework-eventkit>=12.1
|
|
20
|
+
Requires-Dist: pyobjc-framework-corelocation>=12.1
|
|
21
|
+
Requires-Dist: python-dateutil>=2.9.0.post0
|
|
22
|
+
Requires-Dist: typer>=0.24.1
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Project-URL: Homepage, https://github.com/ukaratay/calctl
|
|
25
|
+
Project-URL: Repository, https://github.com/ukaratay/calctl
|
|
26
|
+
Project-URL: Issues, https://github.com/ukaratay/calctl/issues
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# calctl
|
|
30
|
+
|
|
31
|
+
**macOS Calendar CLI using EventKit**
|
|
32
|
+
|
|
33
|
+
[](https://pypi.org/project/calctl/)
|
|
34
|
+
[](https://pypi.org/project/calctl/)
|
|
35
|
+
[](https://github.com/ukaratay/calctl/blob/main/LICENSE)
|
|
36
|
+
|
|
37
|
+
`calctl` is a command-line interface for Apple Calendar on macOS. It uses the native EventKit framework via PyObjC — the same API the Calendar app uses — so it reads and writes all your calendars directly, with no sync or bridge required.
|
|
38
|
+
|
|
39
|
+
## Features
|
|
40
|
+
|
|
41
|
+
- **List calendars** — see all calendars with their source and type
|
|
42
|
+
- **List events** — browse events in any date range, optionally filtered by calendar
|
|
43
|
+
- **Search events** — full-text search across titles, notes, and locations
|
|
44
|
+
- **Create events** — all-day or timed events with full metadata
|
|
45
|
+
- **Edit events** — update any field; control whether edits apply to this occurrence or all future occurrences
|
|
46
|
+
- **Delete events** — single occurrence or this-and-future for recurring events
|
|
47
|
+
- **Full EventKit support** — recurrence rules (RRULE), alarms, attendees, availability, geo coordinates, timezones
|
|
48
|
+
- **JSON and human-readable text output** — choose your format explicitly or let calctl detect it
|
|
49
|
+
- **Auto-detects output format** — JSON when piped, text when run in a terminal
|
|
50
|
+
|
|
51
|
+
## Requirements
|
|
52
|
+
|
|
53
|
+
- macOS (EventKit is macOS-only)
|
|
54
|
+
- Python ≥ 3.10
|
|
55
|
+
|
|
56
|
+
## Installation
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# Using pipx (recommended for CLI tools)
|
|
60
|
+
pipx install calctl
|
|
61
|
+
|
|
62
|
+
# Using uv
|
|
63
|
+
uv tool install calctl
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Permissions
|
|
67
|
+
|
|
68
|
+
calctl needs access to your calendars. On first run, macOS will show a permission dialog. If you previously denied access, go to:
|
|
69
|
+
|
|
70
|
+
**System Settings → Privacy & Security → Calendars → calctl** → enable access
|
|
71
|
+
|
|
72
|
+
## Quick Start
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
# List all calendars
|
|
76
|
+
calctl calendars
|
|
77
|
+
|
|
78
|
+
# List events for the next 7 days
|
|
79
|
+
calctl list
|
|
80
|
+
|
|
81
|
+
# List events in a specific date range
|
|
82
|
+
calctl list --from 2026-03-19 --to 2026-03-26
|
|
83
|
+
|
|
84
|
+
# List events from a specific calendar
|
|
85
|
+
calctl list --calendar Work
|
|
86
|
+
|
|
87
|
+
# Search events by keyword
|
|
88
|
+
calctl search "meeting"
|
|
89
|
+
|
|
90
|
+
# Search within a date range and calendar
|
|
91
|
+
calctl search "standup" --from 2026-03-01 --to 2026-03-31 --calendar Work
|
|
92
|
+
|
|
93
|
+
# Show full details for an event
|
|
94
|
+
calctl show EVENT_ID
|
|
95
|
+
|
|
96
|
+
# Create a timed event
|
|
97
|
+
calctl create --title "Team Standup" --start 2026-03-20T09:00:00 --end 2026-03-20T09:30:00 --calendar Work
|
|
98
|
+
|
|
99
|
+
# Create an all-day event
|
|
100
|
+
calctl create --title "Company Holiday" --start 2026-03-20 --all-day
|
|
101
|
+
|
|
102
|
+
# Create a recurring event with an alarm
|
|
103
|
+
calctl create \
|
|
104
|
+
--title "Weekly Review" \
|
|
105
|
+
--start 2026-03-20T14:00:00 \
|
|
106
|
+
--rrule "FREQ=WEEKLY;BYDAY=FR" \
|
|
107
|
+
--alarm -15m
|
|
108
|
+
|
|
109
|
+
# Create an event with location and geo coordinates
|
|
110
|
+
calctl create \
|
|
111
|
+
--title "Lunch" \
|
|
112
|
+
--start 2026-03-20T12:00:00 \
|
|
113
|
+
--end 2026-03-20T13:00:00 \
|
|
114
|
+
--location "Blue Bottle Coffee" \
|
|
115
|
+
--geo "37.7749,-122.4194"
|
|
116
|
+
|
|
117
|
+
# Edit an event's title and location
|
|
118
|
+
calctl edit EVENT_ID --title "Updated Title" --location "Room 42"
|
|
119
|
+
|
|
120
|
+
# Edit a recurring event — this and all future occurrences
|
|
121
|
+
calctl edit EVENT_ID --title "Renamed Series" --span future
|
|
122
|
+
|
|
123
|
+
# Delete an event
|
|
124
|
+
calctl delete EVENT_ID
|
|
125
|
+
|
|
126
|
+
# Delete a recurring event — this occurrence only
|
|
127
|
+
calctl delete EVENT_ID --span this
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## CLI Reference
|
|
131
|
+
|
|
132
|
+
### Global Options
|
|
133
|
+
|
|
134
|
+
These options apply to all commands and must come before the command name:
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
calctl [OPTIONS] COMMAND [ARGS]...
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
| Option | Short | Type | Default | Description |
|
|
141
|
+
|--------|-------|------|---------|-------------|
|
|
142
|
+
| `--format` | `-f` | `json\|text` | auto | Output format. Defaults to `text` on TTY, `json` when piped. |
|
|
143
|
+
| `--verbose` | `-v` | flag | false | Enable debug logging to stderr. |
|
|
144
|
+
| `--help` | | flag | | Show help and exit. |
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
### `calctl calendars`
|
|
149
|
+
|
|
150
|
+
List all calendars.
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
calctl calendars
|
|
154
|
+
calctl calendars --format json
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
### `calctl list`
|
|
160
|
+
|
|
161
|
+
List events in a date range.
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
calctl list [OPTIONS]
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
| Option | Type | Default | Description |
|
|
168
|
+
|--------|------|---------|-------------|
|
|
169
|
+
| `--from` | `YYYY-MM-DD` | today | Start date (inclusive). |
|
|
170
|
+
| `--to` | `YYYY-MM-DD` | today + 7 days | End date (inclusive). |
|
|
171
|
+
| `--calendar` | string | (all calendars) | Filter by calendar name. |
|
|
172
|
+
|
|
173
|
+
**Examples:**
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
calctl list
|
|
177
|
+
calctl list --from 2026-03-01 --to 2026-03-31
|
|
178
|
+
calctl list --calendar Personal
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
### `calctl search`
|
|
184
|
+
|
|
185
|
+
Search events by keyword. Matches against title, notes, and location.
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
calctl search QUERY [OPTIONS]
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
| Argument/Option | Type | Default | Description |
|
|
192
|
+
|-----------------|------|---------|-------------|
|
|
193
|
+
| `QUERY` | string | required | Search keyword(s). |
|
|
194
|
+
| `--from` | `YYYY-MM-DD` | (no limit) | Restrict search start date. |
|
|
195
|
+
| `--to` | `YYYY-MM-DD` | (no limit) | Restrict search end date. |
|
|
196
|
+
| `--calendar` | string | (all calendars) | Filter by calendar name. |
|
|
197
|
+
|
|
198
|
+
**Examples:**
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
calctl search "team meeting"
|
|
202
|
+
calctl search "invoice" --from 2026-01-01 --to 2026-03-31
|
|
203
|
+
calctl search "standup" --calendar Work
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
### `calctl show`
|
|
209
|
+
|
|
210
|
+
Show full details for a single event, including recurrence, alarms, and attendees.
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
calctl show EVENT_ID
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
| Argument | Type | Description |
|
|
217
|
+
|----------|------|-------------|
|
|
218
|
+
| `EVENT_ID` | string | Event identifier (from `list` or `search` output). |
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
### `calctl create`
|
|
223
|
+
|
|
224
|
+
Create a new event.
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
calctl create --title TITLE --start DATETIME [OPTIONS]
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
| Option | Type | Default | Description |
|
|
231
|
+
|--------|------|---------|-------------|
|
|
232
|
+
| `--title` | string | **required** | Event title. |
|
|
233
|
+
| `--start` | `YYYY-MM-DD` or `YYYY-MM-DDTHH:MM:SS` | **required** | Start date or datetime. |
|
|
234
|
+
| `--end` | `YYYY-MM-DD` or `YYYY-MM-DDTHH:MM:SS` | start + 1h (or same day if `--all-day`) | End date or datetime. |
|
|
235
|
+
| `--calendar` | string | default calendar | Calendar to add the event to. |
|
|
236
|
+
| `--location` | string | | Location string. |
|
|
237
|
+
| `--geo` | `lat,lng` | | Geographic coordinates (e.g. `37.7749,-122.4194`). |
|
|
238
|
+
| `--notes` | string | | Event notes / description. |
|
|
239
|
+
| `--url` | string | | URL associated with the event. |
|
|
240
|
+
| `--all-day` / `--no-all-day` | flag | false | Create as an all-day event. |
|
|
241
|
+
| `--availability` | `busy\|free\|tentative\|unavailable` | | Availability status. |
|
|
242
|
+
| `--timezone` | string | | Timezone identifier (e.g. `America/New_York`). |
|
|
243
|
+
| `--rrule` | RRULE string | | Recurrence rule (e.g. `FREQ=WEEKLY;BYDAY=MO,WE,FR`). |
|
|
244
|
+
| `--alarm` | duration | | Alarm offset before event (e.g. `-15m`, `-1h`). Repeatable for multiple alarms. Use `--alarm ""` to explicitly clear alarms. |
|
|
245
|
+
|
|
246
|
+
**Examples:**
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
# Simple 30-minute event
|
|
250
|
+
calctl create --title "Coffee" --start 2026-03-20T10:00:00 --end 2026-03-20T10:30:00
|
|
251
|
+
|
|
252
|
+
# All-day event
|
|
253
|
+
calctl create --title "PTO" --start 2026-03-20 --all-day --calendar Personal
|
|
254
|
+
|
|
255
|
+
# Recurring weekly event with two alarms
|
|
256
|
+
calctl create \
|
|
257
|
+
--title "Weekly Sync" \
|
|
258
|
+
--start 2026-03-20T10:00:00 \
|
|
259
|
+
--rrule "FREQ=WEEKLY;BYDAY=FR" \
|
|
260
|
+
--alarm -10m \
|
|
261
|
+
--alarm -1h
|
|
262
|
+
|
|
263
|
+
# Event with location details
|
|
264
|
+
calctl create \
|
|
265
|
+
--title "Conference" \
|
|
266
|
+
--start 2026-03-20T09:00:00 \
|
|
267
|
+
--end 2026-03-20T17:00:00 \
|
|
268
|
+
--location "Moscone Center, San Francisco" \
|
|
269
|
+
--geo "37.7842,-122.4016" \
|
|
270
|
+
--timezone "America/Los_Angeles"
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
### `calctl edit`
|
|
276
|
+
|
|
277
|
+
Edit an existing event. Only the fields you specify are changed.
|
|
278
|
+
|
|
279
|
+
```bash
|
|
280
|
+
calctl edit EVENT_ID [OPTIONS]
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
| Argument/Option | Type | Default | Description |
|
|
284
|
+
|-----------------|------|---------|-------------|
|
|
285
|
+
| `EVENT_ID` | string | **required** | Event to edit. |
|
|
286
|
+
| `--title` | string | | New title. |
|
|
287
|
+
| `--start` | datetime | | New start datetime. |
|
|
288
|
+
| `--end` | datetime | | New end datetime. |
|
|
289
|
+
| `--calendar` | string | | Move to this calendar. |
|
|
290
|
+
| `--location` | string | | New location string. |
|
|
291
|
+
| `--geo` | `lat,lng` | | New geo coordinates. |
|
|
292
|
+
| `--notes` | string | | New notes. |
|
|
293
|
+
| `--url` | string | | New URL. |
|
|
294
|
+
| `--all-day` / `--no-all-day` | flag | | Set or clear all-day flag. |
|
|
295
|
+
| `--availability` | `busy\|free\|tentative\|unavailable` | | New availability. |
|
|
296
|
+
| `--timezone` | string | | New timezone. |
|
|
297
|
+
| `--rrule` | RRULE string | | New recurrence rule. |
|
|
298
|
+
| `--alarm` | duration | | New alarm(s). Repeatable. Use `--alarm ""` to clear all alarms. |
|
|
299
|
+
| `--span` | `this\|future` | `this` | For recurring events: edit only this occurrence (`this`) or this and all future occurrences (`future`). |
|
|
300
|
+
|
|
301
|
+
**Examples:**
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
# Rename an event
|
|
305
|
+
calctl edit EVENT_ID --title "New Name"
|
|
306
|
+
|
|
307
|
+
# Reschedule
|
|
308
|
+
calctl edit EVENT_ID --start 2026-03-21T10:00:00 --end 2026-03-21T11:00:00
|
|
309
|
+
|
|
310
|
+
# Edit all future occurrences of a recurring event
|
|
311
|
+
calctl edit EVENT_ID --title "Renamed Series" --span future
|
|
312
|
+
|
|
313
|
+
# Move event to a different calendar
|
|
314
|
+
calctl edit EVENT_ID --calendar Personal
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
### `calctl delete`
|
|
320
|
+
|
|
321
|
+
Delete an event.
|
|
322
|
+
|
|
323
|
+
```bash
|
|
324
|
+
calctl delete EVENT_ID [OPTIONS]
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
| Argument/Option | Type | Default | Description |
|
|
328
|
+
|-----------------|------|---------|-------------|
|
|
329
|
+
| `EVENT_ID` | string | **required** | Event to delete. |
|
|
330
|
+
| `--span` | `this\|future` | `this` | For recurring events: delete only this occurrence (`this`) or this and all future occurrences (`future`). |
|
|
331
|
+
|
|
332
|
+
**Examples:**
|
|
333
|
+
|
|
334
|
+
```bash
|
|
335
|
+
# Delete a single event
|
|
336
|
+
calctl delete EVENT_ID
|
|
337
|
+
|
|
338
|
+
# Delete this and all future occurrences
|
|
339
|
+
calctl delete EVENT_ID --span future
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
## Output Formats
|
|
345
|
+
|
|
346
|
+
calctl supports two output formats, controlled by `--format` / `-f`:
|
|
347
|
+
|
|
348
|
+
| Format | Flag | Description |
|
|
349
|
+
|--------|------|-------------|
|
|
350
|
+
| `text` | `--format text` | Human-readable, table-style output for the terminal. |
|
|
351
|
+
| `json` | `--format json` | Machine-readable JSON. Arrays for list commands, objects for single-item commands. |
|
|
352
|
+
|
|
353
|
+
**Auto-detection:** When `--format` is not specified, calctl detects whether stdout is a terminal (TTY):
|
|
354
|
+
- **Terminal** → `text` format
|
|
355
|
+
- **Pipe or redirect** → `json` format
|
|
356
|
+
|
|
357
|
+
This means you can pipe calctl output to `jq` without specifying `--format json`:
|
|
358
|
+
|
|
359
|
+
```bash
|
|
360
|
+
# Pipe output — JSON is selected automatically
|
|
361
|
+
calctl list | jq '.[] | .title'
|
|
362
|
+
calctl search "meeting" | jq '.[0].id'
|
|
363
|
+
|
|
364
|
+
# Force text format in a script
|
|
365
|
+
calctl list --format text > events.txt
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
## License
|
|
369
|
+
|
|
370
|
+
MIT — see [LICENSE](LICENSE) for details.
|
calctl-0.1.0/README.md
ADDED
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
# calctl
|
|
2
|
+
|
|
3
|
+
**macOS Calendar CLI using EventKit**
|
|
4
|
+
|
|
5
|
+
[](https://pypi.org/project/calctl/)
|
|
6
|
+
[](https://pypi.org/project/calctl/)
|
|
7
|
+
[](https://github.com/ukaratay/calctl/blob/main/LICENSE)
|
|
8
|
+
|
|
9
|
+
`calctl` is a command-line interface for Apple Calendar on macOS. It uses the native EventKit framework via PyObjC — the same API the Calendar app uses — so it reads and writes all your calendars directly, with no sync or bridge required.
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- **List calendars** — see all calendars with their source and type
|
|
14
|
+
- **List events** — browse events in any date range, optionally filtered by calendar
|
|
15
|
+
- **Search events** — full-text search across titles, notes, and locations
|
|
16
|
+
- **Create events** — all-day or timed events with full metadata
|
|
17
|
+
- **Edit events** — update any field; control whether edits apply to this occurrence or all future occurrences
|
|
18
|
+
- **Delete events** — single occurrence or this-and-future for recurring events
|
|
19
|
+
- **Full EventKit support** — recurrence rules (RRULE), alarms, attendees, availability, geo coordinates, timezones
|
|
20
|
+
- **JSON and human-readable text output** — choose your format explicitly or let calctl detect it
|
|
21
|
+
- **Auto-detects output format** — JSON when piped, text when run in a terminal
|
|
22
|
+
|
|
23
|
+
## Requirements
|
|
24
|
+
|
|
25
|
+
- macOS (EventKit is macOS-only)
|
|
26
|
+
- Python ≥ 3.10
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# Using pipx (recommended for CLI tools)
|
|
32
|
+
pipx install calctl
|
|
33
|
+
|
|
34
|
+
# Using uv
|
|
35
|
+
uv tool install calctl
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Permissions
|
|
39
|
+
|
|
40
|
+
calctl needs access to your calendars. On first run, macOS will show a permission dialog. If you previously denied access, go to:
|
|
41
|
+
|
|
42
|
+
**System Settings → Privacy & Security → Calendars → calctl** → enable access
|
|
43
|
+
|
|
44
|
+
## Quick Start
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# List all calendars
|
|
48
|
+
calctl calendars
|
|
49
|
+
|
|
50
|
+
# List events for the next 7 days
|
|
51
|
+
calctl list
|
|
52
|
+
|
|
53
|
+
# List events in a specific date range
|
|
54
|
+
calctl list --from 2026-03-19 --to 2026-03-26
|
|
55
|
+
|
|
56
|
+
# List events from a specific calendar
|
|
57
|
+
calctl list --calendar Work
|
|
58
|
+
|
|
59
|
+
# Search events by keyword
|
|
60
|
+
calctl search "meeting"
|
|
61
|
+
|
|
62
|
+
# Search within a date range and calendar
|
|
63
|
+
calctl search "standup" --from 2026-03-01 --to 2026-03-31 --calendar Work
|
|
64
|
+
|
|
65
|
+
# Show full details for an event
|
|
66
|
+
calctl show EVENT_ID
|
|
67
|
+
|
|
68
|
+
# Create a timed event
|
|
69
|
+
calctl create --title "Team Standup" --start 2026-03-20T09:00:00 --end 2026-03-20T09:30:00 --calendar Work
|
|
70
|
+
|
|
71
|
+
# Create an all-day event
|
|
72
|
+
calctl create --title "Company Holiday" --start 2026-03-20 --all-day
|
|
73
|
+
|
|
74
|
+
# Create a recurring event with an alarm
|
|
75
|
+
calctl create \
|
|
76
|
+
--title "Weekly Review" \
|
|
77
|
+
--start 2026-03-20T14:00:00 \
|
|
78
|
+
--rrule "FREQ=WEEKLY;BYDAY=FR" \
|
|
79
|
+
--alarm -15m
|
|
80
|
+
|
|
81
|
+
# Create an event with location and geo coordinates
|
|
82
|
+
calctl create \
|
|
83
|
+
--title "Lunch" \
|
|
84
|
+
--start 2026-03-20T12:00:00 \
|
|
85
|
+
--end 2026-03-20T13:00:00 \
|
|
86
|
+
--location "Blue Bottle Coffee" \
|
|
87
|
+
--geo "37.7749,-122.4194"
|
|
88
|
+
|
|
89
|
+
# Edit an event's title and location
|
|
90
|
+
calctl edit EVENT_ID --title "Updated Title" --location "Room 42"
|
|
91
|
+
|
|
92
|
+
# Edit a recurring event — this and all future occurrences
|
|
93
|
+
calctl edit EVENT_ID --title "Renamed Series" --span future
|
|
94
|
+
|
|
95
|
+
# Delete an event
|
|
96
|
+
calctl delete EVENT_ID
|
|
97
|
+
|
|
98
|
+
# Delete a recurring event — this occurrence only
|
|
99
|
+
calctl delete EVENT_ID --span this
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## CLI Reference
|
|
103
|
+
|
|
104
|
+
### Global Options
|
|
105
|
+
|
|
106
|
+
These options apply to all commands and must come before the command name:
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
calctl [OPTIONS] COMMAND [ARGS]...
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
| Option | Short | Type | Default | Description |
|
|
113
|
+
|--------|-------|------|---------|-------------|
|
|
114
|
+
| `--format` | `-f` | `json\|text` | auto | Output format. Defaults to `text` on TTY, `json` when piped. |
|
|
115
|
+
| `--verbose` | `-v` | flag | false | Enable debug logging to stderr. |
|
|
116
|
+
| `--help` | | flag | | Show help and exit. |
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
### `calctl calendars`
|
|
121
|
+
|
|
122
|
+
List all calendars.
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
calctl calendars
|
|
126
|
+
calctl calendars --format json
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
### `calctl list`
|
|
132
|
+
|
|
133
|
+
List events in a date range.
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
calctl list [OPTIONS]
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
| Option | Type | Default | Description |
|
|
140
|
+
|--------|------|---------|-------------|
|
|
141
|
+
| `--from` | `YYYY-MM-DD` | today | Start date (inclusive). |
|
|
142
|
+
| `--to` | `YYYY-MM-DD` | today + 7 days | End date (inclusive). |
|
|
143
|
+
| `--calendar` | string | (all calendars) | Filter by calendar name. |
|
|
144
|
+
|
|
145
|
+
**Examples:**
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
calctl list
|
|
149
|
+
calctl list --from 2026-03-01 --to 2026-03-31
|
|
150
|
+
calctl list --calendar Personal
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
### `calctl search`
|
|
156
|
+
|
|
157
|
+
Search events by keyword. Matches against title, notes, and location.
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
calctl search QUERY [OPTIONS]
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
| Argument/Option | Type | Default | Description |
|
|
164
|
+
|-----------------|------|---------|-------------|
|
|
165
|
+
| `QUERY` | string | required | Search keyword(s). |
|
|
166
|
+
| `--from` | `YYYY-MM-DD` | (no limit) | Restrict search start date. |
|
|
167
|
+
| `--to` | `YYYY-MM-DD` | (no limit) | Restrict search end date. |
|
|
168
|
+
| `--calendar` | string | (all calendars) | Filter by calendar name. |
|
|
169
|
+
|
|
170
|
+
**Examples:**
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
calctl search "team meeting"
|
|
174
|
+
calctl search "invoice" --from 2026-01-01 --to 2026-03-31
|
|
175
|
+
calctl search "standup" --calendar Work
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
### `calctl show`
|
|
181
|
+
|
|
182
|
+
Show full details for a single event, including recurrence, alarms, and attendees.
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
calctl show EVENT_ID
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
| Argument | Type | Description |
|
|
189
|
+
|----------|------|-------------|
|
|
190
|
+
| `EVENT_ID` | string | Event identifier (from `list` or `search` output). |
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
### `calctl create`
|
|
195
|
+
|
|
196
|
+
Create a new event.
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
calctl create --title TITLE --start DATETIME [OPTIONS]
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
| Option | Type | Default | Description |
|
|
203
|
+
|--------|------|---------|-------------|
|
|
204
|
+
| `--title` | string | **required** | Event title. |
|
|
205
|
+
| `--start` | `YYYY-MM-DD` or `YYYY-MM-DDTHH:MM:SS` | **required** | Start date or datetime. |
|
|
206
|
+
| `--end` | `YYYY-MM-DD` or `YYYY-MM-DDTHH:MM:SS` | start + 1h (or same day if `--all-day`) | End date or datetime. |
|
|
207
|
+
| `--calendar` | string | default calendar | Calendar to add the event to. |
|
|
208
|
+
| `--location` | string | | Location string. |
|
|
209
|
+
| `--geo` | `lat,lng` | | Geographic coordinates (e.g. `37.7749,-122.4194`). |
|
|
210
|
+
| `--notes` | string | | Event notes / description. |
|
|
211
|
+
| `--url` | string | | URL associated with the event. |
|
|
212
|
+
| `--all-day` / `--no-all-day` | flag | false | Create as an all-day event. |
|
|
213
|
+
| `--availability` | `busy\|free\|tentative\|unavailable` | | Availability status. |
|
|
214
|
+
| `--timezone` | string | | Timezone identifier (e.g. `America/New_York`). |
|
|
215
|
+
| `--rrule` | RRULE string | | Recurrence rule (e.g. `FREQ=WEEKLY;BYDAY=MO,WE,FR`). |
|
|
216
|
+
| `--alarm` | duration | | Alarm offset before event (e.g. `-15m`, `-1h`). Repeatable for multiple alarms. Use `--alarm ""` to explicitly clear alarms. |
|
|
217
|
+
|
|
218
|
+
**Examples:**
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
# Simple 30-minute event
|
|
222
|
+
calctl create --title "Coffee" --start 2026-03-20T10:00:00 --end 2026-03-20T10:30:00
|
|
223
|
+
|
|
224
|
+
# All-day event
|
|
225
|
+
calctl create --title "PTO" --start 2026-03-20 --all-day --calendar Personal
|
|
226
|
+
|
|
227
|
+
# Recurring weekly event with two alarms
|
|
228
|
+
calctl create \
|
|
229
|
+
--title "Weekly Sync" \
|
|
230
|
+
--start 2026-03-20T10:00:00 \
|
|
231
|
+
--rrule "FREQ=WEEKLY;BYDAY=FR" \
|
|
232
|
+
--alarm -10m \
|
|
233
|
+
--alarm -1h
|
|
234
|
+
|
|
235
|
+
# Event with location details
|
|
236
|
+
calctl create \
|
|
237
|
+
--title "Conference" \
|
|
238
|
+
--start 2026-03-20T09:00:00 \
|
|
239
|
+
--end 2026-03-20T17:00:00 \
|
|
240
|
+
--location "Moscone Center, San Francisco" \
|
|
241
|
+
--geo "37.7842,-122.4016" \
|
|
242
|
+
--timezone "America/Los_Angeles"
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
### `calctl edit`
|
|
248
|
+
|
|
249
|
+
Edit an existing event. Only the fields you specify are changed.
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
calctl edit EVENT_ID [OPTIONS]
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
| Argument/Option | Type | Default | Description |
|
|
256
|
+
|-----------------|------|---------|-------------|
|
|
257
|
+
| `EVENT_ID` | string | **required** | Event to edit. |
|
|
258
|
+
| `--title` | string | | New title. |
|
|
259
|
+
| `--start` | datetime | | New start datetime. |
|
|
260
|
+
| `--end` | datetime | | New end datetime. |
|
|
261
|
+
| `--calendar` | string | | Move to this calendar. |
|
|
262
|
+
| `--location` | string | | New location string. |
|
|
263
|
+
| `--geo` | `lat,lng` | | New geo coordinates. |
|
|
264
|
+
| `--notes` | string | | New notes. |
|
|
265
|
+
| `--url` | string | | New URL. |
|
|
266
|
+
| `--all-day` / `--no-all-day` | flag | | Set or clear all-day flag. |
|
|
267
|
+
| `--availability` | `busy\|free\|tentative\|unavailable` | | New availability. |
|
|
268
|
+
| `--timezone` | string | | New timezone. |
|
|
269
|
+
| `--rrule` | RRULE string | | New recurrence rule. |
|
|
270
|
+
| `--alarm` | duration | | New alarm(s). Repeatable. Use `--alarm ""` to clear all alarms. |
|
|
271
|
+
| `--span` | `this\|future` | `this` | For recurring events: edit only this occurrence (`this`) or this and all future occurrences (`future`). |
|
|
272
|
+
|
|
273
|
+
**Examples:**
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
# Rename an event
|
|
277
|
+
calctl edit EVENT_ID --title "New Name"
|
|
278
|
+
|
|
279
|
+
# Reschedule
|
|
280
|
+
calctl edit EVENT_ID --start 2026-03-21T10:00:00 --end 2026-03-21T11:00:00
|
|
281
|
+
|
|
282
|
+
# Edit all future occurrences of a recurring event
|
|
283
|
+
calctl edit EVENT_ID --title "Renamed Series" --span future
|
|
284
|
+
|
|
285
|
+
# Move event to a different calendar
|
|
286
|
+
calctl edit EVENT_ID --calendar Personal
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
### `calctl delete`
|
|
292
|
+
|
|
293
|
+
Delete an event.
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
calctl delete EVENT_ID [OPTIONS]
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
| Argument/Option | Type | Default | Description |
|
|
300
|
+
|-----------------|------|---------|-------------|
|
|
301
|
+
| `EVENT_ID` | string | **required** | Event to delete. |
|
|
302
|
+
| `--span` | `this\|future` | `this` | For recurring events: delete only this occurrence (`this`) or this and all future occurrences (`future`). |
|
|
303
|
+
|
|
304
|
+
**Examples:**
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
# Delete a single event
|
|
308
|
+
calctl delete EVENT_ID
|
|
309
|
+
|
|
310
|
+
# Delete this and all future occurrences
|
|
311
|
+
calctl delete EVENT_ID --span future
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
## Output Formats
|
|
317
|
+
|
|
318
|
+
calctl supports two output formats, controlled by `--format` / `-f`:
|
|
319
|
+
|
|
320
|
+
| Format | Flag | Description |
|
|
321
|
+
|--------|------|-------------|
|
|
322
|
+
| `text` | `--format text` | Human-readable, table-style output for the terminal. |
|
|
323
|
+
| `json` | `--format json` | Machine-readable JSON. Arrays for list commands, objects for single-item commands. |
|
|
324
|
+
|
|
325
|
+
**Auto-detection:** When `--format` is not specified, calctl detects whether stdout is a terminal (TTY):
|
|
326
|
+
- **Terminal** → `text` format
|
|
327
|
+
- **Pipe or redirect** → `json` format
|
|
328
|
+
|
|
329
|
+
This means you can pipe calctl output to `jq` without specifying `--format json`:
|
|
330
|
+
|
|
331
|
+
```bash
|
|
332
|
+
# Pipe output — JSON is selected automatically
|
|
333
|
+
calctl list | jq '.[] | .title'
|
|
334
|
+
calctl search "meeting" | jq '.[0].id'
|
|
335
|
+
|
|
336
|
+
# Force text format in a script
|
|
337
|
+
calctl list --format text > events.txt
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
## License
|
|
341
|
+
|
|
342
|
+
MIT — see [LICENSE](LICENSE) for details.
|