

{"id":12537,"date":"2019-10-28T09:33:00","date_gmt":"2019-10-28T14:33:00","guid":{"rendered":"https:\/\/rud.is\/b\/?p=12537"},"modified":"2019-10-28T09:33:00","modified_gmt":"2019-10-28T14:33:00","slug":"spelunking-macos-screentime-app-usage-with-r","status":"publish","type":"post","link":"https:\/\/rud.is\/b\/2019\/10\/28\/spelunking-macos-screentime-app-usage-with-r\/","title":{"rendered":"Spelunking macOS &#8216;ScreenTime&#8217; App Usage with R"},"content":{"rendered":"<p>Apple has brought <a href=\"https:\/\/support.apple.com\/en-us\/HT210387\">Screen Time<\/a> to macOS for some time now and that means it has to store this data <em>somewhere<\/em>. Thankfully, Sarah Edwards has foraged through the macOS filesystem for us and explained where these bits of knowledge are in her post, <a href=\"https:\/\/www.mac4n6.com\/blog\/2018\/8\/5\/knowledge-is-power-using-the-knowledgecdb-database-on-macos-and-ios-to-determine-precise-user-and-application-usage\">Knowledge is Power! Using the macOS\/iOS knowledgeC.db Database to Determine Precise User and Application Usage<\/a>, which ultimately reveals the data lurks in <code>~\/Library\/Application Support\/Knowledge\/knowledgeC.db<\/code>. Sarah also has a neat little Python utility dubbed <a href=\"https:\/\/github.com\/mac4n6\/APOLLO\">APOLLO<\/a> (Apple Pattern of Life Lazy Output&#8217;er) which has a smattering of <code>knowledgeC.db<\/code> <a href=\"https:\/\/github.com\/mac4n6\/APOLLO\/search?q=knowledgeC.db&amp;unscoped_q=knowledgeC.db\">canned SQL queries<\/a> that cover a myriad of tracked items.<\/p>\n<p>Today, we&#8217;ll show how to work with this database in R and the {tidyverse} to paint our own pictures of application usage.<\/p>\n<p>There are quite a number of tables in the <code>knowledgeC.db<\/code> SQLite 3 database:<\/p>\n<p><a href=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/knowledgeC.png?ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" data-attachment-id=\"12538\" data-permalink=\"https:\/\/rud.is\/b\/2019\/10\/28\/spelunking-macos-screentime-app-usage-with-r\/knowledgec\/\" data-orig-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/knowledgeC.png?fit=1949%2C4313&amp;ssl=1\" data-orig-size=\"1949,4313\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"knowledgeC\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/knowledgeC.png?fit=463%2C1024&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/knowledgeC.png?resize=510%2C1129&#038;ssl=1\" alt=\"\" width=\"510\" height=\"1129\" class=\"aligncenter size-full wp-image-12538\" srcset=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/knowledgeC.png?w=1949&amp;ssl=1 1949w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/knowledgeC.png?resize=68%2C150&amp;ssl=1 68w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/knowledgeC.png?resize=136%2C300&amp;ssl=1 136w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/knowledgeC.png?resize=768%2C1700&amp;ssl=1 768w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/knowledgeC.png?resize=463%2C1024&amp;ssl=1 463w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/knowledgeC.png?resize=500%2C1106&amp;ssl=1 500w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/knowledgeC.png?resize=150%2C332&amp;ssl=1 150w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/knowledgeC.png?resize=1200%2C2656&amp;ssl=1 1200w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/knowledgeC.png?resize=400%2C885&amp;ssl=1 400w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/knowledgeC.png?resize=800%2C1770&amp;ssl=1 800w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/knowledgeC.png?resize=200%2C443&amp;ssl=1 200w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/knowledgeC.png?w=1020&amp;ssl=1 1020w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/knowledgeC.png?w=1530&amp;ssl=1 1530w\" sizes=\"auto, (max-width: 510px) 100vw, 510px\" \/><\/a><\/p>\n<p>That visual schema was created in OmniGraffle via a <a href=\"https:\/\/paste.sr.ht\/~hrbrmstr\/333bd9e13dfeaca4fc70f895ab03e5c6839b7cd1\">small R script<\/a> that uses the OmniGraffle automation framework. The OmniGraffle source files are also available upon request.<\/p>\n<p>Most of the interesting bits (for any tracking-related spelunking) are in the <code>ZOBJECT<\/code> table and to get a full picture of usage we&#8217;ll need to join it with some other tables that are connected via a few foreign keys:<\/p>\n<p><a href=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage.png?ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" data-attachment-id=\"12539\" data-permalink=\"https:\/\/rud.is\/b\/2019\/10\/28\/spelunking-macos-screentime-app-usage-with-r\/usage\/\" data-orig-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage.png?fit=1570%2C4313&amp;ssl=1\" data-orig-size=\"1570,4313\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"usage\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage.png?fit=373%2C1024&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage.png?resize=510%2C1401&#038;ssl=1\" alt=\"\" width=\"510\" height=\"1401\" class=\"aligncenter size-full wp-image-12539\" srcset=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage.png?w=1570&amp;ssl=1 1570w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage.png?resize=55%2C150&amp;ssl=1 55w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage.png?resize=109%2C300&amp;ssl=1 109w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage.png?resize=768%2C2110&amp;ssl=1 768w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage.png?resize=373%2C1024&amp;ssl=1 373w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage.png?resize=500%2C1374&amp;ssl=1 500w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage.png?resize=150%2C412&amp;ssl=1 150w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage.png?resize=1200%2C3297&amp;ssl=1 1200w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage.png?resize=400%2C1099&amp;ssl=1 400w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage.png?resize=800%2C2198&amp;ssl=1 800w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage.png?resize=200%2C549&amp;ssl=1 200w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage.png?w=1020&amp;ssl=1 1020w\" sizes=\"auto, (max-width: 510px) 100vw, 510px\" \/><\/a><\/p>\n<p>There are a few ways to do this in {tidyverse} R. The first is an extended straight SQL riff off of one of Sarah&#8217;s original queries:<\/p>\n<pre><code class=\"language-r\">library(hrbrthemes) # for ggplot2 machinations\nlibrary(tidyverse)\n\n# source the knowledge db\nkdb &lt;- src_sqlite(\"~\/Library\/Application Support\/Knowledge\/knowledgeC.db\")\n\ntbl(\n  kdb, \n  sql('\nSELECT\n  ZOBJECT.ZVALUESTRING AS \"app\", \n    (ZOBJECT.ZENDDATE - ZOBJECT.ZSTARTDATE) AS \"usage\",  \n    CASE ZOBJECT.ZSTARTDAYOFWEEK \n      WHEN \"1\" THEN \"Sunday\"\n      WHEN \"2\" THEN \"Monday\"\n      WHEN \"3\" THEN \"Tuesday\"\n      WHEN \"4\" THEN \"Wednesday\"\n      WHEN \"5\" THEN \"Thursday\"\n      WHEN \"6\" THEN \"Friday\"\n      WHEN \"7\" THEN \"Saturday\"\n    END \"dow\",\n    ZOBJECT.ZSECONDSFROMGMT\/3600 AS \"tz\",\n    DATETIME(ZOBJECT.ZSTARTDATE + 978307200, \\'UNIXEPOCH\\') as \"start_time\", \n    DATETIME(ZOBJECT.ZENDDATE + 978307200, \\'UNIXEPOCH\\') as \"end_time\",\n    DATETIME(ZOBJECT.ZCREATIONDATE + 978307200, \\'UNIXEPOCH\\') as \"created_at\", \n    CASE ZMODEL\n      WHEN ZMODEL THEN ZMODEL\n      ELSE \"Other\"\n    END \"source\"\n  FROM\n    ZOBJECT \n    LEFT JOIN\n      ZSTRUCTUREDMETADATA \n    ON ZOBJECT.ZSTRUCTUREDMETADATA = ZSTRUCTUREDMETADATA.Z_PK \n    LEFT JOIN\n      ZSOURCE \n    ON ZOBJECT.ZSOURCE = ZSOURCE.Z_PK \n    LEFT JOIN\n      ZSYNCPEER\n    ON ZSOURCE.ZDEVICEID = ZSYNCPEER.ZDEVICEID\n  WHERE\n    ZSTREAMNAME = \"\/app\/usage\"'\n  )) -&gt; usage\n\nusage\n## # Source:   SQL [?? x 8]\n## # Database: sqlite 3.29.0 [\/Users\/johndoe\/Library\/Application Support\/Knowledge\/knowledgeC.db]\n##    app                      usage dow         tz start_time          end_time            created_at         source       \n##    &lt;chr&gt;                    &lt;int&gt; &lt;chr&gt;    &lt;int&gt; &lt;chr&gt;               &lt;chr&gt;               &lt;chr&gt;              &lt;chr&gt;        \n##  1 com.bitrock.appinstaller    15 Friday      -4 2019-10-05 01:11:27 2019-10-05 01:11:42 2019-10-05 01:11:\u2026 MacBookPro13\u2026\n##  2 com.tinyspeck.slackmacg\u2026  4379 Tuesday     -4 2019-10-01 13:19:24 2019-10-01 14:32:23 2019-10-01 14:32:\u2026 Other        \n##  3 com.tinyspeck.slackmacg\u2026  1167 Tuesday     -4 2019-10-01 18:19:24 2019-10-01 18:38:51 2019-10-01 18:38:\u2026 Other        \n##  4 com.tinyspeck.slackmacg\u2026  1316 Tuesday     -4 2019-10-01 19:13:49 2019-10-01 19:35:45 2019-10-01 19:35:\u2026 Other        \n##  5 com.tinyspeck.slackmacg\u2026 12053 Thursday    -4 2019-10-03 12:25:18 2019-10-03 15:46:11 2019-10-03 15:46:\u2026 Other        \n##  6 com.tinyspeck.slackmacg\u2026  1258 Thursday    -4 2019-10-03 15:50:16 2019-10-03 16:11:14 2019-10-03 16:11:\u2026 Other        \n##  7 com.tinyspeck.slackmacg\u2026  2545 Thursday    -4 2019-10-03 16:24:30 2019-10-03 17:06:55 2019-10-03 17:06:\u2026 Other        \n##  8 com.tinyspeck.slackmacg\u2026   303 Thursday    -4 2019-10-03 17:17:10 2019-10-03 17:22:13 2019-10-03 17:22:\u2026 Other        \n##  9 com.tinyspeck.slackmacg\u2026  9969 Thursday    -4 2019-10-03 17:33:38 2019-10-03 20:19:47 2019-10-03 20:19:\u2026 Other        \n## 10 com.tinyspeck.slackmacg\u2026  2813 Thursday    -4 2019-10-03 20:19:52 2019-10-03 21:06:45 2019-10-03 21:06:\u2026 Other        \n## # \u2026 with more rows\n<\/code><\/pre>\n<p>Before explaining what that query does, let&#8217;s rewrite it {dbplyr}-style:<\/p>\n<pre><code class=\"language-r\">tbl(kdb, \"ZOBJECT\") %&gt;% \n  mutate(\n    created_at = datetime(ZCREATIONDATE + 978307200, \"UNIXEPOCH\", \"LOCALTIME\"),\n    start_dow = case_when(\n      ZSTARTDAYOFWEEK == 1 ~ \"Sunday\",\n      ZSTARTDAYOFWEEK == 2 ~ \"Monday\",\n      ZSTARTDAYOFWEEK == 3 ~ \"Tuesday\",\n      ZSTARTDAYOFWEEK == 4 ~ \"Wednesday\",\n      ZSTARTDAYOFWEEK == 5 ~ \"Thursday\",\n      ZSTARTDAYOFWEEK == 6 ~ \"Friday\",\n      ZSTARTDAYOFWEEK == 7 ~ \"Saturday\"\n    ),\n    start_time = datetime(ZSTARTDATE + 978307200, \"UNIXEPOCH\", \"LOCALTIME\"),\n    end_time = datetime(ZENDDATE + 978307200, \"UNIXEPOCH\", \"LOCALTIME\"),\n    usage = (ZENDDATE - ZSTARTDATE),\n    tz = ZSECONDSFROMGMT\/3600 \n  ) %&gt;% \n  left_join(tbl(kdb, \"ZSTRUCTUREDMETADATA\"), c(\"ZSTRUCTUREDMETADATA\" = \"Z_PK\")) %&gt;% \n  left_join(tbl(kdb, \"ZSOURCE\"), c(\"ZSOURCE\" = \"Z_PK\")) %&gt;% \n  left_join(tbl(kdb, \"ZSYNCPEER\"), \"ZDEVICEID\") %&gt;% \n  filter(ZSTREAMNAME == \"\/app\/usage\")  %&gt;% \n  select(\n    app = ZVALUESTRING, created_at, start_dow, start_time, end_time, usage, tz, source = ZMODEL\n  ) %&gt;% \n  mutate(source = ifelse(is.na(source), \"Other\", source)) %&gt;% \n  collect() %&gt;% \n  mutate_at(vars(created_at, start_time, end_time), as.POSIXct) -&gt; usage\n<\/code><\/pre>\n<p>What we&#8217;re doing is pulling out the day of week, start\/end usage times &amp; timezone info, app bundle id, source of the app interactions and the total usage time for each entry along with when that entry was created. We need to do some maths since Apple stores time-y whime-y info in its own custom format, plus we need to convert numeric DOW to labeled DOW.<\/p>\n<p>The bundle ids are pretty readable, but they&#8217;re not really intended for human consumption, so we&#8217;ll make a translation table for the bundle id to app name by using the <a href=\"https:\/\/ss64.com\/osx\/mdls.html\"><code>mdls<\/code><\/a> command.<\/p>\n<pre><code class=\"language-r\">list.files(\n  c(\"\/Applications\", \"\/System\/Library\/CoreServices\", \"\/Applications\/Utilities\", \"\/System\/Applications\"), # main places apps are stored (there are potentially more but this is sufficient for our needs)\n  pattern = \"\\\\.app$\", \n  full.names = TRUE\n) -&gt; apps\n\nx &lt;- sys::exec_internal(\"mdls\", c(\"-name\", \"kMDItemCFBundleIdentifier\", \"-r\", apps))\n\n# mdls null (\\0) terminates each entry so we have to do some raw surgery to get it into a format we can use\nx$stdout[x$stdout == as.raw(0)] &lt;- as.raw(0x0a)\n\ntibble(\n  name = gsub(\"\\\\.app$\", \"\", basename(apps)),\n  app = read_lines(x$stdout) \n) -&gt; app_trans\n\napp_trans\n## # A tibble: 270 x 2\n##    name                    app                                    \n##    &lt;chr&gt;                   &lt;chr&gt;                                  \n##  1 1Password 7             com.agilebits.onepassword7             \n##  2 Adium                   com.adiumX.adiumX                      \n##  3 Agenda                  com.momenta.agenda.macos               \n##  4 Alfred 4                com.runningwithcrayons.Alfred          \n##  5 Amazon Music            com.amazon.music                       \n##  6 Android File Transfer   com.google.android.mtpviewer           \n##  7 Awsaml                  com.rapid7.awsaml                      \n##  8 Bartender 2             com.surteesstudios.Bartender           \n##  9 BBEdit                  com.barebones.bbedit                   \n## 10 BitdefenderVirusScanner com.bitdefender.BitdefenderVirusScanner\n## # \u2026 with 260 more rows\n<\/code><\/pre>\n<p>The usage info goes back ~30 days, so let&#8217;s do a quick summary of the top 10 apps and their total usage (in hours):<\/p>\n<pre><code class=\"language-r\">usage %&gt;% \n  group_by(app) %&gt;% \n  summarise(first = min(start_time), last = max(end_time), total = sum(usage, na.rm=TRUE)) %&gt;% \n  ungroup() %&gt;% \n  mutate(total = total \/ 60 \/ 60) %&gt;% # hours\n  arrange(desc(total)) %&gt;% \n  left_join(app_trans) -&gt; overall_usage\n\noverall_usage %&gt;% \n  slice(1:10) %&gt;% \n  left_join(app_trans) %&gt;%\n  mutate(name = fct_inorder(name) %&gt;% fct_rev()) %&gt;%\n  ggplot(aes(x=total, y=name)) + \n  geom_segment(aes(xend=0, yend=name), size=5, color = ft_cols$slate) +\n  scale_x_comma(position = \"top\") +\n  labs(\n    x = \"Total Usage (hrs)\", y = NULL,\n    title = glue::glue('App usage in the past {round(as.numeric(max(usage$end_time) - min(usage$start_time), \"days\"))} days')\n  ) +\n  theme_ft_rc(grid=\"X\")\n<\/code><\/pre>\n<p><a href=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/total-app-usage.png?ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" data-attachment-id=\"12540\" data-permalink=\"https:\/\/rud.is\/b\/2019\/10\/28\/spelunking-macos-screentime-app-usage-with-r\/total-app-usage\/\" data-orig-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/total-app-usage.png?fit=1756%2C920&amp;ssl=1\" data-orig-size=\"1756,920\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"total-app-usage\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/total-app-usage.png?fit=510%2C268&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/total-app-usage.png?resize=510%2C267&#038;ssl=1\" alt=\"\" width=\"510\" height=\"267\" class=\"aligncenter size-full wp-image-12540\" srcset=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/total-app-usage.png?w=1756&amp;ssl=1 1756w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/total-app-usage.png?resize=150%2C79&amp;ssl=1 150w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/total-app-usage.png?resize=300%2C157&amp;ssl=1 300w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/total-app-usage.png?resize=768%2C402&amp;ssl=1 768w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/total-app-usage.png?resize=530%2C278&amp;ssl=1 530w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/total-app-usage.png?resize=500%2C262&amp;ssl=1 500w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/total-app-usage.png?resize=1200%2C629&amp;ssl=1 1200w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/total-app-usage.png?resize=400%2C210&amp;ssl=1 400w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/total-app-usage.png?resize=800%2C419&amp;ssl=1 800w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/total-app-usage.png?resize=200%2C105&amp;ssl=1 200w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/total-app-usage.png?w=1020&amp;ssl=1 1020w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/total-app-usage.png?w=1530&amp;ssl=1 1530w\" sizes=\"auto, (max-width: 510px) 100vw, 510px\" \/><\/a><\/p>\n<p>There&#8217;s a YUGE flaw in the current way macOS tracks application usage. Unlike iOS where apps really don&#8217;t run simultaneously (with iPadOS they <em>kinda<\/em> can\/do, now), macOS apps are usually started and left open along with other apps. Apple doesn&#8217;t do a great job identifying only active app usage activity so many of these usage numbers are heavily inflated. Hopefully that will be fixed by macOS 10.15.<\/p>\n<p>We have more data at our disposal, so let&#8217;s see when these apps get used. To do that, we&#8217;ll use segments to plot individual usage tracks and color them by weekday\/weekend usage (still limiting to top 10 for blog brevity):<\/p>\n<pre><code class=\"language-r\">usage %&gt;% \n  filter(app %in% overall_usage$app[1:10]) %&gt;% \n  left_join(app_trans) %&gt;%\n  mutate(name = factor(name, levels = rev(overall_usage$name[1:10]))) %&gt;% \n  ggplot() +\n  geom_segment(\n    aes(\n      x = start_time, xend = end_time, y = name, yend = name, \n      color = ifelse(start_dow %in% c(\"Saturday\", \"Sunday\"), \"Weekend\", \"Weekday\")\n    ),\n    size = 10,\n  ) +\n  scale_x_datetime(position = \"top\") +\n  scale_colour_manual(\n    name = NULL,\n    values = c(\n      \"Weekend\" = ft_cols$light_blue, \n      \"Weekday\" = ft_cols$green\n    )\n  ) +\n  guides(\n    colour = guide_legend(override.aes = list(size = 1))\n  ) +\n  labs(\n    x = NULL, y = NULL,\n    title = glue::glue('Top 10 App usage on this Mac in the past {round(as.numeric(max(usage$end_time) - min(usage$start_time), \"days\"))} days'),\n    subtitle = \"Each segment represents that app being 'up' (Open to Quit).\\nUnfortunately, this is what Screen Time uses for its calculations on macOS\"\n  ) +\n  theme_ft_rc(grid=\"X\") +\n  theme(legend.position = c(1, 1.25)) +\n  theme(legend.justification = \"right\")\n<\/code><\/pre>\n<p><a href=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/when-used.png?ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" data-attachment-id=\"12543\" data-permalink=\"https:\/\/rud.is\/b\/2019\/10\/28\/spelunking-macos-screentime-app-usage-with-r\/when-used\/\" data-orig-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/when-used.png?fit=1790%2C1122&amp;ssl=1\" data-orig-size=\"1790,1122\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"when-used\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/when-used.png?fit=510%2C319&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/when-used.png?resize=510%2C320&#038;ssl=1\" alt=\"\" width=\"510\" height=\"320\" class=\"aligncenter size-full wp-image-12543\" srcset=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/when-used.png?w=1790&amp;ssl=1 1790w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/when-used.png?resize=150%2C94&amp;ssl=1 150w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/when-used.png?resize=300%2C188&amp;ssl=1 300w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/when-used.png?resize=768%2C481&amp;ssl=1 768w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/when-used.png?resize=530%2C332&amp;ssl=1 530w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/when-used.png?resize=500%2C313&amp;ssl=1 500w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/when-used.png?resize=1200%2C752&amp;ssl=1 1200w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/when-used.png?resize=400%2C251&amp;ssl=1 400w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/when-used.png?resize=800%2C501&amp;ssl=1 800w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/when-used.png?resize=200%2C125&amp;ssl=1 200w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/when-used.png?w=1020&amp;ssl=1 1020w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/when-used.png?w=1530&amp;ssl=1 1530w\" sizes=\"auto, (max-width: 510px) 100vw, 510px\" \/><\/a><\/p>\n<p>I&#8217;m not entirely sure &#8220;on this Mac&#8221; is completely accurate since I think this syncs across all active Screen Time devices due to this (<em>n<\/em> is in seconds):<\/p>\n<pre><code class=\"language-r\">count(usage, source, wt=usage, sort=TRUE)\n## # A tibble: 2 x 2\n##   source               n\n##   &lt;chr&gt;            &lt;int&gt;\n## 1 Other          4851610\n## 2 MacBookPro13,2 1634137\n<\/code><\/pre>\n<p>The &#8220;Other&#8221; appears to be the work-dev Mac but it doesn&#8217;t have the identifier mapped so I think that means it&#8217;s the local one and that the above chart is looking at Screen Time across all devices. I literally (right before this sentence) enabled Screen Time on my iPhone so we&#8217;ll see if that ends up in the database and I&#8217;ll post a quick update if it does.<\/p>\n<p>We&#8217;ll take one last look by day of week and use a heatmap to see the results:<\/p>\n<pre><code class=\"language-r\">count(usage, start_dow, app, wt=usage\/60\/60) %&gt;% \n  left_join(app_trans) %&gt;%\n  filter(app %in% overall_usage$app[1:10]) %&gt;% \n  mutate(name = factor(name, levels = rev(overall_usage$name[1:10]))) %&gt;% \n  mutate(start_dow = factor(start_dow, c(\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"))) %&gt;% \n  ggplot() +\n  geom_tile(aes(start_dow, name, fill = n), color = \"#252a32\", size = 0.75) +\n  scale_x_discrete(expand = c(0, 0.5), position = \"top\") +\n  scale_y_discrete(expand = c(0, 0.5)) +\n  scale_fill_viridis_c(direction = -1, option = \"magma\", name = \"Usage (hrs)\") +\n  labs(\n    x = NULL, y = NULL,\n    title = \"Top 10 App usage by day of week\"\n  ) +\n  theme_ft_rc(grid=\"\")\n<\/code><\/pre>\n<p><a href=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage-dow.png?ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" data-attachment-id=\"12545\" data-permalink=\"https:\/\/rud.is\/b\/2019\/10\/28\/spelunking-macos-screentime-app-usage-with-r\/usage-dow\/\" data-orig-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage-dow.png?fit=1790%2C1122&amp;ssl=1\" data-orig-size=\"1790,1122\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"usage-dow\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage-dow.png?fit=510%2C319&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage-dow.png?resize=510%2C320&#038;ssl=1\" alt=\"\" width=\"510\" height=\"320\" class=\"aligncenter size-full wp-image-12545\" srcset=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage-dow.png?w=1790&amp;ssl=1 1790w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage-dow.png?resize=150%2C94&amp;ssl=1 150w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage-dow.png?resize=300%2C188&amp;ssl=1 300w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage-dow.png?resize=768%2C481&amp;ssl=1 768w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage-dow.png?resize=530%2C332&amp;ssl=1 530w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage-dow.png?resize=500%2C313&amp;ssl=1 500w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage-dow.png?resize=1200%2C752&amp;ssl=1 1200w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage-dow.png?resize=400%2C251&amp;ssl=1 400w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage-dow.png?resize=800%2C501&amp;ssl=1 800w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage-dow.png?resize=200%2C125&amp;ssl=1 200w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage-dow.png?w=1020&amp;ssl=1 1020w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/usage-dow.png?w=1530&amp;ssl=1 1530w\" sizes=\"auto, (max-width: 510px) 100vw, 510px\" \/><\/a><\/p>\n<p>I really need to get into the habit of using the RStudio Server access features of <a href=\"https:\/\/rud.is\/rswitch\/\">RSwitch<\/a> over Chrome so I can get RSwitch into the top 10, but some habits (and bookmarks) die hard.<\/p>\n<h3>FIN<\/h3>\n<p>Apple&#8217;s Screen Time also tracks &#8220;category&#8221;, which is something we can pick up from each application&#8217;s embedded metadata. We&#8217;ll do that in a follow-up post along with seeing whether we can capture iOS usage now that I&#8217;ve enabled Screen Time on those devices as well.<\/p>\n<p>Keep spelunking the <code>knowledgeC.db<\/code> table(s) and blog about or reply in the comments with any interesting nuggets you find.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Apple has brought Screen Time to macOS for some time now and that means it has to store this data somewhere. Thankfully, Sarah Edwards has foraged through the macOS filesystem for us and explained where these bits of knowledge are in her post, Knowledge is Power! Using the macOS\/iOS knowledgeC.db Database to Determine Precise User [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"activitypub_content_warning":"","activitypub_content_visibility":"","activitypub_max_image_attachments":3,"activitypub_interaction_policy_quote":"anyone","activitypub_status":"","footnotes":""},"categories":[780,91],"tags":[],"class_list":["post-12537","post","type-post","status-publish","format-standard","hentry","category-macos","category-r"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Spelunking macOS &#039;ScreenTime&#039; App Usage with R - rud.is<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/rud.is\/b\/2019\/10\/28\/spelunking-macos-screentime-app-usage-with-r\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Spelunking macOS &#039;ScreenTime&#039; App Usage with R - rud.is\" \/>\n<meta property=\"og:description\" content=\"Apple has brought Screen Time to macOS for some time now and that means it has to store this data somewhere. Thankfully, Sarah Edwards has foraged through the macOS filesystem for us and explained where these bits of knowledge are in her post, Knowledge is Power! Using the macOS\/iOS knowledgeC.db Database to Determine Precise User [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/rud.is\/b\/2019\/10\/28\/spelunking-macos-screentime-app-usage-with-r\/\" \/>\n<meta property=\"og:site_name\" content=\"rud.is\" \/>\n<meta property=\"article:published_time\" content=\"2019-10-28T14:33:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/rud.is\/b\/wp-content\/uploads\/2019\/10\/knowledgeC.png\" \/>\n<meta name=\"author\" content=\"hrbrmstr\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"hrbrmstr\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2019\\\/10\\\/28\\\/spelunking-macos-screentime-app-usage-with-r\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2019\\\/10\\\/28\\\/spelunking-macos-screentime-app-usage-with-r\\\/\"},\"author\":{\"name\":\"hrbrmstr\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#\\\/schema\\\/person\\\/d7cb7487ab0527447f7fda5c423ff886\"},\"headline\":\"Spelunking macOS &#8216;ScreenTime&#8217; App Usage with R\",\"datePublished\":\"2019-10-28T14:33:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2019\\\/10\\\/28\\\/spelunking-macos-screentime-app-usage-with-r\\\/\"},\"wordCount\":703,\"commentCount\":8,\"publisher\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#\\\/schema\\\/person\\\/d7cb7487ab0527447f7fda5c423ff886\"},\"image\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2019\\\/10\\\/28\\\/spelunking-macos-screentime-app-usage-with-r\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2019\\\/10\\\/knowledgeC.png\",\"articleSection\":[\"macOS\",\"R\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/rud.is\\\/b\\\/2019\\\/10\\\/28\\\/spelunking-macos-screentime-app-usage-with-r\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2019\\\/10\\\/28\\\/spelunking-macos-screentime-app-usage-with-r\\\/\",\"url\":\"https:\\\/\\\/rud.is\\\/b\\\/2019\\\/10\\\/28\\\/spelunking-macos-screentime-app-usage-with-r\\\/\",\"name\":\"Spelunking macOS 'ScreenTime' App Usage with R - rud.is\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2019\\\/10\\\/28\\\/spelunking-macos-screentime-app-usage-with-r\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2019\\\/10\\\/28\\\/spelunking-macos-screentime-app-usage-with-r\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2019\\\/10\\\/knowledgeC.png\",\"datePublished\":\"2019-10-28T14:33:00+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2019\\\/10\\\/28\\\/spelunking-macos-screentime-app-usage-with-r\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/rud.is\\\/b\\\/2019\\\/10\\\/28\\\/spelunking-macos-screentime-app-usage-with-r\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2019\\\/10\\\/28\\\/spelunking-macos-screentime-app-usage-with-r\\\/#primaryimage\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2019\\\/10\\\/knowledgeC.png?fit=1949%2C4313&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2019\\\/10\\\/knowledgeC.png?fit=1949%2C4313&ssl=1\",\"width\":1949,\"height\":4313},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2019\\\/10\\\/28\\\/spelunking-macos-screentime-app-usage-with-r\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/rud.is\\\/b\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Spelunking macOS &#8216;ScreenTime&#8217; App Usage with R\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#website\",\"url\":\"https:\\\/\\\/rud.is\\\/b\\\/\",\"name\":\"rud.is\",\"description\":\"&quot;In God we trust. All others must bring data&quot;\",\"publisher\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#\\\/schema\\\/person\\\/d7cb7487ab0527447f7fda5c423ff886\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/rud.is\\\/b\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#\\\/schema\\\/person\\\/d7cb7487ab0527447f7fda5c423ff886\",\"name\":\"hrbrmstr\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2023\\\/10\\\/ukr-shield.png?fit=460%2C460&ssl=1\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2023\\\/10\\\/ukr-shield.png?fit=460%2C460&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2023\\\/10\\\/ukr-shield.png?fit=460%2C460&ssl=1\",\"width\":460,\"height\":460,\"caption\":\"hrbrmstr\"},\"logo\":{\"@id\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2023\\\/10\\\/ukr-shield.png?fit=460%2C460&ssl=1\"},\"description\":\"Don't look at me\u2026I do what he does \u2014 just slower. #rstats avuncular \u2022 ?Resistance Fighter \u2022 Cook \u2022 Christian \u2022 [Master] Chef des Donn\u00e9es de S\u00e9curit\u00e9 @ @rapid7\",\"sameAs\":[\"http:\\\/\\\/rud.is\"],\"url\":\"https:\\\/\\\/rud.is\\\/b\\\/author\\\/hrbrmstr\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Spelunking macOS 'ScreenTime' App Usage with R - rud.is","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/rud.is\/b\/2019\/10\/28\/spelunking-macos-screentime-app-usage-with-r\/","og_locale":"en_US","og_type":"article","og_title":"Spelunking macOS 'ScreenTime' App Usage with R - rud.is","og_description":"Apple has brought Screen Time to macOS for some time now and that means it has to store this data somewhere. Thankfully, Sarah Edwards has foraged through the macOS filesystem for us and explained where these bits of knowledge are in her post, Knowledge is Power! Using the macOS\/iOS knowledgeC.db Database to Determine Precise User [&hellip;]","og_url":"https:\/\/rud.is\/b\/2019\/10\/28\/spelunking-macos-screentime-app-usage-with-r\/","og_site_name":"rud.is","article_published_time":"2019-10-28T14:33:00+00:00","og_image":[{"url":"https:\/\/rud.is\/b\/wp-content\/uploads\/2019\/10\/knowledgeC.png","type":"","width":"","height":""}],"author":"hrbrmstr","twitter_card":"summary_large_image","twitter_misc":{"Written by":"hrbrmstr","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/rud.is\/b\/2019\/10\/28\/spelunking-macos-screentime-app-usage-with-r\/#article","isPartOf":{"@id":"https:\/\/rud.is\/b\/2019\/10\/28\/spelunking-macos-screentime-app-usage-with-r\/"},"author":{"name":"hrbrmstr","@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886"},"headline":"Spelunking macOS &#8216;ScreenTime&#8217; App Usage with R","datePublished":"2019-10-28T14:33:00+00:00","mainEntityOfPage":{"@id":"https:\/\/rud.is\/b\/2019\/10\/28\/spelunking-macos-screentime-app-usage-with-r\/"},"wordCount":703,"commentCount":8,"publisher":{"@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886"},"image":{"@id":"https:\/\/rud.is\/b\/2019\/10\/28\/spelunking-macos-screentime-app-usage-with-r\/#primaryimage"},"thumbnailUrl":"https:\/\/rud.is\/b\/wp-content\/uploads\/2019\/10\/knowledgeC.png","articleSection":["macOS","R"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/rud.is\/b\/2019\/10\/28\/spelunking-macos-screentime-app-usage-with-r\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/rud.is\/b\/2019\/10\/28\/spelunking-macos-screentime-app-usage-with-r\/","url":"https:\/\/rud.is\/b\/2019\/10\/28\/spelunking-macos-screentime-app-usage-with-r\/","name":"Spelunking macOS 'ScreenTime' App Usage with R - rud.is","isPartOf":{"@id":"https:\/\/rud.is\/b\/#website"},"primaryImageOfPage":{"@id":"https:\/\/rud.is\/b\/2019\/10\/28\/spelunking-macos-screentime-app-usage-with-r\/#primaryimage"},"image":{"@id":"https:\/\/rud.is\/b\/2019\/10\/28\/spelunking-macos-screentime-app-usage-with-r\/#primaryimage"},"thumbnailUrl":"https:\/\/rud.is\/b\/wp-content\/uploads\/2019\/10\/knowledgeC.png","datePublished":"2019-10-28T14:33:00+00:00","breadcrumb":{"@id":"https:\/\/rud.is\/b\/2019\/10\/28\/spelunking-macos-screentime-app-usage-with-r\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/rud.is\/b\/2019\/10\/28\/spelunking-macos-screentime-app-usage-with-r\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/rud.is\/b\/2019\/10\/28\/spelunking-macos-screentime-app-usage-with-r\/#primaryimage","url":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/knowledgeC.png?fit=1949%2C4313&ssl=1","contentUrl":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/10\/knowledgeC.png?fit=1949%2C4313&ssl=1","width":1949,"height":4313},{"@type":"BreadcrumbList","@id":"https:\/\/rud.is\/b\/2019\/10\/28\/spelunking-macos-screentime-app-usage-with-r\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/rud.is\/b\/"},{"@type":"ListItem","position":2,"name":"Spelunking macOS &#8216;ScreenTime&#8217; App Usage with R"}]},{"@type":"WebSite","@id":"https:\/\/rud.is\/b\/#website","url":"https:\/\/rud.is\/b\/","name":"rud.is","description":"&quot;In God we trust. All others must bring data&quot;","publisher":{"@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/rud.is\/b\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886","name":"hrbrmstr","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1","url":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1","contentUrl":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1","width":460,"height":460,"caption":"hrbrmstr"},"logo":{"@id":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1"},"description":"Don't look at me\u2026I do what he does \u2014 just slower. #rstats avuncular \u2022 ?Resistance Fighter \u2022 Cook \u2022 Christian \u2022 [Master] Chef des Donn\u00e9es de S\u00e9curit\u00e9 @ @rapid7","sameAs":["http:\/\/rud.is"],"url":"https:\/\/rud.is\/b\/author\/hrbrmstr\/"}]}},"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p23idr-3gd","jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":12878,"url":"https:\/\/rud.is\/b\/2021\/01\/16\/new-swiftr-chapter-up-building-an-r-backed-swiftui-macos-app\/","url_meta":{"origin":12537,"position":0},"title":"New SwiftR Chapter Up: Building an R-backed SwiftUI macOS App","author":"hrbrmstr","date":"2021-01-16","format":false,"excerpt":"Last week I introduced a new bookdown series on how to embed R into a macOS Swift application. The initial chapters focused on core concepts and showed how to build a macOS compiled, binary command line application that uses embedded R for some functionality. This week, a new chapter is\u2026","rel":"","context":"In &quot;Apple&quot;","block_context":{"text":"Apple","link":"https:\/\/rud.is\/b\/category\/apple\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":12645,"url":"https:\/\/rud.is\/b\/2020\/02\/06\/prying-r-script-files-away-from-xcode-et-al-on-macos\/","url_meta":{"origin":12537,"position":1},"title":"Prying &#8220;.R&#8221; Script Files Away from Xcode (et al) on macOS","author":"hrbrmstr","date":"2020-02-06","format":false,"excerpt":"As the maintainer of RSwitch --- and developer of my own (for personal use) macOS, iOS, watchOS, iPadOS and tvOS apps --- I need the full Apple Xcode install around (more R-focused macOS folk can get away with just the command-line tools being installed). As an Apple Developer who insanely\u2026","rel":"","context":"In &quot;macOS&quot;","block_context":{"text":"macOS","link":"https:\/\/rud.is\/b\/category\/macos\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":10991,"url":"https:\/\/rud.is\/b\/2018\/07\/06\/visualizing-macos-app-usage\/","url_meta":{"origin":12537,"position":2},"title":"Visualizing macOS App Usage with a Little Help from osqueryr &#038; mactheknife","author":"hrbrmstr","date":"2018-07-06","format":false,"excerpt":"Both my osqueryr and macthekinfe packages have had a few updates and I wanted to put together a fun example (it being Friday, and all) for what you can do with them. All my packages are now on GitHub and GitLab and I'll be maintaining them on both so I\u2026","rel":"","context":"In &quot;R&quot;","block_context":{"text":"R","link":"https:\/\/rud.is\/b\/category\/r\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/07\/app-lod-tree-1.png?fit=1200%2C1197&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/07\/app-lod-tree-1.png?fit=1200%2C1197&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/07\/app-lod-tree-1.png?fit=1200%2C1197&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/07\/app-lod-tree-1.png?fit=1200%2C1197&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/07\/app-lod-tree-1.png?fit=1200%2C1197&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":12990,"url":"https:\/\/rud.is\/b\/2021\/03\/13\/retrieve-process-run-time-architecture-on-apple-silicon-macs-on-the-command-line-with-archinfo\/","url_meta":{"origin":12537,"position":3},"title":"Retrieve Process Run-time Architecture on Apple Silicon Macs On The Command Line with `archinfo`","author":"hrbrmstr","date":"2021-03-13","format":false,"excerpt":"Apple M1\/Apple Silicon\/arm64 macOS can run x86_64 programs via Rosetta and most M1 systems currently (~March 2021) very likely run a mix of x86_64 and arm64 processes. Activity Monitor can show the architecture: but command line tools such as ps and top do not due to Apple hiding the details\u2026","rel":"","context":"In &quot;Apple&quot;","block_context":{"text":"Apple","link":"https:\/\/rud.is\/b\/category\/apple\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":13365,"url":"https:\/\/rud.is\/b\/2022\/03\/13\/a-zsh-helper-script-for-updating-macos-rstudio-daily-electron-quarto-cli-installs\/","url_meta":{"origin":12537,"position":4},"title":"A zsh Helper Script For Updating macOS RStudio Daily Electron + Quarto CLI Installs","author":"hrbrmstr","date":"2022-03-13","format":false,"excerpt":"RStudio's macOS Electron build is coming along quite nicely and is blazing fast on Apple Silicon. I like to install the dailies, well, daily!; and, of late, RStudio and Quarto are joined at the hip. As a result, I regularly found myself having to manually update Quarto CLI right after\u2026","rel":"","context":"In &quot;macOS&quot;","block_context":{"text":"macOS","link":"https:\/\/rud.is\/b\/category\/macos\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":12497,"url":"https:\/\/rud.is\/b\/2019\/09\/14\/rswitch-1-5-0-release-now-also-corrals-rstudio-server-connections\/","url_meta":{"origin":12537,"position":5},"title":"RSwitch 1.5.0 Release Now Also Corrals RStudio Server Connections","author":"hrbrmstr","date":"2019-09-14","format":false,"excerpt":"RSwitch is a macOS menubar application that works on macOS 10.14+ and provides handy shortcuts for developing with R on macOS. Version 1.5.0 brings a reorganized menu system and the ability to manage and make connections to RStudio Server instances. Here's a quick peek at the new setup: All books,\u2026","rel":"","context":"In &quot;Apple&quot;","block_context":{"text":"Apple","link":"https:\/\/rud.is\/b\/category\/apple\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/09\/rswitch-1.5.0-rstudio-server.png?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/09\/rswitch-1.5.0-rstudio-server.png?resize=350%2C200 1x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/09\/rswitch-1.5.0-rstudio-server.png?resize=525%2C300 1.5x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/09\/rswitch-1.5.0-rstudio-server.png?resize=700%2C400 2x"},"classes":[]}],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/posts\/12537","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/comments?post=12537"}],"version-history":[{"count":0,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/posts\/12537\/revisions"}],"wp:attachment":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/media?parent=12537"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/categories?post=12537"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/tags?post=12537"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}