Skip to content

feat: add top apps by screen time percentage table to profile README#3952

Merged
marcusquinn merged 2 commits intomainfrom
feature/top-apps-table
Mar 9, 2026
Merged

feat: add top apps by screen time percentage table to profile README#3952
marcusquinn merged 2 commits intomainfrom
feature/top-apps-table

Conversation

@marcusquinn
Copy link
Owner

@marcusquinn marcusquinn commented Mar 9, 2026

Summary

  • Adds a "Top Apps by Screen Time" table to the GitHub profile README showing percentage share of foreground app time across Today / 7 Days / 28 Days
  • Queries macOS Knowledge DB /app/usage stream for per-app foreground time
  • Includes bundle ID to friendly name mapping for ~40 apps (system apps, Brave PWAs like GitHub/X/YouTube, third-party apps)
  • Percentages are accurate regardless of Knowledge DB coverage gaps — relative proportions are correct even when absolute hours undercount

Example output

| App | Today | 7 Days | 28 Days |
| --- | ---: | ---: | ---: |
| Tabby | 44% | 16% | 25% |
| Brave Browser | 21% | 19% | 17% |
| Slack | 11% | 12% | 9% |
| Mail | -- | 13% | 9% |
| X | 8% | 8% | 9% |

Testing

  • ShellCheck clean
  • generate command outputs correct table with real data
  • update --dry-run shows correct diff
  • update successfully pushed to profile repo (live at github.com/marcusquinn)

Summary by CodeRabbit

  • New Features
    • Added "Top Apps by Screen Time" section to generated statistics, displaying your most-used applications with usage percentages for today, the past week, and past month (macOS only).

Query macOS Knowledge DB /app/usage stream for per-app foreground time,
calculate percentage share across Today/7 Days/28 Days periods, and
render as a top-10 table in the profile README.

Includes bundle ID to friendly name mapping for system apps, common
third-party apps, and Brave PWAs (GitHub, X, YouTube, etc.).

Percentages are accurate regardless of Knowledge DB coverage gaps --
relative proportions between apps are correct even when absolute
hours undercount vs macOS Screen Time.
@github-actions github-actions bot added the enhancement Auto-created from TODO.md tag label Mar 9, 2026
@gemini-code-assist
Copy link

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a dynamic feature to enrich the GitHub profile README by displaying a 'Top Apps by Screen Time' table. It leverages macOS system data to provide insights into application usage, presenting a clear overview of how time is spent across various applications over different periods. This enhancement aims to offer a more personalized and informative profile without requiring manual updates.

Highlights

  • New Feature: Top Apps by Screen Time: Introduced a new section in the GitHub profile README that displays a table of top applications by screen time percentage across Today, 7 Days, and 28 Days.
  • macOS Knowledge DB Integration: Implemented logic to query the macOS Knowledge Database (knowledgeC.db) for per-app foreground usage data.
  • App Name Mapping: Included a comprehensive mapping of macOS bundle IDs to user-friendly application names for system, third-party, and Brave PWA applications.
  • Robust Percentage Calculation: Ensured that screen time percentages are accurately calculated, maintaining relative proportions even when the Knowledge DB might have coverage gaps.
Changelog
  • .agents/scripts/profile-readme-helper.sh
    • Added a new function _friendly_app_name to convert application bundle IDs into human-readable names.
    • Implemented _get_top_apps function to query the macOS Knowledge Database for app usage statistics and calculate screen time percentages.
    • Integrated the new app usage data into the README generation process, creating a formatted Markdown table.
    • Included logic to handle cases where app usage data is unavailable or zero, displaying '--' for percentages.
Activity
  • No human activity has been recorded on this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 9, 2026

Warning

Rate limit exceeded

@marcusquinn has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 6 minutes and 56 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e3d14afc-a9e5-4405-b9d0-825f7a633b13

📥 Commits

Reviewing files that changed from the base of the PR and between cab467b and 84240fd.

📒 Files selected for processing (1)
  • .agents/scripts/profile-readme-helper.sh

Walkthrough

Introduces macOS-specific screen-time tracking to the profile-readme-helper script by adding a new data collector that reads per-app usage metrics from the Knowledge database and displays them in a generated Markdown table with friendly app names.

Changes

Cohort / File(s) Summary
Top Apps Screen-Time Display
.agents/scripts/profile-readme-helper.sh
Adds _friendly_app_name() helper to map bundle IDs to human-readable app names; introduces _get_top_apps() to extract per-app usage data from macOS Knowledge database with percentage calculations (today, 7-day, 28-day windows); extends cmd_generate() to render "Top Apps by Screen Time" table when data is available, with fallback handling for missing or zero data.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

enhancement

Poem

📱 Know thy apps, by the screen's bright glow,
Where macOS secrets now proudly show,
From Knowledge's vault, the metrics flow—
Top apps by time, in a friendly table's row,
A profile enriched, with insights to know! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main feature addition: a new table displaying top apps by screen time percentage in the profile README.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/top-apps-table

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 9, 2026

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 392 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Mon Mar 9 03:03:10 UTC 2026: Code review monitoring started
Mon Mar 9 03:03:10 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 392

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 392
  • VULNERABILITIES: 0

Generated on: Mon Mar 9 03:03:13 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new feature to display top apps by screen time on the profile README. However, it also introduces significant security vulnerabilities, most notably a high-severity command injection flaw via bash arithmetic expansion and a medium-severity JSON injection flaw, stemming from trusting unvalidated data from the macOS Knowledge database. My review focuses on improving robustness, security, and performance by suggesting fixes like removing error suppression, using jq for safe JSON construction to prevent injection issues from special characters, consolidating jq calls for efficiency, and implementing strict input validation for variables used in arithmetic operations.

Comment on lines +288 to +294
today_pct=$(((today_s * 100 + total_today / 2) / total_today))
fi
if [[ $total_week -gt 0 ]]; then
week_pct=$(((week_s * 100 + total_week / 2) / total_week))
fi
if [[ $total_month -gt 0 ]]; then
month_pct=$(((month_s * 100 + total_month / 2) / total_month))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

The variables today_s, week_s, and month_s (lines 288, 291, 294) are used in arithmetic expansions without validation. These values, derived from the external Knowledge database, can be manipulated via crafted bundle IDs, posing a high-severity command injection risk. Additionally, the current manual JSON string concatenation is fragile and susceptible to issues if app names contain special characters. It is recommended to implement strict input validation for these variables and use a robust method like jq for safe JSON construction to mitigate both the command injection and JSON fragility issues.

Comment on lines +268 to +270
total_today=$((total_today + today_s))
total_week=$((total_week + week_s))
total_month=$((total_month + month_s))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

The script is vulnerable to command injection via bash arithmetic expansion. The variables today_s, week_s, and month_s are populated from the macOS Knowledge database (knowledgeC.db), which contains app bundle IDs. An attacker can influence this database by running an app with a crafted bundle ID containing a payload like |a[$(id >&2)0]. When these values are used in an arithmetic context $((...)), bash evaluates the embedded command. This could allow a malicious app to execute arbitrary commands with the privileges of the script, potentially stealing GitHub tokens or other sensitive data.

Suggested change
total_today=$((total_today + today_s))
total_week=$((total_week + week_s))
total_month=$((total_month + month_s))
[[ "$today_s" =~ ^[0-9]+$ ]] && total_today=$((total_today + today_s))
[[ "$week_s" =~ ^[0-9]+$ ]] && total_week=$((total_week + week_s))
[[ "$month_s" =~ ^[0-9]+$ ]] && total_month=$((total_month + month_s))

else
json_arr="${json_arr},"
fi
json_arr="${json_arr}{\"app\":\"${name}\",\"today_pct\":${today_pct},\"week_pct\":${week_pct},\"month_pct\":${month_pct}}"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

The script constructs a JSON string by direct variable interpolation. If the app name (derived from the bundle ID) contains double quotes or other JSON-special characters, it will result in invalid JSON or allow for JSON injection. This can cause the script to fail when parsing with jq or allow an attacker to inject arbitrary data into the generated profile README.

Suggested change
json_arr="${json_arr}{\"app\":\"${name}\",\"today_pct\":${today_pct},\"week_pct\":${week_pct},\"month_pct\":${month_pct}}"
json_arr="${json_arr}{\"app\":$(jq -n --arg name "$name" '$name'),\"today_pct\":${today_pct},\"week_pct\":${week_pct},\"month_pct\":${month_pct}}"
References
  1. In shell scripts, use jq --arg for strings and --argjson for other JSON types (like numbers) to safely pass variables into a jq filter. This avoids syntax errors if the variables contain special characters.
  2. To reliably wrap the entire content of a shell variable as a single JSON string, use jq -Rn --arg v "$VAR" '$v'. This is more robust than piping the variable to jq -Rs '.'.

AND ZSTARTDATE > (strftime('%s', 'now') - 978307200 - 86400*28)
GROUP BY ZVALUESTRING
HAVING month_secs > 0;
" 2>/dev/null) || {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

You're suppressing stderr from the sqlite3 command by redirecting it to /dev/null. This can hide important errors, such as a corrupted database, syntax errors in the query, or sqlite3 not being available, which makes debugging difficult. It's better to allow error messages to be printed to stderr. The || { ... } construct will still correctly handle the failure and prevent the script from exiting.

Suggested change
" 2>/dev/null) || {
") || {
References
  1. Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.

Comment on lines +532 to +535
app=$(echo "$row" | jq -r '.app')
today_pct=$(echo "$row" | jq -r '.today_pct')
week_pct=$(echo "$row" | jq -r '.week_pct')
month_pct=$(echo "$row" | jq -r '.month_pct')

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

You are calling jq four times inside a loop to extract values from a single JSON object. This is inefficient. You can consolidate these into a single jq call and use read to populate the variables. This is more performant and idiomatic.

Suggested change
app=$(echo "$row" | jq -r '.app')
today_pct=$(echo "$row" | jq -r '.today_pct')
week_pct=$(echo "$row" | jq -r '.week_pct')
month_pct=$(echo "$row" | jq -r '.month_pct')
IFS=$'\t' read -r app today_pct week_pct month_pct < <(echo "$row" | jq -r '[.app, .today_pct, .week_pct, .month_pct] | @tsv')
References
  1. Consolidate multiple 'jq' calls into a single pass where possible to improve performance and script efficiency.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
.agents/scripts/profile-readme-helper.sh (1)

297-307: Consider using jq for JSON construction to ensure proper escaping.

The manual JSON string building works correctly with the current _friendly_app_name mappings since all return values are safe strings. However, if a bundle ID's final component ever contained a quote or backslash, this could produce malformed JSON.

For zero-tech-debt robustness, consider using jq to safely construct the JSON objects:

♻️ Optional: Use jq for safer JSON construction
-		json_arr="${json_arr}{\"app\":\"${name}\",\"today_pct\":${today_pct},\"week_pct\":${week_pct},\"month_pct\":${month_pct}}"
+		local entry
+		entry=$(jq -n --arg app "$name" --argjson t "$today_pct" --argjson w "$week_pct" --argjson m "$month_pct" \
+			'{app: $app, today_pct: $t, week_pct: $w, month_pct: $m}')
+		json_arr="${json_arr}${entry}"

This is a defensive improvement — the current implementation is functional given the controlled inputs.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agents/scripts/profile-readme-helper.sh around lines 297 - 307, The current
loop builds json_arr by concatenating strings (variables json_arr, name,
today_pct, week_pct, month_pct) which can produce invalid JSON if app names
contain quotes/backslashes; replace the manual concatenation with jq-based
construction: for each record use jq -n to create an object with --arg for the
app name (from _friendly_app_name/name) and --argjson for numeric fields
(today_pct, week_pct, month_pct), then collect objects into an array (e.g.,
piping objects into jq -s to produce the final array) and echo that result
instead of the hand-assembled json_arr.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In @.agents/scripts/profile-readme-helper.sh:
- Around line 297-307: The current loop builds json_arr by concatenating strings
(variables json_arr, name, today_pct, week_pct, month_pct) which can produce
invalid JSON if app names contain quotes/backslashes; replace the manual
concatenation with jq-based construction: for each record use jq -n to create an
object with --arg for the app name (from _friendly_app_name/name) and --argjson
for numeric fields (today_pct, week_pct, month_pct), then collect objects into
an array (e.g., piping objects into jq -s to produce the final array) and echo
that result instead of the hand-assembled json_arr.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: fe709e97-7dd1-4ae3-a295-2403c9c89717

📥 Commits

Reviewing files that changed from the base of the PR and between e60858d and cab467b.

📒 Files selected for processing (1)
  • .agents/scripts/profile-readme-helper.sh

Address CodeRabbit review: validate that sqlite3 output values are
integers before using in bash arithmetic (prevents injection via
crafted DB records), and use jq --arg for JSON construction instead
of string interpolation (prevents injection from special characters
in app names).
@github-actions
Copy link
Contributor

github-actions bot commented Mar 9, 2026

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 392 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Mon Mar 9 03:07:48 UTC 2026: Code review monitoring started
Mon Mar 9 03:07:48 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 392

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 392
  • VULNERABILITIES: 0

Generated on: Mon Mar 9 03:07:51 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 9, 2026

@marcusquinn marcusquinn merged commit 1b906f2 into main Mar 9, 2026
12 checks passed
@marcusquinn marcusquinn deleted the feature/top-apps-table branch March 9, 2026 03:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Auto-created from TODO.md tag

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant