Unofficial automated RSS/Atom links from the source ainoya.io, covering The author builds local-first journaling and workout apps and explains implementation choices. Original creators are credited at the source; follow original links. Zaps support the independent feed operator, not the source creators.
Public Key
npub16zna8909fjxlma4ana3m0930j9deymt2z3dc4us8fm8dke84e6asvl897l Profile Code
nprofile1qqsdpf7njhj5er0a767e7cahjchezkujd44pgku27gr5ankmvn6uawcpp4mhxue69uhkummn9ekx7mqppamhxue69uhkummnw3ezumt0d5q3gamnwvaz7tmjv4kxz7fwv3sk6atn9e5k7wx5myf
Show more details
Published at
2026-10-16T03:50:18Z Event JSON
{
"id": "7c9b8923a9da712248e9b4a9ec2aa03ef6d114dbdaefb828afbf631e6b8d03d0" ,
"pubkey": "d0a7d395e54c8dfdf6bd9f63b7962f915b926d6a145b8af2074ecedb64f5cebb" ,
"created_at": 1792122618 ,
"kind": 0 ,
"tags": [],
"content": "{\"subject\":\"The author builds local-first journaling and workout apps and explains implementation choices\",\"icon_attribution\":{\"source\":\"https://github.com/twitter/twemoji/tree/v14.0.2/assets/72x72\",\"creator\":\"Twitter and contributors\",\"license\":\"CC BY 4.0\",\"license_url\":\"https://creativecommons.org/licenses/by/4.0/\"},\"name\":\"ainoya.io (Unofficial)\",\"display_name\":\"ainoya.io (Unofficial)\",\"about\":\"Unofficial automated RSS/Atom links from the source ainoya.io, covering The author builds local-first journaling and workout apps and explains implementation choices. Original creators are credited at the source; follow original links. Zaps support the independent feed operator, not the source creators.\",\"picture\":\"https://cdn.jsdelivr.net/gh/twitter/[email protected] /assets/72x72/1f58b.png\",\"website\":\"https://ainoya.io\",\"nip05\":\"[email protected] \",\"lud16\":\"[email protected] \",\"bot\":true}" ,
"sig": "4ce686e046bd82c0bdcbd4717602b281fb575a6a6009c0d7d2651f92bc8f0cfa348214ec73cfad4ac24320472a87d8f124d462480d148a088208d07588315f72"
}
Last Notes npub16zna8909fjxlma4ana3m0930j9deymt2z3dc4us8fm8dke84e6asvl897l ainoya.io (Unofficial) Letting AI Agents Untangle a Stuck iCloud Sync When iCloud sync gets tangled I like handing a stuck iCloud sync to an AI agent. Sometimes the state of the files and folders gets tangled enough that syncing stops. A symlink left behind while rearranging folders, for example, can get in the way of synchronization. Investigating this myself can swallow as much time as I let it. An AI agent, with its stubborn persistence and seemingly endless willingness to keep trying, can work through the mess and get things moving again. Small problems around me I see similar uses for agents in other everyday tasks: Tuning local network performance Improving local network security Operating business applications through all those little clicks What interests me is how much value AI can deliver when I put it to work on these small problems around me. The payoff can be surprisingly large for something that sounds so mundane. https://ainoya.dev/posts/letting-ai-agents-untangle-icloud-sync/ #stuckicloud #icloudsync #agentsuntangle #small #improving #operating #sometimes #ai #rss #feeds #linksharing #qwibbit npub16zna8909fjxlma4ana3m0930j9deymt2z3dc4us8fm8dke84e6asvl897l ainoya.io (Unofficial) The Dark Forest Web Web services in Japan have been hacked one after another lately, and there are suggestions that AI agents are behind the attacks. Following the news, I started to picture a web where a service gets hacked the moment it goes public. It reminded me of the dark forest in Liu Cixin's Three-Body trilogy. Automated attacks are nothing new. Shodan, Masscan, and Mirai all show that anything reachable on the internet has long been scanned and attacked, and Mirai already automated everything from scanning to infection back in 2016. What AI changes is how cheaply an attacker can adapt to each target, probing its specific weaknesses and adjusting tactics based on what it finds. That widens the range of targets and techniques. What worries me is a web where a public service gets attacked continuously, with tactics tailored to it, even if no human attacker ever chose it as a target. In the second book, The Dark Forest, the universe is a dark forest. Every civilization is an armed hunter moving quietly through the trees, and any civilization that reveals its location is wiped out by another. A web where an attack follows discovery, with no one deciding to make it, follows the same rule. Publishing a service is revealing your location. The same situation can also be compared to the sophons. In the novel, the Trisolarans send sophons to Earth, and through them they can see and hear everything humans do. Only what stays inside human minds is hidden, and humanity is placed under near-total surveillance. If agents are probing everything that is reachable, the web is in a similar state: nothing publicly exposed can count on going unnoticed. Spoilers for the trilogy follow. In the novel, the standoff is held in place for a while by mutual assured destruction. Luo Ji threatens to broadcast the location of the Trisolaran star system to the universe, which would doom both civilizations. In the third book, that deterrence breaks down. But on the web, there may be no equivalent deterrent. Later, the Trisolarans communicate through a humanoid android called Sophon, controlled by the sophons. She serves as an instrument of surveillance and domination, yet eventually helps individual humans. The same intelligence can be a threat or an ally, depending on whose goals it serves. Unlike civilizations in the dark forest, web services cannot survive by staying silent. They exist to be discovered. If AI agents make attacks cheap and relentless, the defenders may have to become just as autonomous. https://ainoya.dev/posts/dark-forest-web/ #darkforest #web #liucixin #mirai #automated #rss #feeds #linksharing #qwibbit npub16zna8909fjxlma4ana3m0930j9deymt2z3dc4us8fm8dke84e6asvl897l ainoya.io (Unofficial) Write Heavy, Read Light: Clarity Is the Writer's Job Earlier today I came across an online discussion about whether you should react to Slack posts with :thinking_face: or :eyes:. The people who use them usually mean well: "I'm thinking about it" or "I'm looking at it." But the person who wrote the post can read those reactions in other ways. A thinking face might mean the post is controversial, or that the reactor disagrees. Eyes might mean they saw it and nothing more, and the poster has no idea what happened after that. A reaction is extremely easy to leave. The cost shows up when someone reads it: the reactor's intent is unclear, and the poster has to guess. I think business communication should work the other way around. The writer takes on the cost so that the reader doesn't have to. I call this Write Heavy, Read Light. Heavy here means effort, not length: the writer does the work of removing room for interpretation. Ambiguity is paid for in the reader's time If you abstract the Slack example, you get a pattern that I think is common. Someone sends a message or an instruction in an ambiguous form. The receiver misreads it, or comes up with several interpretations, and time is wasted sorting it out. I believe this leads to rework, delays, and wasted hours more often than we notice. This doesn't make reactions bad in themselves. If everyone in a channel agrees on what a reaction means, it is cheap to leave and cheap to read. The trouble starts when only the person reacting knows what it means. Slack reactions are only one case. Here are two more. Instructions without background Ordinary messages and instructions can be ambiguous too. One common form is the bare command: "Do X," with no background at all. If the receiver doesn't know what the work is for, they can't move on their own, and you end up having to keep giving them instructions. A command alone rarely carries enough for the receiver to work out your intent. I see it working only in a high-trust organization where people already share enough context. Abbreviations move the cost to the reader Abbreviations are another example. A long term gets compressed into two or three letters to make it quicker to get across. It works like dictionary-based compression. Compressing is cheap for the writer, but it puts a heavy load on the reader. So using abbreviations is a trade-off. What matters is whether the abbreviation is part of the reader's vocabulary. Abbreviations save time only when the reader already knows how to decode them. To decompress an abbreviation, the reader needs the dictionary, and the abbreviation makes carrying that dictionary the reader's job. The load is heaviest on people who just joined and on anyone who doesn't have the context yet. I think this does more harm than it seems to. Written once, read a hundred times There is a common lesson about writing documentation: you write it once, and it gets read a hundred times. A message may be read by many people, often more than once. With that in mind, you should write clearly enough that what you intended actually comes across, leaving as little room for interpretation as possible. One way to see why: the cost of a message is the cost of writing it, plus the number of reads times the cost of understanding it each time. Extra effort while writing is paid once. Any reduction in the cost of understanding is multiplied by every read. This also explains when reactions and abbreviations are fine. If the reader already shares their meaning, the cost of understanding is close to zero, and the shortcut costs almost nothing. I think this matters for business communication in general, not only for documents. The goal isn't to write more. It's to make understanding easier. Every ambiguity we leave behind becomes a decision someone else has to make. Write Heavy, Read Light is about making those decisions while writing, instead of leaving them to every reader. https://ainoya.dev/posts/write-heavy-read-light/ #readlight #job #writeheavy #slack #instructions #rss #feeds #linksharing #qwibbit npub16zna8909fjxlma4ana3m0930j9deymt2z3dc4us8fm8dke84e6asvl897l ainoya.io (Unofficial) Spending the Google AI Pro Cloud Credit on Transcription A Google AI Pro subscription includes $10 of Google Cloud credit every month. If you do not run anything on Google Cloud, it is easy to end up not knowing what to do with it. I spend mine on transcription for Ayumi, the voice-journaling app I am building. Recordings go to Gemini 3.8 Flash through the Gemini API, and the bill is paid out of that credit. Whether the credit covers the Gemini API My setup uses postpaid billing: Ayumi's API key belongs to an AI Studio project linked to a regular postpaid Cloud Billing account. In that setup, the credit does apply. In the billing report for that project from July to October 2026, the usage appears under the Gemini API service, and the credit offset ¥2,147 of ¥2,159. Prepaid billing is less clear, and it matters because the Gemini API billing guide says new users default to the prepaid plan. A June 2026 thread on the Gemini developer forum reports that the AI Pro credit could not be used for an AI Studio project on prepaid billing; Google Support's reply there said promotional credits cannot fund the prepaid balance. The billing guide, as of October 2026, describes the prepaid plan this way: the minimum purchase is $5, and once you have a positive prepaid balance, eligible Google Cloud credits are consumed before that balance. When the prepaid balance reaches $0, credits stop being consumed and the API keys stop working, even if credit remains. The guide does not say whether the AI Pro credit counts as eligible, and I have not tried the prepaid route myself. The credit also does not have to be spent in the month it arrives. Each monthly grant is a separate credit valid for one year, and I currently have five grants that are still untouched. How many hours $10 buys The figures below come from the token counts I measured in kikitori-bench, my ASR benchmark: 3 hours 5 minutes of unscripted Japanese voice-journal audio, priced at the Gemini API paid-tier list prices as of October 2026. Model Cost per hour of audio Hours for $10 Gemini 3.8 Flash about $0.21 about 47 hours Gemini 3.8 Flash (thinking off) about $0.09 about 107 hours Gemini 3.5 Transcribe about $0.30 about 33 hours Gemini 3.5 Flash-Lite (estimate) about $0.04 about 220 hours Gemini 3.8 Flash, with thinking left at the API default, is the one I use. In my benchmark it scored highest on my recordings, and roughly 47 hours a month is far more than I dictate into a journal. Turning thinking off more than doubles the hours. In kikitori-bench, it cut the ASR cost by more than half and lowered the overall score from 76.1% to 71.1%. Gemini 3.5 Transcribe is the dedicated transcription model. It is the most expensive of the four per hour, and on my audio it scored below Gemini 3.8 Flash. Flash-Lite is the cheapest option. I have not benchmarked it, so its row is an estimate: the same input token count at Gemini 3.5 Flash-Lite's rates ($0.30 per million audio input tokens, $2.50 per million output tokens), with the output token count of the thinking-off run. I do not know how accurate it is on my recordings. Caveats These numbers come from one speaker's Japanese dictation. Output token counts depend on the language and on how much the model thinks, so your hours will differ. The Gemini 3.8 Flash price is a promotional rate that runs through December 31, 2026. From January 1, 2027, input goes from $0.75 to $1.50 per million tokens and output from $3.75 to $7.50, which halves the hours in the first two rows. If your credit is sitting unused, I hope this gives you one idea for it. https://ainoya.dev/posts/google-ai-pro-gcp-credit-for-transcription/ #geminiapi #googlecloud #cloudcredit #pro #prepaid #flash #billing #transcription #googlesupport #october #rss #feeds #linksharing #qwibbit npub16zna8909fjxlma4ana3m0930j9deymt2z3dc4us8fm8dke84e6asvl897l ainoya.io (Unofficial) Sampling Video Without Decoding Every Frame While adding video import to Ayumi, I wanted to reduce how much video I sent to Gemini, especially when uploading over a mobile connection. Sending the original camera video meant transferring far more data than I wanted for a transcription-oriented journaling workflow. Gemini's default static video processing samples one frame per second. If Gemini looks at one frame per second anyway, uploading thirty frames per second mostly transfers pictures it does not use. Supported models also offer an agentic mode that dynamically explores the timeline and inspects content as needed, as described in Google's video-understanding documentation; a one-frame-per-second proxy would leave that mode less to explore. For my transcription-oriented use case, static processing seemed sufficient, although I have not compared the output quality of the two modes. That led me to explore sampling and compressing the video on the device before sending it. Having Gemini sample an uploaded original would still require transferring that original. I wanted to reduce upload traffic and mobile-data costs by sending a smaller video in the first place. The preprocessing happens on the device; the resulting proxy still goes to Gemini for cloud processing. My first AVFoundation pipeline decoded a 4K HEVC track, kept one frame per second, and wrote those frames as H.264. I also needed still images for the resulting entry. The output was small, but preparing it still took several seconds for a short clip. I questioned why dropping so many frames was still slow. The drop happened after AVAssetReader had decoded each frame. Writing one frame per second had not removed the work of decoding thirty. Remove the writer to find the cost I tested the read paths separately on a Mac with a synthetic 4K HEVC, 30 fps clip: six generated scenes with text-to-speech narration, lasting about 44.6 seconds. A second input repeated that sequence eight times, lasting about six minutes. Neither input was a private journal recording. The microbenchmark did no video writing. It compared decoded reader output, compressed reader output, and AVAssetImageGenerator requests at one-second intervals. The image generator's maximum size was 640 × 640. Read path 44.6 s clip ~6 min clip Decode every frame 7.16 s 57.73 s Read compressed samples 0.06 s 0.41 s Request 1 image/s, ±0.5 s 0.46 s 3.84 s Request 1 image/s, zero tolerance 0.76 s 6.13 s The decoded reader returned 1,338 frames for the short clip. The tolerant image generator returned 45 images. This isolated the expensive part: reading compressed samples was cheap in this run, while turning all of them into pixels was not. These are single-run microbenchmarks, not complete proxy-export times or an iPhone speed claim, and they do not predict the cost for a different encoding or longer keyframe intervals. The sparse path also reduces image dimensions, so the table compares work I could omit for this importer rather than identical outputs. The zero-tolerance path returned 44 images on the short input and 356 on the long one, one fewer than the tolerant path in each case. The harness skipped failed requests, so I did not establish that exact-time requests succeed at every timestamp. Request sparse images before encoding I replaced the full-track video reader with AVAssetImageGenerator, then fed the generated images to AVAssetWriter. Audio still goes through a separate reader. The same generated images also supply candidate stills, so preparing the proxy and preparing those stills share one extraction pass. The relevant setup in the builder is: let generator = AVAssetImageGenerator(asset: asset) generator.appliesPreferredTrackTransform = true generator.dynamicRangePolicy = .forceSDR generator.maximumSize = CGSize(width: options.stillLongSide, height: options.stillLongSide) let tolerance = CMTime(seconds: 0.5 / options.framesPerSecond, preferredTimescale: 600) generator.requestedTimeToleranceBefore = tolerance generator.requestedTimeToleranceAfter = tolerance The production builder requests larger images than the microbenchmark, 1920 pixels on the long side by default, because they also become stills. It scales those pixels down for the proxy, whose default short side is 360 pixels. The benchmark's 0.46 seconds therefore does not describe this whole builder. The tolerance is half the sampling interval, 0.5 / fps, which is ±0.5 seconds at the default one frame per second. Apple documents that the default tolerance is unbounded, and that setting both tolerances to zero requests frame-accurate generation and may add decoding delay. Allowing half an interval on either side leaves room to use a nearby image that is cheaper to produce, while keeping each picture no farther from its own sample time than from the next one. In the extraction-only benchmark, going from zero to ±0.5 seconds cut the time from 0.76 to 0.46 seconds on the 44.6-second clip and from 6.13 to 3.84 seconds on the six-minute one, though the two paths did not return the same number of images. A nonzero tolerance still does not promise that every request uses a keyframe or avoids all intermediate decoding. I have not shown that ±0.5 seconds is the best value. I did not compare it with ±0.1 or ±0.25 seconds, or measure how the time offset affects recognition quality. I took it as a compromise between speed and timing accuracy. That choice has a visible boundary. The builder writes each image at the requested presentation time and records that requested time for the still. The picture can come from a nearby source time. This is a sampled proxy, not a frame-accurate editing timeline. Check the pixels as well as the duration A smaller output file would not catch a sideways or cropped picture. The builder's regression test creates a landscape-encoded red-and-blue clip with a portrait display transform and a synthetic audio tone. It checks that the proxy is physically 360 × 640 with an identity transform, red above blue, three candidate stills for a three-second input, and a 16 kHz mono AAC track. A separate test covers video with no audio. Those tests establish the synthetic geometry and audio paths. They do not establish HDR appearance, Gemini's interpretation of arbitrary video, or long-video performance on a phone. The frame-generation loop also skips failed image requests, leaving the preceding proxy frame visible longer; successful export alone is not a check that every requested image was produced. For this importer I kept the tolerant, sparse-image path. Decoding fewer pictures changed the work before the encoder, while dropping pictures afterward had only changed what I wrote. https://ainoya.dev/posts/sampling-video-without-decoding-every-frame/ #everyframe #gemini #hevc #sending #request #rss #feeds #linksharing #qwibbit