@chronicle.app/timing-app
v0.4.0
Published
Chronicle plugin for extracting app usage, projects, and time blocks from Timing.app
Maintainers
Readme
@chronicle.app/timing-app
Chronicle plugin that extracts app/screen usage, manually-logged time entries, and relayed phone/FaceTime call history from Timing.app's local SQLite database.
Source
~/Library/Application Support/info.eurocomp.Timing2/SQLite.db (opened read-only).
Timestamps are Unix epoch seconds.
Timing is partly a relay: Mac AppActivity/TaskActivity/Project are native,
while iOS app usage rides in AppActivity via Apple Screen Time, and Apple Call
History rides in Event.
Extraction types
Bare chronicle extract timing-app runs the default extractor — a
reverse-chronological merge of the three focused streams below (so --limit 1
is the single most-recent record across all of them). Each stream is also
selectable on its own:
| --type | Table | Emits |
| ---------------- | ------------------------------ | --------------------------------- |
| (none, default) | all three, merged newest-first | — |
| app-activities | AppActivity | ExecuteAction + DeviceSession |
| time-entries | TaskActivity | ExperienceAction + Session |
| calls | Event (call relay) | CallAction + CallSession |
Mapping
- App usage →
ExecuteAction+DeviceSession. The action carries the measured span (startTime/endTime),agent: @me,object: theSoftwareApplication,instrument: theDevice,result: theDeviceSession. The session carriesisPartOf→ Project and, for the on-screen resource, a URL-keyed webEntityor a realm-scoped filesystem entry as itssubject. A filesystem entry is keyed by path within the machine's name-keyed:Realm(source: hostname, viainRealm) — not globally, since a path isn't unique. A trailing-slash path is a:Directoryand lands onworkingDirectory(the terminal CWD / Finder folder the block happened in); any other path IS the media object living there, typed by extension as far as a path-only source can tell (ImageObject/AudioObject/VideoObject/DocumentObject, else a plainMediaObjecta byte-reader may refine later). The window title, when it adds anything beyond the subject's name, holds the session'sname. - Time entry →
ExperienceAction+Session. A manually-logged block of real time (Timing's "time entries"; each belongs to a project). The action carries the real occurrence (startTime/endTime, notscheduledStart/scheduledEnd); the leanSessionobject carriesisPartOf→ Project,name(title), anddescription(notes). - Project ancestry is nested via
isPartOfon the session (leaf → parent → …), not emitted as standalone records. - Call relay (
--type calls). Timing relays Apple Call History; this plugin reads that DB. It emitsCallAction/CallSessionundersource: apple-call-history- the shared call UUID, so it folds with the Apple Call History plugin's richer Apple records — supplying the long tail Apple prunes. Direction is lost and named contacts carry no number, so these are thin (a name, no participant).
Identity
- App: bundle id (
source: apple-bundle-id) where present, elsetiming-app+ executable/title. Never keyed on the localApplication.id. - Device:
timing-app+Device.globalID, with the hardware MAC linked viasameAs(source: mac-address) on Macs. @me: Timing has no account of its own, so the self node is just the@metag sourced totiming-app(no assumed name); the token merges it with the subject's named identities from other sources.
Usage
# Default merge, recent window (~90 days), newest-first
chronicle extract timing-app
# Full history
chronicle extract timing-app --all --limit 0
# A single focused stream
chronicle extract timing-app --type app-activities
chronicle extract timing-app --type time-entries
chronicle extract timing-app --type calls
# Another copy of the database
chronicle extract timing-app --input /path/to/SQLite.dbTests use a synthetic Timing SQLite.db and a synthetic AddressBook under a
temporary HOME, so they never read the host's Timing data or contacts.
