Skip to content

mbologna/trakt-toggl-sync

Repository files navigation

trakt-toggl-sync

Automatically sync Trakt viewing history to Toggl for complete time tracking

Motivation

I use Toggl for holistic time management—tracking work, projects, and personal activities. However, entertainment time was missing from this picture.

By syncing my Trakt viewing history to Toggl, I now have:

  • Complete time tracking: Work, hobbies, AND entertainment in one place
  • Better insights: Understand actual free time vs. perceived free time
  • Accurate reporting: No gaps in my daily timeline
  • Effortless tracking: No manual entry for movies and TV shows

This bridges productivity tracking with leisure tracking for a truly comprehensive view of my time.

Features

  • ✅ Auto-deduplication (Trakt and Toggl)
  • ✅ Smart syncing with stateful sync log (prevents re-watch duplicates)
  • ✅ Retroactive close-in-time duplicate cleanup (24-hour window)
  • ✅ Automatic token refresh
  • ✅ Graceful rate limit handling
  • ✅ Multiple deployment options (local, Docker, Kubernetes)

How It Works

  1. Deduplicate Trakt - Removes duplicate watch history entries
  2. Deduplicate Toggl - Removes duplicate time entries, including a second pass that clusters entries with the same title within 24 hours and keeps only the most recently created one (retroactive re-watch cleanup)
  3. Sync - Creates or updates Toggl entries for recent Trakt history (default: 7 days), using a persistent state file (.sync_state.json) to map each Trakt content ID to its Toggl entry ID—preventing duplicate entries when the same episode is re-watched across sync runs

Rate limits are handled gracefully—if Toggl returns 402, deduplication is skipped and sync continues.

The Kubernetes CronJob automatically refreshes OAuth tokens before they expire, ensuring uninterrupted syncing.

Example Output

[2026-01-10 12:47:51] ===== Starting trakt-toggl-sync =====

[2026-01-10 12:47:51] === Step 1: Removing Trakt Duplicates ===
[2026-01-10 12:47:52] Found 6 duplicate entries
[2026-01-10 12:47:52] ✓ Successfully removed 6 duplicates

[2026-01-10 12:47:53] === Step 2: Removing Toggl Duplicates ===
[2026-01-10 12:47:53] ⚠ Toggl rate limit reached. Skipping deduplication.

[2026-01-10 12:47:54] === Step 3: Syncing Trakt to Toggl ===
[2026-01-10 12:47:55] ✓ Created: 📺 The Office - S03E15 (at 2025-12-30 20:00)
[2026-01-10 12:47:56] Skipped (exists): 🎞️ Inception (2010)

[2026-01-10 12:48:00] ===== Sync Complete =====

Prerequisites

API Credentials:

Runtime:

  • Python 3.14+ with uv
  • Docker (optional)
  • Kubernetes (optional)

Usage

Quick Start

# Clone and setup
git clone https://github.com/YOUR_USERNAME/trakt-toggl-sync.git
cd trakt-toggl-sync
cp .env.template .env
# Edit .env with your API credentials

# Run locally
make run

# Or with Docker
make docker-run

Configuration

Edit .env:

# Trakt
TRAKT_CLIENT_ID=your_client_id
TRAKT_CLIENT_SECRET=your_client_secret
TRAKT_HISTORY_DAYS=7

# Toggl
TOGGL_API_TOKEN=your_api_token
TOGGL_WORKSPACE_ID=your_workspace_id
TOGGL_PROJECT_ID=your_project_id
TOGGL_TAGS=watching,entertainment

# State (optional — defaults to .sync_state.json)
SYNC_STATE_FILE=.sync_state.json

Docker

# One-time setup for multi-platform builds
make docker-setup

# Build for local architecture
make docker-build

# Run locally
make docker-run

# Build and push multi-platform (amd64 + arm64) to Docker Hub
make docker-push

Kubernetes

The Kubernetes deployment uses a CronJob that runs every 6 hours with persistent storage for Trakt OAuth tokens.

Initial Setup

Step 1: Prepare Kubernetes configuration

# Create namespace
kubectl apply -f k8s/base/namespace.yaml

# Copy and edit configuration templates
cp k8s/base/configmap-template.yaml k8s/secrets/configmap.yaml
cp k8s/base/secret-template.yaml k8s/secrets/secret.yaml

# Edit k8s/secrets/configmap.yaml with your Toggl IDs
# Edit k8s/secrets/secret.yaml with base64-encoded API credentials:
echo -n "your_trakt_client_id" | base64
echo -n "your_trakt_client_secret" | base64
echo -n "your_toggl_api_token" | base64

