Google Calendar Sync
Duet can sync todos with due dates to Google Calendar, giving you a unified view of your schedule. Agent-created events are automatically flagged so you know where they came from.
Features
- Two-way sync - changes in Duet update your calendar, and vice versa.
- Agent-created events flagged - events created by agents are labeled so you can distinguish them from your own.
- Automatic sync - whenever a todo with a due date is created or updated, the calendar syncs automatically.
- Manual sync - trigger a sync at any time from settings or via the API.
Step 1: Create a Google Cloud Project
- Go to the Google Cloud Console.
- Click Select a project at the top, then New Project.
- Name it something like "Duet Calendar" and click Create.
- Select your new project from the project picker.
Step 2: Enable the Google Calendar API
- In the Cloud Console, go to APIs & Services > Library.
- Search for Google Calendar API.
- Click on it and press Enable.
Step 3: Create OAuth 2.0 Credentials
- Go to APIs & Services > Credentials.
- Click Create Credentials > OAuth client ID.
- If prompted, configure the OAuth consent screen first:
- User Type: External (or Internal if using Google Workspace)
- Fill in the required fields (app name, support email)
- Add the scope:
https://www.googleapis.com/auth/calendar - Add your email as a test user
- For Application type, select Web application.
- Name it "Duet".
- Under Authorized redirect URIs, add your callback URL:
# For local development:
http://localhost:7777/api/calendar/callback
# For production (replace with your domain):
https://your-domain.com/api/calendar/callback- Click Create and note down your Client ID and Client Secret.
Step 4: Configure Environment Variables
Add the OAuth credentials to your Duet environment:
# In your .env file or environment:
GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-client-secretIf you're using Docker, add these to your .env file. If deployed to Fly.io, use fly secrets set.
# Fly.io
fly secrets set GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
fly secrets set GOOGLE_CLIENT_SECRET=your-client-secretStep 5: Connect in Duet
- Open Duet in your browser.
- Go to Settings.
- In the Google Calendar section, click Connect Google Calendar.
- You'll be redirected to Google to authorize access.
- Grant Duet permission to manage your calendar events.
- You'll be redirected back to Duet. The connection status should show as connected.
How Sync Works
- When you create or update a todo with a due date, a corresponding calendar event is created or updated automatically.
- When you mark a todo as done, the calendar event is updated to reflect completion.
- Events created by agents include an [Agent] prefix in the event title so they stand out.
- Deleting a todo removes its associated calendar event.
API Endpoints
You can also manage the calendar integration via the API:
| Endpoint | Description |
|---|---|
| GET /api/calendar/auth-url | Get the OAuth authorization URL |
| GET /api/calendar/callback | OAuth callback (redirect target) |
| GET /api/calendar/status | Check if calendar is connected |
| POST /api/calendar/sync | Trigger a manual sync |
| POST /api/calendar/disconnect | Disconnect Google Calendar |
# Check connection status
curl http://localhost:7777/api/calendar/status -b cookies.txt
# Trigger a manual sync
curl -X POST http://localhost:7777/api/calendar/sync -b cookies.txtTroubleshooting
- OAuth error: redirect_uri_mismatch - make sure the redirect URI in your Google Cloud Console exactly matches your Duet callback URL, including the protocol and port.
- Events not appearing - verify the todo has a due date set. Only todos with due dates are synced to the calendar.
- Token expired - Duet automatically refreshes OAuth tokens. If issues persist, disconnect and reconnect the calendar from Settings.
- Test user restriction - if your OAuth consent screen is in "Testing" mode, only users added as test users can authorize the app. Add your Google account as a test user or publish the app.