Voice-powered Google Tasks management for OpenHome. Add tasks, check what's due, mark things done, get daily summaries, and switch between task lists — all by voice. Uses OAuth 2.0 for secure authentication with your Google account.
| Mode | Example Voice Commands | Description |
|---|---|---|
| Add Task | "Add a task: call the dentist by Friday" / "Remind me to buy groceries tomorrow" | Creates a task with optional due date and notes |
| List Tasks | "What's due today?" / "What's on my list?" / "Any overdue tasks?" | Lists tasks with date filtering (today, this week, overdue, all) |
| Complete Task | "Mark call the dentist done" / "Complete task 2" / "Mark the first one done" | Completes a task by name, number, or position |
| Daily Summary | "Task summary" / "How's my day?" | Overview of overdue, today, upcoming, and undated tasks |
| Switch List | "Switch to Work list" / "What lists do I have?" | View and switch between Google Tasks lists |
You need a Google Cloud project with the Tasks API enabled. This is a one-time setup (~5 minutes).
- Go to Google Cloud Console
- Click the project dropdown (top-left) → New Project
- Name it (e.g.,
OpenHome Tasks) → click Create - Select the new project from the dropdown
- In the left sidebar, go to APIs & Services → Library
- Search for "Tasks API" (by Google — NOT "Cloud Tasks API")
- Click it → click Enable
- Go to APIs & Services → OAuth consent screen (or Google Auth Platform → Audience in the new UI)
- Select External → click Create
- Fill in:
- App name:
OpenHome Tasks - User support email:
yourname@gmail.com - Developer contact email:
yourname@gmail.com
- App name:
- Click Save and Continue
- On the Scopes page → click Add or Remove Scopes → paste
https://www.googleapis.com/auth/tasks→ click Update → Save and Continue - On the Test users page → click Add Users → add your Gmail address → click Add → Save and Continue
- Go to APIs & Services → Credentials (or Google Auth Platform → Clients)
- Click + CREATE CREDENTIALS → OAuth client ID
- Application type: Web application
- Name:
OpenHome Tasks Web - Under Authorized redirect URIs → click + ADD URI → paste:
https://developers.google.com/oauthplayground - Click Create
- Copy the Client ID (looks like
123456789-xxxxxx.apps.googleusercontent.com) - Copy the Client Secret (looks like
GOCSPX-xxxxxx)
- Go to Google OAuth 2.0 Playground
- Click the gear icon ⚙️ (top right) → check "Use your own OAuth credentials"
- Paste your Client ID and Client Secret from steps 20-21
- Close the settings panel
- In the left panel, in the "Input your own scopes" box, type:
https://www.googleapis.com/auth/tasks - Click "Authorize APIs"
- Sign in with your Google account → click Continue → click Continue again
- Back at the Playground, click "Exchange authorization code for tokens"
- In the response on the right, copy the
refresh_tokenvalue (starts with1//)
Open main.py and replace the placeholder values at the top with all three values:
GOOGLE_CLIENT_ID = "123456789-xxxxxx.apps.googleusercontent.com"
GOOGLE_CLIENT_SECRET = "GOCSPX-xxxxxx"
GOOGLE_REFRESH_TOKEN = "1//xxxxxx"With all three pre-filled, the ability skips OAuth entirely and connects immediately.
Alternative options:
- Pre-fill credentials only: Fill just
GOOGLE_CLIENT_IDandGOOGLE_CLIENT_SECRET. On first use, the ability will guide you through getting a refresh token via OAuth Playground by voice. - Voice-guided setup: Leave all placeholders as-is. On first use, the ability will ask for everything by voice.
- Go to the Customize Ability page
- Upload all 3 files:
main.py,__init__.py,README.md - Fill in:
- Unique Name:
google_tasks - Description: Voice-powered Google Tasks management
- Hotwords: task, tasks, to do, todo, add a task, new task, remind me, my tasks, what's due, task list, mark done, complete task, check off, task summary, daily tasks, overdue, switch list, google tasks, what do I need to do, finish task
- Unique Name:
- Click Start Live Test
If you pre-filled all three constants (Option A), the ability connects automatically — no authorization step needed.
Otherwise, on first use:
- Say "my tasks" to trigger the ability
- The ability will try the device flow first (enter a short code at google.com/device)
- If that fails, it falls back to OAuth Playground: it will ask you to get a refresh token from developers.google.com/oauthplayground and paste it in
- The ability saves your tokens and auto-refreshes them going forward
OAuth & Connection:
| # | Say | Expected |
|---|---|---|
| 1 | "my tasks" | Triggers OAuth setup on first run, or goes straight to tasks if already connected |
| 2 | (after connecting) "my tasks" again | Should NOT re-do OAuth — goes straight to tasks |
Add Tasks:
| # | Say | Expected |
|---|---|---|
| 3 | "add a task call the dentist by Friday" | Creates task with due date |
| 4 | "remind me to buy groceries tomorrow" | Creates task due tomorrow |
| 5 | "new task submit report" | Creates task with no due date |
| 6 | "add a task" (no details) | Asks "What's the task?" → then you provide details |
List Tasks:
| # | Say | Expected |
|---|---|---|
| 7 | "what's due today?" | Lists tasks due today |
| 8 | "what's due this week?" | Lists tasks due this week |
| 9 | "what's on my list?" | Lists all incomplete tasks |
| 10 | "any overdue tasks?" | Lists overdue tasks |
Complete Tasks:
| # | Say | Expected |
|---|---|---|
| 11 | "mark the first one done" | Completes 1st task from last listing |
| 12 | "complete task 2" | Completes 2nd task from last listing |
| 13 | "mark call the dentist done" | Fuzzy matches task by name |
| 14 | "complete something random xyz" | "I couldn't find a task matching that..." |
Daily Summary:
| # | Say | Expected |
|---|---|---|
| 15 | "task summary" | Summary with overdue/today/upcoming/undated counts |
| 16 | "how's my day?" | Same summary in natural language |
Switch Lists:
| # | Say | Expected |
|---|---|---|
| 17 | "what lists do I have?" | Shows all task lists |
| 18 | "switch to Work" | Switches active list (if you have one) |
| 19 | "switch to My Tasks" | Switches back to default list |
Follow-up & Exit:
| # | Say | Expected |
|---|---|---|
| 20 | (after any action, wait for "Anything else?") | Ability stays active for follow-up |
| 21 | "add a task water the plants" | Works in follow-up without re-triggering |
| 22 | "done" or "stop" | Exits ability cleanly |
Voice trigger → run() → load prefs → check OAuth
→ If no refresh_token → handle_oauth_setup() (device flow → OAuth Playground fallback)
→ If connected → _ensure_valid_token() (auto-refresh)
→ Classify intent via LLM → Route to handler
→ Execute handler → Speak result
→ Follow-up loop ("Anything else?")
→ User says "done" → resume_normal_flow()
- Token refresh: Automatic before every API call. If token has <60s left, it refreshes. On 401, it retries once.
- Fuzzy matching: 3 layers — substring match →
difflib.SequenceMatcher→ LLM fallback. Handles "dentist" matching "call the dentist". - Date parsing: LLM converts natural language ("by Friday", "next Tuesday") to RFC 3339 dates with timezone awareness.
- Task caching: After listing tasks, results are cached so "mark the first one done" works without re-fetching.
- Timezone: Auto-detected from IP on first run, stored in prefs.
- Persistence: All prefs stored via
capability_worker.write_file()— no rawopen()calls.
- Testing mode: If your Google Cloud app is in "Testing" status, refresh tokens expire after 7 days. You'll need to re-authorize. To avoid this, publish your app (requires Google review).
- Date only: Google Tasks only stores dates, not times. "By 3pm Friday" → saved as "Friday".
- No server-side search: Google Tasks API has no search endpoint. The ability fetches tasks and matches locally using fuzzy matching.
- Rate limits: Google Tasks API allows 50,000 requests/day per project.
task, tasks, to do, todo, add a task, new task, remind me, my tasks, what's due, task list, mark done, complete task, check off, task summary, daily tasks, overdue, switch list, google tasks, what do I need to do, finish task