commit e739a7d779e9184b00eaef43fb05bac98bd31080 Author: zlei9 Date: Sun Mar 29 10:22:58 2026 +0800 Initial commit with translated description diff --git a/README.md b/README.md new file mode 100644 index 0000000..5509d17 --- /dev/null +++ b/README.md @@ -0,0 +1,65 @@ +# gcalcli-calendar + +An OpenClaw skill for managing Google Calendar via [gcalcli](https://github.com/insanum/gcalcli). + +## What this skill does + +Teaches the agent to read, search, create, and delete Google Calendar events using the `gcalcli` CLI. Optimized for low tool calls, minimal token usage, and fast conversational calendar management. + +## About gcalcli + +[gcalcli](https://github.com/insanum/gcalcli) is a well-established open-source CLI for Google Calendar (5k+ GitHub stars, actively maintained). It authenticates via OAuth2 and stores credentials locally. This skill does not handle authentication — gcalcli must be set up and authenticated before use. + +## Prerequisites + +- Python 3.6+ +- `gcalcli` — install via `pip install gcalcli` or `brew install gcalcli` +- Google Calendar OAuth2 credentials (set up via `gcalcli init` or `gcalcli list` on first run) + +## Actions policy — design rationale + +**This skill intentionally skips user confirmation for unambiguous destructive actions (delete/edit).** This is a deliberate UX decision, not an oversight. Here's why and how it's kept safe: + +### Why skip confirmation? + +This skill is designed for personal assistant use via messaging apps (Telegram, WhatsApp, etc.), where: +- The user has already stated their intent explicitly (e.g. "delete my dentist appointment on Thursday"). +- An extra "Are you sure?" round-trip adds latency and friction with no real safety benefit when the target is unambiguous. +- The interaction model is conversational — the user's message *is* the confirmation. + +### Safety guards in place + +The skill does NOT blindly delete. All of these must hold before executing without confirmation: + +1. **Explicit user request** — the user must have asked for the action in their message. +2. **Single unambiguous match** — exactly one event matches in a tight, bounded time window. +3. **Post-action verification** — after every delete, the agent verifies via agenda that the event is actually gone. It never claims success without verification. +4. **Disambiguation for ambiguous cases** — if multiple events match, the agent always stops and asks the user to choose before proceeding. +5. **Overlap checks for creates** — before creating events, the agent checks for scheduling conflicts across all calendars and asks for confirmation if an overlap exists. + +### If you prefer confirmation for all actions + +You can modify the "Actions policy" section in SKILL.md to require confirmation for all destructive actions. Change the "Unambiguous actions" rule to always ask before executing. + +## Network access + +This skill invokes `gcalcli`, which communicates with: +- `https://www.googleapis.com/calendar/` — Google Calendar API (authenticated via local OAuth2 tokens) +- `https://oauth2.googleapis.com/` — OAuth2 token refresh + +No other network access is made. The skill itself makes no HTTP requests — all API communication is handled by gcalcli. OAuth2 credentials are stored locally by gcalcli (typically in `~/.gcalcli_oauth`). + +## Commands used + +All `gcalcli` commands used by this skill: +- `gcalcli agenda` — list events in a time window (read-only) +- `gcalcli search` — search events by text query (read-only) +- `gcalcli add` — create a one-off event +- `gcalcli import` — create events via ICS (for recurrence/free-busy) +- `gcalcli delete` — delete events (uses `--iamaexpert` flag for non-interactive mode, which is gcalcli's built-in flag for scripted/automated use) + +No other commands or subcommands are used. No file system writes are performed (ICS content is piped via stdin, never written to disk). + +## License + +This skill is MIT licensed. [gcalcli](https://github.com/insanum/gcalcli) is MIT licensed. diff --git a/SKILL.md b/SKILL.md new file mode 100644 index 0000000..ff91c4d --- /dev/null +++ b/SKILL.md @@ -0,0 +1,163 @@ +--- +name: gcalcli-calendar +description: "通过gcalcli使用Google日历。" +metadata: {"openclaw":{"emoji":"📅","requires":{"bins":["gcalcli"]}}} +--- + +# gcalcli-calendar + +Use `gcalcli` to read/search/manage Google Calendar with minimal tool calls and minimal output. + +## Rules + +### CLI flag placement (critical) +- Global flags (`--nocolor`, `--calendar`) go BEFORE the subcommand. +- Subcommand-specific flags go AFTER the subcommand name. +- Example: `gcalcli --nocolor delete --iamaexpert "query" start end` — NOT `gcalcli --nocolor --iamaexpert delete ...`. +- This applies to ALL subcommand flags: `--iamaexpert` (delete), `--noprompt`/`--allday` (add), `--use-legacy-import` (import), etc. + +### Output & language +- Don't print CLI commands/flags/tool details unless the user explicitly asks (e.g. "show commands used", "/debug", "/commands"). +- If asked for commands: print ALL executed commands in order (including retries) and nothing else. +- Don't mix languages within one reply. +- Be concise. No scope unless nothing found. + +### Dates & formatting +- Human-friendly dates by default. ISO only if explicitly requested. +- Don't quote event titles unless needed to disambiguate. + +### Calendar scope +- Trust gcalcli config (default/ignore calendars). Don't broaden scope unless user asks "across all calendars" or results are clearly wrong. + +### Agenda (today-only by default) +- If user asks "agenda" without a period, return today only. +- Expand only if explicitly asked (tomorrow / next N days / date range). + +### Weekday requests (no mental math) +If user says "on Monday/Tuesday/..." without a date: +1) fetch next 14 days agenda once, +2) pick matching day/event from tool output, +3) proceed (or disambiguate if multiple). + +### Finding events: prefer deterministic agenda scan (meaning-first) +When locating events to cancel/delete/edit: +- Prefer `agenda` over `search`. +- Use a bounded window and match events by meaning (semantic match) rather than exact text. +- Default locate windows: + - If user gives an exact date: scan that day only. + - If user gives a weekday: scan next 14 days. + - If user gives only meaning words ("train", "lecture", etc.) with no date: scan next 30 days first. + - If still not found: expand to 180 days and say so only if still empty. + +Use gcalcli `search` only as a fallback when: +- the time window would be too large to scan via agenda (token-heavy), or +- the user explicitly asked to "search". + +### Search (bounded) +- Default search window: next ~180 days (unless user specified otherwise). +- If no matches: say "No matches in next ~6 months (->)" and offer to expand. +- Show scope only when nothing is found. + +### Tool efficiency +- Default: use `--nocolor` to reduce formatting noise and tokens. +- Use `--tsv` only if you must parse/dedupe/sort. + +## Actions policy (optimized for conversational speed) + +This skill is designed for personal assistant use where the user expects fast, low-friction calendar management. The confirmation policy below is an intentional UX choice — see README.md for rationale and safety guards. + +### Unambiguous actions: execute immediately +For cancel/delete/edit actions, skip confirmation when ALL of these hold: +- The user explicitly requested the action (e.g. "delete my dentist appointment"). +- Exactly one event matches in a tight time window. +- The match is unambiguous (single clear result on an exact date, or user specified date+time). + +### Ambiguous actions: always ask first +If multiple candidates match, or the match is uncertain: +- Ask a short disambiguation question listing the candidates (1-3 lines) and wait for the user's choice. + +### Create events: overlap check MUST be cross-calendar (non-ignored scope) +When creating an event: +- Always run a best-effort overlap check across ALL non-ignored calendars by scanning agenda WITHOUT `--calendar`. + - This ensures overlaps are detected even if the new event is created into a specific calendar. +- If overlap exists with busy events: + - Ask for confirmation before creating. +- If no overlap: + - Create immediately. + +### Choose the right create method +- **`add`** — default for one-off events. Supports `--allday`, `--reminder`, `--noprompt`. Does NOT support recurrence or free/busy (transparency). +- **`import` via stdin** — use ONLY when you need recurrence (RRULE) or free/busy (TRANSP:TRANSPARENT). Pipe ICS content via stdin; NEVER write temp .ics files (working directory is unreliable in exec sandbox). +- **`quick`** — avoid unless user explicitly asks for natural-language add. Less deterministic. + +### Deletes must be verified +- Use non-interactive delete with `--iamaexpert` (a `delete` subcommand flag — goes AFTER `delete`). This is gcalcli's built-in flag for non-interactive/scripted deletion. +- Always verify via agenda in the same tight window after deletion. +- If verification still shows the event, do one retry with `--refresh`. +- Never claim success unless verification confirms the event is gone. + +## Canonical commands + +### Agenda (deterministic listing) +- Today: `gcalcli --nocolor agenda today tomorrow` +- Next 14d (weekday resolution): `gcalcli --nocolor agenda today +14d` +- Next 30d (meaning-first locate): `gcalcli --nocolor agenda today +30d` +- Custom: `gcalcli --nocolor agenda ` + +### Search (fallback / explicit request) +- Default (~6 months): `gcalcli --nocolor search "" today +180d` +- Custom: `gcalcli --nocolor search "" ` + +### Create — `add` (one-off events) +- Overlap preflight (tight, cross-calendar): + - `gcalcli --nocolor agenda ` + - IMPORTANT: do NOT add `--calendar` here; overlaps must be checked across all non-ignored calendars. +- Timed event: + - `gcalcli --nocolor --calendar "" add --noprompt --title "" --when "<Start>" --duration <minutes>` +- All-day event: + - `gcalcli --nocolor --calendar "<Cal>" add --noprompt --allday --title "<Title>" --when "<Date>"` +- With reminders (repeatable flag): + - `--reminder "20160 popup"` → 14 days before (20160 = 14×24×60) + - `--reminder "10080 popup"` → 7 days before + - `--reminder "0 popup"` → at event start + - Time unit suffixes: `w` (weeks), `d` (days), `h` (hours), `m` (minutes). No suffix = minutes. + - Method: `popup` (default), `email`, `sms`. + +### Create — `import` via stdin (recurrence / free/busy) +Use ONLY when `add` can't cover the need (recurring events, TRANSP, etc.). +Pipe ICS directly via stdin — never write temp files. +``` +echo 'BEGIN:VCALENDAR +VERSION:2.0 +BEGIN:VEVENT +DTSTART;VALUE=DATE:20260308 +SUMMARY:Event Title +RRULE:FREQ=YEARLY +TRANSP:TRANSPARENT +END:VEVENT +END:VCALENDAR' | gcalcli import --calendar "<Cal>" +``` +- `DTSTART;VALUE=DATE:YYYYMMDD` for all-day; `DTSTART:YYYYMMDDTHHmmSS` for timed. +- `RRULE:FREQ=YEARLY` — yearly recurrence. Also: `DAILY`, `WEEKLY`, `MONTHLY`. +- `TRANSP:TRANSPARENT` — free; `TRANSP:OPAQUE` — busy (default). +- One import call = one event (one VEVENT block). For multiple events, run separate piped imports. +- Add `--reminder "TIME"` flag(s) to set reminders (overrides any VALARM in ICS). +- All import-specific flags (`--use-legacy-import`, `--verbose`, etc.) go AFTER `import`. + +### Delete (with post-delete verification) +- Locate via agenda (preferred): + - `gcalcli --nocolor agenda <dayStart> <dayEnd>` (exact date) + - `gcalcli --nocolor agenda today +14d` (weekday) + - `gcalcli --nocolor agenda today +30d` (meaning only) +- Delete (non-interactive, bounded): + - `gcalcli --nocolor delete --iamaexpert "<query>" <start> <end>` +- Verify (same window): + - `gcalcli --nocolor agenda <dayStart> <dayEnd>` +- Optional one retry if still present: + - `gcalcli --nocolor --refresh agenda <dayStart> <dayEnd>` + +### Edit / Modify existing events +- `gcalcli edit` is interactive — cannot be used in non-interactive exec. +- To change properties not editable in-place: **delete + recreate** the event. + - Locate → delete (with `--iamaexpert`) → create with updated properties → verify. +- For bulk property changes (e.g. setting all events to free): iterate delete+recreate per event. diff --git a/_meta.json b/_meta.json new file mode 100644 index 0000000..7ae5aec --- /dev/null +++ b/_meta.json @@ -0,0 +1,6 @@ +{ + "ownerId": "kn757ghzsay7zhsft6rb14jhwn80d28q", + "slug": "gcalcli-calendar", + "version": "3.0.0", + "publishedAt": 1770939510320 +} \ No newline at end of file