<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://temochka.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://temochka.com/" rel="alternate" type="text/html" /><updated>2026-01-09T23:51:20-05:00</updated><id>https://temochka.com/feed.xml</id><title type="html">Artem Chistyakov</title><subtitle>My name is Artem. I’m passionate about computers, arts, and writing. I’m both a career software engineer and a hobby computerist.
</subtitle><author><name>Artem Chistyakov</name></author><entry><title type="html">Vacation Trip Dramas</title><link href="https://temochka.com/blog/notes/2025/11/03/vacaton-trip-dramas.html" rel="alternate" type="text/html" title="Vacation Trip Dramas" /><published>2025-11-03T17:03:38-05:00</published><updated>2025-11-03T17:03:38-05:00</updated><id>https://temochka.com/blog/notes/2025/11/03/vacaton-trip-dramas</id><content type="html" xml:base="https://temochka.com/blog/notes/2025/11/03/vacaton-trip-dramas.html"><![CDATA[<p>There’s one genre I haven’t seen formally recognized, but is very dear to my heart. I call it “vacation trip drama” and it’s exactly what it sounds like: a dramatic story that takes place on a vacation trip, or involves one as a plot progression device. There’s something special about how the temporary nature of vacation trips brings about nuance and complexity to the characters. Almost as if they’re as surprised by their actions and feelings as we are.</p>

<p>Below are just some examples that come to mind (in no particular order).</p>

<h3 id="movies">Movies</h3>
<ul>
  <li><a href="https://en.wikipedia.org/wiki/Aftersun">Aftersun</a> (2022)</li>
  <li><a href="https://en.wikipedia.org/wiki/Afire">Afire</a> (2023)</li>
  <li><a href="https://en.wikipedia.org/wiki/A_Bigger_Splash_(2015_film)">A Bigger Splash</a> (2015)</li>
  <li><a href="https://en.wikipedia.org/wiki/Sex_and_Lucia">Sex and Lucia</a> (2001)</li>
  <li><a href="https://en.wikipedia.org/wiki/Stealing_Beauty">Stealing Beauty</a> (1996)</li>
  <li><a href="https://en.wikipedia.org/wiki/The_Hand_of_God_(film)">The Hand of God</a> (2021)</li>
  <li><a href="https://en.wikipedia.org/wiki/Call_Me_by_Your_Name_(film)">Call Me By Your Name</a> (2017)</li>
  <li><a href="https://en.wikipedia.org/wiki/Force_Majeure_(film)">Force Majeure</a> (2014)</li>
  <li><a href="https://en.wikipedia.org/wiki/Youth_(2015_film)">Youth</a> (2015)</li>
</ul>

<h3 id="novels">Novels</h3>
<ul>
  <li>Sally Rooney, “<a href="https://en.wikipedia.org/wiki/Conversations_with_Friends">Conversations with friends</a>” (2017, also a 2022 <a href="https://en.wikipedia.org/wiki/Conversations_with_Friends_(TV_series)">TV Series</a>)</li>
  <li>Renée Knight, “<a href="https://www.goodreads.com/book/show/23346719-disclaimer">Disclaimer</a>” (2015, also a 2024 <a href="https://en.wikipedia.org/wiki/Disclaimer_(TV_series)">TV Series</a>)</li>
</ul>]]></content><author><name>Artem Chistyakov</name></author><category term="blog" /><category term="notes" /><summary type="html"><![CDATA[There’s one genre I haven’t seen formally recognized, but is very dear to my heart. I call it “vacation trip drama” and it’s exactly what it sounds like: a dramatic story that takes place on a vacation trip, or involves one as a plot progression device. There’s something special about how the temporary nature of vacation trips brings about nuance and complexity to the characters. Almost as if they’re as surprised by their actions and feelings as we are.]]></summary></entry><entry><title type="html">The elephant in the room</title><link href="https://temochka.com/blog/posts/2025/08/03/elephant-in-the-room.html" rel="alternate" type="text/html" title="The elephant in the room" /><published>2025-08-03T21:55:49-04:00</published><updated>2025-08-03T21:55:49-04:00</updated><id>https://temochka.com/blog/posts/2025/08/03/elephant-in-the-room</id><content type="html" xml:base="https://temochka.com/blog/posts/2025/08/03/elephant-in-the-room.html"><![CDATA[<p>I’ve so far avoided writing about The Thing on this blog, mostly because I wasn’t sure whether a post about AI would have me channeling naive optimism or launching into a bitter anti-capitalist diatribe. If you’re on social media, it’s easy to get the impression that software engineers either believe that “manual coding is already obsolete” or that “a single line of LLM output will turn your codebase into unethical and/or subtly broken garbage.” In person, though, I’m hearing much more nuanced takes from my network of industry peers. These folks are trying to approach AI just as they have any new tech throughout their careers—remaining cautious but maintaining the requisite level of curiosity.</p>

<p>I’ll be frank: some days I get mad about how AI has sucked all the air out of the room. It’s become the stopgap for any discussions about the future of software, contributed to a climate of fear and distrust in many tech organizations, made tech hiring even worse, and devalued the lifelong stores of trivia collected by career engineers. But other times, I’m able to breeze through a dreaded chore or dabble in areas where I previously lacked confidence or expertise—all with the help of the same tools. The latter does feel good and, for a moment, makes me forget that, as a customer, I have little agency and no privacy in the face of the companies building them.</p>

<p>By now, I’ve been using various LLM-based tools virtually daily for several years. Though I don’t consider myself an expert in the space and remain skeptical about many of the bigger promises—and apprehensive about the potential for harm—I do find them useful. I may share more about my specific workflow some other time, but in this post I wanted to offer some random observations and “feels,” both positive and negative, as they appear to me through the lens of my decades-long experience building and using various software.</p>

<h3 id="the-potential-is-exciting">The potential is exciting</h3>

<p>At its best, programming with an AI assistant is what my 10-year-old self dreamed computer programming would be like—before being told by a stern informatics teacher to put my dreams of building a killer RPG on hold and learn five hundred memory-efficient ways to rearrange elements in a two-dimensional array. As time went on, I often wondered if, somewhere along the way, the acquired taste for puzzle-solving had overtaken the original desire to build things.</p>

<h3 id="its-dehumanizing">It’s dehumanizing</h3>

<p>I’ve heard people rehash this sentiment: “It’s dehumanizing to be told to ask AI for help, to review AI’s solution, to read a letter generated by an AI, etc.” I think I’m personally okay with this—as long as I’m the one writing the prompt. However, I never want to be the first person reviewing AI’s output to someone else’s prompt. At work, I’ve already had the unpleasant experience of code-reviewing AI-generated slop in good faith, only to see the “author” feed my feedback back to their code assistant and produce another iteration of half-baked, subtly wrong slop. I’m also fully in support of any regulation that makes it illegal for AIs to pose as humans.</p>

<h3 id="it-seems-familiar">It seems familiar</h3>

<p>I remember when web programming was looked down upon. Back in college, a mean senior made fun of me for investing time into learning the web stack. Having wrapped up his internship at a large consultancy specializing in native enterprise apps for Windows, he confidently proclaimed that “Web is not real programming.” At the time, it was obvious to me that all these types of apps would be on the web within ten years—which turned out to be true. The mean senior is now a friend and runs a consultancy specializing in building web apps for medical facilities. I’d surmise there are already more people using AI tools daily than there are web programmers.</p>

