<rss xmlns:source="http://source.scripting.com/" version="2.0">
  <channel>
    <title>Carlo Zottmann</title>
    <link>https://zottmann.org/</link>
    <description></description>
    
    <language>en</language>
    
    <lastBuildDate>Sat, 24 Jan 2026 01:12:20 +0100</lastBuildDate>
    <item>
      <title>TIL how to auto-move Xcode DEBUG builds to Applications</title>
      <link>https://zottmann.org/2026/01/24/til-how-to-automove-xcode.html</link>
      <pubDate>Sat, 24 Jan 2026 01:12:20 +0100</pubDate>
      
      <guid>http://czottmann.micro.blog/2026/01/24/til-how-to-automove-xcode.html</guid>
      <description>&lt;p&gt;TIL a neat Xcode trick!&lt;/p&gt;
&lt;p&gt;So my apps contain app intents. Those won&amp;rsquo;t show up in Shortcuts unless the app is anywhere in &lt;code&gt;/Applications&lt;/code&gt;. For months now I&amp;rsquo;ve been using a post-build scheme script to move the DEBUG build there, w/ a symlink to the app in its original place in derived data.&lt;/p&gt;
&lt;p&gt;This worked well but was a whole thing because I had to make sure cleaning the build would wipe the moved app etc.&lt;/p&gt;
&lt;p&gt;Turns out I was overthinking it! All I needed to do was to add this in the right &lt;code&gt;.xcconfig&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;DEPLOYMENT_LOCATION = YES
DSTROOT = /Applications/Dev Builds
INSTALL_PATH = /
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now Xcode takes care of all the things, I don&amp;rsquo;t need those scripts anymore, and Xcode even correctly cleans the built when necessary.&lt;/p&gt;
&lt;p&gt;So that&amp;rsquo;s that. The more you know!&lt;/p&gt;
</description>
      <source:markdown>TIL a neat Xcode trick! 

So my apps contain app intents. Those won&#39;t show up in Shortcuts unless the app is anywhere in `/Applications`. For months now I&#39;ve been using a post-build scheme script to move the DEBUG build there, w/ a symlink to the app in its original place in derived data.

This worked well but was a whole thing because I had to make sure cleaning the build would wipe the moved app etc.

Turns out I was overthinking it! All I needed to do was to add this in the right `.xcconfig`:

```
DEPLOYMENT_LOCATION = YES
DSTROOT = /Applications/Dev Builds
INSTALL_PATH = /
```

Now Xcode takes care of all the things, I don&#39;t need those scripts anymore, and Xcode even correctly cleans the built when necessary.

So that&#39;s that. The more you know!
</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://zottmann.org/2026/01/22/aller-deutschsprachigen-kommentare-zu-jedwedem.html</link>
      <pubDate>Thu, 22 Jan 2026 18:18:06 +0100</pubDate>
      
      <guid>http://czottmann.micro.blog/2026/01/22/aller-deutschsprachigen-kommentare-zu-jedwedem.html</guid>
      <description>&lt;p&gt;83% aller deutschsprachigen Kommentare zu jedwedem Thema sind &lt;em&gt;&amp;ldquo;Das haben wir noch nie so gemacht&amp;rdquo;&lt;/em&gt;, &lt;em&gt;&amp;ldquo;Sie können hier nicht parken&amp;rdquo;&lt;/em&gt; und &lt;em&gt;&amp;ldquo;Hier wird nicht gerannt&amp;rdquo;&lt;/em&gt;, nur halt mit Hut und Trenchcoat und aufgeklebtem Schnauzbart.&lt;/p&gt;
</description>
      <source:markdown>83% aller deutschsprachigen Kommentare zu jedwedem Thema sind _&#34;Das haben wir noch nie so gemacht&#34;_, _&#34;Sie können hier nicht parken&#34;_ und _&#34;Hier wird nicht gerannt&#34;_, nur halt mit Hut und Trenchcoat und aufgeklebtem Schnauzbart.
</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://zottmann.org/2026/01/01/quoting-craig-mod-on-the.html</link>
      <pubDate>Thu, 01 Jan 2026 21:40:41 +0100</pubDate>
      
      <guid>http://czottmann.micro.blog/2026/01/01/quoting-craig-mod-on-the.html</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://craigmod.com/ridgeline/203/&#34;&gt;Quoting Craig Mod&lt;/a&gt;, on the correct way of handling the garbage we create:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A funny thing happens when a Snickers bar goes from whole to eaten — the wrapper transmogrifies from useful to toxic. Suddenly, this thing that was keeping germs and dirt off your chocolate sugar log is now &amp;ldquo;useless&amp;rdquo; and with this comes the heaviest burden a modern person unencumbered by genocide or famine can hold: garbage responsibility. […]&lt;/p&gt;
&lt;p&gt;There are no garbage cans in Kamakura, and, indeed, if you are buying a coffee to go, you will be responsible for that receptacle for, potentially, a very long time. This is your grandé-sized hair shirt to bear. […]&lt;/p&gt;
&lt;p&gt;This obsession with the immediate &amp;ldquo;unburdening&amp;rdquo; of a thing &lt;em&gt;you&lt;/em&gt; created is common in non-Japanese contexts, but I posit: The Japanese way is the correct way. Be an adult. Own your garbage. Garbage responsibility is something we’ve long since abdicated not only to faceless cans on street corners (or just all over the street, as seems to be the case in Manhattan or Paris), but also faceless developing countries around the world. Our oceans teem with the waste from generations of averted eyes. And I believe the two — local pathologies and attendant global pathologies — are &lt;em&gt;not&lt;/em&gt; not connected.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I&amp;rsquo;m slowly starting to believe I&amp;rsquo;m secretly Japanese.&lt;/p&gt;
</description>
      <source:markdown>[Quoting Craig Mod](https://craigmod.com/ridgeline/203/), on the correct way of handling the garbage we create:

&gt; A funny thing happens when a Snickers bar goes from whole to eaten — the wrapper transmogrifies from useful to toxic. Suddenly, this thing that was keeping germs and dirt off your chocolate sugar log is now &#34;useless&#34; and with this comes the heaviest burden a modern person unencumbered by genocide or famine can hold: garbage responsibility. […]
&gt;
&gt; There are no garbage cans in Kamakura, and, indeed, if you are buying a coffee to go, you will be responsible for that receptacle for, potentially, a very long time. This is your grandé-sized hair shirt to bear. […]
&gt;
&gt; This obsession with the immediate &#34;unburdening&#34; of a thing *you* created is common in non-Japanese contexts, but I posit: The Japanese way is the correct way. Be an adult. Own your garbage. Garbage responsibility is something we’ve long since abdicated not only to faceless cans on street corners (or just all over the street, as seems to be the case in Manhattan or Paris), but also faceless developing countries around the world. Our oceans teem with the waste from generations of averted eyes. And I believe the two — local pathologies and attendant global pathologies — are *not* not connected.

I&#39;m slowly starting to believe I&#39;m secretly Japanese.
</source:markdown>
    </item>
    
    <item>
      <title>Toleranz ist kein moralisches Gebot, sondern ein Friedensvertrag</title>
      <link>https://zottmann.org/2026/01/01/toleranz-ist-kein-moralisches-gebot.html</link>
      <pubDate>Thu, 01 Jan 2026 14:36:01 +0100</pubDate>
      
      <guid>http://czottmann.micro.blog/2026/01/01/toleranz-ist-kein-moralisches-gebot.html</guid>
      <description>&lt;p&gt;Das Essay &lt;a href=&#34;https://medium.com/extra-extra/tolerance-is-not-a-moral-precept-1af7007d6376&#34;&gt;Tolerance is not a moral precept&lt;/a&gt; von Yonatan Zunger ist eines, das ich regelmäßig auf Mastodon teile, denn es ist sehr gut. Yonatan löst das scheinbare &lt;a href=&#34;https://de.wikipedia.org/wiki/Toleranz-Paradoxon&#34;&gt;Paradoxon der Toleranz&lt;/a&gt; sehr elegant auf, indem er das &lt;em&gt;Framing&lt;/em&gt; zurechtrückt, und das Konzept &amp;ldquo;Toleranz&amp;rdquo; schärfer definiert.&lt;/p&gt;
&lt;p&gt;Da ich es als sehr klug empfinde, aber keine Möglichkeit gefunden habe, den Autor zu kontaktieren&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;, um ihn zu fragen, ob ich es liebevoll ins Deutsche übersetzen darf, möchte ich hier auf seinen frei zugänglichen Post in der (sehr lesbaren) Auto-Übersetzung hinweisen.&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;→ &lt;a href=&#34;https://freedium--mirror-cfd.translate.goog/https://medium.com/extra-extra/tolerance-is-not-a-moral-precept-1af7007d6376?_x_tr_sl=auto&amp;amp;_x_tr_tl=de&amp;amp;_x_tr_hl=de&#34;&gt;Toleranz ist kein moralisches Gebot | von Yonatan Zunger&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Toleranz ist kein absoluter moralischer Wert, sondern ein Friedensvertrag.&lt;/strong&gt; Toleranz ist eine soziale Norm, weil sie es verschiedenen Menschen ermöglicht, friedlich zusammenzuleben. Sie bedeutet, dass wir akzeptieren, dass Menschen anders sein können als wir – in ihren Bräuchen, ihrem Verhalten, ihrer Kleidung, ihrem Sexualleben – und dass uns das nichts angeht, solange es unser Leben nicht direkt betrifft. Doch das Modell eines Friedensvertrags unterscheidet sich von einem moralischen Gebot in einem einfachen Punkt: Der Schutz eines Friedensvertrags gilt nur für diejenigen, die bereit sind, sich an seine Bedingungen zu halten. Es ist eine Vereinbarung, in Frieden zu leben, nicht eine Vereinbarung, unabhängig vom Verhalten anderer friedlich zu sein. Ein Friedensvertrag ist kein Selbstmordpakt.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ich wünsche Euch ein gutes neues Jahr. Bleibt tolerant, aber nicht passiv.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;#FCKNZS&lt;/code&gt; `#FCKAFD&lt;/p&gt;
&lt;p&gt;Links:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://medium.com/extra-extra/tolerance-is-not-a-moral-precept-1af7007d6376&#34;&gt;Tolerance is not a moral precept. | by Yonatan Zunger&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://archive.is/20250325114235/https://medium.com/extra-extra/tolerance-is-not-a-moral-precept-1af7007d6376&#34;&gt;archive.is&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://web.archive.org/web/20251112164151/https://medium.com/extra-extra/tolerance-is-not-a-moral-precept-1af7007d6376&#34;&gt;web.archive.org&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Ausserhalb LinkedIn, und meinen LI-Account habe ich vor Jahren schon gelöscht. Tja.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Mit Umweg über den freedium-Mirror des originalen Medium-Posts.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
      <source:markdown>Das Essay [Tolerance is not a moral precept](https://medium.com/extra-extra/tolerance-is-not-a-moral-precept-1af7007d6376) von Yonatan Zunger ist eines, das ich regelmäßig auf Mastodon teile, denn es ist sehr gut. Yonatan löst das scheinbare [Paradoxon der Toleranz](https://de.wikipedia.org/wiki/Toleranz-Paradoxon) sehr elegant auf, indem er das _Framing_ zurechtrückt, und das Konzept &#34;Toleranz&#34; schärfer definiert.

Da ich es als sehr klug empfinde, aber keine Möglichkeit gefunden habe, den Autor zu kontaktieren[^1], um ihn zu fragen, ob ich es liebevoll ins Deutsche übersetzen darf, möchte ich hier auf seinen frei zugänglichen Post in der (sehr lesbaren) Auto-Übersetzung hinweisen.[^2]

[^1]: Ausserhalb LinkedIn, und meinen LI-Account habe ich vor Jahren schon gelöscht. Tja.
[^2]: Mit Umweg über den freedium-Mirror des originalen Medium-Posts.

→ [Toleranz ist kein moralisches Gebot | von Yonatan Zunger](https://freedium--mirror-cfd.translate.goog/https://medium.com/extra-extra/tolerance-is-not-a-moral-precept-1af7007d6376?_x_tr_sl=auto&amp;_x_tr_tl=de&amp;_x_tr_hl=de):

&gt; **Toleranz ist kein absoluter moralischer Wert, sondern ein Friedensvertrag.** Toleranz ist eine soziale Norm, weil sie es verschiedenen Menschen ermöglicht, friedlich zusammenzuleben. Sie bedeutet, dass wir akzeptieren, dass Menschen anders sein können als wir – in ihren Bräuchen, ihrem Verhalten, ihrer Kleidung, ihrem Sexualleben – und dass uns das nichts angeht, solange es unser Leben nicht direkt betrifft. Doch das Modell eines Friedensvertrags unterscheidet sich von einem moralischen Gebot in einem einfachen Punkt: Der Schutz eines Friedensvertrags gilt nur für diejenigen, die bereit sind, sich an seine Bedingungen zu halten. Es ist eine Vereinbarung, in Frieden zu leben, nicht eine Vereinbarung, unabhängig vom Verhalten anderer friedlich zu sein. Ein Friedensvertrag ist kein Selbstmordpakt.

Ich wünsche Euch ein gutes neues Jahr. Bleibt tolerant, aber nicht passiv.

`#FCKNZS` `#FCKAFD

Links:

- [Tolerance is not a moral precept. | by Yonatan Zunger](https://medium.com/extra-extra/tolerance-is-not-a-moral-precept-1af7007d6376)
	- [archive.is](https://archive.is/20250325114235/https://medium.com/extra-extra/tolerance-is-not-a-moral-precept-1af7007d6376)
	- [web.archive.org](https://web.archive.org/web/20251112164151/https://medium.com/extra-extra/tolerance-is-not-a-moral-precept-1af7007d6376)
</source:markdown>
    </item>
    
    <item>
      <title>Cities are organisms</title>
      <link>https://zottmann.org/2025/12/25/cities-are-organisms.html</link>
      <pubDate>Thu, 25 Dec 2025 00:21:33 +0100</pubDate>
      
      <guid>http://czottmann.micro.blog/2025/12/25/cities-are-organisms.html</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://www.samholden.jp/p/is-a-city-alive&#34;&gt;An interesting question posed by Sam Holden:&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&#34;https://www.theguardian.com/books/2025/apr/28/is-a-river-alive-by-robert-macfarlane-review-streams-of-consciousness&#34;&gt;Robert Macfarlane’s Is A River Alive?&lt;/a&gt; asks what would it mean for our understanding of the natural world and our relationship to it if we saw rivers not just as ecosystems containing life, but as truly alive. In beautifully animistic prose, Macfarlane ventures to the frontier of the rights of nature movement, where rivers are treated as subjective entities that think, feel and are endowed with legal protections. The book also inspires a related thought experiment: is a city alive?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;My personal view, one that I held for years, is that a city is an organism – so yes, it is alive. Its citizens are its cells, its genome, its flesh, its live blood. Remove those, and the organism will die and wither. Remove the stones, however, the steel and glass, the asphalt, and you&amp;rsquo;re left with half an organism quickly regrowing the missing parts of its body.&lt;/p&gt;
</description>
      <source:markdown>[An interesting question posed by Sam Holden:](https://www.samholden.jp/p/is-a-city-alive)

&gt; [Robert Macfarlane’s Is A River Alive?](https://www.theguardian.com/books/2025/apr/28/is-a-river-alive-by-robert-macfarlane-review-streams-of-consciousness) asks what would it mean for our understanding of the natural world and our relationship to it if we saw rivers not just as ecosystems containing life, but as truly alive. In beautifully animistic prose, Macfarlane ventures to the frontier of the rights of nature movement, where rivers are treated as subjective entities that think, feel and are endowed with legal protections. The book also inspires a related thought experiment: is a city alive?

My personal view, one that I held for years, is that a city is an organism – so yes, it is alive. Its citizens are its cells, its genome, its flesh, its live blood. Remove those, and the organism will die and wither. Remove the stones, however, the steel and glass, the asphalt, and you&#39;re left with half an organism quickly regrowing the missing parts of its body.
</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://zottmann.org/2025/12/07/quoting-jon-worth-from-a.html</link>
      <pubDate>Sun, 07 Dec 2025 22:51:59 +0100</pubDate>
      
      <guid>http://czottmann.micro.blog/2025/12/07/quoting-jon-worth-from-a.html</guid>
      <description>&lt;p&gt;Quoting &lt;a href=&#34;https://bsky.app/profile/jonworth.eu/post/3m7gdnt775s26&#34;&gt;Jon Worth&lt;/a&gt; from a Bluesky thread:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;After […] Musk&amp;rsquo;s statement to abolish the EU (after the Commission fined X), let&amp;rsquo;s ask ourselves simply:&lt;/p&gt;
&lt;p&gt;HOW ARE EUROPEAN COMMISSIONERS USING X NOW? […]&lt;/p&gt;
&lt;p&gt;If European Digital Sovereignty is to mean anything, it ought to mean NOT posting on a platform owned and run by a fascist intent on undermining the EU!&lt;/p&gt;
&lt;p&gt;And don&amp;rsquo;t give me the bullshit you have to be there for &amp;ldquo;balance&amp;rdquo; or &amp;ldquo;reach&amp;rdquo; - the rules are stacked against you from the outset&lt;/p&gt;
&lt;/blockquote&gt;
</description>
      <source:markdown>Quoting [Jon Worth](https://bsky.app/profile/jonworth.eu/post/3m7gdnt775s26) from a Bluesky thread:

&gt; After \[…] Musk&#39;s statement to abolish the EU (after the Commission fined X), let&#39;s ask ourselves simply:
&gt; 
&gt; HOW ARE EUROPEAN COMMISSIONERS USING X NOW? \[…]
&gt;
&gt; If European Digital Sovereignty is to mean anything, it ought to mean NOT posting on a platform owned and run by a fascist intent on undermining the EU!
&gt; 
&gt; And don&#39;t give me the bullshit you have to be there for &#34;balance&#34; or &#34;reach&#34; - the rules are stacked against you from the outset
</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://zottmann.org/2025/12/02/quoting-louis-rosenberg-in-other.html</link>
      <pubDate>Tue, 02 Dec 2025 13:22:34 +0100</pubDate>
      
      <guid>http://czottmann.micro.blog/2025/12/02/quoting-louis-rosenberg-in-other.html</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://bigthink.com/the-present/the-rise-of-ai-denialism/&#34;&gt;Quoting Louis Rosenberg&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In other words, we are not watching a bubble expand with blustery vapors. We are watching a planet form from churning magma, and it will solidify into a new framework for society. Denial will only make us unprepared. This is not an AI bubble. This is real.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I agree with several of his points, but I also take the whole post with a grain of salt, mind. The guy is a computer scientist but also the &lt;a href=&#34;https://bigthink.com/people/louis-rosenberg/&#34;&gt;CEO of a AI company&lt;/a&gt; which I suspect colors/ informs his POV and predictions.&lt;/p&gt;
</description>
      <source:markdown>[Quoting Louis Rosenberg](https://bigthink.com/the-present/the-rise-of-ai-denialism/):

&gt; In other words, we are not watching a bubble expand with blustery vapors. We are watching a planet form from churning magma, and it will solidify into a new framework for society. Denial will only make us unprepared. This is not an AI bubble. This is real.

I agree with several of his points, but I also take the whole post with a grain of salt, mind. The guy is a computer scientist but also the [CEO of a AI company](https://bigthink.com/people/louis-rosenberg/) which I suspect colors/ informs his POV and predictions.
</source:markdown>
    </item>
    
    <item>
      <title>November Sale! 25% off of BarCuts and Browser Actions</title>
      <link>https://zottmann.org/2025/11/27/november-sale-off-of-barcuts.html</link>
      <pubDate>Thu, 27 Nov 2025 14:07:10 +0100</pubDate>
      
      <guid>http://czottmann.micro.blog/2025/11/27/november-sale-off-of-barcuts.html</guid>
      <description>&lt;p&gt;I recently released updates to both my contextual macOS Shortcuts launcher, &lt;a href=&#34;https://actions.work/barcuts&#34;&gt;BarCuts&lt;/a&gt;, and &lt;a href=&#34;https://actions.work/browser-actions&#34;&gt;Browser Actions&lt;/a&gt;, which let you automate Google Chrome, Vivaldi, Microsoft Edge, and other browsers. 🚀&lt;/p&gt;
&lt;p&gt;And since it&amp;rsquo;s November, I&amp;rsquo;ve also decided to join the fray and run a sale for them:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;✨They&amp;rsquo;re 25% off with code &lt;code&gt;FCKNZS2025&lt;/code&gt; until end of the month!✨&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;(People asked me whether &lt;a href=&#34;https://actions.work/actions-for-obsidian&#34;&gt;Actions For Obsidian&lt;/a&gt; will go on sale, but given it&amp;rsquo;s been &lt;a href=&#34;https://docs.actions.work/actions-for-obsidian/faqs/licensing/#pay-what-you-think-is-fair&#34;&gt;&amp;ldquo;Pay What You Think Is Fair&amp;rdquo;&lt;/a&gt; since the very beginning, I feel like it&amp;rsquo;s kind of always been on sale.😉)&lt;/p&gt;
&lt;p&gt;🖖🏼&lt;/p&gt;
</description>
      <source:markdown>I recently released updates to both my contextual macOS Shortcuts launcher, [BarCuts](https://actions.work/barcuts), and [Browser Actions](https://actions.work/browser-actions), which let you automate Google Chrome, Vivaldi, Microsoft Edge, and other browsers. 🚀 

And since it&#39;s November, I&#39;ve also decided to join the fray and run a sale for them:

 **✨They&#39;re 25% off with code `FCKNZS2025` until end of the month!✨**

(People asked me whether [Actions For Obsidian](https://actions.work/actions-for-obsidian) will go on sale, but given it&#39;s been [&#34;Pay What You Think Is Fair&#34;](https://docs.actions.work/actions-for-obsidian/faqs/licensing/#pay-what-you-think-is-fair) since the very beginning, I feel like it&#39;s kind of always been on sale.😉)

🖖🏼
</source:markdown>
    </item>
    
    <item>
      <title>A quick story about how a LLM saved me €100&#43; today</title>
      <link>https://zottmann.org/2025/11/19/a-quick-story-about-how.html</link>
      <pubDate>Wed, 19 Nov 2025 19:18:05 +0100</pubDate>
      
      <guid>http://czottmann.micro.blog/2025/11/19/a-quick-story-about-how.html</guid>
      <description>&lt;p&gt;I have this setup: XLR mic → ext. USB audio interface → Mac. The name of the audio interface (UMC22) has a trailing space, which macOS gets confused by every other day. It sanitizes the stored name, can’t find the device anymore, removes it, then finds a &amp;ldquo;new&amp;rdquo; device it doesn’t know and re-adds it. The mic works fine, but setting the audio interface as the default for anything doesn’t, because macOS keeps forgetting it.&lt;/p&gt;
&lt;p&gt;This has been going on forever, but it has gotten progressively worse with every major macOS update. (Don&amp;rsquo;t at me; I’ll keep using macOS because I write software for it-this is how I make my money.) Since macOS 26 rolled around, it happens every two days — basically every time I dock the MBP.&lt;/p&gt;
&lt;p&gt;I finally got fed up and started looking into a new USB mic — €100+ for quality products, naturally — which pissed me off because I like my existing mic; it&amp;rsquo;s good, and it works. It&amp;rsquo;s just that shitty interface issue + macOS, damn it.&lt;/p&gt;
&lt;p&gt;In the past, I&amp;rsquo;d tried setting up an aggregate (virtual) audio device that contained the audio interface, but that didn&amp;rsquo;t change anything. The interface would vanish and reappear as a new device, and the aggregate device wouldn&amp;rsquo;t know about it. I had to manually add the new device to the aggregate — no good.&lt;/p&gt;
&lt;p&gt;Anyway. Today I asked Claude to research that problem for me. It did and came back with a lot of technical detail, which boiled down to &lt;em&gt;&amp;ldquo;Carlo, you were right about what&amp;rsquo;s going on.&amp;quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;But all my describing the issue, plus the research, gave Claude a metric shit-ton of insight, so I then asked it to write me a Swift CLI tool that would let me add a named device to an existing aggregate device. And it did! When it was almost done, the 5-hour limit window struck, so I handed the prototype script over to Kimi K2 Thinking&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;, and it hammered out the rest for me.&lt;/p&gt;
&lt;p&gt;Frens, I was tickled fancy, let me tell you.&lt;/p&gt;
&lt;p&gt;Now I have a script that runs automatically in the background every time the USB device is connected. And since the aggregate doesn&amp;rsquo;t change (it&amp;rsquo;s just updated!), I can use that as the default device.&lt;/p&gt;
&lt;p&gt;Sure, without Claude and K2, I could&amp;rsquo;ve written that script myself, but it probably would have taken several days of my free time (since I have a day job) for research, trial, and error. This way, it took less than an hour to fix this specific issue.&lt;/p&gt;
&lt;p&gt;And I can keep using my old stuff. Win!&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;It&amp;rsquo;s a monster! A slow, slow monster.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
      <source:markdown>I have this setup: XLR mic → ext. USB audio interface → Mac. The name of the audio interface (UMC22) has a trailing space, which macOS gets confused by every other day. It sanitizes the stored name, can’t find the device anymore, removes it, then finds a &#34;new&#34; device it doesn’t know and re-adds it. The mic works fine, but setting the audio interface as the default for anything doesn’t, because macOS keeps forgetting it.

This has been going on forever, but it has gotten progressively worse with every major macOS update. (Don&#39;t at me; I’ll keep using macOS because I write software for it-this is how I make my money.) Since macOS 26 rolled around, it happens every two days — basically every time I dock the MBP.

I finally got fed up and started looking into a new USB mic — €100+ for quality products, naturally — which pissed me off because I like my existing mic; it&#39;s good, and it works. It&#39;s just that shitty interface issue + macOS, damn it.

In the past, I&#39;d tried setting up an aggregate (virtual) audio device that contained the audio interface, but that didn&#39;t change anything. The interface would vanish and reappear as a new device, and the aggregate device wouldn&#39;t know about it. I had to manually add the new device to the aggregate — no good.

Anyway. Today I asked Claude to research that problem for me. It did and came back with a lot of technical detail, which boiled down to _&#34;Carlo, you were right about what&#39;s going on.&#34;_

But all my describing the issue, plus the research, gave Claude a metric shit-ton of insight, so I then asked it to write me a Swift CLI tool that would let me add a named device to an existing aggregate device. And it did! When it was almost done, the 5-hour limit window struck, so I handed the prototype script over to Kimi K2 Thinking[^1], and it hammered out the rest for me.

[^1]: It&#39;s a monster! A slow, slow monster.

Frens, I was tickled fancy, let me tell you.

Now I have a script that runs automatically in the background every time the USB device is connected. And since the aggregate doesn&#39;t change (it&#39;s just updated!), I can use that as the default device.

Sure, without Claude and K2, I could&#39;ve written that script myself, but it probably would have taken several days of my free time (since I have a day job) for research, trial, and error. This way, it took less than an hour to fix this specific issue.

And I can keep using my old stuff. Win!
</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://zottmann.org/2025/11/16/why-solarpunk-is-already-happening.html</link>
      <pubDate>Sun, 16 Nov 2025 20:16:58 +0100</pubDate>
      
      <guid>http://czottmann.micro.blog/2025/11/16/why-solarpunk-is-already-happening.html</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://climatedrift.substack.com/p/why-solarpunk-is-already-happening&#34;&gt;Why Solarpunk is already happening in Africa&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;What’s happening across Sub-Saharan Africa right now is the most ambitious infrastructure project in human history, except it’s not being built by governments or utilities or World Bank consortiums. It’s being built by startups selling solar panels to farmers on payment plans. And it’s working.&lt;/p&gt;
&lt;p&gt;Over 30 million solar products sold in 2024. 400,000 new solar installations every month across Africa. 50% market share captured by companies that didn’t exist 15 years ago. Carbon credits subsidizing the cost. IoT chips in every device. 90%+ repayment rates on loans to people earning $2/day.&lt;/p&gt;
&lt;p&gt;And if you understand what’s happening in Africa, you understand the template for how infrastructure will get built everywhere else for the next 50 years.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Really, really cool.&lt;/p&gt;
</description>
      <source:markdown>[Why Solarpunk is already happening in Africa](https://climatedrift.substack.com/p/why-solarpunk-is-already-happening):

&gt; What’s happening across Sub-Saharan Africa right now is the most ambitious infrastructure project in human history, except it’s not being built by governments or utilities or World Bank consortiums. It’s being built by startups selling solar panels to farmers on payment plans. And it’s working.
&gt; 
&gt; Over 30 million solar products sold in 2024. 400,000 new solar installations every month across Africa. 50% market share captured by companies that didn’t exist 15 years ago. Carbon credits subsidizing the cost. IoT chips in every device. 90%+ repayment rates on loans to people earning $2/day.
&gt; 
&gt; And if you understand what’s happening in Africa, you understand the template for how infrastructure will get built everywhere else for the next 50 years.

Really, really cool.
</source:markdown>
    </item>
    
    <item>
      <title>Restarting macOS/iOS Continuity &amp; Handoff</title>
      <link>https://zottmann.org/2025/11/15/restarting-macosios-continuity-handoff.html</link>
      <pubDate>Sat, 15 Nov 2025 12:19:23 +0100</pubDate>
      
      <guid>http://czottmann.micro.blog/2025/11/15/restarting-macosios-continuity-handoff.html</guid>
      <description>&lt;p&gt;After updating both my Mac and iPhone to the latest OS 26 versions, Continuity/Handoff wasn&amp;rsquo;t working anymore, meaning no more cross-device copy-n-paste etc. Rebooting either device didn&amp;rsquo;t change anything.&lt;/p&gt;
&lt;p&gt;15 mins of searching brought me to &lt;a href=&#34;https://old.reddit.com/r/mac/comments/1fo2976/solution_to_handoff_not_working_between_mac_and/&#34;&gt;a Reddit post by /u/shesabadone&lt;/a&gt; which suggested resetting macOS&#39; &lt;code&gt;useractivityd&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;defaults delete com.apple.coreservices.useractivityd
killall useractivityd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It did the trick!&lt;/p&gt;
</description>
      <source:markdown>After updating both my Mac and iPhone to the latest OS 26 versions, Continuity/Handoff wasn&#39;t working anymore, meaning no more cross-device copy-n-paste etc. Rebooting either device didn&#39;t change anything.

15 mins of searching brought me to [a Reddit post by /u/shesabadone](https://old.reddit.com/r/mac/comments/1fo2976/solution_to_handoff_not_working_between_mac_and/) which suggested resetting macOS&#39; `useractivityd`:

```bash
defaults delete com.apple.coreservices.useractivityd
killall useractivityd
```

It did the trick!
</source:markdown>
    </item>
    
    <item>
      <title>Linearis v2025.11.2</title>
      <link>https://zottmann.org/2025/11/12/linearis-v.html</link>
      <pubDate>Wed, 12 Nov 2025 14:38:25 +0100</pubDate>
      
      <guid>http://czottmann.micro.blog/2025/11/12/linearis-v.html</guid>
      <description>&lt;p&gt;Yesterday, I released &lt;a href=&#34;https://github.com/czottmann/linearis&#34;&gt;Linearis v2025.11.2&lt;/a&gt;, a new version of my CLI tool&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; that lets you (and your LLM) work with the very good project management and ticketing system, Linear&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;. The headliner features for this update are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;support for cycles&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;support for project milestones&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;issues now specify their sub-issues and parents&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Shout-out to &lt;a href=&#34;https://github.com/ryanrozich&#34;&gt;@ryanrozich&lt;/a&gt; for the patch that added both cycles and project milestones. 🤘🏼&lt;/p&gt;
&lt;p&gt;Also, I&amp;rsquo;m happy to announce that the tool is now &lt;a href=&#34;https://www.npmjs.com/package/linearis&#34;&gt;a standard npm package&lt;/a&gt;, meaning that it&amp;rsquo;s installable with a simple &lt;code&gt;npm install -g linearis&lt;/code&gt; call. (Up until now, you could only install it directly from the GitHub repo, but that brought some issues with updating.)&lt;/p&gt;
&lt;p&gt;And ICYMI: the previous update, &lt;strong&gt;v2025.11.1, added support for downloading screenshots and documents&lt;/strong&gt; that are embedded in a ticket description or a comment. So now your agent of choice gets to look everything! For example, to read one of my test tickets, it&amp;rsquo;d do this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;❯ linearis issues read ZCO-1569
&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;de732438-8ae2-4f9e-95a9-85a614b04816&amp;#34;&lt;/span&gt;,
  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;identifier&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ZCO-1569&amp;#34;&lt;/span&gt;,
  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;File embed testing grounds&amp;#34;&lt;/span&gt;,
  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;The Earth was small, light blue, and so touchingly alone, our home that must be defended like a holy relic. The Earth was absolutely round. I believe I never knew what the word round meant until I saw Earth from space.\n\nThe dreams of yesterday are the hopes of today and the reality of tomorrow.\n\n![Confident Man and Futuristic Car.png](https://uploads.linear.app/7df2165d-5920-4338-950f-f2b7152a3c02/8a8adc83-0609-4bb7-9c2d-6450bd2e20a5/db4145e5-6499-45cd-b35c-9aa621bfde51?signature=&amp;lt;signature_omitted&amp;gt;)\n\nIt suddenly struck me that that tiny pea, pretty and blue, was the Earth. I put up my thumb and shut one eye, and my thumb blotted out the planet Earth. I didn&amp;#39;t feel like a giant. I felt very, very small.\n\n![i-swear-to-god-connor.gif](https://uploads.linear.app/7df2165d-5920-4338-950f-f2b7152a3c02/571bf0bf-3586-4f92-9427-a88c13d3c7e4/00d4a028-2053-452c-8da4-a55930943868?signature=&amp;lt;signature_omitted&amp;gt;)&amp;#34;&lt;/span&gt;,
  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;embeds&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;
    &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;label&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Confident Man and Futuristic Car.png&amp;#34;&lt;/span&gt;,
      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://uploads.linear.app/7df2165d-5920-4338-950f-f2b7152a3c02/8a8adc83-0609-4bb7-9c2d-6450bd2e20a5/db4145e5-6499-45cd-b35c-9aa621bfde51?signature=&amp;lt;signature_omitted&amp;gt;&amp;#34;&lt;/span&gt;,
      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;expiresAt&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2025-11-12T14:19:59.963Z&amp;#34;&lt;/span&gt;
    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;,
    &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;label&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;i-swear-to-god-connor.gif&amp;#34;&lt;/span&gt;,
      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://uploads.linear.app/7df2165d-5920-4338-950f-f2b7152a3c02/571bf0bf-3586-4f92-9427-a88c13d3c7e4/00d4a028-2053-452c-8da4-a55930943868?signature=&amp;lt;signature_omitted&amp;gt;&amp;#34;&lt;/span&gt;,
      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;expiresAt&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2025-11-12T14:19:59.963Z&amp;#34;&lt;/span&gt;
    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
  &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;,
  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;state&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;0d744059-bc97-4dc2-82d0-5bac53673c26&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Done&amp;#34;&lt;/span&gt;
  &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;,
  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;assignee&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;cef0517b-cd50-48d9-80d6-8ad34007458a&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Carlo Zottmann&amp;#34;&lt;/span&gt;
  &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;,
  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;team&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;413e044c-d008-4bcb-b48d-1ef45ada89f4&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;key&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ZCO&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ZCo&amp;#34;&lt;/span&gt;
  &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;,
  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;project&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;904984cc-eb35-4e4d-9caf-aa21f9f7daa7&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Linearis&amp;#34;&lt;/span&gt;
  &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;,
  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;cycle&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;bbde6b5b-c5fe-4319-9bbc-9081746e6660&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: null,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;number&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;110&lt;/span&gt;
  &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;,
  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;projectMilestone&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;38cb29af-af9e-493c-b935-205b31396a4b&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2025.11.1&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;targetDate&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2025-11-06&amp;#34;&lt;/span&gt;
  &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;,
  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;priority&amp;#34;&lt;/span&gt;: 0,
  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;labels&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[]&lt;/span&gt;,
  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;parentIssue&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;d2d0ad4d-8ad6-4e6d-8ab0-cb9b748d21e8&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;identifier&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ZCO-1441&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Implement Linear API File Download Capabilities&amp;#34;&lt;/span&gt;
  &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;,
  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;subIssues&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[]&lt;/span&gt;,
  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;comments&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[]&lt;/span&gt;,
  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;createdAt&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2025-11-06T16:09:46.447Z&amp;#34;&lt;/span&gt;,
  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;updatedAt&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2025-11-09T18:45:35.964Z&amp;#34;&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What&amp;rsquo;s great about that is that e.g. Claude is clever enough to understand that result without any further explanations. For me, that means that I had to teach Claude four things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;My ticket IDs sport the prefix &amp;ldquo;ZCO-&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;linearis&lt;/code&gt; to work with tickets.&lt;/li&gt;
&lt;li&gt;Before doing that, run &lt;code&gt;linearis usage&lt;/code&gt; once to learn how to use it.&lt;/li&gt;
&lt;li&gt;If you come across embeds, fetch and read them as well.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And that&amp;rsquo;s it. The output is structured enough, and Claude knows how to extract what it needs and how to look up anything else related to that ticket using &lt;code&gt;linearis&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;No MCP server eating 16k tokens at rest, just a CLI tool. (I recommend that approach in general.)&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://zottmann.org/2025/09/03/linearis-my-linear-cli-built.html&#34;&gt;Earlier announcement blog post here.&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://linear.app/&#34;&gt;Linear – Plan and build products&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://linear.app/docs/use-cycles&#34;&gt;Cycles – Linear Docs&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://linear.app/docs/project-milestones&#34;&gt;Project milestones – Linear Docs&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
      <source:markdown>Yesterday, I released [Linearis v2025.11.2](https://github.com/czottmann/linearis), a new version of my CLI tool[^announcement] that lets you (and your LLM) work with the very good project management and ticketing system, Linear[^linear]. The headliner features for this update are:

- support for cycles[^cycles]
- support for project milestones[^milestones]
- issues now specify their sub-issues and parents

[^linear]: [Linear – Plan and build products](https://linear.app/)
[^announcement]: [Earlier announcement blog post here.](/2025/09/03/linearis-my-linear-cli-built.html)
[^cycles]: [Cycles – Linear Docs](https://linear.app/docs/use-cycles)
[^milestones]: [Project milestones – Linear Docs](https://linear.app/docs/project-milestones)

Shout-out to [@ryanrozich](https://github.com/ryanrozich) for the patch that added both cycles and project milestones. 🤘🏼

Also, I&#39;m happy to announce that the tool is now [a standard npm package](https://www.npmjs.com/package/linearis), meaning that it&#39;s installable with a simple `npm install -g linearis` call. (Up until now, you could only install it directly from the GitHub repo, but that brought some issues with updating.)

And ICYMI: the previous update, **v2025.11.1, added support for downloading screenshots and documents** that are embedded in a ticket description or a comment. So now your agent of choice gets to look everything! For example, to read one of my test tickets, it&#39;d do this:

```bash
❯ linearis issues read ZCO-1569
{
  &#34;id&#34;: &#34;de732438-8ae2-4f9e-95a9-85a614b04816&#34;,
  &#34;identifier&#34;: &#34;ZCO-1569&#34;,
  &#34;title&#34;: &#34;File embed testing grounds&#34;,
  &#34;description&#34;: &#34;The Earth was small, light blue, and so touchingly alone, our home that must be defended like a holy relic. The Earth was absolutely round. I believe I never knew what the word round meant until I saw Earth from space.\n\nThe dreams of yesterday are the hopes of today and the reality of tomorrow.\n\n![Confident Man and Futuristic Car.png](https://uploads.linear.app/7df2165d-5920-4338-950f-f2b7152a3c02/8a8adc83-0609-4bb7-9c2d-6450bd2e20a5/db4145e5-6499-45cd-b35c-9aa621bfde51?signature=&lt;signature_omitted&gt;)\n\nIt suddenly struck me that that tiny pea, pretty and blue, was the Earth. I put up my thumb and shut one eye, and my thumb blotted out the planet Earth. I didn&#39;t feel like a giant. I felt very, very small.\n\n![i-swear-to-god-connor.gif](https://uploads.linear.app/7df2165d-5920-4338-950f-f2b7152a3c02/571bf0bf-3586-4f92-9427-a88c13d3c7e4/00d4a028-2053-452c-8da4-a55930943868?signature=&lt;signature_omitted&gt;)&#34;,
  &#34;embeds&#34;: [
    {
      &#34;label&#34;: &#34;Confident Man and Futuristic Car.png&#34;,
      &#34;url&#34;: &#34;https://uploads.linear.app/7df2165d-5920-4338-950f-f2b7152a3c02/8a8adc83-0609-4bb7-9c2d-6450bd2e20a5/db4145e5-6499-45cd-b35c-9aa621bfde51?signature=&lt;signature_omitted&gt;&#34;,
      &#34;expiresAt&#34;: &#34;2025-11-12T14:19:59.963Z&#34;
    },
    {
      &#34;label&#34;: &#34;i-swear-to-god-connor.gif&#34;,
      &#34;url&#34;: &#34;https://uploads.linear.app/7df2165d-5920-4338-950f-f2b7152a3c02/571bf0bf-3586-4f92-9427-a88c13d3c7e4/00d4a028-2053-452c-8da4-a55930943868?signature=&lt;signature_omitted&gt;&#34;,
      &#34;expiresAt&#34;: &#34;2025-11-12T14:19:59.963Z&#34;
    }
  ],
  &#34;state&#34;: {
    &#34;id&#34;: &#34;0d744059-bc97-4dc2-82d0-5bac53673c26&#34;,
    &#34;name&#34;: &#34;Done&#34;
  },
  &#34;assignee&#34;: {
    &#34;id&#34;: &#34;cef0517b-cd50-48d9-80d6-8ad34007458a&#34;,
    &#34;name&#34;: &#34;Carlo Zottmann&#34;
  },
  &#34;team&#34;: {
    &#34;id&#34;: &#34;413e044c-d008-4bcb-b48d-1ef45ada89f4&#34;,
    &#34;key&#34;: &#34;ZCO&#34;,
    &#34;name&#34;: &#34;ZCo&#34;
  },
  &#34;project&#34;: {
    &#34;id&#34;: &#34;904984cc-eb35-4e4d-9caf-aa21f9f7daa7&#34;,
    &#34;name&#34;: &#34;Linearis&#34;
  },
  &#34;cycle&#34;: {
    &#34;id&#34;: &#34;bbde6b5b-c5fe-4319-9bbc-9081746e6660&#34;,
    &#34;name&#34;: null,
    &#34;number&#34;: 110
  },
  &#34;projectMilestone&#34;: {
    &#34;id&#34;: &#34;38cb29af-af9e-493c-b935-205b31396a4b&#34;,
    &#34;name&#34;: &#34;2025.11.1&#34;,
    &#34;targetDate&#34;: &#34;2025-11-06&#34;
  },
  &#34;priority&#34;: 0,
  &#34;labels&#34;: [],
  &#34;parentIssue&#34;: {
    &#34;id&#34;: &#34;d2d0ad4d-8ad6-4e6d-8ab0-cb9b748d21e8&#34;,
    &#34;identifier&#34;: &#34;ZCO-1441&#34;,
    &#34;title&#34;: &#34;Implement Linear API File Download Capabilities&#34;
  },
  &#34;subIssues&#34;: [],
  &#34;comments&#34;: [],
  &#34;createdAt&#34;: &#34;2025-11-06T16:09:46.447Z&#34;,
  &#34;updatedAt&#34;: &#34;2025-11-09T18:45:35.964Z&#34;
}
```

What&#39;s great about that is that e.g. Claude is clever enough to understand that result without any further explanations. For me, that means that I had to teach Claude four things:

1. My ticket IDs sport the prefix &#34;ZCO-&#34;.
2. Use `linearis` to work with tickets.
3. Before doing that, run `linearis usage` once to learn how to use it.
4. If you come across embeds, fetch and read them as well.

And that&#39;s it. The output is structured enough, and Claude knows how to extract what it needs and how to look up anything else related to that ticket using `linearis`!

No MCP server eating 16k tokens at rest, just a CLI tool. (I recommend that approach in general.)

</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://zottmann.org/2025/11/07/hn-user-yanhangyhy-on-a.html</link>
      <pubDate>Fri, 07 Nov 2025 13:19:26 +0100</pubDate>
      
      <guid>http://czottmann.micro.blog/2025/11/07/hn-user-yanhangyhy-on-a.html</guid>
      <description>&lt;p&gt;Quoting &lt;a href=&#34;https://news.ycombinator.com/user?id=yanhangyhy&#34;&gt;HN user yanhangyhy&lt;/a&gt;&amp;rsquo;s &lt;a href=&#34;https://news.ycombinator.com/item?id=45843056&#34;&gt;comment about Kimi K2 Thinking&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[…] China&amp;rsquo;s open-source strategy has many significant effects—not only because it aligns with the spirit of open source. For domestic Chinese companies, it also prevents startups from making reckless investments to develop mediocre models. Instead, everyone is pushed to start from a relatively high baseline. Of course, many small companies in the U.S., Japan, and Europe are also building on Qwen. Kimi is similar: before DeepSeek and others emerged, their model quality was pretty bad. Once the open-source strategy was set, these companies had no choice but to adjust their product lines and development approaches to improve their models.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Moreover, the ultimate competition between models will eventually become a competition over energy.&lt;/strong&gt; China’s open-source models have major advantages in energy consumption, and China itself has a huge advantage in energy resources. They may not necessarily outperform the U.S., but they probably won’t fall too far behind either.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;(Emphasis mine.)&lt;/p&gt;
</description>
      <source:markdown>Quoting [HN user yanhangyhy](https://news.ycombinator.com/user?id=yanhangyhy)&#39;s [comment about Kimi K2 Thinking](https://news.ycombinator.com/item?id=45843056):

&gt; […] China&#39;s open-source strategy has many significant effects—not only because it aligns with the spirit of open source. For domestic Chinese companies, it also prevents startups from making reckless investments to develop mediocre models. Instead, everyone is pushed to start from a relatively high baseline. Of course, many small companies in the U.S., Japan, and Europe are also building on Qwen. Kimi is similar: before DeepSeek and others emerged, their model quality was pretty bad. Once the open-source strategy was set, these companies had no choice but to adjust their product lines and development approaches to improve their models.
&gt;
&gt; **Moreover, the ultimate competition between models will eventually become a competition over energy.** China’s open-source models have major advantages in energy consumption, and China itself has a huge advantage in energy resources. They may not necessarily outperform the U.S., but they probably won’t fall too far behind either.

(Emphasis mine.)
</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://zottmann.org/2025/11/05/wild-wild-space-hbo-original.html</link>
      <pubDate>Wed, 05 Nov 2025 18:15:00 +0100</pubDate>
      
      <guid>http://czottmann.micro.blog/2025/11/05/wild-wild-space-hbo-original.html</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=Q50dAiKB4lI&#34;&gt;Wild Wild Space&lt;/a&gt;: &lt;em&gt;&amp;ldquo;HBO Original Documentary that chronicles the fierce competition to tackle humanity’s next great frontier and the dark side of capitalism’s insatiable appetite for profit&amp;rdquo;&lt;/em&gt;&lt;/p&gt;

&lt;style&gt;
:root {
   
  --yt-aspect-ratio-16-9: 56.25%;

   
  --yt-bg-black: #000;
  --yt-play-button-bg: rgba(255, 0, 0, 0.8);
  --yt-play-button-bg-hover: rgba(255, 0, 0, 1);
  --yt-play-button-icon: #fff;
  --yt-overlay-bg: rgba(0, 0, 0, 0.85);
  --yt-overlay-text: #fff;
  --yt-focus-outline: #e53935;

   
  --yt-play-button-width: 68px;
  --yt-play-button-height: 48px;
  --yt-play-button-border-radius: 12px;

   
  --yt-focus-outline-width: 3px;
  --yt-focus-outline-offset: 4px;

   
  --yt-transition-duration: 0.2s;
  --yt-transition-timing: ease-in-out;
}

.video-wrapper {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  padding-bottom: var(--yt-aspect-ratio-16-9);
  margin: 0;
  height: 0;
  max-width: 100%;
  overflow: hidden;
  background-color: var(--yt-bg-black);
  cursor: pointer;
  outline: none;
  border: none;
  color: inherit;
  font: inherit;
  text-align: inherit;
  appearance: none;
  -webkit-appearance: none;
}

.video-wrapper[data-is-loaded=&#34;true&#34;] {
  cursor: auto;
}

.video-wrapper:focus-visible {
  outline: var(--yt-focus-outline-width) solid var(--yt-focus-outline);
  outline-offset: var(--yt-focus-outline-offset);
}

.video-thumbnail {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  margin: auto;
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  object-position: center;
  background-color: var(--yt-bg-black);
  z-index: 1;
  transition: opacity var(--yt-transition-duration) var(--yt-transition-timing);
}

.video-wrapper:hover .video-thumbnail {
  opacity: 0.9;
}

.video-overlay {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  background: var(--yt-overlay-bg);
  color: var(--yt-overlay-text);
  text-align: center;
  font-size: 0.85em;
  padding: 0.5em 1em;
  z-index: 2;
  pointer-events: auto;
}

.video-play-button {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: var(--yt-play-button-width);
  height: var(--yt-play-button-height);
  background-color: var(--yt-play-button-bg);
  border-radius: var(--yt-play-button-border-radius);
  z-index: 3;
  pointer-events: none;
  transition: all var(--yt-transition-duration) var(--yt-transition-timing);
}

.video-wrapper:hover .video-play-button {
  background-color: var(--yt-play-button-bg-hover);
  transform: translate(-50%, -50%) scale(1.1);
}

.video-wrapper:active .video-play-button {
  transform: translate(-50%, -50%) scale(1.05);
}

.video-play-button::before {
  content: &#39;&#39;;
  position: absolute;
  left: 26px;
  top: 14px;
  width: 0;
  height: 0;
  border-left: 18px solid var(--yt-play-button-icon);
  border-top: 12px solid transparent;
  border-bottom: 12px solid transparent;
}

.video-wrapper iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border: none;
  z-index: 4;
}

.video-noscript {
  display: block;
  max-width: 100%;
  background-color: var(--yt-bg-black);
  color: inherit;
  text-align: center;
  padding: 0;
  margin-top: 0.5em;
}

.video-noscript img {
  display: block;
  width: 100%;
  height: auto;
}

.video-noscript a {
  display: inline-block;
  padding: 0.75em 1em;
  color: inherit;
  text-decoration: underline;
}

.yt-text-link {
  display: none;
}
&lt;/style&gt;

&lt;script&gt;
(function(){
  &#39;use strict&#39;;

  
  const CONSTANTS = {
    VIDEO_ID_LENGTH: 11,
    MAX_INPUT_LENGTH: 2048,
    VIDEO_ID_PATTERN: /^[a-zA-Z0-9_-]{11}$/,
    PLAYLIST_PREFIXES: /^(PL|OL|UU|LL|FL)/i,
    ALLOWED_URL_CHARS: /^[a-zA-Z0-9_\-?=&amp;#:/.]+$/,
    TIME_FORMATS: {
      HOURS: 3600,
      MINUTES: 60,
      SECONDS: 1
    },
    YOUTUBE_NOCOOKIE_DOMAIN: &#39;https://www.youtube-nocookie.com&#39;,
    YOUTUBE_IMG_DOMAIN: &#39;https://img.youtube.com&#39;,
    EMBED_PARAMS: &#39;autoplay=1&amp;mute=1&#39;
  };

  

  function validateInput(input, maxLength = CONSTANTS.MAX_INPUT_LENGTH) {
    if (!input || typeof input !== &#39;string&#39;) return &#39;&#39;;

    const trimmed = input.trim();

    if (trimmed.length &gt; maxLength) {
      console.warn(`Input exceeds maximum length of ${maxLength}`);
      return &#39;&#39;;
    }

    
    if (!CONSTANTS.ALLOWED_URL_CHARS.test(trimmed)) {
      console.warn(&#39;Input contains invalid characters&#39;);
      return &#39;&#39;;
    }

    return trimmed;
  }

  

  function parseStartValue(value) {
    if (!value) return 0;

    
    if (/^\d+$/.test(value)) {
      const parsed = parseInt(value, 10);
      return isNaN(parsed) ? 0 : Math.max(0, parsed);
    }

    
    let total = 0;
    let matched = false;
    const regex = /(\d+)(h|m|s)/gi;
    let match;

    while ((match = regex.exec(value)) !== null) {
      matched = true;
      const num = parseInt(match[1], 10);
      if (isNaN(num)) continue;

      const unit = match[2].toLowerCase();
      if (unit === &#39;h&#39;) total += num * CONSTANTS.TIME_FORMATS.HOURS;
      else if (unit === &#39;m&#39;) total += num * CONSTANTS.TIME_FORMATS.MINUTES;
      else if (unit === &#39;s&#39;) total += num * CONSTANTS.TIME_FORMATS.SECONDS;
    }

    return matched ? Math.max(0, total) : 0;
  }

  

  function extractStartTime(queryString) {
    if (!queryString) return 0;

    try {
      const cleanQuery = queryString.startsWith(&#39;?&#39;) || queryString.startsWith(&#39;#&#39;)
        ? queryString.slice(1)
        : queryString;

      const params = new URLSearchParams(cleanQuery);

      
      return parseStartValue(params.get(&#39;start&#39;)) ||
             parseStartValue(params.get(&#39;t&#39;)) ||
             parseStartValue(params.get(&#39;time_continue&#39;)) ||
             0;
    } catch (e) {
      console.warn(&#39;Failed to parse query parameters:&#39;, e);
      return 0;
    }
  }

  

  function parseId(raw) {
    const validated = validateInput(raw);
    if (!validated) {
      return { type: &#39;unknown&#39;, id: &#39;&#39;, start: 0 };
    }

    let startSeconds = 0;
    let normalized = validated;

    
    const queryIndex = normalized.indexOf(&#39;?&#39;);
    if (queryIndex !== -1) {
      startSeconds = extractStartTime(normalized.slice(queryIndex + 1));
      normalized = normalized.slice(0, queryIndex);
    }

    
    const hashIndex = normalized.indexOf(&#39;#&#39;);
    if (hashIndex !== -1) {
      startSeconds = startSeconds || extractStartTime(normalized.slice(hashIndex + 1));
      normalized = normalized.slice(0, hashIndex);
    }

    
    if (CONSTANTS.PLAYLIST_PREFIXES.test(normalized)) {
      return { type: &#39;playlist&#39;, id: normalized, start: startSeconds };
    }

    
    if (CONSTANTS.VIDEO_ID_PATTERN.test(normalized)) {
      return { type: &#39;video&#39;, id: normalized, start: startSeconds };
    }

    
    const listMatch = normalized.match(/list=([^&amp;]+)/);
    if (listMatch &amp;&amp; listMatch[1]) {
      return { type: &#39;playlist&#39;, id: listMatch[1], start: startSeconds };
    }

    console.warn(&#39;Unable to parse video/playlist ID:&#39;, raw);
    return { type: &#39;unknown&#39;, id: &#39;&#39;, start: startSeconds };
  }

  

  function validateThumbnailUrl(thumbUrl) {
    if (!thumbUrl) return &#39;&#39;;

    let cleaned = thumbUrl.trim();

    
    const markdownMatch = cleaned.match(/^\[[^\]]*\]\(([^)]+)\)$/);
    if (markdownMatch) {
      cleaned = markdownMatch[1].trim();
    }

    
    try {
      const url = new URL(cleaned, document.baseURI);

      
      if (url.protocol !== &#39;http:&#39; &amp;&amp; url.protocol !== &#39;https:&#39;) {
        console.warn(&#39;Thumbnail URL must use http or https protocol&#39;);
        return &#39;&#39;;
      }

      return url.href;
    } catch (e) {
      console.warn(&#39;Invalid thumbnail URL:&#39;, e);
      return &#39;&#39;;
    }
  }

  

  function getPlaylistPlaceholder() {
    const svg = `&lt;svg xmlns=&#39;http://www.w3.org/2000/svg&#39; viewBox=&#39;0 0 1280 720&#39;&gt;` +
                `&lt;rect width=&#39;100%&#39; height=&#39;100%&#39; fill=&#39;#000&#39;/&gt;` +
                `&lt;rect x=&#39;220&#39; y=&#39;260&#39; width=&#39;840&#39; height=&#39;60&#39; fill=&#39;#fff&#39;/&gt;` +
                `&lt;rect x=&#39;220&#39; y=&#39;340&#39; width=&#39;660&#39; height=&#39;60&#39; fill=&#39;#fff&#39;/&gt;` +
                `&lt;/svg&gt;`;
    return &#39;data:image/svg+xml;charset=utf-8,&#39; + encodeURIComponent(svg);
  }

  /**
   * Sets up thumbnail for video wrapper
   * @param {HTMLImageElement} thumbnail - Thumbnail element
   * @param {Object} kind - Parsed video/playlist info
   * @param {string} customThumb - Custom thumbnail URL
   */
  function setupThumbnail(thumbnail, kind, customThumb) {
    if (!thumbnail) return;

    if (customThumb) {
      // Use custom thumbnail
      thumbnail.onerror = null;
      thumbnail.src = customThumb;
    } else if (kind.type === &#39;playlist&#39;) {
      // Use playlist placeholder
      thumbnail.src = getPlaylistPlaceholder();
    } else if (kind.type === &#39;video&#39; &amp;&amp; kind.id) {
      // Use YouTube thumbnail with fallback
      thumbnail.src = `${CONSTANTS.YOUTUBE_IMG_DOMAIN}/vi/${kind.id}/maxresdefault.jpg`;
      thumbnail.onerror = () =&gt; {
        thumbnail.onerror = null;
        thumbnail.src = `${CONSTANTS.YOUTUBE_IMG_DOMAIN}/vi/${kind.id}/0.jpg`;
      };
    }
    // For unknown type, keep the default placeholder
  }

  /**
   * Creates embed URL for video or playlist
   * @param {Object} kind - Parsed video/playlist info
   * @returns {string} Embed URL or empty string if invalid
   */
  function createEmbedUrl(kind) {
    if (kind.type === &#39;playlist&#39; &amp;&amp; kind.id) {
      return `${CONSTANTS.YOUTUBE_NOCOOKIE_DOMAIN}/embed/videoseries?list=${encodeURIComponent(kind.id)}&amp;${CONSTANTS.EMBED_PARAMS}`;
    } else if (kind.type === &#39;video&#39; &amp;&amp; kind.id) {
      let url = `${CONSTANTS.YOUTUBE_NOCOOKIE_DOMAIN}/embed/${encodeURIComponent(kind.id)}?${CONSTANTS.EMBED_PARAMS}`;
      if (kind.start &gt; 0) {
        url += `&amp;start=${Math.floor(kind.start)}`;
      }
      return url;
    }
    return &#39;&#39;;
  }

  /**
   * Creates and loads iframe embed
   * @param {HTMLElement} wrapper - Video wrapper element
   * @param {Object} kind - Parsed video/playlist info
   * @param {string} title - Video title
   */
  function loadEmbed(wrapper, kind, title) {
    if (wrapper.dataset.isLoaded === &#39;true&#39;) return;

    const embedUrl = createEmbedUrl(kind);
    if (!embedUrl) {
      console.error(&#39;Unable to create embed URL - invalid video/playlist ID&#39;);
      // Show error message to user
      wrapper.innerHTML = &#39;&lt;div style=&#34;padding: 2em; text-align: center; color: #fff;&#34;&gt;Unable to load video. Please check the video ID.&lt;/div&gt;&#39;;
      return;
    }

    // Create iframe
    const iframe = document.createElement(&#39;iframe&#39;);
    iframe.setAttribute(&#39;allowfullscreen&#39;, &#39;&#39;);
    iframe.setAttribute(&#39;loading&#39;, &#39;lazy&#39;);
    iframe.setAttribute(&#39;allow&#39;, &#39;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#39;);
    iframe.setAttribute(&#39;title&#39;, title ? `YouTube video player: ${title}` : &#39;YouTube video player&#39;);
    iframe.src = embedUrl;

    
    const replacement = document.createElement(&#39;div&#39;);
    replacement.className = wrapper.className;
    replacement.dataset.listenersAdded = &#39;true&#39;;
    replacement.dataset.isLoaded = &#39;true&#39;;
    replacement.appendChild(iframe);

    wrapper.replaceWith(replacement);
  }

  

  function enhanceEmbeds() {
    const wrappers = document.querySelectorAll(&#39;.video-wrapper&#39;);

    wrappers.forEach(wrapper =&gt; {
      
      if (wrapper.dataset.listenersAdded === &#39;true&#39;) return;
      wrapper.dataset.listenersAdded = &#39;true&#39;;

      
      const rawVideoId = wrapper.dataset.videoId || &#39;&#39;;
      const rawThumbUrl = wrapper.dataset.thumb || &#39;&#39;;
      const videoTitle = wrapper.dataset.videoTitle || &#39;&#39;;

      
      const kind = parseId(rawVideoId);
      const safeThumb = validateThumbnailUrl(rawThumbUrl);

      
      const thumbnail = wrapper.querySelector(&#39;.video-thumbnail&#39;);
      setupThumbnail(thumbnail, kind, safeThumb);

      
      const loadHandler = () =&gt; loadEmbed(wrapper, kind, videoTitle);

      wrapper.addEventListener(&#39;click&#39;, loadHandler);

      const overlay = wrapper.querySelector(&#39;.video-overlay&#39;);
      if (overlay) overlay.addEventListener(&#39;click&#39;, loadHandler);
      if (thumbnail) thumbnail.addEventListener(&#39;click&#39;, loadHandler);

      
      wrapper.addEventListener(&#39;keydown&#39;, (e) =&gt; {
        if (e.key === &#39;Enter&#39; || e.key === &#39; &#39;) {
          e.preventDefault();
          loadHandler();
        }
      });
    });
  }

  
  enhanceEmbeds();
  if (document.readyState === &#39;loading&#39;) {
    document.addEventListener(&#39;DOMContentLoaded&#39;, enhanceEmbeds);
  }
})();
&lt;/script&gt;&lt;p class=&#34;yt-text-link&#34;&gt;
      &lt;a href=&#34;https://www.youtube.com/watch?v=Q50dAiKB4lI&#34;&gt;YouTube Video&lt;/a&gt;
    &lt;/p&gt;&lt;button type=&#34;button&#34;
    class=&#34;video-wrapper&#34;
    aria-label=&#34;Play YouTube video&#34;
    data-video-id=&#34;Q50dAiKB4lI&#34;
    data-thumb=&#34;https://i.ytimg.com/vi_webp/Q50dAiKB4lI/sddefault.webp&#34;
    &gt;&lt;img
      class=&#34;video-thumbnail&#34;
      src=&#34;data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20viewBox=%270%200%201280%20720%27%3E%3Crect%20width=%27100%25%25%27%20height=%27100%25%25%27%20fill=%27%23000%27/%3E%3C/svg%3E&#34;
      alt=&#34;YouTube Thumbnail&#34;
      loading=&#34;lazy&#34;
      decoding=&#34;async&#34;&gt;&lt;div class=&#34;video-play-button&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;&lt;noscript&gt;
    &lt;div class=&#34;video-noscript&#34;&gt;&lt;img src=&#34;https://i.ytimg.com/vi_webp/Q50dAiKB4lI/sddefault.webp&#34;
             alt=&#34;YouTube Thumbnail&#34;&gt;&lt;p&gt;
          &lt;a href=&#34;https://www.youtube.com/watch?v=Q50dAiKB4lI&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;YouTube Video&lt;/a&gt;
        &lt;/p&gt;&lt;/div&gt;
  &lt;/noscript&gt;
&lt;p&gt;A cool documentary to watch if you&amp;rsquo;re interested in the current commercial space race (like I am), showing some key players, and telling the story how it came to be. Based on Ashlee Vance&amp;rsquo;s book &lt;a href=&#34;https://www.harpercollins.com/products/when-the-heavens-went-on-sale-ashlee-vance?variant=41111416995874&#34;&gt;&amp;ldquo;When the Heavens Went on Sale&amp;rdquo;&lt;/a&gt; which I&amp;rsquo;ve yet to read.&lt;/p&gt;
</description>
      <source:markdown>[Wild Wild Space](https://www.youtube.com/watch?v=Q50dAiKB4lI): _&#34;HBO Original Documentary that chronicles the fierce competition to tackle humanity’s next great frontier and the dark side of capitalism’s insatiable appetite for profit&#34;_

{{&lt; yt &#34;Q50dAiKB4lI&#34; &#34;[i.ytimg.com/vi_webp/Q...](https://i.ytimg.com/vi_webp/Q50dAiKB4lI/sddefault.webp)&#34; &gt;}}

A cool documentary to watch if you&#39;re interested in the current commercial space race (like I am), showing some key players, and telling the story how it came to be. Based on Ashlee Vance&#39;s book [&#34;When the Heavens Went on Sale&#34;](https://www.harpercollins.com/products/when-the-heavens-went-on-sale-ashlee-vance?variant=41111416995874) which I&#39;ve yet to read.
</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://zottmann.org/2025/11/05/bbc-radio-live-bugzy-malones.html</link>
      <pubDate>Wed, 05 Nov 2025 18:04:12 +0100</pubDate>
      
      <guid>http://czottmann.micro.blog/2025/11/05/bbc-radio-live-bugzy-malones.html</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://www.bbc.co.uk/programmes/p0df1893&#34;&gt;BBC Radio 5 Live - Bugzy Malone’s Grandest Game&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A loving look at the GTA series by BBC&amp;rsquo;s Chris Warburton and UK rapper Bugzy Malone. &lt;em&gt;&amp;ldquo;It&amp;rsquo;s the game that shocked and thrilled the world: Grand Theft Auto. Its rise to domination is an incredible story.&amp;quot;&lt;/em&gt; They look at how GTA came to be, how it grew, its controversies, and what it meant to different people. They talked with ex-Rockstar devs, modders, games journalists, players. Seven episodes, nicely produced, ace little treats right before bed time.&lt;/p&gt;
</description>
      <source:markdown>[BBC Radio 5 Live - Bugzy Malone’s Grandest Game](https://www.bbc.co.uk/programmes/p0df1893)

A loving look at the GTA series by BBC&#39;s Chris Warburton and UK rapper Bugzy Malone. _&#34;It&#39;s the game that shocked and thrilled the world: Grand Theft Auto. Its rise to domination is an incredible story.&#34;_ They look at how GTA came to be, how it grew, its controversies, and what it meant to different people. They talked with ex-Rockstar devs, modders, games journalists, players. Seven episodes, nicely produced, ace little treats right before bed time.
</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://zottmann.org/2025/11/03/peter-leyden-why-is-the.html</link>
      <pubDate>Mon, 03 Nov 2025 00:22:24 +0100</pubDate>
      
      <guid>http://czottmann.micro.blog/2025/11/03/peter-leyden-why-is-the.html</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=w5k72A30kUc&#34;&gt;Peter Leyden: Why 2025 is the single most pivotal year in our lifetime&lt;/a&gt;&lt;/p&gt;

&lt;style&gt;
:root {
   
  --yt-aspect-ratio-16-9: 56.25%;

   
  --yt-bg-black: #000;
  --yt-play-button-bg: rgba(255, 0, 0, 0.8);
  --yt-play-button-bg-hover: rgba(255, 0, 0, 1);
  --yt-play-button-icon: #fff;
  --yt-overlay-bg: rgba(0, 0, 0, 0.85);
  --yt-overlay-text: #fff;
  --yt-focus-outline: #e53935;

   
  --yt-play-button-width: 68px;
  --yt-play-button-height: 48px;
  --yt-play-button-border-radius: 12px;

   
  --yt-focus-outline-width: 3px;
  --yt-focus-outline-offset: 4px;

   
  --yt-transition-duration: 0.2s;
  --yt-transition-timing: ease-in-out;
}

.video-wrapper {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  padding-bottom: var(--yt-aspect-ratio-16-9);
  margin: 0;
  height: 0;
  max-width: 100%;
  overflow: hidden;
  background-color: var(--yt-bg-black);
  cursor: pointer;
  outline: none;
  border: none;
  color: inherit;
  font: inherit;
  text-align: inherit;
  appearance: none;
  -webkit-appearance: none;
}

.video-wrapper[data-is-loaded=&#34;true&#34;] {
  cursor: auto;
}

.video-wrapper:focus-visible {
  outline: var(--yt-focus-outline-width) solid var(--yt-focus-outline);
  outline-offset: var(--yt-focus-outline-offset);
}

.video-thumbnail {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  margin: auto;
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  object-position: center;
  background-color: var(--yt-bg-black);
  z-index: 1;
  transition: opacity var(--yt-transition-duration) var(--yt-transition-timing);
}

.video-wrapper:hover .video-thumbnail {
  opacity: 0.9;
}

.video-overlay {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  background: var(--yt-overlay-bg);
  color: var(--yt-overlay-text);
  text-align: center;
  font-size: 0.85em;
  padding: 0.5em 1em;
  z-index: 2;
  pointer-events: auto;
}

.video-play-button {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: var(--yt-play-button-width);
  height: var(--yt-play-button-height);
  background-color: var(--yt-play-button-bg);
  border-radius: var(--yt-play-button-border-radius);
  z-index: 3;
  pointer-events: none;
  transition: all var(--yt-transition-duration) var(--yt-transition-timing);
}

.video-wrapper:hover .video-play-button {
  background-color: var(--yt-play-button-bg-hover);
  transform: translate(-50%, -50%) scale(1.1);
}

.video-wrapper:active .video-play-button {
  transform: translate(-50%, -50%) scale(1.05);
}

.video-play-button::before {
  content: &#39;&#39;;
  position: absolute;
  left: 26px;
  top: 14px;
  width: 0;
  height: 0;
  border-left: 18px solid var(--yt-play-button-icon);
  border-top: 12px solid transparent;
  border-bottom: 12px solid transparent;
}

.video-wrapper iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border: none;
  z-index: 4;
}

.video-noscript {
  display: block;
  max-width: 100%;
  background-color: var(--yt-bg-black);
  color: inherit;
  text-align: center;
  padding: 0;
  margin-top: 0.5em;
}

.video-noscript img {
  display: block;
  width: 100%;
  height: auto;
}

.video-noscript a {
  display: inline-block;
  padding: 0.75em 1em;
  color: inherit;
  text-decoration: underline;
}

.yt-text-link {
  display: none;
}
&lt;/style&gt;

&lt;script&gt;
(function(){
  &#39;use strict&#39;;

  
  const CONSTANTS = {
    VIDEO_ID_LENGTH: 11,
    MAX_INPUT_LENGTH: 2048,
    VIDEO_ID_PATTERN: /^[a-zA-Z0-9_-]{11}$/,
    PLAYLIST_PREFIXES: /^(PL|OL|UU|LL|FL)/i,
    ALLOWED_URL_CHARS: /^[a-zA-Z0-9_\-?=&amp;#:/.]+$/,
    TIME_FORMATS: {
      HOURS: 3600,
      MINUTES: 60,
      SECONDS: 1
    },
    YOUTUBE_NOCOOKIE_DOMAIN: &#39;https://www.youtube-nocookie.com&#39;,
    YOUTUBE_IMG_DOMAIN: &#39;https://img.youtube.com&#39;,
    EMBED_PARAMS: &#39;autoplay=1&amp;mute=1&#39;
  };

  

  function validateInput(input, maxLength = CONSTANTS.MAX_INPUT_LENGTH) {
    if (!input || typeof input !== &#39;string&#39;) return &#39;&#39;;

    const trimmed = input.trim();

    if (trimmed.length &gt; maxLength) {
      console.warn(`Input exceeds maximum length of ${maxLength}`);
      return &#39;&#39;;
    }

    
    if (!CONSTANTS.ALLOWED_URL_CHARS.test(trimmed)) {
      console.warn(&#39;Input contains invalid characters&#39;);
      return &#39;&#39;;
    }

    return trimmed;
  }

  

  function parseStartValue(value) {
    if (!value) return 0;

    
    if (/^\d+$/.test(value)) {
      const parsed = parseInt(value, 10);
      return isNaN(parsed) ? 0 : Math.max(0, parsed);
    }

    
    let total = 0;
    let matched = false;
    const regex = /(\d+)(h|m|s)/gi;
    let match;

    while ((match = regex.exec(value)) !== null) {
      matched = true;
      const num = parseInt(match[1], 10);
      if (isNaN(num)) continue;

      const unit = match[2].toLowerCase();
      if (unit === &#39;h&#39;) total += num * CONSTANTS.TIME_FORMATS.HOURS;
      else if (unit === &#39;m&#39;) total += num * CONSTANTS.TIME_FORMATS.MINUTES;
      else if (unit === &#39;s&#39;) total += num * CONSTANTS.TIME_FORMATS.SECONDS;
    }

    return matched ? Math.max(0, total) : 0;
  }

  

  function extractStartTime(queryString) {
    if (!queryString) return 0;

    try {
      const cleanQuery = queryString.startsWith(&#39;?&#39;) || queryString.startsWith(&#39;#&#39;)
        ? queryString.slice(1)
        : queryString;

      const params = new URLSearchParams(cleanQuery);

      
      return parseStartValue(params.get(&#39;start&#39;)) ||
             parseStartValue(params.get(&#39;t&#39;)) ||
             parseStartValue(params.get(&#39;time_continue&#39;)) ||
             0;
    } catch (e) {
      console.warn(&#39;Failed to parse query parameters:&#39;, e);
      return 0;
    }
  }

  

  function parseId(raw) {
    const validated = validateInput(raw);
    if (!validated) {
      return { type: &#39;unknown&#39;, id: &#39;&#39;, start: 0 };
    }

    let startSeconds = 0;
    let normalized = validated;

    
    const queryIndex = normalized.indexOf(&#39;?&#39;);
    if (queryIndex !== -1) {
      startSeconds = extractStartTime(normalized.slice(queryIndex + 1));
      normalized = normalized.slice(0, queryIndex);
    }

    
    const hashIndex = normalized.indexOf(&#39;#&#39;);
    if (hashIndex !== -1) {
      startSeconds = startSeconds || extractStartTime(normalized.slice(hashIndex + 1));
      normalized = normalized.slice(0, hashIndex);
    }

    
    if (CONSTANTS.PLAYLIST_PREFIXES.test(normalized)) {
      return { type: &#39;playlist&#39;, id: normalized, start: startSeconds };
    }

    
    if (CONSTANTS.VIDEO_ID_PATTERN.test(normalized)) {
      return { type: &#39;video&#39;, id: normalized, start: startSeconds };
    }

    
    const listMatch = normalized.match(/list=([^&amp;]+)/);
    if (listMatch &amp;&amp; listMatch[1]) {
      return { type: &#39;playlist&#39;, id: listMatch[1], start: startSeconds };
    }

    console.warn(&#39;Unable to parse video/playlist ID:&#39;, raw);
    return { type: &#39;unknown&#39;, id: &#39;&#39;, start: startSeconds };
  }

  

  function validateThumbnailUrl(thumbUrl) {
    if (!thumbUrl) return &#39;&#39;;

    let cleaned = thumbUrl.trim();

    
    const markdownMatch = cleaned.match(/^\[[^\]]*\]\(([^)]+)\)$/);
    if (markdownMatch) {
      cleaned = markdownMatch[1].trim();
    }

    
    try {
      const url = new URL(cleaned, document.baseURI);

      
      if (url.protocol !== &#39;http:&#39; &amp;&amp; url.protocol !== &#39;https:&#39;) {
        console.warn(&#39;Thumbnail URL must use http or https protocol&#39;);
        return &#39;&#39;;
      }

      return url.href;
    } catch (e) {
      console.warn(&#39;Invalid thumbnail URL:&#39;, e);
      return &#39;&#39;;
    }
  }

  

  function getPlaylistPlaceholder() {
    const svg = `&lt;svg xmlns=&#39;http://www.w3.org/2000/svg&#39; viewBox=&#39;0 0 1280 720&#39;&gt;` +
                `&lt;rect width=&#39;100%&#39; height=&#39;100%&#39; fill=&#39;#000&#39;/&gt;` +
                `&lt;rect x=&#39;220&#39; y=&#39;260&#39; width=&#39;840&#39; height=&#39;60&#39; fill=&#39;#fff&#39;/&gt;` +
                `&lt;rect x=&#39;220&#39; y=&#39;340&#39; width=&#39;660&#39; height=&#39;60&#39; fill=&#39;#fff&#39;/&gt;` +
                `&lt;/svg&gt;`;
    return &#39;data:image/svg+xml;charset=utf-8,&#39; + encodeURIComponent(svg);
  }

  /**
   * Sets up thumbnail for video wrapper
   * @param {HTMLImageElement} thumbnail - Thumbnail element
   * @param {Object} kind - Parsed video/playlist info
   * @param {string} customThumb - Custom thumbnail URL
   */
  function setupThumbnail(thumbnail, kind, customThumb) {
    if (!thumbnail) return;

    if (customThumb) {
      // Use custom thumbnail
      thumbnail.onerror = null;
      thumbnail.src = customThumb;
    } else if (kind.type === &#39;playlist&#39;) {
      // Use playlist placeholder
      thumbnail.src = getPlaylistPlaceholder();
    } else if (kind.type === &#39;video&#39; &amp;&amp; kind.id) {
      // Use YouTube thumbnail with fallback
      thumbnail.src = `${CONSTANTS.YOUTUBE_IMG_DOMAIN}/vi/${kind.id}/maxresdefault.jpg`;
      thumbnail.onerror = () =&gt; {
        thumbnail.onerror = null;
        thumbnail.src = `${CONSTANTS.YOUTUBE_IMG_DOMAIN}/vi/${kind.id}/0.jpg`;
      };
    }
    // For unknown type, keep the default placeholder
  }

  /**
   * Creates embed URL for video or playlist
   * @param {Object} kind - Parsed video/playlist info
   * @returns {string} Embed URL or empty string if invalid
   */
  function createEmbedUrl(kind) {
    if (kind.type === &#39;playlist&#39; &amp;&amp; kind.id) {
      return `${CONSTANTS.YOUTUBE_NOCOOKIE_DOMAIN}/embed/videoseries?list=${encodeURIComponent(kind.id)}&amp;${CONSTANTS.EMBED_PARAMS}`;
    } else if (kind.type === &#39;video&#39; &amp;&amp; kind.id) {
      let url = `${CONSTANTS.YOUTUBE_NOCOOKIE_DOMAIN}/embed/${encodeURIComponent(kind.id)}?${CONSTANTS.EMBED_PARAMS}`;
      if (kind.start &gt; 0) {
        url += `&amp;start=${Math.floor(kind.start)}`;
      }
      return url;
    }
    return &#39;&#39;;
  }

  /**
   * Creates and loads iframe embed
   * @param {HTMLElement} wrapper - Video wrapper element
   * @param {Object} kind - Parsed video/playlist info
   * @param {string} title - Video title
   */
  function loadEmbed(wrapper, kind, title) {
    if (wrapper.dataset.isLoaded === &#39;true&#39;) return;

    const embedUrl = createEmbedUrl(kind);
    if (!embedUrl) {
      console.error(&#39;Unable to create embed URL - invalid video/playlist ID&#39;);
      // Show error message to user
      wrapper.innerHTML = &#39;&lt;div style=&#34;padding: 2em; text-align: center; color: #fff;&#34;&gt;Unable to load video. Please check the video ID.&lt;/div&gt;&#39;;
      return;
    }

    // Create iframe
    const iframe = document.createElement(&#39;iframe&#39;);
    iframe.setAttribute(&#39;allowfullscreen&#39;, &#39;&#39;);
    iframe.setAttribute(&#39;loading&#39;, &#39;lazy&#39;);
    iframe.setAttribute(&#39;allow&#39;, &#39;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#39;);
    iframe.setAttribute(&#39;title&#39;, title ? `YouTube video player: ${title}` : &#39;YouTube video player&#39;);
    iframe.src = embedUrl;

    
    const replacement = document.createElement(&#39;div&#39;);
    replacement.className = wrapper.className;
    replacement.dataset.listenersAdded = &#39;true&#39;;
    replacement.dataset.isLoaded = &#39;true&#39;;
    replacement.appendChild(iframe);

    wrapper.replaceWith(replacement);
  }

  

  function enhanceEmbeds() {
    const wrappers = document.querySelectorAll(&#39;.video-wrapper&#39;);

    wrappers.forEach(wrapper =&gt; {
      
      if (wrapper.dataset.listenersAdded === &#39;true&#39;) return;
      wrapper.dataset.listenersAdded = &#39;true&#39;;

      
      const rawVideoId = wrapper.dataset.videoId || &#39;&#39;;
      const rawThumbUrl = wrapper.dataset.thumb || &#39;&#39;;
      const videoTitle = wrapper.dataset.videoTitle || &#39;&#39;;

      
      const kind = parseId(rawVideoId);
      const safeThumb = validateThumbnailUrl(rawThumbUrl);

      
      const thumbnail = wrapper.querySelector(&#39;.video-thumbnail&#39;);
      setupThumbnail(thumbnail, kind, safeThumb);

      
      const loadHandler = () =&gt; loadEmbed(wrapper, kind, videoTitle);

      wrapper.addEventListener(&#39;click&#39;, loadHandler);

      const overlay = wrapper.querySelector(&#39;.video-overlay&#39;);
      if (overlay) overlay.addEventListener(&#39;click&#39;, loadHandler);
      if (thumbnail) thumbnail.addEventListener(&#39;click&#39;, loadHandler);

      
      wrapper.addEventListener(&#39;keydown&#39;, (e) =&gt; {
        if (e.key === &#39;Enter&#39; || e.key === &#39; &#39;) {
          e.preventDefault();
          loadHandler();
        }
      });
    });
  }

  
  enhanceEmbeds();
  if (document.readyState === &#39;loading&#39;) {
    document.addEventListener(&#39;DOMContentLoaded&#39;, enhanceEmbeds);
  }
})();
&lt;/script&gt;&lt;p class=&#34;yt-text-link&#34;&gt;
      &lt;a href=&#34;https://www.youtube.com/watch?v=w5k72A30kUc&#34;&gt;YouTube Video&lt;/a&gt;
    &lt;/p&gt;&lt;button type=&#34;button&#34;
    class=&#34;video-wrapper&#34;
    aria-label=&#34;Play YouTube video&#34;
    data-video-id=&#34;w5k72A30kUc&#34;
    data-thumb=&#34;&#34;
    &gt;&lt;img
      class=&#34;video-thumbnail&#34;
      src=&#34;data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20viewBox=%270%200%201280%20720%27%3E%3Crect%20width=%27100%25%25%27%20height=%27100%25%25%27%20fill=%27%23000%27/%3E%3C/svg%3E&#34;
      alt=&#34;YouTube Thumbnail&#34;
      loading=&#34;lazy&#34;
      decoding=&#34;async&#34;&gt;&lt;div class=&#34;video-play-button&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;&lt;noscript&gt;
    &lt;div class=&#34;video-noscript&#34;&gt;&lt;img src=&#34;https://img.youtube.com/vi/w5k72A30kUc/maxresdefault.jpg&#34;
             alt=&#34;YouTube Thumbnail&#34;&gt;&lt;p&gt;
          &lt;a href=&#34;https://www.youtube.com/watch?v=w5k72A30kUc&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;YouTube Video&lt;/a&gt;
        &lt;/p&gt;&lt;/div&gt;
  &lt;/noscript&gt;
&lt;p&gt;That was an interesting 15 min watch. What I liked a lot was that it briefly touched on massive inequality, too, it didn&amp;rsquo;t just ignore it – in fact, I think inequality&amp;rsquo;s very much part of Mr Leyden&amp;rsquo;s prediction:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The economic system […] that has worked for essentially the top 10% for sure and certainly for the top 1% has &lt;em&gt;not&lt;/em&gt; been working for 80%. And it&amp;rsquo;s gotten to the point where they just have had it.&lt;/p&gt;
&lt;/blockquote&gt;
</description>
      <source:markdown>[Peter Leyden: Why 2025 is the single most pivotal year in our lifetime](https://www.youtube.com/watch?v=w5k72A30kUc)

{{&lt; yt &#34;w5k72A30kUc&#34; &gt;}}

That was an interesting 15 min watch. What I liked a lot was that it briefly touched on massive inequality, too, it didn&#39;t just ignore it – in fact, I think inequality&#39;s very much part of Mr Leyden&#39;s prediction:

&gt; The economic system […] that has worked for essentially the top 10% for sure and certainly for the top 1% has *not* been working for 80%. And it&#39;s gotten to the point where they just have had it.
</source:markdown>
    </item>
    
    <item>
      <title>Adding some Vygotsky to my LLM system prompt </title>
      <link>https://zottmann.org/2025/10/25/adding-some-vygotsky-to-my.html</link>
      <pubDate>Sat, 25 Oct 2025 11:52:19 +0100</pubDate>
      
      <guid>http://czottmann.micro.blog/2025/10/25/adding-some-vygotsky-to-my.html</guid>
      <description>&lt;p&gt;Anders Thoresson came up with a good addition to LLM system prompts (Claude, Codex, GLM et al). I&amp;rsquo;ve been using it for the last few weeks, and &lt;strong&gt;it definitely feels like I get better interactions out of Claude&lt;/strong&gt; when tasking it with research, helping me think things through, or have it explain new concepts to me.&lt;/p&gt;
&lt;p&gt;The prompt:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Meet me where I am (Vygotsky&amp;rsquo;s theory of zone of proximal development): Gauge my understanding from what I write. If unclear, ask one question about my current knowledge level, then proceed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Since &lt;a href=&#34;https://anders.thoresson.se/post/2025/10/a-hundred-year-old-pedagogical-theory-that-elevates-ai-as-a-thinking-partner/&#34;&gt;Anders&#39; post is a good read&lt;/a&gt; which explains the theory and how he arrived at the prompt, I think you should just go there to learn more.&lt;/p&gt;
</description>
      <source:markdown>Anders Thoresson came up with a good addition to LLM system prompts (Claude, Codex, GLM et al). I&#39;ve been using it for the last few weeks, and **it definitely feels like I get better interactions out of Claude** when tasking it with research, helping me think things through, or have it explain new concepts to me.

The prompt:

&gt; Meet me where I am (Vygotsky&#39;s theory of zone of proximal development): Gauge my understanding from what I write. If unclear, ask one question about my current knowledge level, then proceed.

Since [Anders&#39; post is a good read](https://anders.thoresson.se/post/2025/10/a-hundred-year-old-pedagogical-theory-that-elevates-ai-as-a-thinking-partner/) which explains the theory and how he arrived at the prompt, I think you should just go there to learn more.
</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://zottmann.org/2025/10/12/quoting-craig-mod-once-more.html</link>
      <pubDate>Sun, 12 Oct 2025 18:34:16 +0100</pubDate>
      
      <guid>http://czottmann.micro.blog/2025/10/12/quoting-craig-mod-once-more.html</guid>
      <description>&lt;p&gt;Quoting &lt;a href=&#34;https://craigmod.com/&#34;&gt;Craig Mod&lt;/a&gt; once more:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Everyone was uniquely nuts. Each human contained their own special crazy. This was humanity&amp;rsquo;s gift to the universe. Humans were the &amp;ldquo;sensory organs&amp;rdquo; of the cosmos. The walker liked this framing — the purpose of humans was to meta-cognitize the universe itself. So to be, to observe, was to fulfill. If you thought about it like that, things were a lot less pressing.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Another excerpt from his ongoing (and lovely) pop-up &lt;a href=&#34;https://craigmod.com/newsletters/&#34;&gt;newsletter&lt;/a&gt;, &lt;strong&gt;Between Two Mountains&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;BTW, I think the origin of that framing is &lt;a href=&#34;https://en.wikiquote.org/wiki/Carl_Sagan#The_Shores_of_the_Cosmic_Ocean_%5BEpisode_1%5D&#34;&gt;Carl Sagan&lt;/a&gt;: &lt;em&gt;&amp;ldquo;We are a way for the universe to know itself&amp;rdquo;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I am also reminded of a video short by Jason Silva that I watched about ten years ago (and which lived rent-free in my mind ever since for some reason), &lt;a href=&#34;https://www.youtube.com/watch?v=8D3NCSVIWUQ&#34;&gt;&amp;ldquo;Humans are the Sex Organs of Technology&amp;rdquo;&lt;/a&gt;. Different topic, sure, yet equally wild.&lt;/p&gt;
&lt;p&gt;The ideas of humanity as a witness, or a parent/ midwife for &lt;em&gt;something else&lt;/em&gt; to emerge are kind of mindbending.&lt;/p&gt;
</description>
      <source:markdown>Quoting [Craig Mod](https://craigmod.com/) once more:

&gt; Everyone was uniquely nuts. Each human contained their own special crazy. This was humanity&#39;s gift to the universe. Humans were the &#34;sensory organs&#34; of the cosmos. The walker liked this framing — the purpose of humans was to meta-cognitize the universe itself. So to be, to observe, was to fulfill. If you thought about it like that, things were a lot less pressing.  

Another excerpt from his ongoing (and lovely) pop-up [newsletter](https://craigmod.com/newsletters/), **Between Two Mountains**.

BTW, I think the origin of that framing is [Carl Sagan](https://en.wikiquote.org/wiki/Carl_Sagan#The_Shores_of_the_Cosmic_Ocean_[Episode_1]): _&#34;We are a way for the universe to know itself&#34;_.

I am also reminded of a video short by Jason Silva that I watched about ten years ago (and which lived rent-free in my mind ever since for some reason), [&#34;Humans are the Sex Organs of Technology&#34;](https://www.youtube.com/watch?v=8D3NCSVIWUQ). Different topic, sure, yet equally wild.

The ideas of humanity as a witness, or a parent/ midwife for _something else_ to emerge are kind of mindbending.
</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://zottmann.org/2025/10/05/ein-wirklich-interessantes-interview-mit.html</link>
      <pubDate>Sun, 05 Oct 2025 18:56:58 +0100</pubDate>
      
      <guid>http://czottmann.micro.blog/2025/10/05/ein-wirklich-interessantes-interview-mit.html</guid>
      <description>&lt;p&gt;Ein wirklich interessantes Interview mit dem Autoren Thomas Chatterton Williams beim ZEITmagazin: &lt;a href=&#34;https://archive.is/newest/https://www.zeit.de/zeit-magazin/2025/41/thomas-chatterton-williams-wokeness-politische-rechte-polarisierung/komplettansicht#selection-1283.62-1283.94&#34;&gt;&amp;ldquo;Ein Klima, in dem viele lieber schwiegen. Das machte Woke so wirksam&amp;rdquo;&lt;/a&gt;. Ich finde es in Gänze sehr lesenswert, und hätte die Hälfte des gesamten Artikels zitieren können, daher hier nur ein kurzer Auszug:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;ZEITmagazin:&lt;/strong&gt; Was war das Gute an Wokeness?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Williams:&lt;/strong&gt; Wokeness benannte vieles richtig. Ein Beispiel ist MeToo: Als heterosexueller Mann hatte ich nie darüber nachgedacht, mit welchen subtilen Hürden Frauen am Arbeitsplatz konfrontiert sind, etwa beim Netzwerken oder Bewerben. Wokeness machte solche Unsichtbarkeiten sichtbar. […] Problematisch wurde Wokeness dort, wo sie über das Ziel hinausschoss: Wenn Unschuldige durch bloße Anschuldigungen ruiniert wurden und das als Preis fürs größere Ganze galt. Ein Kurator des San Francisco Museum of Modern Art wurde zum Rückzug gedrängt, nachdem er gesagt hatte, er wolle weiterhin Kunst von weißen Künstlern kaufen. Der Präsident und der Vorstandsvorsitzende der Poetry Foundation mussten zurücktreten, weil sie zwar Black Lives Matter unterstützten, aber nicht entschieden genug.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ZEITmagazin:&lt;/strong&gt; Black Lives Matter war der sichtbarste Ausdruck dieser neuen Sensibilität. Wo genau hat sich die Bewegung aus Ihrer Sicht verrannt?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Williams:&lt;/strong&gt; Der ursprüngliche Impuls von Black Lives Matter war berechtigt. Die Zahl der tödlichen Polizeieinsätze in den USA ist skandalös. Aber schnell verlagerte sich der Fokus von der Gewalt selbst auf die Gruppenzugehörigkeit der Opfer. Das hat viele Menschen entfremdet. Es gibt etwa den Fall von Tony Timpa, einem weißen Mann, der 2016 in Dallas fast auf dieselbe Weise starb wie George Floyd: Polizisten knieten auf ihm, während er um Atem rang, sie lachten – und er starb. Doch das Video ging nicht viral. Warum? Weil der identitätspolitische Fokus fehlte. Genau das war langfristig kontraproduktiv: Statt sich gemeinsam gegen Polizeigewalt zu wenden, wurde alles durch eine identitätspolitische Brille betrachtet.&lt;/p&gt;
&lt;/blockquote&gt;
</description>
      <source:markdown>Ein wirklich interessantes Interview mit dem Autoren Thomas Chatterton Williams beim ZEITmagazin: [&#34;Ein Klima, in dem viele lieber schwiegen. Das machte Woke so wirksam&#34;](https://archive.is/newest/https://www.zeit.de/zeit-magazin/2025/41/thomas-chatterton-williams-wokeness-politische-rechte-polarisierung/komplettansicht#selection-1283.62-1283.94). Ich finde es in Gänze sehr lesenswert, und hätte die Hälfte des gesamten Artikels zitieren können, daher hier nur ein kurzer Auszug:

&gt; **ZEITmagazin:** Was war das Gute an Wokeness?
&gt;
&gt; **Williams:** Wokeness benannte vieles richtig. Ein Beispiel ist MeToo: Als heterosexueller Mann hatte ich nie darüber nachgedacht, mit welchen subtilen Hürden Frauen am Arbeitsplatz konfrontiert sind, etwa beim Netzwerken oder Bewerben. Wokeness machte solche Unsichtbarkeiten sichtbar. […] Problematisch wurde Wokeness dort, wo sie über das Ziel hinausschoss: Wenn Unschuldige durch bloße Anschuldigungen ruiniert wurden und das als Preis fürs größere Ganze galt. Ein Kurator des San Francisco Museum of Modern Art wurde zum Rückzug gedrängt, nachdem er gesagt hatte, er wolle weiterhin Kunst von weißen Künstlern kaufen. Der Präsident und der Vorstandsvorsitzende der Poetry Foundation mussten zurücktreten, weil sie zwar Black Lives Matter unterstützten, aber nicht entschieden genug.
&gt; 
&gt; **ZEITmagazin:** Black Lives Matter war der sichtbarste Ausdruck dieser neuen Sensibilität. Wo genau hat sich die Bewegung aus Ihrer Sicht verrannt?
&gt;
&gt; **Williams:** Der ursprüngliche Impuls von Black Lives Matter war berechtigt. Die Zahl der tödlichen Polizeieinsätze in den USA ist skandalös. Aber schnell verlagerte sich der Fokus von der Gewalt selbst auf die Gruppenzugehörigkeit der Opfer. Das hat viele Menschen entfremdet. Es gibt etwa den Fall von Tony Timpa, einem weißen Mann, der 2016 in Dallas fast auf dieselbe Weise starb wie George Floyd: Polizisten knieten auf ihm, während er um Atem rang, sie lachten – und er starb. Doch das Video ging nicht viral. Warum? Weil der identitätspolitische Fokus fehlte. Genau das war langfristig kontraproduktiv: Statt sich gemeinsam gegen Polizeigewalt zu wenden, wurde alles durch eine identitätspolitische Brille betrachtet.
</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://zottmann.org/2025/10/03/quoting-craig-mod-tiny-men.html</link>
      <pubDate>Fri, 03 Oct 2025 18:02:49 +0100</pubDate>
      
      <guid>http://czottmann.micro.blog/2025/10/03/quoting-craig-mod-tiny-men.html</guid>
      <description>&lt;p&gt;Quoting &lt;a href=&#34;https://craigmod.com/&#34;&gt;Craig Mod&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Tiny men with big sticks upend sanity the world ‘round and all you can do is try to find your footing and push back.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;From the first missive of his current pop-up &lt;a href=&#34;https://craigmod.com/newsletters/&#34;&gt;newsletter&lt;/a&gt;, &lt;strong&gt;Between Two Mountains&lt;/strong&gt;.&lt;/p&gt;
</description>
      <source:markdown>Quoting [Craig Mod](https://craigmod.com/):

&gt; Tiny men with big sticks upend sanity the world ‘round and all you can do is try to find your footing and push back.

From the first missive of his current pop-up [newsletter](https://craigmod.com/newsletters/), **Between Two Mountains**.
</source:markdown>
    </item>
    
    <item>
      <title>iOS iCloud Drive Synchronization Deep Dive</title>
      <link>https://zottmann.org/2025/09/08/ios-icloud-drive-synchronization-deep.html</link>
      <pubDate>Mon, 08 Sep 2025 19:20:37 +0100</pubDate>
      
      <guid>http://czottmann.micro.blog/2025/09/08/ios-icloud-drive-synchronization-deep.html</guid>
      <description>&lt;p&gt;Today I was pondering a feature idea for my macOS/iOS app &lt;a href=&#34;https://actions.work/actions-for-obsidian&#34;&gt;Actions For Obsidian&lt;/a&gt;. That idea is loosely related to iCloud Drive. But ever since AFO’s release a few years back, I have received dozens of support requests from people who ran into issues while attempting to use iCloud Drive as a means of synchronizing their &lt;a href=&#34;https://obsidian.md&#34;&gt;Obsidian&lt;/a&gt; vaults between their devices.&lt;/p&gt;
&lt;p&gt;Usually my one-word answer to these questions is &lt;em&gt;&amp;ldquo;Don&amp;rsquo;t&amp;rdquo;&lt;/em&gt;, followed by a link to a FAQ entry that I wrote a while back: &lt;a href=&#34;https://docs.actions.work/actions-for-obsidian/faqs/#can-i-use-icloud-sync-with-obsidian-and-actions-for-obsidian&#34;&gt;&lt;em&gt;&amp;ldquo;Can I use iCloud Sync with Obsidian and Actions for Obsidian?&amp;quot;&lt;/em&gt;&lt;/a&gt; (Spoiler: Yes, you can, but it’ll be painful at one point or another… or several.)&lt;/p&gt;
&lt;p&gt;I had a pretty good mental model of iCloud Drive&amp;rsquo;s behavior built up already, but as I was thinking about that aforementioned feature idea, I figured that Claude Opus 4.1&amp;rsquo;s &amp;ldquo;research mode&amp;rdquo; might speed up the process a bit. So I tasked it to dive deep into researching how iCloud Drive synchronization works, particularly focusing on iOS behavior and specific scenarios with Obsidian vaults and the &amp;ldquo;Keep Downloaded&amp;rdquo; feature.&lt;/p&gt;
&lt;p&gt;The resulting doc is what you&amp;rsquo;ll find below. Enjoy. #sharingIsCaring&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;ios-icloud-drive-synchronization-deep-dive&#34;&gt;iOS iCloud Drive Synchronization Deep Dive&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Apple&amp;rsquo;s iCloud Drive synchronization on iOS operates as a system-controlled process that prioritizes device performance and battery life over real-time sync&lt;/strong&gt;, fundamentally changing how third-party apps like Obsidian must approach data synchronization. Unlike traditional file sync services, iOS maintains strict control over when, how, and under what conditions synchronization occurs, creating both powerful integration opportunities and significant technical challenges for developers and users.&lt;/p&gt;
&lt;p&gt;The core architectural principle revealed through Apple&amp;rsquo;s official documentation is that &lt;strong&gt;applications cannot force synchronization&lt;/strong&gt;&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; - the iOS system decides all sync timing based on complex algorithms that consider network conditions, battery state, thermal management, and learned user behavior patterns&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;. This system-first approach means that apps like Obsidian must work within iOS&amp;rsquo;s scheduling constraints rather than implementing direct sync control.&lt;/p&gt;
&lt;h2 id=&#34;system-controlled-sync-architecture-governs-all-operations&#34;&gt;System-controlled sync architecture governs all operations&lt;/h2&gt;
&lt;p&gt;Apple&amp;rsquo;s iCloud Drive uses a sophisticated &lt;strong&gt;two-stage synchronization process&lt;/strong&gt; where files move from app containers to system-managed directories, then propagate to iCloud servers &amp;ldquo;as soon as possible&amp;rdquo;&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt; - but timing remains entirely system-controlled. All file operations must use &lt;code&gt;NSFileCoordinator&lt;/code&gt; objects to prevent conflicts between applications and the sync daemon, creating a coordination layer that acts as a locking mechanism&lt;sup id=&#34;fnref:5&#34;&gt;&lt;a href=&#34;#fn:5&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:6&#34;&gt;&lt;a href=&#34;#fn:6&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;6&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:7&#34;&gt;&lt;a href=&#34;#fn:7&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;7&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;The system implements &lt;strong&gt;intelligent throttling mechanisms&lt;/strong&gt; designed to protect both device resources and server infrastructure. CloudKit throttles requests when it determines the request rate is too high, with 30-second minimum intervals between rapid operations&lt;sup id=&#34;fnref:5&#34;&gt;&lt;a href=&#34;#fn:5&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:6&#34;&gt;&lt;a href=&#34;#fn:6&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;6&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:7&#34;&gt;&lt;a href=&#34;#fn:7&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;7&lt;/a&gt;&lt;/sup&gt;. This throttling serves as protection against overwhelming system resources and maintains server stability.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;File coordination requirements&lt;/strong&gt; create significant technical complexity for developers. Every file access requires coordination to prevent race conditions, and file presenters are &amp;ldquo;very expensive objects&amp;rdquo; requiring extensive inter-process communication&lt;sup id=&#34;fnref:8&#34;&gt;&lt;a href=&#34;#fn:8&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;8&lt;/a&gt;&lt;/sup&gt;. Context switches occur between the reading process, presenting process, and file coordination daemon, risking depletion of system resources if too many presenters are registered.&lt;/p&gt;
&lt;h2 id=&#34;synchronization-triggers-operate-on-multiple-system-levels&#34;&gt;Synchronization triggers operate on multiple system levels&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Automatic triggers&lt;/strong&gt; include app foreground events, network state changes, system resource availability, and device wake cycles. When an app comes to the foreground, especially on macOS, sync often triggers immediately&lt;sup id=&#34;fnref:9&#34;&gt;&lt;a href=&#34;#fn:9&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;9&lt;/a&gt;&lt;/sup&gt;. Network connectivity changes - particularly switching from cellular to WiFi - initiate sync attempts. The system also monitors storage conditions, pausing sync when iCloud storage is full or device storage is constrained&lt;sup id=&#34;fnref:10&#34;&gt;&lt;a href=&#34;#fn:10&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;10&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:11&#34;&gt;&lt;a href=&#34;#fn:11&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;11&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Manual sync triggers&lt;/strong&gt; are limited but exist through specific user actions. Users can force sync by toggling iCloud Drive settings off and on, signing out and back into iCloud accounts, or using app-specific refresh mechanisms like pull-to-refresh in Contacts and Calendar apps&lt;sup id=&#34;fnref:10&#34;&gt;&lt;a href=&#34;#fn:10&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;10&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:11&#34;&gt;&lt;a href=&#34;#fn:11&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;11&lt;/a&gt;&lt;/sup&gt;. However, these methods don&amp;rsquo;t guarantee immediate sync - they merely request that the system prioritize sync operations.&lt;/p&gt;
&lt;p&gt;Background app refresh plays a &lt;strong&gt;critical enabling role&lt;/strong&gt; for sync operations. Apps must be granted Background App Refresh permission, and iOS uses machine learning to determine optimal sync timing based on user behavior patterns, available system resources, network quality, battery level, and time-of-day patterns&lt;sup id=&#34;fnref:12&#34;&gt;&lt;a href=&#34;#fn:12&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;12&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:13&#34;&gt;&lt;a href=&#34;#fn:13&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;13&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:14&#34;&gt;&lt;a href=&#34;#fn:14&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;14&lt;/a&gt;&lt;/sup&gt;. The system can take &amp;ldquo;seven days for Apple&amp;rsquo;s on-device ML to pick up that the user really wants to use the app,&amp;quot;&lt;sup id=&#34;fnref:15&#34;&gt;&lt;a href=&#34;#fn:15&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;15&lt;/a&gt;&lt;/sup&gt; affecting sync frequency during this learning period.&lt;/p&gt;
&lt;h2 id=&#34;timing-patterns-follow-intelligent-resource-management&#34;&gt;Timing patterns follow intelligent resource management&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Synchronization frequency varies dramatically&lt;/strong&gt; based on system conditions rather than following fixed intervals. Apple&amp;rsquo;s documentation explicitly states that &amp;ldquo;CloudKit synchronization isn&amp;rsquo;t real time&amp;rdquo; and timing is &amp;ldquo;as-designed to better balance the use of system resources and achieve the best overall user experience.&amp;quot;&lt;sup id=&#34;fnref:16&#34;&gt;&lt;a href=&#34;#fn:16&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;16&lt;/a&gt;&lt;/sup&gt; The system implements no guaranteed timing - sync operates on an opportunistic basis when conditions are favorable&lt;sup id=&#34;fnref:17&#34;&gt;&lt;a href=&#34;#fn:17&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;17&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Priority scheduling&lt;/strong&gt; follows a clear hierarchy: foreground app operations receive highest priority, followed by critical system functions, user-initiated sync requests, scheduled background sync tasks, and finally opportunistic background sync. iOS uses BGTaskScheduler (iOS 13+) to replace legacy background fetch with more sophisticated scheduling based on device usage patterns learned over time&lt;sup id=&#34;fnref:18&#34;&gt;&lt;a href=&#34;#fn:18&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;18&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:19&#34;&gt;&lt;a href=&#34;#fn:19&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;19&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:20&#34;&gt;&lt;a href=&#34;#fn:20&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;20&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Background execution limitations&lt;/strong&gt; significantly impact sync behavior. Background App Refresh provides only limited execution time - typically 30 seconds for BGAppRefreshTask and longer durations for BGProcessingTask, but only when external power is available for heavy operations&lt;sup id=&#34;fnref:21&#34;&gt;&lt;a href=&#34;#fn:21&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;21&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:22&#34;&gt;&lt;a href=&#34;#fn:22&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;22&lt;/a&gt;&lt;/sup&gt;. Apps cannot force specific sync intervals and must work within iOS scheduling constraints where background execution is &amp;ldquo;cooperative&amp;rdquo; and can be terminated at any time.&lt;/p&gt;
&lt;h2 id=&#34;app-specific-behavior-creates-unique-integration-challenges&#34;&gt;App-specific behavior creates unique integration challenges&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Obsidian&amp;rsquo;s vault synchronization&lt;/strong&gt; exemplifies the challenges third-party apps face with iCloud Drive integration. User reports consistently describe unidirectional sync failures where &amp;ldquo;creating new notes in macOS syncs immediately to iOS, but editing notes in iOS doesn&amp;rsquo;t sync back to macOS.&amp;quot;&lt;sup id=&#34;fnref:23&#34;&gt;&lt;a href=&#34;#fn:23&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;23&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:24&#34;&gt;&lt;a href=&#34;#fn:24&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;24&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:25&#34;&gt;&lt;a href=&#34;#fn:25&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;25&lt;/a&gt;&lt;/sup&gt; Files frequently get &amp;ldquo;stuck uploading&amp;rdquo; with cloud icons showing indefinitely, and the app lacks native conflict resolution, leading to silent overwrites when notes are edited on multiple devices while offline.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Developer implementation challenges&lt;/strong&gt; stem from iCloud&amp;rsquo;s low-level API requirements. Developers report that &amp;ldquo;the iCloud API is too low level,&amp;rdquo; requiring extensive code for basic operations with no single function for putting files into or removing them from iCloud&lt;sup id=&#34;fnref:26&#34;&gt;&lt;a href=&#34;#fn:26&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;26&lt;/a&gt;&lt;/sup&gt;. The asynchronous, cooperative, lock-based nature creates &amp;ldquo;implications that are often not easy to grasp,&amp;quot;&lt;sup id=&#34;fnref:27&#34;&gt;&lt;a href=&#34;#fn:27&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;27&lt;/a&gt;&lt;/sup&gt; leading many developers to prefer alternatives like Dropbox for reliability.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Document-based versus file-based sync&lt;/strong&gt; creates different user experiences. Document-based apps using NSDocument/UIDocument protocols benefit from automatic conflict resolution, while file-based sync (like Obsidian) relies on basic iCloud Drive file synchronization without built-in conflict handling&lt;sup id=&#34;fnref:28&#34;&gt;&lt;a href=&#34;#fn:28&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;28&lt;/a&gt;&lt;/sup&gt;. Advanced apps must implement custom conflict resolution UIs to match user expectations&lt;sup id=&#34;fnref:29&#34;&gt;&lt;a href=&#34;#fn:29&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;29&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2 id=&#34;sync-interruption-patterns-follow-predictable-system-states&#34;&gt;Sync interruption patterns follow predictable system states&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Network-dependent behavior&lt;/strong&gt; shows strong WiFi preference with cellular serving as a heavily throttled fallback. Even with cellular enabled, iOS implements intelligent throttling where sync only occurs over cellular when WiFi hasn&amp;rsquo;t been available for extended periods&lt;sup id=&#34;fnref:30&#34;&gt;&lt;a href=&#34;#fn:30&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;30&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:31&#34;&gt;&lt;a href=&#34;#fn:31&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;31&lt;/a&gt;&lt;/sup&gt;. Low Data Mode specifically pauses iCloud sync operations&lt;sup id=&#34;fnref:32&#34;&gt;&lt;a href=&#34;#fn:32&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;32&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:33&#34;&gt;&lt;a href=&#34;#fn:33&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;33&lt;/a&gt;&lt;/sup&gt;, and users report that iCloud Drive downloads often fail over cellular connections even when uploads work&lt;sup id=&#34;fnref:34&#34;&gt;&lt;a href=&#34;#fn:34&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;34&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Power management creates definitive sync boundaries&lt;/strong&gt;. Low Power Mode automatically pauses all iCloud sync operations when battery drops below 20% and remains paused even when the device is charged until manually disabled&lt;sup id=&#34;fnref:35&#34;&gt;&lt;a href=&#34;#fn:35&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;35&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:36&#34;&gt;&lt;a href=&#34;#fn:36&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;36&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:37&#34;&gt;&lt;a href=&#34;#fn:37&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;37&lt;/a&gt;&lt;/sup&gt;. iOS displays &amp;ldquo;Optimizing Battery Power&amp;rdquo; messages when pausing sync to preserve battery life, and thermal management pauses operations when devices overheat with &amp;ldquo;Device Needs to Cool Down&amp;rdquo; messages&lt;sup id=&#34;fnref:38&#34;&gt;&lt;a href=&#34;#fn:38&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;38&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Storage conditions&lt;/strong&gt; create hard stops for synchronization. Sync completely halts when iCloud storage quota is exceeded, and iOS pauses sync when device storage drops below critical thresholds&lt;sup id=&#34;fnref:39&#34;&gt;&lt;a href=&#34;#fn:39&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;39&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:40&#34;&gt;&lt;a href=&#34;#fn:40&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;40&lt;/a&gt;&lt;/sup&gt;. The system displays specific status messages including &amp;ldquo;Low Data Mode,&amp;rdquo; &amp;ldquo;Poor Network Connection,&amp;rdquo; and &amp;ldquo;Device Needs to Cool Down&amp;rdquo; to communicate sync pause reasons&lt;sup id=&#34;fnref:41&#34;&gt;&lt;a href=&#34;#fn:41&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;41&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2 id=&#34;file-prioritization-follows-system-managed-algorithms&#34;&gt;File prioritization follows system-managed algorithms&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&amp;ldquo;Keep Downloaded&amp;rdquo; versus normal cloud storage&lt;/strong&gt; creates two distinct sync behaviors. Files marked &amp;ldquo;Keep Downloaded&amp;rdquo; remain local even when storage optimization is active, while normal cloud storage uses on-demand download where files exist as placeholders until accessed&lt;sup id=&#34;fnref:42&#34;&gt;&lt;a href=&#34;#fn:42&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;42&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:43&#34;&gt;&lt;a href=&#34;#fn:43&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;43&lt;/a&gt;&lt;/sup&gt;. The system provides visual indicators through cloud/download status icons, and users can manually set Keep Downloaded status via context menus.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sync prioritization algorithms&lt;/strong&gt; aren&amp;rsquo;t fully documented by Apple, but research reveals patterns: the system prioritizes based on system resources first, then user experience considerations, data integrity requirements, and server load management. Large files are often deprioritized in favor of smaller, more critical data, and iOS may selectively sync metadata before file contents when storage is constrained.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Background versus foreground sync behavior&lt;/strong&gt; creates dramatically different user experiences. Foreground sync typically works &amp;ldquo;within seconds&amp;rdquo; with immediate updates, while background sync can take &amp;ldquo;minutes or even up to an hour&amp;rdquo; depending on iOS scheduling decisions&lt;sup id=&#34;fnref:44&#34;&gt;&lt;a href=&#34;#fn:44&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;44&lt;/a&gt;&lt;/sup&gt;. macOS apps sync continuously while running, but iOS apps depend entirely on system wake-ups that follow learned usage patterns.&lt;/p&gt;
&lt;h2 id=&#34;network-and-battery-conditions-shape-sync-behavior&#34;&gt;Network and battery conditions shape sync behavior&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;WiFi versus cellular sync patterns&lt;/strong&gt; show strong system bias toward WiFi connections. Users must explicitly enable cellular data for iCloud Drive in Settings &amp;gt; Cellular &amp;gt; iCloud Drive&lt;sup id=&#34;fnref:45&#34;&gt;&lt;a href=&#34;#fn:45&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;45&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:46&#34;&gt;&lt;a href=&#34;#fn:46&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;46&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:47&#34;&gt;&lt;a href=&#34;#fn:47&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;47&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:48&#34;&gt;&lt;a href=&#34;#fn:48&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;48&lt;/a&gt;&lt;/sup&gt;, but even with cellular enabled, iOS implements aggressive throttling. The &amp;ldquo;Documents &amp;amp; Sync&amp;rdquo; system service can consume substantial cellular data (1-8GB reported cases)&lt;sup id=&#34;fnref:49&#34;&gt;&lt;a href=&#34;#fn:49&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;49&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:50&#34;&gt;&lt;a href=&#34;#fn:50&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;50&lt;/a&gt;&lt;/sup&gt;, leading iOS to discourage cellular sync through power management restrictions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Battery state management&lt;/strong&gt; creates multiple intervention points. Beyond Low Power Mode&amp;rsquo;s complete sync pause, iOS implements &amp;ldquo;Optimizing System Performance&amp;rdquo; states that pause sync to prioritize foreground tasks&lt;sup id=&#34;fnref:51&#34;&gt;&lt;a href=&#34;#fn:51&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;51&lt;/a&gt;&lt;/sup&gt;. The system preferentially schedules heavy sync operations when devices are connected to power, with iCloud Photos specifically requiring power connection, WiFi, and locked screen for backup operations&lt;sup id=&#34;fnref:52&#34;&gt;&lt;a href=&#34;#fn:52&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;52&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thermal management&lt;/strong&gt; adds another layer of sync control where operations pause automatically when devices overheat. System-level thermal protection takes priority over sync completion, and users report that sync issues can persist even after cooling if the thermal event triggered system resource reallocation.&lt;/p&gt;
&lt;h2 id=&#34;background-app-refresh-fundamentally-enables-sync-functionality&#34;&gt;Background app refresh fundamentally enables sync functionality&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Background execution architecture&lt;/strong&gt; through BGTaskScheduler provides the foundation for non-foreground sync operations. The system grants limited execution time with tasks running when iOS determines optimal conditions exist: device charging, stable WiFi, learned usage patterns, and available system resources&lt;sup id=&#34;fnref:53&#34;&gt;&lt;a href=&#34;#fn:53&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;53&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:54&#34;&gt;&lt;a href=&#34;#fn:54&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;54&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:55&#34;&gt;&lt;a href=&#34;#fn:55&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;55&lt;/a&gt;&lt;/sup&gt;. Machine learning algorithms determine which apps deserve background execution time, with new devices requiring iOS to &amp;ldquo;relearn&amp;rdquo; app usage patterns&lt;sup id=&#34;fnref:56&#34;&gt;&lt;a href=&#34;#fn:56&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;56&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;App-specific background sync behavior&lt;/strong&gt; varies significantly between foreground and background states. Active apps can immediately respond to file changes and trigger downloads, while backgrounded apps rely on silent push notifications and Background App Refresh scheduling&lt;sup id=&#34;fnref:57&#34;&gt;&lt;a href=&#34;#fn:57&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;57&lt;/a&gt;&lt;/sup&gt;. Suspended apps cannot perform any sync operations, and force-quit apps will not receive background wake-ups at all&lt;sup id=&#34;fnref:58&#34;&gt;&lt;a href=&#34;#fn:58&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;58&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Background sync limitations&lt;/strong&gt; create user experience challenges where sync can appear unreliable or delayed. iOS provides &amp;ldquo;opportunistic&amp;rdquo; scheduling rather than guaranteed execution, and background tasks are treated as &amp;ldquo;low priority&amp;rdquo; with delivery not guaranteed&lt;sup id=&#34;fnref:59&#34;&gt;&lt;a href=&#34;#fn:59&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;59&lt;/a&gt;&lt;/sup&gt;. Some apps implement &amp;ldquo;Incremental Sync&amp;rdquo; strategies to be more energy-efficient within these constraints.&lt;/p&gt;
&lt;h2 id=&#34;network-connectivity-creates-distinct-behavioral-patterns&#34;&gt;Network connectivity creates distinct behavioral patterns&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;WiFi versus cellular behavior differences&lt;/strong&gt; extend beyond data usage to sync reliability and speed. WiFi connections enable full-featured sync with immediate file downloads and uploads, while cellular connections often experience partial sync where uploads succeed but downloads fail. Users report that toggling between airplane mode and cellular can sometimes restart stalled uploads, suggesting iOS manages cellular sync more conservatively.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;VPN and network security impacts&lt;/strong&gt; create additional sync complications. Some VPN configurations block iCloud traffic entirely, and network security applications may interfere with sync operations&lt;sup id=&#34;fnref:60&#34;&gt;&lt;a href=&#34;#fn:60&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;60&lt;/a&gt;&lt;/sup&gt;. Enterprise MDM profiles often include restrictions that disable cloud sync&lt;sup id=&#34;fnref:61&#34;&gt;&lt;a href=&#34;#fn:61&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;61&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:62&#34;&gt;&lt;a href=&#34;#fn:62&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;62&lt;/a&gt;&lt;/sup&gt;, and corporate firewalls can selectively block iCloud synchronization traffic.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Network transition handling&lt;/strong&gt; reveals system sophistication in managing connectivity changes. iOS automatically pauses sync during poor network conditions and resumes when connectivity improves. The system displays &amp;ldquo;Poor Network Connection&amp;rdquo; status messages and implements intelligent retry algorithms that avoid overwhelming weak connections&lt;sup id=&#34;fnref:63&#34;&gt;&lt;a href=&#34;#fn:63&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;63&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2 id=&#34;developer-documentation-reveals-architectural-constraints&#34;&gt;Developer documentation reveals architectural constraints&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Apple&amp;rsquo;s official technical documentation&lt;/strong&gt; emphasizes that iCloud Drive operates as a &lt;strong&gt;system-managed service&lt;/strong&gt; rather than application-controlled sync. WWDC sessions explicitly state &amp;ldquo;the system decides when to synchronize data&amp;rdquo; and &amp;ldquo;there is no API for app developers to force an iCloud Drive synchronization.&amp;quot;&lt;sup id=&#34;fnref:64&#34;&gt;&lt;a href=&#34;#fn:64&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;64&lt;/a&gt;&lt;/sup&gt; This architectural decision prioritizes overall device performance over individual app sync requirements.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;File coordination requirements&lt;/strong&gt; mandate that all iCloud operations use NSFileCoordinator objects and NSFilePresenter protocols. Apple&amp;rsquo;s Technical Note TN3162 reveals that CloudKit throttles applications when request rates are too high, with 30-second minimum intervals between rapid operations&lt;sup id=&#34;fnref:65&#34;&gt;&lt;a href=&#34;#fn:65&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;65&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:66&#34;&gt;&lt;a href=&#34;#fn:66&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;66&lt;/a&gt;&lt;/sup&gt;. These constraints protect system resources but create complexity for developers building sync-dependent applications.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Conflict resolution frameworks&lt;/strong&gt; provide automatic handling for document-based apps but require custom implementation for file-based sync. Apple mandates that apps resolve conflicts &amp;ldquo;quietly whenever possible&amp;rdquo; and only prompt users when automatic resolution isn&amp;rsquo;t feasible&lt;sup id=&#34;fnref:67&#34;&gt;&lt;a href=&#34;#fn:67&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;67&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:68&#34;&gt;&lt;a href=&#34;#fn:68&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;68&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:69&#34;&gt;&lt;a href=&#34;#fn:69&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;69&lt;/a&gt;&lt;/sup&gt;. The system provides NSFileVersion frameworks for conflict detection but requires app-level logic for resolution&lt;sup id=&#34;fnref:70&#34;&gt;&lt;a href=&#34;#fn:70&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;70&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2 id=&#34;common-sync-issues-follow-predictable-patterns&#34;&gt;Common sync issues follow predictable patterns&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Most frequent problems&lt;/strong&gt; include &amp;ldquo;Syncing with iCloud Paused&amp;rdquo; errors&lt;sup id=&#34;fnref:71&#34;&gt;&lt;a href=&#34;#fn:71&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;71&lt;/a&gt;&lt;/sup&gt;, files stuck &amp;ldquo;Waiting to Upload/Download,&amp;quot;&lt;sup id=&#34;fnref:72&#34;&gt;&lt;a href=&#34;#fn:72&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;72&lt;/a&gt;&lt;/sup&gt; partial sync where some files sync while others remain pending, and &amp;ldquo;Zero KB of XGB&amp;rdquo; upload progress displays&lt;sup id=&#34;fnref:73&#34;&gt;&lt;a href=&#34;#fn:73&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;73&lt;/a&gt;&lt;/sup&gt;. Users also report missing files across devices, duplicate files with number suffixes during conflicts, and grayed-out files with exclamation mark cloud icons&lt;sup id=&#34;fnref:74&#34;&gt;&lt;a href=&#34;#fn:74&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;74&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:75&#34;&gt;&lt;a href=&#34;#fn:75&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;75&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:76&#34;&gt;&lt;a href=&#34;#fn:76&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;76&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Diagnostic approaches&lt;/strong&gt; range from basic connectivity checks to advanced terminal commands on macOS. Users can check sync status in Photos app status messages, monitor iCloud storage usage, verify app-specific sync settings, and test with small files to verify basic functionality. Mac power users employ terminal commands like &lt;code&gt;brctl log -w --shorten&lt;/code&gt; for real-time sync monitoring and &lt;code&gt;brctl status&lt;/code&gt; for container sync status&lt;sup id=&#34;fnref:77&#34;&gt;&lt;a href=&#34;#fn:77&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;77&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:78&#34;&gt;&lt;a href=&#34;#fn:78&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;78&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:79&#34;&gt;&lt;a href=&#34;#fn:79&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;79&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Recovery strategies&lt;/strong&gt; include both official Apple solutions and community-developed workarounds. Official methods involve device restarts, iCloud Drive setting toggles, and complete iCloud account refresh&lt;sup id=&#34;fnref:80&#34;&gt;&lt;a href=&#34;#fn:80&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;80&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:81&#34;&gt;&lt;a href=&#34;#fn:81&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;81&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:82&#34;&gt;&lt;a href=&#34;#fn:82&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;82&lt;/a&gt;&lt;/sup&gt;. Community solutions include VPN cycling, router restarts, time zone changes, and systematic network cycling routines&lt;sup id=&#34;fnref:83&#34;&gt;&lt;a href=&#34;#fn:83&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;83&lt;/a&gt;&lt;/sup&gt;. Advanced users employ mass file download scripts and automated sync health checks using command-line tools&lt;sup id=&#34;fnref:84&#34;&gt;&lt;a href=&#34;#fn:84&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;84&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:85&#34;&gt;&lt;a href=&#34;#fn:85&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;85&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2 id=&#34;third-party-app-interaction-reveals-system-limitations&#34;&gt;Third-party app interaction reveals system limitations&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Apps like Obsidian face inherent challenges&lt;/strong&gt; working within iOS sync constraints. The vault-based file structure requires reliable bidirectional sync, but iCloud Drive&amp;rsquo;s system-controlled timing creates user experience issues where edits made on iOS devices don&amp;rsquo;t propagate reliably to other platforms&lt;sup id=&#34;fnref:86&#34;&gt;&lt;a href=&#34;#fn:86&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;86&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:87&#34;&gt;&lt;a href=&#34;#fn:87&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;87&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:88&#34;&gt;&lt;a href=&#34;#fn:88&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;88&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:89&#34;&gt;&lt;a href=&#34;#fn:89&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;89&lt;/a&gt;&lt;/sup&gt;. Users frequently report directional sync failures and recommend keeping apps in foreground during critical sync operations.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Developer alternatives&lt;/strong&gt; often include migrating away from iCloud Drive toward more predictable sync solutions. Many developers prefer Dropbox for its reliability and traditional file/folder approach, while others migrate to CloudKit for better control over structured data&lt;sup id=&#34;fnref:90&#34;&gt;&lt;a href=&#34;#fn:90&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;90&lt;/a&gt;&lt;/sup&gt;. Third-party sync solutions like Simperium offer more predictable behavior but require custom infrastructure.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Integration best practices&lt;/strong&gt; that emerge from developer experiences include designing UIs to gracefully handle sync delays and failures, providing manual sync triggers for user-initiated operations, implementing proper state restoration for interrupted sync processes, and educating users about iOS sync limitations and optimal usage patterns&lt;sup id=&#34;fnref:91&#34;&gt;&lt;a href=&#34;#fn:91&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;91&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&#34;fnref:92&#34;&gt;&lt;a href=&#34;#fn:92&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;92&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;iCloud Drive synchronization on iOS represents a sophisticated system-managed approach that prioritizes device performance, battery life, and user experience over application-controlled real-time sync. While this creates powerful integration capabilities within Apple&amp;rsquo;s ecosystem, it fundamentally changes how developers and users must approach cloud synchronization.&lt;/p&gt;
&lt;p&gt;The key insight is that &lt;strong&gt;iOS treats sync as a system service rather than an application feature&lt;/strong&gt;, implementing intelligent scheduling, resource management, and conflict prevention that operates beyond direct application control. This approach succeeds in protecting device resources and providing generally reliable sync for most users, but creates significant challenges for applications requiring predictable, real-time synchronization behavior.&lt;/p&gt;
&lt;p&gt;For users of apps like Obsidian, understanding these system limitations helps set appropriate expectations and develop workflows that work within iOS constraints rather than against them. The future of iOS sync will likely continue emphasizing system intelligence over application control, making adaptation to these patterns essential for both developers and users relying on iCloud Drive synchronization.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://forums.developer.apple.com/forums/thread/771643&#34;&gt;Apple Developer Forums - Develop a piece of code to force iCloud Drive sync&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/swiftdata/syncing-model-data-across-a-persons-devices&#34;&gt;Apple Developer - Syncing model data across a person&amp;rsquo;s devices&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://www.snow.dog/blog/how-to-manage-background-tasks-with-the-task-scheduler-in-ios-13&#34;&gt;Snowdog - How to manage background tasks with the Task Scheduler in iOS 13?&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/iCloud/iCloud.html&#34;&gt;Apple Developer - iCloud File Management&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:5&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/forums/thread/770908&#34;&gt;Apple Developer Forums - CloudKit error - CKErrorRequestRat&amp;hellip;&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:5&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:6&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/library/archive/technotes/tn2336/_index.html&#34;&gt;Apple Developer - Technical Note TN2336: Handling version conflicts in the iCloud environment&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:6&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:7&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://www.snow.dog/blog/how-to-manage-background-tasks-with-the-task-scheduler-in-ios-13&#34;&gt;Snowdog - How to manage background tasks with the Task Scheduler in iOS 13?&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:7&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:8&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://www.objc.io/issues/10-syncing-data/icloud-document-store/&#34;&gt;objc.io - Mastering the iCloud Document Store&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:8&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:9&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://forums.developer.apple.com/forums/thread/756315&#34;&gt;Apple Developer Forums - CloudKit sync refresh problem when&amp;hellip;&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:9&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:10&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://support.apple.com/en-us/102543&#34;&gt;Apple Support - If your iCloud Contacts, Calendars, or Reminders won&amp;rsquo;t sync&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:10&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:11&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://www.computerworld.com/article/1367384/how-to-fix-icloud-sync-in-seconds.html&#34;&gt;Computerworld - How to fix iCloud sync in seconds&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:11&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:12&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://dueapp.zendesk.com/hc/en-us/articles/204235325-Background-sync-not-working&#34;&gt;Due App Support - Background sync not working&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:12&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:13&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://www.snow.dog/blog/how-to-manage-background-tasks-with-the-task-scheduler-in-ios-13&#34;&gt;Snowdog - How to manage background tasks with the Task Scheduler in iOS 13?&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:13&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:14&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://dueapp.zendesk.com/hc/en-us/articles/204235325-Background-sync-not-working&#34;&gt;Due App Support - Background sync not working&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:14&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:15&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://news.ycombinator.com/item?id=39571726&#34;&gt;Hacker News - Yes, the app does iOS background sync&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:15&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:16&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/forums/thread/772283&#34;&gt;Apple Developer Forums - Collaboration of iCloud Drive docu&amp;hellip;&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:16&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:17&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://forums.developer.apple.com/forums/thread/771643&#34;&gt;Apple Developer Forums - Develop a piece of code to force iCloud Drive sync&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:17&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:18&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://www.andyibanez.com/posts/modern-background-tasks-ios13/&#34;&gt;Andy Ibanez - Modern Backgrounds Tasks in iOS 13&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:18&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:19&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://ma-kobol-public-prod.apple.com/documentation/BackgroundTasks/BGTaskScheduler&#34;&gt;Apple Developer - BGTaskScheduler&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:19&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:20&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://stackoverflow.com/questions/73126077/bgtaskscheduler-is-it-possible-to-schedule-a-background-task-inside-a-backgroun&#34;&gt;Stack Overflow - BGTaskScheduler: Is it possible to schedule a background task inside a background task?&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:20&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:21&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/forums/thread/766919&#34;&gt;Apple Developer Forums - IOS Development - Background sync&amp;hellip;&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:21&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:22&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://stackoverflow.com/questions/73126077/bgtaskscheduler-is-it-possible-to-schedule-a-background-task-inside-a-backgroun&#34;&gt;Stack Overflow - BGTaskScheduler: Is it possible to schedule a background task inside a background task?&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:22&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:23&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://forum.obsidian.md/t/obsidian-wont-sync-via-icloud/58346&#34;&gt;Obsidian Forum - Obsidian won&amp;rsquo;t sync via icloud&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:23&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:24&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://forum.obsidian.md/t/icloud-drive-ios-and-macos-sync-inconsistencies-serious/34542&#34;&gt;Obsidian Forum - iCloud Drive iOS and MacOS Sync Inconsistencies - Serious&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:24&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:25&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://forum.obsidian.md/t/icloud-drive-ios-and-macos-sync-inconsistencies-serious/34542&#34;&gt;Obsidian Forum - iCloud Drive iOS and MacOS Sync Inconsistencies - Serious&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:25&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:26&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://support.gingerlabs.com/hc/en-us/articles/205688797-Troubleshooting-iCloud-Sync&#34;&gt;Notability - Troubleshooting iCloud Sync&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:26&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:27&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://www.objc.io/issues/10-syncing-data/icloud-document-store/&#34;&gt;objc.io - Mastering the iCloud Document Store&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:27&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:28&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://forum.obsidian.md/t/understanding-icloud-sync-issues/78186&#34;&gt;Obsidian Forum - Understanding iCloud Sync issues&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:28&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:29&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/library/archive/technotes/tn2336/_index.html&#34;&gt;Apple Developer - Technical Note TN2336: Handling version conflicts in the iCloud environment&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:29&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:30&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://discussions.apple.com/thread/8644550&#34;&gt;Apple Community - Cellular vs WiFi causing the iCloud sync&amp;hellip;&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:30&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:31&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://discussions.apple.com/thread/254081595&#34;&gt;Apple Community - iCloud Drive on cellular data network&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:31&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:32&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://support.apple.com/en-us/102433&#34;&gt;Apple Support - Use Low Data Mode on your iPhone and iPad&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:32&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:33&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://www.eskimo.travel/en/blog/what-is-low-data-mode-iphone&#34;&gt;Eskimo - What is Low Data Mode on iPhone and How to Turn It Off&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:33&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:34&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://support.apple.com/en-us/101559&#34;&gt;Apple Support - If your iCloud Photos are not syncing&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:34&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:35&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://support.apple.com/en-us/101559&#34;&gt;Apple Support - If your iCloud Photos are not syncing&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:35&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:36&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://support.apple.com/en-us/101559&#34;&gt;Apple Support - If your iCloud Photos are not syncing&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:36&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:37&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://support.gingerlabs.com/hc/en-us/articles/205688797-Troubleshooting-iCloud-Sync&#34;&gt;Notability - Troubleshooting iCloud Sync&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:37&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:38&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://www.eskimo.travel/en/blog/what-is-low-data-mode-iphone&#34;&gt;Eskimo - What is Low Data Mode on iPhone and How to Turn It Off&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:38&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:39&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://www.gbyte.com/blog/syncing-with-icloud-paused&#34;&gt;Gbyte - Syncing with iCloud Paused: Complete Guide to Fix It&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:39&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:40&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://support.apple.com/en-us/101559&#34;&gt;Apple Support - If your iCloud Photos are not syncing&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:40&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:41&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://support.apple.com/en-us/101559&#34;&gt;Apple Support - If your iCloud Photos are not syncing&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:41&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:42&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://support.apple.com/guide/mac-help/check-icloud-drive-file-folder-status-mac-mchlc994344b/mac&#34;&gt;Apple Support - Check your iCloud Drive file and folder status on Mac&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:42&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:43&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://support.apple.com/en-us/101559&#34;&gt;Apple Support - If your iCloud Photos are not syncing&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:43&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:44&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://support.apple.com/en-us/101559&#34;&gt;Apple Support - If your iCloud Photos are not syncing&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:44&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:45&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://support.apple.com/guide/mac-help/work-with-folders-and-files-in-icloud-drive-mchl1a02d711/mac&#34;&gt;Apple Support - Work with folders and files in iCloud Drive&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:45&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:46&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://support.apple.com/en-sa/guide/mac-help/mchl1a02d711/mac&#34;&gt;Apple Support - Work with folders and files in iCloud Drive (SA)&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:46&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:47&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://dueapp.zendesk.com/hc/en-us/articles/204235325-Background-sync-not-working&#34;&gt;Due App Support - Background sync not working&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:47&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:48&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://support.apple.com/guide/icloud/set-up-icloud-drive-mm203b05aec8/icloud&#34;&gt;Apple Support - Set up iCloud Drive on all your devices&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:48&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:49&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://apple.stackexchange.com/questions/374118/on-ios-is-there-any-way-to-see-what-the-documents-sync-system-service-is-us&#34;&gt;Ask Different - On iOS, is there any way to see what the &amp;ldquo;Documents &amp;amp; Sync&amp;rdquo; system service is using cellular data for?&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:49&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:50&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://discussions.apple.com/thread/8278754&#34;&gt;Apple Community - Why Documents &amp;amp; Sync use my Cellular Data&amp;hellip;&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:50&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:51&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://support.apple.com/en-us/101559&#34;&gt;Apple Support - If your iCloud Photos are not syncing&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:51&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:52&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://www.macworld.com/article/215122/icloud-vs-wi-fi-sync-which-does-what.html&#34;&gt;Macworld - iCloud vs. Wi-Fi Sync: Which does what?&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:52&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:53&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://www.andyibanez.com/posts/modern-background-tasks-ios13/&#34;&gt;Andy Ibanez - Modern Backgrounds Tasks in iOS 13&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:53&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:54&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://stackoverflow.com/questions/73126077/bgtaskscheduler-is-it-possible-to-schedule-a-background-task-inside-a-backgroun&#34;&gt;Stack Overflow - BGTaskScheduler: Is it possible to schedule a background task inside a background task?&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:54&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:55&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://www.snow.dog/blog/how-to-manage-background-tasks-with-the-task-scheduler-in-ios-13&#34;&gt;Snowdog - How to manage background tasks with the Task Scheduler in iOS 13?&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:55&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:56&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://dueapp.zendesk.com/hc/en-us/articles/204235325-Background-sync-not-working&#34;&gt;Due App Support - Background sync not working&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:56&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:57&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://dueapp.zendesk.com/hc/en-us/articles/204235325-Background-sync-not-working&#34;&gt;Due App Support - Background sync not working&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:57&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:58&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://dueapp.zendesk.com/hc/en-us/articles/204235325-Background-sync-not-working&#34;&gt;Due App Support - Background sync not working&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:58&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:59&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://dueapp.zendesk.com/hc/en-us/articles/204235325-Background-sync-not-working&#34;&gt;Due App Support - Background sync not working&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:59&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:60&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://forums.macrumors.com/threads/icloud-sync-photos-on-battery-possible.2375035/&#34;&gt;MacRumors Forums - iCloud sync photos on battery (possible?)&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:60&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:61&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://support.goodnotes.com/hc/en-us/articles/7352796404495-iCloud-Sync-issues&#34;&gt;Goodnotes Support - iCloud Sync issues&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:61&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:62&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://support.gingerlabs.com/hc/en-us/articles/205688797-Troubleshooting-iCloud-Sync&#34;&gt;Notability - Troubleshooting iCloud Sync&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:62&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:63&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://techcommunity.microsoft.com/blog/intunecustomersuccess/changes-to-applications%E2%80%99-backup-and-restore-behavior-on-iosipados-and-macos-devi/3692064&#34;&gt;Microsoft Community Hub - Changes to applications&#39; backup and restore behavior on iOS/iPadOS and macOS devices&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:63&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:64&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2021/10182/&#34;&gt;Apple Developer - Sync files to the cloud with FileProvider on macOS - WWDC21&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:64&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:65&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/documentation/technotes/tn3162-understanding-cloudkit-throttles&#34;&gt;Apple Developer - TN3162: Understanding CloudKit throttles&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:65&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:66&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://forums.developer.apple.com/forums/thread/758198&#34;&gt;Apple Developer Forums - CloudKit user &amp;lsquo;throttling&amp;rsquo;&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:66&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:67&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/library/archive/technotes/tn2336/_index.html&#34;&gt;Apple Developer - Technical Note TN2336: Handling version conflicts in the iCloud environment&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:67&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:68&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/library/archive/technotes/tn2336/_index.html&#34;&gt;Apple Developer - Technical Note TN2336: Handling version conflicts in the iCloud environment&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:68&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:69&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/library/archive/technotes/tn2336/_index.html&#34;&gt;Apple Developer - Technical Note TN2336: Handling version conflicts in the iCloud environment&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:69&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:70&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/iCloud/iCloud.html&#34;&gt;Apple Developer - iCloud File Management&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:70&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:71&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://www.airdroid.com/file-transfer/syncing-with-icloud-paused/&#34;&gt;AirDroid - Fix &amp;ldquo;Syncing With iCloud Paused&amp;rdquo; Error Within Minutes&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:71&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:72&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://discussions.apple.com/thread/251061918&#34;&gt;Apple Community - iCloud Files Sync Stuck&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:72&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:73&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://discussions.apple.com/thread/251009341&#34;&gt;Apple Community - iCloud sync stuck?&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:73&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:74&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://support.apple.com/en-us/101559&#34;&gt;Apple Support - If your iCloud Photos are not syncing&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:74&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:75&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://www.computerworld.com/article/1367384/how-to-fix-icloud-sync-in-seconds.html&#34;&gt;Computerworld - How to fix iCloud sync in seconds&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:75&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:76&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://support.gingerlabs.com/hc/en-us/articles/205688797-Troubleshooting-iCloud-Sync&#34;&gt;Notability - Troubleshooting iCloud Sync&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:76&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:77&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://wesleydegroot.nl/blog/iCloud-drive-tips-and-tricks&#34;&gt;Wesley de Groot - iCloud Drive Tips &amp;amp; Tricks&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:77&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:78&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://wesleydegroot.nl/blog/iCloud-drive-tips-and-tricks&#34;&gt;Wesley de Groot - iCloud Drive Tips &amp;amp; Tricks&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:78&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:79&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://apple.stackexchange.com/questions/349082/icloud-sync-activity-log&#34;&gt;Ask Different - iCloud Sync activity log&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:79&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:80&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://support.apple.com/en-us/102543&#34;&gt;Apple Support - If your iCloud Contacts, Calendars, or Reminders won&amp;rsquo;t sync&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:80&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:81&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://www.computerworld.com/article/1367384/how-to-fix-icloud-sync-in-seconds.html&#34;&gt;Computerworld - How to fix iCloud sync in seconds&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:81&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:82&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://superuser.com/questions/1045791/icloud-drive-sync-stuck&#34;&gt;Super User - icloud drive sync stuck&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:82&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:83&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://discussions.apple.com/thread/255573626&#34;&gt;Apple Community - iCloud sync and update very, very slow&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:83&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:84&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://architchandra.com/articles/a-side-effect-of-storing-a-git-repository-in-icloud-drive&#34;&gt;Archit Chandra - A Side Effect of Storing a Git Repository in iCloud Drive&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:84&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:85&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://forums.developer.apple.com/forums/thread/765948&#34;&gt;Apple Developer Forums - SwiftData iCloud sync breaks after&amp;hellip;&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:85&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:86&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://forum.obsidian.md/t/obsidian-wont-sync-via-icloud/58346&#34;&gt;Obsidian Forum - Obsidian won&amp;rsquo;t sync via icloud&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:86&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:87&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://forum.obsidian.md/t/icloud-drive-ios-and-macos-sync-inconsistencies-serious/34542&#34;&gt;Obsidian Forum - iCloud Drive iOS and MacOS Sync Inconsistencies - Serious&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:87&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:88&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://forum.obsidian.md/t/icloud-drive-ios-and-macos-sync-inconsistencies-serious/34542&#34;&gt;Obsidian Forum - iCloud Drive iOS and MacOS Sync Inconsistencies - Serious&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:88&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:89&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://forum.obsidian.md/t/sync-solutions/98495&#34;&gt;Obsidian Forum - Sync solutions&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:89&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:90&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://support.gingerlabs.com/hc/en-us/articles/205688797-Troubleshooting-iCloud-Sync&#34;&gt;Notability - Troubleshooting iCloud Sync&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:90&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:91&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://forums.developer.apple.com/forums/thread/765948&#34;&gt;Apple Developer Forums - SwiftData iCloud sync breaks after&amp;hellip;&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:91&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:92&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://forums.developer.apple.com/forums/thread/765948&#34;&gt;Apple Developer Forums - SwiftData iCloud sync breaks after&amp;hellip;&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:92&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
      <source:markdown>Today I was pondering a feature idea for my macOS/iOS app [Actions For Obsidian](https://actions.work/actions-for-obsidian). That idea is loosely related to iCloud Drive. But ever since AFO’s release a few years back, I have received dozens of support requests from people who ran into issues while attempting to use iCloud Drive as a means of synchronizing their [Obsidian](https://obsidian.md) vaults between their devices.

Usually my one-word answer to these questions is _&#34;Don&#39;t&#34;_, followed by a link to a FAQ entry that I wrote a while back: [_&#34;Can I use iCloud Sync with Obsidian and Actions for Obsidian?&#34;_](https://docs.actions.work/actions-for-obsidian/faqs/#can-i-use-icloud-sync-with-obsidian-and-actions-for-obsidian) (Spoiler: Yes, you can, but it’ll be painful at one point or another… or several.)

I had a pretty good mental model of iCloud Drive&#39;s behavior built up already, but as I was thinking about that aforementioned feature idea, I figured that Claude Opus 4.1&#39;s &#34;research mode&#34; might speed up the process a bit. So I tasked it to dive deep into researching how iCloud Drive synchronization works, particularly focusing on iOS behavior and specific scenarios with Obsidian vaults and the &#34;Keep Downloaded&#34; feature.

The resulting doc is what you&#39;ll find below. Enjoy. #sharingIsCaring

---

## iOS iCloud Drive Synchronization Deep Dive

**Apple&#39;s iCloud Drive synchronization on iOS operates as a system-controlled process that prioritizes device performance and battery life over real-time sync**, fundamentally changing how third-party apps like Obsidian must approach data synchronization. Unlike traditional file sync services, iOS maintains strict control over when, how, and under what conditions synchronization occurs, creating both powerful integration opportunities and significant technical challenges for developers and users.

The core architectural principle revealed through Apple&#39;s official documentation is that **applications cannot force synchronization**[^1] - the iOS system decides all sync timing based on complex algorithms that consider network conditions, battery state, thermal management, and learned user behavior patterns[^2][^3]. This system-first approach means that apps like Obsidian must work within iOS&#39;s scheduling constraints rather than implementing direct sync control.

## System-controlled sync architecture governs all operations

Apple&#39;s iCloud Drive uses a sophisticated **two-stage synchronization process** where files move from app containers to system-managed directories, then propagate to iCloud servers &#34;as soon as possible&#34;[^4] - but timing remains entirely system-controlled. All file operations must use `NSFileCoordinator` objects to prevent conflicts between applications and the sync daemon, creating a coordination layer that acts as a locking mechanism[^5][^6][^7].

The system implements **intelligent throttling mechanisms** designed to protect both device resources and server infrastructure. CloudKit throttles requests when it determines the request rate is too high, with 30-second minimum intervals between rapid operations[^5][^6][^7]. This throttling serves as protection against overwhelming system resources and maintains server stability.

**File coordination requirements** create significant technical complexity for developers. Every file access requires coordination to prevent race conditions, and file presenters are &#34;very expensive objects&#34; requiring extensive inter-process communication[^8]. Context switches occur between the reading process, presenting process, and file coordination daemon, risking depletion of system resources if too many presenters are registered.

## Synchronization triggers operate on multiple system levels

**Automatic triggers** include app foreground events, network state changes, system resource availability, and device wake cycles. When an app comes to the foreground, especially on macOS, sync often triggers immediately[^9]. Network connectivity changes - particularly switching from cellular to WiFi - initiate sync attempts. The system also monitors storage conditions, pausing sync when iCloud storage is full or device storage is constrained[^10][^11].

**Manual sync triggers** are limited but exist through specific user actions. Users can force sync by toggling iCloud Drive settings off and on, signing out and back into iCloud accounts, or using app-specific refresh mechanisms like pull-to-refresh in Contacts and Calendar apps[^10][^11]. However, these methods don&#39;t guarantee immediate sync - they merely request that the system prioritize sync operations.

Background app refresh plays a **critical enabling role** for sync operations. Apps must be granted Background App Refresh permission, and iOS uses machine learning to determine optimal sync timing based on user behavior patterns, available system resources, network quality, battery level, and time-of-day patterns[^12][^13][^14]. The system can take &#34;seven days for Apple&#39;s on-device ML to pick up that the user really wants to use the app,&#34;[^15] affecting sync frequency during this learning period.

## Timing patterns follow intelligent resource management

**Synchronization frequency varies dramatically** based on system conditions rather than following fixed intervals. Apple&#39;s documentation explicitly states that &#34;CloudKit synchronization isn&#39;t real time&#34; and timing is &#34;as-designed to better balance the use of system resources and achieve the best overall user experience.&#34;[^16] The system implements no guaranteed timing - sync operates on an opportunistic basis when conditions are favorable[^17][^1].

**Priority scheduling** follows a clear hierarchy: foreground app operations receive highest priority, followed by critical system functions, user-initiated sync requests, scheduled background sync tasks, and finally opportunistic background sync. iOS uses BGTaskScheduler (iOS 13+) to replace legacy background fetch with more sophisticated scheduling based on device usage patterns learned over time[^18][^19][^20].

**Background execution limitations** significantly impact sync behavior. Background App Refresh provides only limited execution time - typically 30 seconds for BGAppRefreshTask and longer durations for BGProcessingTask, but only when external power is available for heavy operations[^21][^22]. Apps cannot force specific sync intervals and must work within iOS scheduling constraints where background execution is &#34;cooperative&#34; and can be terminated at any time.

## App-specific behavior creates unique integration challenges

**Obsidian&#39;s vault synchronization** exemplifies the challenges third-party apps face with iCloud Drive integration. User reports consistently describe unidirectional sync failures where &#34;creating new notes in macOS syncs immediately to iOS, but editing notes in iOS doesn&#39;t sync back to macOS.&#34;[^23][^24][^25] Files frequently get &#34;stuck uploading&#34; with cloud icons showing indefinitely, and the app lacks native conflict resolution, leading to silent overwrites when notes are edited on multiple devices while offline.

**Developer implementation challenges** stem from iCloud&#39;s low-level API requirements. Developers report that &#34;the iCloud API is too low level,&#34; requiring extensive code for basic operations with no single function for putting files into or removing them from iCloud[^26]. The asynchronous, cooperative, lock-based nature creates &#34;implications that are often not easy to grasp,&#34;[^27] leading many developers to prefer alternatives like Dropbox for reliability.

**Document-based versus file-based sync** creates different user experiences. Document-based apps using NSDocument/UIDocument protocols benefit from automatic conflict resolution, while file-based sync (like Obsidian) relies on basic iCloud Drive file synchronization without built-in conflict handling[^28]. Advanced apps must implement custom conflict resolution UIs to match user expectations[^29].

## Sync interruption patterns follow predictable system states

**Network-dependent behavior** shows strong WiFi preference with cellular serving as a heavily throttled fallback. Even with cellular enabled, iOS implements intelligent throttling where sync only occurs over cellular when WiFi hasn&#39;t been available for extended periods[^30][^31]. Low Data Mode specifically pauses iCloud sync operations[^32][^33], and users report that iCloud Drive downloads often fail over cellular connections even when uploads work[^34].

**Power management creates definitive sync boundaries**. Low Power Mode automatically pauses all iCloud sync operations when battery drops below 20% and remains paused even when the device is charged until manually disabled[^35][^36][^37]. iOS displays &#34;Optimizing Battery Power&#34; messages when pausing sync to preserve battery life, and thermal management pauses operations when devices overheat with &#34;Device Needs to Cool Down&#34; messages[^38].

**Storage conditions** create hard stops for synchronization. Sync completely halts when iCloud storage quota is exceeded, and iOS pauses sync when device storage drops below critical thresholds[^39][^40]. The system displays specific status messages including &#34;Low Data Mode,&#34; &#34;Poor Network Connection,&#34; and &#34;Device Needs to Cool Down&#34; to communicate sync pause reasons[^41].

## File prioritization follows system-managed algorithms

**&#34;Keep Downloaded&#34; versus normal cloud storage** creates two distinct sync behaviors. Files marked &#34;Keep Downloaded&#34; remain local even when storage optimization is active, while normal cloud storage uses on-demand download where files exist as placeholders until accessed[^42][^43]. The system provides visual indicators through cloud/download status icons, and users can manually set Keep Downloaded status via context menus.

**Sync prioritization algorithms** aren&#39;t fully documented by Apple, but research reveals patterns: the system prioritizes based on system resources first, then user experience considerations, data integrity requirements, and server load management. Large files are often deprioritized in favor of smaller, more critical data, and iOS may selectively sync metadata before file contents when storage is constrained.

**Background versus foreground sync behavior** creates dramatically different user experiences. Foreground sync typically works &#34;within seconds&#34; with immediate updates, while background sync can take &#34;minutes or even up to an hour&#34; depending on iOS scheduling decisions[^44]. macOS apps sync continuously while running, but iOS apps depend entirely on system wake-ups that follow learned usage patterns.

## Network and battery conditions shape sync behavior

**WiFi versus cellular sync patterns** show strong system bias toward WiFi connections. Users must explicitly enable cellular data for iCloud Drive in Settings &gt; Cellular &gt; iCloud Drive[^45][^46][^47][^48], but even with cellular enabled, iOS implements aggressive throttling. The &#34;Documents &amp; Sync&#34; system service can consume substantial cellular data (1-8GB reported cases)[^49][^50], leading iOS to discourage cellular sync through power management restrictions.

**Battery state management** creates multiple intervention points. Beyond Low Power Mode&#39;s complete sync pause, iOS implements &#34;Optimizing System Performance&#34; states that pause sync to prioritize foreground tasks[^51]. The system preferentially schedules heavy sync operations when devices are connected to power, with iCloud Photos specifically requiring power connection, WiFi, and locked screen for backup operations[^52].

**Thermal management** adds another layer of sync control where operations pause automatically when devices overheat. System-level thermal protection takes priority over sync completion, and users report that sync issues can persist even after cooling if the thermal event triggered system resource reallocation.

## Background app refresh fundamentally enables sync functionality

**Background execution architecture** through BGTaskScheduler provides the foundation for non-foreground sync operations. The system grants limited execution time with tasks running when iOS determines optimal conditions exist: device charging, stable WiFi, learned usage patterns, and available system resources[^53][^54][^55]. Machine learning algorithms determine which apps deserve background execution time, with new devices requiring iOS to &#34;relearn&#34; app usage patterns[^56].

**App-specific background sync behavior** varies significantly between foreground and background states. Active apps can immediately respond to file changes and trigger downloads, while backgrounded apps rely on silent push notifications and Background App Refresh scheduling[^57]. Suspended apps cannot perform any sync operations, and force-quit apps will not receive background wake-ups at all[^58].

**Background sync limitations** create user experience challenges where sync can appear unreliable or delayed. iOS provides &#34;opportunistic&#34; scheduling rather than guaranteed execution, and background tasks are treated as &#34;low priority&#34; with delivery not guaranteed[^59]. Some apps implement &#34;Incremental Sync&#34; strategies to be more energy-efficient within these constraints.

## Network connectivity creates distinct behavioral patterns

**WiFi versus cellular behavior differences** extend beyond data usage to sync reliability and speed. WiFi connections enable full-featured sync with immediate file downloads and uploads, while cellular connections often experience partial sync where uploads succeed but downloads fail. Users report that toggling between airplane mode and cellular can sometimes restart stalled uploads, suggesting iOS manages cellular sync more conservatively.

**VPN and network security impacts** create additional sync complications. Some VPN configurations block iCloud traffic entirely, and network security applications may interfere with sync operations[^60]. Enterprise MDM profiles often include restrictions that disable cloud sync[^61][^62], and corporate firewalls can selectively block iCloud synchronization traffic.

**Network transition handling** reveals system sophistication in managing connectivity changes. iOS automatically pauses sync during poor network conditions and resumes when connectivity improves. The system displays &#34;Poor Network Connection&#34; status messages and implements intelligent retry algorithms that avoid overwhelming weak connections[^63].

## Developer documentation reveals architectural constraints

**Apple&#39;s official technical documentation** emphasizes that iCloud Drive operates as a **system-managed service** rather than application-controlled sync. WWDC sessions explicitly state &#34;the system decides when to synchronize data&#34; and &#34;there is no API for app developers to force an iCloud Drive synchronization.&#34;[^64] This architectural decision prioritizes overall device performance over individual app sync requirements.

**File coordination requirements** mandate that all iCloud operations use NSFileCoordinator objects and NSFilePresenter protocols. Apple&#39;s Technical Note TN3162 reveals that CloudKit throttles applications when request rates are too high, with 30-second minimum intervals between rapid operations[^65][^66]. These constraints protect system resources but create complexity for developers building sync-dependent applications.

**Conflict resolution frameworks** provide automatic handling for document-based apps but require custom implementation for file-based sync. Apple mandates that apps resolve conflicts &#34;quietly whenever possible&#34; and only prompt users when automatic resolution isn&#39;t feasible[^67][^68][^69]. The system provides NSFileVersion frameworks for conflict detection but requires app-level logic for resolution[^70].

## Common sync issues follow predictable patterns

**Most frequent problems** include &#34;Syncing with iCloud Paused&#34; errors[^71], files stuck &#34;Waiting to Upload/Download,&#34;[^72] partial sync where some files sync while others remain pending, and &#34;Zero KB of XGB&#34; upload progress displays[^73]. Users also report missing files across devices, duplicate files with number suffixes during conflicts, and grayed-out files with exclamation mark cloud icons[^74][^75][^76].

**Diagnostic approaches** range from basic connectivity checks to advanced terminal commands on macOS. Users can check sync status in Photos app status messages, monitor iCloud storage usage, verify app-specific sync settings, and test with small files to verify basic functionality. Mac power users employ terminal commands like `brctl log -w --shorten` for real-time sync monitoring and `brctl status` for container sync status[^77][^78][^79].

**Recovery strategies** include both official Apple solutions and community-developed workarounds. Official methods involve device restarts, iCloud Drive setting toggles, and complete iCloud account refresh[^80][^81][^82]. Community solutions include VPN cycling, router restarts, time zone changes, and systematic network cycling routines[^83]. Advanced users employ mass file download scripts and automated sync health checks using command-line tools[^84][^85].

## Third-party app interaction reveals system limitations

**Apps like Obsidian face inherent challenges** working within iOS sync constraints. The vault-based file structure requires reliable bidirectional sync, but iCloud Drive&#39;s system-controlled timing creates user experience issues where edits made on iOS devices don&#39;t propagate reliably to other platforms[^86][^87][^88][^89]. Users frequently report directional sync failures and recommend keeping apps in foreground during critical sync operations.

**Developer alternatives** often include migrating away from iCloud Drive toward more predictable sync solutions. Many developers prefer Dropbox for its reliability and traditional file/folder approach, while others migrate to CloudKit for better control over structured data[^90]. Third-party sync solutions like Simperium offer more predictable behavior but require custom infrastructure.

**Integration best practices** that emerge from developer experiences include designing UIs to gracefully handle sync delays and failures, providing manual sync triggers for user-initiated operations, implementing proper state restoration for interrupted sync processes, and educating users about iOS sync limitations and optimal usage patterns[^91][^92].

## Conclusion

iCloud Drive synchronization on iOS represents a sophisticated system-managed approach that prioritizes device performance, battery life, and user experience over application-controlled real-time sync. While this creates powerful integration capabilities within Apple&#39;s ecosystem, it fundamentally changes how developers and users must approach cloud synchronization.

The key insight is that **iOS treats sync as a system service rather than an application feature**, implementing intelligent scheduling, resource management, and conflict prevention that operates beyond direct application control. This approach succeeds in protecting device resources and providing generally reliable sync for most users, but creates significant challenges for applications requiring predictable, real-time synchronization behavior.

For users of apps like Obsidian, understanding these system limitations helps set appropriate expectations and develop workflows that work within iOS constraints rather than against them. The future of iOS sync will likely continue emphasizing system intelligence over application control, making adaptation to these patterns essential for both developers and users relying on iCloud Drive synchronization.

[^1]: [Apple Developer Forums - Develop a piece of code to force iCloud Drive sync](https://forums.developer.apple.com/forums/thread/771643)
[^2]: [Apple Developer - Syncing model data across a person&#39;s devices](https://developer.apple.com/documentation/swiftdata/syncing-model-data-across-a-persons-devices)
[^3]: [Snowdog - How to manage background tasks with the Task Scheduler in iOS 13?](https://www.snow.dog/blog/how-to-manage-background-tasks-with-the-task-scheduler-in-ios-13)
[^4]: [Apple Developer - iCloud File Management](https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/iCloud/iCloud.html)
[^5]: [Apple Developer Forums - CloudKit error - CKErrorRequestRat...](https://developer.apple.com/forums/thread/770908)
[^6]: [Apple Developer - Technical Note TN2336: Handling version conflicts in the iCloud environment](https://developer.apple.com/library/archive/technotes/tn2336/_index.html)
[^7]: [Snowdog - How to manage background tasks with the Task Scheduler in iOS 13?](https://www.snow.dog/blog/how-to-manage-background-tasks-with-the-task-scheduler-in-ios-13)
[^8]: [objc.io - Mastering the iCloud Document Store](https://www.objc.io/issues/10-syncing-data/icloud-document-store/)
[^9]: [Apple Developer Forums - CloudKit sync refresh problem when...](https://forums.developer.apple.com/forums/thread/756315)
[^10]: [Apple Support - If your iCloud Contacts, Calendars, or Reminders won&#39;t sync](https://support.apple.com/en-us/102543)
[^11]: [Computerworld - How to fix iCloud sync in seconds](https://www.computerworld.com/article/1367384/how-to-fix-icloud-sync-in-seconds.html)
[^12]: [Due App Support - Background sync not working](https://dueapp.zendesk.com/hc/en-us/articles/204235325-Background-sync-not-working)
[^13]: [Snowdog - How to manage background tasks with the Task Scheduler in iOS 13?](https://www.snow.dog/blog/how-to-manage-background-tasks-with-the-task-scheduler-in-ios-13)
[^14]: [Due App Support - Background sync not working](https://dueapp.zendesk.com/hc/en-us/articles/204235325-Background-sync-not-working)
[^15]: [Hacker News - Yes, the app does iOS background sync](https://news.ycombinator.com/item?id=39571726)
[^16]: [Apple Developer Forums - Collaboration of iCloud Drive docu...](https://developer.apple.com/forums/thread/772283)
[^17]: [Apple Developer Forums - Develop a piece of code to force iCloud Drive sync](https://forums.developer.apple.com/forums/thread/771643)
[^18]: [Andy Ibanez - Modern Backgrounds Tasks in iOS 13](https://www.andyibanez.com/posts/modern-background-tasks-ios13/)
[^19]: [Apple Developer - BGTaskScheduler](https://ma-kobol-public-prod.apple.com/documentation/BackgroundTasks/BGTaskScheduler)
[^20]: [Stack Overflow - BGTaskScheduler: Is it possible to schedule a background task inside a background task?](https://stackoverflow.com/questions/73126077/bgtaskscheduler-is-it-possible-to-schedule-a-background-task-inside-a-backgroun)
[^21]: [Apple Developer Forums - IOS Development - Background sync...](https://developer.apple.com/forums/thread/766919)
[^22]: [Stack Overflow - BGTaskScheduler: Is it possible to schedule a background task inside a background task?](https://stackoverflow.com/questions/73126077/bgtaskscheduler-is-it-possible-to-schedule-a-background-task-inside-a-backgroun)
[^23]: [Obsidian Forum - Obsidian won&#39;t sync via icloud](https://forum.obsidian.md/t/obsidian-wont-sync-via-icloud/58346)
[^24]: [Obsidian Forum - iCloud Drive iOS and MacOS Sync Inconsistencies - Serious](https://forum.obsidian.md/t/icloud-drive-ios-and-macos-sync-inconsistencies-serious/34542)
[^25]: [Obsidian Forum - iCloud Drive iOS and MacOS Sync Inconsistencies - Serious](https://forum.obsidian.md/t/icloud-drive-ios-and-macos-sync-inconsistencies-serious/34542)
[^26]: [Notability - Troubleshooting iCloud Sync](https://support.gingerlabs.com/hc/en-us/articles/205688797-Troubleshooting-iCloud-Sync)
[^27]: [objc.io - Mastering the iCloud Document Store](https://www.objc.io/issues/10-syncing-data/icloud-document-store/)
[^28]: [Obsidian Forum - Understanding iCloud Sync issues](https://forum.obsidian.md/t/understanding-icloud-sync-issues/78186)
[^29]: [Apple Developer - Technical Note TN2336: Handling version conflicts in the iCloud environment](https://developer.apple.com/library/archive/technotes/tn2336/_index.html)
[^30]: [Apple Community - Cellular vs WiFi causing the iCloud sync...](https://discussions.apple.com/thread/8644550)
[^31]: [Apple Community - iCloud Drive on cellular data network](https://discussions.apple.com/thread/254081595)
[^32]: [Apple Support - Use Low Data Mode on your iPhone and iPad](https://support.apple.com/en-us/102433)
[^33]: [Eskimo - What is Low Data Mode on iPhone and How to Turn It Off](https://www.eskimo.travel/en/blog/what-is-low-data-mode-iphone)
[^34]: [Apple Support - If your iCloud Photos are not syncing](https://support.apple.com/en-us/101559)
[^35]: [Apple Support - If your iCloud Photos are not syncing](https://support.apple.com/en-us/101559)
[^36]: [Apple Support - If your iCloud Photos are not syncing](https://support.apple.com/en-us/101559)
[^37]: [Notability - Troubleshooting iCloud Sync](https://support.gingerlabs.com/hc/en-us/articles/205688797-Troubleshooting-iCloud-Sync)
[^38]: [Eskimo - What is Low Data Mode on iPhone and How to Turn It Off](https://www.eskimo.travel/en/blog/what-is-low-data-mode-iphone)
[^39]: [Gbyte - Syncing with iCloud Paused: Complete Guide to Fix It](https://www.gbyte.com/blog/syncing-with-icloud-paused)
[^40]: [Apple Support - If your iCloud Photos are not syncing](https://support.apple.com/en-us/101559)
[^41]: [Apple Support - If your iCloud Photos are not syncing](https://support.apple.com/en-us/101559)
[^42]: [Apple Support - Check your iCloud Drive file and folder status on Mac](https://support.apple.com/guide/mac-help/check-icloud-drive-file-folder-status-mac-mchlc994344b/mac)
[^43]: [Apple Support - If your iCloud Photos are not syncing](https://support.apple.com/en-us/101559)
[^44]: [Apple Support - If your iCloud Photos are not syncing](https://support.apple.com/en-us/101559)
[^45]: [Apple Support - Work with folders and files in iCloud Drive](https://support.apple.com/guide/mac-help/work-with-folders-and-files-in-icloud-drive-mchl1a02d711/mac)
[^46]: [Apple Support - Work with folders and files in iCloud Drive (SA)](https://support.apple.com/en-sa/guide/mac-help/mchl1a02d711/mac)
[^47]: [Due App Support - Background sync not working](https://dueapp.zendesk.com/hc/en-us/articles/204235325-Background-sync-not-working)
[^48]: [Apple Support - Set up iCloud Drive on all your devices](https://support.apple.com/guide/icloud/set-up-icloud-drive-mm203b05aec8/icloud)
[^49]: [Ask Different - On iOS, is there any way to see what the &#34;Documents &amp; Sync&#34; system service is using cellular data for?](https://apple.stackexchange.com/questions/374118/on-ios-is-there-any-way-to-see-what-the-documents-sync-system-service-is-us)
[^50]: [Apple Community - Why Documents &amp; Sync use my Cellular Data...](https://discussions.apple.com/thread/8278754)
[^51]: [Apple Support - If your iCloud Photos are not syncing](https://support.apple.com/en-us/101559)
[^52]: [Macworld - iCloud vs. Wi-Fi Sync: Which does what?](https://www.macworld.com/article/215122/icloud-vs-wi-fi-sync-which-does-what.html)
[^53]: [Andy Ibanez - Modern Backgrounds Tasks in iOS 13](https://www.andyibanez.com/posts/modern-background-tasks-ios13/)
[^54]: [Stack Overflow - BGTaskScheduler: Is it possible to schedule a background task inside a background task?](https://stackoverflow.com/questions/73126077/bgtaskscheduler-is-it-possible-to-schedule-a-background-task-inside-a-backgroun)
[^55]: [Snowdog - How to manage background tasks with the Task Scheduler in iOS 13?](https://www.snow.dog/blog/how-to-manage-background-tasks-with-the-task-scheduler-in-ios-13)
[^56]: [Due App Support - Background sync not working](https://dueapp.zendesk.com/hc/en-us/articles/204235325-Background-sync-not-working)
[^57]: [Due App Support - Background sync not working](https://dueapp.zendesk.com/hc/en-us/articles/204235325-Background-sync-not-working)
[^58]: [Due App Support - Background sync not working](https://dueapp.zendesk.com/hc/en-us/articles/204235325-Background-sync-not-working)
[^59]: [Due App Support - Background sync not working](https://dueapp.zendesk.com/hc/en-us/articles/204235325-Background-sync-not-working)
[^60]: [MacRumors Forums - iCloud sync photos on battery (possible?)](https://forums.macrumors.com/threads/icloud-sync-photos-on-battery-possible.2375035/)
[^61]: [Goodnotes Support - iCloud Sync issues](https://support.goodnotes.com/hc/en-us/articles/7352796404495-iCloud-Sync-issues)
[^62]: [Notability - Troubleshooting iCloud Sync](https://support.gingerlabs.com/hc/en-us/articles/205688797-Troubleshooting-iCloud-Sync)
[^63]: [Microsoft Community Hub - Changes to applications&#39; backup and restore behavior on iOS/iPadOS and macOS devices](https://techcommunity.microsoft.com/blog/intunecustomersuccess/changes-to-applications%E2%80%99-backup-and-restore-behavior-on-iosipados-and-macos-devi/3692064)
[^64]: [Apple Developer - Sync files to the cloud with FileProvider on macOS - WWDC21](https://developer.apple.com/videos/play/wwdc2021/10182/)
[^65]: [Apple Developer - TN3162: Understanding CloudKit throttles](https://developer.apple.com/documentation/technotes/tn3162-understanding-cloudkit-throttles)
[^66]: [Apple Developer Forums - CloudKit user &#39;throttling&#39;](https://forums.developer.apple.com/forums/thread/758198)
[^67]: [Apple Developer - Technical Note TN2336: Handling version conflicts in the iCloud environment](https://developer.apple.com/library/archive/technotes/tn2336/_index.html)
[^68]: [Apple Developer - Technical Note TN2336: Handling version conflicts in the iCloud environment](https://developer.apple.com/library/archive/technotes/tn2336/_index.html)
[^69]: [Apple Developer - Technical Note TN2336: Handling version conflicts in the iCloud environment](https://developer.apple.com/library/archive/technotes/tn2336/_index.html)
[^70]: [Apple Developer - iCloud File Management](https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/iCloud/iCloud.html)
[^71]: [AirDroid - Fix &#34;Syncing With iCloud Paused&#34; Error Within Minutes](https://www.airdroid.com/file-transfer/syncing-with-icloud-paused/)
[^72]: [Apple Community - iCloud Files Sync Stuck](https://discussions.apple.com/thread/251061918)
[^73]: [Apple Community - iCloud sync stuck?](https://discussions.apple.com/thread/251009341)
[^74]: [Apple Support - If your iCloud Photos are not syncing](https://support.apple.com/en-us/101559)
[^75]: [Computerworld - How to fix iCloud sync in seconds](https://www.computerworld.com/article/1367384/how-to-fix-icloud-sync-in-seconds.html)
[^76]: [Notability - Troubleshooting iCloud Sync](https://support.gingerlabs.com/hc/en-us/articles/205688797-Troubleshooting-iCloud-Sync)
[^77]: [Wesley de Groot - iCloud Drive Tips &amp; Tricks](https://wesleydegroot.nl/blog/iCloud-drive-tips-and-tricks)
[^78]: [Wesley de Groot - iCloud Drive Tips &amp; Tricks](https://wesleydegroot.nl/blog/iCloud-drive-tips-and-tricks)
[^79]: [Ask Different - iCloud Sync activity log](https://apple.stackexchange.com/questions/349082/icloud-sync-activity-log)
[^80]: [Apple Support - If your iCloud Contacts, Calendars, or Reminders won&#39;t sync](https://support.apple.com/en-us/102543)
[^81]: [Computerworld - How to fix iCloud sync in seconds](https://www.computerworld.com/article/1367384/how-to-fix-icloud-sync-in-seconds.html)
[^82]: [Super User - icloud drive sync stuck](https://superuser.com/questions/1045791/icloud-drive-sync-stuck)
[^83]: [Apple Community - iCloud sync and update very, very slow](https://discussions.apple.com/thread/255573626)
[^84]: [Archit Chandra - A Side Effect of Storing a Git Repository in iCloud Drive](https://architchandra.com/articles/a-side-effect-of-storing-a-git-repository-in-icloud-drive)
[^85]: [Apple Developer Forums - SwiftData iCloud sync breaks after...](https://forums.developer.apple.com/forums/thread/765948)
[^86]: [Obsidian Forum - Obsidian won&#39;t sync via icloud](https://forum.obsidian.md/t/obsidian-wont-sync-via-icloud/58346)
[^87]: [Obsidian Forum - iCloud Drive iOS and MacOS Sync Inconsistencies - Serious](https://forum.obsidian.md/t/icloud-drive-ios-and-macos-sync-inconsistencies-serious/34542)
[^88]: [Obsidian Forum - iCloud Drive iOS and MacOS Sync Inconsistencies - Serious](https://forum.obsidian.md/t/icloud-drive-ios-and-macos-sync-inconsistencies-serious/34542)
[^89]: [Obsidian Forum - Sync solutions](https://forum.obsidian.md/t/sync-solutions/98495)
[^90]: [Notability - Troubleshooting iCloud Sync](https://support.gingerlabs.com/hc/en-us/articles/205688797-Troubleshooting-iCloud-Sync)
[^91]: [Apple Developer Forums - SwiftData iCloud sync breaks after...](https://forums.developer.apple.com/forums/thread/765948)
[^92]: [Apple Developer Forums - SwiftData iCloud sync breaks after...](https://forums.developer.apple.com/forums/thread/765948)
</source:markdown>
    </item>
    
    <item>
      <title>Linearis, A Linear CLI Tool Built for Humans (and LLM Agents)</title>
      <link>https://zottmann.org/2025/09/03/linearis-my-linear-cli-built.html</link>
      <pubDate>Wed, 03 Sep 2025 10:02:00 +0100</pubDate>
      
      <guid>http://czottmann.micro.blog/2025/09/03/linearis-my-linear-cli-built.html</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; I built a &lt;a href=&#34;https://github.com/czottmann/linearis&#34;&gt;CLI tool for Linear.app with JSON output, smart ID resolution, and optimized GraphQL queries; designed for LLM agents and humans who prefer structured data.&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I use &lt;a href=&#34;https://linear.app&#34;&gt;Linear&lt;/a&gt; daily, in all my projects. It just such a nice piece of thoughtful software. It&amp;rsquo;s fast, well-laid out, flexible without being overwhelming, and respectful of my time both as a planner and a dev. And it looks good.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s the anti-JIRA.&lt;/p&gt;
&lt;p&gt;The last few months I&amp;rsquo;ve &lt;em&gt;also&lt;/em&gt; been using Claude Code, &lt;a href=&#34;https://github.com/sst/opencode&#34;&gt;sst/opencode&lt;/a&gt;, and &lt;a href=&#34;https://github.com/charmbracelet/crush&#34;&gt;charmbracelet/crush&lt;/a&gt; a lot. (Primarily CC.) And naturally, during that time, I wanted to be able to tell the agent to work on this ticket or update that ticket, so I used &lt;a href=&#34;https://linear.app/docs/mcp&#34;&gt;the official Linear MCP server&lt;/a&gt;. It worked great, no complaints.&lt;/p&gt;
&lt;h2 id=&#34;the-problems&#34;&gt;The Problem(s)&lt;/h2&gt;
&lt;p&gt;Then one day I discovered the &lt;code&gt;/context&lt;/code&gt; command in Claude, Code which gives a nice overview of what&amp;rsquo;s currently occupying its memory. Of the available 200k tokens, roughly 13k were taken up by the Linear MCP server alone – just by connecting and providing its tool definitions.&lt;/p&gt;
&lt;p&gt;Now 13k tokens isn&amp;rsquo;t much if you&amp;rsquo;re working with models that have million-token context windows (hello, Gemini Pro). But when you&amp;rsquo;re dealing with 100k or 200k token limits, that&amp;rsquo;s a significant chunk of your available context – gone before you even start doing actual work.&lt;/p&gt;
&lt;p&gt;Thinking about it, I realized that I am only using maybe three or four tools out of the 20+ that the Linear MCP server offers. Why spend tokens on project-management and workspace-setup features when I&amp;rsquo;m never going to use them? On top of that, I can&amp;rsquo;t use that MCP server in shell scripts.&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&#34;my-solution-linearis&#34;&gt;My Solution: Linearis&lt;/h2&gt;
&lt;p&gt;I finally decided to scratch my own itch and build something focused on what I &lt;em&gt;actually&lt;/em&gt; do with Linear on the command line and in agent prompts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create and update tickets&lt;/li&gt;
&lt;li&gt;Add comments and labels&lt;/li&gt;
&lt;li&gt;Search and filter issues&lt;/li&gt;
&lt;li&gt;Manage ticket relationships&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What I don&amp;rsquo;t do in these contexts is project management, workspace creation, or administrative setup. That stuff I handle manually in the UI when needed.&lt;/p&gt;
&lt;p&gt;So I wrote &lt;a href=&#34;https://github.com/czottmann/linearis&#34;&gt;Linearis&lt;/a&gt;, a CLI tool for Linear.app with JSON output, smart ID resolution, and optimized GraphQL queries. I designed it for LLM agents and humans who prefer structured data.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s a command-line tool that outputs JSON, resolves ticket IDs smartly, and keeps token usage light.&lt;/p&gt;
&lt;h3 id=&#34;installation&#34;&gt;Installation&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;npm install -g --install-links czottmann/linearis
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once installed, &lt;a href=&#34;https://github.com/czottmann/linearis#authentication&#34;&gt;authenticate yourself&lt;/a&gt;, and then you&amp;rsquo;re good to go.&lt;/p&gt;
&lt;h3 id=&#34;usage-examples&#34;&gt;Usage Examples&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Show usage&lt;/span&gt;
linearis

&lt;span style=&#34;color:#75715e&#34;&gt;# Show *everything* the agent needs to know&lt;/span&gt;
linearis usage

&lt;span style=&#34;color:#75715e&#34;&gt;# Create tickets with full context&lt;/span&gt;
linearis issues create &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Fix login timeout&amp;#34;&lt;/span&gt; --team Backend &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;  --assignee user123 --labels &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Bug,Critical&amp;#34;&lt;/span&gt; --priority &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;

&lt;span style=&#34;color:#75715e&#34;&gt;# Create bare-bones sub-issues &lt;/span&gt;
linearis issues create &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Fix login timeout&amp;#34;&lt;/span&gt; --parent-ticket ABC-234

&lt;span style=&#34;color:#75715e&#34;&gt;# Smart ID resolution - works with ABC-123 format&lt;/span&gt;
linearis issues read DEV-456
linearis issues update ABC-123 --state &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;In Review&amp;#34;&lt;/span&gt;

&lt;span style=&#34;color:#75715e&#34;&gt;# JSON output plays nice with other tools, like jq&lt;/span&gt;
linearis issues list -l &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt; | jq &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;.[] | .identifier + &amp;#34;: &amp;#34; + .title&amp;#39;&lt;/span&gt;

&lt;span style=&#34;color:#75715e&#34;&gt;# Add comments to track progress&lt;/span&gt;
linearis comments create ABC-123 --body &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Fixed in PR #456&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;using-linearis-in-a-llm-agent&#34;&gt;Using Linearis in a LLM agent&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s &lt;strong&gt;agent-friendly by design.&lt;/strong&gt; The key idea was making it dead simple for LLM agents to understand and use the tool:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;linearis usage
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This single command returns comprehensive yet concise usage information for all available tools. Agents can pipe this directly into their context and immediately understand everything the tool can do.&lt;/p&gt;
&lt;p&gt;The flags and options are well-documented and consistently structured, so agents can easily call it through their Bash tools without any special integration.&lt;/p&gt;
&lt;p&gt;So I put this in my &lt;code&gt;CLAUDE.md&lt;/code&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We track our tickets and projects in Linear (&lt;a href=&#34;https://linear.app&#34;&gt;https://linear.app&lt;/a&gt;), a project management tool. We use the &lt;code&gt;linearis&lt;/code&gt; CLI tool for communicating with Linear. Use your Bash tool to call the &lt;code&gt;linearis&lt;/code&gt; executable. Run &lt;code&gt;linearis usage&lt;/code&gt; to see usage information.&lt;/p&gt;
&lt;p&gt;The ticket numbers follow the format &amp;ldquo;ZCO-&lt;number&gt;&amp;rdquo;. Always reference tickets by their number.&lt;/p&gt;
&lt;p&gt;If you create a ticket, and it&amp;rsquo;s not clear which project to assign it to, prompt the user. When creating sub-issues, use the project of the parent ticket by default.&lt;/p&gt;
&lt;p&gt;When the the status of a task in the ticket description has changed (task → task done), update the description accordingly. When updating a ticket with a progress report that is more than just a checkbox change, add that report as a ticket comment.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That&amp;rsquo;s probably overly verbose, I guess. 😉 Some examples for prompts I use daily:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;we&amp;rsquo;re working on ABC-1234 now&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;later: &lt;em&gt;&amp;ldquo;add a progress report to the ticket&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;mark ABC-2345 as &amp;lsquo;in progress&amp;rsquo;&amp;quot;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;make this a sub-issue of ABC-3456&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;mark ABC-4567 as a bug&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;the-result&#34;&gt;The Result&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve been using Linearis for a while now, both manually and with my agentic tools. It does exactly what I need it to do without the overhead I don&amp;rsquo;t need. The agents can create tickets, update them, add comments, and manage labels efficiently. And when I need to do project setup or workspace management, I just use Linear&amp;rsquo;s web UI.&lt;/p&gt;
&lt;p&gt;Sometimes the best tool is the one that doesn&amp;rsquo;t try to do everything – just the things you actually need, done well. Linearis solves my particular requirements, but I think it might be helpful to you, too.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/czottmann/linearis&#34;&gt;Check it out on GitHub.&lt;/a&gt;&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;I know I could, technically, but I&amp;rsquo;m not an insane person. 😉&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
      <source:markdown>**TL;DR:** I built a [CLI tool for Linear.app with JSON output, smart ID resolution, and optimized GraphQL queries; designed for LLM agents and humans who prefer structured data.](https://github.com/czottmann/linearis)

---

I use [Linear](https://linear.app) daily, in all my projects. It just such a nice piece of thoughtful software. It&#39;s fast, well-laid out, flexible without being overwhelming, and respectful of my time both as a planner and a dev. And it looks good.

It&#39;s the anti-JIRA.

The last few months I&#39;ve _also_ been using Claude Code, [sst/opencode](https://github.com/sst/opencode), and [charmbracelet/crush](https://github.com/charmbracelet/crush) a lot. (Primarily CC.) And naturally, during that time, I wanted to be able to tell the agent to work on this ticket or update that ticket, so I used [the official Linear MCP server](https://linear.app/docs/mcp). It worked great, no complaints.


## The Problem(s)

Then one day I discovered the `/context` command in Claude, Code which gives a nice overview of what&#39;s currently occupying its memory. Of the available 200k tokens, roughly 13k were taken up by the Linear MCP server alone – just by connecting and providing its tool definitions.

Now 13k tokens isn&#39;t much if you&#39;re working with models that have million-token context windows (hello, Gemini Pro). But when you&#39;re dealing with 100k or 200k token limits, that&#39;s a significant chunk of your available context – gone before you even start doing actual work.

Thinking about it, I realized that I am only using maybe three or four tools out of the 20+ that the Linear MCP server offers. Why spend tokens on project-management and workspace-setup features when I&#39;m never going to use them? On top of that, I can&#39;t use that MCP server in shell scripts.[^1]

[^1]: I know I could, technically, but I&#39;m not an insane person. 😉


## My Solution: Linearis

I finally decided to scratch my own itch and build something focused on what I _actually_ do with Linear on the command line and in agent prompts:

- Create and update tickets
- Add comments and labels  
- Search and filter issues
- Manage ticket relationships

What I don&#39;t do in these contexts is project management, workspace creation, or administrative setup. That stuff I handle manually in the UI when needed.

So I wrote [Linearis](https://github.com/czottmann/linearis), a CLI tool for Linear.app with JSON output, smart ID resolution, and optimized GraphQL queries. I designed it for LLM agents and humans who prefer structured data.

It&#39;s a command-line tool that outputs JSON, resolves ticket IDs smartly, and keeps token usage light.


### Installation

```bash
npm install -g --install-links czottmann/linearis
```

Once installed, [authenticate yourself](https://github.com/czottmann/linearis#authentication), and then you&#39;re good to go.


### Usage Examples

```bash
# Show usage
linearis

# Show *everything* the agent needs to know
linearis usage

# Create tickets with full context
linearis issues create &#34;Fix login timeout&#34; --team Backend \
  --assignee user123 --labels &#34;Bug,Critical&#34; --priority 1

# Create bare-bones sub-issues 
linearis issues create &#34;Fix login timeout&#34; --parent-ticket ABC-234

# Smart ID resolution - works with ABC-123 format
linearis issues read DEV-456
linearis issues update ABC-123 --state &#34;In Review&#34;

# JSON output plays nice with other tools, like jq
linearis issues list -l 5 | jq &#39;.[] | .identifier + &#34;: &#34; + .title&#39;

# Add comments to track progress
linearis comments create ABC-123 --body &#34;Fixed in PR #456&#34;
```


## Using Linearis in a LLM agent

It&#39;s **agent-friendly by design.** The key idea was making it dead simple for LLM agents to understand and use the tool:

```bash
linearis usage
```

This single command returns comprehensive yet concise usage information for all available tools. Agents can pipe this directly into their context and immediately understand everything the tool can do.

The flags and options are well-documented and consistently structured, so agents can easily call it through their Bash tools without any special integration.

So I put this in my `CLAUDE.md`:

&gt; We track our tickets and projects in Linear (https://linear.app), a project management tool. We use the `linearis` CLI tool for communicating with Linear. Use your Bash tool to call the `linearis` executable. Run `linearis usage` to see usage information.
&gt; 
&gt; The ticket numbers follow the format &#34;ZCO-&lt;number&gt;&#34;. Always reference tickets by their number.
&gt; 
&gt; If you create a ticket, and it&#39;s not clear which project to assign it to, prompt the user. When creating sub-issues, use the project of the parent ticket by default.
&gt; 
&gt; When the the status of a task in the ticket description has changed (task → task done), update the description accordingly. When updating a ticket with a progress report that is more than just a checkbox change, add that report as a ticket comment.

That&#39;s probably overly verbose, I guess. 😉 Some examples for prompts I use daily:

- _&#34;we&#39;re working on ABC-1234 now&#34;_
- later: _&#34;add a progress report to the ticket&#34;_
- _&#34;mark ABC-2345 as &#39;in progress&#39;&#34;_
- _&#34;make this a sub-issue of ABC-3456&#34;_
- _&#34;mark ABC-4567 as a bug&#34;_


## The Result

I&#39;ve been using Linearis for a while now, both manually and with my agentic tools. It does exactly what I need it to do without the overhead I don&#39;t need. The agents can create tickets, update them, add comments, and manage labels efficiently. And when I need to do project setup or workspace management, I just use Linear&#39;s web UI.

Sometimes the best tool is the one that doesn&#39;t try to do everything – just the things you actually need, done well. Linearis solves my particular requirements, but I think it might be helpful to you, too.

[Check it out on GitHub.](https://github.com/czottmann/linearis)
</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://zottmann.org/2025/09/01/i-finally-pulled-the-trigger.html</link>
      <pubDate>Mon, 01 Sep 2025 15:34:27 +0100</pubDate>
      
      <guid>http://czottmann.micro.blog/2025/09/01/i-finally-pulled-the-trigger.html</guid>
      <description>&lt;p&gt;I finally pulled the trigger on booking the Danish language course (level A1) at our fine local Dansk Centralbibliotek 🎉&lt;/p&gt;
&lt;p&gt;2 weeks, 40h – the &amp;ldquo;pressure-cooker&amp;rdquo; version to get started!&lt;/p&gt;
&lt;p&gt;Why? Well, Denmark is right around the corner, we moved here 3+ years ago, and at this point, me still not being able to speak the language feels rude somehow. 😉 Also, it opens up opportunities. I mean, we&amp;rsquo;re still toying with the idea of moving farther North. Who knows?&lt;/p&gt;
</description>
      <source:markdown>I finally pulled the trigger on booking the Danish language course (level A1) at our fine local Dansk Centralbibliotek 🎉

2 weeks, 40h – the &#34;pressure-cooker&#34; version to get started!

Why? Well, Denmark is right around the corner, we moved here 3+&amp;nbsp;years ago, and at this point, me still not being able to speak the language feels rude somehow. 😉 Also, it opens up opportunities. I mean, we&#39;re still toying with the idea of moving farther North. Who knows?
</source:markdown>
    </item>
    
    <item>
      <title>Dear creators, I am judging your Nazi-enabling</title>
      <link>https://zottmann.org/2025/08/27/dear-creators-i-am-judging.html</link>
      <pubDate>Wed, 27 Aug 2025 17:42:26 +0100</pubDate>
      
      <guid>http://czottmann.micro.blog/2025/08/27/dear-creators-i-am-judging.html</guid>
      <description>&lt;h3 id=&#34;dear-creators&#34;&gt;Dear creators,&lt;/h3&gt;
&lt;p&gt;Hosting your newsletter on Substack or posting on X says &lt;em&gt;&amp;ldquo;I am fine with my Nazi neighbours&amp;rdquo;&lt;/em&gt;. Because that&amp;rsquo;s what these platforms are: &lt;a href=&#34;https://en.wiktionary.org/wiki/Nazi_bar&#34;&gt;Nazi bars&lt;/a&gt;, run by right-wing people and fascists.&lt;/p&gt;
&lt;p&gt;Using them as a creator means that &lt;strong&gt;you are actively helping them&lt;/strong&gt; grow and succeed. Your brain power and creations are propping up their Klan crosses. There&amp;rsquo;s no two sides to seeing this, there simply isn&amp;rsquo;t. Whatever your reasons, you are not only tolerating what they do, &lt;strong&gt;you directly and indirectly help legitimize their shit&lt;/strong&gt;, and help them make money.&lt;/p&gt;
&lt;p&gt;And for that I do judge you. Yes, I might dig your personal blog or tech newsletter or whathaveyou, but you are part of the problem. Both those things can be true. Because it&amp;rsquo;s 2025, and we&amp;rsquo;re way past beyond the &lt;em&gt;&amp;ldquo;I didn&amp;rsquo;t know they are bad&amp;rdquo;&lt;/em&gt; phase. We all know. You don&amp;rsquo;t get a pass anymore.&lt;/p&gt;
&lt;p&gt;Because the thing is: &lt;strong&gt;There&amp;rsquo;s no reason anymore to use those bad actors and their platforms.&lt;/strong&gt; You do not have to. Yes, we heard your arguments about reach and whatnot, but right now, a big ass portion of your reach is bot accounts and fans of fascism.&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; There are a great many viable alternatives for pretty much all your use cases, including &lt;a href=&#34;https://bsky.app&#34;&gt;social&lt;/a&gt; &lt;a href=&#34;https://joinmastodon.org&#34;&gt;media&lt;/a&gt; and &lt;a href=&#34;https://ghost.org&#34;&gt;blog + newsletter hosting&lt;/a&gt; – and believe me, among your friends, readers, and followers there are folks who will help you move. Just ask around, FFS.&lt;/p&gt;
&lt;p&gt;And if you don&amp;rsquo;t find anyone, send me &lt;a href=&#34;mailto:carlo@zottmann.dev&#34;&gt;an email&lt;/a&gt; or &lt;a href=&#34;https://bsky.app/profile/zottmann.dev&#34;&gt;a skeet&lt;/a&gt; or &lt;a href=&#34;https://norden.social/@czottmann&#34;&gt;a toot&lt;/a&gt;, I&amp;rsquo;ll help you get going.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;And if you happen to like this part of your fanbase, then by all means, fuck the fuck off.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
      <source:markdown>### Dear creators,

Hosting your newsletter on Substack or posting on X says _&#34;I am fine with my Nazi neighbours&#34;_. Because that&#39;s what these platforms are: [Nazi bars](https://en.wiktionary.org/wiki/Nazi_bar), run by right-wing people and fascists.

Using them as a creator means that **you are actively helping them** grow and succeed. Your brain power and creations are propping up their Klan crosses. There&#39;s no two sides to seeing this, there simply isn&#39;t. Whatever your reasons, you are not only tolerating what they do, **you directly and indirectly help legitimize their shit**, and help them make money.

And for that I do judge you. Yes, I might dig your personal blog or tech newsletter or whathaveyou, but you are part of the problem. Both those things can be true. Because it&#39;s 2025, and we&#39;re way past beyond the _&#34;I didn&#39;t know they are bad&#34;_ phase. We all know. You don&#39;t get a pass anymore.

Because the thing is: **There&#39;s no reason anymore to use those bad actors and their platforms.** You do not have to. Yes, we heard your arguments about reach and whatnot, but right now, a big ass portion of your reach is bot accounts and fans of fascism.[^1] There are a great many viable alternatives for pretty much all your use cases, including [social](https://bsky.app) [media](https://joinmastodon.org) and [blog + newsletter hosting](https://ghost.org) – and believe me, among your friends, readers, and followers there are folks who will help you move. Just ask around, FFS.

And if you don&#39;t find anyone, send me [an email](mailto:carlo@zottmann.dev) or [a skeet](https://bsky.app/profile/zottmann.dev) or [a toot](https://norden.social/@czottmann), I&#39;ll help you get going.

[^1]: And if you happen to like this part of your fanbase, then by all means, fuck the fuck off.

</source:markdown>
    </item>
    
    <item>
      <title>BarCuts: Building a Contextual macOS Shortcuts Launcher</title>
      <link>https://zottmann.org/2025/08/18/barcuts-building-a-contextual-macos.html</link>
      <pubDate>Fri, 15 Aug 2025 22:00:00 +0100</pubDate>
      
      <guid>http://czottmann.micro.blog/2025/08/18/barcuts-building-a-contextual-macos.html</guid>
      <description>&lt;p&gt;Sometimes the best software comes from scratching your own itch. That&amp;rsquo;s definitely the case with &lt;a href=&#34;https://actions.work/barcuts&#34;&gt;BarCuts&lt;/a&gt;, my take on a &lt;strong&gt;contextual macOS Shortcuts launcher.&lt;/strong&gt; What started as a personal annoyance turned into a proper little utility that I&amp;rsquo;m genuinely proud of – and it&amp;rsquo;s been quite the journey getting here.&lt;/p&gt;
&lt;h2 id=&#34;the-problem-that-started-it-all&#34;&gt;The Problem That Started It All&lt;/h2&gt;
&lt;p&gt;Picture this: you&amp;rsquo;ve got dozens of Shortcuts workflows on your Mac. Some are for processing files in Finder, others for grabbing URLs from Safari, maybe a few for formatting text in your notes app. But they&amp;rsquo;re all just sitting there in the Shortcuts app, or worse: in Shortcuts&#39; own menu bar, mixed together in one giant list with no context about when you&amp;rsquo;d actually want to use them.&lt;/p&gt;
&lt;p&gt;I kept thinking: wouldn&amp;rsquo;t it be nice if the right workflows just appeared when you needed them? Like, when I&amp;rsquo;m in Finder, show me my file-processing workflows. When I&amp;rsquo;m in Safari, Chrome, Edge, or another browser, show me &lt;a href=&#34;https://actions.work/browser-actions&#34;&gt;my web-related ones&lt;/a&gt;. Context-sensitive launching, basically.&lt;/p&gt;
&lt;p&gt;Turns out, that&amp;rsquo;s exactly what I ended up building.&lt;/p&gt;

&lt;style&gt;
:root {
   
  --yt-aspect-ratio-16-9: 56.25%;

   
  --yt-bg-black: #000;
  --yt-play-button-bg: rgba(255, 0, 0, 0.8);
  --yt-play-button-bg-hover: rgba(255, 0, 0, 1);
  --yt-play-button-icon: #fff;
  --yt-overlay-bg: rgba(0, 0, 0, 0.85);
  --yt-overlay-text: #fff;
  --yt-focus-outline: #e53935;

   
  --yt-play-button-width: 68px;
  --yt-play-button-height: 48px;
  --yt-play-button-border-radius: 12px;

   
  --yt-focus-outline-width: 3px;
  --yt-focus-outline-offset: 4px;

   
  --yt-transition-duration: 0.2s;
  --yt-transition-timing: ease-in-out;
}

.video-wrapper {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  padding-bottom: var(--yt-aspect-ratio-16-9);
  margin: 0;
  height: 0;
  max-width: 100%;
  overflow: hidden;
  background-color: var(--yt-bg-black);
  cursor: pointer;
  outline: none;
  border: none;
  color: inherit;
  font: inherit;
  text-align: inherit;
  appearance: none;
  -webkit-appearance: none;
}

.video-wrapper[data-is-loaded=&#34;true&#34;] {
  cursor: auto;
}

.video-wrapper:focus-visible {
  outline: var(--yt-focus-outline-width) solid var(--yt-focus-outline);
  outline-offset: var(--yt-focus-outline-offset);
}

.video-thumbnail {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  margin: auto;
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  object-position: center;
  background-color: var(--yt-bg-black);
  z-index: 1;
  transition: opacity var(--yt-transition-duration) var(--yt-transition-timing);
}

.video-wrapper:hover .video-thumbnail {
  opacity: 0.9;
}

.video-overlay {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  background: var(--yt-overlay-bg);
  color: var(--yt-overlay-text);
  text-align: center;
  font-size: 0.85em;
  padding: 0.5em 1em;
  z-index: 2;
  pointer-events: auto;
}

.video-play-button {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: var(--yt-play-button-width);
  height: var(--yt-play-button-height);
  background-color: var(--yt-play-button-bg);
  border-radius: var(--yt-play-button-border-radius);
  z-index: 3;
  pointer-events: none;
  transition: all var(--yt-transition-duration) var(--yt-transition-timing);
}

.video-wrapper:hover .video-play-button {
  background-color: var(--yt-play-button-bg-hover);
  transform: translate(-50%, -50%) scale(1.1);
}

.video-wrapper:active .video-play-button {
  transform: translate(-50%, -50%) scale(1.05);
}

.video-play-button::before {
  content: &#39;&#39;;
  position: absolute;
  left: 26px;
  top: 14px;
  width: 0;
  height: 0;
  border-left: 18px solid var(--yt-play-button-icon);
  border-top: 12px solid transparent;
  border-bottom: 12px solid transparent;
}

.video-wrapper iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border: none;
  z-index: 4;
}

.video-noscript {
  display: block;
  max-width: 100%;
  background-color: var(--yt-bg-black);
  color: inherit;
  text-align: center;
  padding: 0;
  margin-top: 0.5em;
}

.video-noscript img {
  display: block;
  width: 100%;
  height: auto;
}

.video-noscript a {
  display: inline-block;
  padding: 0.75em 1em;
  color: inherit;
  text-decoration: underline;
}

.yt-text-link {
  display: none;
}
&lt;/style&gt;

&lt;script&gt;
(function(){
  &#39;use strict&#39;;

  
  const CONSTANTS = {
    VIDEO_ID_LENGTH: 11,
    MAX_INPUT_LENGTH: 2048,
    VIDEO_ID_PATTERN: /^[a-zA-Z0-9_-]{11}$/,
    PLAYLIST_PREFIXES: /^(PL|OL|UU|LL|FL)/i,
    ALLOWED_URL_CHARS: /^[a-zA-Z0-9_\-?=&amp;#:/.]+$/,
    TIME_FORMATS: {
      HOURS: 3600,
      MINUTES: 60,
      SECONDS: 1
    },
    YOUTUBE_NOCOOKIE_DOMAIN: &#39;https://www.youtube-nocookie.com&#39;,
    YOUTUBE_IMG_DOMAIN: &#39;https://img.youtube.com&#39;,
    EMBED_PARAMS: &#39;autoplay=1&amp;mute=1&#39;
  };

  

  function validateInput(input, maxLength = CONSTANTS.MAX_INPUT_LENGTH) {
    if (!input || typeof input !== &#39;string&#39;) return &#39;&#39;;

    const trimmed = input.trim();

    if (trimmed.length &gt; maxLength) {
      console.warn(`Input exceeds maximum length of ${maxLength}`);
      return &#39;&#39;;
    }

    
    if (!CONSTANTS.ALLOWED_URL_CHARS.test(trimmed)) {
      console.warn(&#39;Input contains invalid characters&#39;);
      return &#39;&#39;;
    }

    return trimmed;
  }

  

  function parseStartValue(value) {
    if (!value) return 0;

    
    if (/^\d+$/.test(value)) {
      const parsed = parseInt(value, 10);
      return isNaN(parsed) ? 0 : Math.max(0, parsed);
    }

    
    let total = 0;
    let matched = false;
    const regex = /(\d+)(h|m|s)/gi;
    let match;

    while ((match = regex.exec(value)) !== null) {
      matched = true;
      const num = parseInt(match[1], 10);
      if (isNaN(num)) continue;

      const unit = match[2].toLowerCase();
      if (unit === &#39;h&#39;) total += num * CONSTANTS.TIME_FORMATS.HOURS;
      else if (unit === &#39;m&#39;) total += num * CONSTANTS.TIME_FORMATS.MINUTES;
      else if (unit === &#39;s&#39;) total += num * CONSTANTS.TIME_FORMATS.SECONDS;
    }

    return matched ? Math.max(0, total) : 0;
  }

  

  function extractStartTime(queryString) {
    if (!queryString) return 0;

    try {
      const cleanQuery = queryString.startsWith(&#39;?&#39;) || queryString.startsWith(&#39;#&#39;)
        ? queryString.slice(1)
        : queryString;

      const params = new URLSearchParams(cleanQuery);

      
      return parseStartValue(params.get(&#39;start&#39;)) ||
             parseStartValue(params.get(&#39;t&#39;)) ||
             parseStartValue(params.get(&#39;time_continue&#39;)) ||
             0;
    } catch (e) {
      console.warn(&#39;Failed to parse query parameters:&#39;, e);
      return 0;
    }
  }

  

  function parseId(raw) {
    const validated = validateInput(raw);
    if (!validated) {
      return { type: &#39;unknown&#39;, id: &#39;&#39;, start: 0 };
    }

    let startSeconds = 0;
    let normalized = validated;

    
    const queryIndex = normalized.indexOf(&#39;?&#39;);
    if (queryIndex !== -1) {
      startSeconds = extractStartTime(normalized.slice(queryIndex + 1));
      normalized = normalized.slice(0, queryIndex);
    }

    
    const hashIndex = normalized.indexOf(&#39;#&#39;);
    if (hashIndex !== -1) {
      startSeconds = startSeconds || extractStartTime(normalized.slice(hashIndex + 1));
      normalized = normalized.slice(0, hashIndex);
    }

    
    if (CONSTANTS.PLAYLIST_PREFIXES.test(normalized)) {
      return { type: &#39;playlist&#39;, id: normalized, start: startSeconds };
    }

    
    if (CONSTANTS.VIDEO_ID_PATTERN.test(normalized)) {
      return { type: &#39;video&#39;, id: normalized, start: startSeconds };
    }

    
    const listMatch = normalized.match(/list=([^&amp;]+)/);
    if (listMatch &amp;&amp; listMatch[1]) {
      return { type: &#39;playlist&#39;, id: listMatch[1], start: startSeconds };
    }

    console.warn(&#39;Unable to parse video/playlist ID:&#39;, raw);
    return { type: &#39;unknown&#39;, id: &#39;&#39;, start: startSeconds };
  }

  

  function validateThumbnailUrl(thumbUrl) {
    if (!thumbUrl) return &#39;&#39;;

    let cleaned = thumbUrl.trim();

    
    const markdownMatch = cleaned.match(/^\[[^\]]*\]\(([^)]+)\)$/);
    if (markdownMatch) {
      cleaned = markdownMatch[1].trim();
    }

    
    try {
      const url = new URL(cleaned, document.baseURI);

      
      if (url.protocol !== &#39;http:&#39; &amp;&amp; url.protocol !== &#39;https:&#39;) {
        console.warn(&#39;Thumbnail URL must use http or https protocol&#39;);
        return &#39;&#39;;
      }

      return url.href;
    } catch (e) {
      console.warn(&#39;Invalid thumbnail URL:&#39;, e);
      return &#39;&#39;;
    }
  }

  

  function getPlaylistPlaceholder() {
    const svg = `&lt;svg xmlns=&#39;http://www.w3.org/2000/svg&#39; viewBox=&#39;0 0 1280 720&#39;&gt;` +
                `&lt;rect width=&#39;100%&#39; height=&#39;100%&#39; fill=&#39;#000&#39;/&gt;` +
                `&lt;rect x=&#39;220&#39; y=&#39;260&#39; width=&#39;840&#39; height=&#39;60&#39; fill=&#39;#fff&#39;/&gt;` +
                `&lt;rect x=&#39;220&#39; y=&#39;340&#39; width=&#39;660&#39; height=&#39;60&#39; fill=&#39;#fff&#39;/&gt;` +
                `&lt;/svg&gt;`;
    return &#39;data:image/svg+xml;charset=utf-8,&#39; + encodeURIComponent(svg);
  }

  /**
   * Sets up thumbnail for video wrapper
   * @param {HTMLImageElement} thumbnail - Thumbnail element
   * @param {Object} kind - Parsed video/playlist info
   * @param {string} customThumb - Custom thumbnail URL
   */
  function setupThumbnail(thumbnail, kind, customThumb) {
    if (!thumbnail) return;

    if (customThumb) {
      // Use custom thumbnail
      thumbnail.onerror = null;
      thumbnail.src = customThumb;
    } else if (kind.type === &#39;playlist&#39;) {
      // Use playlist placeholder
      thumbnail.src = getPlaylistPlaceholder();
    } else if (kind.type === &#39;video&#39; &amp;&amp; kind.id) {
      // Use YouTube thumbnail with fallback
      thumbnail.src = `${CONSTANTS.YOUTUBE_IMG_DOMAIN}/vi/${kind.id}/maxresdefault.jpg`;
      thumbnail.onerror = () =&gt; {
        thumbnail.onerror = null;
        thumbnail.src = `${CONSTANTS.YOUTUBE_IMG_DOMAIN}/vi/${kind.id}/0.jpg`;
      };
    }
    // For unknown type, keep the default placeholder
  }

  /**
   * Creates embed URL for video or playlist
   * @param {Object} kind - Parsed video/playlist info
   * @returns {string} Embed URL or empty string if invalid
   */
  function createEmbedUrl(kind) {
    if (kind.type === &#39;playlist&#39; &amp;&amp; kind.id) {
      return `${CONSTANTS.YOUTUBE_NOCOOKIE_DOMAIN}/embed/videoseries?list=${encodeURIComponent(kind.id)}&amp;${CONSTANTS.EMBED_PARAMS}`;
    } else if (kind.type === &#39;video&#39; &amp;&amp; kind.id) {
      let url = `${CONSTANTS.YOUTUBE_NOCOOKIE_DOMAIN}/embed/${encodeURIComponent(kind.id)}?${CONSTANTS.EMBED_PARAMS}`;
      if (kind.start &gt; 0) {
        url += `&amp;start=${Math.floor(kind.start)}`;
      }
      return url;
    }
    return &#39;&#39;;
  }

  /**
   * Creates and loads iframe embed
   * @param {HTMLElement} wrapper - Video wrapper element
   * @param {Object} kind - Parsed video/playlist info
   * @param {string} title - Video title
   */
  function loadEmbed(wrapper, kind, title) {
    if (wrapper.dataset.isLoaded === &#39;true&#39;) return;

    const embedUrl = createEmbedUrl(kind);
    if (!embedUrl) {
      console.error(&#39;Unable to create embed URL - invalid video/playlist ID&#39;);
      // Show error message to user
      wrapper.innerHTML = &#39;&lt;div style=&#34;padding: 2em; text-align: center; color: #fff;&#34;&gt;Unable to load video. Please check the video ID.&lt;/div&gt;&#39;;
      return;
    }

    // Create iframe
    const iframe = document.createElement(&#39;iframe&#39;);
    iframe.setAttribute(&#39;allowfullscreen&#39;, &#39;&#39;);
    iframe.setAttribute(&#39;loading&#39;, &#39;lazy&#39;);
    iframe.setAttribute(&#39;allow&#39;, &#39;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#39;);
    iframe.setAttribute(&#39;title&#39;, title ? `YouTube video player: ${title}` : &#39;YouTube video player&#39;);
    iframe.src = embedUrl;

    
    const replacement = document.createElement(&#39;div&#39;);
    replacement.className = wrapper.className;
    replacement.dataset.listenersAdded = &#39;true&#39;;
    replacement.dataset.isLoaded = &#39;true&#39;;
    replacement.appendChild(iframe);

    wrapper.replaceWith(replacement);
  }

  

  function enhanceEmbeds() {
    const wrappers = document.querySelectorAll(&#39;.video-wrapper&#39;);

    wrappers.forEach(wrapper =&gt; {
      
      if (wrapper.dataset.listenersAdded === &#39;true&#39;) return;
      wrapper.dataset.listenersAdded = &#39;true&#39;;

      
      const rawVideoId = wrapper.dataset.videoId || &#39;&#39;;
      const rawThumbUrl = wrapper.dataset.thumb || &#39;&#39;;
      const videoTitle = wrapper.dataset.videoTitle || &#39;&#39;;

      
      const kind = parseId(rawVideoId);
      const safeThumb = validateThumbnailUrl(rawThumbUrl);

      
      const thumbnail = wrapper.querySelector(&#39;.video-thumbnail&#39;);
      setupThumbnail(thumbnail, kind, safeThumb);

      
      const loadHandler = () =&gt; loadEmbed(wrapper, kind, videoTitle);

      wrapper.addEventListener(&#39;click&#39;, loadHandler);

      const overlay = wrapper.querySelector(&#39;.video-overlay&#39;);
      if (overlay) overlay.addEventListener(&#39;click&#39;, loadHandler);
      if (thumbnail) thumbnail.addEventListener(&#39;click&#39;, loadHandler);

      
      wrapper.addEventListener(&#39;keydown&#39;, (e) =&gt; {
        if (e.key === &#39;Enter&#39; || e.key === &#39; &#39;) {
          e.preventDefault();
          loadHandler();
        }
      });
    });
  }

  
  enhanceEmbeds();
  if (document.readyState === &#39;loading&#39;) {
    document.addEventListener(&#39;DOMContentLoaded&#39;, enhanceEmbeds);
  }
})();
&lt;/script&gt;&lt;p class=&#34;yt-text-link&#34;&gt;
      &lt;a href=&#34;https://www.youtube.com/watch?v=sczwaYyaevY&#34;&gt;YouTube Video&lt;/a&gt;
    &lt;/p&gt;&lt;button type=&#34;button&#34;
    class=&#34;video-wrapper&#34;
    aria-label=&#34;Play YouTube video&#34;
    data-video-id=&#34;sczwaYyaevY&#34;
    data-thumb=&#34;&#34;
    &gt;&lt;img
      class=&#34;video-thumbnail&#34;
      src=&#34;data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20viewBox=%270%200%201280%20720%27%3E%3Crect%20width=%27100%25%25%27%20height=%27100%25%25%27%20fill=%27%23000%27/%3E%3C/svg%3E&#34;
      alt=&#34;YouTube Thumbnail&#34;
      loading=&#34;lazy&#34;
      decoding=&#34;async&#34;&gt;&lt;div class=&#34;video-play-button&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;&lt;noscript&gt;
    &lt;div class=&#34;video-noscript&#34;&gt;&lt;img src=&#34;https://img.youtube.com/vi/sczwaYyaevY/maxresdefault.jpg&#34;
             alt=&#34;YouTube Thumbnail&#34;&gt;&lt;p&gt;
          &lt;a href=&#34;https://www.youtube.com/watch?v=sczwaYyaevY&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;YouTube Video&lt;/a&gt;
        &lt;/p&gt;&lt;/div&gt;
  &lt;/noscript&gt;
&lt;p&gt;(Note: The image above is a video embed. If it doesn&amp;rsquo;t load for you, here&amp;rsquo;s the video: &lt;a href=&#34;https://www.youtube.com/watch?v=sczwaYyaevY&#34;&gt;BarCuts: A Surprisingly Useful macOS Shortcuts Launcher (2025.4)&lt;/a&gt;.)&lt;/p&gt;
&lt;h2 id=&#34;what-barcuts-brings-to-the-table&#34;&gt;What BarCuts Brings To The Table&lt;/h2&gt;
&lt;p&gt;As an example, let&amp;rsquo;s pretend you have a Shortcuts workflow named &amp;ldquo;Get today&amp;rsquo;s appointments&amp;rdquo; which fetches your appointments from the calendar, and which you only ever need when working in Notes. Here it is in the Shortcuts editor:&lt;/p&gt;
&lt;figure class=&#34;fullwidth&#34;&gt;
  &lt;img 
    src=&#34;https://eu.uploads.micro.blog/24102/2025/bc-basics-1.png&#34;
    alt=&#34;BarCuts Tagger panel shown next to a Shortcuts workflow &#39;Get Today\&#39;s Appointments&#39; being edited. The panel shows that the workflow was tagged to the Notes app&#34;
  &gt;
  &lt;figcaption&gt;
      The BarCuts Tagger panel for tagging your workflows to one or more apps. (v2025.4)
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;You want this workflow to be available in BarCuts whenever the Notes app is in front. So you&amp;rsquo;ll find the floating panel titled &amp;ldquo;BarCuts Tagger&amp;rdquo; next to the window, and &amp;ldquo;tag&amp;rdquo; Notes as a related app to this Shortcuts workflow, as shown above.&lt;/p&gt;
&lt;p&gt;Now, BarCuts&#39; menu will list the workflow when Notes is the frontmost app:&lt;/p&gt;
&lt;figure class=&#34;fullwidth&#34;&gt;
  &lt;img 
    src=&#34;https://eu.uploads.micro.blog/24102/2025/bc-basics-3.png&#34;
    alt=&#34;The Notes app is the frontmost app; the BarCuts menu bar menu shows the workflow&#34;
  &gt;
  &lt;figcaption&gt;
    The workflow we tagged with the Notes app is shown in BarCuts&#39; menu because Notes is in front
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;And that&amp;rsquo;s all there is to it!&lt;/p&gt;
&lt;p&gt;The menu can be opened with the mouse, but you can also configure a global hotkey that will open it, in the app&amp;rsquo;s Settings tab. Alternatively, you could also hook up &lt;a href=&#34;https://actions.work/barcuts&#34;&gt;BarCuts&lt;/a&gt; to Alfred, or connect it to your Raycast.&lt;/p&gt;
&lt;h2 id=&#34;timeline-or-everythings-a-journey-now&#34;&gt;Timeline, or: Everything&amp;rsquo;s A Journey Now&lt;/h2&gt;
&lt;h3 id=&#34;prototype-actions-based-tagging&#34;&gt;Prototype: Actions-Based Tagging&lt;/h3&gt;
&lt;p&gt;My initial approach was pretty straightforward (and, in hindsight, a bit naïve). I created a special Shortcuts action called &amp;ldquo;BarCuts Tagger&amp;rdquo; that you&amp;rsquo;d add to your workflows. You&amp;rsquo;d configure it with the app you wanted to associate the workflow with — say, &amp;ldquo;Finder&amp;rdquo; — and BarCuts would watch for when that app was active and surface the relevant workflows in its menu bar.&lt;/p&gt;
&lt;figure class=&#34;fullwidth&#34;&gt;
  &lt;img 
    src=&#34;https://eu.uploads.micro.blog/24102/2025/bc-basics-2.png&#34;
    alt=&#34;The &#39;BarCuts Tagger&#39; Shortcuts action, configured to show its surrounding workflow in BarCuts when app Notes is active, in top-level menu&#34;
  &gt;
  &lt;figcaption&gt;
      The BarCuts Tagger action. (v2025.1)
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;It worked! The concept was solid, and I was pretty pleased with the initial implementation. Little did I know there was a significant problem lurking that I wouldn&amp;rsquo;t fully appreciate until later&amp;hellip;&lt;/p&gt;
&lt;h3 id=&#34;the-public-beta&#34;&gt;The Public Beta&lt;/h3&gt;
&lt;p&gt;In February 2025, two weeks after starting the project, I &lt;a href=&#34;https://forum.actions.work/t/barcuts-public-beta/604&#34;&gt;launched the public beta&lt;/a&gt;, and the initial feedback was encouraging! People got the concept and found it useful.&lt;/p&gt;
&lt;p&gt;Shortly thereafter, I properly &lt;a href=&#34;https://forum.actions.work/t/barcuts-2025-1-0-launch/621&#34;&gt;launched version 2025.1&lt;/a&gt;. 🚀&lt;/p&gt;
&lt;h3 id=&#34;version-20252-a-reality-check&#34;&gt;Version 2025.2: A Reality Check&lt;/h3&gt;
&lt;p&gt;But as I was working on version 2025.2, I started hearing from more users about a problem I hadn&amp;rsquo;t fully grasped initially. To be honest, most of my own tagged workflows are macOS-only anyway, so I rarely ran into the sharing or iOS compatibility issues that were frustrating other people.&lt;/p&gt;
&lt;p&gt;I realized there was this massive, glaring problem with my original approach: your workflows were no longer &amp;ldquo;clean.&amp;rdquo; They had this Tagger action cluttering them up, which meant:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You couldn&amp;rsquo;t share them with anyone who didn&amp;rsquo;t have BarCuts&lt;/li&gt;
&lt;li&gt;They&amp;rsquo;d throw errors on iOS (where BarCuts obviously doesn&amp;rsquo;t exist)&lt;/li&gt;
&lt;li&gt;Your beautiful, &lt;em&gt;artisanal&lt;/em&gt; workflows suddenly had this extra cruft in them&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;My practical approach turned out to be the opposite of elegant.&lt;/p&gt;
&lt;p&gt;Despite this workflow pollution issue, I kept working on BarCuts because the core concept was still solid. &lt;a href=&#34;https://forum.actions.work/t/barcuts-2025-2/650/1&#34;&gt;Version 2025.2 was all about &amp;ldquo;connectivity&amp;rdquo;&lt;/a&gt;: I added proper scripting support, built companion extensions for &lt;a href=&#34;https://docs.actions.work/barcuts/alfred/&#34;&gt;Alfred&lt;/a&gt; and &lt;a href=&#34;https://docs.actions.work/barcuts/raycast/&#34;&gt;Raycast&lt;/a&gt;, and included a CLI tool for my fellow automation nerds.&lt;/p&gt;
&lt;p&gt;Because a launcher like that shouldn&amp;rsquo;t be a closed system. If you prefer launching workflows from Alfred or Raycast instead of the menu bar, great – you should be able to do that and still get the contextual filtering that makes the app useful.&lt;/p&gt;
&lt;p&gt;I also finally got around to writing &lt;a href=&#34;https://docs.actions.work/barcuts/&#34;&gt;proper documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;version-20253-polish-and-fixes&#34;&gt;Version 2025.3: Polish and Fixes&lt;/h3&gt;
&lt;p&gt;Better settings, fixed some annoying bugs, improved the workflow execution system. The kind of update that doesn&amp;rsquo;t look like much from the outside but makes everything feel more solid and reliable.&lt;/p&gt;
&lt;p&gt;During that time my old #1 problem was rearing its fugly head again: building the software is actually the easy part. Getting people to notice a new Mac utility? That&amp;rsquo;s the real challenge. Turns out there are &lt;em&gt;lots&lt;/em&gt; of great apps that barely anyone knows about because, well, &lt;strong&gt;marketing is hard.&lt;/strong&gt; Who knew?&lt;/p&gt;
&lt;p&gt;I was trying to get the tech news and pundits interested in earnest. Nobody cared. 🫤&lt;/p&gt;
&lt;h3 id=&#34;version-20254-the-present&#34;&gt;Version 2025.4: The Present&lt;/h3&gt;
&lt;p&gt;And that brings us to &lt;a href=&#34;https://forum.actions.work/t/barcuts-2025-4-the-clean-workflows-update/713&#34;&gt;the latest update&lt;/a&gt;, which I&amp;rsquo;m genuinely excited about because it finally got around to solving that nagging workflow pollution problem I mentioned earlier.&lt;/p&gt;
&lt;p&gt;I completely replaced the old Shortcuts action approach. Instead, BarCuts now adds a floating &amp;ldquo;BarCuts Tagger&amp;rdquo; panel directly to the Shortcuts editor. When you&amp;rsquo;re editing a workflow and BarCuts is running, you&amp;rsquo;ll see this lovely little panel floating next to your workflow window:&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the nice bit: your workflows remain &amp;ldquo;clean&amp;rdquo;. No more BarCuts actions. You can share them with anyone, run them on iOS, whatever – they&amp;rsquo;re just normal Shortcuts workflows, as they should be. Lesson learned.&lt;/p&gt;
&lt;p&gt;To tag a workflow now, you open it in Shortcuts and use the floating panel to tag it to whichever apps you want. You can even tag a single workflow to multiple apps if it&amp;rsquo;s useful in different contexts. Or put it in a submenu for even more structure.&lt;/p&gt;
&lt;p&gt;All existing tagged workflows get migrated automatically, and if you still have old BarCuts actions lying around, the app will help you clean them up.&lt;/p&gt;
&lt;h2 id=&#34;how-it-works-today&#34;&gt;How It Works Today&lt;/h2&gt;
&lt;p&gt;The current BarCuts experience is dead simple:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Install the app and grant it the necessary permissions&lt;/li&gt;
&lt;li&gt;Open any workflow in Shortcuts&lt;/li&gt;
&lt;li&gt;Use the floating panel to tag it to relevant applications&lt;/li&gt;
&lt;li&gt;Switch to one of those apps, and your tagged workflows appear in the BarCuts menu bar&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That&amp;rsquo;s it. No actions to configure, no workflows to modify, no compromises on shareability.&lt;/p&gt;
&lt;h2 id=&#34;why-this-matters&#34;&gt;Why This Matters&lt;/h2&gt;
&lt;p&gt;Look, I know there are lots of ways to launch Shortcuts workflows. Spotlight search, the Shortcuts app itself, various launcher apps – they all work fine for what they do.&lt;/p&gt;
&lt;p&gt;But BarCuts does something different: it surfaces the &lt;em&gt;right&lt;/em&gt; workflows at the &lt;em&gt;right&lt;/em&gt; time. When you&amp;rsquo;re in Finder and want to process some files, you don&amp;rsquo;t want to see your Safari bookmarking workflows cluttering up the list. When you&amp;rsquo;re writing in Notes, you want your text-processing workflows front and center, not your photo editing ones.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It&amp;rsquo;s about reducing cognitive overhead.&lt;/strong&gt; Instead of remembering which workflow does what and hunting through lists, the relevant ones just appear when you need them.&lt;/p&gt;
&lt;p&gt;And now, with the floating panel approach, you get all that contextual goodness without any of the workflow pollution that was holding people back.&lt;/p&gt;
&lt;h2 id=&#34;whats-next&#34;&gt;What&amp;rsquo;s Next?&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve got a proper backlog of ideas for future updates. Keyboard shortcuts for the menu, bulk workflow configuration, maybe some deeper integration with other automation tools – the usual &lt;em&gt;&amp;ldquo;wouldn&amp;rsquo;t it be cool if…&amp;quot;&lt;/em&gt; stuff that keeps me up at night thinking about software.&lt;/p&gt;
&lt;p&gt;But for now, I&amp;rsquo;m pretty chuffed — &lt;em&gt;chuffed!!&lt;/em&gt; — with where BarCuts has ended up. The core concept is the same as when I started, but its implementation is cleaner now.&lt;/p&gt;
&lt;h2 id=&#34;give-it-a-whirl&#34;&gt;Give It a Whirl&lt;/h2&gt;
&lt;p&gt;If you&amp;rsquo;re a macOS Shortcuts user who&amp;rsquo;s ever felt overwhelmed by a growing collection of workflows, BarCuts might be worth a look. There&amp;rsquo;s a 14-day trial, no strings attached, and the app works with macOS 14 and later.&lt;/p&gt;
&lt;p&gt;You can download it from &lt;a href=&#34;https://actions.work/barcuts&#34;&gt;the website&lt;/a&gt;, and if you want to chat about automation or share your setup, the &lt;a href=&#34;https://forum.actions.work/c/barcuts/12&#34;&gt;ActionsDotWork Forum&lt;/a&gt; is full of friendly folks who love this stuff as much as I do.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;P.S. Building and launching an indie Mac app has been quite the education. If you&amp;rsquo;re curious about that journey — the technical challenges, the marketing struggles, the weird satisfaction of solving problems for yourself and maybe a few other people — drop me a line. Always happy to chat about the indie dev life!&lt;/em&gt;&lt;/p&gt;
</description>
      <source:markdown>Sometimes the best software comes from scratching your own itch. That&#39;s definitely the case with [BarCuts](https://actions.work/barcuts), my take on a **contextual macOS Shortcuts launcher.** What started as a personal annoyance turned into a proper little utility that I&#39;m genuinely proud of – and it&#39;s been quite the journey getting here.

## The Problem That Started It All

Picture this: you&#39;ve got dozens of Shortcuts workflows on your Mac. Some are for processing files in Finder, others for grabbing URLs from Safari, maybe a few for formatting text in your notes app. But they&#39;re all just sitting there in the Shortcuts app, or worse: in Shortcuts&#39; own menu bar, mixed together in one giant list with no context about when you&#39;d actually want to use them.

I kept thinking: wouldn&#39;t it be nice if the right workflows just appeared when you needed them? Like, when I&#39;m in Finder, show me my file-processing workflows. When I&#39;m in Safari, Chrome, Edge, or another browser, show me [my web-related ones](https://actions.work/browser-actions). Context-sensitive launching, basically.

Turns out, that&#39;s exactly what I ended up building.

{{&lt; yt &#34;sczwaYyaevY&#34; &gt;}}

(Note: The image above is a video embed. If it doesn&#39;t load for you, here&#39;s the video: [BarCuts: A Surprisingly Useful macOS Shortcuts Launcher (2025.4)](https://www.youtube.com/watch?v=sczwaYyaevY).)

## What BarCuts Brings To The Table

As an example, let&#39;s pretend you have a Shortcuts workflow named &#34;Get today&#39;s appointments&#34; which fetches your appointments from the calendar, and which you only ever need when working in Notes. Here it is in the Shortcuts editor:

&lt;figure class=&#34;fullwidth&#34;&gt;
  &lt;img 
    src=&#34;https://eu.uploads.micro.blog/24102/2025/bc-basics-1.png&#34;
    alt=&#34;BarCuts Tagger panel shown next to a Shortcuts workflow &#39;Get Today\&#39;s Appointments&#39; being edited. The panel shows that the workflow was tagged to the Notes app&#34;
  &gt;
  &lt;figcaption&gt;
      The BarCuts Tagger panel for tagging your workflows to one or more apps. (v2025.4)
  &lt;/figcaption&gt;
&lt;/figure&gt;

You want this workflow to be available in BarCuts whenever the Notes app is in front. So you&#39;ll find the floating panel titled &#34;BarCuts Tagger&#34; next to the window, and &#34;tag&#34; Notes as a related app to this Shortcuts workflow, as shown above.

Now, BarCuts&#39; menu will list the workflow when Notes is the frontmost app:

&lt;figure class=&#34;fullwidth&#34;&gt;
  &lt;img 
    src=&#34;https://eu.uploads.micro.blog/24102/2025/bc-basics-3.png&#34;
    alt=&#34;The Notes app is the frontmost app; the BarCuts menu bar menu shows the workflow&#34;
  &gt;
  &lt;figcaption&gt;
    The workflow we tagged with the Notes app is shown in BarCuts&#39; menu because Notes is in front
  &lt;/figcaption&gt;
&lt;/figure&gt;

And that&#39;s all there is to it!

The menu can be opened with the mouse, but you can also configure a global hotkey that will open it, in the app&#39;s Settings tab. Alternatively, you could also hook up [BarCuts](https://actions.work/barcuts) to Alfred, or connect it to your Raycast.

## Timeline, or: Everything&#39;s A Journey Now

### Prototype: Actions-Based Tagging

My initial approach was pretty straightforward (and, in hindsight, a bit naïve). I created a special Shortcuts action called &#34;BarCuts Tagger&#34; that you&#39;d add to your workflows. You&#39;d configure it with the app you wanted to associate the workflow with — say, &#34;Finder&#34; — and BarCuts would watch for when that app was active and surface the relevant workflows in its menu bar.

&lt;figure class=&#34;fullwidth&#34;&gt;
  &lt;img 
    src=&#34;https://eu.uploads.micro.blog/24102/2025/bc-basics-2.png&#34;
    alt=&#34;The &#39;BarCuts Tagger&#39; Shortcuts action, configured to show its surrounding workflow in BarCuts when app Notes is active, in top-level menu&#34;
  &gt;
  &lt;figcaption&gt;
      The BarCuts Tagger action. (v2025.1)
  &lt;/figcaption&gt;
&lt;/figure&gt;

It worked! The concept was solid, and I was pretty pleased with the initial implementation. Little did I know there was a significant problem lurking that I wouldn&#39;t fully appreciate until later...

### The Public Beta

In February 2025, two weeks after starting the project, I [launched the public beta](https://forum.actions.work/t/barcuts-public-beta/604), and the initial feedback was encouraging! People got the concept and found it useful.

Shortly thereafter, I properly [launched version 2025.1](https://forum.actions.work/t/barcuts-2025-1-0-launch/621). 🚀

### Version 2025.2: A Reality Check

But as I was working on version 2025.2, I started hearing from more users about a problem I hadn&#39;t fully grasped initially. To be honest, most of my own tagged workflows are macOS-only anyway, so I rarely ran into the sharing or iOS compatibility issues that were frustrating other people.

I realized there was this massive, glaring problem with my original approach: your workflows were no longer &#34;clean.&#34; They had this Tagger action cluttering them up, which meant:

- You couldn&#39;t share them with anyone who didn&#39;t have BarCuts
- They&#39;d throw errors on iOS (where BarCuts obviously doesn&#39;t exist)  
- Your beautiful, _artisanal_ workflows suddenly had this extra cruft in them

My practical approach turned out to be the opposite of elegant.

Despite this workflow pollution issue, I kept working on BarCuts because the core concept was still solid. [Version 2025.2 was all about &#34;connectivity&#34;](https://forum.actions.work/t/barcuts-2025-2/650/1): I added proper scripting support, built companion extensions for [Alfred](https://docs.actions.work/barcuts/alfred/) and [Raycast](https://docs.actions.work/barcuts/raycast/), and included a CLI tool for my fellow automation nerds.

Because a launcher like that shouldn&#39;t be a closed system. If you prefer launching workflows from Alfred or Raycast instead of the menu bar, great – you should be able to do that and still get the contextual filtering that makes the app useful.

I also finally got around to writing [proper documentation](https://docs.actions.work/barcuts/).

### Version 2025.3: Polish and Fixes

Better settings, fixed some annoying bugs, improved the workflow execution system. The kind of update that doesn&#39;t look like much from the outside but makes everything feel more solid and reliable.

During that time my old #1 problem was rearing its fugly head again: building the software is actually the easy part. Getting people to notice a new Mac utility? That&#39;s the real challenge. Turns out there are *lots* of great apps that barely anyone knows about because, well, **marketing is hard.** Who knew?

I was trying to get the tech news and pundits interested in earnest. Nobody cared. 🫤

### Version 2025.4: The Present

And that brings us to [the latest update](https://forum.actions.work/t/barcuts-2025-4-the-clean-workflows-update/713), which I&#39;m genuinely excited about because it finally got around to solving that nagging workflow pollution problem I mentioned earlier.

I completely replaced the old Shortcuts action approach. Instead, BarCuts now adds a floating &#34;BarCuts Tagger&#34; panel directly to the Shortcuts editor. When you&#39;re editing a workflow and BarCuts is running, you&#39;ll see this lovely little panel floating next to your workflow window:

Here&#39;s the nice bit: your workflows remain &#34;clean&#34;. No more BarCuts actions. You can share them with anyone, run them on iOS, whatever – they&#39;re just normal Shortcuts workflows, as they should be. Lesson learned.

To tag a workflow now, you open it in Shortcuts and use the floating panel to tag it to whichever apps you want. You can even tag a single workflow to multiple apps if it&#39;s useful in different contexts. Or put it in a submenu for even more structure.

All existing tagged workflows get migrated automatically, and if you still have old BarCuts actions lying around, the app will help you clean them up.

## How It Works Today

The current BarCuts experience is dead simple:

1. Install the app and grant it the necessary permissions
2. Open any workflow in Shortcuts
3. Use the floating panel to tag it to relevant applications
4. Switch to one of those apps, and your tagged workflows appear in the BarCuts menu bar

That&#39;s it. No actions to configure, no workflows to modify, no compromises on shareability.

## Why This Matters

Look, I know there are lots of ways to launch Shortcuts workflows. Spotlight search, the Shortcuts app itself, various launcher apps – they all work fine for what they do.

But BarCuts does something different: it surfaces the *right* workflows at the *right* time. When you&#39;re in Finder and want to process some files, you don&#39;t want to see your Safari bookmarking workflows cluttering up the list. When you&#39;re writing in Notes, you want your text-processing workflows front and center, not your photo editing ones.

**It&#39;s about reducing cognitive overhead.** Instead of remembering which workflow does what and hunting through lists, the relevant ones just appear when you need them.

And now, with the floating panel approach, you get all that contextual goodness without any of the workflow pollution that was holding people back.

## What&#39;s Next?

I&#39;ve got a proper backlog of ideas for future updates. Keyboard shortcuts for the menu, bulk workflow configuration, maybe some deeper integration with other automation tools – the usual _&#34;wouldn&#39;t it be cool if…&#34;_ stuff that keeps me up at night thinking about software.

But for now, I&#39;m pretty chuffed — _chuffed!!_ — with where BarCuts has ended up. The core concept is the same as when I started, but its implementation is cleaner now.

## Give It a Whirl

If you&#39;re a macOS Shortcuts user who&#39;s ever felt overwhelmed by a growing collection of workflows, BarCuts might be worth a look. There&#39;s a 14-day trial, no strings attached, and the app works with macOS 14 and later.

You can download it from [the website](https://actions.work/barcuts), and if you want to chat about automation or share your setup, the [ActionsDotWork Forum](https://forum.actions.work/c/barcuts/12) is full of friendly folks who love this stuff as much as I do.

---

*P.S. Building and launching an indie Mac app has been quite the education. If you&#39;re curious about that journey — the technical challenges, the marketing struggles, the weird satisfaction of solving problems for yourself and maybe a few other people — drop me a line. Always happy to chat about the indie dev life!*
</source:markdown>
    </item>
    
  </channel>
</rss>
