Understanding How ActivityWatch Stores Data

ActivityWatch is an open-source platform designed to monitor and record your digital activities, giving insight into how you spend your time on your devices. It tracks application usage and records event data in SQLite databases, providing a detailed look at user behavior.

Database Schema

Buckets Table

This table defines “buckets” that categorize different types of recorded events.

Column NameData TypeDescription
idINTEGER PRIMARY KEYThe unique autoincrement id of the “bucket”.
nameTEXT UNIQUE NOT NULLThe unique name identifying the “bucket”.
typeTEXT NOT NULLThe type of events the “bucket” records.
clientTEXT NOT NULLThe client or watcher that created the “bucket”.
hostnameTEXT NOT NULLThe hostname of the device where events are tracked.
createdTEXT NOT NULLThe creation timestamp of the “bucket”.
data_deprecatedTEXT DEFAULT ’{}‘Legacy field for additional data (unused, deprecated).
dataTEXT NOT NULL DEFAULT ’{}‘A field for additional JSON-formatted data about the “bucket”.
idnametypeclienthostnamecreateddata_deprecateddata
1aw-watcher-afk_shasharma-c13130afkstatusaw-watcher-afkshasharma-c131302024-07-29 15:53:15.705137+00:00{}{“$aw.sync.origin”:“shasharma-c13130”}
2aw-watcher-window_shasharma-c13130currentwindowaw-watcher-windowshasharma-c131302024-07-29 15:53:13.811889+00:00{}{“$aw.sync.origin”:“shasharma-c13130”}

Events Table

This table stores the actual time-tracked events.

Column NameData TypeDescription
idINTEGER PRIMARY KEYThe unique autoincrement id of the event.
bucketrowINTEGER NOT NULLForeign key to the associated “bucket”.
starttimeINTEGER NOT NULLThe starting timestamp of the event.
endtimeINTEGER NOT NULLThe ending timestamp of the event.
dataTEXT NOT NULLThe JSON-formatted data about the event.
idbucketrowstarttimeendtimedata
1966217223441791730000001722344199921000000{“app”:“Arc”,“title”:“ActivityWatch Web Watcher

1967217223441999220000001722344200879000000{“app”:“Arc”,“title”:“github.com/activitywatch

1968217223442008800000001722344208653000000{“app”:“Arc”,“title”:“github.com/ActivityWatch


Key-Value Table

A table for various settings and configuration values.

Column NameData TypeDescription
keyTEXT PRIMARY KEYThe unique identifier for the setting.
valueTEXTThe attached value for the setting.
last_modifiedNUMBER NOT NULLThe timestamp of the last modification.

Indexes

ActivityWatch creates indexes to improve the performance of the database:

CREATE INDEX bucket_id_index ON buckets(id);
CREATE INDEX events_bucketrow_index ON events(bucketrow);
CREATE INDEX events_starttime_index ON events(starttime);
CREATE INDEX events_endtime_index ON events(endtime);

Query

.headers on
.mode column

SELECT *
FROM events
JOIN buckets ON events.bucketrow = buckets.id LIMIT 5;
Event IDBucketRowStartTimeEndTimeEvent DataBucket IDBucket NameBucket TypeBucket ClientBucket HostnameBucket CreatedBucket Data DeprecatedBucket Data
1117222485957000000001722248846293000000{“status”:“not-afk”}1aw-watcher-afk_shasharma-c13130afkstatusaw-watcher-afkshasharma-c131302024-07-29 15:53:15.705137+00:00{}{“$aw.sync.origin”:“shasharma-c13130”}
2117222488462930000001722249644100000000{“status”:“afk”}1aw-watcher-afk_shasharma-c13130afkstatusaw-watcher-afkshasharma-c131302024-07-29 15:53:15.705137+00:00{}{“$aw.sync.origin”:“shasharma-c13130”}
3117222496440990000001722251767816000000{“status”:“not-afk”}1aw-watcher-afk_shasharma-c13130afkstatusaw-watcher-afkshasharma-c131302024-07-29 15:53:15.705137+00:00{}{“$aw.sync.origin”:“shasharma-c13130”}
4117222496440990000001722249748850000000{“status”:“not-afk”}1aw-watcher-afk_shasharma-c13130afkstatusaw-watcher-afkshasharma-c131302024-07-29 15:53:15.705137+00:00{}{“$aw.sync.origin”:“shasharma-c13130”}
5117222496440990000001722249718606000000{“status”:“not-afk”}1aw-watcher-afk_shasharma-c13130afkstatusaw-watcher-afkshasharma-c131302024-07-29 15:53:15.705137+00:00{}{“$aw.sync.origin”:“shasharma-c13130”}

Better query will look like:

SELECT
    e.id AS EventID,
    e.starttime AS StartTime,
    e.endtime AS EndTime,
    e.data AS EventData,
    b.id AS BucketID,
    b.name AS BucketName,
    b.type AS BucketType,
    b.client AS BucketClient,
    b.hostname AS BucketHostname
FROM events e
JOIN buckets b ON e.bucketrow = b.id LIMIT 5;