<h3 id="some-problems-should-not-be-solved">Some problems should not be solved</h3>

<p>When a human engineer picks up a task, it’s not uncommon for them to <em>not</em> produce any output for days, weeks… or ever. They may eventually return the task to the backlog. Those are not necessarily bad engineers. Sometimes there’s a mismatch between the task at hand and the person’s strengths. Other times, the whole premise of the task is flawed, and the best solution is to replace it with a different task—or keep procrastinating on it until (maybe) it goes away. There’s something unnatural about AI tools always giving their best effort to every problem they’re faced with.</p>

<h3 id="hard-way-is-not-always-the-right-way">Hard way is not always the right way</h3>

<p>I remember when jQuery was just gaining popularity around 2008. I’d already been a proficient JavaScript programmer, having embraced AJAX and rich client-side interactions. Somehow, I convinced myself that using this hot new library was “cheating,” “bloat,” and “not for real programmers.” Then a new engineer joined my team and rewrote a fragile component using jQuery—fixing multiple browser compatibility issues while removing half the existing code. It would be years before native browser APIs got anywhere near the ergonomics offered by jQuery (if they ever did). If nobody can tell the difference, there’s no special prize for doing things the hard way.</p>

<h3 id="can-software-afford-to-get-any-worse">Can software afford to get any worse?</h3>

<p>Earlier this year, one of my Mastodon posts went viral (by my standards anyway):</p>

<blockquote class="mastodon-embed" data-embed-url="https://jawns.club/@temochka/114181425759223498/embed" style="background: #FCF8FF; border-radius: 8px; border: 1px solid #C9C4DA; margin: 0; max-width: 540px; min-width: 270px; overflow: hidden; padding: 0;"> <a href="https://jawns.club/@temochka/114181425759223498" target="_blank" style="align-items: center; color: #1C1A25; display: flex; flex-direction: column; font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', Roboto, sans-serif; font-size: 14px; justify-content: center; letter-spacing: 0.25px; line-height: 20px; padding: 24px; text-decoration: none;"> ... </a> </blockquote>
<script data-allowed-prefixes="https://jawns.club/" async="" src="https://jawns.club/embed.js"></script>
<p><br /></p>

<p>I was referring to <a href="https://www.theatlantic.com/technology/archive/2017/09/saving-the-world-from-code/540393/">these</a> <a href="https://www.theatlantic.com/technology/archive/2015/11/programmers-should-not-call-themselves-engineers/414271/">two</a> different articles published in <em>The Atlantic</em> a while ago, pre-ChatGPT—back when there was a growing sentiment that software engineers ought to step up their game and take real responsibility for the effects low-quality software has on people’s lives. Software <a href="/blog/posts/2018/03/16/why-software-sucks.html">was a mess to begin with</a>, but now organizations are supercharged to churn out code beyond their engineers’ comprehension—something previously only possible by copy/pasting and introducing dependencies. This cannot be good.</p>

<h3 id="vibe-coding-is-viable">Vibe coding is viable</h3>

<p>More than a year ago, I “vibe coded” (which wasn’t even a term back then) a macOS app that presents itself as a MIDI-connected “recording light,” but in fact controls my Mac’s webcam so that when I press “Record” in Logic Pro X, a video of me playing the recorded region is saved in a separate folder. For a while, I used it to record guitar playthroughs for my <a href="/blog/posts/2024/01/23/random-melody.html">musicians club</a>. It’s the kind of project that would’ve required several nights of researching macOS multimedia APIs and a good refresher on Swift. To paraphrase: it’s the kind of project I’d never complete otherwise. If I end up losing my job to AI, I hope that at least it means programming is solved and everyone can make their computer do anything.</p>

<h3 id="asserting-control">Asserting control</h3>

<p>I’ve long accepted that professional programming is not some lofty mathematical discipline but a <a href="/blog/posts/2019/07/11/statistically-makes-sense.html">thing you do by poking around</a>. However, I’m not ready to give up the hope of developing at least a high-level understanding of the systems I work with. I’ll continue to push for a cohesive theory of the code my teams write (or generate) at work. Neither will I stop maintaining my own private “garden” of lightweight tools for personal productivity—such as <a href="/blog/posts/2021/02/26/anykey.html">Anykey</a>, my <a href="/blog/posts/2025/02/11/text-bookmarks.html">text-based bookmark manager</a>, clipboard helper, and a custom <a href="/blog/posts/2021/01/12/easy-calendar-navigation-with-alfred.html">calendar workflow</a>. There’s still something to be said for the value of small programs that can be fully understood.</p>]]></content><author><name>Artem Chistyakov</name></author><category term="blog" /><category term="posts" /><summary type="html"><![CDATA[I’ve so far avoided writing about The Thing on this blog, mostly because I wasn’t sure whether a post about AI would have me channeling naive optimism or launching into a bitter anti-capitalist diatribe. If you’re on social media, it’s easy to get the impression that software engineers either believe that “manual coding is already obsolete” or that “a single line of LLM output will turn your codebase into unethical and/or subtly broken garbage.” In person, though, I’m hearing much more nuanced takes from my network of industry peers. These folks are trying to approach AI just as they have any new tech throughout their careers—remaining cautious but maintaining the requisite level of curiosity.]]></summary></entry><entry><title type="html">Linking to iCloud files</title><link href="https://temochka.com/blog/posts/2025/04/11/linking-to-icloud.html" rel="alternate" type="text/html" title="Linking to iCloud files" /><published>2025-04-11T23:04:03-04:00</published><updated>2025-04-11T23:04:03-04:00</updated><id>https://temochka.com/blog/posts/2025/04/11/linking-to-icloud</id><content type="html" xml:base="https://temochka.com/blog/posts/2025/04/11/linking-to-icloud.html"><![CDATA[<p>Today I want to share a neat trick I use to link to files from my iCloud Drive in my <a href="/blog/posts/2025/03/11/notes-and-tasks-belong-together.html">notes and tasks</a>. These links work across macOS and iOS and don’t require an active Internet connection. By default, iCloud doesn’t offer anything like this—but luckily, there’s another built-in app we can call to the rescue.</p>

