<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: hiyoyo</title>
    <description>The latest articles on DEV Community by hiyoyo (@hiyoyok).</description>
    <link>https://dev.to/hiyoyok</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3851832%2Fa2762ba1-e687-4ae9-901d-245b96cf95d6.jpg</url>
      <title>DEV Community: hiyoyo</title>
      <link>https://dev.to/hiyoyok</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hiyoyok"/>
    <language>en</language>
    <item>
      <title>MTP on Android Is a Minefield — What I Learned After Building My Own Mac Client</title>
      <dc:creator>hiyoyo</dc:creator>
      <pubDate>Sat, 30 May 2026 07:15:06 +0000</pubDate>
      <link>https://dev.to/hiyoyok/mtp-on-android-is-a-minefield-what-i-learned-after-building-my-own-mac-client-4jk7</link>
      <guid>https://dev.to/hiyoyok/mtp-on-android-is-a-minefield-what-i-learned-after-building-my-own-mac-client-4jk7</guid>
      <description>&lt;p&gt;I built HiyokoMTP because the existing tools kept failing me.&lt;/p&gt;

&lt;p&gt;Android File Transfer has been effectively abandoned. OpenMTP is Electron-based — which means every USB operation runs through JavaScript, and its device recognition layer differs fundamentally from a native implementation. So I wrote my own MTP stack in Rust using nusb.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(All tests run on an 8-year-old MacBook Air — if it works there, it works anywhere.)&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Existing Tools Fall Short
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Android File Transfer&lt;/strong&gt;: no longer actively maintained, frequently fails to recognize modern Android devices.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenMTP&lt;/strong&gt;: every USB operation runs through the Electron runtime; its device recognition approach differs from native, leading to inconsistent behavior across manufacturers.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The 5 MTP Landmines
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Manufacturer quirks&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Pixel, Samsung, and Xiaomi all behave differently. Xiaomi defaults to "charging only" mode on connect; switching modes mid-session can silently terminate the MTP session.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The 4 GB wall&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;MTP uses 32-bit object size counters. Files over 4 GB require special handling, or transfers silently corrupt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Special characters&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Filenames containing &lt;code&gt;\ / : * ? " &amp;lt; &amp;gt; |&lt;/code&gt; must be sanitized before transfer. No sanitization = silent error or crash.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Cable-pull at 90%&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Unplugging during a transfer is the most common user mistake. Without clean disconnect detection, the app crashes or enters an undefined state.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. USB hub instability&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Hubs introduce instability. MTP is far more sensitive to this than mass storage protocols. Always test through a hub.&lt;/p&gt;




&lt;p&gt;If you're building your own MTP client, plan for these edge cases — they're invisible until a real user hits them.&lt;/p&gt;

&lt;p&gt;Building HiyokoMTP forced me to handle every one of these cases explicitly. All of the above is baked in. One-time purchase, no subscription.&lt;/p&gt;

&lt;p&gt;→ &lt;a href="https://hiyokomtp.lemonsqueezy.com/checkout/buy/2e966b64-554e-42a0-b865-4240281978a1" rel="noopener noreferrer"&gt;https://hiyokomtp.lemonsqueezy.com/checkout/buy/2e966b64-554e-42a0-b865-4240281978a1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What's the weirdest USB/MTP behavior you've run into?&lt;/p&gt;

</description>
      <category>android</category>
      <category>mtp</category>
      <category>tauri</category>
      <category>rust</category>
    </item>
    <item>
      <title>Tauri Sandbox Permissions — Why Your Command Silently Does Nothing</title>
      <dc:creator>hiyoyo</dc:creator>
      <pubDate>Sat, 30 May 2026 03:29:40 +0000</pubDate>
      <link>https://dev.to/hiyoyok/tauri-sandbox-permissions-why-your-command-silently-does-nothing-hcn</link>
      <guid>https://dev.to/hiyoyok/tauri-sandbox-permissions-why-your-command-silently-does-nothing-hcn</guid>
      <description>&lt;p&gt;All tests run on an 8-year-old MacBook Air. All results from shipping 7 Mac apps as a solo developer. No sponsored opinion.&lt;/p&gt;

&lt;p&gt;The most common Tauri v2 frustration: you write a command, invoke it from the frontend, and nothing happens. No error. No crash. Just silence. It's almost always permissions.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Tauri v2 permissions work
&lt;/h2&gt;

&lt;p&gt;Tauri v2 introduced a capability system. Every plugin action — reading files, executing shell commands, sending notifications — requires an explicit permission declaration in your config. Without the permission, the plugin call fails silently on the frontend. The Rust code never runs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;src-tauri/capabilities/main.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"identifier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"main-capability"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Permissions for main window"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"windows"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"permissions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"core:default"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"fs:read-all"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"fs:write-all"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"shell:allow-execute"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"opener:allow-open"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"global-shortcut:allow-register"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"global-shortcut:allow-unregister"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; As of Tauri v2.1, &lt;code&gt;shell:allow-open&lt;/code&gt; is deprecated. Use &lt;code&gt;tauri-plugin-opener&lt;/code&gt; and &lt;code&gt;opener:allow-open&lt;/code&gt; instead.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The debugging flow
&lt;/h2&gt;

&lt;p&gt;When a command does nothing:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Open DevTools&lt;/strong&gt; (&lt;code&gt;Cmd+Option+I&lt;/code&gt; in dev mode) — check the console for a rejected Promise or permission error&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check your terminal output&lt;/strong&gt; — the Rust side logs errors directly in the &lt;code&gt;tauri dev&lt;/code&gt; terminal; look for lines like &lt;code&gt;[tauri] permission denied&lt;/code&gt; or &lt;code&gt;not allowed&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enable verbose logging&lt;/strong&gt; — set &lt;code&gt;RUST_LOG=tauri=debug&lt;/code&gt; before running &lt;code&gt;tauri dev&lt;/code&gt; for more detailed backend output&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check your capabilities file&lt;/strong&gt; — missing or misspelled permission identifiers are the #1 cause&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Permission errors in the console typically look like a rejected Promise with a message such as &lt;code&gt;plugin:shell|execute not allowed&lt;/code&gt;. The capabilities file is always the first thing to check.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common permissions you'll need
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"permissions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"core:default"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"fs:read-all"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;read&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;any&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;file&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"fs:write-all"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;write&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;any&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;file&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"identifier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shell:allow-execute"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allow"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my-cmd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"cmd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"adb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"opener:allow-open"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;open&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;URLs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;files&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(replaces&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;shell:allow-open)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"path:allow-app-data-dir"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;access&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;app&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;directory&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"notification:default"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;send&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;notifications&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"global-shortcut:allow-register"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"clipboard-manager:allow-read-text"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"clipboard-manager:allow-write-text"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;shell:allow-execute&lt;/code&gt; now requires an explicit allow scope — wildcards are blocked by default for security.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The scope system
&lt;/h2&gt;

&lt;p&gt;For filesystem access, Tauri supports scoped permissions — allow access only to specific directories:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"identifier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fs:allow-app-data-read"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"allow"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$APPDATA/**"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use scoped permissions in production. &lt;code&gt;fs:read-all&lt;/code&gt; is convenient for development, but shipping with it exposes more than needed.&lt;/p&gt;




&lt;h2&gt;
  
  
  The verdict
&lt;/h2&gt;

&lt;p&gt;Tauri v2's permission system is correct. The sandboxing is good for security. The silent failure mode is painful until you know the pattern. When something stops working after a plugin update, always check whether the permission identifiers have changed — &lt;code&gt;opener&lt;/code&gt; replacing &lt;code&gt;shell:allow-open&lt;/code&gt; is a real example of this happening.&lt;/p&gt;

&lt;p&gt;Check the capabilities file first. Always.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If this was useful, a ❤️ helps more than you'd think — thanks!&lt;/em&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;Hiyoko PDF Vault → &lt;a href="https://hiyokomtp.lemonsqueezy.com/checkout/buy/a1b4d7d8-a4b8-433c-9d36-abdc0f3937c3" rel="noopener noreferrer"&gt;https://hiyokomtp.lemonsqueezy.com/checkout/buy/a1b4d7d8-a4b8-433c-9d36-abdc0f3937c3&lt;/a&gt;&lt;/em&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;X → &lt;a href="https://x.com/hiyoyok" rel="noopener noreferrer"&gt;@hiyoyok&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>tauri</category>
      <category>rust</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>I Can Copy on My Phone and Paste on My Mac Instantly — Across 10 Devices at Once</title>
      <dc:creator>hiyoyo</dc:creator>
      <pubDate>Fri, 29 May 2026 07:57:56 +0000</pubDate>
      <link>https://dev.to/hiyoyok/i-can-copy-on-my-phone-and-paste-on-my-mac-instantly-across-10-devices-at-once-2f8n</link>
      <guid>https://dev.to/hiyoyok/i-can-copy-on-my-phone-and-paste-on-my-mac-instantly-across-10-devices-at-once-2f8n</guid>
      <description>&lt;p&gt;&lt;em&gt;All tests run on an 8-year-old MacBook Air.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Copy something on your phone. Paste it on your Mac. No QR codes, no cloud accounts, no manual steps.&lt;/p&gt;

&lt;p&gt;Now do that with 10 devices simultaneously.&lt;/p&gt;

&lt;p&gt;That's what HiyokoClip does.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem with Clipboard on Android
&lt;/h2&gt;

&lt;p&gt;If you've ever tried to sync clipboard between Android and Mac, you already know the pain.&lt;/p&gt;

&lt;p&gt;The usual options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud clipboard tools that require an account and internet&lt;/li&gt;
&lt;li&gt;Browser extensions with privacy concerns&lt;/li&gt;
&lt;li&gt;Manual copy-paste via messaging apps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these feel seamless. And Android 10+ makes it even harder — apps can no longer read the clipboard in the background by default.&lt;/p&gt;




&lt;h2&gt;
  
  
  How HiyokoClip Solves It
&lt;/h2&gt;

&lt;p&gt;HiyokoClip runs entirely on your local network. No cloud. No accounts. No data leaving your devices.&lt;/p&gt;

&lt;p&gt;The moment you copy something on your Android device, it appears on your Mac clipboard. Instantly.&lt;/p&gt;

&lt;p&gt;And it works the other way too — copy on Mac, paste on any connected Android device.&lt;/p&gt;




&lt;h2&gt;
  
  
  N-to-N Sync: The Part That's Actually Fun
&lt;/h2&gt;

&lt;p&gt;Most clipboard tools are 1-to-1. One phone, one Mac.&lt;/p&gt;

&lt;p&gt;HiyokoClip supports N-to-N sync:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Copy on Phone A → paste on Phone B, Phone C, and Mac simultaneously&lt;/li&gt;
&lt;li&gt;Copy on Mac → paste on all connected Android devices&lt;/li&gt;
&lt;li&gt;Connect up to 10 devices at once&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you work with multiple test devices, or just have a tablet and a phone on your desk, this changes how you move information around.&lt;/p&gt;




&lt;h2&gt;
  
  
  Fully Local, Fully Private
&lt;/h2&gt;

&lt;p&gt;Everything stays on your local network:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No internet connection required after setup&lt;/li&gt;
&lt;li&gt;No account needed&lt;/li&gt;
&lt;li&gt;No clipboard data sent to any server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For developers handling sensitive data — API keys, tokens, internal URLs — this matters.&lt;/p&gt;




&lt;h2&gt;
  
  
  Seamless Link Included
&lt;/h2&gt;

&lt;p&gt;HiyokoClip also includes Seamless Link: plug in your Android via USB once, and it automatically switches to Wi-Fi. Pull the cable out and the sync keeps running wirelessly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;HiyokoClip for Mac&lt;br&gt;
&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
      &lt;div class="c-embed__body flex items-center justify-between"&gt;
        &lt;a href="https://hiyokomtp.lemonsqueezy.com/checkout/cart/ce9e4ef9-7a33-4a56-98e2-30b2785aaaf5" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;hiyokomtp.lemonsqueezy.com&lt;/span&gt;
          

        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;If you're an Android developer or just tired of the clipboard gap between your devices, give it a shot. Let me know how it goes in the comments &lt;/p&gt;

</description>
      <category>android</category>
      <category>productivity</category>
      <category>tauri</category>
      <category>macos</category>
    </item>
    <item>
      <title>Claude API Cheatsheet 2026 — Models, Pricing, Limits in One Place</title>
      <dc:creator>hiyoyo</dc:creator>
      <pubDate>Thu, 28 May 2026 17:19:33 +0000</pubDate>
      <link>https://dev.to/hiyoyok/claude-api-cheatsheet-2026-models-pricing-limits-in-one-place-4jf2</link>
      <guid>https://dev.to/hiyoyok/claude-api-cheatsheet-2026-models-pricing-limits-in-one-place-4jf2</guid>
      <description>&lt;h1&gt;
  
  
  Claude API Cheatsheet 2026 — Models, Pricing, Limits in One Place
&lt;/h1&gt;

&lt;p&gt;All information verified from Anthropic's official documentation as of May 2026.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Updated May 29, 2026:&lt;/strong&gt; Claude Opus 4.8 released. Model ID, pricing, and tips updated.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Models
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;ID&lt;/th&gt;
&lt;th&gt;Context&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Claude Opus 4.8&lt;/td&gt;
&lt;td&gt;&lt;code&gt;claude-opus-4-8&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1M&lt;/td&gt;
&lt;td&gt;Complex reasoning, hardest tasks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Sonnet 4.6&lt;/td&gt;
&lt;td&gt;&lt;code&gt;claude-sonnet-4-6&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1M&lt;/td&gt;
&lt;td&gt;Most production workloads&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Haiku 4.5&lt;/td&gt;
&lt;td&gt;&lt;code&gt;claude-haiku-4-5-20251001&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;200K&lt;/td&gt;
&lt;td&gt;Fast, simple tasks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Opus 4.8 and Sonnet 4.6 both support 1M token context at flat rate — no surcharge.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  API Pricing (per million tokens)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;Output&lt;/th&gt;
&lt;th&gt;Batch Input&lt;/th&gt;
&lt;th&gt;Batch Output&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Opus 4.8 (regular)&lt;/td&gt;
&lt;td&gt;$5.00&lt;/td&gt;
&lt;td&gt;$25.00&lt;/td&gt;
&lt;td&gt;$2.50&lt;/td&gt;
&lt;td&gt;$12.50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opus 4.8 (fast mode)&lt;/td&gt;
&lt;td&gt;$10.00&lt;/td&gt;
&lt;td&gt;$50.00&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sonnet 4.6&lt;/td&gt;
&lt;td&gt;$3.00&lt;/td&gt;
&lt;td&gt;$15.00&lt;/td&gt;
&lt;td&gt;$1.50&lt;/td&gt;
&lt;td&gt;$7.50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Haiku 4.5&lt;/td&gt;
&lt;td&gt;$1.00&lt;/td&gt;
&lt;td&gt;$5.00&lt;/td&gt;
&lt;td&gt;$0.50&lt;/td&gt;
&lt;td&gt;$2.50&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ Batch API = 50% discount, but processes within 24 hours (async only).&lt;br&gt;&lt;br&gt;
💡 Fast mode runs at 2.5× speed. Now 3× cheaper than fast mode was for previous Opus models.&lt;br&gt;&lt;br&gt;
¹ &lt;strong&gt;fast mode note:&lt;/strong&gt; Opus 4.8 fast mode ($10/$50) is separately priced from the older Opus 4.6/4.7 fast mode ($30/$150). The fast mode docs now confirm &lt;code&gt;speed: "fast"&lt;/code&gt; works with Opus 4.8, but explicit 4.8 pricing is not yet listed there. Prices above are from the official release announcement and Anthropic's pricing page.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Prompt Caching
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Cache Type&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cache write (5 min TTL)&lt;/td&gt;
&lt;td&gt;1.25x input rate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cache write (1 hour TTL)&lt;/td&gt;
&lt;td&gt;2x input rate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cache hit&lt;/td&gt;
&lt;td&gt;~0.1x input rate (up to 90% savings)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Best for: system prompts, repeated context, long documents.&lt;br&gt;&lt;br&gt;
💡 &lt;strong&gt;Opus 4.8 lowers the minimum cacheable tokens from 4,096 to 1,024&lt;/strong&gt; — making caching practical for shorter system prompts too.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Subscription Plans (not API)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;Monthly&lt;/th&gt;
&lt;th&gt;Annual&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td&gt;Sonnet 4.6, rolling 5hr limit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pro&lt;/td&gt;
&lt;td&gt;$20/mo&lt;/td&gt;
&lt;td&gt;$17/mo&lt;/td&gt;
&lt;td&gt;All models + Claude Code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max 5x&lt;/td&gt;
&lt;td&gt;$100/mo&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;5x Pro usage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max 20x&lt;/td&gt;
&lt;td&gt;$200/mo&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;20x Pro usage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Team Standard&lt;/td&gt;
&lt;td&gt;$25/seat&lt;/td&gt;
&lt;td&gt;$20/seat&lt;/td&gt;
&lt;td&gt;Min 5 seats&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Team Premium&lt;/td&gt;
&lt;td&gt;$125/seat&lt;/td&gt;
&lt;td&gt;$100/seat&lt;/td&gt;
&lt;td&gt;Includes Claude Code &amp;amp; Cowork&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ Subscriptions ≠ API access. API is always billed separately per token.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Basic API Call
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;anthropic&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Anthropic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your_key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-opus-4-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Batch API
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;anthropic&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Anthropic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;batch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;batches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;custom_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;request-1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;params&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-sonnet-4-6&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Mid-task System Updates (NEW in Opus 4.8)
&lt;/h2&gt;

&lt;p&gt;The Messages API now accepts &lt;code&gt;system&lt;/code&gt; entries inside the &lt;code&gt;messages&lt;/code&gt; array.&lt;br&gt;
This lets you update Claude's instructions mid-task without breaking the prompt cache.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Start the migration.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;assistant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Starting now...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Updated instruction: also update test files.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Continue.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;💡 Useful for updating permissions, token budgets, or environment context while an agent is running.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Key Tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Haiku&lt;/strong&gt; → simple classification, summaries, high-volume tasks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sonnet&lt;/strong&gt; → most production use cases, best price/performance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Opus&lt;/strong&gt; → complex reasoning, long-horizon agentic tasks (~1.7x more expensive than Sonnet, 5x more than Haiku)&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;Batch API&lt;/strong&gt; for non-realtime workloads (50% cheaper)&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;prompt caching&lt;/strong&gt; for repeated system prompts (up to 90% cheaper)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Opus 4.8 defaults to &lt;code&gt;high&lt;/code&gt; effort.&lt;/strong&gt; Use &lt;code&gt;xhigh&lt;/code&gt; (Claude Code) or &lt;code&gt;max&lt;/code&gt; for harder tasks — more tokens, better results. Rate limits in Claude Code have been increased to accommodate this.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Opus 4.8 fast mode&lt;/strong&gt; runs at 2.5× speed at $10/$50 per million tokens — 3× cheaper than fast mode was on previous Opus models.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Opus 4.8 is ~4× less likely than Opus 4.7&lt;/strong&gt; to let code flaws pass unremarked (per Anthropic's evaluations).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Migrating from Opus 4.7?&lt;/strong&gt; No new breaking changes have been officially announced for 4.8. Constraints introduced in 4.7 (non-default &lt;code&gt;temperature&lt;/code&gt;/&lt;code&gt;top_p&lt;/code&gt;/&lt;code&gt;top_k&lt;/code&gt; returning 400, adaptive thinking replacing extended thinking) are expected to carry over. Tokenizer is assumed unchanged, but actual token cost may vary — verify with your own inputs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extended thinking: not supported&lt;/strong&gt; on Opus 4.8 (confirmed in Anthropic's model overview). Use adaptive thinking instead.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Sources: &lt;a href="https://www.anthropic.com/news/claude-opus-4-8" rel="noopener noreferrer"&gt;Anthropic news — Introducing Claude Opus 4.8&lt;/a&gt; · &lt;a href="https://platform.claude.com/docs/en/about-claude/models/overview" rel="noopener noreferrer"&gt;Claude API docs&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If this was useful, a ❤️ helps more than you'd think.&lt;/p&gt;

</description>
      <category>claude</category>
      <category>llm</category>
      <category>cheatsheet</category>
      <category>ai</category>
    </item>
    <item>
      <title>Gumroad Cut Off My Payments Without a Word. Their Support Never Replied.</title>
      <dc:creator>hiyoyo</dc:creator>
      <pubDate>Thu, 28 May 2026 02:16:32 +0000</pubDate>
      <link>https://dev.to/hiyoyok/gumroad-cut-off-my-payments-without-a-word-their-support-never-replied-5ab</link>
      <guid>https://dev.to/hiyoyok/gumroad-cut-off-my-payments-without-a-word-their-support-never-replied-5ab</guid>
      <description>&lt;p&gt;7 Mac apps shipped as a solo developer. No sponsored opinion.&lt;/p&gt;




&lt;p&gt;I sold Mac apps on Gumroad for over a year.&lt;/p&gt;

&lt;p&gt;It worked. Simple setup, clean JP/EN storefront split, flat 10% fee. For a solo dev&lt;br&gt;
shipping their first paid app, the simplicity matters more than the fee. I recommended&lt;br&gt;
it. I built my entire payment infrastructure around it.&lt;/p&gt;

&lt;p&gt;Then it fell apart in the most frustrating way possible.&lt;/p&gt;




&lt;p&gt;The first sign: a UI I couldn't even use&lt;/p&gt;

&lt;p&gt;I hadn't logged in for about a month. When I did, there was an error message telling&lt;br&gt;
me to contact support — with a link I couldn't click. The UI itself was broken.&lt;/p&gt;

&lt;p&gt;I want to be upfront about this: yes, I hadn't checked in for a month. But the problem&lt;br&gt;
wasn't that I'd neglected something that needed maintenance. The problem was that&lt;br&gt;
Gumroad's own interface for reporting a problem was broken. I couldn't even follow&lt;br&gt;
their instructions.&lt;/p&gt;

&lt;p&gt;So I went around it and contacted support directly.&lt;/p&gt;




&lt;p&gt;The support loop&lt;/p&gt;

&lt;p&gt;Gumroad's support starts with an AI bot. Fine. I answered its questions. It asked the&lt;br&gt;
same questions again. I answered again. Same questions.&lt;/p&gt;

&lt;p&gt;The bot wasn't moving toward a resolution. It was just looping.&lt;/p&gt;

&lt;p&gt;I asked to be escalated to a human.&lt;/p&gt;

&lt;p&gt;They agreed.&lt;/p&gt;

&lt;p&gt;That was the last response I ever received.&lt;/p&gt;

&lt;p&gt;For over a month, nothing. No follow-up. No resolution. No acknowledgment that my&lt;br&gt;
storefront had an active error.&lt;/p&gt;




&lt;p&gt;Then I opened Gumroad one day and payment was just... gone&lt;/p&gt;

&lt;p&gt;No warning email. No violation notice. No explanation of any kind.&lt;/p&gt;

&lt;p&gt;I just logged in one day and both Stripe and PayPal were no longer functional. My&lt;br&gt;
Gumroad account still existed — I could log in, see my products, see my sales history.&lt;br&gt;
But payment processing was dead. Stripe banned, PayPal frozen, simultaneously.&lt;/p&gt;

&lt;p&gt;In practice, it didn't matter that my account was technically alive. No payment&lt;br&gt;
processor means no sales. For a solo dev with no backup platform, it was effectively&lt;br&gt;
a shutdown.&lt;/p&gt;

&lt;p&gt;I still don't know why. No reason was ever given. My support ticket was still open&lt;br&gt;
and unanswered when it happened.&lt;/p&gt;




&lt;p&gt;Emergency migration to LemonSqueezy&lt;/p&gt;

&lt;p&gt;I had apps listed. Customers trying to buy. Zero way to process payment. I had no&lt;br&gt;
choice but to move immediately.&lt;/p&gt;

&lt;p&gt;The migration meant:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rewriting Cloudflare Worker license validation from scratch — the logic that verifies
purchase keys on every app launch had to be rebuilt for LemonSqueezy's API. Several
hours of work across multiple apps.&lt;/li&gt;
&lt;li&gt;Rebuilding DMGs for every app — each binary needed updating to point to the new
validation endpoint. With 7+ apps, this alone took the better part of a day.&lt;/li&gt;
&lt;li&gt;Registering all products on LemonSqueezy and submitting W-8BEN tax paperwork.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Time I hadn't budgeted. Time I should have spent building.&lt;/p&gt;

&lt;p&gt;LemonSqueezy works. The checkout is cleaner. Tax handling as merchant of record is&lt;br&gt;
genuinely better. I should have diversified earlier.&lt;/p&gt;




&lt;p&gt;What I actually learned&lt;/p&gt;

&lt;p&gt;Two things, not one.&lt;/p&gt;

&lt;p&gt;First: check your storefronts regularly. Platforms can break silently. A month of&lt;br&gt;
not logging in was enough time for something to go wrong without me knowing. That's&lt;br&gt;
on me, and it's a cheap lesson compared to what it could have been.&lt;/p&gt;

&lt;p&gt;Second — and this is the bigger one — Gumroad didn't fail because it's a bad product.&lt;br&gt;
It failed as a platform dependency. The lesson isn't "use LemonSqueezy instead." The&lt;br&gt;
lesson is: never build your payment infrastructure around a single platform you don't&lt;br&gt;
control.&lt;/p&gt;

&lt;p&gt;Concretely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Have a backup payment processor ready before you need it&lt;/li&gt;
&lt;li&gt;If support goes silent for weeks, start migrating — don't wait for resolution&lt;/li&gt;
&lt;li&gt;Platform risk is real, boring, and easy to ignore until it isn't&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;The ticket is probably still open.&lt;/p&gt;

&lt;p&gt;If you're a solo dev selling digital products — how are you handling platform risk?&lt;br&gt;
Have you ever had a payment processor disappear on you?&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>webdev</category>
      <category>startup</category>
      <category>webmonetization</category>
    </item>
    <item>
      <title>I Fed 100 Files to Claude and Gemini to Find Bugs — Here's Why It Failed</title>
      <dc:creator>hiyoyo</dc:creator>
      <pubDate>Wed, 27 May 2026 10:49:23 +0000</pubDate>
      <link>https://dev.to/hiyoyok/i-fed-100-files-to-claude-and-gemini-to-find-bugs-heres-why-it-failed-1obh</link>
      <guid>https://dev.to/hiyoyok/i-fed-100-files-to-claude-and-gemini-to-find-bugs-heres-why-it-failed-1obh</guid>
      <description>&lt;p&gt;&lt;em&gt;All tests run on an 8-year-old MacBook Air.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;I regularly feed 100+ files into LLMs as part of my development workflow. One day I thought: why not just dump everything in and let it find all the bugs?&lt;/p&gt;

&lt;p&gt;Spoiler: it didn't work. Here's exactly what happened — and what actually does work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Setup
&lt;/h2&gt;

&lt;p&gt;I tested both &lt;strong&gt;Claude Opus 4.7&lt;/strong&gt; and &lt;strong&gt;Gemini 3.5 Flash&lt;/strong&gt; with thinking mode enabled on both. The task: find bugs across a multi-file Rust (Tauri v2) codebase. I suspect this happens regardless of language.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Happened
&lt;/h2&gt;

&lt;p&gt;The models didn't crash or throw errors. They confidently returned answers. The problem was those answers were wrong — and if you don't know the codebase well enough, you'd never catch it.&lt;/p&gt;

&lt;p&gt;This is the part nobody talks about: &lt;strong&gt;AI output is only as trustworthy as your ability to verify it.&lt;/strong&gt; If you hand 100 files to an LLM and it says "no bugs found," how would you know it's lying?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude Opus 4.7:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Up to ~5 files: accuracy was excellent. Genuinely impressive.&lt;/li&gt;
&lt;li&gt;10+ files: started getting shaky. Missing things it should catch.&lt;/li&gt;
&lt;li&gt;15 files (confirmed with src-tauri): hallucinations increased significantly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Gemini 3.5 Flash:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Single file up to ~300 lines: barely usable. Handles simple logic fine when the prompt is clear.&lt;/li&gt;
&lt;li&gt;Multiple files: fell apart quickly. Results vary significantly depending on prompt quality.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both models, even with thinking mode on, returned "no bugs found" on code that definitely had bugs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Happens: Lost in the Middle
&lt;/h2&gt;

&lt;p&gt;This is a known phenomenon called &lt;strong&gt;"Lost in the Middle"&lt;/strong&gt;. LLMs don't read context linearly like humans do. Information in the middle of a large context window gets significantly less attention than content at the beginning or end.&lt;/p&gt;

&lt;p&gt;So when you dump 15 files into the context, the model "sees" all of it technically — but effectively ignores large chunks in the middle.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important distinction&lt;/strong&gt;: thinking mode increases reasoning depth, but it doesn't fix the fundamental information retrieval problem. A wider context window ≠ the model can actually process all of it accurately.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fix: One File at a Time
&lt;/h2&gt;

&lt;p&gt;The solution I landed on from experience: feed files one at a time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Instead of this:
"Here are 100 files, find all bugs"

# Do this:
"Here is file X. Find bugs in this file only."
→ repeat for each file
→ aggregate results manually via copy-paste
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;More tedious? Yes. More accurate? Dramatically.&lt;/p&gt;

&lt;p&gt;For Opus specifically, staying under 5 files per request keeps the quality high. For Gemini, one file at a time with under 300 lines is the safe zone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Takeaways
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Sweet spot&lt;/th&gt;
&lt;th&gt;Starts breaking down&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Claude Opus 4.7&lt;/td&gt;
&lt;td&gt;1–5 files&lt;/td&gt;
&lt;td&gt;10+ files, confirmed at 15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemini 3.5 Flash&lt;/td&gt;
&lt;td&gt;1 file, &amp;lt;300 lines (prompt quality matters)&lt;/td&gt;
&lt;td&gt;Multiple files&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Don't trust "no bugs found" on large inputs&lt;/strong&gt; — the model may have simply stopped paying attention&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Thinking mode helps with reasoning, not with reading everything accurately&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Context window size is marketing. Effective context is much smaller in practice.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;When in doubt, split the task smaller&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;Large context windows are impressive on paper. In practice, the effective range where you can trust the output is much smaller than advertised.&lt;/p&gt;

&lt;p&gt;The fix isn't a better model — it's a better workflow. One file at a time, aggregated manually, beats dumping everything in and hoping for the best.&lt;/p&gt;

&lt;p&gt;Progress updates on X: &lt;a href="https://x.com/hiyoyok" rel="noopener noreferrer"&gt;@hiyoyok&lt;/a&gt;&lt;/p&gt;

</description>
      <category>gemini</category>
      <category>claude</category>
      <category>rust</category>
      <category>tauri</category>
    </item>
    <item>
      <title>I Built a macOS ADB GUI Tool with Tauri v2 + Rust — Here's What I Actually Implemented</title>
      <dc:creator>hiyoyo</dc:creator>
      <pubDate>Wed, 27 May 2026 08:45:38 +0000</pubDate>
      <link>https://dev.to/hiyoyok/i-built-a-macos-adb-gui-tool-with-tauri-v2-rust-heres-what-i-actually-implemented-1ioo</link>
      <guid>https://dev.to/hiyoyok/i-built-a-macos-adb-gui-tool-with-tauri-v2-rust-heres-what-i-actually-implemented-1ioo</guid>
      <description>&lt;p&gt;&lt;em&gt;All tests run on an 8-year-old MacBook Air.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;After getting tired of googling ADB commands every time I needed one, I built &lt;strong&gt;HiyokoADB&lt;/strong&gt; — a macOS GUI tool for Android developers. Here's a breakdown of what I actually shipped.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stack
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Rust + Tauri v2 + React&lt;/strong&gt; — same stack I use across all my Hiyoko tools. Lightweight, fast, and runs fine on older hardware.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Custom Command CRUD
&lt;/h3&gt;

&lt;p&gt;The core feature. In the Custom tab, you can register any ADB command with a label, then run it with one click.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Storage&lt;/strong&gt;: &lt;code&gt;localStorage&lt;/code&gt; — commands persist across sessions without a database&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operations&lt;/strong&gt;: Add via label + command input, delete via trash icon&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use case&lt;/strong&gt;: Stop copy-pasting from Stack Overflow. Register once, run forever.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Preset Commands
&lt;/h3&gt;

&lt;p&gt;A full set of commonly used ADB commands, organized by category:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Network&lt;/strong&gt;: WiFi On/Off, Airplane Mode Toggle&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Display&lt;/strong&gt;: Keep Screen On, Screen Off, Animation Speed x0 (instant UI)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Input&lt;/strong&gt;: Unlock Screen, Home Button, Back Button&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;System Debug&lt;/strong&gt;: GPU Rendering ON/OFF, Check ADB State, Reset WM/Density&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Settings (Direct)&lt;/strong&gt;: Developer Options, Accessibility, Battery Optimization, Notification Settings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Settings category uses &lt;code&gt;adb shell am start&lt;/code&gt; to open Android settings screens directly from your Mac — no need to dig through your phone.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Color-coded Result Log
&lt;/h3&gt;

&lt;p&gt;Every command execution outputs to the Result Log at the bottom:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Yellow&lt;/strong&gt; — &lt;code&gt;Executing: adb ...&lt;/code&gt; (the command being run)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;White/Gray&lt;/strong&gt; — stdout (normal output)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Red&lt;/strong&gt; — stderr (errors)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reused and adapted from my HiyokoKit codebase, so this was mostly a copy-paste job.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Batch Mode (Multi-device)
&lt;/h3&gt;

&lt;p&gt;Toggle "Batch Mode" in the sidebar and the same command fires to all connected devices simultaneously. Useful if you're testing across multiple Android devices.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Tools Tab — Advanced Input
&lt;/h3&gt;

&lt;p&gt;Beyond simple button commands, the Tools tab handles precision input:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Swipe&lt;/strong&gt;: Set start point, end point, and duration in milliseconds&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Long Press&lt;/strong&gt;: Coordinate + hold duration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Text Input&lt;/strong&gt;: Send strings directly from your Mac keyboard to the device&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coordinate Converter&lt;/strong&gt;: Convert scrcpy window coordinates to ADB tap coordinates automatically&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. System Utilities
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Resolution + DPI change (with reset button)&lt;/li&gt;
&lt;li&gt;GPU rendering toggle&lt;/li&gt;
&lt;li&gt;ADB state check&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I Reused from HiyokoKit
&lt;/h2&gt;

&lt;p&gt;Honest answer: a lot. The USB device detection, ADB command execution layer, and color log display were all adapted from my existing HiyokoKit codebase. The new work was:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Custom command CRUD with localStorage&lt;/li&gt;
&lt;li&gt;Coordinate converter logic&lt;/li&gt;
&lt;li&gt;Batch mode implementation&lt;/li&gt;
&lt;li&gt;Sequence runner (register multiple commands, execute in order)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Building on existing code meant shipping faster. The whole thing came together in roughly one day.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;HiyokoADB is still a work in progress, but the core is solid. If you're an Android developer on macOS who's tired of typing ADB commands, give it a look.&lt;/p&gt;

&lt;p&gt;Progress updates on X: &lt;a href="https://x.com/hiyoyok" rel="noopener noreferrer"&gt;@hiyoyok&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Built with Rust + Tauri v2 + React. macOS only.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>tauri</category>
      <category>rust</category>
      <category>android</category>
      <category>mac</category>
    </item>
    <item>
      <title>Building a Card Game AI with Reinforcement Learning — Implementation Details#2</title>
      <dc:creator>hiyoyo</dc:creator>
      <pubDate>Wed, 27 May 2026 08:06:54 +0000</pubDate>
      <link>https://dev.to/hiyoyok/building-a-card-game-ai-with-reinforcement-learning-implementation-details2-fp9</link>
      <guid>https://dev.to/hiyoyok/building-a-card-game-ai-with-reinforcement-learning-implementation-details2-fp9</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This is a follow-up to my previous article. If you haven't read it yet, check it out below.&lt;/p&gt;

&lt;p&gt;👇 Part 1 here&lt;br&gt;
(link to simple version)&lt;/p&gt;

&lt;p&gt;In Part 1, I covered the basics of Google Colab. This time, I'll go deeper into the mechanics — specifically how I used reinforcement learning to train an AI to play a card game.&lt;/p&gt;


&lt;h2&gt;
  
  
  What Is Reinforcement Learning?
&lt;/h2&gt;

&lt;p&gt;Reinforcement learning is a method where an AI learns by &lt;strong&gt;repeatedly trying things and adjusting based on the results&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Think of it like solving a maze:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go the right way → &lt;strong&gt;reward&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Hit a wall → &lt;strong&gt;penalty&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do this enough times and the AI gradually figures out the optimal path.&lt;/p&gt;

&lt;p&gt;Applied to a card game:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Play a good move → &lt;strong&gt;reward&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Lose the game → &lt;strong&gt;penalty&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I ran this loop &lt;strong&gt;200,000 times&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  Representing the Game State as Numbers
&lt;/h2&gt;

&lt;p&gt;To train an AI with reinforcement learning, every aspect of the game needs to be expressed as &lt;strong&gt;numbers&lt;/strong&gt;. "Dimensions" here just means the number of data fields passed to the AI.&lt;/p&gt;

&lt;p&gt;I ended up representing the game state with &lt;strong&gt;20 dimensions&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;State parameters: 10 dimensions&lt;/strong&gt;&lt;br&gt;
Numerical values representing the current game situation — things like HP and defense values&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Card information: 10 dimensions&lt;/strong&gt;&lt;br&gt;
Numerical values representing the cards in hand and available options&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I started with &lt;strong&gt;17 dimensions&lt;/strong&gt; and ran 100,000 training episodes, but the accuracy wasn't good enough. As I iterated, I realized certain game elements were missing from the representation. Adding those brought the total to 20 dimensions.&lt;/p&gt;

&lt;p&gt;Deciding &lt;strong&gt;what to include&lt;/strong&gt; in the state representation was both the hardest and most interesting part of the whole project.&lt;/p&gt;


&lt;h2&gt;
  
  
  Results After 200,000 Episodes
&lt;/h2&gt;

&lt;p&gt;After upgrading to 20 dimensions and running 200,000 episodes, the AI reached &lt;strong&gt;stable, reasonable accuracy&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Situations where the 17-dimension / 100,000-episode model made poor decisions were handled correctly after the upgrade.&lt;/p&gt;

&lt;p&gt;Honestly, reinforcement learning itself was easier than I expected. If you can clearly define the rules of the game in numerical form, the rest is just running the training loop.&lt;/p&gt;

&lt;p&gt;That said, &lt;strong&gt;deep knowledge of the game is a prerequisite&lt;/strong&gt;. I was able to design the state representation properly because I understood the game well enough to clear the hardest difficulty. Without that, the numbers wouldn't have captured what actually matters.&lt;/p&gt;


&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;I covered the basics of reinforcement learning, how I represented a card game's state in 20 dimensions, and what 200,000 training episodes produced.&lt;/p&gt;

&lt;p&gt;Reinforcement learning sounds intimidating, but if you understand the game you're modeling, it's surprisingly approachable. The hardest part isn't the ML — it's &lt;strong&gt;accurately translating the game into numbers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If this gets a good response, I might write about the Rust implementation too — no promises though 😊&lt;/p&gt;

&lt;p&gt;👇 Part 1 here&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/hiyoyok/my-old-macbook-air-couldnt-handle-it-so-i-used-google-colab-to-train-an-ai1-6p4" class="crayons-story__hidden-navigation-link"&gt;My Old MacBook Air Couldn't Handle It — So I Used Google Colab to Train an AI＃1&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/hiyoyok" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3851832%2Fa2762ba1-e687-4ae9-901d-245b96cf95d6.jpg" alt="hiyoyok profile" class="crayons-avatar__image" width="400" height="400"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/hiyoyok" class="crayons-story__secondary fw-medium m:hidden"&gt;
              hiyoyo
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                hiyoyo
                
              
              &lt;div id="story-author-preview-content-3674253" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/hiyoyok" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3851832%2Fa2762ba1-e687-4ae9-901d-245b96cf95d6.jpg" class="crayons-avatar__image" alt="" width="400" height="400"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;hiyoyo&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/hiyoyok/my-old-macbook-air-couldnt-handle-it-so-i-used-google-colab-to-train-an-ai1-6p4" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;May 21&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/hiyoyok/my-old-macbook-air-couldnt-handle-it-so-i-used-google-colab-to-train-an-ai1-6p4" id="article-link-3674253"&gt;
          My Old MacBook Air Couldn't Handle It — So I Used Google Colab to Train an AI＃1
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/python"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;python&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/googlecolab"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;googlecolab&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/rust"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;rust&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/hiyoyok/my-old-macbook-air-couldnt-handle-it-so-i-used-google-colab-to-train-an-ai1-6p4#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            3 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>ai</category>
      <category>python</category>
      <category>googlecolab</category>
      <category>rust</category>
    </item>
    <item>
      <title>I'm Building a GUI Tool for ADB Commands on macOS (Work in Progress)</title>
      <dc:creator>hiyoyo</dc:creator>
      <pubDate>Wed, 27 May 2026 03:25:06 +0000</pubDate>
      <link>https://dev.to/hiyoyok/im-building-a-gui-tool-for-adb-commands-on-macos-work-in-progress-3a0j</link>
      <guid>https://dev.to/hiyoyok/im-building-a-gui-tool-for-adb-commands-on-macos-work-in-progress-3a0j</guid>
      <description>&lt;p&gt;&lt;em&gt;All tests run on an 8-year-old MacBook Air.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;I got tired of googling ADB commands every single time.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;adb shell dumpsys battery&lt;/code&gt; — what was the exact syntax again?&lt;br&gt;
&lt;code&gt;adb shell svc wifi disable&lt;/code&gt; — or was it &lt;code&gt;enable&lt;/code&gt;?&lt;br&gt;
&lt;code&gt;adb shell am start -a android.settings.APPLICATION_DEVELOPMENT_SETTINGS&lt;/code&gt; — yeah, nobody memorizes that.&lt;/p&gt;

&lt;p&gt;So I started building &lt;strong&gt;HiyokoADB&lt;/strong&gt; — a macOS GUI tool that lets you run ADB commands without typing anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does (so far)
&lt;/h2&gt;

&lt;p&gt;The app has three sections:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dashboard&lt;/strong&gt; — shows connected device info at a glance: battery level, Android version, IP address, model, serial number.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Presets&lt;/strong&gt; — a collection of commonly used ADB commands organized by category (Network, Display, Input). One click to run.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Custom&lt;/strong&gt; — save your own ADB commands with a label. No more copy-pasting from Stack Overflow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0sy86msvw1o5rixz6xqp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0sy86msvw1o5rixz6xqp.png" alt=" " width="800" height="579"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tech stack
&lt;/h2&gt;

&lt;p&gt;Built with &lt;strong&gt;Rust + Tauri v2 + React&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Why Tauri v2 instead of Electron? The usual reasons — it's lightweight, fast, and works great on older hardware. My 8-year-old MacBook Air runs it without breaking a sweat.&lt;/p&gt;

&lt;p&gt;The ADB execution layer is pure Rust, which makes command output parsing reliable and fast. Device discovery, shell commands, output capture — all handled in &lt;code&gt;adb.rs&lt;/code&gt; on the backend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Current preset commands
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;WiFi On / Off&lt;/li&gt;
&lt;li&gt;Airplane Mode Toggle&lt;/li&gt;
&lt;li&gt;Keep Screen On&lt;/li&gt;
&lt;li&gt;Screen Off&lt;/li&gt;
&lt;li&gt;Animation x0 (developer favorite)&lt;/li&gt;
&lt;li&gt;Unlock Screen&lt;/li&gt;
&lt;li&gt;Home Button / Back Button&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More coming. The custom command feature means you can add whatever's missing for your workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;This is still a work in progress. Planned for upcoming versions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Coordinate converter (scrcpy coords ↔ ADB coords ↔ Android real coords)&lt;/li&gt;
&lt;li&gt;Android settings shortcuts (open Developer Options, Accessibility, Battery Optimization directly from your Mac)&lt;/li&gt;
&lt;li&gt;Device profiles (name your devices, multi-device command broadcast)&lt;/li&gt;
&lt;li&gt;Command sequences (chain multiple commands into one button)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why I'm sharing this now
&lt;/h2&gt;

&lt;p&gt;Honestly, I want feedback. If you use ADB regularly on macOS, what commands do you run most? What would you want in a tool like this?&lt;/p&gt;

&lt;p&gt;Drop a comment — I'm actively building and would love to hear what's missing.&lt;/p&gt;




&lt;p&gt;If you're interested in HiyokoADB, follow the progress on X: &lt;a href="https://x.com/hiyoyok" rel="noopener noreferrer"&gt;@hiyoyok&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Built with Rust + Tauri v2 + React. macOS only.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>tauri</category>
      <category>rust</category>
      <category>android</category>
      <category>mac</category>
    </item>
    <item>
      <title>Code Signing a Tauri App for macOS — The Complete Flow</title>
      <dc:creator>hiyoyo</dc:creator>
      <pubDate>Wed, 27 May 2026 02:36:18 +0000</pubDate>
      <link>https://dev.to/hiyoyok/code-signing-a-tauri-app-for-macos-the-complete-flow-54jk</link>
      <guid>https://dev.to/hiyoyok/code-signing-a-tauri-app-for-macos-the-complete-flow-54jk</guid>
      <description>&lt;p&gt;How to Sign and Notarize a Tauri Mac App for Distribution&lt;/p&gt;

&lt;p&gt;All tests run on an 8-year-old MacBook Air.&lt;br&gt;
All results from shipping 7 Mac apps as a solo developer. No sponsored opinion.&lt;/p&gt;

&lt;p&gt;Every Mac app I've shipped required this. Here's the exact flow I use.&lt;/p&gt;

&lt;p&gt;An unsigned Mac app triggers a Gatekeeper warning that looks like malware. Users close it immediately. Code signing is not optional for a shipping product.&lt;/p&gt;

&lt;p&gt;What you need&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Apple Developer account ($99/year)&lt;/li&gt;
&lt;li&gt;Developer ID Application certificate (for distribution outside App Store)&lt;/li&gt;
&lt;li&gt;App-specific password for notarization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tauri's built-in signing&lt;br&gt;
Tauri v2 handles signing automatically if you configure it:&lt;/p&gt;

&lt;p&gt;// tauri.conf.json&lt;br&gt;
{&lt;br&gt;
  "bundle": {&lt;br&gt;
    "macOS": {&lt;br&gt;
      "signingIdentity": "Developer ID Application: Your Name (TEAMID)",&lt;br&gt;
      "providerShortName": "TEAMID"&lt;br&gt;
    }&lt;br&gt;
  }&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;Set environment variables for the build:&lt;/p&gt;

&lt;p&gt;export APPLE_SIGNING_IDENTITY="Developer ID Application: Your Name (TEAMID)"&lt;br&gt;
export APPLE_ID="&lt;a href="mailto:your@email.com"&gt;your@email.com&lt;/a&gt;"&lt;br&gt;
export APPLE_PASSWORD="your-app-specific-password"&lt;br&gt;
export APPLE_TEAM_ID="YOURTEAMID"&lt;br&gt;
npm run tauri build&lt;/p&gt;

&lt;p&gt;Tauri signs the app and submits for notarization automatically.&lt;/p&gt;

&lt;p&gt;Manual notarization when needed&lt;/p&gt;
&lt;h1&gt;
  
  
  Build without auto-notarize
&lt;/h1&gt;

&lt;p&gt;npm run tauri build&lt;/p&gt;
&lt;h1&gt;
  
  
  Submit DMG manually
&lt;/h1&gt;

&lt;p&gt;xcrun notarytool submit \&lt;br&gt;
  "target/release/bundle/dmg/YourApp.dmg" \&lt;br&gt;
  --apple-id "$APPLE_ID" \&lt;br&gt;
  --team-id "$APPLE_TEAM_ID" \&lt;br&gt;
  --password "$APPLE_PASSWORD" \&lt;br&gt;
  --wait&lt;/p&gt;
&lt;h1&gt;
  
  
  Staple the notarization ticket
&lt;/h1&gt;

&lt;p&gt;xcrun stapler staple "target/release/bundle/dmg/YourApp.dmg"&lt;/p&gt;

&lt;p&gt;--wait blocks until notarization completes (usually 1-5 minutes).&lt;/p&gt;

&lt;p&gt;Verifying the result&lt;/p&gt;
&lt;h1&gt;
  
  
  Check signing
&lt;/h1&gt;

&lt;p&gt;codesign -dv --verbose=4 YourApp.app&lt;/p&gt;
&lt;h1&gt;
  
  
  Check notarization
&lt;/h1&gt;

&lt;p&gt;spctl -a -v YourApp.app&lt;/p&gt;
&lt;h1&gt;
  
  
  Should output: "accepted"
&lt;/h1&gt;
&lt;h1&gt;
  
  
  Check DMG
&lt;/h1&gt;

&lt;p&gt;spctl -a -v YourApp.dmg&lt;/p&gt;

&lt;p&gt;The entitlements file&lt;br&gt;
Some capabilities require entitlements. For a Tauri app that runs shell commands:&lt;/p&gt;



&lt;p&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br&gt;
&amp;lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "..."&amp;gt;&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
  com.apple.security.cs.allow-unsigned-executable-memory&lt;br&gt;
  &lt;br&gt;
  com.apple.security.cs.disable-library-validation&lt;br&gt;
  &lt;br&gt;
&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Tauri configures entitlements via tauri.conf.json. Check the docs for your specific requirements. For my ADB-based apps, these two entitlements were the minimum needed to run shell commands without Gatekeeper blocking the process.&lt;/p&gt;

&lt;p&gt;The $99/year question&lt;br&gt;
Worth it if you're selling apps. Without it, users see a Gatekeeper warning. Many won't proceed. The developer account pays for itself with the first few sales.&lt;/p&gt;




&lt;p&gt;If this was useful, a ❤️ helps more than you'd think — thanks!&lt;/p&gt;

&lt;p&gt;Hiyoko Kit → &lt;a href="https://hiyokomtp.lemonsqueezy.com/checkout/buy/2c94dd0f-e28a-4a17-8efc-7bd93087d46d" rel="noopener noreferrer"&gt;https://hiyokomtp.lemonsqueezy.com/checkout/buy/2c94dd0f-e28a-4a17-8efc-7bd93087d46d&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;X → &lt;a class="mentioned-user" href="https://dev.to/hiyoyok"&gt;@hiyoyok&lt;/a&gt;&lt;/p&gt;

</description>
      <category>tuari</category>
      <category>rust</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>I Used Gemini 3.5 Flash via Direct API for a Week — An Honest Report on Its Speed Trade-offs and Real-World Pitfalls</title>
      <dc:creator>hiyoyo</dc:creator>
      <pubDate>Tue, 26 May 2026 14:26:55 +0000</pubDate>
      <link>https://dev.to/hiyoyok/i-used-gemini-35-flash-via-direct-api-for-a-week-an-honest-report-on-its-speed-trade-offs-and-458j</link>
      <guid>https://dev.to/hiyoyok/i-used-gemini-35-flash-via-direct-api-for-a-week-an-honest-report-on-its-speed-trade-offs-and-458j</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;After publishing a piece on debugging Rust code with Gemini 3.5 Flash, the response was bigger than I expected. So I spent the following week integrating it directly into my personal development workflow via the API and documenting the results.&lt;/p&gt;

&lt;p&gt;The previous article was a controlled test. This one is about real-world usage. Bottom line: it can be a powerhouse depending on how you use it — but use it without thinking and you'll hit a wall fast.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Worked Well
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Simple tasks are accurate and blazing fast
&lt;/h3&gt;

&lt;p&gt;For straightforward requests like "which files do I need to touch to remove the dock icon display for this app?", the speed is genuinely impressive. My gut feeling is it's at least 10x faster than 3.1 Pro.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bulk edits are stable — if your instructions are solid
&lt;/h3&gt;

&lt;p&gt;I threw cross-file edits totaling around 300 lines at it in a single prompt, and when the instructions were precise, it handled them cleanly. For developers who can write tight, complete instruction documents, this becomes a seriously fast tool.&lt;/p&gt;

&lt;h3&gt;
  
  
  Evaluations feel more grounded than 3.1 Pro
&lt;/h3&gt;

&lt;p&gt;When I asked it to "evaluate this critically," the feedback felt more realistic than what I'd get from 3.1 Pro. This is specifically for non-code evaluation — ideas, writing, etc. For use cases where you want "tell me the real situation, not the ideal," there's a noticeable improvement.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Was Genuinely Painful
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Token consumption burns through your budget alarmingly fast
&lt;/h3&gt;

&lt;p&gt;This was the biggest surprise. Even in casual exchanges, I'd watch nearly 10% of my available tokens disappear within 5 minutes. A significant portion of that is thinking tokens — the model reasoning internally while you wait. If you're planning any long sessions, you need to design your cost model carefully or you'll get hit with an unexpected bill.&lt;/p&gt;

&lt;h3&gt;
  
  
  Under server load, the "blazing fast" reputation disappears
&lt;/h3&gt;

&lt;p&gt;Speed is one of the main selling points, but when the server is under heavy load, it's just... normal speed. Sometimes nearly identical to 3.1 Pro. "Blazing fast" is more accurately "blazing fast when the servers aren't busy."&lt;/p&gt;

&lt;h3&gt;
  
  
  Complex logic chains start to break down
&lt;/h3&gt;

&lt;p&gt;Simple bug fixes and single-file edits are fine. But in real development, I noticed things going wrong when around five or more pieces of logic were interconnected.&lt;/p&gt;

&lt;p&gt;When you have something like "A triggers B triggers C triggers D triggers E, and changing A affects E," it starts missing intermediate connections and making edits that ignore those dependencies. The previous benchmark (200 lines, 14 bugs, all correct) worked because the bugs were relatively independent. Real-world dependency chains are a different animal.&lt;/p&gt;

&lt;h3&gt;
  
  
  Round-trip costs pile up on complex problems
&lt;/h3&gt;

&lt;p&gt;There was a bug I handed off to Gemini where we went through multiple cycles of investigation → fix → re-investigation, and I eventually spent more time reviewing its attempts than I would have spent just fixing it myself.&lt;/p&gt;

&lt;p&gt;"Just hand it to AI and it'll be faster" only holds when the problem is simple. On complex problems, the round-trip overhead stacks up, and doing it yourself can be quicker.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security-related code gets missed
&lt;/h3&gt;

&lt;p&gt;I had Gemini work on a file that mixed front-end and back-end logic, and it moved forward with a fix while quietly missing a gap in security-related processing.&lt;/p&gt;

&lt;p&gt;I only caught it because I later handed the code to Claude Opus, which flagged it immediately: "This code is missing its security processing." If I hadn't run that second check, I wouldn't have caught it.&lt;/p&gt;

&lt;p&gt;Whether Gemini actively removed it or simply missed an existing gap is unclear, but I've since made it a habit to verify any security-related code with a separate model or by hand after Gemini edits it. For complex cases, doing it myself often ends up being faster anyway.&lt;/p&gt;

&lt;h3&gt;
  
  
  Long-context ingestion is mediocre — but that's not unique to Gemini
&lt;/h3&gt;

&lt;p&gt;Feeding in large amounts of text at once degrades accuracy. This happens with Claude Opus too. Bulk long-context reading is an industry-wide problem, not a Gemini-specific one.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Get the Most Out of It
&lt;/h2&gt;

&lt;p&gt;After a week of use, what became clear is that Gemini 3.5 Flash is a model that's very sensitive to &lt;em&gt;how&lt;/em&gt; you use it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stick to well-scoped, simple tasks&lt;/li&gt;
&lt;li&gt;If you can write a precise instruction document, bulk edits are fair game&lt;/li&gt;
&lt;li&gt;For security-related code, verify with a separate model or by hand after any Gemini edit — and for complex cases, just fix it yourself&lt;/li&gt;
&lt;li&gt;For complex problems, going straight to Opus or Sonnet is often faster overall&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How I Split Work Between Claude and Gemini
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;Better Model&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Simple repetitive edits&lt;/td&gt;
&lt;td&gt;Gemini 3.5 Flash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bulk file edits (with a solid instruction doc)&lt;/td&gt;
&lt;td&gt;Gemini 3.5 Flash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security-related code&lt;/td&gt;
&lt;td&gt;Claude, no question&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Problems with complex interdependent logic&lt;/td&gt;
&lt;td&gt;Claude Sonnet / Opus&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Core architecture and foundation work&lt;/td&gt;
&lt;td&gt;Claude Opus&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Long-context bulk ingestion&lt;/td&gt;
&lt;td&gt;Neither is great&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Gemini's strengths are speed and volume. Claude's are complexity and precision. It's not about which is better — it's about matching the model to the task.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Gemini 3.5 Flash is a powerful tool for developers who use it deliberately. But if your approach is "just throw it at the AI and see what happens," expect to be let down.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand the token consumption rate and plan your costs accordingly&lt;/li&gt;
&lt;li&gt;Invest in writing better instruction documents&lt;/li&gt;
&lt;li&gt;Always verify security-related code with a separate model or by hand — complex cases are usually faster to fix yourself&lt;/li&gt;
&lt;li&gt;For genuinely complex problems, consider reaching for a different model from the start&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you read this alongside my previous benchmark article, you'll get both sides: what it can do in controlled testing, and what it's actually like in daily development.&lt;/p&gt;




&lt;h2&gt;
  
  
  Appendix: Music Analysis via URL Doesn't Work
&lt;/h2&gt;

&lt;p&gt;Unrelated to development, but I saw claims that "Gemini 3.5 improved significantly at music analysis," so I tested it by passing a YouTube link and asking it to analyze the track. It started describing a completely different song.&lt;/p&gt;

&lt;p&gt;In hindsight, the model isn't actually listening to the audio at the URL, so this shouldn't be surprising — but there's a meaningful gap between the hype and the reality. For music, my own ears and knowledge are faster and more accurate.&lt;/p&gt;




&lt;p&gt;I build Mac × Android utilities as a solo indie developer.&lt;br&gt;
X → &lt;a class="mentioned-user" href="https://dev.to/hiyoyok"&gt;@hiyoyok&lt;/a&gt;&lt;/p&gt;

</description>
      <category>gemini</category>
      <category>claude</category>
      <category>ai</category>
      <category>tauri</category>
    </item>
    <item>
      <title>What I Learned Shipping 7 Mac Apps in 12 Months — The Honest Retrospective</title>
      <dc:creator>hiyoyo</dc:creator>
      <pubDate>Tue, 26 May 2026 13:20:34 +0000</pubDate>
      <link>https://dev.to/hiyoyok/what-i-learned-shipping-7-mac-apps-in-12-months-the-honest-retrospective-48j</link>
      <guid>https://dev.to/hiyoyok/what-i-learned-shipping-7-mac-apps-in-12-months-the-honest-retrospective-48j</guid>
      <description>&lt;p&gt;All tests run on an 8-year-old MacBook Air. All results from shipping 7 Mac apps as a solo developer. No sponsored opinion. Seven apps. Twelve months. One developer. Here's what I'd tell myself at app number one.&lt;/p&gt;

&lt;p&gt;Ship earlier than you're comfortable with&lt;br&gt;
The first version of every app I shipped was incomplete. That's correct. The users who buy version 1.0 are telling you what they actually need. No amount of building in isolation produces that signal. The features I was most proud of at launch often weren't the ones users cared about. The features users wanted most were often things I hadn't thought of. Ship, then iterate.&lt;/p&gt;

&lt;p&gt;Free tools are more valuable than paid tools at the start&lt;br&gt;
HiyokoLogcat is free and open source. It's driven more paid app sales than any other marketing I've done. A free tool that solves a real problem builds trust and audience. Users who trust your free tool buy your paid tools. The funnel works.&lt;/p&gt;

&lt;p&gt;The platform matters less than the problem&lt;br&gt;
I agonized over Gumroad vs App Store, Tauri vs Electron, Rust vs Swift. None of these decisions mattered as much as: does this solve a real problem for a real person who will pay for it? Pick a platform and build. Optimize the platform decision later.&lt;/p&gt;

&lt;p&gt;AI makes solo development viable at a scale it wasn't before&lt;br&gt;
I couldn't have shipped 7 apps this fast without AI assistance. Not because AI writes the code — it doesn't, not reliably. But because AI compresses the time between "I don't know how this works" and "I understand this well enough to build it." The bottleneck shifted from "can I figure this out" to "do I have time to build it." That's a better bottleneck. If you're a solo developer who's been hesitant about AI tooling — it's not about replacing your judgment. It's about spending less time being stuck and more time building.&lt;/p&gt;

&lt;p&gt;The things that didn't matter&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Perfect architecture on v1&lt;/li&gt;
&lt;li&gt;Comprehensive test coverage before shipping&lt;/li&gt;
&lt;li&gt;Having a large audience before launching&lt;/li&gt;
&lt;li&gt;Waiting until I felt ready&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these mattered. Shipping mattered. Everything else is refinement.&lt;/p&gt;

&lt;p&gt;What actually moved the needle&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solving a problem I had myself&lt;/li&gt;
&lt;li&gt;Writing about what I built&lt;/li&gt;
&lt;li&gt;Making the free tool good enough that people shared it&lt;/li&gt;
&lt;li&gt;Responding to every user question personally&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Small things. Done consistently.&lt;/p&gt;




&lt;p&gt;If this was useful, a ❤️ helps more than you'd think — thanks!&lt;/p&gt;

&lt;p&gt;Hiyoko Kit → &lt;a href="https://hiyokomtp.lemonsqueezy.com/checkout/buy/2c94dd0f-e28a-4a17-8efc-7bd93087d46d" rel="noopener noreferrer"&gt;https://hiyokomtp.lemonsqueezy.com/checkout/buy/2c94dd0f-e28a-4a17-8efc-7bd93087d46d&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;X → &lt;a class="mentioned-user" href="https://dev.to/hiyoyok"&gt;@hiyoyok&lt;/a&gt;&lt;/p&gt;

</description>
      <category>tauri</category>
      <category>rust</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
