M A N D A L I V I A
Obsidian Lab All Notes

Voice-Driven Time Tracking with Toggl and Claude

The Problem

I tracked time in my daily notes for a week using a DataviewJS pie chart — and it worked. The visual feedback was genuinely motivating. But the entry method was pure friction: typing - 10:00 - 11:30 Gym [exercise] for every block, keeping the format exact, remembering to log in the moment. I’d batch-enter entries at end of day from memory, which defeats the purpose.

The other issue: daily notes are static markdown. You can’t query “how much time on writing this week?” without rebuilding the DataviewJS every time.

The Solution

Use Toggl as the data layer — it’s a proper time-tracking database with an API, mobile app, and reporting. Log entries by speaking naturally to Claude. Obsidian stays the planning and reflection layer.

The architecture is:

  • Toggl — source of truth, stores all entries with projects/tags/timestamps
  • Claude skill — the intelligent layer that parses natural language and maps it to structured data
  • toggl.py — the dumb layer that logs entries via API and returns JSON
  • obsidian-toggl-report — fetches today’s summary and writes it back into the daily note
  • ~/.env — stores the API token safely, never touches the vault

How To

Prerequisites

  1. Toggl account (free plan works, with some rate limit caveats)
  2. API token: Toggl profile → scroll to bottom → API Token section
  3. Workspace ID: visible in the URL when you’re in your workspace

Setup

Add to ~/.env:

TOGGL_TOKEN=your_token_here
TOGGL_WORKSPACE_ID=your_workspace_id

The skill and script live in ~/.claude/skills/toggl/ — global, not vault-specific.

Project structure

Set up Toggl projects that mirror your life areas. I use:

  • Meditation, Exercise — body and spirit
  • Family, Friends — community
  • Writing, Coding, Consulting, Learning — creating
  • Admin — sustaining
  • Rest — explicitly tracked and celebrated

Clients (Foundation, Community, Creating, Sustaining, Rest) group the projects in Toggl’s UI — assign them manually since the free plan API doesn’t expose client creation.

Logging entries

Just speak naturally to Claude:

“This morning I meditated from 9:50 to 10:20 and had a Spanish class from 7 to 7:30”

Claude parses, maps to projects and tags, calls the script with a JSON batch, and confirms what was logged. If there’s a conflict with an existing entry, it asks before overriding.

Tags handle sub-category detail: project Coding + tag jomo vs webmcp. Project Meditation + tag wim-hof if it was breathwork.

Conflict detection

Before logging anything, the script fetches existing entries for the day and checks for time overlaps. Useful when you’ve logged something in the Toggl mobile app and don’t want duplicates from Claude.

Seeing it in Obsidian

A second script (obsidian-toggl-report in ~/dotfiles/bin/) fetches today’s entries and writes a callout block into the daily note:

> [!note] Today · 3h 25m of 7h 44m elapsed (44%)
> █████████░░░░░░░░░░░
>
> Coding 1h 49m · Meditation 30m · Learning 30m · Exercise 24m

Add the markers once under ## Time in your daily note template:

<!-- toggl-report-start -->
<!-- toggl-report-end -->

The script replaces whatever is between them on each run. Run manually, or schedule hourly via launchd (same pattern as obsidian-daily-catchup).

Day start defaults to 5:30 AM — configurable via --day-start HH:MM or TOGGL_DAY_START in the environment.

What I Learned

Separate the intelligent layer from the data layer. The script is deliberately dumb — it takes structured JSON, makes API calls, returns JSON. Claude handles all the reasoning: parsing “gym with M this morning” into {"desc": "Gym", "start": "09:00", "end": "10:00", "project": "Exercise", "tags": "gym"}. This makes both layers easier to debug and extend.

Auth is token-based, not password-based. The Toggl API docs show -u email:password in examples but you should use -u YOUR_API_TOKEN:api_token — the literal string api_token as the password. Safer, revocable.

The Obsidian DataviewJS experiment wasn’t wasted. It revealed that the category mapping (grocery shopping = [good-enough life] = caring for family) was the real insight. That philosophy transferred directly to the Toggl project/tag structure.

Marker comments let scripts update notes safely. <!-- toggl-report-start --> / <!-- toggl-report-end --> give the script a stable target to replace without caring about the surrounding note structure. No regex gymnastics, no heading detection — just find and replace between the markers. The same pattern works for any script that needs to inject live data into a static document.

Caveats

Free plan rate limit — roughly 10 API calls per hour. For daily use (2-4 entries at a time) you’ll never notice. Batch-importing a full day of 12 entries will hit it.

Toggl client creation requires paid plan — you can set up client groupings manually in the Toggl UI, but the API returns 403 for client operations on free accounts.

Weekly summary not yet built — the daily note view works, but cross-day reporting (how much time on writing this week?) still requires opening Toggl directly. This will likely use the Toggl Reports API.

Nightly Toggl Summary in Your Obsidian Daily Note Syncing Completed Things 3 Tasks into Obsidian Daily Notes Semantic Search for Your Obsidian Vault

Keep Exploring