<p>You guessed it—this is yet another post about Shortcuts and Alfred! My workaround is pretty simple: I have a shortcut called “<a href="https://www.icloud.com/shortcuts/aaa6b8d8ed8148c887c149cbb2212da3">icloud</a>,” which is triggered via the Shortcuts URL scheme (e.g., <code class="language-plaintext highlighter-rouge">shortcuts://run-shortcut?name=icloud&amp;text=path/filename</code>) and opens the provided file path in Quick View.</p>

<p>To create these URLs, I use another shortcut called “<a href="https://www.icloud.com/shortcuts/82e19fc4f28a4029ac4864fb0922b5a1">Copy iCloud Link</a>,” which takes one or more files as input and produces a list of Markdown links:</p>

<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="nv">Music/Die on Mars/Audiodreams/Audiodreams.mp3</span><span class="p">](</span><span class="sx">shortcuts://run-shortcut?name=icloud&amp;input=text&amp;text=Music/Die%20on%20Mars/Audiodreams/Audiodreams.mp3</span><span class="p">)</span>
</code></pre></div></div>

<p>To make URL creation even easier on macOS, I also have an Alfred file action (part of <a href="https://github.com/temochka/macos-automation/tree/main/AlfredProcess">Process</a>) that triggers the “Copy iCloud Link” shortcut.</p>

<figure class="figure figure--center">
    <img src="https://img.temochka.com/7f1e510f735b3c6a565b14a1e8200602.png" alt="A screenshot of Alfred file actions featuring Copy iCloud Link" width="700" />
    <figcaption>Creating iCloud URLs from Alfred</figcaption>
</figure>

<p>P.S. The “Copy iCloud Link” shortcut used to be slightly fancier. I used to convert Markdown to Rich Text and copy the RTF to the clipboard. This had the benefit of working across both Markdown editors and various WYSIWYGs. I could also swear it used to work on iOS, but it no longer does. It seems to have broken with a recent macOS update, and I’ve given up on trying to fix it.</p>]]></content><author><name>Artem Chistyakov</name></author><category term="blog" /><category term="posts" /><summary type="html"><![CDATA[Today I want to share a neat trick I use to link to files from my iCloud Drive in my notes and tasks. These links work across macOS and iOS and don’t require an active Internet connection. By default, iCloud doesn’t offer anything like this—but luckily, there’s another built-in app we can call to the rescue.]]></summary></entry><entry><title type="html">Notes and tasks belong together</title><link href="https://temochka.com/blog/posts/2025/03/11/notes-and-tasks-belong-together.html" rel="alternate" type="text/html" title="Notes and tasks belong together" /><published>2025-03-11T21:17:09-04:00</published><updated>2025-03-11T21:17:09-04:00</updated><id>https://temochka.com/blog/posts/2025/03/11/notes-and-tasks-belong-together</id><content type="html" xml:base="https://temochka.com/blog/posts/2025/03/11/notes-and-tasks-belong-together.html"><![CDATA[<p>I’ve written before about my fondness for the <a href="/blog/posts/2020/02/22/linking-to-apple-notes.html">simplicity of Apple Notes</a> and the seemingly infinite <a href="/blog/posts/2017/02/06/omnifocus-nginx-sync.html">flexibility of OmniFocus</a>. I’m still partial to both apps but haven’t used either for some time. The reason is that I’ve concluded that <em>notes and tasks belong together</em>, and neither app could be stretched to do both well enough. As a result, I ended up switching to Obsidian, which, with the help of some plugins, just manages to pull it off. It’s not perfect, though, and I’ll cover the trade-offs at the end.</p>

<p>Being a GTD adept, the way I set things up is that for every project (any task that takes more than a single action to complete), I have a dedicated note where I dump all relevant information—web links, random thoughts, file attachments—which may or may not develop more structure as I progress. More often than not, it’s a mess of URLs and half-finished sentences. Other times, it reads like a blog post or an outline of one.</p>

<p>The way I had this set up with Notes and OmniFocus never felt <em>great</em>. Constantly switching windows, wondering whether I should leave a short note on the OmniFocus task or put it in the project note, and all those times when I made a <em>note</em> that something should be done but forgot to add a corresponding task. I was also envious of the bi-directional links popularized by Roam Research and quickly adopted by every other note-taking app (except Apple Notes).</p>

<p>Despite all that, I tried my best to stretch my existing tools to fit this workflow:</p>
<ul>
  <li>I hacked together a solution for <a href="/blog/posts/2020/02/22/linking-to-apple-notes.html">linking to notes via AppleScript and Shortcuts</a>, allowing me to establish a bidirectional link between OmniFocus and the project note in Apple Notes.</li>
  <li>I built a system-wide <a href="">fuzzy search for notes via AppleScript</a> and Alfred (later replaced with Sean Ballinger’s excellent <a href="https://github.com/sballin/alfred-search-notes-app">Alfred workflow</a>) to quickly pull up the relevant project note.</li>
  <li>I developed <a href="/blog/posts/2021/02/26/anykey.html">Anykey</a> and used it to add various missing navigation shortcuts (Next note, Previous note, Move note to…) to work around some deficiencies in the Notes UI.</li>
  <li>I even had a pretty elaborate <a href="https://github.com/temochka/macos-automation/blob/4fb6d0200d62db733484d12cd0f39b359239bb06/applescript/com.apple.Notes/launcher.json#L60-L67">setup</a> where, if I typed <code class="language-plaintext highlighter-rouge">[[</code> anywhere (in any Mac app, not just Notes), an Alfred-powered fuzzy search of all notes would pop up and allow me to insert a bi-directional link between whatever was currently focused and the target note using <a href="https://hookproductivity.com">Hookmark</a>.</li>
</ul>

<p>Needless to say, doing all this was FUN. Unfortunately, the resulting solution was still quirky and difficult to maintain, with both Apple and OmniGroup constantly fiddling with their apps and causing regressions for me. Thus, after long consideration and an adventurous migration, I ended up storing my notes and tasks in Markdown files on iCloud and using Obsidian to organize them. The task management workflow described below is what I arrived at after about two years of various experiments and another year of using this particular configuration. That is to say, I understand the trade-offs pretty well.</p>

<figure class="figure figure--center">
    <img src="https://img.temochka.com/2b92468ade49d26fbcf36c8d294b5acb.png" alt="A screenshot of my project note in Obsidian containing multiple tasks." title="An excerpt of an actual project note that’s currently in progress in my Obsidian vault" width="700" />
    <figcaption>A project log interspersed with tasks</figcaption>
</figure>

<h2 id="capture">Capture</h2>

<p>Unless a task belongs to an existing project, it goes into a new file under the Task directory. The file names are timestamped and contain the task description (e.g., <code class="language-plaintext highlighter-rouge">2025-03-05 - Renew vehicle registration.md</code>). The created file starts with a single Markdown checklist item that duplicates the file name.</p>

<p>This simple setup has the following benefits:</p>

<ul>
  <li>Each task is a separate note, so I can brain-dump everything—links, code snippets, attachments—then close the file with peace of mind, knowing it won’t get lost.</li>
  <li>I can easily link to tasks and projects from other notes by file name.</li>
  <li>I don’t <em>have to</em> use Obsidian to create new tasks; any new file under the Task directory will get picked up by my system just the same.</li>
  <li>Any task can easily be turned into a “project”—just add more tasks to the same file (nested tasks also supported). It feels very natural to add to-dos just as I’m fleshing out the project note (see the project log example above).</li>
</ul>

<p>I use the <a href="https://quickadd.obsidian.guide">QuickAdd</a> plugin and have a keyboard shortcut that triggers a capture flow for new tasks within Obsidian on Mac. For iOS, I made a shortcut that does the same but outside of Obsidian, enabling me to add tasks through Siri. This kind of thing is “<a href="https://stephango.com/file-over-app">File Over App</a>” philosophy at its best.</p>

<p>There are also caveats to naming files after the task: first, the file name may get out of sync with the actual task in the file, and second, file systems impose various restrictions on valid file names. I haven’t had any issues with the former, but I had to write a QuickAdd macro that scrubs restricted characters and converts Markdown to text. For example, an input like <code class="language-plaintext highlighter-rouge">Buy tickets to [Captain America: Brave New World](https://example.org)</code> results in a file named <code class="language-plaintext highlighter-rouge">2025-03-11 - Buy tickets to Captain America Brave New World.md</code>.</p>

<h2 id="organization">Organization</h2>

<p>I rely on the <a href="https://publish.obsidian.md/tasks/Introduction">Tasks</a> plugin for keeping track of my active projects and tasks. The most important features it provides beyond Obsidian’s built-in task management are deferred tasks (“ignore task until date X”), repeating tasks (e.g., “repeat every 2nd Sunday”), and a highly flexible query language for searching available tasks. Those are <a href="https://www.youtube.com/watch?v=9AXFsLv6pZc" title="a reference to “The Bear”">non-negotiables</a> for any serious GTD practitioner.</p>

<p>My main task view is called “Priority”—an actual note named <code class="language-plaintext highlighter-rouge">GTD/Priority.md</code>. I love the simplicity compared to custom perspectives in OmniFocus. This note queries tasks that are either due soon or marked as priority during review.</p>

<figure class="figure figure--center">
    <img src="https://img.temochka.com/5f1f614af635b2a6f9baa3f35f324af4.png" alt="A screenshot of my GTD/Priority note in Obsidian listing due &amp; overdue tasks as well as priorities picked for each of my life values." title="Yes, I’m overdue on sharpening knives. It’s such a dull chore." width="700" />
    <figcaption>Priority view</figcaption>
</figure>

<p>In addition, I insert an overview of created and completed tasks as part of my Daily Note template:</p>

<figure class="figure figure--center">
    <img src="https://img.temochka.com/100e52a5f5f7edf0a00d443c5bb6f6be.png" alt="A screenshot of my daily note in Obsidian containing multiple completed tasks." title="My daily notes are primarily read-only, and their main purpose is tying together various notes for the day" width="700" />
    <figcaption>Completed tasks are highlighted in each daily note</figcaption>
</figure>

<p>I also maintain many additional views over my tasks: all unfinished tasks grouped by tags (or project), “orphaned” projects (without any pending tasks), priority tasks finished this week (for my weekly review note), etc. Given how easy it is to add these views, I’ll probably add even more in the future.</p>

<h2 id="final-thoughts">Final thoughts</h2>

<p>Keeping tasks alongside notes has been incredibly freeing—add a new line after a to-do, jot down some thoughts, and move on. It feels natural. Back when I used paper notebooks, I always interspersed notes with tasks. In hindsight, it’s almost strange that I spent so much time trying to separate them in my digital workflows.</p>]]></content><author><name>Artem Chistyakov</name></author><category term="blog" /><category term="posts" /><summary type="html"><![CDATA[I’ve written before about my fondness for the simplicity of Apple Notes and the seemingly infinite flexibility of OmniFocus. I’m still partial to both apps but haven’t used either for some time. The reason is that I’ve concluded that notes and tasks belong together, and neither app could be stretched to do both well enough. As a result, I ended up switching to Obsidian, which, with the help of some plugins, just manages to pull it off. It’s not perfect, though, and I’ll cover the trade-offs at the end.]]></summary></entry><entry><title type="html">How I manage my bookmarks</title><link href="https://temochka.com/blog/posts/2025/02/11/text-bookmarks.html" rel="alternate" type="text/html" title="How I manage my bookmarks" /><published>2025-02-11T23:09:10-05:00</published><updated>2025-02-11T23:09:10-05:00</updated><id>https://temochka.com/blog/posts/2025/02/11/text-bookmarks</id><content type="html" xml:base="https://temochka.com/blog/posts/2025/02/11/text-bookmarks.html"><![CDATA[<p>Several years ago, I deleted all bookmarks from my web browser and moved them into a plain text note. I then set up <a href="https://www.alfredapp.com">Alfred</a> to always keep those important URLs <a href="/blog/posts/2018/11/14/flow-notes-searching.html">right at my fingertips</a>. This simple setup has since become a crucial part of my workflow, bringing me daily joy and impressed reactions from coworkers watching my screen. In this post, I’ll describe how it works.</p>

<figure class="figure figure--center">
    <img src="https://img.temochka.com/38f5ae3e1851b9eb8f7c0acaec5cb31e.png" alt="A screenshot of Alfred window with “elm” typed in it showing a list matching bookmarks." title="I miss writing Elm so felt like giving it a shoutout." width="700" />
    <figcaption>Searching bookmarked Elm library docs</figcaption>
</figure>

<p>Like many others, I had been guilty of neglecting web bookmarks. I relied on Google search or my browser’s address bar auto-completion and then navigated through the target website until I reached the destination page. At some point, I began bookmarking my most-used websites and relied on Alfred’s browser bookmarks search for <a href="/blog/posts/2018/11/14/flow-notes-searching">quick access</a>. However, it often took multiple clicks (and page loads) to reach the exact page I was after. So, I started bookmarking individual pages: Grafana dashboards, my profile settings on different apps, docs for specific libraries and modules, etc. This was a marked improvement, but there was an unexpected downside.</p>

<p>Turns out, managing bookmarks in the browser is a miserable experience. Simple operations like “update the title of a recently bookmarked URL” or “review all bookmarked pages for a particular website” often required multiple clicks through slow and unwieldy menus. To make things worse, Safari has two completely different bookmark-related UIs: “Show Bookmarks” (a sidebar) and “Edit Bookmarks” (a settings tab), both allowing editing, but only one of them supporting search. Yes, you can, in fact, open them in the same tab for extra confusion.</p>

<figure class="figure figure--center">
    <img src="https://img.temochka.com/71097f52b8e71cd07fdea8cc4b13aa59.png" alt="A screenshot of Safari showing “Show bookmarks” and “Edit bookmarks” panels open side by side" title="Yes, you can, in fact, open them side by side." width="700" />
    <figcaption>This is the kind of GUI that kills “power users” before they’re born</figcaption>
</figure>

<p>Now imagine you’re onboarding to a new team where, within the first few days, you’re likely to receive dozens of links to various dashboards, internal tools, and code repositories. Trying to organize these using the aforementioned browser UI is tedious, and in my opinion, this is why so many people give up and rely on scattered notes, search, and their address bar auto-completion to get around.</p>

<p>More than once, I thought, “This would be so much more manageable if it were just a text file.” So, when I was about to join a new project, I decided to try something different. I created a fresh Markdown note that looked something like this:</p>

<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gh"># Bookmarks</span>

<span class="gu">## Logging</span>

Splunk - Trace transaction  
https://example.org/dashboard/trace-transaction

Splunk - HTTP Server Logs  
https://example.org/index/http

Splunk - RPC Server Logs  
https://example.org/index/rpc

<span class="gu">## Monitoring</span>

Grafana - HTTP Server Golden Metrics  
https://example.org/dashboard/http-server

Grafana - RPC Server Golden Metrics  
https://example.org/dashboard/rpc-server
</code></pre></div></div>

<p>I then set up an Alfred workflow that runs a program capable of reading this file and outputting it in Alfred’s <a href="https://www.alfredapp.com/help/workflows/inputs/script-filter/json/">Script Filter format</a>. Initially, the program was a Ruby script, but eventually, I <a href="https://github.com/temochka/macos-automation/blob/main/cli/bm.c">rewrote it in C</a> with zero dependencies. Even without any caching or clever optimizations, the conversion is still instant, even on my 1,000-line bookmarks file. This workflow allows me to fire up Alfred and fuzzy search my entire collection of bookmarks. And if I type “edit” and press Return, it opens the bookmarks note in VS Code for quick editing. I briefly considered using a structured format like YAML or TOML, but I like how my Markdown-inspired text format is low on ceremony and also looks like a regular note in my note-taking app.</p>

<figure class="figure figure--center">
    <img src="https://img.temochka.com/ea9eed01dd8f047de19858e04aadc1e9.png" alt="A screenshot of my Alfred workflow setup in Alfred UI" title="The script filter just runs the compiled binary linked above" width="700" />
    <figcaption>The entire Bookmarks workflow setup in Alfred</figcaption>
</figure>

<p>In terms of organization, I typically maintain a “Misc” section at the top and place new bookmarks there until it grows unwieldy, at which point I move things around in bulk (which is a breeze, thanks to text editors!). Another benefit of storing bookmarks as text is that I can easily share a bunch of related links with someone since it’s just a simple copy and paste: “Hey, Aliana, these are the three most important dashboards that we pay attention to.”</p>

<p>That’s it! That’s the pitch. I transitioned all of my actively used bookmarks to this format and haven’t looked back. I find it somewhat ironic that browsers used to store bookmarks in plain text, only to later switch to a local database—partly to prevent people from modifying the file with scripts.</p>

<p>If you currently rely mostly on your address bar and (maybe) sparse bookmarks but would like to try some of the ideas in this post, here are a few suggestions I often give to people who ask about my productivity tools:</p>

<ul>
  <li>Start by utilizing your browser’s bookmarks. There’s already fuzzy search built into most browsers (in Safari, all bookmarks are searchable via <code class="language-plaintext highlighter-rouge">Cmd+Shift+/</code>). Get used to navigating this way instead of relying solely on the address bar. Add missing bookmarks as you go.</li>
  <li>Try <a href="https://www.alfredapp.com">Alfred</a> or <a href="https://www.raycast.com">Raycast</a>. These tools can teach you how to apply the same approach for navigating your clipboard history, files, and apps.</li>
  <li>Consider the text file approach. <a href="https://github.com/temochka/macos-automation/blob/main/cli/bm.c">My C parser</a> might be useful (even just as a reference) for Alfred users, but if Raycast is more your style or you’re a programmer, you may enjoy writing your own.</li>
  <li>You can, in fact, <a href="https://github.com/temochka/macos-automation/tree/main/AlfredProcess">download my entire Alfred workflow from GitHub</a>, but do so at your own risk as I don’t provide any support for my automation projects.</li>
</ul>]]></content><author><name>Artem Chistyakov</name></author><category term="blog" /><category term="posts" /><summary type="html"><![CDATA[Several years ago, I deleted all bookmarks from my web browser and moved them into a plain text note. I then set up Alfred to always keep those important URLs right at my fingertips. This simple setup has since become a crucial part of my workflow, bringing me daily joy and impressed reactions from coworkers watching my screen. In this post, I’ll describe how it works.]]></summary></entry><entry><title type="html">A Random Melody</title><link href="https://temochka.com/blog/posts/2024/01/23/random-melody.html" rel="alternate" type="text/html" title="A Random Melody" /><published>2024-01-23T21:31:06-05:00</published><updated>2024-01-23T21:31:06-05:00</updated><id>https://temochka.com/blog/posts/2024/01/23/random-melody</id><content type="html" xml:base="https://temochka.com/blog/posts/2024/01/23/random-melody.html"><![CDATA[<figure class="figure figure--center">
    <img src="https://img.temochka.com/34f0a54e89c1b7c95fcc4be6bf5fc1b9.png" alt="A screenshot the Random Melody app that the author built. It features a piano keyboard with key numbered with the order in which they should be played" title="I didn’t check the math but another club member calculated the odds of throwing an increasing sequence of five numbers on D12 as p=0.0031." width="700" />
    <figcaption>A screenshot of the running Random Melody app</figcaption>
</figure>

<p>My online musicians community has been running
a fun little challenge: every Friday night the organizer throws a D12 die five times.
Each throw represents the number of semi-tones from the root note (1).
The end result is a six-note sequence (including root) that looks something like this:
“<a href="https://random-melody.temochka.com/?melody=1-4-6-9-10-11">1-4-6-9-10-11</a>”.</p>

<p>Each participant then has a week to craft a 30 to 60-second musical piece featuring the assigned
note sequence, following the rules below:</p>

<ul>
  <li>Keep the original note order, but feel free to:
    <ul>
      <li>transpose the entire sequence by any number of semitones;</li>
      <li>change any note’s octave;</li>
      <li>experiment with different note durations.</li>
    </ul>
  </li>
  <li>If stuck, alter one note by a semitone.</li>
</ul>

<p>You can listen to <a href="https://youtube.com/shorts/hnqwWfymfw4?feature=share">one of my own recent solutions on YouTube</a>.</p>

<p>So far, we’ve made it to the sixth week of the challenge and I’m still in love with this musical puzzle. Finding the “right” underlying harmony consistently
fills me with pride and joy. What surprised me most was how diverse and dissimilar the submissions are: not just due to participants’ preferred genres (ranging from EDM to progressive metal),
but hinting at fundamental differences in everyone’s sense of harmony.</p>

<p>This past weekend I was away from my instruments when the new assignment was posted.
Having access to my laptop, I fumbled with the on-screen piano keyboard for a bit, but,
as usual for me, my heart was not in it without the physical sensation of playing an instrument.
Instead, I got an idea for a small app that would:</p>

<ul>
  <li>visualize the melody on a piano keyboard,</li>
  <li>play the melody,</li>
  <li>transpose the melody to a different root note,</li>
  <li>generate more random melodies,</li>
  <li>support shareable links to generated melodies.</li>
</ul>

<p>The skeptic in me tried to object with “why don’t you just open Logic Pro X and throw together an
entry using some electronic instruments for a change”, which, admittedly, was a fair point.
And yet, I shushed that bore away and chose to listen to the other, more excited and fun voice that was all
fired up discussing the quickest way to build this thing.
It didn’t take long for that voice to sway me: I’m no stranger to the <a href="/blog/posts/2018/05/01/parser-therapy.html">joy of building small well-defined apps</a>,
and here I had the added benefit of it being somewhat useful to a handful of actual people I know.</p>

<p>I used the tools I’m most familiar with and banged out the initial prototype in about an hour.
Thanks to the power of <a href="https://elm-lang.org">Elm</a>, its standard library, and Matthew Griffith’s <a href="https://package.elm-lang.org/packages/mdgriffith/elm-ui/latest/">elm-ui</a>,
I didn’t have to fiddle around with complex build pipelines or even write a single line of HTML or CSS.
The whole thing came out as a single Elm file that I was able to deploy and
present to the community that same evening.</p>

<p>Over the next couple of days I spent an odd hour here and there adding some polish and missing features,
and now I can happily say that <em>it’s done</em>. It’s a humble app that does its little thing pretty well.
I don’t think I’ll be coming back to make more changes. I’ll use it while the club challenge lasts and then it’ll remain on the web while my website exists. Somebody (maybe you?) may even partake in the challenge. Knowing this feels good.</p>

<p>Links:</p>

<ul>
  <li><a href="https://random-melody.temochka.com/">Random melody page</a></li>
  <li><a href="https://github.com/temochka/random-melody/tree/main">Code on GitHub</a></li>
</ul>]]></content><author><name>Artem Chistyakov</name></author><category term="blog" /><category term="posts" /><summary type="html"><![CDATA[A screenshot of the running Random Melody app]]></summary></entry><entry><title type="html">Anykey: my first native macOS app</title><link href="https://temochka.com/blog/posts/2021/02/26/anykey.html" rel="alternate" type="text/html" title="Anykey: my first native macOS app" /><published>2021-02-26T20:54:25-05:00</published><updated>2021-02-26T20:54:25-05:00</updated><id>https://temochka.com/blog/posts/2021/02/26/anykey</id><content type="html" xml:base="https://temochka.com/blog/posts/2021/02/26/anykey.html"><![CDATA[<p>Recently, my system automation journey took me on an unexpected excursion as I found myself building a native macOS app. Now, mere two weeks later, it’s finished and I’ve integrated it into my main setup. It’s called <a href="https://github.com/temochka/Anykey">Anykey</a>, and it’s a tool for binding arbitrary shell commands to system-wide or app-specific hotkeys. It’s configured via a text file that can be stored in Git or synced to Dropbox. It’s free (as in <a href="https://www.gnu.org/licenses/quick-guide-gplv3.html">GPLv3</a>) and open-source, so anyone curious can <a href="https://github.com/temochka/Anykey/releases/latest">download it from GitHub</a>.</p>

<figure class="figure figure--center">
  <img src="https://img.temochka.com/1ea7b3e3306dbacbaa4c1c39620b495f.png" width="128" title="Anykey icon" />
  <figcaption>Of course, Anykey icon is <a href="https://madebyjulia.com">made by Julia</a></figcaption>
</figure>

<p>It all started when I finally conceded that some of my most used <a href="https://github.com/temochka/macos-automation">automation scripts</a> could benefit from dedicated keyboard shortcuts, as I got tired of <a href="/blog/posts/2018/11/14/flow-notes-searching.html">invoking them by name</a> every single time. To be fair, I’d already set up a few hotkeys in <a href="https://github.com/temochka/macos-automation/tree/main/AlfredProcess">my Alfred workflow</a>, but, aside from having to hook each one up using an awkward graph GUI, those can be pretty cumbersome to maintain across multiple machines. For security reasons, Alfred doesn’t export concrete hotkeys bindings for its workflows.</p>

<p>I believed there must be “a better way”, so I began to investigate what others are doing. A popular suggestion is to use <a href="https://support.apple.com/guide/automator/welcome/mac">Automator</a> to <a href="https://appleinsider.com/articles/18/03/14/how-to-create-keyboard-shortcuts-to-launch-apps-in-macos-using-automator">create a simple system service</a>. The service can then be assigned a hotkey in System Preferences. This works well if you only have a few automations and don’t mind repeating the process on every machine that you work on. I briefly considered writing a script to build macOS services programmatically, but that still wouldn’t solve the need to manually edit the settings. Overall, hardly an improvement over Alfred.</p>

<p>The conversation threads unveiled by my web searches kept mentioning tools like <a href="https://www.keyboardmaestro.com/main/">Keyboard Maestro</a>, but neither it nor its kin supported text configs. So I turned to <a href="https://www.hammerspoon.org">Hammerspoon</a>, which advertised the ability to assign shortcuts to automations. Ultimately, I wasn’t too thrilled about the Lua config and I was skeptical that it’d be able to create app-scoped hotkeys (this hunch later proved to be correct), given how the API is structured. So it was about at that time when I thought to myself: “hell, <a href="/blog/posts/2021/01/12/easy-calendar-navigation-with-alfred.html">I know some Swift</a>, maybe I could build this thing in a couple of days”.</p>

<p>Unsurprisingly, I soon became the living illustration of the tortured JFK’s saying: “we chose to do this not because it is easy, but because we thought it was going to be easy”. In my mind, this whole process looked something like: generate a “status bar app” in Xcode (nope, not an actual starter template, but <a href="https://www.appcoda.com/macos-status-bar-apps/">Gabriel Theodoropoulos’ epic writeup</a> helps), then crank up the views in the much-vaunted <a href="https://developer.apple.com/xcode/swiftui/">SwiftUI</a> (turns out, there’s still a ton of stuff that exists exclusively in AppKit/Cocoa), then hook up this promising <a href="https://github.com/soffes/HotKey">Hotkey lib</a> (oops, creates exclusive shortcuts that cannot be scoped to a particular app) to a JSON config (<a href="https://elm-lang.org">Elm</a> has made me forget how cumbersome and error-prone dealing with JSON is in statically typed languages), PROFIT?</p>

<p>So, after the first few nights of frantically putting this thing together, my enthusiasm noticeably waned. So much that I considered giving up on the idea. When the Hotkey lib couldn’t do what I needed, I felt at an impasse. At the <a href="https://twitter.com/artemchistyakov/status/1359245853165240323">lowest point</a>, I found myself studying an obscure PDF describing Apple’s deprecated Carbon APIs, then forking Hotkey to try to apply what I learned to work around some of the issues I was seeing. No luck: any keyboard shortcut declared by Hotkey immediately stopped working in all other apps. Having virtually no experience developing for the Apple platform, I felt out of my depth. Finally a forum comment somewhere pointed me towards the <a href="https://developer.apple.com/documentation/coregraphics/quartz_event_services">Quartz Events Services</a>, which, at a first glance, seemed like another obscure macOS API. But searching GitHub for usage examples (a criminally under-appreciated way of studying APIs), I found a bunch of apps successfully using it for similar use cases (whole-OS Vim emulators, keyboard cleaners, etc.). In hindsight, this was the key to the puzzle, and once I got it to work, everything just kind of snapped together.</p>

<p>Integrating Anykey into my automation setup went even smoother than I expected: I updated <a href="https://github.com/temochka/macos-automation/tree/main/AlfredProcess">Process</a> to expose an <a href="https://www.alfredapp.com/help/workflows/triggers/external/">external trigger</a> for my script launcher workflow. Anykey then invokes a simple AppleScript that “pulls” that trigger with a specified argument. The <a href="https://github.com/temochka/macos-automation/commit/913f6f21a64daf35c840649f590e1f8444663248">whole changeset</a> is less than one hundred lines of code and I can now easily assign a hotkey to any AppleScript in my collection and my status bar is adorned by this (cliché, I know) <a href="https://en.wikipedia.org/wiki/Command_key">looped square</a> that I chose for the Anykey logo.</p>

<figure class="figure figure--center">
  <img src="https://img.temochka.com/1eb942957b99993c1d8ae953d8f9d0d4.png" width="800" alt="macOS status bar with Anykey icon highlighted" title="Anykey in the macOS status bar" />
  <figcaption>Anykey lurking in the macOS status bar</figcaption>
</figure>

<p>From the feedback to my low-key <a href="https://twitter.com/artemchistyakov/status/1364393337508233216">Twitter announcement</a> of Anykey, I learned that <a href="https://karabiner-elements.pqrs.org">Karabiner-Elements</a>, which I’d only known as a “fancy keyboard remapping tool“ also has the ability to run shell commands, and can even scope assignments to individual apps. Had I known this, I would’ve likely deemed it “good enough” and went with it. So I’m thankful for my ignorance in this instance. Karabiner feels a lot more heavyweight and it doesn’t auto-reload its configuration when it changes on the disk, so I’m going to stick with Anykey. I also have another unique feature in mind that, if it works out, would put Anykey miles ahead of Karabiner for this particular use case. Stay tuned!</p>]]></content><author><name>Artem Chistyakov</name></author><category term="blog" /><category term="posts" /><summary type="html"><![CDATA[Recently, my system automation journey took me on an unexpected excursion as I found myself building a native macOS app. Now, mere two weeks later, it’s finished and I’ve integrated it into my main setup. It’s called Anykey, and it’s a tool for binding arbitrary shell commands to system-wide or app-specific hotkeys. It’s configured via a text file that can be stored in Git or synced to Dropbox. It’s free (as in GPLv3) and open-source, so anyone curious can download it from GitHub.]]></summary></entry><entry><title type="html">Makeshift image sharing using Alfred</title><link href="https://temochka.com/blog/posts/2021/01/14/makeshift-image-sharing-using-alfred.html" rel="alternate" type="text/html" title="Makeshift image sharing using Alfred" /><published>2021-01-14T16:49:06-05:00</published><updated>2021-01-14T16:49:06-05:00</updated><id>https://temochka.com/blog/posts/2021/01/14/makeshift-image-sharing-using-alfred</id><content type="html" xml:base="https://temochka.com/blog/posts/2021/01/14/makeshift-image-sharing-using-alfred.html"><![CDATA[<p>I really like this comic by <a href="https://twitter.com/freetonik">Rakhim</a>:</p>

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Blogging is inversely proportional to the number of posts about elaborate blog setups<br /><br />More comics here → <a href="https://t.co/gOsFFvbKHh">https://t.co/gOsFFvbKHh</a> <a href="https://t.co/0mx1aehrES">pic.twitter.com/0mx1aehrES</a></p>&mdash; Rakhim (@freetonik) <a href="https://twitter.com/freetonik/status/1324297857218842624?ref_src=twsrc%5Etfw">November 5, 2020</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<p>As someone in the “static gen” camp, I’ve definitely had to suppress the urge to share the intricacies of my own <a href="https://jekyllrb.com">Jekyll</a> setup. Ultimately, I decided against it because… frankly, it <em>sucks</em>. And I don’t mean it in a humble, self-deprecating way. Publishing anything on this blog involves writing Markdown (meh) in several editors (the “nice” one for writing, then the “programming” one for custom markup and final edits), fumbling with version control, running CLI commands, hand-writing image paths, deploying, et cetera, et cetera.</p>

<p>After having to go through all this again for my <a href="/blog/posts/2021/01/12/easy-calendar-navigation-with-alfred.html">post from the other day</a>, I resolved to make this mess a little more bearable by at least removing the “hand-writing image paths” step. Currently, most of my blog post graphics are stored in Git with the rest of the content. This means that to add an illustration, I need to create an image, place it into the images directory, then finally link it from the post (and try my best to remember to commit it). Ideally, I’d rather just take a screenshot and immediately get a shareable public link (a-la <a href="https://www.getcloudapp.com">CloudApp</a>) that I can insert into my post.</p>

<p>I ended up setting up another <a href="https://www.alfredapp.com">Alfred</a> workflow that can accept an image from Clipboard (or a file via Alfred’s <a href="https://www.alfredapp.com/blog/tips-and-tricks/file-actions-from-alfred-or-finder/">File Actions</a>), upload it to my private image hosting server, and paste the generated public URL to the frontmost app.</p>

<figure class="figure">
  <img class="img--border" src="https://img.temochka.com/efde3c6c8fb30b703f8b9eb1797d0623.png
" alt="Text showing an image URL alongside a macOS notification reading “Image URL copied to clipboard”" width="650" />
  <figcaption>The workflow in action.</figcaption>
</figure>

<p>The image below displays the overall structure of the resulting workflow, which can be triggered either via a keyword (for clipped a image) or a file action.</p>

<figure class="figure">
  <img src="https://img.temochka.com/3cab4cca3e670c65c70225c6af7aa699.png" title="Workflow Graph. This image was uploaded with the described workflow :)" alt="Workflow graph. We enter the workflow either via the “imglink” keyword or via a file action. The file action goes straight to scp upload Bash script, the clipboard path has another step that uses AppleScript to save clipboard contents to a temporary file (potentially, erroring if the operation fails). Once the file is uploaded, we copy its URL to Clipboard and, at the same time, display an OS notification." width="650" />
  <figcaption>The workflow implementation graph.</figcaption>
</figure>

<p>In contrast to some of the similar workflows I’ve found online, my implementation has no external dependencies and should work on any relatively recent macOS version. To achieve this zero-dependency property, I had to solve the problem of getting the screenshot data out of Clipboard without relying on an external utility like <a href="https://github.com/jcsalterego/pngpaste">pngpaste</a> (unfortunately, the built-in <code class="language-plaintext highlighter-rouge">pbpaste</code> is limited to text and RTF). It turned out that by using some “Dark AppleScript” with <a href="https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptLangGuide/conceptual/ASLR_lexical_conventions.html#//apple_ref/doc/uid/TP40000983-CH214-SW5">raw data format incantations</a>, one can get the desired bytes by casting the clipboard to “PNGf” (four-byte file type code for PNG):</p>

<div class="language-applescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">set</span><span class="w"> </span><span class="nv">tmpfile</span><span class="w"> </span><span class="k">to</span><span class="w"> </span><span class="p">(</span><span class="nb">do shell script</span><span class="w"> </span><span class="s2">"mktemp"</span><span class="p">)</span><span class="w">

</span><span class="k">try</span><span class="w">
  </span><span class="k">set</span><span class="w"> </span><span class="nv">fhandle</span><span class="w"> </span><span class="k">to</span><span class="w"> </span><span class="nb">open for access</span><span class="w"> </span><span class="nv">tmpfile</span><span class="w"> </span><span class="nv">with</span><span class="w"> </span><span class="nb">write</span><span class="w"> </span><span class="nv">permission</span><span class="w">
  </span><span class="nb">write</span><span class="w"> </span><span class="p">(</span><span class="nb">the clipboard</span><span class="w"> </span><span class="k">as</span><span class="w"> </span>«<span class="nb">class PNGf</span>»<span class="p">)</span><span class="w"> </span><span class="k">to</span><span class="w"> </span><span class="nv">fhandle</span><span class="w">
  </span><span class="nb">close access</span><span class="w"> </span><span class="nv">fhandle</span><span class="w">
  </span><span class="nv">tmpfile</span><span class="w">
</span><span class="k">on</span> <span class="k">error</span><span class="w"> </span><span class="nv">errMsg</span><span class="w"> </span><span class="nv">number</span><span class="w"> </span><span class="nv">n</span><span class="w">
  </span><span class="k">if</span><span class="w"> </span><span class="nv">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">-</span><span class="mi">1700</span><span class="w"> </span><span class="k">then</span><span class="w"> </span><span class="c1">-- Not a PNG clibpoard</span><span class="w">
    </span><span class="nb">display dialog</span><span class="w"> </span><span class="s2">"The clibpoard is not a PNG image."</span><span class="w"> </span><span class="nb">buttons</span><span class="w"> </span><span class="p">{</span><span class="s2">"OK"</span><span class="p">}</span><span class="w">
  </span><span class="k">end</span><span class="w"> </span><span class="k">if</span><span class="w">
  </span><span class="k">try</span><span class="w">
    </span><span class="nb">close access</span><span class="w"> </span><span class="nv">tmpfile</span><span class="w">
  </span><span class="k">end</span><span class="w"> </span><span class="k">try</span><span class="w">
  
  </span><span class="s2">""</span><span class="w">
</span><span class="k">end</span><span class="w"> </span><span class="k">try</span><span class="w">
</span></code></pre></div></div>

<p>Once that step’s done, it’s just a matter of uploading the resulting file to your web server, S3, etc. (I just run <a href="https://www.ssh.com/ssh/scp/">scp</a>). I use the uploaded file’s MD5 hash for its destination name, since these paths don’t have to be human-readable (“SEO experts” might disagree). The workflow completes by posting a notification and copying the image link to Clipboard.</p>

<p>I’m pretty happy with the result and I <em>think</em> this shouldn’t create a lot of extra maintenance for me down the line (which is always a concern with “rolling your own”). Of course, there are some (acceptable for me) drawbacks of decoupling image storage from blog content:</p>

<ul>
  <li>you no longer see images while running the site locally;</li>
  <li>detecting broken image links becomes slightly more difficult;</li>
  <li>another thing that can break :-)</li>
</ul>

<p>Anyway, I’ve been on a kind of automation spree this past year so there are likely more AppleScript/Alfred posts coming soon. I hope they’re helpful to someone (let me know via email below or on Twitter)! If you think the described workflow could be useful for you, my meta-workflow called Process (includes this workflow) is <a href="https://github.com/temochka/macos-automation#alfredprocess">available on GitHub</a>. You’re welcome to build it from source, run “as is”, study the implementation, cherry-pick from it, or anything, really (all at your own risk).</p>]]></content><author><name>Artem Chistyakov</name></author><category term="blog" /><category term="posts" /><summary type="html"><![CDATA[I really like this comic by Rakhim:]]></summary></entry><entry><title type="html">Easy Calendar navigation with Alfred</title><link href="https://temochka.com/blog/posts/2021/01/12/easy-calendar-navigation-with-alfred.html" rel="alternate" type="text/html" title="Easy Calendar navigation with Alfred" /><published>2021-01-12T21:22:49-05:00</published><updated>2021-01-12T21:22:49-05:00</updated><id>https://temochka.com/blog/posts/2021/01/12/easy-calendar-navigation-with-alfred</id><content type="html" xml:base="https://temochka.com/blog/posts/2021/01/12/easy-calendar-navigation-with-alfred.html"><![CDATA[<p>This past year, like many other “suddenly remote” workers, I found myself using digital calendars even more than usual. Mainly, trying to block some focus time before another “X sync” splits my afternoon into two chunks too small to do any deep work, but also looking for any documents linked via attached notes (yes, the documents everyone was supposed to read <em>before</em> the meeting), and, of course, panic-scanning the event notes for the elusive Zoom ID so I can join within that “3-minute late” sweet spot.</p>

<p>The macOS Calendar app doesn’t make any of this particularly easy: in Apple’s typical fashion, current meeting’s notes and relevant URLs are neatly tucked away in the details popup, and I often have to scroll the popup contents to find the right field. I strongly believe that “<a href="/blog/posts/2018/11/14/flow-notes-searching.html">searching is typing</a>” and any time you’re visually scanning the content on the screen is a wasted an opportunity to let the computer do it for you. Naturally, once I’ve recognized this inefficiency, I got an itch to resolve it.</p>

<p>Unsurprisingly, <a href="https://www.alfredapp.com">Alfred</a> came to the rescue. I wrote a <a href="https://github.com/temochka/macos-automation/blob/main/AlfredProcess/src/calendar.swift">small CLI program</a> that reads calendar data from <a href="https://developer.apple.com/documentation/eventkit">EventKit</a> and then used Alfred’s <a href="https://www.alfredapp.com/help/workflows/inputs/script-filter/">Script Filters</a> to give it an ergonomic, search-driven UI. Now, within a keystroke, I have an option to:</p>

<ul>
  <li>jump to the current or upcoming event in the Calendar app;</li>
  <li>quickly open any link attached to current or upcoming events without even opening the Calendar app.</li>
</ul>

<p>The first workflow displays events happening between now and 24 hours from now in chronological order and includes a “Jump to Today” fallback option to open the Today’s view in Calendar.</p>

<figure class="figure">
  <img src="/images/alfred-calendar-nowc.png" width="500" alt="A screenshot of Jump to event shortcut" title="Jump to event" />
</figure>

<p>The latter extracts every link mentioned in notes, URL, or location fields of every event happening between now and three hours from now, making them easily accessible.</p>

<figure class="figure">
  <img src="/images/alfred-calendar-nowl.png" width="500" alt="A screenshot of Jump to link shortcut" title="Jump to link" />
</figure>

<p>This workflow has changed the way I interact with my calendar. I rarely even have to open the app: <code class="language-plaintext highlighter-rouge">nowc</code> gives me the agenda and <code class="language-plaintext highlighter-rouge">nowl</code> gets me to the right Zoom. Aside from impressing some coworkers during screen sharing sessions, another unexpected benefit was how this workflow made OmniFocus time blocking at least twice better. When doing my daily review of current projects, I often drag tasks from OmniFocus onto the calendar, which creates back-linked time blocks. Typically, these backlinks are only marginally useful, but now that they’re just a keystroke away, it’s my favorite way to navigate to the current task to mark it as complete or access its metadata.</p>

<figure class="figure">
  <img src="/images/alfred-calendar-of.png" width="500" alt="A screenshot of Jump to link shortcut with an OmniFocus link" title="Jump to OmniFocus" />
</figure>

<p>If you think these automations could be useful for you, too, they are available publicly as a part of my <a href="https://github.com/temochka/macos-automation#alfredprocess">macos-automation</a> GitHub repo and anyone is welcome to build them from source following the provided instructions. Use them at your own risk! This post is to give you ideas of what automations are possible with Alfred and a a few lines of Swift. The rest is left as an exercise to the reader.</p>]]></content><author><name>Artem Chistyakov</name></author><category term="blog" /><category term="posts" /><summary type="html"><![CDATA[This past year, like many other “suddenly remote” workers, I found myself using digital calendars even more than usual. Mainly, trying to block some focus time before another “X sync” splits my afternoon into two chunks too small to do any deep work, but also looking for any documents linked via attached notes (yes, the documents everyone was supposed to read before the meeting), and, of course, panic-scanning the event notes for the elusive Zoom ID so I can join within that “3-minute late” sweet spot.]]></summary></entry><entry><title type="html">Choosing Your Giants: Principles for Navigating the Landscape of Emerging Tech</title><link href="https://temochka.com/blog/links/2021/01/04/choosing-your-giants.html" rel="alternate" type="text/html" title="Choosing Your Giants: Principles for Navigating the Landscape of Emerging Tech" /><published>2021-01-04T15:40:31-05:00</published><updated>2021-01-04T15:40:31-05:00</updated><id>https://temochka.com/blog/links/2021/01/04/choosing-your-giants</id><content type="html" xml:base="https://temochka.com/blog/links/2021/01/04/choosing-your-giants.html"><![CDATA[<p>I gave a talk about the philosophy of technology choices at the (online) Philly ETE 2020. You can <a href="https://youtu.be/nh5j6v69EhI">watch the recording on YouTube</a> or in the embedded player below.</p>

<iframe width="560" height="315" src="https://www.youtube.com/embed/nh5j6v69EhI" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>]]></content><author><name>Artem Chistyakov</name></author><category term="blog" /><category term="links" /><summary type="html"><![CDATA[I gave a talk about the philosophy of technology choices at the (online) Philly ETE 2020. You can watch the recording on YouTube or in the embedded player below.]]></summary></entry></feed>