Maggie Wang59 downloadsInsert a day's Google Calendar schedule (via gcloud credentials) into notes, e.g. from a Templater daily-note template.
☕ Enjoying GCal Daily? If it saves you a few minutes each morning, you can buy me a coffee 💛 It keeps me building and fixing things 🛠️✨
Insert a day's calendar schedule into a note. It's designed for daily notes: drop one line into your Templater daily-note template and each new note starts with that day's events.
Calendars can come from two kinds of source, and you can mix them:
.ics link from Google Calendar, Outlook / Microsoft 365, iCloud, Fastmail and so on. No sign-in, no Google Cloud project.gcloud credentials. See Advanced: Google Calendar API.The schedule is fetched once, when you insert it. It doesn't sync, so the note won't change if your calendar changes later.
A bullet list (default) or a table, merged from as many calendars as you configure:
**All day:** Company offsite (3 Nov – 5 Nov)
- **09:00–09:30** Team stand-up ✅ · [Meet](https://meet.google.com/abc-defg-hij)
- **12:00–13:00** 🏠 Lunch with Sam
- **14:00–15:00** ~~Quarterly planning~~ ❌ · Room 4
<small>Fetched 2026-10-30 08:55 · 🏠 personal · ❌ declined</small>
The output looks the same whichever source an event came from.
.ics) link (see Finding your feed URL).https://calendar.google.com/calendar/ical/…/basic.ics, 🏠, personal
webcal://example.com/…/rota.ics, 🔄, rota
webcal:// links are fine; they're fetched over https://.That's it. With only feed URLs, the Credentials file and Quota project settings are ignored, and you don't need gcloud or a Google Cloud project.
Before you paste a link, read Privacy & security. A private feed URL works like a password for that calendar.
These menus change from time to time, so treat the paths as rough directions.
https://calendar.google.com/calendar/ical/you%40gmail.com/private-<long code>/basic.ics
Two look-alike links on the same page won't work:…/public/basic.ics) returns HTTP 404 unless the calendar is public.…/calendar/embed?src=…) is a web page, not a feed, and returns HTTP 401.webcal:// link. Note that this makes the calendar public to anyone with the link.Work accounts: Google Workspace and Microsoft 365 admins can turn off secret or published calendar addresses, so the option may be missing. Even where it's available, check your organisation's policy before exporting a work calendar through a link.
From a Templater daily-note template. Add this where you want the schedule to appear:
<%* tR += await app.plugins.plugins["gcal-daily"].scheduleMarkdown(tp.file.title) %>
The date is read from the note title. Any YYYY-MM-DD in the title works, e.g. 2026-10-30 or 2026-10-30, Friday. If the title has no date, the plugin uses today.
From the command palette. Run GCal Daily: Insert schedule for this note's date to insert the schedule at the cursor. This works well for filling in older notes, or for retrying after a failed fetch.
If a fetch fails, the plugin inserts a warning callout instead of the schedule. The callout says what went wrong and how to retry, so creating the note still succeeds. Feed errors name the calendar by its label (or the feed's host name), never by its URL.
| Setting | Description | Default |
|---|---|---|
| Format | Bullet list or table. | Bullet list |
| Credentials file | Google calendar IDs only. The file saved by gcloud auth application-default login. |
gcloud's default location: ~/.config/gcloud/application_default_credentials.json, or %APPDATA%\gcloud\… on Windows |
| Quota project | Google calendar IDs only. The Google Cloud project with the Calendar API enabled. | The quota project saved with your credentials |
| Show events Gmail added from emails | Google feeds only. Includes events Gmail creates from emails, such as train tickets and bookings. Off by default to match the Google Calendar API, which leaves them out. | Off |
| Time zone | An IANA time zone name, e.g. Europe/London. Sets which hours count as "the day". |
Your system time zone |
| Calendars | One calendar per line, as calendar, marker, label. The first field is a feed URL or a Google calendar ID. The marker and label are optional. |
primary |
Writing calendar lines:
https://… or webcal://… URL.primary for your main calendar, or a calendar ID (Google Calendar: Settings → (calendar) → Integrate calendar → Calendar ID).https://calendar.google.com/calendar/ical/…/basic.ics, 🏠, personal
https://outlook.office365.com/owa/calendar/…/calendar.ics, 💼, work
The marker (🏠) is added to the start of event titles from that calendar. If a line has both a marker and a label, the pair (e.g. 🏠 personal) is added to the footer legend. Earlier lines win when an event is on several calendars..obsidian/plugins/gcal-daily/data.json, inside your vault. Don't commit that file to a public repository or share it, and think about who can see it if you sync or share your vault.This plugin:
calendar.google.com, outlook.office365.com). Nothing else is sent.https://oauth2.googleapis.com/token), to swap your saved credentials for a short-lived access token, and the Google Calendar API (https://www.googleapis.com/calendar/v3), to read the requested day's events. With only feed URLs, neither is contacted.data.json inside your vault.Use this if you'd rather not create feed URLs, or want to read Google calendars by ID. It needs more setup.
gcloud). It's only used once, to sign in. The plugin never runs it.gcloud auth application-default login \
--scopes=https://www.googleapis.com/auth/calendar.readonly,https://www.googleapis.com/auth/cloud-platform
gcloud auth application-default set-quota-project <project-id>, or enter the project ID in the plugin's Quota project setting.primary for your main calendar, or a calendar ID. You can mix these with feed URLs.gcloud auth application-default login saves (see the Credentials file setting). It reads the refresh token and client ID from that file and sends them only to Google's sign-in endpoint, to get access tokens. The plugin never writes to the file, copies it, or sends it anywhere else.fs is used: Obsidian's vault API can only reach files inside the vault, so the plugin uses Node's fs to read this one file. It makes a single read-only call (readFile), for the path in the Credentials file setting. It doesn't list, write or delete files, or read anything else.gcloud auth application-default login (e.g. for BigQuery) replaces it without the Calendar scope, and fetches then fail with an "insufficient authentication scopes" error. Repeat step 2 to fix it.npm install
npm run build # type-check and bundle to main.js
npm run smoke -- 2026-10-30 # print a day's schedule in the terminal, using data.json if present
The source is in src/. src/calendar.ts handles fetching and rendering, with the two sources in src/ics.ts (feeds) and src/google.ts (Google Calendar API). None of these depend on Obsidian, which is why the smoke test can run them from the terminal.
The plugin bundles ical.js to parse iCal feeds. ical.js is licensed under the Mozilla Public License 2.0 and is included unmodified.
MIT. Not affiliated with Google, Microsoft or Apple.