Step 2: Deploy to Kubernetes

# Apply PersistentVolumeClaim for token storage
kubectl apply -f k8s/base/pvc.yaml

# Apply configuration and secrets
kubectl apply -f k8s/secrets/configmap.yaml
kubectl apply -f k8s/secrets/secret.yaml

# Deploy the CronJob
kubectl apply -f k8s/base/cronjob.yaml

Step 3: Initial token setup (first time only)

Since the CronJob won't have authentication tokens yet, you have to manually trigger the first job and authenticate interactively:

# Create a one-time job from the cronjob
kubectl create job --from=cronjob/trakt-toggl-sync trakt-sync-initial -n trakt-toggl

# Watch the logs
kubectl logs -f job/trakt-sync-initial -n trakt-toggl

# Follow the authentication URL shown in the logs
# Once authenticated, the token will be saved to the PVC

Automation via CronJob

The Kubernetes deployment uses a CronJob that runs every 6 hours with persistent storage for Trakt OAuth tokens.

Management Commands
# Check CronJob status
kubectl get cronjob -n trakt-toggl

# View recent job runs
kubectl get jobs -n trakt-toggl

# View logs from latest run
kubectl logs -l app=trakt-toggl-sync -n trakt-toggl --tail=100

# Manually trigger a sync
kubectl create job --from=cronjob/trakt-toggl-sync trakt-sync-manual-$(date +%s) -n trakt-toggl

# Check PVC status
kubectl get pvc -n trakt-toggl

# Delete everything
kubectl delete namespace trakt-toggl

Storage Configuration

The deployment uses a PersistentVolumeClaim (PVC) to store Trakt OAuth tokens. By default, it requests 3Mi of storage.

Troubleshooting

Rate Limiting (402 Error)

  • Handled gracefully—sync continues
  • Deduplication skipped temporarily
  • Try again in a few minutes

Token Expired

# Local
rm .trakt_tokens.json
make run  # Re-authenticate

# Kubernetes
kubectl delete pvc trakt-tokens-pvc -n trakt-toggl
kubectl apply -f k8s/pvc.yaml
# Then follow Step 4 again to re-authenticate

No Entries Syncing

  • Verify TOGGL_PROJECT_ID is correct
  • Check logs for "Skipped (exists)" messages
  • Adjust TRAKT_HISTORY_DAYS to sync more history
  • Ensure entries exist in Trakt for the specified time period

Kubernetes Pod Crashes

# Check pod logs
kubectl logs -l app=trakt-toggl-sync -n trakt-toggl

# Check pod events
kubectl describe pod -l app=trakt-toggl-sync -n trakt-toggl

# Verify secrets are created correctly
kubectl get secrets -n trakt-toggl
kubectl describe secret trakt-toggl-credentials -n trakt-toggl

PVC Not Mounting

  • Verify your cluster has a storage provisioner installed
  • Check available storage classes: kubectl get storageclass
  • Update k8s/pvc.yaml with your cluster's storage class

Development

make install    # Install dependencies
make run        # Run sync
make test       # Run tests
make lint       # Check code
make format     # Format code
make check      # Lint and format
make test-cov   # Run tests with coverage
make clean      # Clean cache

End-to-End Testing

The project includes comprehensive E2E tests that verify integration with real Trakt and Toggl APIs.

Setup E2E Tests:

# 1. Authenticate with Trakt (creates .trakt_tokens.json)
make run

# 2. Get setup instructions
make test-e2e-setup

# 3. Export the environment variables shown (example):
export E2E_TRAKT_CLIENT_ID="your_client_id"
export E2E_TRAKT_CLIENT_SECRET="your_client_secret"
export E2E_TRAKT_ACCESS_TOKEN="token_from_json"
export E2E_TRAKT_REFRESH_TOKEN="token_from_json"
export E2E_TOGGL_API_TOKEN="your_api_token"
export E2E_TOGGL_WORKSPACE_ID="123456"
export E2E_TOGGL_PROJECT_ID="789012"
export E2E_TEST_ENABLED=true

# 4. Run E2E tests
make test-e2e

Note: E2E tests will create temporary test entries in your Toggl project. These are tagged with e2e-test and should be cleaned up manually.

Pre-commit Hooks

Install pre-commit hooks to automatically check code quality before commits:

make pre-commit-install

# Run hooks manually
make pre-commit-run

# Update hooks to latest versions
make pre-commit-update

Hooks include:

  • Ruff linting and formatting
  • YAML/TOML syntax checking
  • Trailing whitespace removal
  • Security vulnerability scanning (Bandit)
  • Docstring validation

About

Sync your Trakt history to Toggl

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors