flake-update-20260505
..
rw-r--r--
5.4 KB
rw-r--r--
323 B
rw-r--r--
61 B
rw-r--r--
9.3 KB

gcal-to-org

One-way sync from Google Calendar to org-mode file.

Features

  • One-way sync: Google Calendar → org-mode only (read-only, no modifications to Google Calendar)
  • Separate file: Generates ~/desktop/org/calendar.org which is easily regenerated
  • Automatic cleanup: Keeps only events from 2 weeks ago onward (configurable)
  • Works with gcalcli: Uses your existing gcalcli setup and authentication
  • Automatic categorization: Events are automatically categorized as “personal” or “work” based on their source calendar
  • Smart filtering: Only includes events you’ve accepted or marked as “maybe” (declined events are excluded)

Usage

Basic usage

# Sync default calendars to default file
gcal-to-org

# This generates ~/desktop/org/calendar.org with:
# - Events from 2 weeks ago to 4 weeks forward
# - Personal and work calendars

Custom configuration

# Sync specific calendars
gcal-to-org --calendar "My Calendar" --calendar "Work Calendar"

# Custom date range
gcal-to-org --days-back 7 --days-forward 14

# Custom output file
gcal-to-org --output ~/my-calendar.org

# Combine options
gcal-to-org \
  --calendar "Vincent Demeester (personal)" \
  --days-back 14 \
  --days-forward 28 \
  --output ~/desktop/org/calendar.org

Configuration

Default settings

  • Calendars:
  • Output file: ~/desktop/org/calendar.org
  • Date range: 14 days back to 28 days forward

Changing defaults

Edit the constants in main.go:

var (
    defaultCalendars = []string{
        "Vincent Demeester (personal)",
        "vdemeest@redhat.com",
    }
)

const (
    defaultDaysBack    = 14
    defaultDaysForward = 28
)

Automation

If using NixOS with home-manager, add to your home configuration:

{
  imports = [
    ../../home/common/services/gcal-to-org.nix
  ];

  services.gcal-to-org = {
    enable = true;
    interval = "hourly"; # Can be "hourly", "daily", or any systemd timer format
  };
}

This will automatically:

  • Create a systemd service to run gcal-to-org
  • Create a systemd timer to run it on your chosen schedule
  • Start the timer on login

Check timer status:

systemctl --user list-timers gcal-to-org
systemctl --user status gcal-to-org.service

Manual systemd timer

Create ~/.config/systemd/user/gcal-sync.service:

[Unit]
Description=Sync Google Calendar to org-mode

[Service]
Type=oneshot
ExecStart=%h/.nix-profile/bin/gcal-to-org

Create ~/.config/systemd/user/gcal-sync.timer:

[Unit]
Description=Sync Google Calendar every hour

[Timer]
OnCalendar=hourly
Persistent=true

[Install]
WantedBy=timers.target

Enable and start:

systemctl --user enable --now gcal-sync.timer
systemctl --user status gcal-sync.timer

Cron

# Add to crontab -e
0 * * * * /path/to/gcal-to-org

Output format

The generated org file includes:

#+TITLE: Google Calendar Sync
#+DESCRIPTION: Auto-generated from Google Calendar (one-way sync)
#+STARTUP: overview
#+CATEGORY: calendar
#+FILETAGS: :calendar:gcal:

This file is automatically generated from Google Calendar.
DO NOT EDIT MANUALLY - changes will be overwritten.

* 2026-01-14 Wednesday

* Meeting with team
:PROPERTIES:
:CATEGORY: work
:END:
<2026-01-14 Wed 09:00-10:00>

* All-day event
:PROPERTIES:
:CATEGORY: personal
:END:
<2026-01-14 Wed>

* Multi-day conference
:PROPERTIES:
:CATEGORY: work
:END:
<2026-01-14 Wed>--<2026-01-16 Fri>

Event Categorization

Events are automatically categorized based on their source calendar:

  • Work: Calendars containing “redhat”, “work”, or “vdemeest@redhat” are tagged with CATEGORY: work
  • Personal: All other calendars are tagged with CATEGORY: personal

This allows you to:

  • Filter events by category in org-agenda views
  • Color-code events based on category
  • Create separate agenda views for personal vs work events

Building

# Build with Nix
nix build .#gcal-to-org

# Or build with Go
cd tools/gcal-to-org
go build

Troubleshooting

Authentication errors

Make sure gcalcli is set up and authenticated:

gcalcli list

If this fails, run:

gcalcli init

Missing calendars

List available calendars:

gcalcli list

Then use the exact calendar names with --calendar flag.

Parsing errors

If you encounter TSV parsing errors, this is likely due to special characters in event titles. The tool uses LazyQuotes mode to handle most cases, but if issues persist, try filtering specific calendars with --calendar.

Integration with org-mode

To use the calendar in your agenda views, add to your Emacs config:

;; Add calendar.org to agenda files
(add-to-list 'org-agenda-files "~/desktop/org/calendar.org")

;; Optional: exclude from refile targets (read-only)
(setq org-refile-targets
      '((org-agenda-files :maxlevel . 3)))

;; Optional: Color-code categories in agenda
(setq org-agenda-category-icon-alist
      '(("work" "💼" nil nil :ascent center)
        ("personal" "🏠" nil nil :ascent center)))

;; Optional: Create custom agenda views by category
(setq org-agenda-custom-commands
      '(("w" "Work events" agenda ""
         ((org-agenda-category-filter-preset '("+work"))))
        ("p" "Personal events" agenda ""
         ((org-agenda-category-filter-preset '("+personal"))))))

License

Apache 2.0