<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>projects &#8211; Zachary Hamed</title>
	<atom:link href="https://zmh.org/tag/projects/feed/" rel="self" type="application/rss+xml" />
	<link>https://zmh.org/</link>
	<description></description>
	<lastBuildDate>Tue, 14 Apr 2026 11:35:18 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/12/cropped-favicon-zmh.gif?fit=32%2C32&#038;ssl=1</url>
	<title>projects &#8211; Zachary Hamed</title>
	<link>https://zmh.org/</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">239930377</site>	<item>
		<title>Personal Site Gallery</title>
		<link>https://zmh.org/personal-site-gallery/</link>
					<comments>https://zmh.org/personal-site-gallery/#respond</comments>
		
		<dc:creator><![CDATA[zacharyhamed]]></dc:creator>
		<pubDate>Mon, 13 Apr 2026 06:47:20 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[projects]]></category>
		<guid isPermaLink="false">https://zmh.org/?p=2541</guid>

					<description><![CDATA[I’ve put together what I think is currently the most comprehensive directory of personal sites available on the internet today. 31,000+ personal web p]]></description>
										<content:encoded><![CDATA[
<p>I’ve put together what I think is currently the most comprehensive directory of personal sites available on the internet today. 31,000+ personal web pages, screenshotted for easy browsing and tagged with visual characteristics so you can search through them very easily.</p>



<p>Give it a try at <a href="https://zmh.github.io/personal-site-gallery/">zmh.github.io/personal-site-gallery/</a></p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4f873de816&quot;}" data-wp-interactive="core/image" data-wp-key="69e4f873de816" class="wp-block-image size-large wp-lightbox-container"><img data-recalc-dims="1" fetchpriority="high" decoding="async" width="1024" height="732" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-13-at-14.44.20%402x.png?resize=1024%2C732&#038;quality=80&#038;ssl=1" alt="" class="wp-image-2542" srcset="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-13-at-14.44.20%402x-scaled.png?resize=1024%2C732&amp;quality=80&amp;ssl=1 1024w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-13-at-14.44.20%402x-scaled.png?resize=300%2C215&amp;quality=80&amp;ssl=1 300w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-13-at-14.44.20%402x-scaled.png?resize=768%2C549&amp;quality=80&amp;ssl=1 768w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-13-at-14.44.20%402x-scaled.png?resize=1536%2C1098&amp;quality=80&amp;ssl=1 1536w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-13-at-14.44.20%402x-scaled.png?resize=2048%2C1465&amp;quality=80&amp;ssl=1 2048w" sizes="(max-width: 1000px) 100vw, 1000px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>
]]></content:encoded>
					
					<wfw:commentRss>https://zmh.org/personal-site-gallery/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2541</post-id>	</item>
		<item>
		<title>Dispatch</title>
		<link>https://zmh.org/dispatch/</link>
					<comments>https://zmh.org/dispatch/#respond</comments>
		
		<dc:creator><![CDATA[zacharyhamed]]></dc:creator>
		<pubDate>Wed, 08 Apr 2026 16:49:29 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[projects]]></category>
		<guid isPermaLink="false">https://zmh.org/?p=2519</guid>

					<description><![CDATA[An opinionated, focused inbox for Slack.

https://x.com/youyuxi/status/2036298146704400793]]></description>
										<content:encoded><![CDATA[
<h3 class="wp-block-heading"><span style="font-family: var(--editor-font-family); font-size: var(--editor-font-size);">A focused inbox for Slack.</span></h3>



<figure class="wp-block-gallery has-nested-images columns-3 is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex">
<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4f873e72cc&quot;}" data-wp-interactive="core/image" data-wp-key="69e4f873e72cc" class="wp-block-image size-large wp-lightbox-container"><img data-recalc-dims="1" decoding="async" width="1024" height="859" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" data-id="2529" src="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-08-at-01.14.00%402x.png?resize=1024%2C859&#038;quality=80&#038;ssl=1" alt="" class="wp-image-2529" srcset="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-08-at-01.14.00%402x.png?resize=1024%2C859&amp;quality=80&amp;ssl=1 1024w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-08-at-01.14.00%402x.png?resize=300%2C252&amp;quality=80&amp;ssl=1 300w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-08-at-01.14.00%402x.png?resize=768%2C644&amp;quality=80&amp;ssl=1 768w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-08-at-01.14.00%402x.png?resize=1536%2C1288&amp;quality=80&amp;ssl=1 1536w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-08-at-01.14.00%402x.png?resize=2048%2C1717&amp;quality=80&amp;ssl=1 2048w" sizes="(max-width: 1000px) 100vw, 1000px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4f873e8465&quot;}" data-wp-interactive="core/image" data-wp-key="69e4f873e8465" class="wp-block-image size-large wp-lightbox-container"><img data-recalc-dims="1" decoding="async" width="1024" height="825" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" data-id="2527" src="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-08-at-01.09.29%402x.png?resize=1024%2C825&#038;quality=80&#038;ssl=1" alt="" class="wp-image-2527" srcset="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-08-at-01.09.29%402x.png?resize=1024%2C825&amp;quality=80&amp;ssl=1 1024w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-08-at-01.09.29%402x.png?resize=300%2C242&amp;quality=80&amp;ssl=1 300w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-08-at-01.09.29%402x.png?resize=768%2C619&amp;quality=80&amp;ssl=1 768w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-08-at-01.09.29%402x.png?resize=1536%2C1238&amp;quality=80&amp;ssl=1 1536w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-08-at-01.09.29%402x.png?w=1908&amp;quality=80&amp;ssl=1 1908w" sizes="(max-width: 1000px) 100vw, 1000px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4f873e9504&quot;}" data-wp-interactive="core/image" data-wp-key="69e4f873e9504" class="wp-block-image size-large wp-lightbox-container"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="859" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" data-id="2528" src="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-08-at-01.10.50%402x.png?resize=1024%2C859&#038;quality=80&#038;ssl=1" alt="" class="wp-image-2528" srcset="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-08-at-01.10.50%402x.png?resize=1024%2C859&amp;quality=80&amp;ssl=1 1024w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-08-at-01.10.50%402x.png?resize=300%2C252&amp;quality=80&amp;ssl=1 300w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-08-at-01.10.50%402x.png?resize=768%2C644&amp;quality=80&amp;ssl=1 768w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-08-at-01.10.50%402x.png?resize=1536%2C1288&amp;quality=80&amp;ssl=1 1536w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-08-at-01.10.50%402x.png?resize=2048%2C1717&amp;quality=80&amp;ssl=1 2048w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4f873eaa47&quot;}" data-wp-interactive="core/image" data-wp-key="69e4f873eaa47" class="wp-block-image size-large wp-lightbox-container"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="825" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" data-id="2526" src="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-08-at-01.09.20%402x.png?resize=1024%2C825&#038;quality=80&#038;ssl=1" alt="" class="wp-image-2526" srcset="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-08-at-01.09.20%402x.png?resize=1024%2C825&amp;quality=80&amp;ssl=1 1024w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-08-at-01.09.20%402x.png?resize=300%2C242&amp;quality=80&amp;ssl=1 300w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-08-at-01.09.20%402x.png?resize=768%2C619&amp;quality=80&amp;ssl=1 768w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-08-at-01.09.20%402x.png?resize=1536%2C1238&amp;quality=80&amp;ssl=1 1536w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/04/CleanShot-2026-04-08-at-01.09.20%402x.png?w=1908&amp;quality=80&amp;ssl=1 1908w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>
</figure>



<p>I hate how Slack&#8217;s Activity and Catch Up features work, so I built <a href="https://github.com/zmh/dispatch">Dispatch</a>, an opinionated and focused inbox for Slack. Sort of like Superhuman for Slack — never miss an important message, and triage your inbox quickly.</p>



<ol class="wp-block-list">
<li>Add your Slack cookie so it can connect to your workspace. Everything happens locally.</li>



<li>Choose what messages you want brought into Dispatch. Mentions are included by default. You can additionally specify people or channels. For example, I have people I work most closely with and senior execs listed, along with a few whole-company channels I know might be relevant.</li>



<li>All the messages imported by the above will be categorized into split inboxes or categories, based either on simple keywords (e.g. <code>from:@Matt</code> should be filtered into the Important inbox) or, optionally, with Claude Haiku using a prompt you can configure. If you choose to enable Claude, you&#8217;ll effectively have a little assistant categorizing each message into a bucket based on your description.</li>



<li>Go through each inbox. Star, snooze, or mark messages as done with keyboard shortcuts. Hit enter to read more or reply in Slack directly.</li>
</ol>



<p>This lets you treat Slack just like email. Messages come in, get filtered into inboxes, and then you can action them quickly. </p>



<p>The design is inspired by Superhuman Mail, as well as a now-defunct alternative Slack client I used and loved called <a href="https://cancel.fm/ripcord/">Ripcord</a>. Dispatch is typography-heavy and very dense, with inspiration and guidance from Matthew Butterick&#8217;s <em><a href="https://practicaltypography.com/">Practical Typography</a></em>, which argues that typography (font size, spacing, and density) are the primary interface of any text-heavy app. Dispatch uses SF Pro at 13px with tight row heights so you can scan dozens of messages without wasted space, and lets you switch to monospace or adjust sizes from 11–18px, because good typography respects the reader&#8217;s context. Just enough structure to let you read fast and act. </p>



<p>There are <s>probably</s> definitely bugs, but I&#8217;ve been using it for the past few days and it&#8217;s helped cut through a lot of the noise on Slack. <a href="https://github.com/zmh/dispatch">Give it a try</a> and let me know what you think!</p>



<p>Why build a Slack client? For years, I&#8217;ve been fed up with how Slack treats channels, messages, and threads. Channels are too noisy, important context gets lost in threads, the Activity view captures a subset of actionable items, and notifications often don&#8217;t fire. And seemingly most of the internet agrees with me:</p>



<figure class="wp-block-embed is-type-rich is-provider-twitter wp-block-embed-twitter"><div class="wp-block-embed__wrapper">
<div class="embed-twitter"><blockquote class="twitter-tweet" data-width="500" data-dnt="true"><p lang="en" dir="ltr">&quot;graveyard of unread messages&quot; is a very accurate description &#8211; the default state of every Slack workspace eventually becomes a pile of things nobody actually got back to</p>&mdash; Josh Jackson (@IamJoshJackson) <a href="https://twitter.com/IamJoshJackson/status/2038797159047496129?ref_src=twsrc%5Etfw">March 31, 2026</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></div>
</div></figure>



<figure class="wp-block-embed is-type-rich is-provider-twitter wp-block-embed-twitter"><div class="wp-block-embed__wrapper">
<div class="embed-twitter"><blockquote class="twitter-tweet" data-width="500" data-dnt="true"><p lang="en" dir="ltr">Is Slack performance degrading for anyone else?<br><br>Thread content sometimes loads, alerts usually happen, reactions appear and disappear, channels aren&#39;t marked as unread sometimes.</p>&mdash; Ryan Jones (@rjonesy) <a href="https://twitter.com/rjonesy/status/1832099839586537770?ref_src=twsrc%5Etfw">September 6, 2024</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></div>
</div></figure>



<figure class="wp-block-embed is-type-rich is-provider-twitter wp-block-embed-twitter"><div class="wp-block-embed__wrapper">
<div class="embed-twitter"><blockquote class="twitter-tweet" data-width="500" data-dnt="true"><p lang="en" dir="ltr">Slack is always broken. How is this error even happening?<br><br>* Activity: 1 notification<br>* Click on Activity<br>* No activity listed<br><br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f635-200d-1f4ab.png" alt="😵‍💫" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <a href="https://t.co/y0h5kpuWqH">pic.twitter.com/y0h5kpuWqH</a></p>&mdash; Anastasios Nikolas Angelopoulos (@ml_angelopoulos) <a href="https://twitter.com/ml_angelopoulos/status/2028624751942668659?ref_src=twsrc%5Etfw">March 3, 2026</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></div>
</div></figure>



<figure class="wp-block-embed is-type-rich is-provider-twitter wp-block-embed-twitter"><div class="wp-block-embed__wrapper">
<div class="embed-twitter"><blockquote class="twitter-tweet" data-width="500" data-dnt="true"><p lang="en" dir="ltr">Slack is where context goes to die. By thread 200 you can&#39;t find anything. Async tools that force structured thinking beat it every time for small teams doing real work.</p>&mdash; Teddy Gyabaah (@teddykabg) <a href="https://twitter.com/teddykabg/status/2034584165799145768?ref_src=twsrc%5Etfw">March 19, 2026</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></div>
</div></figure>



<p>If someone doesn&#8217;t @-mention you or the channel, the only way you&#8217;ll see that message is to read every message, in every channel, every day. For orgs with hundreds of channels, it&#8217;s a mess.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zmh.org/dispatch/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2519</post-id>	</item>
		<item>
		<title>2025 Side Projects</title>
		<link>https://zmh.org/2025-side-projects/</link>
					<comments>https://zmh.org/2025-side-projects/#respond</comments>
		
		<dc:creator><![CDATA[zacharyhamed]]></dc:creator>
		<pubDate>Thu, 01 Jan 2026 15:32:21 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[projects]]></category>
		<guid isPermaLink="false">https://zmh.org/?p=2464</guid>

					<description><![CDATA[I’m finally publishing my side projects for 2025 on Github —  36,408 lines of code, almost entirely vibe coded.

• Quill, a native Mac WordPress blogg]]></description>
										<content:encoded><![CDATA[
<p>I’m finally publishing my side projects for 2025 on Github — 36,408 lines of code, almost entirely vibe coded.</p>



<ul class="wp-block-list">
<li><a href="https://zmh.org/quill/">Quill</a>, a beautiful, fast, native Mac WordPress blogging editor inspired by IA Writer but with full, bidirectional Gutenberg block support</li>



<li><a href="https://zmh.org/gymtxt/">Gymtxt</a>, a lightweight way to log workouts as plaintext</li>



<li><a href="https://zmh.org/day-one-publish/">Day One Publish</a>, a way to generate static sites from a Day One journal to share with friends and family</li>



<li><a href="https://zmh.org/shrinksearch/">Shrinksearch</a>, a fast way to search and browse Psychology Today profiles</li>
</ul>



<figure class="wp-block-gallery has-nested-images columns-2 is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex">
<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4f873f1b50&quot;}" data-wp-interactive="core/image" data-wp-key="69e4f873f1b50" class="wp-block-image size-large wp-lightbox-container"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="720" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" data-id="2477" src="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/quill-hero.png?resize=1024%2C720&#038;quality=80&#038;ssl=1" alt="" class="wp-image-2477" srcset="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/quill-hero-scaled.png?resize=1024%2C720&amp;quality=80&amp;ssl=1 1024w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/quill-hero-scaled.png?resize=300%2C211&amp;quality=80&amp;ssl=1 300w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/quill-hero-scaled.png?resize=768%2C540&amp;quality=80&amp;ssl=1 768w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/quill-hero-scaled.png?resize=1536%2C1080&amp;quality=80&amp;ssl=1 1536w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/quill-hero-scaled.png?resize=2048%2C1440&amp;quality=80&amp;ssl=1 2048w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4f873f2a2b&quot;}" data-wp-interactive="core/image" data-wp-key="69e4f873f2a2b" class="wp-block-image size-large wp-lightbox-container"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="613" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" data-id="2479" src="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/01/gymtxt-hero.png?resize=1024%2C613&#038;quality=80&#038;ssl=1" alt="" class="wp-image-2479" srcset="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/01/gymtxt-hero-scaled.png?resize=1024%2C613&amp;quality=80&amp;ssl=1 1024w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/01/gymtxt-hero-scaled.png?resize=300%2C180&amp;quality=80&amp;ssl=1 300w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/01/gymtxt-hero-scaled.png?resize=768%2C460&amp;quality=80&amp;ssl=1 768w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/01/gymtxt-hero-scaled.png?resize=1536%2C920&amp;quality=80&amp;ssl=1 1536w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/01/gymtxt-hero-scaled.png?resize=2048%2C1227&amp;quality=80&amp;ssl=1 2048w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4f873f3b66&quot;}" data-wp-interactive="core/image" data-wp-key="69e4f873f3b66" class="wp-block-image size-large wp-lightbox-container"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="737" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" data-id="2481" src="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/dayonepublish-hero.png?resize=1024%2C737&#038;quality=80&#038;ssl=1" alt="" class="wp-image-2481" srcset="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/dayonepublish-hero-scaled.png?resize=1024%2C737&amp;quality=80&amp;ssl=1 1024w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/dayonepublish-hero-scaled.png?resize=300%2C216&amp;quality=80&amp;ssl=1 300w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/dayonepublish-hero-scaled.png?resize=768%2C553&amp;quality=80&amp;ssl=1 768w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/dayonepublish-hero-scaled.png?resize=1536%2C1106&amp;quality=80&amp;ssl=1 1536w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/dayonepublish-hero-scaled.png?resize=2048%2C1474&amp;quality=80&amp;ssl=1 2048w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4f87400b5b&quot;}" data-wp-interactive="core/image" data-wp-key="69e4f87400b5b" class="wp-block-image size-large wp-lightbox-container"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="737" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" data-id="2483" src="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/shrinksearch-hero.png?resize=1024%2C737&#038;quality=80&#038;ssl=1" alt="" class="wp-image-2483" srcset="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/shrinksearch-hero-scaled.png?resize=1024%2C737&amp;quality=80&amp;ssl=1 1024w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/shrinksearch-hero-scaled.png?resize=300%2C216&amp;quality=80&amp;ssl=1 300w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/shrinksearch-hero-scaled.png?resize=768%2C553&amp;quality=80&amp;ssl=1 768w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/shrinksearch-hero-scaled.png?resize=1536%2C1106&amp;quality=80&amp;ssl=1 1536w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/shrinksearch-hero-scaled.png?resize=2048%2C1474&amp;quality=80&amp;ssl=1 2048w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>
</figure>



<p>Some notes from building this year:</p>



<ul class="wp-block-list">
<li>I’ve been preferring one-page tools that read/write from a local CSV, JSON file, or sqlite db — the data layer is easy for the models to use, version controlled, and super fast on the frontend for the user.</li>



<li>I like UX where the app is a layer on top of plaintext. Gymtxt was my first attempt at this, and I love <a href="https://x.com/zehf/status/2004571994126455003">this travel app</a> with a similar vibe. Treating the text area as the database means the user, LLM, and developer can all easily interact with the same dataset.</li>



<li>I highly recommend <a href="https://coolify.io">Coolify</a> or <a href="https://dokploy.com/">Dokploy</a> for vibecoding projects with Claude Code. They’re essentially a self-hosted Replit or V0 — you get a unique URL per project, and they auto-deploy when you push to Github. Set it up once on a cheap $5 VPS and you can go from a new folder on your computer to a link you can share in ~3 steps (create the repo in Github, push to it, and then tell Coolify about the new repo.)</li>



<li>I’m interested in what LLMs can “see” when processing images. Web projects were easier than native apps because Claude Code could snapshot the page and verify its results vs. native apps where I would largely do that (though I imagine giving screen access in the future will fix that.) But even when snapshotting, specific layout tweaks were sometimes hard for it to see in the generated image.</li>



<li>Apple should have an App Store submission MCP and an improved notarization experience. The hardest part of Quill was getting it into executable form so people could download it and run directly. Until then, my default stack will skew towards web technologies unless there’s a specific reason to build natively.</li>



<li>I find it crazy that, when facing a bug the LLM can’t solve, starting entirely from scratch and referencing the old project code will often result in 100% feature parity with the issue resolved. I wonder if coding agents will adopt this as a way to get around roadblocks.</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://zmh.org/2025-side-projects/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2464</post-id>	</item>
		<item>
		<title>Day One Publish</title>
		<link>https://zmh.org/day-one-publish/</link>
					<comments>https://zmh.org/day-one-publish/#respond</comments>
		
		<dc:creator><![CDATA[zacharyhamed]]></dc:creator>
		<pubDate>Mon, 29 Dec 2025 13:53:51 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[projects]]></category>
		<guid isPermaLink="false">https://zmh.org/?p=2462</guid>

					<description><![CDATA[Day One Publish is a project I made to generate a static site from a Day One journal.

For some recent travel, I wanted a way to add photos each day f]]></description>
										<content:encoded><![CDATA[
<p><a href="https://github.com/zmh/dayone-publish">Day One Publish</a> is a project I made to generate a static site from a Day One journal.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4f874038ce&quot;}" data-wp-interactive="core/image" data-wp-key="69e4f874038ce" class="wp-block-image size-large wp-lightbox-container"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="737" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/dayonepublish-hero.png?resize=1024%2C737&#038;quality=80&#038;ssl=1" alt="" class="wp-image-2481" srcset="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/dayonepublish-hero-scaled.png?resize=1024%2C737&amp;quality=80&amp;ssl=1 1024w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/dayonepublish-hero-scaled.png?resize=300%2C216&amp;quality=80&amp;ssl=1 300w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/dayonepublish-hero-scaled.png?resize=768%2C553&amp;quality=80&amp;ssl=1 768w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/dayonepublish-hero-scaled.png?resize=1536%2C1106&amp;quality=80&amp;ssl=1 1536w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/dayonepublish-hero-scaled.png?resize=2048%2C1474&amp;quality=80&amp;ssl=1 2048w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>



<p><span style="font-family: var(--editor-font-family); font-size: var(--editor-font-size);">For some recent travel, I wanted a way to add photos each day for a small group of family and friends to see. A blog would work, but I wanted a great native editing experience, with particular focus on places we were visiting. Luckily Day One has gorgeous native apps and now allows shared journals, but there was no way to take a journal and publish it as a site.&nbsp;</span><br></p>



<p>The design is entirely inspired by the Day One app interface itself, so it feels native. View entries as a timeline, calendar, mosaic of photos, or on a map. I have it run nightly locally on my Mac, and it deploys via Coolify.</p>



<p></p>



<p></p>



<p><br></p>
]]></content:encoded>
					
					<wfw:commentRss>https://zmh.org/day-one-publish/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2462</post-id>	</item>
		<item>
		<title>Quill</title>
		<link>https://zmh.org/quill/</link>
					<comments>https://zmh.org/quill/#comments</comments>
		
		<dc:creator><![CDATA[zacharyhamed]]></dc:creator>
		<pubDate>Sat, 01 Nov 2025 15:22:37 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[projects]]></category>
		<guid isPermaLink="false">https://zmh.org/?p=2449</guid>

					<description><![CDATA[Quill is a native macOS WordPress editor, built for those who like to edit their site posts directly.

I’ve used Ulysses, IA Writer, and MarsEdit, but]]></description>
										<content:encoded><![CDATA[
<p><a href="https://github.com/zmh/Quill">Quill</a> is a native macOS WordPress editor, built for those who like to edit their site posts directly.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4f87404791&quot;}" data-wp-interactive="core/image" data-wp-key="69e4f87404791" class="wp-block-image size-large wp-lightbox-container"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="720" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/quill-hero.png?resize=1024%2C720&#038;quality=80&#038;ssl=1" alt="" class="wp-image-2477" srcset="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/quill-hero-scaled.png?resize=1024%2C720&amp;quality=80&amp;ssl=1 1024w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/quill-hero-scaled.png?resize=300%2C211&amp;quality=80&amp;ssl=1 300w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/quill-hero-scaled.png?resize=768%2C540&amp;quality=80&amp;ssl=1 768w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/quill-hero-scaled.png?resize=1536%2C1080&amp;quality=80&amp;ssl=1 1536w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/quill-hero-scaled.png?resize=2048%2C1440&amp;quality=80&amp;ssl=1 2048w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>



<p>I’ve used Ulysses, IA Writer, and MarsEdit, but none of them let me publish a post and then edit it later in the editor. Once a post was published, I’d need to switch to WordPress to edit (or in MarsEdit’s case, I’d get a bunch of HTML comments around each block, which made editing hard.)</p>



<p>So I made the Mac WordPress post editor I’ve always wanted, mainly for blogging:</p>



<ul class="wp-block-list">
<li><span style="font-family: var(--editor-font-family); font-size: var(--editor-font-size);"><b>Native</b> &#8211; primarily I wanted this for the writing and editor experience, but it also means things like keyboard shortcuts, drag and drop, etc</span></li>



<li><b>Well-designed</b> &#8211; nice fonts, fits into Mac OS, and feels like a place where I can get cozy and write</li>



<li><b>Blogging-focused</b> &#8211; I really wanted to know how much I was writing and set goals</li>



<li><b>Notes-like</b> &#8211; I wanted to treat posts as notes so they’re living documents. Easy to open quickly, make a change, and save. Fast and available offline so you can edit on a plane</li>



<li><b>Gutenberg support</b> &#8211; I wanted the editor to be bidirectionally compatible with the Gutenberg block editor. Edit on web or in the app, resume editing in the other. No weird save artifacts or unsupported blocks</li>
</ul>



<p>The app was almost entirely vibe-coded using Claude Code in a few sessions. Some observations:</p>



<ul class="wp-block-list">
<li>Claude Code, and Opus, are substantially better at project management and context compacting since I started in June.&nbsp;</li>



<li>Opus is very good at Mac development — the hardest part was notarization. If Apple fixed notarization and App Store submissions for Mac and iOS (perhaps using MCPs), I think you’d see a renaissance of native app development.</li>



<li>Building text editors continues to be one of the hardest problems in computer science.</li>
</ul>



<p>Check out the <a href="https://github.com/zmh/Quill">project on Github</a>, and <a href="https://github.com/zmh/Quill/releases/latest/download/Quill.dmg">download the Mac app here</a>.</p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://zmh.org/quill/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2449</post-id>	</item>
		<item>
		<title>Gymtxt</title>
		<link>https://zmh.org/gymtxt/</link>
					<comments>https://zmh.org/gymtxt/#respond</comments>
		
		<dc:creator><![CDATA[zacharyhamed]]></dc:creator>
		<pubDate>Tue, 30 Sep 2025 15:18:13 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[projects]]></category>
		<guid isPermaLink="false">https://zmh.org/?p=2475</guid>

					<description><![CDATA[Gymtxt.com is a lightweight way to jot down exercises at the gym, in plaintext. It’s based on how I log workouts in Apple Notes / IA Writer, with a li]]></description>
										<content:encoded><![CDATA[
<p><a href="https://gymtxt.com">Gymtxt.com</a> is a lightweight way to jot down exercises at the gym, in plaintext. It’s based on how I log workouts in Apple Notes / IA Writer, with a little scaffolding to make it easier to track workouts over time.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4f87406cdc&quot;}" data-wp-interactive="core/image" data-wp-key="69e4f87406cdc" class="wp-block-image size-large wp-lightbox-container"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1215" height="728" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/01/gymtxt-hero-edited.png?resize=1215%2C728&#038;quality=80&#038;ssl=1" alt="" class="wp-image-2490" srcset="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/01/gymtxt-hero-edited.png?w=1215&amp;quality=80&amp;ssl=1 1215w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/01/gymtxt-hero-edited.png?resize=300%2C180&amp;quality=80&amp;ssl=1 300w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/01/gymtxt-hero-edited.png?resize=1024%2C614&amp;quality=80&amp;ssl=1 1024w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/01/gymtxt-hero-edited.png?resize=768%2C460&amp;quality=80&amp;ssl=1 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>



<p>It allows you to write something like</p>



<pre class="wp-block-code wp-block-preformatted"><code>10/13
squats 100lbs 5x5 
bench press 45 each side 5x8</code></pre>



<p>The date, exercise, set count, rep count, and weight are parsed automatically and tracked over time with graphs. </p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4f874079cd&quot;}" data-wp-interactive="core/image" data-wp-key="69e4f874079cd" class="wp-block-image size-large wp-lightbox-container"><img data-recalc-dims="1" loading="lazy" decoding="async" width="2277" height="1318" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/01/CleanShot-2026-01-01-at-08.58.11%402x-edited.png?resize=2277%2C1318&#038;quality=80&#038;ssl=1" alt="" class="wp-image-2494" srcset="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/01/CleanShot-2026-01-01-at-08.58.11%402x-edited.png?w=2277&amp;quality=80&amp;ssl=1 2277w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/01/CleanShot-2026-01-01-at-08.58.11%402x-edited.png?resize=300%2C174&amp;quality=80&amp;ssl=1 300w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/01/CleanShot-2026-01-01-at-08.58.11%402x-edited.png?resize=1024%2C593&amp;quality=80&amp;ssl=1 1024w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/01/CleanShot-2026-01-01-at-08.58.11%402x-edited.png?resize=768%2C445&amp;quality=80&amp;ssl=1 768w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/01/CleanShot-2026-01-01-at-08.58.11%402x-edited.png?resize=1536%2C889&amp;quality=80&amp;ssl=1 1536w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2026/01/CleanShot-2026-01-01-at-08.58.11%402x-edited.png?resize=2048%2C1185&amp;quality=80&amp;ssl=1 2048w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>



<p>Easily remember what you did last time and update your workout as you go. <span style="font-family: var(--editor-font-family); font-size: var(--editor-font-size);">It also includes a basic timer for breaks between sets.</span></p>



<p>All data is stored in local storage and importable/exportable as plain .txt files.<br></p>
]]></content:encoded>
					
					<wfw:commentRss>https://zmh.org/gymtxt/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2475</post-id>	</item>
		<item>
		<title>Shrinksearch</title>
		<link>https://zmh.org/shrinksearch/</link>
					<comments>https://zmh.org/shrinksearch/#respond</comments>
		
		<dc:creator><![CDATA[zacharyhamed]]></dc:creator>
		<pubDate>Tue, 29 Apr 2025 14:20:32 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[projects]]></category>
		<guid isPermaLink="false">https://zmh.org/?p=2463</guid>

					<description><![CDATA[Shrinksearch lets you quickly search and browse mental health providers from the NYC area, with data from Psychology Today as of April 2025.

Psycholo]]></description>
										<content:encoded><![CDATA[
<p><a href="https://zmh.github.io/shrinksearch/">Shrinksearch</a> lets you quickly search and browse mental health providers from the NYC area, with data from Psychology Today as of April 2025.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4f87408e29&quot;}" data-wp-interactive="core/image" data-wp-key="69e4f87408e29" class="wp-block-image size-large wp-lightbox-container"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="737" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/shrinksearch-hero.png?resize=1024%2C737&#038;quality=80&#038;ssl=1" alt="" class="wp-image-2483" srcset="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/shrinksearch-hero-scaled.png?resize=1024%2C737&amp;quality=80&amp;ssl=1 1024w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/shrinksearch-hero-scaled.png?resize=300%2C216&amp;quality=80&amp;ssl=1 300w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/shrinksearch-hero-scaled.png?resize=768%2C553&amp;quality=80&amp;ssl=1 768w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/shrinksearch-hero-scaled.png?resize=1536%2C1106&amp;quality=80&amp;ssl=1 1536w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2025/12/shrinksearch-hero-scaled.png?resize=2048%2C1474&amp;quality=80&amp;ssl=1 2048w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>



<p>Psychology Today has the best data set for mental health providers, but it doesn’t let you search the text of providers’ descriptions and only shows a few providers per page.&nbsp;</p>



<p><a href="https://zmh.github.io/shrinksearch/">View live here</a>, or the <a href="https://github.com/zmh/shrinksearch">code on Github here</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zmh.org/shrinksearch/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2463</post-id>	</item>
		<item>
		<title>2025-01-27</title>
		<link>https://zmh.org/2025-01-27/</link>
					<comments>https://zmh.org/2025-01-27/#respond</comments>
		
		<dc:creator><![CDATA[zacharyhamed]]></dc:creator>
		<pubDate>Tue, 28 Jan 2025 02:08:47 +0000</pubDate>
				<category><![CDATA[Microblog]]></category>
		<category><![CDATA[home]]></category>
		<category><![CDATA[projects]]></category>
		<guid isPermaLink="false">https://zmh.org/?p=1256</guid>

					<description><![CDATA[I&#8217;ve been waiting for a DIY / open source version of Find My, mainly to allow new form factors beyond AirTags and supported third parties. Came across OpenHaystack today and it seems like the best so far given their supported device list. Their version cleverly works as an Apple Mail plugin, but biemster/FindMy is another [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I&#8217;ve been waiting for a DIY / open source version of Find My, mainly to allow new form factors beyond AirTags and supported third parties.</p>
<p>Came across <a href="https://github.com/seemoo-lab/openhaystack">OpenHaystack</a> today and it seems like the best so far given their <a href="https://github.com/seemoo-lab/openhaystack#how-to-track-other-bluetooth-devices">supported device list</a>. Their version cleverly works as an Apple Mail plugin, but <a href="https://github.com/biemster/FindMy">biemster/FindMy</a> is another project that works with just your Apple ID.</p>
<p>I wonder if this would allow for something like remote Find My beacons that you could post around your house to instantly find items instead of wandering around with an iPhone, or help visualize things moving around a space like a marauder&#8217;s map.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zmh.org/2025-01-27/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1256</post-id>	</item>
		<item>
		<title>Installing Comma.ai on a 2018 Mazda CX-5</title>
		<link>https://zmh.org/comma-ai/</link>
					<comments>https://zmh.org/comma-ai/#comments</comments>
		
		<dc:creator><![CDATA[zacharyhamed]]></dc:creator>
		<pubDate>Mon, 05 Aug 2024 02:31:02 +0000</pubDate>
				<category><![CDATA[Essays]]></category>
		<category><![CDATA[Gear]]></category>
		<category><![CDATA[most-read]]></category>
		<category><![CDATA[projects]]></category>
		<guid isPermaLink="false">http://zmh.micro.blog/2024/08/04/installing-commaai-on.html</guid>

					<description><![CDATA[I recently ordered a Comma.ai kit to add semi-autonomous driving capabilities to my 2018 Mazda CX-5. It took some trial and error (and help from the Comma.ai community on Discord) to get it working properly, but I highly recommend it as I’ll explain later. I&#8217;m sharing the steps I took in case it&#8217;s helpful for [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>I recently ordered a <a href="https://comma.ai/">Comma.ai</a> kit to add semi-autonomous driving capabilities to my 2018 Mazda CX-5. It took some trial and error (and help from the <a href="https://discord.com/invite/FEzeve2NX2">Comma.ai community on Discord</a>) to get it working properly, but I <em>highly</em> recommend it as I’ll explain later.</p>



<p>I&#8217;m sharing the steps I took in case it&#8217;s helpful for others looking to install the Comma 3X on the same or a similar vehicle. It&#8217;s a pretty intuitive process, all things considered, but there weren’t a lot of guides with photos on how to do the actual installation process.</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Mazda CX-9 2022 - Comma 3 OpenPilot Highway Driving Experience" width="500" height="281" src="https://www.youtube.com/embed/dA3duO4a0O4?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<h3 class="wp-block-heading">What is Comma.ai?</h3>



<p>Comma is like Tesla Autopilot for your existing car. It plugs into the car&#8217;s <a href="https://www.geotab.com/blog/obd-ii/">OBD-II port</a> and uses data from your car&#8217;s existing sensors to do some <a href="https://www.pcmag.com/how-to/6-levels-of-autonomous-self-driving-explained">Level 3 automation</a> (ish). That&#8217;s partial automation —&nbsp;if the systems fail or there&#8217;s a major incident on the road, you still need to be ready to take over. But it works well on highway drives and anywhere you&#8217;d normally be using cruise control. </p>



<p>This might sound sketchy, but Comma was actually <a href="https://data.consumerreports.org/wp-content/uploads/2020/11/consumer-reports-active-driving-assistance-systems-november-16-2020.pdf">ranked #1 by Consumer Reports</a>. After a few months of using it, I can attest it&#8217;s not a fly-by-night hardware operation, and the software is quite good.</p>



<h3 class="wp-block-heading">What cars support Comma.ai?</h3>



<p>Comma&#8217;s <a href="https://comma.ai/vehicles">official compatibility list is here</a>, but if you don&#8217;t see your car listed it doesn&#8217;t mean it&#8217;s not supported. As I later found out, there&#8217;s an &#8220;unofficial&#8221; list of community-supported vehicles (<a href="https://github.com/commaai/openpilot/wiki/Mazda">like this for Mazda</a>) where the sensors exist but capabilities have various limitations. </p>



<p>In my case, CX-5 models earlier than 2022 have all the sensors needed for the full Comma.ai experience, but the EPS motor (which provides lane departure warnings by rumbling the wheel a bit) isn&#8217;t strong enough to move the wheel enough for medium to large turns when automated. That changed in 2022 model years and later, which is why they&#8217;re officially supported. </p>



<p>Earlier models are community-supported, and there are some asterisks around what you get with the out-of-the-box Comma experience. But — if you&#8217;re willing to do a 30 minute part swap (that I thought would be scary and warranty-voiding, but is actually easier than you&#8217;d think with my guide below) you get the full Comma experience, which is better than most built-in car autopilot features today.</p>



<h2 class="wp-block-heading">A false start</h2>



<p>When I initially received the Comma 3X kit and installed it (follow the <a href="https://www.youtube.com/watch?v=FV7_Su4xbzs">installation video</a> and <a href="https://medium.com/@to.jafar/how-to-setup-openpilot-on-mazda-3eb54c62fdc5">Jafar&#8217;s post</a>, it&#8217;s pretty simple) I thought I’d be up and running quickly. However, the device seemed stuck in dashcam mode and didn&#8217;t move the steering wheel at all. After digging into the Discord server and reading more, it appeared to be an issue with fingerprinting my specific Mazda model.</p>



<p>I reset the device and installed a <a href="https://smiskol.com/fork/jafaral/mazda-0.9.6">special fork</a> I found on the Discord server which had more Mazda car fingerprints to help identify how to interface with the car. This worked on a test drive, but the car would beep aggressively every 5 seconds if you weren&#8217;t holding the wheel very deliberately, making highway driving difficult. Even without Comma installed the car would complain when you had cruise control enabled and weren’t holding the steering wheel in the right place, but adding the Comma made it complain much more.</p>



<p>The Discord community <a href="https://discord.com/channels/469524606043160576/533836721541087242/628249300555792394">recommends</a> trying a wheel cover with weights underneath, which worked somewhat but was quite bulky. Ultimately, I decided to pursue the ultimate solution I had been trying to avoid: swapping out the EPS motor.</p>



<h2 class="wp-block-heading">Swapping the EPS motor</h2>



<p>The EPS motor on pre-2022 Mazdas is designed for very lightweight lane departure vibrations. I always thought it felt a bit underpowered, and you could feel the car lightly bouncing between the lane markers. On any serious turn, the car would just continue to depart the lane.</p>



<p>Newer Mazda EPS motors can apply more torque to the wheel, allowing for real LKAS (lane keep assistance) that can turn the car even through 10+ degree curves. I was initially hesitant to replace the EPS motor because I wasn&#8217;t sure exactly where it was located. But after reading the <a href="https://discord.com/channels/469524606043160576/533836721541087242/1250213678108905574">pinned messages</a> on Discord and asking a few questions, the community reassured me it was pretty straightforward.</p>



<p>The process ended up being easier than I anticipated, although there were a few tricky parts. Here&#8217;s a detailed breakdown of how it works:</p>



<ol class="wp-block-list">
<li>Order the new EPS motor from eBay — the LKQ store has several options, but you have to make sure the vehicle is model year 2022 or higher. As an example, <a href="https://www.ebay.com/sch/i.html?_dkr=1&amp;iconV2Request=true&amp;_blrs=recall_filtering&amp;_ssn=lkqonline&amp;store_cat=0&amp;store_name=lkqonline&amp;_oac=1&amp;_nkw=2023%20mazda%20cx-5%20power%20steering%20pump%20oem">here&#8217;s a search</a> on LKQ&#8217;s eBay store, or just look for &#8220;2023 Mazda CX-5 Power Steering Pump OEM&#8221;. You’ll also need a 10mm and 12mm wrench for later.</li>



<li>You&#8217;ll receive a hunk of metal similar to this. The only part needed is the circular gearbox-looking piece on the left of this picture.</li>
</ol>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4f8740dd19&quot;}" data-wp-interactive="core/image" data-wp-key="69e4f8740dd19" class="wp-block-image size-large wp-lightbox-container"><img data-recalc-dims="1" loading="lazy" decoding="async" width="768" height="1024" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/img-8387-1.jpg?resize=768%2C1024&#038;quality=89&#038;ssl=1" alt="" class="wp-image-1852" srcset="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/img-8387-1.jpg?resize=768%2C1024&amp;quality=89&amp;ssl=1 768w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/img-8387-1.jpg?resize=225%2C300&amp;quality=89&amp;ssl=1 225w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/img-8387-1.jpg?resize=1152%2C1536&amp;quality=89&amp;ssl=1 1152w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/img-8387-1.jpg?resize=1536%2C2048&amp;quality=89&amp;ssl=1 1536w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/img-8387-1.jpg?w=1800&amp;quality=89&amp;ssl=1 1800w" sizes="auto, (max-width: 768px) 100vw, 768px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>



<ol start="3" class="wp-block-list">
<li>Remove the two bolts pictured here, which will detach the shaft from the EPS motor. Use a 12mm wrench for these and be careful not to lose the small plastic gear in the center of the motor once you remove it.</li>
</ol>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4f8740ee7a&quot;}" data-wp-interactive="core/image" data-wp-key="69e4f8740ee7a" class="wp-block-image size-large wp-lightbox-container"><img data-recalc-dims="1" loading="lazy" decoding="async" width="766" height="1024" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/cleanshot-2024-08-04-at-21.31.512x-1.png?resize=766%2C1024&#038;quality=80&#038;ssl=1" alt="" class="wp-image-1854" srcset="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/cleanshot-2024-08-04-at-21.31.512x-1.png?resize=766%2C1024&amp;quality=80&amp;ssl=1 766w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/cleanshot-2024-08-04-at-21.31.512x-1.png?resize=224%2C300&amp;quality=80&amp;ssl=1 224w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/cleanshot-2024-08-04-at-21.31.512x-1.png?resize=768%2C1027&amp;quality=80&amp;ssl=1 768w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/cleanshot-2024-08-04-at-21.31.512x-1.png?resize=1148%2C1536&amp;quality=80&amp;ssl=1 1148w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/cleanshot-2024-08-04-at-21.31.512x-1.png?w=1292&amp;quality=80&amp;ssl=1 1292w" sizes="auto, (max-width: 766px) 100vw, 766px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>



<ol start="4" class="wp-block-list">
<li><a href="https://www.youtube.com/watch?v=KWTWZWl6Lgc">Disconnect your car battery</a> using a 10mm wrench to prevent the airbags from firing.</li>



<li>While not required, I recommend removing the cover to the left of the steering wheel. It pops out easily and improves access to the EPS motor.</li>
</ol>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4f8741038e&quot;}" data-wp-interactive="core/image" data-wp-key="69e4f8741038e" class="wp-block-image size-large wp-lightbox-container"><img data-recalc-dims="1" loading="lazy" decoding="async" width="966" height="1024" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/img-8393-1.jpg?resize=966%2C1024&#038;quality=89&#038;ssl=1" alt="" class="wp-image-1855" srcset="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/img-8393-1.jpg?resize=966%2C1024&amp;quality=89&amp;ssl=1 966w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/img-8393-1.jpg?resize=283%2C300&amp;quality=89&amp;ssl=1 283w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/img-8393-1.jpg?resize=768%2C814&amp;quality=89&amp;ssl=1 768w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/img-8393-1.jpg?resize=1449%2C1536&amp;quality=89&amp;ssl=1 1449w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/img-8393-1.jpg?w=1799&amp;quality=89&amp;ssl=1 1799w" sizes="auto, (max-width: 966px) 100vw, 966px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>



<ol start="6" class="wp-block-list">
<li>Now that you’re in, you’ll see the same motor mounted, as pictured here:</li>
</ol>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4f874118a0&quot;}" data-wp-interactive="core/image" data-wp-key="69e4f874118a0" class="wp-block-image size-large wp-lightbox-container"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="952" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/CleanShot-2025-02-28-at-11.56.15%402x.png?resize=1024%2C952&#038;quality=80&#038;ssl=1" alt="" class="wp-image-1858" srcset="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/CleanShot-2025-02-28-at-11.56.15%402x.png?resize=1024%2C952&amp;quality=80&amp;ssl=1 1024w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/CleanShot-2025-02-28-at-11.56.15%402x.png?resize=300%2C279&amp;quality=80&amp;ssl=1 300w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/CleanShot-2025-02-28-at-11.56.15%402x.png?resize=768%2C714&amp;quality=80&amp;ssl=1 768w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/CleanShot-2025-02-28-at-11.56.15%402x.png?w=1500&amp;quality=80&amp;ssl=1 1500w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>



<ol start="7" class="wp-block-list">
<li>Here&#8217;s the trickiest part: you need to remove the same two bolts on the old gearbox, but one bolt is close to a piece of metal, making it hard to fit the wrench in. It&#8217;s doable but will take a few attempts. Both bolts are on quite tight, so don&#8217;t be afraid to use some force to loosen them.</li>
</ol>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4f874128f0&quot;}" data-wp-interactive="core/image" data-wp-key="69e4f874128f0" class="wp-block-image size-large wp-lightbox-container"><img data-recalc-dims="1" loading="lazy" decoding="async" width="767" height="1024" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/CleanShot-2025-02-28-at-11.53.43%402x.png?resize=767%2C1024&#038;quality=80&#038;ssl=1" alt="" class="wp-image-1857" srcset="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/CleanShot-2025-02-28-at-11.53.43%402x.png?resize=767%2C1024&amp;quality=80&amp;ssl=1 767w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/CleanShot-2025-02-28-at-11.53.43%402x.png?resize=225%2C300&amp;quality=80&amp;ssl=1 225w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/CleanShot-2025-02-28-at-11.53.43%402x.png?resize=768%2C1025&amp;quality=80&amp;ssl=1 768w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/CleanShot-2025-02-28-at-11.53.43%402x.png?resize=1150%2C1536&amp;quality=80&amp;ssl=1 1150w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/CleanShot-2025-02-28-at-11.53.43%402x.png?resize=1534%2C2048&amp;quality=80&amp;ssl=1 1534w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/CleanShot-2025-02-28-at-11.53.43%402x.png?w=2000&amp;quality=80&amp;ssl=1 2000w" sizes="auto, (max-width: 767px) 100vw, 767px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4f87413c41&quot;}" data-wp-interactive="core/image" data-wp-key="69e4f87413c41" class="wp-block-image size-large wp-lightbox-container"><img data-recalc-dims="1" loading="lazy" decoding="async" width="768" height="1024" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/img-8399-1.jpg?resize=768%2C1024&#038;quality=89&#038;ssl=1" alt="" class="wp-image-1859" srcset="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/img-8399-1.jpg?resize=768%2C1024&amp;quality=89&amp;ssl=1 768w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/img-8399-1.jpg?resize=225%2C300&amp;quality=89&amp;ssl=1 225w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/img-8399-1.jpg?resize=1152%2C1536&amp;quality=89&amp;ssl=1 1152w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/img-8399-1.jpg?resize=1536%2C2048&amp;quality=89&amp;ssl=1 1536w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/img-8399-1.jpg?w=1800&amp;quality=89&amp;ssl=1 1800w" sizes="auto, (max-width: 768px) 100vw, 768px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>



<ol start="8" class="wp-block-list">
<li>Once the bolts are out, unhook the 3 cables at the top and detach the old motor.</li>
</ol>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4f8741549a&quot;}" data-wp-interactive="core/image" data-wp-key="69e4f8741549a" class="wp-block-image size-large wp-lightbox-container"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="767" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/CleanShot-2025-02-28-at-11.58.01%402x.png?resize=1024%2C767&#038;quality=80&#038;ssl=1" alt="" class="wp-image-1860" srcset="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/CleanShot-2025-02-28-at-11.58.01%402x.png?resize=1024%2C767&amp;quality=80&amp;ssl=1 1024w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/CleanShot-2025-02-28-at-11.58.01%402x.png?resize=300%2C225&amp;quality=80&amp;ssl=1 300w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/CleanShot-2025-02-28-at-11.58.01%402x.png?resize=768%2C575&amp;quality=80&amp;ssl=1 768w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/CleanShot-2025-02-28-at-11.58.01%402x.png?resize=1536%2C1151&amp;quality=80&amp;ssl=1 1536w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/CleanShot-2025-02-28-at-11.58.01%402x.png?resize=2048%2C1534&amp;quality=80&amp;ssl=1 2048w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>



<p>One tip: the small gear kept falling out or misaligning as I tried to install the new motor. Rather than fumbling with alignment, I positioned the gear on the other (already mounted) side so it was already lined up correctly. You’ll see what I mean.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4f87416be2&quot;}" data-wp-interactive="core/image" data-wp-key="69e4f87416be2" class="wp-block-image size-large wp-lightbox-container"><img data-recalc-dims="1" loading="lazy" decoding="async" width="768" height="1024" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/img-8409-1.jpg?resize=768%2C1024&#038;quality=89&#038;ssl=1" alt="" class="wp-image-1861" srcset="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/img-8409-1.jpg?resize=768%2C1024&amp;quality=89&amp;ssl=1 768w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/img-8409-1.jpg?resize=225%2C300&amp;quality=89&amp;ssl=1 225w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/img-8409-1.jpg?resize=1152%2C1536&amp;quality=89&amp;ssl=1 1152w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/img-8409-1.jpg?resize=1536%2C2048&amp;quality=89&amp;ssl=1 1536w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/img-8409-1.jpg?w=1800&amp;quality=89&amp;ssl=1 1800w" sizes="auto, (max-width: 768px) 100vw, 768px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>



<ol start="9" class="wp-block-list">
<li>Screw the bolts back in, reconnect your battery, and you&#8217;re all set! Once the Comma turns on, you&#8217;ll go through an installation process. Like <a href="https://youtu.be/ZGHeuHJjFl0?si=KaAQgnEakdh2VTQz&amp;t=105">this video</a> shows, you&#8217;ll want to select &#8220;Custom software&#8221; but then you&#8217;ll enter the URL <a href="https://smiskol.com/fork/jafaral/mazda-eps22-swap">https://smiskol.com/fork/jafaral/mazda-eps22-swap</a> on the Comma 3X, which tells older Mazdas to use the new EPS motor.</li>
</ol>



<h2 class="wp-block-heading">Review</h2>



<p>After installing the new EPS motor, I&#8217;ve been <em>really</em> impressed with its performance. I wouldn&#8217;t even bother installing Comma.ai on an older Mazda without it — the experience is just too annoying otherwise.</p>



<p>The upgraded EPS motor enables stop-and-go adaptive cruise control, which by itself is a fantastic improvement for city traffic. It also provides LKAS that keeps the car smoothly centered in the lane without any warnings to keep your hands on the wheel. These enhancements make long drives much more pleasant.</p>



<p>With the new motor, I&#8217;ve completed a few hundred-mile road trips with only three or four interventions to assist with turning, and just a handful of additional interventions in busy city traffic. It really is quite capable.</p>



<p>Since I had Comma installed before the EPS motor upgrade, I spent some time observing the Openpilot lane markings as we drove. There was never a point where the green outline indicating the car&#8217;s projected path was misdirected or where the detected lane markers deviated from reality. I also drove at night and in the rain, with no issues whatsoever. This gave me a lot of confidence in the system&#8217;s capabilities.</p>



<p>Special thanks to the Comma team for building an incredible hardware product, and to all the maintainers of <a href="https://github.com/commaai/openpilot">Openpilot</a> and volunteers in the <a href="https://discord.com/invite/FEzeve2NX2">#Mazda Discord channel</a>.</p>



<h2 class="wp-block-heading">Update: 6 months later</h2>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4f87418400&quot;}" data-wp-interactive="core/image" data-wp-key="69e4f87418400" class="wp-block-image size-large wp-lightbox-container"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="343" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/IMG_5550.jpeg?resize=1024%2C343&#038;quality=89&#038;ssl=1" alt="" class="wp-image-1862" srcset="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/IMG_5550.jpeg?resize=1024%2C343&amp;quality=89&amp;ssl=1 1024w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/IMG_5550.jpeg?resize=300%2C101&amp;quality=89&amp;ssl=1 300w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/IMG_5550.jpeg?resize=768%2C257&amp;quality=89&amp;ssl=1 768w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2024/08/IMG_5550.jpeg?w=1179&amp;quality=89&amp;ssl=1 1179w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>



<p>Highly recommend the Comma, and will continue updating this post with observations. </p>



<ul class="wp-block-list">
<li>After ~500 drives and 10k+ miles, I&#8217;ve never had any safety issues, and have even relied on it in rain and snow because it did a better job of observing lane markings than I could. </li>



<li>I&#8217;ve noticed on some roads it adjusts the wheel back and forth a bit more than it should — this is a known issue called &#8220;ping-ponging&#8221; and some other branches are supposed to be better at minimizing wheel turn. More info is available on the Discord channel, but it hasn&#8217;t been a big enough issue for me to investigate further.</li>



<li>I might try some of the other forks like Sunnypilot that offer more customization.</li>



<li>I have noticed that the unit doesn&#8217;t do well in extreme temperatures, which usually happens when you leave it connected in a hot or cold parked car. Before purchasing, I had read reviews of people whose units broke in extreme heat, and I think it&#8217;s a real concern but avoidable in average climates. Either way, I&#8217;ve been disconnecting the unit and putting it in the glove box when I know it will be in direct sun or extreme temps. Quite easy to do, and so far no issues there.</li>



<li>I do think having the Comma as a dash cam is an underrated benefit. The team <a href="https://github.com/commaai/openpilot/wiki/Video-Files">discourages</a> its use as such, but it&#8217;s good enough and gives me some peace of mind.</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://zmh.org/comma-ai/feed/</wfw:commentRss>
			<slash:comments>19</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">853</post-id>	</item>
		<item>
		<title>Daily 140 and Macaw, RIP (2014 &#8211; 2023)</title>
		<link>https://zmh.org/daily-140-and-macaw/</link>
					<comments>https://zmh.org/daily-140-and-macaw/#respond</comments>
		
		<dc:creator><![CDATA[zacharyhamed]]></dc:creator>
		<pubDate>Thu, 18 May 2023 12:02:58 +0000</pubDate>
				<category><![CDATA[Essays]]></category>
		<category><![CDATA[projects]]></category>
		<guid isPermaLink="false">http://zmh.micro.blog/2023/05/18/daily-and-macaw.html</guid>

					<description><![CDATA[Last month, after almost exactly ten years, my side projects Daily 140 and Macaw stopped sending out emails thanks to Twitter&#8217;s API changes. Some stats: Daily 140 was by far my most successful side project, so I wanted to document its arc and what I learned, particularly for the many people it&#8217;s helped connect me [&#8230;]]]></description>
										<content:encoded><![CDATA[
<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4f8741fb24&quot;}" data-wp-interactive="core/image" data-wp-key="69e4f8741fb24" class="wp-block-image size-large wp-lightbox-container"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1024" height="793" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2023/05/6379ee3d78-1.png?resize=1024%2C793&#038;quality=80&#038;ssl=1" alt="" class="wp-image-1949" srcset="https://i0.wp.com/zmh.org/blog/wp-content/uploads/2023/05/6379ee3d78-1.png?resize=1024%2C793&amp;quality=80&amp;ssl=1 1024w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2023/05/6379ee3d78-1.png?resize=300%2C232&amp;quality=80&amp;ssl=1 300w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2023/05/6379ee3d78-1.png?resize=768%2C595&amp;quality=80&amp;ssl=1 768w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2023/05/6379ee3d78-1.png?resize=1536%2C1189&amp;quality=80&amp;ssl=1 1536w, https://i0.wp.com/zmh.org/blog/wp-content/uploads/2023/05/6379ee3d78-1.png?w=1888&amp;quality=80&amp;ssl=1 1888w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>



<p>Last month, after almost exactly ten years, my side projects <a href="https://daily140.com">Daily 140</a> and <a href="https://techcrunch.com/2018/10/16/macaw-will-curate-twitter-for-you-help-expand-your-network/">Macaw</a> stopped sending out emails thanks to Twitter&#8217;s <a href="https://www.engadget.com/twitter-shut-off-its-free-api-and-its-breaking-a-lot-of-apps-222011637.html">API</a> <a href="https://thenewstack.io/twitter-apis-are-going-very-wrong/">changes</a>.</p>



<p>Some stats:</p>



<ul class="wp-block-list">
<li>14,547 users</li>



<li>21,201 Twitter accounts that Daily 140 users chose to monitor</li>



<li>7,333,659 total Twitter accounts monitored for likes/follows for Macaw</li>



<li>4 million+ emails sent with a 40% daily open rate</li>
</ul>



<p>Daily 140 was by far my most successful side project, so I wanted to document its arc and what I learned, particularly for the many people it&#8217;s helped connect me with.</p>



<ul class="wp-block-list">
<li>All credit for the premise and the name goes to my old roommate <a href="https://twitter.com/ryandawidjan/">Ryan</a>, who was manually tracking the likes and follows of a few high profile VCs with interesting results and more generally is a spectacularly creative Twitter user</li>



<li>Built over a few weeks in the fall of 2014, and <a href="https://twitter.com/ProductHunt/status/552940441755451393?s=20">launched on Product Hunt</a> in January 2015</li>



<li>I forgot about the project for a few years after starting a new job, but realized after 3 years that I had thousands of users and a bunch of mentions on various blogs</li>



<li>The biggest issue with Daily 140 was not knowing which accounts would yield interesting results (in hindsight, I should have published something like <a href="https://twitter.com/BigTechAlert">@BigTechAlert</a> that was more easily visible and followable). That led me to launch <a href="https://macawfortwitter.com/">Macaw</a>, which showed you a feed of the tweets <em>all</em> of your followers liked each day, and the new accounts they followed.</li>



<li>Tech stack for Daily140 was PHP, MySQL, <a href="https://twitteroauth.com/">TwitterOAuth</a>. Macaw used Python and <a href="https://www.tweepy.org/">Tweepy</a> instead, for performance reasons.</li>
</ul>



<p>Both projects led to a few fun opportunities:</p>



<ul class="wp-block-list">
<li>I met a number of investors who would use it to get leads on new deals, people leaving companies, and other business intelligence</li>



<li>The Twitter Developer team did a one-hour research call with me, as part of their diligence before launching the v2 API and new Developer site</li>



<li>I emailed several crypto anons, all of whom used Daily 140 to monitor new protocols and blockchains</li>



<li>I got 3 offers to buy the software outright</li>
</ul>



<p>And were written up in a few publications:</p>



<ul class="wp-block-list">
<li><a href="https://www.businessinsider.com/best-apps-to-use-on-vacation-2015-7">5 must-have apps to download while you&#8217;re on vacation from work</a> -Business Insider</li>



<li><a href="https://techcrunch.com/2018/10/16/macaw-will-curate-twitter-for-you-help-expand-your-network/">Macaw will curate Twitter for you, help expand your network</a> -TechCrunch</li>



<li><a href="https://blog.hootsuite.com/twitter-tools/">The 50 Best Twitter Tools to Use</a> -Hootsuite</li>



<li><a href="https://buffer.com/library/free-twitter-tools/">The Big List of Twitter Tools</a> -Buffer</li>



<li><a href="https://sproutsocial.com/insights/twitter-tools/">16 Twitter tools to boost your brand’s marketing</a> -SproutSocial</li>



<li><a class="autolink" href="https://www.hongkiat.com/blog/twitter-tools/">80 Twitter Tools for Almost Everything</a> -Hongkiat</li>



<li>&#8220;Sometimes it is hard to get started with Twitter. Take advantage of the daily emails to find people of interest to follow or stay current on the latest education conversations. Use Daily 140 to stay up to date with other educators, politicians, The White House, and more.&#8221; &#8211;<a href="https://teachersfirst.com/subjects/science/all-grades/recent/65/">TeachersFirst</a></li>
</ul>



<p>All of my time now goes towards building <a href="https://clay.earth">Clay</a>, a home for your people and relationships that leverages a lot of the skills I learned building Daily 140 and Macaw, and we may end up rolling in some of the features those tools provided.</p>



<p>In both Clay and my side projects, I&#8217;m thinking about similar features layered on top of the next wave of social tools that are replacing Twitter, like <a class="autolink" href="https://joinmastodon.org/">Mastodon</a>, <a class="autolink" href="https://staging.bsky.app">Bluesky</a>, and <a class="autolink" href="https://Micro.blog">Micro.blog</a>. Decentralized architectures and availability of APIs unlock a whole world of possibilities on those platforms, and there&#8217;s clearly still a need for tools like Daily 140 for research, discovery, and monitoring.</p>



<p>Some final thoughts:</p>



<ol class="wp-block-list">
<li>If you&#8217;d be interested in a replacement for either tool, take my <a href="https://docs.google.com/forms/d/e/1FAIpQLScrh5XsWxdA7RBcRQ9fA4u45HPZTXpN3Ud4XkQoZYbEX0kAeQ/viewform?usp=sf_link">quick survey here</a>.</li>



<li>If you&#8217;re interested in learning more in the coming months, <a href="https://zmh.org/newsletter/">sign up for my updates newsletter here</a>.</li>
</ol>
]]></content:encoded>
					
					<wfw:commentRss>https://zmh.org/daily-140-and-macaw/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">837</post-id>	</item>
	</channel>
</rss>
