Skip to content

Instantly share code, notes, and snippets.

@0xdevalias
Last active October 7, 2025 05:02
Show Gist options
  • Select an option

  • Save 0xdevalias/46fe2f14196eb279ab749f18d2526f86 to your computer and use it in GitHub Desktop.

Select an option

Save 0xdevalias/46fe2f14196eb279ab749f18d2526f86 to your computer and use it in GitHub Desktop.
Some notes on exploring the Toggl Track macOS app's CoreData-backed SQLite database.

Toggl Track macOS SQLite Database Exploration (CoreData)

Some notes on exploring the Toggl Track macOS app's CoreData-backed SQLite database.

Table of Contents

Notes

We can find some of the Toggl Track desktop app's files at:

  • ~/Library/Group Containers/B227VTMZ94.group.com.toggl.daneel.extensions/

Among those, we can find the main SQLite database:

  • ~/Library/Group Containers/B227VTMZ94.group.com.toggl.daneel.extensions/production/DatabaseModel.sqlite

We could start to explore it with some commands like:

# List all tables
sqlite3 -readonly ~/Library/Group\ Containers/B227VTMZ94.group.com.toggl.daneel.extensions/production/DatabaseModel.sqlite \
  ".tables"

# Show full schema (tables + indexes + triggers)
sqlite3 -readonly ~/Library/Group\ Containers/B227VTMZ94.group.com.toggl.daneel.extensions/production/DatabaseModel.sqlite \
  ".schema"

# Show the schema for a single table (replace TableName)
sqlite3 -readonly ~/Library/Group\ Containers/B227VTMZ94.group.com.toggl.daneel.extensions/production/DatabaseModel.sqlite \
  ".schema TableName"

# Show column info for a given table
sqlite3 -readonly ~/Library/Group\ Containers/B227VTMZ94.group.com.toggl.daneel.extensions/production/DatabaseModel.sqlite \
  "PRAGMA table_info(TableName);"

# Show number of rows in each table
sqlite3 -readonly ~/Library/Group\ Containers/B227VTMZ94.group.com.toggl.daneel.extensions/production/DatabaseModel.sqlite \
  "SELECT name, (SELECT COUNT(*) FROM sqlite_master AS m2, main.[name] WHERE m2.name = name LIMIT 1) AS rows FROM sqlite_master WHERE type='table';"

# Peek at the first 10 rows of a table (replace TableName)
sqlite3 -readonly ~/Library/Group\ Containers/B227VTMZ94.group.com.toggl.daneel.extensions/production/DatabaseModel.sqlite \
  "SELECT * FROM TableName LIMIT 10;"

# List all indexes
sqlite3 -readonly ~/Library/Group\ Containers/B227VTMZ94.group.com.toggl.daneel.extensions/production/DatabaseModel.sqlite \
  ".indexes"

# Show foreign keys for a table
sqlite3 -readonly ~/Library/Group\ Containers/B227VTMZ94.group.com.toggl.daneel.extensions/production/DatabaseModel.sqlite \
  "PRAGMA foreign_key_list(TableName);"

Tables:

⇒ sqlite3 -readonly ~/Library/Group\ Containers/B227VTMZ94.group.com.toggl.daneel.extensions/production/DatabaseModel.sqlite '.tables' \
  | tr ' ' '\n' | sed '/^$/d' | sort

ACHANGE
ATRANSACTION
ATRANSACTIONSTRING
ZMANAGEDACTIVITY
ZMANAGEDAUTOTRACKERRULE
ZMANAGEDCLIENT
ZMANAGEDEXTERNALCALENDAR
ZMANAGEDEXTERNALCALENDAREVENT
ZMANAGEDEXTERNALCALENDARINTEGRATION
ZMANAGEDFAVORITE
ZMANAGEDGOAL
ZMANAGEDORGANIZATION
ZMANAGEDPREFERENCES
ZMANAGEDPROJECT
ZMANAGEDTAG
ZMANAGEDTASK
ZMANAGEDTEAMMEMBER
ZMANAGEDTIMEENTRY
ZMANAGEDTIMEENTRYINVITATION
ZMANAGEDUSER
ZMANAGEDUSERGROUP
ZMANAGEDWORKSPACE
Z_12TIMEENTRIES
Z_12TIMEENTRYINVITATIONS
Z_18WORKSPACES
Z_7FAVORITETAGS
Z_METADATA
Z_MODELCACHE
Z_PRIMARYKEY

These look like the structure that CoreData uses:

We can use this tool I wrote based on some of the above to help extract more info

CoreData Model Hierachy:

# ⇒ cd ~/dev/0xdevalias/poc-coredata-sqlite-tools

# ⇒ ./extract-coredata-model-hierarchy.py -h
# 
# usage: extract-coredata-model-hierarchy.py [-h] db_path
# 
# Extract and organize model hierarchy from a CoreData SQLite database.
# 
# positional arguments:
#   db_path     Path to the CoreData SQLite database file.
# 
# options:
#   -h, --help  show this help message and exit

⇒ ./extract-coredata-model-hierarchy.py ~/Library/Group\ Containers/B227VTMZ94.group.com.toggl.daneel.extensions/production/DatabaseModel.sqlite

- 1: ManagedActivity (Table: ZMANAGEDACTIVITY)
- 2: ManagedAutoTrackerRule (Table: ZMANAGEDAUTOTRACKERRULE)
- 3: ManagedClient (Table: ZMANAGEDCLIENT)
- 4: ManagedExternalCalendar (Table: ZMANAGEDEXTERNALCALENDAR)
- 5: ManagedExternalCalendarEvent (Table: ZMANAGEDEXTERNALCALENDAREVENT)
- 6: ManagedExternalCalendarIntegration (Table: ZMANAGEDEXTERNALCALENDARINTEGRATION)
- 7: ManagedFavorite (Table: ZMANAGEDFAVORITE)
- 8: ManagedGoal (Table: ZMANAGEDGOAL)
- 9: ManagedOrganization (Table: ZMANAGEDORGANIZATION)
- 10: ManagedPreferences (Table: ZMANAGEDPREFERENCES)
- 11: ManagedProject (Table: ZMANAGEDPROJECT)
- 12: ManagedTag (Table: ZMANAGEDTAG)
- 13: ManagedTask (Table: ZMANAGEDTASK)
- 14: ManagedTeamMember (Table: ZMANAGEDTEAMMEMBER)
- 15: ManagedTimeEntry (Table: ZMANAGEDTIMEENTRY)
- 16: ManagedTimeEntryInvitation (Table: ZMANAGEDTIMEENTRYINVITATION)
- 17: ManagedUser (Table: ZMANAGEDUSER)
- 18: ManagedUserGroup (Table: ZMANAGEDUSERGROUP)
- 19: ManagedWorkspace (Table: ZMANAGEDWORKSPACE)
- 16001: CHANGE
- 16002: TRANSACTION
- 16003: TRANSACTIONSTRING

We could then further explore various tables as json with commands like:

⇒ sqlite3 -readonly -json ~/Library/Group\ Containers/B227VTMZ94.group.com.toggl.daneel.extensions/production/DatabaseModel.sqlite "PRAGMA table_info('TODO_THE_TABLE_NAME_HERE');"

See Also

My Other Related Deepdive Gist's and Projects

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment