<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Notes on Jonathan Dean</title>
    <link>https://jondean.com/notes/</link>
    <description>Recent content in Notes on Jonathan Dean</description>
    <generator>Hugo</generator>
    <language>en</language>
    <lastBuildDate>Sun, 01 Feb 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://jondean.com/notes/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Per-Product Cursor AI Metrics from the Dashboard Export</title>
      <link>https://jondean.com/notes/cursor-ai-metrics-by-product/</link>
      <pubDate>Sun, 01 Feb 2026 00:00:00 +0000</pubDate>
      <guid>https://jondean.com/notes/cursor-ai-metrics-by-product/</guid>
      <description>&lt;p&gt;I built a tool to produce a per-product breakdown of AI-generated lines. If you&#xA;must report that figure and your products span multiple repositories, Cursor&#xA;gives you per-repository data. Getting to a per-product view means combining it&#xA;with something that knows your repo-to-project mapping.&lt;/p&gt;&#xA;&lt;h2 id=&#34;getting-the-data&#34;&gt;&#xA;  Getting the data&#xA;  &lt;a class=&#34;heading-link&#34; href=&#34;#getting-the-data&#34;&gt;&#xA;    &lt;i class=&#34;fa-solid fa-link&#34; aria-hidden=&#34;true&#34; title=&#34;Link to heading&#34;&gt;&lt;/i&gt;&#xA;    &lt;span class=&#34;sr-only&#34;&gt;Link to heading&lt;/span&gt;&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;The data is in Cursor&amp;rsquo;s analytics dashboard. The approach: connect to an existing&#xA;Chrome session via the&#xA;&lt;a href=&#34;https://chromedevtools.github.io/devtools-protocol/&#34;  class=&#34;external-link&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chrome DevTools Protocol&lt;/a&gt;&#xA;rather than building an authentication flow. Playwright attaches to a running&#xA;Chrome instance, navigates to the dashboard as the already-logged-in user, and&#xA;downloads the CSV export for each repository.&lt;/p&gt;</description>
    </item>
    <item>
      <title>NFS for Desktops, Syncthing for Laptops</title>
      <link>https://jondean.com/notes/nfs-desktops-syncthing-laptops/</link>
      <pubDate>Sat, 15 Nov 2025 00:00:00 +0000</pubDate>
      <guid>https://jondean.com/notes/nfs-desktops-syncthing-laptops/</guid>
      <description>&lt;p&gt;I have two kinds of Linux machine at home: desktops that are always connected to the network, and laptops that are not. That distinction drives everything about how home directories work.&lt;/p&gt;&#xA;&lt;h2 id=&#34;desktops-nfs-transparently&#34;&gt;&#xA;  Desktops: NFS, transparently&#xA;  &lt;a class=&#34;heading-link&#34; href=&#34;#desktops-nfs-transparently&#34;&gt;&#xA;    &lt;i class=&#34;fa-solid fa-link&#34; aria-hidden=&#34;true&#34; title=&#34;Link to heading&#34;&gt;&lt;/i&gt;&#xA;    &lt;span class=&#34;sr-only&#34;&gt;Link to heading&lt;/span&gt;&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;On desktops, &lt;code&gt;/home&lt;/code&gt; is the NFS mount. There is no local home directory: the server&amp;rsquo;s storage is the home directory. Log in and your files are there. No sync, no waiting, no copies to reconcile. The mount happens over Tailscale, so it works from anywhere on the tailnet, not just on the local network.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Home Infrastructure as Debian Packages</title>
      <link>https://jondean.com/notes/home-infra-as-debian-packages/</link>
      <pubDate>Wed, 15 Oct 2025 00:00:00 +0000</pubDate>
      <guid>https://jondean.com/notes/home-infra-as-debian-packages/</guid>
      <description>&lt;p&gt;I have half a dozen Linux machines at home: a primary server, a cloud VM, three desktops, two laptops, and the occasional test VM. For a long time, configuration was a mixture of manual steps, shell scripts, and remembered knowledge. That worked fine until it did not, when setting up a new machine meant either repeating all those steps from memory or reverse-engineering what the others had installed.&lt;/p&gt;&#xA;&lt;p&gt;The fix I landed on was to stop treating home infrastructure as something you configure and start treating it as something you deploy. Every configuration decision is now a Debian package. New machine? &lt;code&gt;sudo apt install dean-network-client&lt;/code&gt;. Done.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Combining the Cursor and Copilot APIs</title>
      <link>https://jondean.com/notes/combining-cursor-and-copilot-apis/</link>
      <pubDate>Thu, 09 Oct 2025 00:00:00 +0000</pubDate>
      <guid>https://jondean.com/notes/combining-cursor-and-copilot-apis/</guid>
      <description>&lt;p&gt;I built a dashboard pulling usage data from the Cursor admin API and the GitHub Copilot API into a single view.&lt;/p&gt;&#xA;&lt;figure&gt;&#xA;  &lt;img src=&#34;https://jondean.com/images/aistats/combined-overview.png&#34; alt=&#34;Combined analytics dashboard showing Cursor and Copilot data side by side, with activity trends and language usage charts&#34;&gt;&#xA;  &lt;figcaption&gt;Illustrative data, generated for this post rather than taken from real usage. The combined view: Copilot numbers are org-level aggregates; Cursor data is per-engineer.&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;h2 id=&#34;two-apis-different-shapes&#34;&gt;&#xA;  Two APIs, different shapes&#xA;  &lt;a class=&#34;heading-link&#34; href=&#34;#two-apis-different-shapes&#34;&gt;&#xA;    &lt;i class=&#34;fa-solid fa-link&#34; aria-hidden=&#34;true&#34; title=&#34;Link to heading&#34;&gt;&lt;/i&gt;&#xA;    &lt;span class=&#34;sr-only&#34;&gt;Link to heading&lt;/span&gt;&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;The problem is that Cursor and Copilot expose fundamentally different data.&lt;/p&gt;</description>
    </item>
    <item>
      <title>What the Jira Changelog Tells You About a Sprint</title>
      <link>https://jondean.com/notes/jira-changelog-sprint-reality/</link>
      <pubDate>Fri, 19 Sep 2025 00:00:00 +0000</pubDate>
      <guid>https://jondean.com/notes/jira-changelog-sprint-reality/</guid>
      <description>&lt;p&gt;When I built a sprint analytics dashboard on top of the Jira REST API, I kept&#xA;running into the same problem: standard queries return the current state of each&#xA;issue. That tells you where things stand now, not what the sprint actually looked&#xA;like while it was running.&lt;/p&gt;&#xA;&lt;p&gt;The changelog is the answer. Every Jira issue carries a complete record of every&#xA;field transition ever made, with a timestamp for each. Include &lt;code&gt;expand=changelog&lt;/code&gt;&#xA;in the &lt;a href=&#34;https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issue-search/&#34;  class=&#34;external-link&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;search request&lt;/a&gt;&#xA;and it comes back alongside the issue data, or fetch it separately via the&#xA;&lt;a href=&#34;https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issues/&#34;  class=&#34;external-link&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;issue changelog endpoint&lt;/a&gt;.&#xA;Most integrations ignore it. It is worth paying attention to.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
