This script migrates your tasks and projects from Things 3 (macOS application) to Google Tasks. It reads data directly from the Things 3 SQLite database and uses the Google Tasks API to create corresponding task lists, tasks, and subtasks.
- Migrates Things Areas to new Google Task Lists.
- Migrates Things Projects to Google Tasks (as main tasks within their respective Area's list).
- Migrates tasks within Things Projects (including those under Headings) as subtasks in Google Tasks.
- Things Headings are represented as placeholder subtasks under their project task in Google Tasks, with actual tasks under that heading becoming subtasks of the placeholder.
- Option to perform a "clean slate" migration by deleting all pre-existing Google Tasks data (task lists and tasks) before starting.
- Flexible configuration via command-line arguments or a
config.pyfile. - Includes a suite of unit tests to verify functionality.
- Python 3.7+
- Access to your Things 3 database file. This script is intended to be run on a macOS machine where Things 3 is installed.
- A Google account.
1. Clone the Repository:
git clone https://github.com/your-username/things-to-google-tasks.git # Replace with actual URL
cd things-to-google-tasks2. Create a Virtual Environment (Recommended):
python3 -m venv venv
source venv/bin/activate # On Windows use: venv\Scripts\activate3. Install Dependencies:
pip install -r requirements.txt4. Set up Google API Credentials:
- Go to the Google Cloud Console.
- Create a new project or select an existing one.
- In the navigation menu, go to "APIs & Services" -> "Library".
- Search for "Google Tasks API" and enable it for your project.
- Go to "APIs & Services" -> "Credentials".
- Click "+ CREATE CREDENTIALS" -> "OAuth client ID".
- For "Application type", select "Desktop app".
- Give the client ID a name (e.g., "Things Migration Script").
- Click "Create". You will see your client ID and client secret.
- Click "DOWNLOAD JSON" to download the client secrets file.
- Rename this downloaded file to
credentials.jsonand place it in the root directory of this project. Alternatively, you can specify a different path using command-line arguments or theconfig.pyfile. - Authorization: The first time you run the migration script, it will attempt to open a new tab in your web browser to ask you to authorize access to your Google Tasks. After successful authorization, a
token.jsonfile will be created in the project's root directory. This file stores your OAuth 2.0 tokens, so you won't need to re-authorize every time you run the script. Keep this file secure.
5. Configure Things Database Path:
- The script needs access to your Things 3 SQLite database file. The typical path on macOS is:
~/Library/Group Containers/JLMPQHK86H.com.culturedcode.ThingsMac/Things Database/main.sqlite - You can provide this path to the script in one of two ways:
- Via
config.py(Recommended): Copy the template file:Editcp config.py.template config.py
config.pyand set theTHINGS_DB_PATHvariable to the correct path of yourmain.sqlitefile. You can also setGOOGLE_API_CREDENTIALS_PATHin this file if your credentials JSON is not namedcredentials.jsonor is not in the project root. - Via Command-Line Argument:
Use the
--db-pathargument when running the script (see below).
- Via
Ensure your virtual environment is activated if you created one.
Using config.py (Recommended):
- Make sure you have created
config.pyfromconfig.py.templateand correctly setTHINGS_DB_PATH(andGOOGLE_API_CREDENTIALS_PATHif needed). - Run the script:
python src/things_to_google_tasks.py --config-file config.py
Using Command-Line Arguments:
python src/things_to_google_tasks.py --db-path "/Users/yourusername/Library/Group Containers/JLMPQHK86H.com.culturedcode.ThingsMac/Things Database/main.sqlite" --creds-path "credentials.json"(Replace paths with your actual paths.)
Clean Slate Option:
To delete all existing Google Task Lists and Tasks from your Google account before migrating your Things data, use the --clean-slate flag. Warning: This is irreversible.
python src/things_to_google_tasks.py --config-file config.py --clean-slateOr with direct arguments:
python src/things_to_google_tasks.py --db-path "/path/to/your/main.sqlite" --creds-path "credentials.json" --clean-slateYou will be prompted for confirmation before any data is deleted.
To run the included unit tests to ensure the script's components are working correctly:
python -m unittest discover -s tests -p "test_*.py"This command should be run from the root directory of the project.
src/: Contains the main Python source code.things_reader.py: Handles reading data from the Things 3 database.google_tasks_client.py: Manages interactions with the Google Tasks API, including authentication.things_to_google_tasks.py: The main executable script that orchestrates the migration.
tests/: Contains unit tests for the modules insrc/.test_things_reader.pytest_google_tasks_client.pytest_migration_logic.py
requirements.txt: Lists the Python dependencies required for the project.config.py.template: A template for the configuration file. Copy this toconfig.pyto set your database path and (optionally) credentials path.credentials.json: (You create this) Your Google API OAuth 2.0 client secrets.token.json: (Created after first run) Stores your Google API OAuth 2.0 access and refresh tokens.README.md: This file.
- Database Lock: It's recommended to close the Things 3 application before running the migration script. This helps prevent potential issues with database locking, which might cause the script to fail to read the Things data.
- Google Tasks API Limits: The Google Tasks API has usage limits (e.g., rate limits on requests). For users with extremely large Things databases (many thousands of tasks and projects), the script might take a significant amount of time to complete or could potentially hit these limits. Currently, the script does not support batching or advanced rate limit handling beyond what the Google client libraries provide.
- First Run Authorization: Remember that on the first run, your web browser will open to ask for permission to access your Google Tasks. You need to grant this permission for the script to work.
- Standalone Tasks: Tasks in Things that are not part of any project will be migrated to a Google Task List corresponding to their Area. If a standalone task has no Area, it will be placed in a default list named "Things Imported Tasks".
- Idempotency:
- Creating Google Task Lists for Areas is idempotent (it checks for existing lists by title).
- Task migration is not fully idempotent. Running the script multiple times without the
--clean-slateoption will likely result in duplicate tasks being created in Google Tasks. If you need to re-run the migration, using--clean-slateis recommended for a fresh start.
Please replace <repository_url> and https://github.com/your-username/things-to-google-tasks.git with the actual URL of your repository if you plan to host it.