<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>T KOLSTO · Tagged macos</title><link>https://t.kolsto.no/tags/macos/</link><description>Posts on technology, infrastructure, and startups by Thomas Kolstø.</description><generator>Hugo</generator><language>en</language><copyright>© 2010 - 2026 Thomas Kolstø</copyright><lastBuildDate>Sun, 04 Oct 2026 05:15:00 +0000</lastBuildDate><atom:link href="https://t.kolsto.no/tags/macos/" rel="self" type="application/rss+xml"/><image><url>https://t.kolsto.no/img/avatar.jpg</url><title>T KOLSTO · Tagged macos</title><link>https://t.kolsto.no/tags/macos/</link></image><item><title>Eight Arms, All Billable</title><link>https://t.kolsto.no/blog/clocktopus/</link><pubDate>Sun, 04 Oct 2026 05:15:00 +0000</pubDate><guid>https://t.kolsto.no/blog/clocktopus/</guid><dc:creator>Thomas Kolstø</dc:creator><category>clocktopus</category><category>macos</category><category>swift</category><category>sidequest</category><category>time-tracking</category><description>Clocktopus is a local macOS time tracker that suggests work sessions and asks before recording them. No screenshots, no cloud. Suggest, never surveil.</description><enclosure url="https://t.kolsto.no/img/clocktopus-share-v1.png" length="51601" type="image/png"/><content:encoded>&lt;p&gt;I used to perform a ritual every Friday that I suspect you&amp;rsquo;ll recognize. Timesheets were due in xledger—hours split across projects and activities because my time belonged to multiple budgets. I would fill them out with the confidence of someone who had been present all week, only to realize I couldn&amp;rsquo;t recall what I&amp;rsquo;d actually done.&lt;/p&gt;&#10;&lt;p&gt;So, I reconstructed it: running &lt;code&gt;git log --since=monday&lt;/code&gt; across repos, checking calendars for meetings, and scrolling Slack history to account for missing time. Then I translated this archaeology into tidy quarter-hour blocks and submitted it as fact.&lt;/p&gt;&#10;&lt;p&gt;Memory is the worst database. It lacks a write-ahead log, runs compaction nightly whether you like it or not, and every query returns a plausible answer with no indication of its truthfulness.&lt;/p&gt;&#10;&lt;h2 id="the-tools-are-all-wrong"&gt;The tools are all wrong&lt;/h2&gt;&#10;&lt;p&gt;The obvious fix is a timer: start when working, stop when done, making Friday an export button. But manual trackers fail because they require &lt;em&gt;remembering&lt;/em&gt; to use them. I don&amp;rsquo;t forget how to work; I forget to say that I am working. Any tool relying on me forming a new habit at the precise moment my brain is busy with something else is designed to fail. My collection of abandoned timewarrior databases proves this.&lt;/p&gt;&#10;&lt;p&gt;At the other end are &amp;ldquo;automatic&amp;rdquo; trackers. They solve forgetting by removing you from the loop entirely. They screenshot your screen every thirty seconds, run it through AI, and upload &amp;ldquo;productivity insights&amp;rdquo; to a cloud dashboard—often read by your manager. I work with patient data for a telemedicine company. A tool that photographs my display and posts it to someone else&amp;rsquo;s cloud isn&amp;rsquo;t an aid; it&amp;rsquo;s an incident report with a subscription fee.&lt;/p&gt;&#10;&lt;p&gt;This leaves a gap: one end trusts you to remember, the other doesn&amp;rsquo;t trust you at all.&lt;/p&gt;&#10;&lt;h2 id="the-sidequest"&gt;The sidequest&lt;/h2&gt;&#10;&lt;p&gt;So, obviously, I built one. This is a proper sidequest: no cloud, no accounts, no roadmap committee, and no ambitions of becoming a company. Just the tracker I wanted, built how any tool touching my work machine should be.&lt;/p&gt;&#10;&lt;p&gt;It&amp;rsquo;s called &lt;a href="https://github.com/tkolsto/clocktopus"&gt;Clocktopus&lt;/a&gt;. Eight arms, all billable.&lt;/p&gt;&#10;&lt;img src="https://t.kolsto.no/img/clocktopus-popover.webp" alt="Clocktopus menubar popover with a running timer, project list, and weekly activity chart" width="600" height="764" loading="lazy"&gt;&#10;&lt;p&gt;The insight is embarrassingly simple: your machine already knows what you&amp;rsquo;re working on. Not via AI—but via &lt;code&gt;pwd&lt;/code&gt;. My shells are cd&amp;rsquo;d into a client&amp;rsquo;s repo. My tmux panes sit in project directories. A running process has a working directory that names the project outright. The frontmost window title shows the open codebase. None of this needs a vision model; it needs a scorer over deterministic signals and a config file where &lt;em&gt;you&lt;/em&gt; write the rules:&lt;/p&gt;&#10;&lt;div class="tk-code"&gt;&lt;div class="tk-code__tools"&gt;&lt;span class="tk-code__lang"&gt;toml&lt;/span&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="nx"&gt;project&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Initech&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;xledger_project&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;T200001&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;xledger_activity&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;DEV&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;dirs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;~/src/initech*&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c"&gt;# shell / tmux / AI-agent cwds&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;keywords&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;initech&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c"&gt;# frontmost window title&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;Longest prefix wins, so &lt;code&gt;~/src/initech-api&lt;/code&gt; beats your &lt;code&gt;~/src&lt;/code&gt; catch-all. Every rule is yours, in a version-controllable TOML file, and every guess shows exactly which signals fired. No vibes.&lt;/p&gt;&#10;&lt;h2 id="suggest-never-surveil"&gt;Suggest, never surveil&lt;/h2&gt;&#10;&lt;p&gt;This is the core feature. When a project holds my focus for minutes, Clocktopus doesn&amp;rsquo;t clock me in. It &lt;em&gt;asks&lt;/em&gt;. A dashed ghost block appears on the day timeline—&amp;ldquo;is this Initech?&amp;quot;—with evidence attached. One click confirms it, backfilling to when I started (the whole point: the app remembers the start time I was too busy to announce). One click dismisses it. Nothing lands in the database without my say-so.&lt;/p&gt;&#10;&lt;img src="https://t.kolsto.no/img/clocktopus-day-timeline.webp" alt="Clocktopus day timeline with a dashed ghost block suggesting a detected work session" width="1800" height="1800" srcset="https://t.kolsto.no/img/clocktopus-day-timeline_hu_6a68ec9bc18832fe.webp 720w, https://t.kolsto.no/img/clocktopus-day-timeline_hu_228a98bf6b529b21.webp 1440w, https://t.kolsto.no/img/clocktopus-day-timeline.webp 1800w" sizes="(min-width: 1120px) 1040px, (min-width: 601px) calc(100vw - 80px), calc(100vw - 40px)" loading="eager" fetchpriority="high"&gt;&#10;&lt;p&gt;The surveillance question is settled by architecture, not policy: the app makes zero network requests. Not for sync, telemetry, or updates—grep the source. Your hours are one SQLite file in &lt;code&gt;~/Library/Application Support&lt;/code&gt;, and the only thing leaving the machine is the CSV you export yourself.&lt;/p&gt;&#10;&lt;h2 id="friday-after"&gt;Friday, after&lt;/h2&gt;&#10;&lt;p&gt;The ritual now: open the week grid (ISO weeks, Monday start), with per-project totals already rounded to the billing increment. I skim it, nudge a block edge if the octopus and I disagree about lunch, and export. The CSV speaks xledger&amp;rsquo;s upload dialect—semicolon-separated, &lt;code&gt;yyyymmdd&lt;/code&gt; dates, decimal hours—because that&amp;rsquo;s what my Fridays demanded, but it&amp;rsquo;s just CSV; point it at whatever your accounting department worships.&lt;/p&gt;&#10;&lt;img src="https://t.kolsto.no/img/clocktopus-week-grid.webp" alt="Clocktopus week review with per-project hours, separate billable and personal totals, and CSV export" width="1800" height="1380" srcset="https://t.kolsto.no/img/clocktopus-week-grid_hu_e107ec88c1b571e0.webp 720w, https://t.kolsto.no/img/clocktopus-week-grid_hu_2e807c2023dde021.webp 1440w, https://t.kolsto.no/img/clocktopus-week-grid.webp 1800w" sizes="(min-width: 1120px) 1040px, (min-width: 601px) calc(100vw - 80px), calc(100vw - 40px)" loading="lazy"&gt;&#10;&lt;p&gt;The archaeology is gone. That&amp;rsquo;s the entire return on investment, and it pays out weekly.&lt;/p&gt;&#10;&lt;h2 id="questions-youre-already-typing"&gt;Questions you&amp;rsquo;re already typing&lt;/h2&gt;&#10;&lt;p&gt;&lt;strong&gt;&amp;ldquo;Why not ActivityWatch?&amp;rdquo;&lt;/strong&gt; A genuinely good project for passive analytics—it lets you study yourself afterwards. Clocktopus is suggest-and-confirm for &lt;em&gt;billing&lt;/em&gt;: nothing is recorded until you approve it, and the output is a timesheet, not a chart. And timewarrior is fine, but it still trusts me to remember. We&amp;rsquo;ve established how that goes.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;&amp;ldquo;Linux port?&amp;rdquo;&lt;/strong&gt; The core—domain models, scoring, rounding, export, ~90 tests—is a pure SwiftPM package with no AppKit, so it&amp;rsquo;s portable-ish. Signal collectors are the macOS-specific part. If cwd-sniffing on Linux sounds interesting, the repo is MIT.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;&amp;ldquo;Why isn&amp;rsquo;t it notarized?&amp;rdquo;&lt;/strong&gt; An Apple Developer ID is $99/year, and this octopus is young. The release build is ad-hoc signed: right-click to open the first time, or build from source (Gatekeeper has no opinions).&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;&amp;ldquo;Can a tmux pane I forgot about bill a client from three days ago?&amp;rdquo;&lt;/strong&gt; No. This was the heuristic I sweated most. Background signals—parked panes, long-running agent sessions—can only &lt;em&gt;reinforce&lt;/em&gt; a project that also has foreground evidence. A forgotten pane can&amp;rsquo;t clock you in on its own; it can only corroborate what you are demonstrably looking at.&lt;/p&gt;&#10;&lt;h2 id="coda"&gt;Coda&lt;/h2&gt;&#10;&lt;p&gt;Clocktopus is &lt;a href="https://github.com/tkolsto/clocktopus"&gt;on GitHub&lt;/a&gt;, MIT licensed, macOS 13+, Swift/SwiftUI, native menubar app. It has exactly one user in production, whose Fridays are much improved. If your accounting department also worships a CSV, maybe it&amp;rsquo;ll improve yours.&lt;/p&gt;&#10;</content:encoded></item></channel></rss>