Skip to content

GraysonCAdams/todoist-bridge

Todoist Bridge

Unified task synchronization from Google Tasks, Alexa, and Microsoft To-Do to Todoist

Build Status Container Registry License Node Version TypeScript


Table of Contents


About

Todoist Bridge is a Node.js daemon that synchronizes tasks between multiple platforms and Todoist. It runs as a background service, polling your task sources at configurable intervals and automatically creating, updating, and completing tasks.

Supported Sources

You can use any combination of the following sources:

Source Sync Direction Description
Google Tasks One-way → Todoist Sync task lists from Google Tasks
Alexa Reminders One-way → Todoist Sync reminders from Alexa devices
Alexa Shopping List One-way → Todoist Sync your Alexa shopping list
Microsoft To-Do Bi-directional ↔ Todoist Two-way sync with Microsoft To-Do lists

Enable only what you need - each source is independently configurable.

Why Todoist Bridge?

  • Centralize your tasks: Consolidate tasks from multiple sources into Todoist
  • Modular sources: Use Google Tasks, Alexa, or both - your choice
  • Hands-free operation: Set it up once and forget about it
  • Flexible mapping: Map specific lists to specific projects with custom tags
  • Self-hosted: Your data stays on your infrastructure

Features

Feature Description
Google Tasks Sync Full sync of tasks including subtasks, due dates, and descriptions
Alexa Reminders Sync reminders from all Alexa devices to Todoist
Alexa Shopping List Keep your shopping list in sync
Microsoft To-Do Sync Bi-directional sync with Microsoft To-Do (great for shared lists)
Completion Sync Complete tasks on either platform, syncs to the other
Shared List Support Filter shared Microsoft lists to only sync your items
Custom Tags Apply labels to synced tasks for easy filtering
Flexible Mapping Map any source list to any Todoist project or Inbox
Subtask Support Single-level subtask hierarchy preserved
Completed Tasks Optional retroactive import of completed tasks
Delete After Sync Optionally remove tasks from source after syncing
Conflict Resolution Last-write-wins for bi-directional sync conflicts
SQLite State Reliable change detection with local database
Graceful Shutdown Clean handling of SIGTERM/SIGINT signals

Quick Start

Using Docker

# Pull the image
docker pull ghcr.io/graysoncadams/todoist-bridge:latest

# Create directories
mkdir -p ./data ./credentials

# Create config file (see Configuration section)
cp config.example.yaml config.yaml
# Edit config.yaml with your settings

# Run the container
docker run -d \
  --name todoist-bridge \
  -v $(pwd)/config.yaml:/app/config.yaml:ro \
  -v $(pwd)/credentials:/app/credentials \
  -v $(pwd)/data:/app/data \
  ghcr.io/graysoncadams/todoist-bridge:latest

Installation

Docker (Recommended)

Docker provides the simplest deployment path with automatic updates and isolation.

docker pull ghcr.io/graysoncadams/todoist-bridge:latest

See Docker Compose for a complete example.

Docker Compose

Create a docker-compose.yml:

services:
  todoist-bridge:
    image: ghcr.io/graysoncadams/todoist-bridge:latest
    container_name: todoist-bridge
    restart: unless-stopped
    volumes:
      - ./config.yaml:/app/config.yaml:ro
      - ./credentials:/app/credentials
      - ./data:/app/data
    ports:
      - "3000:3000"  # Google OAuth web form (first run only)
      - "3001:3001"  # Alexa auth proxy (first run only, if using Alexa)
    environment:
      - LOG_LEVEL=info
      - TZ=America/New_York

Note: Ports are only needed for initial authorization. After tokens/cookies are saved, you can remove the port mappings. For Alexa, also set proxy_host in config.yaml to your Docker host's IP.

Run with:

docker compose up -d
docker compose logs -f

Manual Installation

Requirements:

  • Node.js 20.0.0 or higher
  • npm
# Clone the repository
git clone https://github.com/GraysonCAdams/todoist-bridge.git
cd todoist-bridge

# Install dependencies
npm install

# Build
npm run build

# Configure
cp config.example.yaml config.yaml
# Edit config.yaml

# Run
npm start

For development:

npm run dev

Configuration

Todoist Bridge uses a YAML configuration file with environment variable overrides.

Minimal Configuration

Choose one or more sources to sync. Each source can be enabled or disabled independently.

Google Tasks only:

todoist:
  api_token: "your-todoist-api-token"

sources:
  google:
    enabled: true
    lists:
      - source_list_id: "YOUR_GOOGLE_LIST_ID"
        todoist_project_id: "YOUR_TODOIST_PROJECT_ID"
  alexa:
    enabled: false

Alexa only:

todoist:
  api_token: "your-todoist-api-token"

sources:
  google:
    enabled: false
  alexa:
    enabled: true
    amazon_page: "amazon.com"
    lists:
      - source_list_id: "all"
        todoist_project_id: "YOUR_TODOIST_PROJECT_ID"

Both sources:

todoist:
  api_token: "your-todoist-api-token"

sources:
  google:
    enabled: true
    lists:
      - source_list_id: "YOUR_GOOGLE_LIST_ID"
        todoist_project_id: "YOUR_TODOIST_PROJECT_ID"
  alexa:
    enabled: true
    lists:
      - source_list_id: "all"
        todoist_project_id: "YOUR_ALEXA_PROJECT_ID"

Microsoft To-Do (bi-directional):

todoist:
  api_token: "your-todoist-api-token"

sources:
  google:
    enabled: false
  alexa:
    enabled: false
  microsoft:
    enabled: true
    client_id: "your-azure-app-client-id"
    tenant_id: "consumers"  # Use "consumers" for personal Microsoft accounts
    lists:
      - list_name: "Groceries"
        todoist_project_id: "inbox"
        tags: ["grocery"]
    assign_to_self: true               # Set reminders on tasks with due times
    exclude_others_assignments: true   # Ignore items from other users

Full Configuration

# Todoist configuration
todoist:
  api_token: "your-todoist-api-token"

# Sources to sync from
sources:
  # Google Tasks (one-way sync to Todoist)
  google:
    enabled: true
    poll_interval_minutes: 5
    credentials_path: "./credentials/google-credentials.json"
    token_path: "./credentials/google-token.json"
    lists:
      - source_list_id: "abc123"
        todoist_project_id: "456789"  # or "inbox"
        include_completed: false
        delete_after_sync: false
        tags:
          - "google-tasks"

  # Alexa Reminders (one-way sync to Todoist)
  alexa:
    enabled: false
    poll_interval_minutes: 5
    cookie_path: "./credentials/alexa-cookie.json"
    amazon_page: "amazon.com"
    proxy_port: 3001
    proxy_host: "192.168.1.140"  # Your Docker host IP (for external access)
    fail_silently: true
    max_retries: 3
    lists:
      - source_list_id: "all"
        todoist_project_id: "789012"
        tags:
          - "alexa"
    # Shopping list sync
    sync_shopping_list:
      enabled: false
      todoist_project_id: "123456"
      tags:
        - "shopping"

  # Microsoft To-Do (bi-directional sync with Todoist)
  microsoft:
    enabled: false
    client_id: "your-azure-app-client-id"
    tenant_id: "consumers"  # Use "consumers" for personal accounts
    token_path: "./credentials/microsoft-token.json"
    poll_interval_minutes: 3
    lists:
      - list_name: "Groceries"
        todoist_project_id: "inbox"
        tags: ["grocery"]
    assign_to_self: false              # Set reminders on tasks with due times
    exclude_others_assignments: true   # Ignore items from other users

# Global sync settings
sync:
  sync_completed_once: true

# Storage
storage:
  database_path: "./data/sync.db"

# Logging
logging:
  level: "info"  # trace, debug, info, warn, error

Environment Variables

Variable Description Default
TODOIST_API_TOKEN Todoist API token -
DATABASE_PATH SQLite database path ./data/sync.db
POLL_INTERVAL_MINUTES Sync interval 5
LOG_LEVEL Log verbosity info

Usage

First Run Authentication

Google Tasks

Google Cloud Console Setup:

  1. Go to Google Cloud Console
  2. Create a new project or select an existing one
  3. Enable the Google Tasks API
  4. Go to APIs & Services > Credentials
  5. Create OAuth credentials > Desktop app (not "Web application")
  6. Download the credentials JSON
  7. Save as ./credentials/google-credentials.json

Authorization Flow:

On first run, you'll be prompted to authorize with Google:

Interactive mode (CLI/Terminal):

  1. A URL will be printed to the console
  2. Open the URL in your browser
  3. Sign in with your Google account
  4. Grant access to Google Tasks
  5. Google displays an authorization code - copy it
  6. Paste the code in the terminal when prompted
  7. The token is saved for future runs

Docker mode (Non-interactive):

  1. Check the container logs for the Google authorization URL
  2. Open the URL in your browser and authorize
  3. Google displays an authorization code - copy it
  4. Visit http://localhost:3000/auth (or your Docker host)
  5. Paste the authorization code in the web form
  6. The token is saved for future runs

Note: For Docker, ensure port 3000 is exposed for the initial authorization:

ports:
  - "3000:3000"

Alexa (if enabled)

  1. A proxy server starts on the configured port (default: 3001)
  2. Open http://localhost:3001 in your browser (or your Docker host IP)
  3. Sign in with your Amazon account
  4. Cookies are saved for future runs

Note for Docker: When running in Docker, set proxy_host in your config to your Docker host's IP address (e.g., 192.168.1.140) so the authentication redirects work correctly. Also expose the proxy port:

# config.yaml
sources:
  alexa:
    proxy_port: 3001
    proxy_host: "192.168.1.140"  # Your Docker host IP
# docker-compose.yml
ports:
  - "3001:3001"

Microsoft To-Do (if enabled)

Azure App Registration Setup:

  1. Go to Azure Portal > App registrations
  2. Click New registration
  3. Configure the app:
    • Name: Todoist Bridge (or any name you prefer)
    • Supported account types: Select "Personal Microsoft accounts only" (recommended for personal To-Do)
  4. Click Register (leave Redirect URI blank)
  5. Copy the Application (client) ID - you'll need this for config
  6. Go to API permissions > Add a permission:
    • Select Microsoft Graph
    • Choose Delegated permissions
    • Add: Tasks.ReadWrite, User.Read
    • Click Add permissions
  7. Go to Authentication:
    • Under Advanced settings, set Allow public client flows to Yes
    • Click Save

Important: Use tenant_id: "consumers" in your config for personal Microsoft accounts (@outlook.com, @hotmail.com, etc.)

Device Code Authentication Flow:

Microsoft To-Do uses Device Code Flow, which works in any environment (CLI, Docker, headless servers):

  1. On first run, the app displays a message like:
    To sign in, use a web browser to open https://microsoft.com/devicelogin
    and enter the code: ABCD1234
    
  2. Open that URL in any browser (can be on your phone or another computer)
  3. Enter the code shown in your terminal
  4. Sign in with the Microsoft account that has the To-Do lists you want to sync
  5. Grant the requested permissions (Tasks.ReadWrite, User.Read)
  6. Return to your terminal - authentication completes automatically
  7. Token is saved to ./credentials/microsoft-token.json for future runs

Which account gets linked? Whatever Microsoft account you sign into during step 4 is the one that gets linked. This is how you choose which To-Do lists to sync - by signing into the correct account.

Shared Lists: If you're syncing a shared Microsoft To-Do list, sign in with your own account. Enable exclude_others_assignments: true to ignore items added by other users.

Finding IDs

See the Wiki: Finding IDs for detailed instructions on obtaining:

  • Google Task List IDs
  • Todoist Project IDs

Field Mapping

Google Tasks / Alexa → Todoist:

Source Todoist Notes
Title Content Direct mapping
Notes/Description Description Direct mapping
Status is_completed Mapped appropriately
Due Date due_date Date only
Parent parent_id Single level subtasks

Microsoft To-Do ↔ Todoist (bi-directional):

Microsoft To-Do Todoist Notes
title content Syncs both directions
body.content description Syncs both directions
status is_completed Completion syncs both ways
dueDateTime due_date Date and time preserved
importance priority high→P1, normal→P4, low→P4
reminderDateTime (via due) Mapped to Todoist due time

Architecture

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│  Google Tasks   │     │  Alexa Skills   │     │ Microsoft To-Do │
│      API        │     │      API        │     │   Graph API     │
└────────┬────────┘     └────────┬────────┘     └────────┬────────┘
         │                       │                       │
         │ (one-way)             │ (one-way)             │ (bi-directional)
         │                       │                       ↕
         └───────────────────────┼───────────────────────┘
                                 │
                          ┌──────▼──────┐
                          │   Todoist   │
                          │   Bridge    │
                          └──────┬──────┘
                                 │
                          ┌──────▼──────┐
                          │   SQLite    │
                          │  State DB   │
                          └──────┬──────┘
                                 │
                          ┌──────▼──────┐
                          │   Todoist   │
                          │     API     │
                          └─────────────┘

Components

Component Description
src/index.ts Main entry point and daemon loop
src/config.ts Configuration loading and validation
src/storage.ts SQLite state management
src/auth/ Authentication for Google, Todoist, Alexa
src/clients/ API client wrappers
src/sources/google/ Google Tasks source (one-way)
src/sources/alexa/ Alexa source (one-way)
src/sources/microsoft/ Microsoft To-Do source (bi-directional)
src/utils/ Logger and retry utilities

Wiki

Detailed documentation is available in the Wiki:


Contributing

Contributions are welcome. Please open an issue to discuss proposed changes before submitting a pull request.

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/improvement)
  3. Commit your changes (git commit -am 'Add improvement')
  4. Push to the branch (git push origin feature/improvement)
  5. Open a Pull Request

Credits

Todoist Bridge is built on the work of these projects:

Project Description License
googleapis Google APIs Node.js Client Apache-2.0
todoist-api-typescript Official Todoist TypeScript SDK MIT
alexa-remote2 Alexa Remote Control MIT
@azure/msal-node Microsoft Authentication Library MIT

License

This project is licensed under the MIT License. See LICENSE for details.

MIT License

Copyright (c) 2024

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

About

Unified task synchronization from Google Tasks and Alexa to Todoist

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

Packages

 
 
 

Contributors 2

  •  
  •  

Languages