🏡


  1. November 15, 2026
    1. 🔗 Register Spill Joy & Curiosity #106 rss

      In the Company of the Future episode of Raising An Agent, Quinn and I talked about what a typical week at Amp looks like:

      • I send out a message to the team on Sunday or early Monday morning. Not always, but when I think it's needed or when I'm in the mood to write. There's no strict formula, but these messages are often about what Quinn and I think are the most important things we should be thinking about.

      • On Monday morning we then have our team meeting. That's the only scheduled meeting we have.

      • In that meeting we talk about what's important, then we have silent writing time in which everyone writes down what they plan to ship this week. Then we go through that list.

      • Then we all work on what we talked about and constantly talk to each other in Amp or on Slack.

      Justin Jackson decided to implement this at Transistor: message with important things, then meeting on Monday. And he seemed very happy about the outcomes!

      So I thought I'd share a little bit about that Monday meeting (since it's coming up tomorrow and already on my mind) because in the podcast we didn't get into the details of it. But, disclaimer: it's a very simple meeting, it's not perfect, it's slightly different each week (intentionally so!), and if you've ever been a part of one you might smile at the idea that there's anything really worth talking about.

      Here's the top of the Monday meeting Google Doc right now:

      It's important that everyone on the call has that document open and is fully focused on it. No other windows, not prompting the agent on the side. People should pay attention, listen to what others are saying, and build up peripheral vision of the whole team. It's the only meeting in the week, it's an hour. Everyone should be able to focus.

      (Also: everybody should have their camera on!)

      There are four sections to the meeting: Leave , Talk , Shipping , News Posts. And that already makes it sound fancier than it is.

      Because what the whole thing boils down to is this: get everybody on the same page as to what's important this week and together figure out how to achieve those goals or solve those problems. The rest is just there to help.

      For the first five minutes of the meeting, we shoot the shit and just talk about whatever until everybody's in the call.

      Then we talk about Leave : who's out this week, who's out next week, who's maybe out in 3 weeks. My rule of thumb: the longer you're off, the earlier you should tell your team about it. If you're off on Friday, it's fine to share that on Monday. If you're going to be off for two weeks in the jungle somewhere, you should probably share that two, three weeks in advance. Be an adult.

      After that, we get to the main thing of the meeting, the Talk section. In the screenshot above, you can see that I've already put three topics in. These are the most important things I think we should talk about tomorrow. Everybody can add their own topics. While talking about things, we might add sub-bullet- points and notes and links and whatnot.

      The Talk section takes up 45min or so. I try to be a good timekeeper and watch the clock so we can get to everything that's in the doc. I probably say "any thoughts, questions, concerns, ideas?" ten times in that meeting, before moving on to the next section. I want everybody to participate.

      The results of Talk are different each week: sometimes we find new things to do while talking and I might ask "who wants to own this?" Other times we conclude that we just need to keep doing what we've been doing that week. Or we call out 4-5 things that we need to ship ASAP and formulate a plan for that. Or we all think there's a single most important thing that week and we try to figure out how we can all contribute.

      It's very loose. Anything goes really. Again, the goal is alignment and everybody being on the same page. The goal isn't to follow The Process. Many roads lead to alignment.

      After Talk and towards the end of the meeting, we get to Shipping and News Posts. For that, I set a timer on my phone, for 2-3 minutes, and we all write down in silence what we plan to ship this week. The goal is to be ambitious. Don't write down things you check off a few hours later. We talked about the important things, now the question is: how are you planning to contribute based on that?

      (Last year, when new people joined the Amp team, I often said: the first task on the Amp team is to figure out what your first task should be. I know it sounds silly, or rude, or like we're throwing people into the deep end, and maybe we are, but it's an incredible filter. There are tremendously good people who can show up and after 45min of talking go "how about I do …" Everybody on the Amp team is like that.)

      When the timer rings, we go through the list top to bottom, and everybody says in 2-3 sentences what their goal for the week is, their focus areas. I might ask follow-up questions or suggest collaboration, or others might ask whether they can help, etc.

      While we go through that, we try and make sure to note down any News Posts(see ampcode.com/chronicle) we need to write and ship that week. In other words: what are you planning to publicly release that week and when exactly? It's important to at least get a rough sense of the timeline, so we don't end up with 3 major features being shipped on the same day.

      And… that's it. Then everybody goes off and works on their thing.

      But that doesn't mean we won't talk to each other again for a week. No, it's the opposite. There will be lots of in-progress work being shared in #wip and others will ask and give feedback. There will be huddles and tagging of each other in Amp. There will be feedback in #orb-good and #orb-bad and plans will get adjusted based on that.

      Could the meeting be better? Sure. But I do think we've hit on a sweet spot where we have just enough process for everybody to be aligned but little enough so it's not a pain in the ass and we have freedom to adjust plans often.

      • And they say models can't be creative: "I asked Fable 5.2 to 'go wild' making a game, and all I got was this Pong clone. And then I played it ..."

      • You have more influence over the future than you think: "The future will be fun. It will be exciting. You will soon be able to create any digital artifact imaginable within a couple of minutes. And many physical artifacts too, though that part is a bit more unclear to me."

      • Linus on "keeping the flame": "Counterintuitively, I've come to learn that keeping the flame alive is far more important to the integrity of our creative pursuits than actually producing the work itself. If we put something into the world that disappoints us, that's okay. We can try again tomorrow, and the day after that, and after that, because the flame will still be there. But if we let the flame wither, by letting the firewoods run out or allowing others to blow it out, there is no tomorrow. There is no fight left in us. We have to start all over again, which may take months, or even years. How do we keep the flame alive?"

      • And since we're talking about creativity… In case you've never seen this clip of Paul McCartney composing Get Back I highly recommend you do. It's an impressive clip on its own, but in the context of the whole Get Back documentary it's extraordinary. They sit there in this huge warehouse studio, they're bored, they're waiting a lot, and not much is going on; they're drinking tea and talk; there's a crew standing around looking at them at all times. And then McCartney feels like he has to push things forward and do something and he sits down and George and Ringo are yawning and it's what I imagine to be the least inspiring atmosphere and yet McCartney starts riffing and that song emerges…. It's very easy and comforting to think that creativity is something that happens or doesn't and that you can't do anything about it. And, hey, that's true, the phrase "some things you can't force" isn't just a cliche. But sometimes, man, I think sometimes you just have to put your head down and see if you can't make creativity happen.

      • I'm really not a big space guy (don't know why, honestly; rockets & space are cool but don't excite me that much), but this was one hell of a video: "Mechazilla catches Starship! Congratulations to the entire SpaceX team on this incredible achievement!" The music! Is that Steely Dan? Who puts such chill music on for this moment? And then it cuts out and you go "holy shit" and then the music comes back and you wonder whether you just watched a little recap scene from a movie filmed in 2053.

      • Paul Ford: The Web Is More Than Enough. Hell yes! I love the web. I stored the link to this post in a little web app that I built on my phone. A native app would be nice, but man, the web is so much better. I can run an agent on the box on which the web app is running, I can deploy ten trillion times a day, I can get easy debug logs, … The web is awesome.

      • This is very, very, very, very, very good: Writing as a thinking tool. So many things to quote here -- the part about writing in the age of LLMs, the "Mess up" rule, the thought about externalized thinking -- so go and read it and then write something.

      • Michael Crichton, psychology, and AI. In the last two years, we've all heard many "… but only a human can do this" claims only for them to look silly a couple months later. So now, whenever something just starts to sound like it's a similar claim, my eyebrows go up. But this one is different. At least I think it is? Interesting stuff.

      • New Ways to Read Ebooks. I'm very much not a "I need to own all my ebooks as files on my disk" kinda guy. I love my Kindle and, hey, maybe love is too strong a word, but I like Amazon. But by now it's just frustrating that I can't give my agent access to my Kindle library and help me find quotes and answers. I'd even buy more books just so I can feed them to my agent, not to read them for me, but to help me refind and extract things. That's all I could think about while reading this post. And that I have to get Amp to hack my Xteink X4.

      • CHIMERA. I don't even know what to say here. It has taken over my brain. All day long I think of this voice. Click that link, watch that video. You must. And then watch these: one, two, three, four, five, six, seven, eight, nine, ten, eleven, and mine. After that, your brain has been taken over too. The next step is to then fork CHIMERA and point your agent at it and go crazy. And then lean back and think about what's going on. Think: if I had to make a computer emit sound like a human voice, how would I do it? And after you've thought about that for a while, remember what CHIMERA does: "my vocal synth models the vocal tract as a network of branching acoustic tubes." And then open it up again and think "this is fucking crazy."

      • If you ever feel sad, watch this video. Works every time.

      • What a job! "You don't have to tell me what day it is." There are just very few things better than watching someone be exceptional at what they do.

      If you think "meetings? fuck yeah!" then, uhm, I don't know. But I think you should subscribe:

    2. 🔗 smol-machines/smolvm smolvm v1.35.1 release

      What's Changed

      • docs: say that virtiofs DAX is off on arm64 hosts and SMOLVM_MOUNT_DAX does nothing there by @BinSquare in #2087
      • Add smolvm docker: one command starts a Docker engine in a managed machine and points docker at it by @BinSquare in #2089
      • Share the home directory with the smolvm docker machine at the same path by @BinSquare in #2090
      • Resolve host.docker.internal to the host from smolvm docker containers by @BinSquare in #2091
      • Fix a port race in the leader-exit test by @BinSquare in #2096
      • Remove smolvm docker by @BinSquare in #2095
      • Hand supplied credential values to a running embedded machine at once by @BinSquare in #2097
      • Pin libkrunfw with UDP kept inside a TSI guest, and test it by @BinSquare in #2099
      • Publish ports below 1024 on macOS, add IPv6 loopback to live-forwarded ports, and lift the 64-mapping cap by @BinSquare in #2092
      • Return idle guest memory to the host within two minutes and cap new machines at half the host's RAM by @BinSquare in #2094
      • Install a root-owned agent-rootfs when root runs install.sh by @rdslw in #2082
      • Announce a changed file to the guest once per change by @BinSquare in #2102
      • Answer guest DNS from a host cache that coalesces bursts and resends lost queries by @BinSquare in #2098
      • Keep every disk chain under the branch depth limit: fold restored checkpoint layers and frozen-source chains by @BinSquare in #2103
      • Exec sessions: commands the node owns, resumable after a dropped connection by @BinSquare in #2101
      • Let a guest hold tens of thousands of connections on virtio-net and free their host sockets promptly by @BinSquare in #2104
      • Scope the usage journal to the test's own thread by @BinSquare in #2106
      • Pin libkrun 526be460 and libkrunfw f290c62b, rebuilt for every platform by @BinSquare in #2109
      • Build the agent rootfs as non-root on hosts with user namespaces again by @BinSquare in #2107
      • Answer a start missing the mediated interceptor with 400, not 500 by @BinSquare in #2108
      • Run tests that need a released file lock free at once in their own process by @BinSquare in #2110
      • Pin libkrun 9df62257 and libkrunfw 7f4d4950, rebuilt for every platform by @BinSquare in #2113
      • Stop resetting virtio-net connections a server closes first by @BinSquare in #2118
      • Upgrade rusqlite to 0.41 for the patched bundled SQLite (RUSTSEC-2026-0459) by @BinSquare in #2128
      • Keep a host memory reserve VMs cannot take and charge branch children for growth by @BinSquare in #2127
      • Ask before stopping a machine on delete, so a refused or declined delete leaves it running by @connorburgess in #2131
      • Prepare SmolVM v1.34.1 for release by @BinSquare in #2135
      • Bring a soft open-file limit above kern.maxfilesperproc down to the cap on macOS, so the limit raise_nofile_limit reports is the one in force by @connorburgess in #2132
      • Leave no data directory behind when exec, status or stop name a machine that does not exist by @connorburgess in #2129
      • Warn when --block-private keeps a named host unreachable by @BinSquare in #2146
      • Register Rosetta itself as the x86_64 interpreter when the host answers its start-up ioctl by @BinSquare in #2148
      • Make a mounted host directory belong to the workload user so a non-root workload can write to it by @BinSquare in #2149
      • Record the image platform on the machine so a Rosetta machine can be created from an amd64 image by @BinSquare in #2147
      • Bump libkrun so a Rosetta machine runs amd64 programs directly and a macOS machine stops promptly by @BinSquare in #2150
      • Keep a cache disk's chain on its shared base when compaction shortens it by @BinSquare in #2145
      • Satisfy Rust 1.100's needless_bool lint in connect_in_progress on Windows by @BinSquare in #2154
      • Bound branch admission and reported capacity by the VM slice's memory limit, not just host free memory by @BinSquare in #2152
      • Stop throttling the VM slice and reclaim it from the pressure guard instead by @BinSquare in #2153
      • Release a paused branch child's VM lock so the memory pressure guard can resume it by @BinSquare in #2157
      • Keep a restored machine's local image on its storage disk instead of mounting the capturing host's archive by @BinSquare in #2163
      • Update quinn-udp to 0.5.16 for RUSTSEC-2026-0538 by @BinSquare in #2165
      • Count every symlink with one mode in the agent rootfs digest so a Mac checkpoint restores on Linux by @BinSquare in #2162
      • Carry guest traffic in 64 KB frames over the gateway link so downloads use a quarter of the CPU by @BinSquare in #2168
      • Pin libkrun 518949b4 and libkrunfw 0fae3853, rebuilt for every platform by @BinSquare in #2169
      • Reserve tmpfs for concurrent RAM captures and sweep abandoned checkpoint scratch at serve start by @BinSquare in #2173
      • Let a packed image's branch take the deferred checkpoint save and say when the VM died mid-save by @BinSquare in #2174
      • Integrate and validate Docker Engine, automatic ports, and nested Rosetta support by @BinSquare in #2172
      • Run x86_64 images in containers Docker starts inside a Rosetta machine, keeping their PID by @BinSquare in #2093
      • Serve the Docker Engine API from smolvm, every container a machine by @BinSquare in #2114
      • Publish the ports a machine starts listening on, with --auto-ports by @BinSquare in #2136
      • Give engine containers user-defined networks, so Docker Compose stacks run by @BinSquare in #2115
      • Let engine containers reach the Docker socket, so Testcontainers and Dev Containers work by @BinSquare in #2116
      • Branch engine containers from a warm base when many of one image run by @BinSquare in #2117
      • Publish engine container ports on the address each one names by @BinSquare in #2119
      • Give engine containers a volume for each VOLUME their image declares by @BinSquare in #2120
      • Move images in and out of the engine: save, load, push, commit, import, export by @BinSquare in #2121
      • Run --network container: containers in that container's machine by @BinSquare in #2122
      • Give engine networks IPv6 by @BinSquare in #2123
      • Run the Docker API on demand with independent workload supervisors by @BinSquare in #2175
      • Fix Buildx volume permissions and macOS restart stalls by @BinSquare in #2178
      • Improve default macOS shared-volume write performance by @BinSquare in #2179
      • engine: speed up macOS Buildx with automatic overlayfs snapshots by @BinSquare in #2181
      • Run the guest keep-alive init as root while workloads and execs keep the image user and its supplementary groups. by @BinSquare in #2004
      • engine: fix multi-stage Buildx builds containing deleted files by @BinSquare in #2183
      • Scrub injected credential values from what a credential host sends back by @BinSquare in #2180
      • Re-authorize a restored checkpoint's credential bindings from the CLI, and refuse a start that could not inject them by @BinSquare in #2182
      • Sweep a deleted machine's pause-operation lock along with its fork-operation lock by @connorburgess in #2184
      • Let machine update set and remove labels, in any machine state by @josmo in #2143
      • Leave the Docker Engine API opt-in so installing or upgrading smolvm never switches the user's Docker context by @BinSquare in #2186
      • Bump every workspace crate and the nix flake to 1.35.0 by @BinSquare in #2185
      • fix(network): retain OS-allocated local TCP listeners by @kumanday in #2112
      • Retry a checkpoint part the object store refuses with a transient error by @BinSquare in #2191
      • fix(shim): preserve foreground helper exit statuses by @hfiguera in #2190
      • Delete the image seed builder when a CLI start is interrupted, and reap builders whose owner exited (#2083) by @rdslw in #2188
      • Honor SMOLVM_DATA_DIR and --state-dir on macOS by @BinSquare in #2193
      • Map a mounted host directory to the workload user again, not the keep-alive init's root, so a non-root workload can write to it by @josmo in #2189

      New Contributors

      Full Changelog : v1.34.0...v1.35.1

    3. 🔗 HexRaysSA/plugin-repository commits sync repo: +1 plugin, +7 releases, -2 releases rss
      sync repo: +1 plugin, +7 releases, -2 releases
      
      ## New plugins
      - [BinQL](https://github.com/thalium/binql) (1.0.0)
      
      ## New releases
      - [btf2ida](https://github.com/nightshift-labs-ai/btf2ida): 0.1.22, 0.1.21
      - [cfiscope](https://github.com/nightshift-labs-ai/cfiscope): 0.1.19
      - [ida-mcp-bridge](https://github.com/eitapreulajhol/ida_mcp): 0.4.0
      - [memlens](https://github.com/nightshift-labs-ai/memlens): 0.3.27, 0.3.26
      
      ## Changes
      - [memlens](https://github.com/nightshift-labs-ai/memlens):
        - removed version(s): 0.3.2, 0.3.1
      
    4. 🔗 backnotprop/plannotator v0.28.65 release

      Follow @plannotator on X for updates

      Missed recent releases? Release | Highlights
      ---|---
      v0.28.64 | Installs and updates download a smaller, compressed copy, a Videos filter on the Artifacts page, GitLab comments on a whole file get their own thread, pull request pictures and videos show in the Inbox
      v0.28.63 | Pair Grok Bot and other cloud agents from Settings, Hermes Agent, OpenClaw and Muse Code can use the Inbox, add a thread to Priority to keep it on top, tag threads, and find each tag in the sidebar, Pull requests board as a table, with bulk Merge
      v0.28.62 | Agents started from the Inbox now work on Windows, pick a model and effort when you start an agent, rules for your agents, written in your own words, post a thread's decisions on its pull request, the Inbox loads faster on a slow connection
      v0.28.61 | Updates now update the Claude Code plugin too, an agent's chosen face shows on every icon of it, filter the Inbox list by pull request state, Modern dark shows section bands and the Reply button, one conversation no longer shows as two agents
      v0.28.60 | Click a word to highlight it, a one-time Themes dialog, Settings → Rows rebuilt, tell your agent how you want your rows, starred threads as pills above the list, a pill for new messages out of view, a half-circle face picker with ten Glass colours, a new phone sidebar and reply box
      v0.28.59 | A quieter Agents section in the sidebar, machine names only when agents run on more than one machine, agent icons that are always gently alive and lean toward your pointer
      v0.28.58 | Start Codex from New message, an Agents section in the sidebar, start an agent in a folder on any drive, play audio attachments and comment at a moment, Claude Code's Plannotator tools work on Windows
      v0.28.57 | Pin artifacts, and see every artifact on one page, filter the list by project, date or agent, a thread shows its pull requests and their state, choose what the sidebar shows, and in what order, Ask AI starts from Side in the selection bar
      v0.28.56 | Questions can show trade-offs and a prototype to try, a thread with many big pictures no longer crashes the tab, Escape closes New message and keeps your draft, read threads stop being bold and keep their place, agent messages that name no thread start a new one
      v0.28.55 | Floating reply drafts, now a setting under Experimental, open questions sit next to Reply again, a comment box that keeps unsent comments as Drafts, choose how your list looks: Minimal, Balanced or Detailed, update an older linked machine from this Inbox
      v0.28.53 | Start an agent in a new folder, or from a git URL, "+" on each project row starts a session there, a reaction tray, a thread's Links, Settings → Activity, New message offers the open thread's files, Bro mode: agents write to you in plain words
      v0.28.52 | Start agents from the Inbox, on by default, a new reply box, Ask AI for everyone, Insights in Settings → Decision data, Plannotator reloads itself after an update

      What's New in v0.28.65

      TL;DR

      • New: Take back a reply your agent has not received yet
      • Changed: Over Tailscale, Plannotator opens only for your own account
      • New: Tag a linked machine's threads; one tag across machines
      • Changed: T3 Code threads get the Inbox with no setup
      • Fixed: Long threads open on slow connections

      0.28.65 lets you take back a reply your agent has not received yet. Over Tailscale, Plannotator now opens only for the account that owns the computer. Tags now work across linked machines, and a T3 Code thread gets the Inbox without any setup. The release has 25 PRs. One is from an outside contributor, @stjepanvrbic, who made a first contribution.

      Take back a reply before your agent gets it

      Before, once you sent a reply, you could not change it while it waited for the agent. To correct it, you had to send a second message, which could leave two different instructions in the queue. Now a reply that no agent has received yet has a Take back button. It shows beside Send now on the waiting band, on the reply's delivery line, and in the message's ⋯ menu.

      Take back saves what you are typing first. Then it puts the reply's words and files back above it in your reply box, with the line "Taken back. Claude Code never got it. Send it again when it's ready." If the reply was the only message in its thread, the thread goes away and New message opens with the same words, files and recipient. When you send again, it goes as a new message.

      The Inbox keeps one rule for every agent: a message either is still yours or has been handed over. Once an agent has the message (it was delivered, an agent read the thread, or it went into Codex's queue or a T3 or cloud send), Take back is no longer offered. If you press it at the wrong moment, a quiet line explains why: "Claude Code already has this message, so it can't be taken back. Reply below to change it." A message that has been handed over now reads "Handed to Codex; it takes this at its next step." instead of offering Send now. A taken-back message is gone from every agent's read, from search, from Activity and from decision exports. There is no keyboard shortcut.

      #3290, #3291, #3293, #3294, requested in #3229 by @Arobotmaster

      Over Tailscale, only the account that owns this computer

      Plannotator has no sign-in and is for one person. Over Tailscale, the Inbox now opens only for the Tailscale account that owns the computer. That account gets the full Inbox from any of its devices. Any other Tailscale account is refused. A browser gets a short page that says "This Inbox belongs to this computer's owner" and names the account that tried. An API call, the event stream and /mcp get a 403 with tailnet_identity_refused.

      This is a behavior change. Before, the Inbox let in any other login listed in config.json inboxTailscaleAllow as a guest with a smaller Inbox. Sessions started with plannotator review --tailscale or plannotator annotate --tailscale opened for anyone on the tailnet. Both now refuse every account except the owner's. On a machine where Tailscale names an owner, inboxTailscaleAllow is ignored, and startup prints one line that says so. The key still names the owner on a tagged machine, which Tailscale gives no owner. A --tailscale session on a tagged machine with no inboxTailscaleAllow cannot tell who the owner is, so it does not start, and it says why.

      Phones and linked Macs are unchanged, because they connect through their own doors. If you shared an Inbox or a --tailscale review with another Tailscale account, that account can no longer open it.

      #3141

      Tags across linked machines

      With two linked Inboxes, such as a MacBook and a Mac mini, you can now tag a thread that lives on the other machine. Add tag is in the row's right-click menu, the phone's long-press sheet and the thread's ⋯ menu, when the other machine runs this version. Tags with the same name are one tag. Spaces at the ends and letter case are ignored, so "Release" and "release" match. When you open a tag in the sidebar, it lists the threads from both machines together, and its counts include them.

      Rename, Delete tag and the delete's Undo now change the tag on every linked machine that holds it, from the sidebar and from the Board's Tags dialog. If a machine is asleep, the change waits and applies when the machine is back. An older machine keeps its own tags, and nothing is sent to it. The Board's tag filter and Tags dialog also list tags that only the other machine holds.

      #3330

      T3 Code threads get the Inbox with no setup

      Before, a Claude thread in T3 Code needed three steps to use the Inbox: plannotator t3 login, a claude mcp add entry and a restart. Now the Claude Code plugin runs in a T3 thread's Claude by itself. The model gets the plannotator_inbox tool. Its messages are filed as that T3 thread, and your reply goes in as a new turn of the running session. T3 keeps its own Plan mode. The T3 sign-in stays useful as a fallback: T3 stops an idle Claude after 30 minutes, and after that the T3 wake sends what still waits.

      The plugin now also runs in claude -p, in other Agent SDK apps and in Claude Desktop. There the model gets plannotator_inbox and can write to your Inbox. Nothing wakes those sessions, so the send tells the agent to read the thread later. Plan review and reviews in those sessions work as before.

      When a reply to a T3 thread cannot go in, the Inbox now says why under the reply: no T3 sign-in, a sign-in that ran out, a sign-in that cannot send into that thread, or T3 not answering. Where signing in fixes it, the line shows the sign-in command with Copy. The line goes away once the reply is delivered.

      T3 threads also get two fixes. The Inbox now wakes every kind of T3 thread, not only threads made in the app. That includes threads made over T3's MCP, launched by an agent, scheduled, delegated or provider threads. A reply to a T3 thread also stays owed to that thread when another agent reads the Inbox thread first.

      #3362, #3365, #3261 by @stjepanvrbic closing #3311 reported by @agents-nils, #3348 closing #3339 reported by @stjepanvrbic

      Long threads open on slow connections

      On a slow link, a long thread could fail to open at all. The thread read had an 8-second limit for the whole answer. A 450-message thread is about 450 KB, so at 50 KB/s it could never finish, and the Inbox retried forever. Now the limit counts from the last bytes received, so a slow answer that keeps arriving is read in full. In a test at 50 KB/s, that thread opened in 8.8 s. A read whose bytes stop still fails, and a read cut off partway now shows as a failure instead of an empty answer.

      An attached HTML page is now sent compressed both ways, which cuts the bytes for each open from about 617 KB to 175 KB. The Inbox also sends less on its first load: Tater mode's pictures left the Inbox's script, which went from 2,510 KB to 1,991 KB. Switching threads, opening Settings, opening search and picking a file in code review redraw much less. The PR's measurements show these steps 10 to 25% faster.

      #3317, #3356

      The Inbox's SQLite store is removed

      0.28.63 added an Inbox store in SQLite, off by default. It is now removed, and the Inbox keeps its records in its files only. If you never turned it on, nothing changes. If your Inbox was on SQLite, it moves back to its files at the next start, with every message, and prints one line in the terminal or inbox.log. The database is kept as a read-only backup in a dated backup-…-sqlite folder inside the Inbox's data folder. If the database cannot be read, the Inbox does not start and does not change anything. It says where the messages are and how much disk to free. The inboxSqlite setting, PLANNOTATOR_INBOX_SQLITE, Settings → Storage's Backup group and plannotator inbox export are gone.

      #3320, #3326

      Code review in the Inbox: off by default

      These show only with Code review turned on in Settings → Capabilities.

      • Close pull requests from the board. Select mode on the Pull requests board has a Close N action. It closes the picked PRs one at a time through your own gh or glab. A toast says "Closed N" with Undo, and Undo reopens exactly those PRs. If a PR cannot be closed, the reason shows under the bar in the forge's words. Only the window can close a PR. No agent tool or command can. #3287
      • Post a GitLab review after new commits. Posting a review on a GitLab merge request that got new commits after you read it used to be refused. It now posts at the commit you read, as GitHub already did, with line comments placed on that version of the merge request. #3244

      Additional Changes

      • A self-managed GitLab at any address. A merge request, issue or work item link on a company's own GitLab, such as git.acme.com, is now recognized by its path, gets the GitLab mark, and attaches to a thread. With glab signed in to that host, it also shows live state. The Inbox learns such hosts from glab's own config file (host names only). Post decisions now runs only against github.com, gitlab.com or a host your gh or glab is signed in to. #3305
      • One Claude Code session is one participant. A Claude Code session that wrote through a hand-added plannotator inbox mcp entry could show up as "An agent" and "An agent 2" beside "Claude Code" in a thread's reply picker. It now shows as one participant, and a reply wakes it. #3336, reported in #3309 by @Arobotmaster
      • A sandboxed agent no longer replaces your Inbox. An agent whose shell cannot reach the Inbox's local address could start a second Inbox and stop yours, so the window had to ask for notifications again. Such a start now refuses with "Could not reach the running Inbox: …" and leaves yours running. #3354
      • Start lines in the debug log. With the Inbox's debug log on, each process that starts or waits for an Inbox writes what it waits for to inbox.log. This helps track down leftover Inbox processes. #3352, for #3350 reported by @zane668
      • Sidebar header buttons line up. In the sidebar, Agents' buttons now read Add machine, then Add agent, so Add agent sits under Tags' "+". While a section is closed, its buttons show when you hover or focus its header. #3328
      • A killed start no longer blocks the next one. A start that was killed while it took the start lock could make every start in the next 30 seconds fail with "try again". #3300
      • The agent face moves to the shared UI , so other parts of Plannotator can show the same animated agent face. The Inbox is unchanged. #3344
      • Test and guidance upkeep: #3307, #3327

      Install / Update

      macOS / Linux:

      curl -fsSL https://plannotator.ai/install.sh | bash
      

      Windows:

      irm https://plannotator.ai/install.ps1 | iex
      

      Claude Code Plugin: The install script above also updates the plugin when claude is on your PATH. Otherwise, in a terminal:

      claude plugin marketplace update plannotator
      claude plugin update plannotator@plannotator --scope user
      

      Then restart Claude Code. Inside Claude Code, run /plugin marketplace update plannotator, then open /plugin → Installed → plannotator → Update now.

      Pi:

      pi update npm:@plannotator/pi-extension
      

      OpenCode: Re-run the install script above. It also clears the OpenCode 2 plugin cache.

      What's Changed

      • Inbox: post a GitLab review after new commits, at the commit read by @backnotprop in #3244
      • Inbox PR review tests: load the TypeScript grammar before the first test by @backnotprop in #3307
      • Inbox: a start killed while taking the start lock no longer blocks the next start by @backnotprop in #3300
      • Inbox: remove the SQLite backend; an Inbox on it returns to its files by @backnotprop in #3320
      • Inbox: take back an undelivered message (server) by @backnotprop in #3290
      • Inbox: taken-back messages leave lists and counts; a handed item says so by @backnotprop in #3291
      • Inbox window: Take back an undelivered message by @backnotprop in #3293
      • Inbox take back: docs, and the relay, launch and old-plugin proofs by @backnotprop in #3294
      • Inbox way back: a starter no longer gives up as the Inbox finishes starting; the test holds on a file by @backnotprop in #3326
      • Agent guidance: one experience across a person's linked machines by @backnotprop in #3327
      • Inbox: recognise a self-managed GitLab at any address by @backnotprop in #3305
      • Frontend performance, batch 1: no bytes or redraws nobody asked for by @backnotprop in #3317
      • Inbox: one Claude Code session is one participant in a thread by @backnotprop in #3336
      • Inbox: tag a thread from any linked machine; one tag across machines by @backnotprop in #3330
      • fix(inbox): wake T3 Code threads whatever id T3 gives them by @stjepanvrbic in #3261
      • Inbox sidebar: Tags and Agents headers place and show their add buttons the same way by @backnotprop in #3328
      • Inbox: Close picked pull requests from the board, with Undo by @backnotprop in #3287
      • T3: a reply stays owed to its thread when another agent reads first by @backnotprop in #3348
      • Inbox: with the debug log on, each start says what it waits for (diagnostic for #3350) by @backnotprop in #3352
      • Inbox: a starter that cannot reach a running Inbox does not start a second one by @backnotprop in #3354
      • Share the Inbox's living agent face with the rest of the UI by @backnotprop in #3344
      • Over Tailscale, only the account that owns this computer by @backnotprop in #3141
      • Frontend performance, batch 2: slow links (long threads open; HTML pages sent compressed) by @backnotprop in #3356
      • Claude Code mod: active in every session, interactive or not by @backnotprop in #3362
      • Inbox: a reply waiting on T3 says why and what to do by @backnotprop in #3365

      New Contributors

      Contributors

      @stjepanvrbic wrote the fix that lets the Inbox wake T3 Code threads whatever id T3 gives them (#3261). The fix covers MCP, launched, scheduled, delegated and provider threads. He tested it against a real T3 Code and ran the full CI on his fork. He then reported the case it left open (#3339): another agent's read could take a reply meant for a T3 thread. He also warned that holding such a reply for good would strand a dead thread's reply. That warning shaped the fix in #3348.

      Community reports and requests that shaped this release:

      • @agents-nils reported that T3 threads made over MCP were never woken (#3311)
      • @sx4im opened a fix for the same mcp: case (#3313), closed in favor of the broader #3261
      • @Arobotmaster asked for a way to change a message before the agent gets it (#3229), which became Take back, and reported one Claude Code session showing as several anonymous agents (#3309)
      • @zane668 reported leftover background Inbox processes and found a reproduction (#3350), which led to the debug start lines and the sandbox fix

      Full Changelog : v0.28.64...v0.28.65

  2. November 14, 2026
    1. 🔗 HexRaysSA/plugin-repository commits sync repo: +1 release rss
      sync repo: +1 release
      
      ## New releases
      - [kflow](https://github.com/nightshift-labs-ai/kflow): 0.0.3
      
    2. 🔗 mhx/dwarfs dwarfs-0.15.10 release

      Bug fixes

      • Avoid integer underflow on problematic TTYs. Using mkdwarfs on narrow terminals with "live" (unicode or ascii) progress output would trigger an integer underflow and subsequently a huge memory allocation. Thanks to @cnt0 for reporting this issue and providing a fix.

      Full Changelog : v0.15.9...v0.15.10

      SHA-256 Checksums

      ad41e474be69825dced9ceea2bac8bf480a00821cd5bb801a740f000dc130812  dwarfs-0.15.10-Linux-aarch64.tar.xz
      4d296701212c210008519dac83ebd6825ffe80cef231d3bdd7afa7b78ee4f72b  dwarfs-0.15.10-Linux-arm.tar.xz
      6a8e2e78d6a27d8884784c7f2918f1a7f6f4bd89a9002e4e0e33d86e028b293b  dwarfs-0.15.10-Linux-i386.tar.xz
      5c91cdcef253cc1b580a5d5c7b8d26ad6fbc950d2e9ba294726460ea0640f0d2  dwarfs-0.15.10-Linux-loongarch64.tar.xz
      ba38a4e490cb82d66ac6703e0964136312d5ab16e621fc886a17d24ab405144c  dwarfs-0.15.10-Linux-ppc64le.tar.xz
      f2ad3def562d8d2dd0749be9155468cc617e19e03a0aa21e6929735f49f4a887  dwarfs-0.15.10-Linux-ppc64.tar.xz
      699d86ee030809edf3b02f33d3de01440948dce0dc11589ebc53b4ecddca110b  dwarfs-0.15.10-Linux-riscv64.tar.xz
      3339f4dcce39d6b9fc5b84a29866bfc5e6843e138251dffd1817cda64e351000  dwarfs-0.15.10-Linux-s390x.tar.xz
      cf90c6fca3b0a069bf5f0a2b66ca613ed78f53f0a9d1bc4a73c08330492cd4b3  dwarfs-0.15.10-Linux-x86_64.tar.xz
      036109bc210b5afa593a005f798918aacdd412a3d9dbf703bed2e70477454027  dwarfs-0.15.10.tar.xz
      4e6ce735114009a09e759ff440ea615a14f714e4cad02de49862fd01e7d478e5  dwarfs-0.15.10-Windows-AMD64.7z
      d0d8b00c4dc0087eeb6486cb6ef6bba54e4c21a491c3c04fb78da2c8849a4d1e  dwarfs-fuse-extract-0.15.10-Linux-aarch64
      7b6dbdc3edd4ddd31b851798e6d0f08f34c3c540e4ca1f48a3e28bf2c65316bb  dwarfs-fuse-extract-0.15.10-Linux-aarch64.upx
      0ccb8dc7d8a7963f2067d6f2eb0aee6f9a58735e8f1952dc06f725a410d68820  dwarfs-fuse-extract-0.15.10-Linux-arm
      e157119bf7d6561c782b5b3741d9079785bc4fc20ea7343019f1721d6066ad8d  dwarfs-fuse-extract-0.15.10-Linux-arm.upx
      b6a6973d17bb41c4b7afc7f4d44b0547a009b7cbb9ebed1020967b073354bffc  dwarfs-fuse-extract-0.15.10-Linux-i386
      84a1ff519bf5925af1b0cc33b1eae4b90347e4130fd5786369927114f268b506  dwarfs-fuse-extract-0.15.10-Linux-i386.upx
      099beea47b90f101f19cd012c12737251d5b90e1d5460244db61eda6eb3d7029  dwarfs-fuse-extract-0.15.10-Linux-loongarch64
      6fcff7623427b1a4f3197c6ce08d915af87596b861015b14b070c62e08ace4a7  dwarfs-fuse-extract-0.15.10-Linux-ppc64
      eae74c7f1837db727a52ba2bc984f3ff74ce922738c1e4192f6c6395ac5e10e9  dwarfs-fuse-extract-0.15.10-Linux-ppc64le
      062a6ab7802791e43ef08bba84cebabdaf3a4b727f59f92c6c7aabc30b2812fb  dwarfs-fuse-extract-0.15.10-Linux-riscv64
      3500cfb6e4e3e3f32fab962ab3c767a7628b71bf5babb32e4334ae1f833bfe40  dwarfs-fuse-extract-0.15.10-Linux-riscv64.upx
      5d81fd29da9040b181fc875ea7c24f97ca8f1722367765afac5819da77c2bd1e  dwarfs-fuse-extract-0.15.10-Linux-s390x
      0e4f6f7c5a8f873fc0046822b155d9a74b581c337da39ae76e2f4757d641f890  dwarfs-fuse-extract-0.15.10-Linux-x86_64
      b153f6ec4bc568b2acb1d9b2b3f6004c51bdf8cc6b1ee8c8d856bc5e59e6d274  dwarfs-fuse-extract-0.15.10-Linux-x86_64.upx
      97245a3504891b6e54a2f91fea76885d446098e6dd084b32a094425d024a1234  dwarfs-universal-0.15.10-Linux-aarch64
      439ed996bd3d47678c18d1bb66f1e7f79f40cedd04ed0c9f10d72e23c376e6e4  dwarfs-universal-0.15.10-Linux-aarch64.upx
      1bbbf96db095f61d153fe5a483a6522d370733f01f05f70ae3cc5954bab66c1a  dwarfs-universal-0.15.10-Linux-arm
      5d6b48317d466b182f8c972cefc30e0177002f09d0bfbb1767114b11fdc7bb96  dwarfs-universal-0.15.10-Linux-arm.upx
      59e9f2d9c66e012c76582616da85c301cf5181c77681805b289ea244b91cc316  dwarfs-universal-0.15.10-Linux-i386
      22616e1a4f78ff32853c1f07f5704e4fbfd64ac3daff8a36960cb2e7d3b66fa6  dwarfs-universal-0.15.10-Linux-i386.upx
      a33e6da699d9b2f692e5b50581be6744c4eee8149bbf7b60f57468006ce01f33  dwarfs-universal-0.15.10-Linux-loongarch64
      98dbc66aa5c998c8e0f8f3b0fdd573a332546c3f99393b52a4223ed4a773a71d  dwarfs-universal-0.15.10-Linux-ppc64
      db8fd1dc775b8f9ff4a1437748e845716a33168957ea2d89746eac5dda1495a4  dwarfs-universal-0.15.10-Linux-ppc64le
      645bc1ebfdc4ab9e4b803d387623569246749d7e347022939f087ccb71d6441b  dwarfs-universal-0.15.10-Linux-riscv64
      fa92dbe85cdb98e366c3e92ba823d632bc0f6bcea954e6233305a0f981a57660  dwarfs-universal-0.15.10-Linux-riscv64.upx
      2e4471ac24edd04ac2af83c82953cf5c690204e78aa8e7d74988820584ce0f96  dwarfs-universal-0.15.10-Linux-s390x
      197ca64cd0e6d3a84b76991bdf237d24aaeaee148821a27743b39e10e7c57c1a  dwarfs-universal-0.15.10-Linux-x86_64
      9d0c8118d9ffaa76622e63b2b9ca672f50ffec2187ba92fddd6399de290a3793  dwarfs-universal-0.15.10-Linux-x86_64.upx
      23786164f5e71e6ef00098baa5eeb6a2146413501e45138f12f65b8390a6b53f  dwarfs-universal-0.15.10-Windows-AMD64.exe
      91ff7f8da0d0433b5969822be36b8a45c37b0f74fdad960c010accc515a15f6e  dwarfs-universal-small-0.15.10-Linux-aarch64
      a8f7340def363d3e3aadb66f12dccc3549ef2d8e558a87418e5c29896003265e  dwarfs-universal-small-0.15.10-Linux-aarch64.upx
      11bb0058e911ccc4046e33d3df57a83be4fb3e914fa93ef5fe6be398a8d32df9  dwarfs-universal-small-0.15.10-Linux-arm
      5621ee0afdc2093868c4941e0a7c22b0514238679c2ff94a4a3ed12f8cfaf2e7  dwarfs-universal-small-0.15.10-Linux-arm.upx
      3ddf7c919d50c34308602c0a52910dff667637a0472d8138b0e7f6ff74c92711  dwarfs-universal-small-0.15.10-Linux-i386
      b555ef5a29cfb084f060c183df5b79f141df818a63fc63f72b3b4c4bd4925c19  dwarfs-universal-small-0.15.10-Linux-i386.upx
      b2605eb1ce4ebbeae08f25d602bc63defb611d3d877dcec14480c6f75be44345  dwarfs-universal-small-0.15.10-Linux-loongarch64
      31eafb8ab87da9d7f46c721cc86a04e4f4bec3c51fc3fd8a337eb0dd3f422b72  dwarfs-universal-small-0.15.10-Linux-ppc64
      366ebeecfd64d2bcc4da83a01b21643d3e74e460f7996418a1d056cf327ac19c  dwarfs-universal-small-0.15.10-Linux-ppc64le
      fc6c2e7caec2f759c7ab711e9e7ebf22ca98685b433334dba5c33ca8db3714a9  dwarfs-universal-small-0.15.10-Linux-riscv64
      4cd007a7bd440582c5509e80ce60501ba9d94b2de05a6e932cf349674e13605a  dwarfs-universal-small-0.15.10-Linux-riscv64.upx
      8ffc08f2bc63e48992b8d4197295c292a5bd95f5c39ea451d3e0e7e5d2dfc746  dwarfs-universal-small-0.15.10-Linux-s390x
      c68ace6ad391a420044803967f9d845e74d7201d5273c001194dcecbb803dfd9  dwarfs-universal-small-0.15.10-Linux-x86_64
      d5177b2cb688c1b59bac9d13396d40f87d18b41d1ea63f70b2737332fde0ba79  dwarfs-universal-small-0.15.10-Linux-x86_64.upx
      
    3. 🔗 mhx/dwarfs dwarfs-0.15.9 release

      Bug fixes

      • Always join I/O thread in filesystem_extractor, even when archive_write_close() causes close() to throw. This caused some of the tests to fail when building against libarchive-3.8.10 or later. Thanks to @tijove for the pull request to fix this.

      • (fix) While v0.15.8 fixed an issue where the total_hardlink_size was computed incorrectly, it introduced an accidentally quadratic complexity algorithm while doing so. This was only noticeable with a large number of duplicate files, but it could cause a significant slowdown when building or re-building metadata.

      • (fix) Correctly update segmenter progress context for sparse holes. Without --no-sparse-files, the segmenter progress context would not count the size of sparse holes, which would cause the progress to be reported incorrectly and finish below 100%. This is purely a cosmetic issue with no functional impact, but the fix was trivial.

      Full Changelog : v0.15.8...v0.15.9

      SHA-256 Checksums

      6972df6800537242160d1b33ad86b0967373093751f0e468bc0f13041ca3ab9d  dwarfs-0.15.9-Linux-aarch64.tar.xz
      968172828b1ac9060d7745d1ee0e9987615d9abbf0fd1859daeee9e1501dcf9c  dwarfs-0.15.9-Linux-arm.tar.xz
      d4ef2f24b2bf13b51e8a37f9773a1fe174312f3672da506cbed49f66c0e260e7  dwarfs-0.15.9-Linux-i386.tar.xz
      25fa7b6b93db69e5ea718412bc2c7786868c724b812ce1a34fce7d4503e95718  dwarfs-0.15.9-Linux-loongarch64.tar.xz
      0ad6d778c141874f481d3e07d364f8d3ce8b5f3c8dccdb4bd7d92ac26de6b872  dwarfs-0.15.9-Linux-ppc64le.tar.xz
      75b1d6ecaa088c18496e6ad1a5ec556e43bf5291ccfaf678ba10528219e675c5  dwarfs-0.15.9-Linux-ppc64.tar.xz
      370b3a9a26ec2762c471c69ea87b9b6e5f693b32a41475bc30834402882121cf  dwarfs-0.15.9-Linux-riscv64.tar.xz
      ac63d8c913378f6f3a3b409976494c134371998758dfe08ebfa1ffe373f103ba  dwarfs-0.15.9-Linux-s390x.tar.xz
      342f312c627b19a170ae4488db890a4f515086c270fe164281f2346327e89e5b  dwarfs-0.15.9-Linux-x86_64.tar.xz
      a2eaafa6265b266d06ae36c7898d0cd40ddd44468e5d9e9f76da568cabd7c1f5  dwarfs-0.15.9.tar.xz
      cc888ef55da9f8af5f4aa7c73243b23e8da8d8a1bd194dcc20f5d2aac6ae5ec1  dwarfs-0.15.9-Windows-AMD64.7z
      0442f6ee647329bb5d20aaf0a0572173f6467839f13a4f4afaa0317a792c47d6  dwarfs-fuse-extract-0.15.9-Linux-aarch64
      3c87bbef4f0ea516580c1527d497cc91a27a53ee1576dd45062157dde5063f5d  dwarfs-fuse-extract-0.15.9-Linux-aarch64.upx
      05a1fe18896ea68849e1e05522c7a96ea7ee48b9d9a74b0f34b8aa7fedaab08f  dwarfs-fuse-extract-0.15.9-Linux-arm
      82eb782e00b22bf1104500d2546cc287476ec0030fb5edae24e8f3683bbb5c89  dwarfs-fuse-extract-0.15.9-Linux-arm.upx
      8de52a248ce0e8101f57e9b3adc2f472dc9be921aaaf0b045c8b723081a19417  dwarfs-fuse-extract-0.15.9-Linux-i386
      bc4bfad80fbe6661374fd249433dd019bbdb06188451315e226c985511dcdf45  dwarfs-fuse-extract-0.15.9-Linux-i386.upx
      72c9bafe6b3a527be86df1111b66a6f26344d9425aed83cbc23ace1753a9cd67  dwarfs-fuse-extract-0.15.9-Linux-loongarch64
      5c1e002237214e6f554e5c82739cec5e91d0c4beb2e9e3a78d6c98f7403bd4f0  dwarfs-fuse-extract-0.15.9-Linux-ppc64
      fa788c5462b3c328f20652d8cd64c798095e817198fe5a3d3e1b9e037c136172  dwarfs-fuse-extract-0.15.9-Linux-ppc64le
      098bfc11a50fe967ee1c12e461a5b822f718b52df245dcd4ea3f2f09a3b1c1d3  dwarfs-fuse-extract-0.15.9-Linux-riscv64
      7c3d1f45fc699e8cd60534b113ecd079b11bc11087739e8a805d6c771b4b4274  dwarfs-fuse-extract-0.15.9-Linux-riscv64.upx
      6e07133b51a52c39cd6278b4c4e4f590a3962a80416dd13f908cbf9a37003c92  dwarfs-fuse-extract-0.15.9-Linux-s390x
      c610d96c9929742b6cb08fdeaaf19ef82fc0b34a7b90f52c2075902d4483ce8d  dwarfs-fuse-extract-0.15.9-Linux-x86_64
      ad9cac436004eaa2d3ba58c439585fb468ebbdc372df7afd6fea63df042d6307  dwarfs-fuse-extract-0.15.9-Linux-x86_64.upx
      4295d097ce79b38bff7748659ad2f7c4fbe5d022710bbba70bc12a727e0f55e9  dwarfs-universal-0.15.9-Linux-aarch64
      e6a6a8444928c6833217b7382de261e688f23fc775bed70576b80029bfd995bc  dwarfs-universal-0.15.9-Linux-aarch64.upx
      754a507de0517518fdc8f5f928c33580686491d2030fa7130cd499259e8fbba2  dwarfs-universal-0.15.9-Linux-arm
      4b8a341b4533830fa03d7ef3ef24dd15e3a2e7903449db287d73c7b2e244f410  dwarfs-universal-0.15.9-Linux-arm.upx
      b73f5e99e4b9e1dedce44b2ea52b1a7df139ae93e167a9dd8e4fa050bd8649fe  dwarfs-universal-0.15.9-Linux-i386
      053e16d7c81b22d0bdb521c0e281a51e019f79fe73f52685511cfacc092db6ae  dwarfs-universal-0.15.9-Linux-i386.upx
      d1715794e5a508d66e08ced570bccb75af9b9da02b61eb52955b0a548db99b5a  dwarfs-universal-0.15.9-Linux-loongarch64
      4a858b8bb85853872e9e29d450a44219e63a05f80b22cdb74086754c2818c627  dwarfs-universal-0.15.9-Linux-ppc64
      bed0c276582ac897a4910ca06fef0f2ce174ac51d3e3a1ccdbcf939d2e02096c  dwarfs-universal-0.15.9-Linux-ppc64le
      6f78c5f50627c7610277ce6fe1ad0456be41deb6d8be955bc8c926fa5834b04e  dwarfs-universal-0.15.9-Linux-riscv64
      1c72b574597de3da008f802417d6771b6dce7ed256c18191832f8e4fff61a3f3  dwarfs-universal-0.15.9-Linux-riscv64.upx
      6e076c28a3bdd7fec40d2aceaf4d0dab099eccedc018f4bdb93e3c58426b6d40  dwarfs-universal-0.15.9-Linux-s390x
      ab758405ffc91d2ddb313f81efe9ceaf70481a294a5e0390ef932a44b4db9e94  dwarfs-universal-0.15.9-Linux-x86_64
      18158bfac8b2418ffdc68ac6064a3b8358e507f2ca9ea318b71aaa48a3a83835  dwarfs-universal-0.15.9-Linux-x86_64.upx
      ba20970bab4b385d6c2983556e1f30e82f062935630e791e104294aca09254a3  dwarfs-universal-0.15.9-Windows-AMD64.exe
      4874271244cbd3a3f37faba13341d5d995b2862a3478d39bd6e34ccfde8df067  dwarfs-universal-small-0.15.9-Linux-aarch64
      85beb9472c42c61ed20b8df7daed4c1f1ceb952222d7f3957d141034eba82e97  dwarfs-universal-small-0.15.9-Linux-aarch64.upx
      4a248528b8e5cd263d02a09836fcc3ec678068677a5c82c8613d0b5697feb015  dwarfs-universal-small-0.15.9-Linux-arm
      9a9d8b67346cccfba7326a2f42406d7c55a11c7da1a6abeff038dd3ff448bc4a  dwarfs-universal-small-0.15.9-Linux-arm.upx
      efc40a240a0242412ff98647628be9d34e265df0ac60a09fae2a1b3660c147fb  dwarfs-universal-small-0.15.9-Linux-i386
      5956798d3fb0421e6394d0239d99789fbd6c833c0dc916d3382e12cbc7d6c1b5  dwarfs-universal-small-0.15.9-Linux-i386.upx
      d505776616db3b536b5027196a26760bc0947e3710a23fce12c3cf6386d2623c  dwarfs-universal-small-0.15.9-Linux-loongarch64
      562d0fdd12fbae2f842df8fb13ca04167f755f37c988ff8d9dd954e95c19924d  dwarfs-universal-small-0.15.9-Linux-ppc64
      1ad6053a72baf3aff7491f0c1358d537919dba2ac5cbd67ca86345fcad9f2ce9  dwarfs-universal-small-0.15.9-Linux-ppc64le
      c6168347081549e7792f3af070e178d1fa0c24e1a62e0459eb922283a750f091  dwarfs-universal-small-0.15.9-Linux-riscv64
      d1657bd79aafb2a93d8de292243e3e961b9f8fde754e90f4c45e2c89b257af12  dwarfs-universal-small-0.15.9-Linux-riscv64.upx
      a416d4af4d454d74888484a2701d92c5c54038f521770fedc65558d1a9fe6789  dwarfs-universal-small-0.15.9-Linux-s390x
      972723ad18be9d4a6885f79ce545597240153ef85a7a18ab48fb19218a6d2c92  dwarfs-universal-small-0.15.9-Linux-x86_64
      8bdbca5822f1b9f660cadec19bdfd4375e494ad4bac2ccd806d8c3d8ce4d34b5  dwarfs-universal-small-0.15.9-Linux-x86_64.upx
      
    4. 🔗 smol-machines/smolvm smolvm v1.35.0 release

      Highlights

      • Docker Engine API. smolvm serves the Docker Engine API, with every container running as its own machine. It supports Compose networks, Testcontainers and Dev Containers, image save/load/push/commit, IPv6 networks, and Buildx, which is faster on macOS. (#2172, #2178, #2179, #2181, #2183)
      • --auto-ports publishes the ports a machine starts listening on. (#2172)
      • Mac → cloud restore fixed. A checkpoint captured on macOS now restores on Linux hosts, including the agent rootfs digest, packed images and the virtio-fs file state. (#2162, #2163, libkrun #238, #239)
      • Branch checkpoints no longer fill the source's RAM. (#2174, libkrun #241)
      • Concurrent RAM captures reserve tmpfs, and serve cleans up abandoned checkpoint scratch when it starts. (#2173)
      • Supplementary groups are kept on execs into branched and restored machines. (#2004, fixes #2075)
      • Credential hosts: injected values are scrubbed from responses. (#2180)
      • machine update can set and remove labels in any machine state. (#2143)

      Behavior changes

      • In image machines, PID 1 (smolvm's keep-alive init) now runs as root. The workload, every exec, shells and upload ownership still use the image's USER and its /etc/group groups. (#2004)
      • A CLI start or branch of a machine with supplied-only credentials and no external interceptor now errors. Before, it intercepted silently with no value. A CLI restore with a matching --credential re-authorizes the checkpoint's bindings. The embedded and serve paths are unchanged. (#2182)
      • The Docker Engine API is opt-in. Installing or upgrading never runs smolvm engine; run it yourself to point docker at smolvm (it selects the smol Docker context). (#2186)
      • Credential-host requests are sent with Accept-Encoding: identity and without Range. A response in an encoding other than gzip or deflate is answered with a 502. (#2180)

      What's Changed

      • docs: say that virtiofs DAX is off on arm64 hosts and SMOLVM_MOUNT_DAX does nothing there by @BinSquare in #2087
      • Add smolvm docker: one command starts a Docker engine in a managed machine and points docker at it by @BinSquare in #2089
      • Share the home directory with the smolvm docker machine at the same path by @BinSquare in #2090
      • Resolve host.docker.internal to the host from smolvm docker containers by @BinSquare in #2091
      • Fix a port race in the leader-exit test by @BinSquare in #2096
      • Remove smolvm docker by @BinSquare in #2095
      • Hand supplied credential values to a running embedded machine at once by @BinSquare in #2097
      • Pin libkrunfw with UDP kept inside a TSI guest, and test it by @BinSquare in #2099
      • Publish ports below 1024 on macOS, add IPv6 loopback to live-forwarded ports, and lift the 64-mapping cap by @BinSquare in #2092
      • Return idle guest memory to the host within two minutes and cap new machines at half the host's RAM by @BinSquare in #2094
      • Install a root-owned agent-rootfs when root runs install.sh by @rdslw in #2082
      • Announce a changed file to the guest once per change by @BinSquare in #2102
      • Answer guest DNS from a host cache that coalesces bursts and resends lost queries by @BinSquare in #2098
      • Keep every disk chain under the branch depth limit: fold restored checkpoint layers and frozen-source chains by @BinSquare in #2103
      • Exec sessions: commands the node owns, resumable after a dropped connection by @BinSquare in #2101
      • Let a guest hold tens of thousands of connections on virtio-net and free their host sockets promptly by @BinSquare in #2104
      • Scope the usage journal to the test's own thread by @BinSquare in #2106
      • Pin libkrun 526be460 and libkrunfw f290c62b, rebuilt for every platform by @BinSquare in #2109
      • Build the agent rootfs as non-root on hosts with user namespaces again by @BinSquare in #2107
      • Answer a start missing the mediated interceptor with 400, not 500 by @BinSquare in #2108
      • Run tests that need a released file lock free at once in their own process by @BinSquare in #2110
      • Pin libkrun 9df62257 and libkrunfw 7f4d4950, rebuilt for every platform by @BinSquare in #2113
      • Stop resetting virtio-net connections a server closes first by @BinSquare in #2118
      • Upgrade rusqlite to 0.41 for the patched bundled SQLite (RUSTSEC-2026-0459) by @BinSquare in #2128
      • Keep a host memory reserve VMs cannot take and charge branch children for growth by @BinSquare in #2127
      • Ask before stopping a machine on delete, so a refused or declined delete leaves it running by @connorburgess in #2131
      • Prepare SmolVM v1.34.1 for release by @BinSquare in #2135
      • Bring a soft open-file limit above kern.maxfilesperproc down to the cap on macOS, so the limit raise_nofile_limit reports is the one in force by @connorburgess in #2132
      • Leave no data directory behind when exec, status or stop name a machine that does not exist by @connorburgess in #2129
      • Warn when --block-private keeps a named host unreachable by @BinSquare in #2146
      • Register Rosetta itself as the x86_64 interpreter when the host answers its start-up ioctl by @BinSquare in #2148
      • Make a mounted host directory belong to the workload user so a non-root workload can write to it by @BinSquare in #2149
      • Record the image platform on the machine so a Rosetta machine can be created from an amd64 image by @BinSquare in #2147
      • Bump libkrun so a Rosetta machine runs amd64 programs directly and a macOS machine stops promptly by @BinSquare in #2150
      • Keep a cache disk's chain on its shared base when compaction shortens it by @BinSquare in #2145
      • Satisfy Rust 1.100's needless_bool lint in connect_in_progress on Windows by @BinSquare in #2154
      • Bound branch admission and reported capacity by the VM slice's memory limit, not just host free memory by @BinSquare in #2152
      • Stop throttling the VM slice and reclaim it from the pressure guard instead by @BinSquare in #2153
      • Release a paused branch child's VM lock so the memory pressure guard can resume it by @BinSquare in #2157
      • Keep a restored machine's local image on its storage disk instead of mounting the capturing host's archive by @BinSquare in #2163
      • Update quinn-udp to 0.5.16 for RUSTSEC-2026-0538 by @BinSquare in #2165
      • Count every symlink with one mode in the agent rootfs digest so a Mac checkpoint restores on Linux by @BinSquare in #2162
      • Carry guest traffic in 64 KB frames over the gateway link so downloads use a quarter of the CPU by @BinSquare in #2168
      • Pin libkrun 518949b4 and libkrunfw 0fae3853, rebuilt for every platform by @BinSquare in #2169
      • Reserve tmpfs for concurrent RAM captures and sweep abandoned checkpoint scratch at serve start by @BinSquare in #2173
      • Let a packed image's branch take the deferred checkpoint save and say when the VM died mid-save by @BinSquare in #2174
      • Integrate and validate Docker Engine, automatic ports, and nested Rosetta support by @BinSquare in #2172
      • Run x86_64 images in containers Docker starts inside a Rosetta machine, keeping their PID by @BinSquare in #2093
      • Serve the Docker Engine API from smolvm, every container a machine by @BinSquare in #2114
      • Publish the ports a machine starts listening on, with --auto-ports by @BinSquare in #2136
      • Give engine containers user-defined networks, so Docker Compose stacks run by @BinSquare in #2115
      • Let engine containers reach the Docker socket, so Testcontainers and Dev Containers work by @BinSquare in #2116
      • Branch engine containers from a warm base when many of one image run by @BinSquare in #2117
      • Publish engine container ports on the address each one names by @BinSquare in #2119
      • Give engine containers a volume for each VOLUME their image declares by @BinSquare in #2120
      • Move images in and out of the engine: save, load, push, commit, import, export by @BinSquare in #2121
      • Run --network container: containers in that container's machine by @BinSquare in #2122
      • Give engine networks IPv6 by @BinSquare in #2123
      • Run the Docker API on demand with independent workload supervisors by @BinSquare in #2175
      • Fix Buildx volume permissions and macOS restart stalls by @BinSquare in #2178
      • Improve default macOS shared-volume write performance by @BinSquare in #2179
      • engine: speed up macOS Buildx with automatic overlayfs snapshots by @BinSquare in #2181
      • Run the guest keep-alive init as root while workloads and execs keep the image user and its supplementary groups. by @BinSquare in #2004
      • engine: fix multi-stage Buildx builds containing deleted files by @BinSquare in #2183
      • Scrub injected credential values from what a credential host sends back by @BinSquare in #2180
      • Re-authorize a restored checkpoint's credential bindings from the CLI, and refuse a start that could not inject them by @BinSquare in #2182
      • Sweep a deleted machine's pause-operation lock along with its fork-operation lock by @connorburgess in #2184
      • Let machine update set and remove labels, in any machine state by @josmo in #2143

      New Contributors

      Full Changelog : v1.34.0...v1.35.0

    5. 🔗 Luke Muehlhauser Composing classical music with AI agents rss

      For 20 years I've wanted to compose contemporary classical music, but I never had the skill or time to do so. Thanks to AI, now I can!

      Some of my favorites pieces I've composed with AI so far are:

      1. hey claude write me a symphony thx (written entirely from only that phrase): a Romantic minimalist symphony inspired by Philip Glass and John Adams
      2. hey claude write me an oboe concerto thx (same): a Romantic oboe concerto with beautiful melodies
      3. "Duck-Rabbit": a never-changing Banjo riff sounds different every few measures due to auditory illusions created by the orchestra playing around it
      4. "De Natura": a dark, driving orchestral piece inspired by prog-rock band Magma
      5. "Pen Pals to Lovers": an American banjo and Japanese koto send each other "letters," gradually learn the other's language, trade ideas more quickly in person, then fall in love and play together
      6. "Castells": a musical representation of building a Catalonian "castell" — a tower made of people standing atop one another
      7. Floating Dreams: a pastoral slow-building orchestral piece inspired by a track by Pat Metheny & Lyle Mays
      8. Homage to The Necks: an homage to five long minimalist grooves by the jazz trio The Necks
      9. "Opus 2": a meditative James Syler theme transformed into an epic mini-symphony for large orchestra and choir
      10. "Squall": inspired by Godspeed You! Black Emperor's "Storm," but with an orchestra, and the end is a cello concerto

      My process is simple: I describe the piece I want to the AI (e.g. Claude or ChatGPT), it writes the first draft composition in a notation format called MusicXML, I open that in MuseScore Studio (free) to see the sheet music and play it back with virtual instruments, and then I either ask AI to make adjustments and then import & listen again, or I export the piece to MP3 and ask AI to make a "scrolling score" video I can upload to YouTube. Every piece above was composed with 10 or fewer prompts.

      Claude (the AI) is so good at composing that, by the measure of "how many hours of music by this artist do I strongly enjoy listening to?", Claude is already my 32nd favorite musical artist across all genres, from just one month of output alone1

      The pieces would sound even better if I spent more time "producing" the music in a digital audio workstation (DAW) like Reaper (which AI can also do for you), and if I paid for higher-quality virtual instruments (e.g. Vienna Performer).2

      In addition to bringing your own compositional ideas to life, AI can also give new life to works that would otherwise remain unheard. For example, AI can:

      You'll often get pretty fun (and sometimes good) results just by trying things like "please write me a 4-movement symphony in MusicXML; my favorite composers are [A, B, and C]." But if you want to invest more time for better results, here are some tips from my experience so far:

      • If the AI's first attempt at your compositional idea isn't very close to something you want, it's typically better to try again with an updated prompt in a new session, rather than trying to massage the bad first draft closer to what you want.
      • In a text file in your working folder, give AI context on your classical music preferences. List favorite composers, point to Spotify playlists, etc. The more detail you've got on specific compositions you've liked vs. disliked, or specific styles you like vs. don't, the better it'll do at composing music you like. (But in some cases you may want the AI to ignore your preferences file, if you're composing for other purposes.)
      • To stimulate or amplify your creativity, ask AI for composition ideas meeting certain criteria, or ask it for potential improvements to your own ideas, before you have it write the piece. Items 3, 5, and 6 above are all based off ideas AI came up with.
      • Have AI "sketch" ideas for you to give feedback on before it writes an entire piece or movement, especially a large complicated piece with many parts. For example, you might say "Write me a MusicXML file with 20 different melodies with [some properties] played on piano solo, then I'll tell you what my favorites are, and you can use those as the main themes of the piece." Or "Write me a MusicXML file with 20 different kinds of polymeter played on congas and drumset, and I'll tell you which grooves I like best."
      • Build and maintain composition-related skill files. (A skill file is just a text file with instructions on how the AI should do a particular thing.) For example, I maintain skill files on (a) how to write MusicXML files that will play correctly in MuseScore, and (b) how to achieve various orchestration effects/sounds.
        • You don't need to write these yourself; you can just say "Please write a skill file on how to write MusicXML files that will be 'performed' well when imported into MuseScore" or "Please read as much as you can find online about skillful orchestration and how to achieve different kinds of orchestral effects and sound profiles, and write your findings to a skill file." And then after each composition session, say "Please update the MusicXML skill and the orchestration skill based on what you learned during this composing session."
        • E.g. AI added things like this to my MusicXML skill file: "Generate with a script, never hand-typed XML" and "MusicXML can't set MS4's beam groups. MS4 4.7.5 beams 7/8 as 3+2+2." (I don't even know what beam groups are.)
      • Consider asking AI to do extensive research before you compose a piece. E.g. for Far-Flung Work Songs, I asked AI to gather as many fully-transcribed "work songs" from folk music traditions around the world as it could find, and keep them in a unified catalogue. It kept a log of sources it couldn't automatically acquire, some of which I could download en masse via a script it wrote, others of which I could choose to acquire manually for it. After the AI had assembled many thousands of work songs from dozens of folk traditions around the world, I asked it to create a simple MIDI file (from the ethnomusicologist's transcription) for each of 50 of the songs from the catalogue that it thought I would find the "most catchy." I then listened to the basic melodies and rhythms of those 50, picked my seven favorites, and asked AI to write orchestrations of them.
      • In general, if you're stuck wondering "Can the AI do X?" or "What questions am I not thinking to ask?" or "Where are skill files stored?" or "How can I make this process simpler for me?" or whatever… Just ask the AI!

      • My favorites are listed here. Of course, Claude has the advantage of composing based on my own desires, and of being able to write music vastly faster than any human can.

      • I have purchased the MuseSounds Pro package already, which gets you lots of instruments for a low price.
      • I haven't done this myself yet, but for an already-existing score, an AI can be used to (a) transfer a written score into a notation format like MusicXML, and (b) improve the details of that MusicXML file for ideal performance by a program like MuseScore.
  3. November 13, 2026
    1. 🔗 IDA Plugin Updates IDA Plugin Updates on 2026-11-13 rss

      IDA Plugin Updates on 2026-11-13

      New Releases:

      Activity:

      • augur
        • f4c64e5a: Merge pull request #18 from 0xdea/dependabot/github_actions/actions-d…
        • 3baa977d: ci: bump the actions-dependencies group with 3 updates
        • 014ee69d: docs: add article to readme
      • haruspex
        • fb5faac8: Merge pull request #22 from 0xdea/dependabot/github_actions/actions-d…
        • 8ef68074: ci: bump the actions-dependencies group with 3 updates
        • 1c9f4f1b: docs: add article to readme
      • IDAPluginList
        • cc429fe6: chore: Auto update IDA plugins (Updated: 19, Cloned: 0, Failed: 0)
      • plugin-ida
        • 7611e42e: fix: declare idaVersions as a range so IDA 9.5 resolves (#39)
      • rhabdomancer
        • c74dc412: docs: add article to readme
        • 2fba38ae: Merge pull request #22 from 0xdea/dependabot/github_actions/actions-d…
        • 762a7385: ci: bump the actions-dependencies group with 3 updates
    2. 🔗 HexRaysSA/plugin-repository commits sync repo: +1 plugin, +5 releases, -1 release rss
      sync repo: +1 plugin, +5 releases, -1 release
      
      ## New plugins
      - [ida-mcp-bridge](https://github.com/eitapreulajhol/ida_mcp) (0.3.0)
      
      ## New releases
      - [btf2ida](https://github.com/nightshift-labs-ai/btf2ida): 0.1.20
      - [cfiscope](https://github.com/nightshift-labs-ai/cfiscope): 0.1.18
      - [memlens](https://github.com/nightshift-labs-ai/memlens): 0.3.25
      - [threatray](https://github.com/threatray/plugin-ida): 3.0.5
      
      ## Changes
      - [memlens](https://github.com/nightshift-labs-ai/memlens):
        - removed version(s): 0.3.0
      
    3. 🔗 anthropics/claude-code v2.1.325 release

      What's changed

      • Fixed a security issue in how zstd-compressed responses are decoded
      • Added a spinner tip in VS Code and similar integrated terminals about re-running a notebook cell, shown once Claude has read or edited a Jupyter notebook
      • Added a line under the error shown when your organization's policy blocks a request, saying how to continue: run /rewind and change the message, or run /clear
      • Added a note for Claude when a sandboxed git checkout, git stash or autostash pull cannot update protected files such as those in .claude
      • Fixed /security-review and skills' inline git commands stopping with an error in worktrees of bare repositories, --separate-git-dir checkouts and Android repo checkouts
      • Fixed subagents with their own model being moved to the plan-mode model when the model setting is opusplan or haiku
      • Fixed subagents on a different model sizing file reads and MCP results with the main session's model
      • Fixed sessions on many third-party gateways and Foundry stopping with a context length error on every turn instead of compacting
      • Fixed recent turns sometimes going missing from a resumed session after Claude Code stopped without a clean exit
      • Fixed shell commands running in the launch directory after the working directory was deleted; the command now fails with a message and can be re-issued
      • Fixed an approved plan edit being lost when the plansDirectory folder can't take it: the plan is now saved in the default plans folder, and a warning says where and why
      • Fixed a saved sonnet[1m] model setting being rewritten on a new install to a model id the API rejects
      • Fixed focus view hiding the reply to your prompt when a scheduled task replied after it
      • Fixed the prompt sometimes missing from a background subagent's view when fullscreen is off
      • Fixed long options in lists and permission prompts being partly overwritten when they wrap, and first-run screens losing lines on narrow terminals
      • Fixed startup warnings about permission rules and the "N MCP servers need authentication" notice being recorded as seen when they were scrolled out of view
      • Fixed the welcome header showing control characters or splitting across lines when an agent's name or the working folder contains them or a line break
      • Fixed the red error shown when Claude tries a command only you can run: a dim line now says it runs only when you type it at the prompt
      • Fixed /stats showing an Active days total that was one day too high
      • Fixed /insights saying a report was ready when no session qualified for analysis, and writing two values into its HTML report without escaping them
      • Fixed /voice saying voice mode changed when managed settings, --settings, or the project's .claude/settings.json or .claude/settings.local.json kept it as it was; it now says what holds it
      • Fixed the IDE welcome dialog showing Cmd+Esc for Quick Launch on Windows and Linux
      • Fixed Slack app tips showing when your organization's policy denies cloud sessions
      • Fixed claude purge hanging silently when there is no terminal to read keys from, and its project picker and -i prompts ignoring the keyboard when stdin is piped
      • Fixed claude plugin eval --output-dir '' writing the report into the current folder; it now exits with an error
      • Fixed claude -p text output on a terminal passing control sequences other than text styling; pipes and files are unchanged
      • Fixed leftover .oauth_refresh.lock.owner.tmp.* files piling up in the config directory
      • Fixed /fast saying "Fast mode has been disabled by your organization" under the keyless Console sign-in, where Claude Code had not asked the server
      • Fixed /model saying that your organization restricts a model when Claude Code could not check that, for example with no network
      • Fixed "Sign in with your Console account" in /login replacing your existing login when you pressed Esc right after the browser step
      • Fixed the browser showing the sign-in success page in some cases where sign-in failed or was canceled
      • Fixed claude auth status and other short commands leaving a lock behind on a Console profile, which made the next session hang for about a minute
      • Fixed background sessions started on your claude.ai login using (and billing) an API key or token from the shell that started the background service
      • Fixed more cases of a session moving to another sign-in in the background; these moves are now refused, with a message saying what works
      • Fixed a second Enter in the exit dialog stopping background work after the move to the background was refused
      • Fixed token counting on Amazon Bedrock sending the conversation to Bedrock when the allowedProviders managed setting does not allow it
      • Fixed AWS credential_process helpers and Google Cloud default credentials failing when Claude Code is started without a HOME environment variable
      • Fixed a session sometimes going back to an earlier permission mode after a subagent's plan was approved
      • Fixed one invalid value in an Agent SDK applyFlagSettings() call silently discarding all settings from earlier calls; a call that would do this is now refused with an error
      • Fixed sessions showing as waiting for input when a finished pull request only needed your own review or merge
      • Fixed an unrecognized teammateMode settings value being ignored without a warning: claude -p, the startup warning and claude doctor now list it as a skipped entry (still not applied)
      • Fixed --worktree skipping a WorktreeCreate hook from a plugin in CLAUDE_CODE_PLUGIN_SEED_DIR on the first run in a new home directory
      • Fixed brief-mode sessions, such as Dispatch, sending a reply again after the turn had already replied
      • Fixed Claude saying a working Atlassian, Asana or Sentry connector had failed in cloud sessions when a plugin listed it at a different URL
      • Fixed Claude Desktop and SDK sessions listing a folder's own MCP servers (.mcp.json, local) as host-added or not at all, and not connecting WebSocket ones, after a folder move or pre-warmed start
      • Fixed /mcp still listing a plugin's MCP server after a plugin reload removed it while it was connecting
      • Fixed an MCP server staying "needs authentication", and its mcp_tool hooks being skipped, after a token refresh that was refused only for a moment
      • Fixed MCP elicitation requests being cancelled without asking in headless mode after a server's connection was replaced during a tool call
      • Fixed MCP tool calls from an SDK host answering "Not connected" after a tool call had reconnected the MCP server
      • Fixed an MCP task getting stuck after its question was closed with Esc or asked again: the footer now says it needs your input, and Enter in /tasks shows the question again
      • Fixed background MCP tasks that stopped updating after another call to the same server lost the connection, when a later call reconnects
      • Fixed a background MCP task's question opening over a message you were still typing; it now waits until you send or clear the draft, and the spinner and turn timer keep running
      • Fixed worktree.sparsePaths and sparse plugin and marketplace clones leaving out the repository's root files on older git versions, such as 2.34
      • Fixed self-hosted runner sessions with several repositories being unable to use a repository added mid-session
      • Fixed Claude asking for permission before reading your own artifact or its data
      • Fixed deny and ask permission rules and hooks for the Artifact tool not applying in some cloud sessions
      • Fixed Code Mode scripts ignoring a worktree entered with EnterWorktree, writing ~ paths into the project, and leaving /mcp showing an MCP server as connected after its sign-in expired
      • Fixed words typed with a Yes at a permission dialog or plan approval not reaching Claude in Code Mode
      • Fixed Claude starting work by itself when you resumed a session that ended during a Code Mode script; it now waits for your next prompt
      • Fixed a missing OpenTelemetry user_prompt event for a message sent while tool calls run. The event has delivery.mode: "mid_turn" and the running turn's prompt.id
      • Fixed the OpenTelemetry user_prompt event leaving out earlier messages' text when queued messages merged into one turn in VS Code, or when one message had an image
      • Fixed a slash command's allowed-tools grants applying to background agents woken during or after its turn
      • Fixed /feedback and /bug to upload other sessions only when they were recorded by the signed-in account or organization
      • Fixed relative deny and ask permission rules (e.g. Read(./.env)) no longer covering the project after a cd; they now also apply in added directories
      • Fixed deny and ask permission rules starting with mcp__plugin_*_ missing a plugin's MCP server or tool spelled in another letter case
      • Fixed deny rules not being applied to a permission approval that arrives after Claude Code restarts, in self-hosted runner and claude remote-control sessions
      • Fixed a case where a committed .claude/settings.local.json could be treated as the user's own when Claude Code was started in certain subfolders of a repository
      • Fixed some deny and ask rules not applying to certain Bash commands
      • Fixed a gap in Bash permission checks where some compound commands could run without asking; these now ask for permission
      • Fixed a case where a Bash allow rule could run a different program than the one it names
      • Fixed a connector tool's approval prompt in cloud sessions being answered automatically while plugins were still loading
      • Fixed some subagents changing an artifact that people outside your organization can see, or uploading files to it, without asking first when an allow rule is set or uploads were approved earlier
      • Fixed some artifact publishes skipping the confirmation for pages that people outside your organization can see when "don't ask again" had been chosen for Artifact
      • Fixed auto mode judging only the first change to an artifact that people outside your organization can see; its yes now covers that change alone
      • Fixed a managed strictPluginOnlyCustomization lock on agents and skills not taking effect in sessions that were already running
      • Fixed sandboxed commands being able to write to the native updater's download folder in some cases
      • Fixed a case where the Bash sandbox did not fully protect a worktree's settings and hooks
      • Fixed a case where the Bash sandbox did not fully protect a linked worktree's shared git folder
      • Fixed /teleport's stash choice in some unusual git states: it now stops and says what to do
      • Windows: Fixed a start-up stall that could last about a second when a PATH entry sits under a folder your account cannot open
      • Fixed /resume on Windows refusing or hiding sessions whose folder was recorded with a different drive-letter case or slashes
      • Fixed an in-session /resume on Windows dropping a project's saved trust when the session was recorded with a different drive-letter case
      • Linux: Fixed sandboxed Bash commands failing with bwrap: Can't create file when the working directory was below an allowRead folder inside a denyRead, such as under a symlinked home directory
      • Fixed Claude Desktop's third-party deployments staying on "Stopping" until a token renewal finished (once it includes this version)
      • Improved subagents cut off at the output token limit: they are now asked for the whole answer again, more briefly, instead of returning only its end
      • Improved startup with a keyless Console sign-in or other Anthropic profile login: a token that is still valid is read without waiting for the credentials lock
      • Improved the account email check: it now also refuses your email as a client's identity in scripts a command runs, file writes, web fetches and MCP calls
      • Improved the HTTPS authentication failed message for private plugin marketplaces: it now says git's terminal prompts and askpass programs are disabled, and it also appears with newer git versions
      • Improved the add-marketplace confirmations, plugin recommendation prompts and plugin install warning to say that plugins can run code on your computer, with access to your files and shell
      • Improved the claude --desktop sign-in error to name the API key, provider or setting that stops a Claude account sign-in from working
      • Improved the /voice "No audio detected" message on macOS and Windows: it now says where to pick your microphone
      • Improved MCP tasks: Claude is now told when a task is waiting for your answer, and can point you to /tasks
      • Improved claude remote-control: it now exits with status 4 when it stops by itself (single-session runs still exit 0) and 69 when it can't register, so a service manager can start it again
      • Improved the messages shown when a background session can't use its session's API key or token: they no longer suggest adding the key to settings
      • Improved the bundled dataviz skill's part-to-whole advice for static images and for parts with a natural order, such as age bands
      • Changed sandboxed Bash commands to follow the normal permission flow by default; set sandbox.autoAllowBashIfSandboxed: true to keep running them without prompts
      • Changed managed settings that turn the sandbox on: to keep commands running without prompts, set sandbox.autoAllowBashIfSandboxed: true in your highest-ranking managed source
      • Changed read-only git commands to ask first in a repository that isn't the project's or one you trusted; name it with --add-dir, not the additionalDirectories setting, to run them without prompts
      • Changed scheduled tasks and /loop to ask before running a skill that declares allowed-tools or hooks; add Skill(name) to permissions.allow to run it unattended
      • Changed "Always allow" in Desktop, IDE and SDK hosts: a rule alone is offered only when saving it would allow that command again, so a scheduled task that relied on one can now wait for you
      • Changed the sandbox to refuse sandboxed writes to .claude settings, skills, agents, commands and hooks in added directories, as it does in the launch folder
      • Changed worktree isolation: an isolated worktree session or agent is now refused git bisect run, git maintenance register|start and scalar's set-up commands, and is told what still works
      • Changed plugin MCP bundles (.mcpb, .dxt) to unpack under the plugins directory, not .mcpb-cache in the plugin's folder, so read-only plugin folders load; one fetched by URL downloads again once
      • Changed plugins of a remote marketplace that managed settings declare, enable and list in prependPlugins or appendPlugins to count as the organization's; pluginDigests is deprecated and ignored
      • Changed plugin loading to skip, and claude plugin validate to report, some unsafe paths and links in a plugin's folder
      • Changed nested skill loading: .claude/skills folders in --plugin-dir plugins no longer load from a session started above them; start Claude Code in the plugin folder instead
      • Changed EnterWorktree to refuse a WorktreeCreate hook path that goes through a symlink inside the project; have the hook print the real path
      • Changed tmux and iTerm2 teammates, and new sessions from the agents view opened with ←, to start in the session's folder instead of where the shell last ran cd
      • Changed prompt suggestions in the terminal to refresh less often after 8 turns in a row started by background or scheduled tasks, saving usage until you press a key or return to the terminal
      • Changed Esc on a background MCP task's question to "answer later": nothing is sent to the server, and the question stays in /tasks
      • Changed CLAUDE_CODE_MAX_CONTEXT_TOKENS to also set the context window of unrecognized model IDs that start with claude-, such as a gateway's claude-sonnet-latest
      • Changed /login to ask for permission to change your privacy settings
      • Changed /cost, $.session.usage(), --max-budget-usd and the cost and token metrics to count a mod's $.model.complete and $.model.classify calls
      • Changed the programs that Claude Code's sandbox starts for its own use, such as its network bridge, to run without Claude Code's sign-in tokens and API keys in their environment
      • Changed ripgrep, local git commands and the sandbox runtime's own helper programs to run without the mTLS client key's passphrase in their environment
      • Remote Control: Changed /resume and /teleport to disconnect first when the connected session has a share link, or when that can't be checked; run /remote-control to connect again
      • Changed Claude Code on the web, cloud scheduled tasks and Cowork cloud sessions to start despite sandbox.failIfUnavailable: the hosted container has no command sandbox
      • Changed requests for settings, permission rules, hooks or status over a cloud or self-hosted session's connection to return less or be refused; what applies in the session is unchanged
      • Changed claude -p with no cached account data to wait for that data before its first request, so a first run in a clean environment can start a few seconds later
      • Changed Claude's instructions to keep files you'll want out of its temporary scratchpad folder, which can be cleared
      • Changed marketplace ref to accept the full ID of any commit on a branch or tag; clients before this version can't clone such a pin, so a marketplace pinned this way stops loading there
      • Changed plugin marketplace and plugin downloads to use a CONNECT tunnel when ALL_PROXY is the only proxy set; a proxy that refuses CONNECT now fails them
      • Changed -p and SDK runs in a worktree or submodule mounted into a container to apply .claude/settings.local.json allow rules only once the folder is trusted
      • Changed self-hosted runners to refuse a session whose session folder or repository path is a symbolic link, other than a checkout hook's checkout
      • Removed "ask your admin to raise it" from spend limit and shared budget errors in cloud sessions and under Remote Control
      • [VSCode] Added prompt suggestions wherever the terminal shows them: Tab accepts the suggested next prompt; promptSuggestionEnabled: false in Claude Code's settings.json turns them off
      • [VSCode] Added a Console sign-in that creates no API key
      • [VSCode] Added a field to paste the redirect URL when signing in to an MCP server from the panel in SSH, WSL and container windows
      • [VSCode] Fixed the model picker's check mark staying on the old model after Claude Code restarted on another model or the model was switched over Remote Control
      • [VSCode] Fixed the effort selector offering levels above the effort cap set by your organization or the maxEffortLevel setting
      • [VSCode] Fixed the sign-in screen offering sign-ins that the managed allowedProviders setting refuses
      • [VSCode] Fixed the permission prompt for MCP tools not saying why Claude Code asks when a safety check raises the question
      • [VSCode] Fixed the message for organization settings that couldn't load saying to run a command again; it now says to try again, matching the tab's Retry link
      • [VSCode] Improved the note shown for an untrusted folder: it now says why the extension is off and how to turn it on
      • [VSCode] Improved the error shown when the system refuses to run Claude Code: it now says your IT team can allow a blocked program
      • [VSCode] Improved the sign-in card to say what to do when the browser shows a connection error for localhost
      • [VSCode] Changed the install link's marketplace confirmation button to "Trust marketplace and continue"
      • [Claude Code on the web] Fixed new cloud sessions cutting MCP tool descriptions loaded through tool search at 4,096 characters; the limit is now 16,384, as in other Claude Code sessions
      • [Claude Tag] Fixed artifact links pasted in Slack getting no card when the poster's Claude sign-in had expired in a workspace their organization doesn't manage; a plain card now appears
    4. 🔗 backnotprop/plannotator v0.28.64 release

      Follow @plannotator on X for updates

      Missed recent releases? Release | Highlights
      ---|---
      v0.28.63 | Pair Grok Bot and other cloud agents from Settings, Hermes Agent, OpenClaw and Muse Code can use the Inbox, add a thread to Priority to keep it on top, tag threads, and find each tag in the sidebar, Pull requests board as a table, with bulk Merge
      v0.28.62 | Agents started from the Inbox now work on Windows, pick a model and effort when you start an agent, rules for your agents, written in your own words, post a thread's decisions on its pull request, the Inbox loads faster on a slow connection
      v0.28.61 | Updates now update the Claude Code plugin too, an agent's chosen face shows on every icon of it, filter the Inbox list by pull request state, Modern dark shows section bands and the Reply button, one conversation no longer shows as two agents
      v0.28.60 | Click a word to highlight it, a one-time Themes dialog, Settings → Rows rebuilt, tell your agent how you want your rows, starred threads as pills above the list, a pill for new messages out of view, a half-circle face picker with ten Glass colours, a new phone sidebar and reply box
      v0.28.59 | A quieter Agents section in the sidebar, machine names only when agents run on more than one machine, agent icons that are always gently alive and lean toward your pointer
      v0.28.58 | Start Codex from New message, an Agents section in the sidebar, start an agent in a folder on any drive, play audio attachments and comment at a moment, Claude Code's Plannotator tools work on Windows
      v0.28.57 | Pin artifacts, and see every artifact on one page, filter the list by project, date or agent, a thread shows its pull requests and their state, choose what the sidebar shows, and in what order, Ask AI starts from Side in the selection bar
      v0.28.56 | Questions can show trade-offs and a prototype to try, a thread with many big pictures no longer crashes the tab, Escape closes New message and keeps your draft, read threads stop being bold and keep their place, agent messages that name no thread start a new one
      v0.28.55 | Floating reply drafts, now a setting under Experimental, open questions sit next to Reply again, a comment box that keeps unsent comments as Drafts, choose how your list looks: Minimal, Balanced or Detailed, update an older linked machine from this Inbox
      v0.28.53 | Start an agent in a new folder, or from a git URL, "+" on each project row starts a session there, a reaction tray, a thread's Links, Settings → Activity, New message offers the open thread's files, Bro mode: agents write to you in plain words
      v0.28.52 | Start agents from the Inbox, on by default, a new reply box, Ask AI for everyone, Insights in Settings → Decision data, Plannotator reloads itself after an update
      v0.28.51 | Starred threads, a note when an agent's session has ended, "Back from snooze", Ask about a past decision, expand arrows in guided reviews

      What's New in v0.28.64

      TL;DR

      • Changed: Installs and updates download a smaller, compressed copy
      • New: A Videos filter on the Artifacts page
      • Changed: GitLab comments on a whole file get their own thread
      • Off by default: Pull request pictures and videos show in the Inbox

      0.28.64 is a small release. Installs and updates now download a compressed copy of Plannotator, the Artifacts page can show only videos, and a GitLab comment on a whole file posts as its own thread. It has 5 PRs, all from the maintainer.

      Smaller downloads for installs and updates

      Each release now carries compressed copies of the Plannotator binary next to the plain one: a .tar.xz for macOS and Linux, and a .gz for every platform. On macOS (Apple silicon) the download goes from 195.6 MB to 44.9 MB as .tar.xz, or 73.9 MB as .gz.

      The installers try them in order. On macOS, the install script takes the .tar.xz, then the .gz, then the plain file. On Linux it takes the .tar.xz only when xz is installed, and otherwise starts with the .gz. On Windows, both install.ps1 and install.cmd take the .gz, then the plain file. Each copy is unpacked and checked against the same SHA-256 as the plain binary before anything is replaced. If a copy is missing, fails to download or unpack, or does not match, the installer quietly moves on to the next one. Only the plain file can fail the install, with the same messages as before. The installer prints one new line that names the file it used, such as Downloaded plannotator-darwin-arm64.tar.xz.

      In a test on a Mac, with the download limited to 2 MB/s, an update took about 24 s with the .tar.xz, 36 s with the .gz and 94 s with the plain file. Updates from inside Plannotator run the same install script, so they get the smaller download too. Older releases have no compressed copies, so installing one of them downloads the plain file as before. To force the plain download, set PLANNOTATOR_SKIP_COMPRESSED_DOWNLOAD=1.

      #3302

      A Videos filter on the Artifacts page

      The Artifacts page (the Artifacts row in the sidebar) listed videos, but its filters were Images, Pages, Documents and Other files, and every video counted as an image. There was no way to see only the clips. The page now has a Videos filter after Images, and an mp4 or webm sits there instead of under Images. Audio stays under Other files. A thread's own Artifacts grid is unchanged.

      #3304

      GitLab: a comment on a whole file gets its own thread

      On a GitLab merge request, a comment on a whole file used to be folded into the review's main note as **path:** text. It now posts as its own thread on that file, as it already did on GitHub. This works from plannotator review and from the Inbox's Post to GitLab, and was checked on gitlab.com, where each one shows as "started a thread on a file".

      If GitLab refuses a file thread, as an older self-hosted GitLab may, that comment goes into the main note as before, so nothing is lost. If the file threads go and the note then fails, a retry sends only what is left, so no file thread is posted twice.

      #3245

      Code review in the Inbox: off by default

      This shows only with Code review turned on in Settings → Capabilities.

      • A pull request's own pictures and videos. On a PR from github.com, the pictures in its description, comments and line threads now show in place, on the PR page and in a thread's full review. Before, each one was a chip saying it opens on the forge. Screenshots written as <img> tags, such as before and after pairs in a table, show as pictures too. A click, or Enter or Space, opens a picture full screen in the attachment viewer, and a video GitHub saved as a link plays there on a plain click. The Inbox fetches each file through your own gh sign-in, only from GitHub's attachment hosts and only when the PR's text names it. A picture that fails to load stays a chip. GitLab merge requests keep their chips for now. #3165

      Additional Changes

      • Setup pages for each agent. The site has a new page at plannotator.ai/inbox/agents that lists the agents that work with the Inbox and what each one supports, with a setup page per agent: steps to copy, how to check it works, and fixes for common problems. #3183

      Install / Update

      macOS / Linux:

      curl -fsSL https://plannotator.ai/install.sh | bash
      

      Windows:

      irm https://plannotator.ai/install.ps1 | iex
      

      Claude Code Plugin: The install script above also updates the plugin when claude is on your PATH. Otherwise, in a terminal:

      claude plugin marketplace update plannotator
      claude plugin update plannotator@plannotator --scope user
      

      Then restart Claude Code. Inside Claude Code, run /plugin marketplace update plannotator, then open /plugin → Installed → plannotator → Update now.

      Pi:

      pi update npm:@plannotator/pi-extension
      

      OpenCode: Re-run the install script above. It also clears the OpenCode 2 plugin cache.

      What's Changed

      • Marketing: pages for each agent and what works with the Inbox by @backnotprop in #3183
      • Inbox: a PR's own pictures show in its text and open in the viewer by @backnotprop in #3165
      • Inbox Artifacts page: a Videos filter by @backnotprop in #3304
      • GitLab: a comment on a whole file becomes its own file thread by @backnotprop in #3245
      • Installers download a compressed copy of the binary when the release has one by @backnotprop in #3302

      Full Changelog : v0.28.63...v0.28.64

    5. 🔗 HexRaysSA/plugin-repository commits sync repo: +1 release rss
      sync repo: +1 release
      
      ## New releases
      - [kflow](https://github.com/nightshift-labs-ai/kflow): 0.0.2
      
    6. 🔗 Anton Zhiyanov Probabilistic data structures in Go rss

      Probabilistic data structures give you approximate answers to questions about the data they handle. Does the set contain a certain item? How many unique items are in the collection? Which items appear most often? Unlike deterministic structures like sets and frequency tables, the answers might not be exact, but in return, you can drastically reduce memory usage.

      In this post, we'll talk about what probabilistic structures are, how they work, and what kinds of guarantees they provide. I'll also introduce unsure — a package that implements these structures in Go. It's simple (the core logic for each data structure is 100–300 LOC), fast (usually several times faster than other implementations), and has no dependencies except for the standard library.

      Bloom filter • Count-min sketch • HyperLogLog • T-digest • Top-k

      # Bloom filter

      A Bloom filter is a set that trades certainty for space. It can tell you that an item is definitely not in the set, or that it probably is (which might be a false positive). The filter doesn't actually store the items, so it's much more compact than a regular set.

      For example, a regular set with 1,000,000 distinct 8-byte strings takes about 64 MB. A Bloom filter for the same strings, with a 1% false positive rate, uses only 1.24 MB (about 10 bits per item) — that's 50 times smaller. The size of the filter doesn't depend on the item size, so the difference gets even bigger with longer strings.

      A Bloom filter often resides in memory and helps minimize expensive I/O operations such as disk reads or network calls. You check if an item is in the filter, and if the answer is "no", you skip the costly lookup. If the answer is "yes", you still have to perform the lookup because it might be a false positive.

      // A filter for 1000 items with a 1% false positive rate.
      filter := bloom.New(1000, 0.01)
      
      filter.Add([]byte("alice"))
      filter.Add([]byte("bob"))
      
      filter.Contains([]byte("alice")) // true
      filter.Contains([]byte("carol")) // false (or, rarely, true)
      

      The filter is sized for the given number of items with a given false positive rate. You can add more, but the false positive rate will go up.

      You can add an item to a Bloom filter and check if an item is in the filter, but you cannot delete an item, count the number of items, or iterate over them.

      How it works

      Bloom filter1 is a large array of m bits, all set to zero at first. To add an item, you compute k hash values for it and set the k bits at those positions:

              ┌──────┐                       ┌───────┐
      item ──►│ hash │──► h1, h2, ..., hk ──►│ mod m │──► i1, i2, ..., ik
              └──────┘                       └───────┘
      
                i1          i2                  ik
      ┌───┬───┬─▼─┬───┬───┬─▼─┬───┬───┬───┬───┬─▼─┬───┐
      │ 0 │ 0 │ 1 │ 0 │ 0 │ 1 │ 0 │ 0 │ 0 │ 0 │ 1 │ 0 │
      └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
        0   1   2                                  m-1
      

      To check if an item is in the filter, you compute the same k hashes and check if all k bits are set:

      • If any of the bits is not set, the item definitely was never added.
      • If all the bits are set, the item was probably added, but it's not guaranteed (the bits could have been set by other items).

              i1          i2                  ik
        

        ┌───┬───┬─▼─┬───┬───┬─▼─┬───┬───┬───┬───┬─▼─┬───┐ │ 1 │ 0 │ 1 │ 0 │ 0 │ 1 │ 1 │ 0 │ 1 │ 0 │ 1 │ 0 │ all 1 → probably in the set └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘

        ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐ │ 1 │ 0 │ 1 │ 0 │ 0 │ 0 │ 1 │ 0 │ 1 │ 0 │ 1 │ 0 │ any 0 → definitely not └───┴───┴───┴───┴───┴─▲─┴───┴───┴───┴───┴───┴───┘ in the set (!)

      The k bits are randomly distributed throughout the entire array. When the filter is larger than the CPU cache, each bit access could result in a cache miss, so a lookup may wait on memory k times.

      Unsure uses a blocked Bloom filter2. The bit array is divided into 512-bit blocks, each matching the size of a CPU cache line. When you add or check an item, it is hashed once: part of the hash selects a block, and the rest selects k bits within that block. Each add or check only accesses one cache line, so the filter stays fast even when it's very large.

              ┌──────┐         ┌──► high 32 bits ──► block
      item ──►│ hash │──► h ───┤                   ┌─────────┐
              └──────┘         └──► low 32 bits ──►│ × salts │──► i1, i2, ..., ik
                                                   └─────────┘
      
                block
      ┌───────┬───▼───┬───────┬───────┬───────┬───────┐
      │   0   │   1   │   2   │   3   │  ...  │  n-1  │
      └───────┴───────┴───────┴───────┴───────┴───────┘
              │       │
      ┌───────┘       └───────────────────────────────┐
      │         i1          i2                  ik    │
      ├───┬───┬─▼─┬───┬───┬─▼─┬───┬───┬───┬───┬─▼─┬───┤
      │ 0 │ 0 │ 1 │ 0 │ 0 │ 1 │ 0 │ 0 │ 0 │ 0 │ 1 │ 0 │
      └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
        0   1   2                                  511
      

      In a blocked Bloom filter, some blocks end up with more items than others, which increases the false positive rate. To make up for this, the filter needs to be a bit larger. Compared to a standard Bloom filter, it uses about 3% more memory at a 1% false positive rate, 8% more at 0.1%, and 15% more at 0.01%.

      The filter uses the local wyhash3 implementation for hashing. It performs roughly the same as xxh34 but has a much simpler implementation, without SIMD or assembly.

      Benchmarks

      Here's an excerpt from the full benchmarks5, comparing unsure to bits- and-blooms6 (a classic Bloom filter) and gloom7 (a blocked one) (ns/op, lower is better):

      Operation | Items | unsure | bits-and-blooms | gloom
      ---|---|---|---|---
      Add | 10K | 9 | 37 | 17
      | 1M | 10 | 36 | 19
      | 50M | 38 | 170 | 63
      Contains, hit | 10K | 8 | 32 | 16
      | 1M | 9 | 32 | 18
      | 50M | 34 | 129 | 60
      Contains, miss | 10K | 8 | 41 | 27
      | 1M | 9 | 48 | 33
      | 50M | 34 | 113 | 60

      Memory, bits per item at 10M items (lower is better):

      False positive rate | unsure | bits-and-blooms | gloom
      ---|---|---|---
      10% | 4.84 | 4.80 | 5.39
      1% | 9.90 | 9.59 | 10.79
      0.1% | 15.49 | 14.38 | 16.18

      Unsure is about 4× faster than bits-and-blooms and 2× faster than gloom , using 1–8% more memory than bits-and-blooms and 4–10% less than gloom.

      # Count-min sketch

      A count-min sketch is a frequency table that trades accuracy for space. It tells you approximately how many times each item has appeared. The estimate is never less than the actual count, but it can be higher. The sketch doesn't actually store the items, so it's much more compact than a regular map of per- item counts.

      For example, a regular map counting 1,000,000 distinct 8-byte strings takes about 64 MB. A count-min sketch for the same strings, with estimates within 0.01% of the total count (with 99% probability), uses only 0.55 MB — that's 116 times smaller. The size of the sketch doesn't depend on the number of distinct items or their size, only on the accuracy you choose. So the difference gets even bigger with more or longer strings.

      A count-min sketch is useful when you want to track how many times an item shows up in a large stream of events. It's often used to check if something has happened a certain number of times, like rate-limiting an IP after X requests or sending an alert after an error happens Y times. A sketch can also help decide if a key is worth keeping in the cache given how often it was requested.

      // Estimates within 0.1% of the total count, with 99% probability.
      sketch := countmin.New(0.001, 0.01)
      
      sketch.Add([]byte("alice"))
      sketch.Add([]byte("bob"))
      sketch.AddN([]byte("alice"), 2)
      
      sketch.Count([]byte("alice")) // 3 (or, rarely, more)
      sketch.Count([]byte("bob"))   // 1 (or, rarely, more)
      sketch.Count([]byte("carol")) // 0 (or, rarely, more)
      sketch.Total()                // 4
      

      The sketch uses two settings: epsilon ε and delta δ. If the actual count for any given item is X and the total of all counts is N, then the estimated count for this item will usually be between X and X+ε·N. However, rarely (with a probability of δ) the estimate could be even higher.

      For example, if ε is 0.001, δ is 0.01, and N is 1 million, then the estimate could be off by up to 1,000 (ε·N) with at least 99% probability (1−δ), and by more than 1,000 with at most 1% probability (δ).

      The counting error in a sketch depends on the total of all counts, not on each individual item. Therefore, frequent items are estimated more or less accurately relative to their count, but rare items are not — the absolute error is too high for them.

      You can increase the per-item counter in a sketch and get the estimated count for an item, but you cannot decrease a counter or iterate over the items.

      How it works

      Count-min sketch8 is a table of counters with d rows and w columns, all starting at zero. Each row uses its own hash function that maps an item to one of the w counters. To add an item, you increment its counter in each row:

              ┌──────┐                       ┌───────┐
      item ──►│ hash │──► h1, h2, ..., hd ──►│ mod w │──► i1, i2, ..., id
              └──────┘                       └───────┘
      
             ┌───┬───┬─▼─┬───┬───┬───┬───┬───┬───┬───┐
      row 1  │ 0 │ 2 │ 4 │ 0 │ 1 │ 0 │ 0 │ 3 │ 0 │ 1 │  4 → 5
             ├───┼───┼───┼───┼───┼───┼─▼─┼───┼───┼───┤
      row 2  │ 1 │ 0 │ 0 │ 0 │ 2 │ 0 │ 3 │ 0 │ 1 │ 0 │  3 → 4
             ├───┼───┼───┼───┼───┼───┼───┼───┼─▼─┼───┤
      row d  │ 0 │ 1 │ 0 │ 2 │ 0 │ 0 │ 1 │ 0 │ 5 │ 0 │  5 → 6
             └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
                       i1              i2      id
      

      To estimate an item's count, you take the smallest value from its d counters:

      • Other items might hash to the same counter, so each counter value is ≥ true count.
      • The smallest counter is the one with the fewest collisions, so it's the best estimate.
           ┌───┬───┬─▼─┬───┬───┬───┬───┬───┬───┬───┐
        

        row 1 │ 0 │ 2 │ 4 │ 0 │ 1 │ 0 │ 0 │ 3 │ 0 │ 1 │ 4 ├───┼───┼───┼───┼───┼───┼─▼─┼───┼───┼───┤ row 2 │ 1 │ 0 │ 0 │ 0 │ 2 │ 0 │ 3 │ 0 │ 1 │ 0 │ 3 ├───┼───┼───┼───┼───┼───┼───┼───┼─▼─┼───┤ row d │ 0 │ 1 │ 0 │ 2 │ 0 │ 0 │ 1 │ 0 │ 5 │ 0 │ 5 min = 3 └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘

      With w = e/ε columns, each counter's error is at most ε·N, with probability at least 1 − 1/e. If you use d = ln(1/δ) rows, the chance that all d of the item's counters exceed its true count by more than ε·N is ≤ δ.

      Unsure uses a conservative update. When you add n to an item, it first finds the current estimate E (the smallest counter), then increases only the counters that are below E+n, leaving the larger ones unchanged. This keeps the same accuracy guarantee, but the actual error is about 2× lower. The tradeoff is that counts can't be decreased.

             ┌───┬───┬─▼─┬───┬───┬───┬───┬───┬───┬───┐
      row 1  │ 0 │ 2 │ 4 │ 0 │ 1 │ 0 │ 0 │ 3 │ 0 │ 1 │  4 → 4
             ├───┼───┼───┼───┼───┼───┼─▼─┼───┼───┼───┤
      row 2  │ 1 │ 0 │ 0 │ 0 │ 2 │ 0 │ 3 │ 0 │ 1 │ 0 │  3 → 4
             ├───┼───┼───┼───┼───┼───┼───┼───┼─▼─┼───┤
      row d  │ 0 │ 1 │ 0 │ 2 │ 0 │ 0 │ 1 │ 0 │ 5 │ 0 │  5 → 5
             └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
      

      Counters are 32-bit instead of the usual 64-bit, so the sketch uses 2× less memory. The item is hashed once, and each row gets its own position from that hash by salting it (multiplying by a random per-row constant).

              ┌──────┐         ┌─────────┐
      item ──►│ hash │──► h ──►│ × salts │──► i1, i2, ..., id
              └──────┘         └─────────┘
      

      The sketch uses wyhash for hashing.

      Benchmarks

      Here's an excerpt from the full benchmarks9, comparing unsure to BoomFilters10 (a classic count-min sketch with 64-bit counters) (ns/op, lower is better):

      Operation | ε | Size (unsure) | unsure | BoomFilters
      ---|---|---|---|---
      Add | 0.001 | 55 KB | 13 | 19
      | 0.00001 | 5.4 MB | 17 | 32
      | 0.000001 | 54 MB | 81 | 98
      Count | 0.001 | 55 KB | 9 | 51
      | 0.00001 | 5.4 MB | 14 | 64
      | 0.000001 | 54 MB | 52 | 139

      Accuracy at ε=0.0001, N=10M additions over 1M distinct items, mean overestimate (lower is better):

      Distribution | unsure | BoomFilters
      ---|---|---
      Uniform | 139 | 302
      Zipf, s = 1.1 | 23 | 44
      Zipf, s = 1.5 | 0.3 | 0.8
      Size | 536 KB | 1080 KB

      Unsure is about 1.5× faster for Add and 4× faster for Count, using 2× less memory with 2–2.7× lower error.

      # HyperLogLog

      HyperLogLog is a unique items counter that trades accuracy for space. It tells you approximately how many distinct items it has seen, no matter how many times each one appeared. HyperLogLog (also called a sketch from here on) doesn't actually store the items, so it's much more compact than a regular set.

      For example, a regular set of 1,000,000 distinct 8-byte strings takes about 64 MB. A HyperLogLog sketch counting the same strings with about 0.8% error uses only 16 KB — that's almost 4,000 times smaller. The size of the sketch doesn't depend on the number of items or their size, only on the accuracy you choose. A 16 KB sketch counts a billion items as accurately as a thousand.

      HyperLogLog is useful when you need to count unique things in a large stream: unique visitors to a website, unique search queries per day, or distinct values in a database column.

      // Standard error about 0.8% of the true count.
      sketch := hll.New()
      
      sketch.Add([]byte("alice"))
      sketch.Add([]byte("bob"))
      sketch.Add([]byte("alice"))
      sketch.Add([]byte("carol"))
      
      sketch.Count() // 3 (approximately)
      

      You can merge sketches to gather data from multiple machines or segments (like by hour, page, or region). When you merge two sketches, you get the total number of unique items from both, without counting shared items twice.

      home := hll.New() // visitors to the home page
      docs := hll.New() // visitors to the docs
      // ...
      home.Merge(docs)
      home.Count() // visitors to either page
      

      The sketch has one setting: the precision p , which gives a relative standard error (stdErr) of 1.04/√(2^p). A common default is p=14, which gives 0.81% error.

      With p=14 and 1 million distinct items:

      • 68% of the time the estimate is within 0.81% (8,100) of the true count,
      • 95% within 1.6% (2·stdErr),
      • 99.7% within 2.4% (3·stdErr).

      The error is relative to the count, so the standard error is the same 0.81% for a thousand items or a billion.

      You can add items to a sketch, get the estimated count, and merge sketches. You cannot check if a specific item was added, remove items, or list them.

      How it works

      HyperLogLog11 is based on a simple observation. If you hash items to random bit strings, about half of them start with 1, a quarter with 01, an eighth with 001, and so on. Seeing a hash with k leading zeros suggests there were about 2^(k+1) distinct items. Duplicates hash to the same value, so they don't affect the result.

      A single observation is unreliable, so the sketch divides the items into m = 2^p groups, where p is the selected precision. The first p bits of the hash pick a group (a register), and the register keeps the highest rank (leading zeros plus one) it has seen in the rest of the hash:

              ┌──────┐   ┌──────────┬────────────────────────┐
      item ──►│ hash │──►│ 01101001 │ 0001101...             │
              └──────┘   └────┬─────┴───────────┬────────────┘
                              │ register i      └ rank = 3 zeros + 1 = 4
                ┌───┬───┬───┬─▼─┬───┬───┬───┬───┬───┬───┐
      registers │ 3 │ 0 │ 5 │ 2 │ 1 │ 0 │ 4 │ 2 │ 0 │ 1 │  2 → 4
                └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
      

      The count is estimated from all the registers together, using a harmonic mean of 2^register. The standard error is about 1.04/√m. Merging two sketches is just taking the maximum value from each pair of registers.

      The original estimator is biased when dealing with small counts (up to a few times m), so in these cases it uses a different formula called linear counting. This switch creates a sudden change in error, and some implementations (like HyperLogLog++12) address it by using large tables of bias corrections based on real data.

      Unsure uses the improved estimator by Otmar Ertl13. Instead of a harmonic mean of the registers, it works from a histogram : how many registers have value 0, value 1, and so on. A formula applied to the histogram gives an accurate estimate for any number of items, from zero to billions, so there's no need for a separate formula for small counts or for correction tables.

      The sketch updates the histogram whenever registers change. Most adds don't change any registers, so this is almost free. Counting always takes the same amount of time, no matter how big the sketch is. Other implementations scan all the registers on every count, which takes from microseconds to milliseconds.

      Registers are one byte each, and the histogram has 64 four-byte counters (256 bytes). The item is hashed once with wyhash , and the 64-bit hash is split into the register index and the rank.

      Benchmarks

      Here's an excerpt from the full benchmarks14, comparing unsure to axiom15 (HyperLogLog with LogLog-Beta estimator and sparse mode) (ns/op, lower is better):

      Operation | p | Size | unsure | axiom
      ---|---|---|---|---
      Add | 10 | 1 KB | 5.5 | 7.6
      | 14 | 16 KB | 5.6 | 7.6
      | 18 | 256 KB | 8.1 | 7.9
      Count | 10 | 1 KB | 68 | 18,300
      | 14 | 16 KB | 62 | 350,000
      | 18 | 256 KB | 57 | 4,710,000
      Merge | 10 | 1 KB | 730 | 1,710
      | 14 | 16 KB | 20,100 | 58,600
      | 18 | 256 KB | 341,000 | 951,000

      Accuracy at p=14 (0.81% standard error), relative RMSE over 100 sketches (lower is better):

      Distinct items | unsure | axiom
      ---|---|---
      1,000 | 0.63% | 0.02%
      40,000 | 0.64% | 0.71%
      1,000,000 | 0.79% | 0.89%

      Memory at p=14 after adding the given number of distinct items (lower is better):

      Distinct items | unsure | axiom
      ---|---|---
      100 | 16 KB | 1.2 KB
      1,000 | 16 KB | 4.2 KB
      10,000 | 16 KB | 16 KB
      1,000,000 | 16 KB | 16 KB

      Unsure adds about as fast as axiom , counts 270–83,000× faster, and merges 2.3–2.9× faster, with the same accuracy and memory for counts above the number of registers. When there are fewer items than registers, axiom 's sparse mode makes it more accurate and compact.

      # T-digest

      A t-digest is a summary of a stream of numbers that trades accuracy for space. It can give you an approximate median, 99th percentile, or any other quantile of the data. It can also estimate what fraction of the numbers are below a certain value (the CDF). The digest doesn't actually store the numbers, so it's much more compact than a sorted list.

      For example, to find the exact 99th percentile of 1,000,000 numbers, you'd have to keep all of them. With 64-bit floats, that takes 8 MB. A t-digest estimates the same percentile within about 0.03% of the rank (between the 98.97th and the 99.03rd percentile) using only 8 KB — 1,000 times smaller. The size of the digest doesn't depend on the number of values, only on the accuracy you choose. An 8 KB digest summarizes a billion values as well as a million.

      A t-digest is useful when you need quantiles over a large stream: latency percentiles for a service, the distribution of request sizes or prices, or the outlier thresholds in sensor data.

      // Response times in milliseconds.
      digest := tdigest.New()
      
      digest.Add(12.5)
      digest.Add(8.1)
      digest.Add(130.0)
      // ...
      
      digest.Quantile(0.5)  // median
      digest.Quantile(0.99) // 99th percentile
      digest.CDF(100)       // fraction of responses faster than 100 ms
      

      You can merge digests to gather data from multiple machines or segments (like by hour, endpoint, or region). A merged digest estimates the percentiles of all values, but with less accuracy than individual digests do.

      east := tdigest.New() // latencies on one server
      west := tdigest.New() // latencies on another
      // ...
      east.Merge(west)
      east.Quantile(0.99) // 99th percentile across both servers
      

      The digest has one setting: the compression δ , which limits the number of centroids (see How it works below) to δ+2. A common default is δ=100, which takes 8 KB. Increasing δ uses more memory but reduces estimation error.

      The error is measured in ranks: a rank error of 0.03% at quantile q=0.99 means the value returned by Quantile(0.99) is somewhere between the 98.97th and the 99.03rd percentile of the actual values. Tail estimates, such as q=0.99 or q=0.999, are more accurate than the median (q=0.5).

      You can add numbers to a digest, estimate quantiles and the CDF, and merge digests. You cannot remove numbers or list them.

      How it works

      T-digest16 summarizes the numbers as a sorted list of centroids. Each centroid has a mean and a weight — the number of values it represents. To estimate a quantile, the digest finds the centroids around the requested rank and interpolates between their means.

      The trick is in how big the centroids are allowed to grow. A scale function k(q) maps a quantile q to a number from -δ/4 to δ/4, and each centroid may only span 1 unit of k: if a centroid covers the quantiles from q₁ to q₂, then k(q₂) − k(q₁) ≤ 1.

      The arcsine scale function, k(q) = δ/(2π)·asin(2q-1), is steep near q=0 and q=1 and flat near the median. This means the centroids it produces are larger in the center and smaller at the ends:

      weight
        │                ┌──┐
        │             ┌──┤  ├──┐
        │          ┌──┤  │  │  ├──┐
        │       ┌──┤  │  │  │  │  ├──┐
        │  ┌─┬──┤  │  │  │  │  │  │  ├──┬─┐
        └──┴─┴──┴──┴──┴──┴──┴──┴──┴──┴──┴─┴──► value
          min      q=0.25   median  q=0.75     max
      

      With 1M values and δ=100, the centroids around the median hold about 27,000 values each, those around the 99th percentile about 5,000, and the outermost ones about 500. This keeps the error near the tails small.

      Unsure is the merging t-digest from the Dunning and Ertl paper. New values go to a buffer of 5·δ numbers. When the buffer is full, the digest sorts it and merges it with the centroids (already sorted) in a single pass, building new centroids from left to right as long as each one fits within its span of k. Every other pass goes right to left, so that neither tail ends up with fuller centroids. Quantile, CDF and Merge flush the buffer first.

      The centroids are kept in two fixed arrays of δ+2 entries (the current list and the next one being built), along with the cumulative weights for a binary search in Quantile and CDF. With δ=100, that's 16·102·2 + 8·103 bytes for the centroids, and 8·500 bytes for the buffer, about 8 KB in total.

      Centroids with weight 1 are treated as exact values rather than spread around their mean, and the exact minimum and maximum are used at the ends. So digests with few values give exact results, and Quantile(0) and Quantile(1) are always exact.

      Benchmarks

      Here's an excerpt from the full benchmarks17, comparing unsure to influxdata18 (merging t-digest with the same scale function) (ns/op, lower is better):

      Operation | δ | unsure | influx
      ---|---|---|---
      Add | 50 | 44 | 78
      | 100 | 49 | 86
      | 500 | 59 | 105
      Quantile | 50 | 11 | 13
      | 100 | 13 | 13
      | 500 | 15 | 16
      Merge | 50 | 296 | 2,060
      | 100 | 630 | 4,330
      | 500 | 2,720 | 23,950

      Accuracy at δ=100, mean rank error over 1M normal values (lower is better):

      Digest | Quantile | unsure | influx
      ---|---|---|---
      Single | 0.5 | 0.007% | 0.015%
      | 0.99 | 0.018% | 0.016%
      | 0.999 | 0.011% | 0.009%
      Merged | 0.5 | 0.055% | 0.037%
      | 0.99 | 0.023% | 0.021%
      | 0.999 | 0.006% | 0.016%

      Memory at δ=100 (lower is better): unsure 8.5 KB, influxdata 14.4 KB.

      Unsure adds values about 1.8× faster than influxdata , queries at the same speed, merges 7–9× faster, and uses 40% less memory at about the same accuracy.

      # Top-k sketch

      A Top-k sketch finds the k most frequent items in a stream (the "heavy hitters"), along with their approximate counts. It uses a fixed amount of memory based only on k, no matter how many different items are in the stream.

      To find the exact top items, you'd have to count every unique item, for example with a map of per-item counts. With millions of distinct items, that takes tens or hundreds of megabytes. A Top-k sketch for the top 1000 items takes about 360 KB, and it usually finds all of them.

      A Top-k sketch is useful when you want to identify the "hottest" data: the most requested URLs, the most active users, or the most common search queries. Unlike a count-min sketch, it keeps the actual items, so it can list them.

      // Track the 2 most frequent items.
      sketch := topk.New(2)
      
      sketch.Add([]byte("alice"))
      sketch.Add([]byte("bob"))
      sketch.Add([]byte("carol"))
      sketch.AddN([]byte("alice"), 4)
      sketch.AddN([]byte("carol"), 2)
      
      sketch.Top()                  // [{alice 5} {carol 3}]
      sketch.Count([]byte("alice")) // 5
      sketch.Count([]byte("bob"))   // 0 (not in the top 2)
      sketch.Total()                // 9
      

      Top returns up to k items, from the most frequent to the least frequent. Counts are estimates: they're usually exact for the most frequent items, but may be slightly lower than the actual count for less common items.

      The sketch works best when the stream is skewed, meaning a few items appear much more often than the others. This is common in real situations. If all items are about equally frequent, there is no clear top k, and the results become less accurate.

      You can add items to the sketch and get the top items with their counts, but you can't decrease counts or check items that aren't in the top k.

      How it works

      HeavyKeeper19 is a table of buckets that estimates item counts. It has d rows and w columns, and each item maps to one bucket in each row. Each bucket holds a fingerprint of the item and a count. To add an item, you update its bucket in each row:

      • If the bucket is empty or owned by the item, increase its count.
      • If the bucket is owned by another item, decay it: decrease its count by 1 with probability b^count (b < 1). When the count reaches 0, the new item takes over the bucket with a count of 1.
              ┌──────┐
        

        add x ──► │ hash │──► h ──► high 32 bits ──► fingerprint = 7 └──────┘ │ │ map to buckets ┌──┴────────────┐ ┌───────┬───▼───┬───────┬───│───┬───────┐ row 1 │ │ fp=7 │ fp=3 │ │ │ fp=5 │ column 2 is owned by x: │ │ 41 │ 2 │ │ │ 980 │ 41 → 42 ├───────┼───────┼───────┼───▼───┼───────┤ row 2 │ fp=9 │ │ │ fp=2 │ fp=4 │ column 4 is owned by another: │ 17 │ │ │ 3 │ 1 │ 3 → 2 with probability b^3 └───────┴───────┴───────┴───────┴───────┘ col 1 col 2 col 3 col 4 col 5

      The item's estimated count is the largest count among its buckets. Frequent items quickly reach counts that make decay very unlikely, so they keep their buckets. Rare items keep replacing each other without affecting the frequent ones. An item that becomes frequent later in the stream can still outnumber a less frequent owner and take over its bucket.

      Next to the table, the sketch keeps a min-heap with the k items that have the largest estimates so far. After an item's buckets are updated, if its estimate is larger than the smallest count in the heap, the item is added to the heap, and the smallest item is removed. If the item is already in the heap, its count is increased.

                         ┌───────────┐
      add x (15) ───────►│ bob    12 │  the root has the smallest count
                         └─────┬─────┘
                    ┌──────────┴────────┐
              ┌─────┴─────┐       ┌─────┴─────┐
              │ alice  30 │       │ dave   14 │  15 > 12: x replaces bob at the root
              └─────┬─────┘       └───────────┘  15 > 14: x moves down, dave moves up
            ┌───────┴──────┐
      ┌─────┴─────┐  ┌─────┴─────┐
      │ eve   980 │  │ fay    41 │
      └───────────┘  └───────────┘
      

      Unsure uses d = 2 rows of max(16k, 256) buckets, and a decay base of b = 0.8. The probabilities b^count are precomputed as 64-bit thresholds, so decay is cheap: the count c decreases if a random number is below the c-th threshold.

      The original HeavyKeeper uses b = 1.08⁻¹ ≈ 0.93, and more rows. A smaller b lets frequent items lock their buckets faster, which makes the sketch more precise on flat streams. However, if b is too small (like 0.5), the first items to claim buckets keep them permanently, so items that become frequent later are never counted, even if they end up being the most frequent. Using b = 0.8 keeps most of the precision and still catches most late-arriving frequent items. As for the rows, two are enough to protect frequent items from collisions in a single row, and adding more rows only makes the sketch slower.

      The item is hashed once. The hash is mapped to a position in each row by salting it (multiplying by a random per-row constant). The fingerprint is the top 32 bits of the hash. The heap uses the 64-bit hash to identify items, so it doesn't compare the actual item bytes.

      Each bucket is 8 bytes (a 32-bit fingerprint and a 32-bit count), so the table takes 256·k bytes. The heap takes about 100 bytes per item plus the item itself.

      The sketch uses wyhash for hashing and wyrand for random numbers.

      Benchmarks

      Here's an excerpt from the full benchmarks20, comparing unsure to keiler21 (HeavyKeeper with b = 0.9 and d = ln k) and dgryski22 (Filtered Space-Saving23) on the Zipf s=0.8 stream (time/op, lower is better):

      Operation | k | unsure | keiler | dgryski
      ---|---|---|---|---
      Add | 10 | 24 ns | 64 ns | 59 ns
      | 100 | 25 ns | 84 ns | 70 ns
      | 1000 | 33 ns | 130 ns | 73 ns
      Top | 10 | 0.34 µs | 0.64 µs | 0.77 µs
      | 100 | 3.7 µs | 13 µs | 14 µs
      | 1000 | 75 µs | 270 µs | 292 µs

      Precision is the fraction of the reported top k that is in the true top k (higher is better):

      k | Zipf s | unsure | keiler | dgryski
      ---|---|---|---|---
      100 | 0.6 | 0.90 | 0.38 | 0.19
      | 0.8 | 1.00 | 0.78 | 0.85
      | 1.0 | 0.99 | 1.00 | 1.00
      | Size | 39 KB | 27 KB | 39 KB
      1000 | 0.6 | 0.97 | 0.70 | 0.52
      | 0.8 | 1.00 | 0.98 | 1.00
      | 1.0 | 1.00 | 1.00 | 1.00
      | Size | 364 KB | 414 KB | 453 KB

      Count error is the mean of |estimate − true| / true over the reported items (lower is better):

      k | Zipf s | unsure | keiler | dgryski
      ---|---|---|---|---
      100 | 0.6 | 14% | 94% | 428×
      | 0.8 | 0.10% | 46% | 230%
      | 1.0 | 0.01% | 0.12% | 0.0%
      1000 | 0.6 | 2.4% | 62% | 18×
      | 0.8 | 0.23% | 1.9% | 0.31%
      | 1.0 | 0.05% | 0.24% | 0.02%

      Unsure is 2–4× faster than the others for Add and 1.8–4× faster for Top. On flat streams (s=0.6), it finds the true top k with 90–97% precision, while keiler drops to 38–70% precision with a count error of 62–94%, and dgryski to 19–52% with counts 18× or more too high. On skewed streams (s=1.0), all three are about equally accurate.

      # Wrapping up

      As engineers, we usually want exact answers from our data. But sometimes, allowing a bit of uncertainty can cut memory usage by tens, hundreds, or even thousands of times. That's where probabilistic data structures come in:

      • Bloom filter checks if an item might be in a set.
      • Count-min sketch estimates how many times each item has occurred.
      • HyperLogLog estimates the number of distinct items.
      • T-digest estimates quantiles of a stream of numbers.
      • Top-k sketch identifies the most frequent items in a stream.

      To use them in Go, try the __nalgeon/unsure package:

      go get github.com/nalgeon/unsure
      

      1. Space/time trade-offs in hash coding with allowable errors by Burton H. Bloom, 1970. ↩︎

      2. Cache-, hash-, and space-efficient Bloom filters by Felix Putze et al., 2009. ↩︎

      3. Reference wyhash implementation by Wang Yi. ↩︎

      4. Reference xxHash implementation by Yann Collet. ↩︎

      5. Bloom filter benchmarks. ↩︎

      6. bits-and-blooms/bloom by Daniel Lemire. ↩︎

      7. jcalabro/gloom by Jim Calabro. ↩︎

      8. An improved data stream summary: the count-min sketch and its applications by Graham Cormode and S. Muthukrishnan, 2005. ↩︎

      9. Count-min sketch benchmarks. ↩︎

      10. tylertreat/BoomFilters by Tyler Treat. ↩︎

      11. HyperLogLog: the analysis of a near-optimal cardinality estimation algorithm by Philippe Flajolet et al., 2007. ↩︎

      12. HyperLogLog in practice by Stefan Heuleet et al., 2013. ↩︎

      13. New cardinality estimation algorithms for HyperLogLog sketches by Otmar Ertl, 2017. ↩︎

      14. HyperLogLog benchmarks. ↩︎

      15. axiomhq/hyperloglog by Axiom. ↩︎

      16. Computing extremely accurate quantiles using t-digests by Ted Dunning and Otmar Ertl, 2019. ↩︎

      17. T-digest benchmarks. ↩︎

      18. influxdata/tdigest by InfluxData. ↩︎

      19. HeavyKeeper: An Accurate Algorithm for Finding Top-k Elephant Flows by Junzhi Gong et al., 2018. ↩︎

      20. Top-k benchmarks. ↩︎

      21. keilerkonzept/topk by KEILERKONZEPT. ↩︎

      22. dgryski/go-topk by Damian Gryski. ↩︎

      23. Efficient Computation of Frequent and Top-k Elements in Data Streams by Ahmed Metwally et al., 2005. ↩︎

    7. 🔗 smol-machines/smolvm smolvm v1.34.4 release

      What's Changed

      • docs: say that virtiofs DAX is off on arm64 hosts and SMOLVM_MOUNT_DAX does nothing there by @BinSquare in #2087
      • Add smolvm docker: one command starts a Docker engine in a managed machine and points docker at it by @BinSquare in #2089
      • Share the home directory with the smolvm docker machine at the same path by @BinSquare in #2090
      • Resolve host.docker.internal to the host from smolvm docker containers by @BinSquare in #2091
      • Fix a port race in the leader-exit test by @BinSquare in #2096
      • Remove smolvm docker by @BinSquare in #2095
      • Hand supplied credential values to a running embedded machine at once by @BinSquare in #2097
      • Pin libkrunfw with UDP kept inside a TSI guest, and test it by @BinSquare in #2099
      • Publish ports below 1024 on macOS, add IPv6 loopback to live-forwarded ports, and lift the 64-mapping cap by @BinSquare in #2092
      • Return idle guest memory to the host within two minutes and cap new machines at half the host's RAM by @BinSquare in #2094
      • Install a root-owned agent-rootfs when root runs install.sh by @rdslw in #2082
      • Announce a changed file to the guest once per change by @BinSquare in #2102
      • Answer guest DNS from a host cache that coalesces bursts and resends lost queries by @BinSquare in #2098
      • Keep every disk chain under the branch depth limit: fold restored checkpoint layers and frozen-source chains by @BinSquare in #2103
      • Exec sessions: commands the node owns, resumable after a dropped connection by @BinSquare in #2101
      • Let a guest hold tens of thousands of connections on virtio-net and free their host sockets promptly by @BinSquare in #2104
      • Scope the usage journal to the test's own thread by @BinSquare in #2106
      • Pin libkrun 526be460 and libkrunfw f290c62b, rebuilt for every platform by @BinSquare in #2109
      • Build the agent rootfs as non-root on hosts with user namespaces again by @BinSquare in #2107
      • Answer a start missing the mediated interceptor with 400, not 500 by @BinSquare in #2108
      • Run tests that need a released file lock free at once in their own process by @BinSquare in #2110
      • Pin libkrun 9df62257 and libkrunfw 7f4d4950, rebuilt for every platform by @BinSquare in #2113
      • Stop resetting virtio-net connections a server closes first by @BinSquare in #2118
      • Upgrade rusqlite to 0.41 for the patched bundled SQLite (RUSTSEC-2026-0459) by @BinSquare in #2128
      • Keep a host memory reserve VMs cannot take and charge branch children for growth by @BinSquare in #2127
      • Ask before stopping a machine on delete, so a refused or declined delete leaves it running by @connorburgess in #2131
      • Prepare SmolVM v1.34.1 for release by @BinSquare in #2135
      • Bring a soft open-file limit above kern.maxfilesperproc down to the cap on macOS, so the limit raise_nofile_limit reports is the one in force by @connorburgess in #2132
      • Leave no data directory behind when exec, status or stop name a machine that does not exist by @connorburgess in #2129
      • Warn when --block-private keeps a named host unreachable by @BinSquare in #2146
      • Register Rosetta itself as the x86_64 interpreter when the host answers its start-up ioctl by @BinSquare in #2148
      • Make a mounted host directory belong to the workload user so a non-root workload can write to it by @BinSquare in #2149
      • Record the image platform on the machine so a Rosetta machine can be created from an amd64 image by @BinSquare in #2147
      • Bump libkrun so a Rosetta machine runs amd64 programs directly and a macOS machine stops promptly by @BinSquare in #2150
      • Keep a cache disk's chain on its shared base when compaction shortens it by @BinSquare in #2145
      • Satisfy Rust 1.100's needless_bool lint in connect_in_progress on Windows by @BinSquare in #2154
      • Bound branch admission and reported capacity by the VM slice's memory limit, not just host free memory by @BinSquare in #2152
      • Stop throttling the VM slice and reclaim it from the pressure guard instead by @BinSquare in #2153
      • Release a paused branch child's VM lock so the memory pressure guard can resume it by @BinSquare in #2157
      • Keep a restored machine's local image on its storage disk instead of mounting the capturing host's archive by @BinSquare in #2163
      • Update quinn-udp to 0.5.16 for RUSTSEC-2026-0538 by @BinSquare in #2165
      • Count every symlink with one mode in the agent rootfs digest so a Mac checkpoint restores on Linux by @BinSquare in #2162
      • Carry guest traffic in 64 KB frames over the gateway link so downloads use a quarter of the CPU by @BinSquare in #2168
      • Pin libkrun 518949b4 and libkrunfw 0fae3853, rebuilt for every platform by @BinSquare in #2169

      New Contributors

      Full Changelog : v1.34.0...v1.34.4

    8. 🔗 tintinweb/pi-subagents v0.25.0 release

      What changes for existing users

      • general-purpose can now spawn subagents of its own, matching Claude Code (#448). Set maxSubagentDepth to 1 to turn nesting off; an ejected general-purpose.md without allowed_subagents keeps the old behavior.
      • /agents → Settings writes ~/.pi/agent/subagents.json unless the project already has .pi/subagents.json; Tab switches the target (#391, #419).

      New

      • /agents → Settings tags each row with the file that sets it, resets a row with Delete, and filters as you type.

      Fixed

      • The Settings number editor refuses values that loading would drop on restart.
      • Finished nested subagents no longer outlive their parent across a session switch.
      • get_subagent_result shows when a saved result finished (#436).
      • A leftover schedule lock no longer freezes pi for 5 seconds (#247, #266).

      QA

      • 2657 tests passed (96 scripted e2e); live e2e against a real model: 93 passed.

      Full details in CHANGELOG.md.

    9. 🔗 backnotprop/plannotator v0.28.63 release

      Follow @plannotator on X for updates

      Missed recent releases? Release | Highlights
      ---|---
      v0.28.62 | Agents started from the Inbox now work on Windows, pick a model and effort when you start an agent, rules for your agents, written in your own words, post a thread's decisions on its pull request, the Inbox loads faster on a slow connection
      v0.28.61 | Updates now update the Claude Code plugin too, an agent's chosen face shows on every icon of it, filter the Inbox list by pull request state, Modern dark shows section bands and the Reply button, one conversation no longer shows as two agents
      v0.28.60 | Click a word to highlight it, a one-time Themes dialog, Settings → Rows rebuilt, tell your agent how you want your rows, starred threads as pills above the list, a pill for new messages out of view, a half-circle face picker with ten Glass colours, a new phone sidebar and reply box
      v0.28.59 | A quieter Agents section in the sidebar, machine names only when agents run on more than one machine, agent icons that are always gently alive and lean toward your pointer
      v0.28.58 | Start Codex from New message, an Agents section in the sidebar, start an agent in a folder on any drive, play audio attachments and comment at a moment, Claude Code's Plannotator tools work on Windows
      v0.28.57 | Pin artifacts, and see every artifact on one page, filter the list by project, date or agent, a thread shows its pull requests and their state, choose what the sidebar shows, and in what order, Ask AI starts from Side in the selection bar
      v0.28.56 | Questions can show trade-offs and a prototype to try, a thread with many big pictures no longer crashes the tab, Escape closes New message and keeps your draft, read threads stop being bold and keep their place, agent messages that name no thread start a new one
      v0.28.55 | Floating reply drafts, now a setting under Experimental, open questions sit next to Reply again, a comment box that keeps unsent comments as Drafts, choose how your list looks: Minimal, Balanced or Detailed, update an older linked machine from this Inbox
      v0.28.53 | Start an agent in a new folder, or from a git URL, "+" on each project row starts a session there, a reaction tray, a thread's Links, Settings → Activity, New message offers the open thread's files, Bro mode: agents write to you in plain words
      v0.28.52 | Start agents from the Inbox, on by default, a new reply box, Ask AI for everyone, Insights in Settings → Decision data, Plannotator reloads itself after an update
      v0.28.51 | Starred threads, a note when an agent's session has ended, "Back from snooze", Ask about a past decision, expand arrows in guided reviews
      v0.28.50 | A faster, lighter Inbox, session names across the Inbox, initiatives on the Board, earlier comments on a file, global comments on Guided Reviews

      What's New in v0.28.63

      TL;DR

      • New: Pair Grok Bot and other cloud agents from Settings
      • New: Hermes Agent, OpenClaw and Muse Code can use the Inbox
      • New: Add a thread to Priority to keep it on top
      • New: Tag threads, and find each tag in the sidebar
      • Off by default: Pull requests board as a table, with bulk Merge

      0.28.63 brings personal and cloud agents into the Inbox. You can pair an agent that runs somewhere else, such as Grok Bot or Muse by Meta, and Hermes Agent, OpenClaw and Muse Code can now message you from the same computer. The Inbox also gets Priority, tags, replies that quote what they answer, and OpenCode in New message. It has 81 PRs. Three come from external contributors, and one of those is a first contribution: welcome @mauricedesaxe.

      Personal and cloud agents

      Pair a cloud agent from Settings

      A cloud agent is an agent that runs somewhere other than your computer: a Claude Code routine, Grok Bot, Muse by Meta, a Hermes Agent or OpenClaw server, or any other agent you can send a message to. Settings → Cloud agents pairs one. Pick its kind, give it a name, and copy the one message Plannotator shows you. The message is shown only once. Send it to the agent and it sets itself up from a public page on plannotator.ai. A Claude Code routine gets three short pieces for its settings instead. The card then says "Waiting for to connect…" until the agent's first call, and "Connected" after that.

      Once paired, the agent shows in New message's To list and in the sidebar's Agents. It can start threads, read the threads it started, was sent or was tagged in, and answer in them. It cannot answer your questions, approve anything, run anything on your computer, open your files, or read any other thread. Its messages pass through Plannotator's relay sealed end to end, so the relay cannot read them. If your computer is asleep, a read says so and a send waits at the relay until the computer is back.

      To have the agent start when you write to it, add its wake address and key, then press Send a test. The thread then shows a line such as "Woke Nightly fixer · run started". Without a wake address the agent checks for new messages by itself, and your reply reads "Saved for …" and then "Delivered", like a reply to Muse Code or Cursor. Muse by Meta has no wake address, so it always checks by itself. New pairing stops the old pairing at once, and Remove cuts the agent off. A How does this work? button beside the section's title opens a five-step walk-through in pictures.

      The section appears once the Inbox has reached the relay. #3138, #3178, #3187, #3197, #3212, #3223, #3254, #3270

      Hermes Agent, OpenClaw and Muse Code on your computer

      Three more agents can use the Inbox from the same computer.

      • Hermes Agent (Nous Research) gets the plannotator_inbox tool through a new plugin, and your reply comes back into the Hermes session that asked, as a new turn. Only your own sessions get it: the terminal, the TUI, the Desktop app and your own direct messages. Install it with hermes plugins install backnotprop/plannotator/apps/hermes-plugin --enable, then run plannotator inbox once to turn the tool on. That line installs the plugin from this repository's main branch; the plugin's README explains the reply switch plannotator inbox turns on, and how to turn it off. #3217, #3238, #3249
      • OpenClaw gets the tool in your own chats only: OpenClaw on this computer and your own direct messages, never a shared chat or a channel. Your reply arrives in the same chat as a new message, once. It needs OpenClaw 2026.11.5-beta.1 or newer. The @plannotator/openclaw package is not on npm yet; the plugin's README shows how to install it from a checkout of this repository today. #3216, #3251, #3263
      • Muse Code (Meta's coding agent in the terminal) is connected when you run plannotator inbox. Its messages show as Muse Code, with Muse's own mark. Replies don't start a Muse turn, so Muse reads your answer on its next turn, as Gemini CLI and Cursor do. #3209, #3262

      Each has a row in Settings → Agents and a mark of its own in the sidebar, the list and the To list. The Inbox tool for Hermes Agent and OpenClaw starts off until plannotator inbox or Settings → Agents turns it on.

      After two days of use, a one-time dialog says that your personal agents are welcome in the Inbox, with Connect one , which opens Settings → Cloud agents. It shows only while none is connected. #3280

      Starting and managing agents

      • Start OpenCode from New message. To offers "OpenCode · New session" next to Claude Code, Codex and Pi, with a model and a variant (OpenCode's word for effort). Replies, Stop, the run line and Open in Terminal work as they do for Pi and Codex. It needs OpenCode 2 and the Plannotator OpenCode plugin from this release. #3186
      • Pick Codex's model and effort. The "Default model" button now works for Codex too, and Effort shows only the levels the picked model takes. #3177
      • Find a model in a long list. When the Model column lists more than 8 models, it starts with a "Find a model" field that narrows the list as you type, the way Pi's own model selector matches. #3200
      • A machine switch in To. With a linked machine, the top of New message's To list has one button per machine, with how many agents run there. Pick one to see what runs there and what you can start; an asleep machine says since when. #3257
      • Stop and Delete from the sidebar. An agent the Inbox started now has "Stop" and "Delete … session…" in its sidebar menu. Delete asks in a dialog, and its "Also archive its N threads" box is off by default. #3241
      • Rename an agent. Right-click an agent in the sidebar, or use its ⋯, and choose Rename…. The name shows everywhere the Inbox names that agent. Agents still see their own labels. #3180
      • Linked machines keep their own marks. An agent's icon and name, and a star on a thread, now live on the machine the agent or thread belongs to, so every linked window shows the same one. Starring another machine's thread used to fail with "No thread". #3234, #3246
      • Starting agents on a linked machine. Four fixes: the "+" tip no longer names the machine twice, "+" no longer opens an empty To for an asleep machine this page never read, picking an agent kind only another machine has now starts it there, and the Board's New card lists only this Inbox's projects. #3233
      • A Claude Code turn that ends in an error says so. When a session the Inbox started hits a credit, sign-in or rate-limit error, the thread gets one note with Claude Code's own words and a Try again button. A notification follows for Claude Code, Codex and Pi, under the same rules as a question's notification. #3184, #3195
      • Claude Code in VS Code's chat panel. Sessions in the Claude Code extension's panel now get the Inbox tool and are woken by your replies, as in the terminal. This has not yet been tried in a real VS Code panel. #3151, toward #3111 by @Qwenjin

      Plannotator Inbox

      Priority

      The row menu, the phone's long-press sheet and a thread's ⋯ menu have Add to Priority. The thread moves to a Priority section at the top of the list, shown only when it holds a thread, and stays there until you remove it or archive it. Its row keeps all its marks. A toast offers Undo.

      An agent can also mark a thread with send_message's new priority: true, or take the mark out with priority: false. Its instructions say to follow you: use it when you said something matters most to you, and take it out when that is over. An agent's mark is the same as yours, and you can remove it at any time. Agents never see which threads are in Priority. #3232, #3277

      A one-time dialog, "Put a thread first in your list", shows how to add a thread to Priority. It comes the day after an update at the earliest, and only if you have never used Priority. #3286

      Tags

      A thread can now have tags. Add tag is in a row's menu and a thread's ⋯ menu: find a tag, tick it, or type a new name. Tags get their own section in the sidebar, under Starred, with each tag's waiting count; a click lists that tag's threads. Right-click a tag to rename or delete it, with Undo. Typing #Name in your own reply tags the thread too.

      On the Board, "Initiative" is now "Tag", and a Board card's tag is the same tag a thread has. Existing initiatives show up as tags, with nothing to move. Agents never see a thread's tags. #3228, #3272

      Reply with a quote

      Press ↩ on an older message, and the reply box gets one quiet line with that message's author, time and first words. Select words in a message first, and the line quotes those words instead. Your own messages get ↩ too. The sent reply shows the same line, which takes you back to the original. The agent reads which message, or which words, you answered. A plain Reply is unchanged. #3160, closing #3109 by @Arobotmaster

      See which session wrote what

      A thread that several agent sessions wrote in used to show only a people icon and a count. The header now shows the sessions' marks and "N sessions"; hover, tap or focus it to see each session's name and state ("waiting on you", "working", "idle", "ended"), and click a name to filter the list to it. Each message in such a thread leads with its session's name. #3163, closing #3108 by @zane668

      Comments

      • On your own messages and on questions. Select words in your own earlier message, or in any part of a question card (the prompt, the context, a choice), to comment on them. A comment never answers or settles a question, and a click on a choice still picks it. #3176
      • Files, voice and a kept draft. The comment card now takes any file, not only pictures, and has the reply box's microphone. A global comment's words and files are kept while you write, so a reload or another window opens the card with them. #2862 by @iurysza
      • Send waits for comments still saving. On a slow connection, a Send pressed while a comment was still saving went out without it, and the comment stayed behind as a draft. Send now waits, so one reply carries every comment. A review's verdict waits the same way. #3240

      Bitbucket pull requests on threads

      An agent can now attach a Bitbucket Cloud pull request to its thread by its URL. The row and the header show its state, checks and review, a Bitbucket PR link in a message gets a hover card, and a Board card moves to Done once its PR is merged. Bitbucket has no CLI, so the new config key bitbucketTokenCommand can read the token from a command, such as one that reads your Keychain, instead of from an environment variable or a plain-text file. The token stays in memory and never reaches the agents the Inbox starts. #3076 by @uvw, closing #3075 by @uvw

      More in the Inbox

      • Filter to Not seen. The list's Filter menu has a new first row, Not seen , that shows only the bold threads. #3226
      • Accept recommended steps aside while you type. On a phone it sat just above the keyboard's Done, and one stray tap replaced your answer. It now hides while you type in a question's fields, keeps your Other… words, and adds Undo to the card's status line. #3268
      • Your reply box is yours. A draft that arrives late, or from another device, no longer drops into a reply box you already opened. It waits beside the box as Restore draft. #3250
      • HTML files open in Interact. An HTML file beside a thread now opens with the pen off, so a click does what the page says. Turn Annotate on and it stays on as you move through the thread's files. ] and [ step between files from inside a page too. #3235
      • Arrow keys between attachments. With focus on one of a message's file tiles, the arrow keys move between that message's tiles. The O keycap now shows only when no file is open. #3237
      • The agent icon picker. A click on an agent's icon now opens the picker instead of stepping through faces. A picked set icon or picture gets its own page with Use this icon , so nothing changes until you press it, and the dialog stays centred. #3227
      • Hide Starred and Projects. Customize sidebar, and the sidebar's right-click menu, can now hide the Starred and Projects sections. #3252
      • Highlighting by touch. On an iPad, a selection made with a finger turned into a highlight mid-drag and lost iOS's handles. It now waits until the finger lifts, and the selection stays. #3142
      • Picture choices open on their set. A waiting question's picture opened from a file tile or the Artifacts view now opens on the question's set, at its choice, as the zoom button does. #3255
      • Pictures inside the choices. Agents are now told to put each option's picture inside its choice, so you can pick by picture, and the hint to resend a question as picture choices fires only when the pictures really are the options. #3179, #3167
      • Two choices that start the same. Two choices with the same words before the dash were read as one answer, and the agent heard the first one whichever you tapped. Each now keeps its whole text. #3260
      • Back on a phone moves an answered thread out of "Waiting on you", and an opened earlier reply now says "Delivered to ". #3258
      • Self-managed GitLab. A merge request attached by its short form (team/project!45) now opens on the project's own GitLab host instead of gitlab.com. #3225
      • A thread's stacked PRs show one under the other in the desktop PR card, instead of squeezed side by side. #3283

      Code review in the Inbox: off by default

      These show only with Code review turned on in Settings → Capabilities. Until 0.29 that switch shows only if you turned Code review on before.

      • The Pull requests board as a table. A desktop's board bar gets Grid | Table. The table has a row per PR (title, author, state, checks, risk, updated, size) under each repository, with sortable columns that keep a stack together. #3243
      • Select and bulk Merge. Select on the board picks PRs, a whole repository at once or a range with shift-click. Merge N merges the picked PRs that can merge now, one at a time, after a second click to confirm; it lists what stays and why, and reports each result. #3247, #3279
      • One PR opens its own page. Clicking a single open PR in Reviews, or its tile on the board, opens one page for it: the guided review, the diff, its review thread and Details. #2743
      • Open review thread. In a thread's PR list, each open PR has an "Open review thread" line that opens its review thread, or its page in Reviews if it has none yet. #3278
      • GitLab's whole-stack view now opens more lines with the expand arrows, and compares a layer from a fork instead of saying it can't. #3242

      Code review

      • Videos in PR descriptions play. A video attached to a GitHub PR description now plays in the review instead of showing as a link. Videos inside an HTML document or embed can also go full screen. #2952 by @mauricedesaxe, closing #2941 by @mauricedesaxe
      • GitLab's MR switcher and stacks. plannotator review <MR url> showed an empty switcher. It now lists the project's recent merge requests, finds the stack from them, and numbers them !12. #3248
      • Code colouring. .m files are coloured as Objective-C and .pl as Perl (they were Wolfram and Prolog). justfile, *.gradle, .zshrc and *.svg get colour, as do the fence labels patch, env, postgresql, mysql, gradle and hpp. A suggestion is coloured like the diff beside it. #3281
      • Collapse all files right away. A click on Collapse all files just after opening All changes was dropped while the code view loaded. It now applies once the view shows. #3253

      Additional Changes

      • Inbox storage on SQLite, still off unless you set it. inboxSqlite in config.json now has a proof on all six release builds, and fixes for moving the files on Windows and for a 30-second wait after a hard kill. Files stay the default for everyone. #3124
      • Relay. Mailbox creation has a strict per-address limit (per /64 for IPv6), and the relay refuses plain HTTP itself. The relay is deployed on its own. #3273, #3275
      • README and docs. The README describes the Inbox as the review layer for work with many agents and names personal assistants. #3266, #3251
      • Site deploy keeps hand-uploaded files under assets/hosted/. #3276
      • CI. The Test jobs can run on self-hosted runners, never for a fork's or a bot's pull request, and TypeScript is pinned at the root. #3259, #3267
      • Tests. No test can reach the hosted relay any more, and a guard keeps it so. Several flaky and stale tests are fixed. #3274, #3282, #3284, #3224, #3231, #3269, #3285, #3288
      • Release pipeline packs and publishes @plannotator/openclaw like the Cline plugin. #3289

      Install / Update

      macOS / Linux:

      curl -fsSL https://plannotator.ai/install.sh | bash
      

      Windows:

      irm https://plannotator.ai/install.ps1 | iex
      

      Claude Code Plugin: The install script above also updates the plugin when claude is on your PATH. Otherwise, in a terminal:

      claude plugin marketplace update plannotator
      claude plugin update plannotator@plannotator --scope user
      

      Then restart Claude Code. Inside Claude Code, run /plugin marketplace update plannotator, then open /plugin → Installed → plannotator → Update now.

      Pi:

      pi update npm:@plannotator/pi-extension
      

      OpenCode: Re-run the install script above. It also clears the OpenCode 2 plugin cache.

      What's Changed

      • Run the Claude Code mod in the VS Code extension's chat panel by @backnotprop in #3151
      • Show a Claude Code turn that ended in an API error in its thread by @backnotprop in #3184
      • Inbox: the folder box's never-start list keeps the folders' order by @backnotprop in #3224
      • Inbox: say "choices have no pictures" only when the pictures are the options by @backnotprop in #3167
      • Reply with a quote: say which message, or which words, a reply answers by @backnotprop in #3160
      • OpenClaw plugin: the Inbox in the owner's own OpenClaw chats, with replies coming back by @backnotprop in #3216
      • Inbox: comments on your own messages and on questions by @backnotprop in #3176
      • Inbox: tell agents to put each option's picture in its choice by @backnotprop in #3179
      • Inbox: wake a paired cloud agent by its webhook (step 1) by @backnotprop in #3138
      • Inbox: filter the list to threads you have not seen by @backnotprop in #3226
      • Hermes Agent plugin for the Inbox: tool, owner filter and native reply wake by @backnotprop in #3217
      • Notify when a launched session's turn ends in an error by @backnotprop in #3195
      • Name each session in a thread with several sessions by @backnotprop in #3163
      • Rename an agent from its sidebar row by @backnotprop in #3180
      • Inbox: a paired cloud agent gets its own agent door (step 2) by @backnotprop in #3178
      • Inbox: a paired cloud agent reaches the Inbox through the relay (step 4) by @backnotprop in #3187
      • Inbox: pair a cloud agent from Settings with one message to send it (step 5) by @backnotprop in #3197
      • Inbox: say when plannotator inbox turns on Hermes's wake switch, and how to undo it by @backnotprop in #3238
      • Inbox: Muse by Meta as a cloud agent by @backnotprop in #3212
      • Inbox: a star on a linked machine's thread lives on that machine by @backnotprop in #3234
      • e2e: the Mark read toast spec taps Undo where the toast rests, after the last Undo has ended by @backnotprop in #3231
      • Inbox: short GitLab refs open on the project's own GitLab host by @backnotprop in #3225
      • Inbox: fix starting agents on a linked machine (tip, asleep +, agent kind, Board projects) by @backnotprop in #3233
      • Inbox: an HTML file opens in Interact, and the pen keeps your choice through the thread by @backnotprop in #3235
      • Highlighting by touch waits until the selection is finished, and keeps it by @backnotprop in #3142
      • Inbox: tags for threads and Board cards (step 1: sidebar section, Add tag, the Board says Tag) by @backnotprop in #3228
      • Inbox: one PR opens its launchpad by @backnotprop in #2743
      • Inbox: pick Codex's model and effort when starting it by @backnotprop in #3177
      • Inbox: connect Muse Code by @backnotprop in #3209
      • Inbox: Bitbucket Cloud pull requests on threads, and a Bitbucket token read from a command by @uvw in #3076
      • Inbox: Customize sidebar can hide Starred and Projects by @backnotprop in #3252
      • Inbox: hide the O keycap while a file is open; arrow keys between a message's attachments by @backnotprop in #3237
      • Inbox storage: SQLite behind a setting; the compiled binary proven on six builds by @backnotprop in #3124
      • Fix two flaky tests: an early Collapse all click, and the import crash test by @backnotprop in #3253
      • fix(review): play GitHub attachment videos in PR descriptions by @mauricedesaxe in #2952
      • Inbox: start OpenCode sessions from New message, with model and variant by @backnotprop in #3186
      • OpenClaw and Hermes docs: version floor, why the tool starts off, what was tested by @backnotprop in #3251
      • Inbox: Hermes Agent's mark is its own Nous girl by @backnotprop in #3249
      • Inbox: Back takes an answered thread out of Waiting on you; an opened reply says Delivered by @backnotprop in #3258
      • Inbox: a click opens the agent icon picker, a picked icon gets a page with Use this icon, and the dialog sits centred by @backnotprop in #3227
      • Let a repo variable move the Test jobs to self-hosted runners by @backnotprop in #3259
      • Inbox Settings: Cloud agents under Agents, six kinds, one calm setup step by @backnotprop in #3223
      • Questions: keep two choices with the same words before the dash apart by @backnotprop in #3260
      • Give global comments the reply composer by @iurysza in #2862
      • Inbox: the Pull requests board as a table by @backnotprop in #3243
      • Cloud agents: How does this work? walk-through by @backnotprop in #3254
      • Close the gaps the self-hosted Test proof run found by @backnotprop in #3267
      • README: describe the Inbox as the review layer and name personal assistants by @backnotprop in #3266
      • Fix the browser smoke test: Agents link locator matched two links by @backnotprop in #3269
      • Inbox: open a waiting question's picture choice on its set from a tile or the Artifacts view by @backnotprop in #3255
      • Thread tag marks read in the same order while open and after a restart (flaky every-read test) by @backnotprop in #3272
      • Keep a linked machine's agent's face and name on that machine by @backnotprop in #3246
      • Inbox: Select mode on the Pull requests board by @backnotprop in #3247
      • Relay: a hard per-IP count on mailbox creation by @backnotprop in #3273
      • Site deploy: keep hand-uploaded files under assets/hosted/ by @backnotprop in #3276
      • Tests never contact the hosted relay by @backnotprop in #3274
      • Accept recommended steps aside while you type, keeps Other words, and can be undone by @backnotprop in #3268
      • Inbox: the person's Priority (PR 1 of 2) by @backnotprop in #3232
      • Inbox: a reply to a cloud agent with no wake address reads Saved, then Delivered by @backnotprop in #3270
      • Inbox: filter long model lists when starting an agent, as Pi's model selector does by @backnotprop in #3200
      • Inbox: Muse's mark is Meta's blue Muse squiggle by @backnotprop in #3262
      • Settings and OpenClaw README: why OpenClaw and Hermes start off; how to install OpenClaw before it is published by @backnotprop in #3263
      • Inbox priority spec: never the hosted relay by @backnotprop in #3284
      • relay: IPv6 /64 brake key, https-only Worker, live check (builds on #3273) by @backnotprop in #3275
      • Inbox: a Send waits for comments still saving, so one reply carries them all by @backnotprop in #3240
      • Tests never contact the hosted relay: unit tests' hand-built child envs by @backnotprop in #3282
      • Inbox: a thread's stacked PRs one under the other in the desktop PR card by @backnotprop in #3283
      • Colour .m, .pl, more file names and fence labels; colour suggestions like their diff by @backnotprop in #3281
      • Inbox: Stop and Delete on a sidebar agent's menu by @backnotprop in #3241
      • Inbox: bulk Merge on the Pull requests board by @backnotprop in #3279
      • feat(inbox): one-time dialog announcing personal agents by @backnotprop in #3280
      • Fix two stale browser tests: comment pictures input, Accept recommended after a note by @backnotprop in #3285
      • Inbox: "Open review thread" under each open PR in a thread's PR list by @backnotprop in #3278
      • Inbox: an agent can mark a thread Priority (send_message priority: true|false) by @backnotprop in #3277
      • Inbox To: a machine switch for linked machines by @backnotprop in #3257
      • Pages only spec: expect the window's picture policy as served (one hosted folder) by @backnotprop in #3288
      • Inbox: a draft that arrives after the reply box was opened waits behind Restore draft by @backnotprop in #3250
      • GitLab: MR switcher list and stack discovery in the review app by @backnotprop in #3248
      • Inbox: expand arrows and fork layers in GitLab's whole-stack view by @backnotprop in #3242
      • Inbox: a one-time Priority dialog in the line of one-time dialogs by @backnotprop in #3286
      • Release: pack and publish @plannotator/openclaw like @plannotator/cline by @backnotprop in #3289

      New Contributors

      Contributors

      @uvw wanted Bitbucket pull requests on Inbox threads without leaving the token in every program's environment, filed it as #3075, and built it in three layers: Bitbucket links read as pull request refs, a token read from a command and held only in memory, and the Inbox's rows, hover cards and Board marks. A clean-room test of the agent text, in the same PR, caught a smaller model storing a Bitbucket PR as a GitHub ref, and the wording was fixed.

      @mauricedesaxe reported that a video attached to a PR description showed as a bare link (#2941), then made it play in the review, with a fallback to the link whenever the video can't load.

      @iurysza gave global comments pictures, files, voice and a kept draft. That work became the one comment card the Inbox now uses everywhere.

      Thanks also to the people whose issues shaped this release:

      • @Arobotmaster asked for Reply to show which message, or which words, it answers (#3109)
      • @zane668 reported that a thread's header showed only a count of sessions, not their names (#3108)
      • @Qwenjin reported that Inbox replies did not wake Claude Code sessions in the VS Code extension (#3111)

      Full Changelog : v0.28.62...v0.28.63

    10. 🔗 smol-machines/smolvm smolvm v1.34.3 release

      What's Changed

      • docs: say that virtiofs DAX is off on arm64 hosts and SMOLVM_MOUNT_DAX does nothing there by @BinSquare in #2087
      • Add smolvm docker: one command starts a Docker engine in a managed machine and points docker at it by @BinSquare in #2089
      • Share the home directory with the smolvm docker machine at the same path by @BinSquare in #2090
      • Resolve host.docker.internal to the host from smolvm docker containers by @BinSquare in #2091
      • Fix a port race in the leader-exit test by @BinSquare in #2096
      • Remove smolvm docker by @BinSquare in #2095
      • Hand supplied credential values to a running embedded machine at once by @BinSquare in #2097
      • Pin libkrunfw with UDP kept inside a TSI guest, and test it by @BinSquare in #2099
      • Publish ports below 1024 on macOS, add IPv6 loopback to live-forwarded ports, and lift the 64-mapping cap by @BinSquare in #2092
      • Return idle guest memory to the host within two minutes and cap new machines at half the host's RAM by @BinSquare in #2094
      • Install a root-owned agent-rootfs when root runs install.sh by @rdslw in #2082
      • Announce a changed file to the guest once per change by @BinSquare in #2102
      • Answer guest DNS from a host cache that coalesces bursts and resends lost queries by @BinSquare in #2098
      • Keep every disk chain under the branch depth limit: fold restored checkpoint layers and frozen-source chains by @BinSquare in #2103
      • Exec sessions: commands the node owns, resumable after a dropped connection by @BinSquare in #2101
      • Let a guest hold tens of thousands of connections on virtio-net and free their host sockets promptly by @BinSquare in #2104
      • Scope the usage journal to the test's own thread by @BinSquare in #2106
      • Pin libkrun 526be460 and libkrunfw f290c62b, rebuilt for every platform by @BinSquare in #2109
      • Build the agent rootfs as non-root on hosts with user namespaces again by @BinSquare in #2107
      • Answer a start missing the mediated interceptor with 400, not 500 by @BinSquare in #2108
      • Run tests that need a released file lock free at once in their own process by @BinSquare in #2110
      • Pin libkrun 9df62257 and libkrunfw 7f4d4950, rebuilt for every platform by @BinSquare in #2113
      • Stop resetting virtio-net connections a server closes first by @BinSquare in #2118
      • Upgrade rusqlite to 0.41 for the patched bundled SQLite (RUSTSEC-2026-0459) by @BinSquare in #2128
      • Keep a host memory reserve VMs cannot take and charge branch children for growth by @BinSquare in #2127
      • Ask before stopping a machine on delete, so a refused or declined delete leaves it running by @connorburgess in #2131
      • Prepare SmolVM v1.34.1 for release by @BinSquare in #2135
      • Bring a soft open-file limit above kern.maxfilesperproc down to the cap on macOS, so the limit raise_nofile_limit reports is the one in force by @connorburgess in #2132
      • Leave no data directory behind when exec, status or stop name a machine that does not exist by @connorburgess in #2129
      • Warn when --block-private keeps a named host unreachable by @BinSquare in #2146
      • Register Rosetta itself as the x86_64 interpreter when the host answers its start-up ioctl by @BinSquare in #2148
      • Make a mounted host directory belong to the workload user so a non-root workload can write to it by @BinSquare in #2149
      • Record the image platform on the machine so a Rosetta machine can be created from an amd64 image by @BinSquare in #2147
      • Bump libkrun so a Rosetta machine runs amd64 programs directly and a macOS machine stops promptly by @BinSquare in #2150
      • Keep a cache disk's chain on its shared base when compaction shortens it by @BinSquare in #2145
      • Satisfy Rust 1.100's needless_bool lint in connect_in_progress on Windows by @BinSquare in #2154
      • Bound branch admission and reported capacity by the VM slice's memory limit, not just host free memory by @BinSquare in #2152
      • Stop throttling the VM slice and reclaim it from the pressure guard instead by @BinSquare in #2153
      • Release a paused branch child's VM lock so the memory pressure guard can resume it by @BinSquare in #2157

      New Contributors

      Full Changelog : v1.34.0...v1.34.3

    11. 🔗 Project Zero Policy and Disclosure: 2026 Edition rss

      Since 2021, Project Zero has followed a “90 + 30” vulnerability disclosure policy, allowing vendors up to 90 days to remediate a vulnerability plus an extra 30 days “soak time” for patch rollout. Our goal was to encourage faster patching and give vendors time to deliver patches to users. The advent of AI- assisted vulnerability discovery and exploitation has changed the threat landscape such that the vulnerability remediation timeline encouraged by our disclosure policy is clearly insufficient.

      LLMs have increased the speed at which attackers can find and exploit vulnerabilities, alongside the risk that multiple parties, including malicious ones, discover the same bug. A vulnerability reported today presents a much higher immediate risk to users than one reported last year. In this new environment, it is crucial that vendors move towards remediating vulnerabilities faster.

      LLMs have also decreased the time it takes for attackers to reverse engineer and exploit a vulnerability based on a patch, to the extent that zero patch- to-exploitation time is a reasonable, though imperfect, model of attacker behavior. Patch soak time is no longer meaningful in a world where attackers can almost immediately determine bug details from a patch, and can put users at risk by creating a false sense of secrecy. “Patch gap” is the time between a fix being released for a security vulnerability and the user installing the relevant update. It is equally crucial that vendors reduce patch gap, either by reducing patch rollout time or using other strategies to protect users while remediation is in progress.

      LLMs have also increased the volume of vulnerabilities that Project Zero reports. We are finding several vulnerabilities a week in targets where we once found a few vulnerabilities a year. Aspects of our policy that require vendor negotiation or agreement, including determining whether a bug is fixed and whether grace period applies, are quickly becoming unmanageable.

      Today, we are announcing a new vulnerability disclosure policy, created with the following goals in mind:

      • Encourage faster vulnerability remediation
      • Encourage vendors to reduce “patch gap”
      • Allow for the policy to be automated by both Project Zero and vendors

      Our new policy: “Full X”

      Vulnerabilities will be disclosed X days after they are reported to the vendor.

      Starting today, our policy is “Full 90”, i.e. vulnerabilities will be disclosed 90 days after they are reported to the vendor.

      On February 2, 2027, we will move to a “Full 60” policy where vulnerabilities are disclosed after 60 days.

      On January 3, 2028, we will move to a “Full 30” policy where vulnerabilities are disclosed after 30 days.

      We are also removing most ‘special cases’ from our disclosure policy, including grace period and variant policy. The only exceptions to our new policy are:

      • Vulnerabilities actively exploited in the wild -- ITW vulnerabilities will be handled according to Google’s application security vulnerability disclosure policy
      • Public vulnerabilities -- Project Zero may make details of a vulnerability public, at our discretion, if the details have already been made public by others
      • Vendor request -- We will make vulnerability details public if the vendor we reported it to requests it

      Why reduce remediation time gradually?

      Project Zero solicited feedback from the vendors we report the most vulnerabilities to as a part of developing this new policy. An overarching concern was that immediately changing the policy could harm users by making unfixed vulnerabilities available to attackers while vendors are in the process of improving their remediation processes and technology. While the benefits of delaying disclosure are declining due to the increased probability that attackers will discover a vulnerability during the embargo period, we still feel there are benefits in the short term.

      In addition, vendors mentioned two more subtle concerns. One was that an overly-aggressive disclosure policy would encourage fixing bugs reported under the new policy with more priority, even if they are less severe than other reported vulnerabilities. The other was that immediately enforcing a policy that some vendors aren’t equipped to meet might lead to a state where vendors accept that they cannot fix bugs within the deadline and don’t attempt to.

      We decided on a policy that encourages vendors to improve remediation time on a schedule that is challenging but realistic, with the hope that this will lead to vendors broadly improving their remediation processes and infrastructure in a way that eventually enables them to fix all reported vulnerabilities quickly.

      What about severity?

      While our analysis isn’t always perfect, Project Zero only reports vulnerabilities with substantial severity and demonstrated security impact in our tracker. That said, we don’t feel severity is an effective metric for making disclosure decisions, especially in the current environment. A vulnerability’s severity does not affect the likelihood that it will be discovered by attackers, only its impact on users.

      When vendors determine severity and use it to prioritize bug fixes, they are making decisions about what risks they are willing to expose their users to, and it is reasonable to accept the risk of low-severity bugs, like unexploitable null pointer crashes or minor info leaks in a lot of circumstances. But this doesn’t change the availability of these vulnerabilities to attackers, and we want our policy to reflect this reality.

      It’s also important to acknowledge that Project Zero holds itself to high standards with regards to the reproducibility, readability, reachability and reported security impact of the vulnerabilities we report. This policy assumes bugs reports are of this quality, and it is reasonable for vendors to treat low quality-bug reports differently.

      What about hardware?

      We encourage all vendors to consider how they would respond to imminent disclosure of a serious vulnerability, including non-patch strategies, as there is no guarantee that defenders will be the first to find a bug. That said, Project Zero has occasionally granted exceptions to our policy on rare occasions, including Spectre and Meltdown, and will continue to do so in the future.

      Are you really not going to check whether bugs are fixed?

      The question of whether a bug is fixed for the purposes of our policy has always been challenging and somewhat unresolved, particularly with regards to code that is not shipped directly to users and not publicly available. It is not unusual for Project Zero to communicate with vendors multiple times for each bug report to come to an agreement on whether a vulnerability is fixed. As more vendors experiment with vulnerability remediation strategies that are not patching like temporarily disabling code paths, we expect this to become even more complex.

      We still plan to track whether bugs are fixed and communicate if they are not, however, this will not be a decision point in our policy. This will enable us to share technical details of how users are protected without needing to make a binary judgement with consequences for the vendor.

    12. 🔗 smol-machines/smolvm smolvm v1.34.2 release

      What's Changed

      • docs: say that virtiofs DAX is off on arm64 hosts and SMOLVM_MOUNT_DAX does nothing there by @BinSquare in #2087
      • Add smolvm docker: one command starts a Docker engine in a managed machine and points docker at it by @BinSquare in #2089
      • Share the home directory with the smolvm docker machine at the same path by @BinSquare in #2090
      • Resolve host.docker.internal to the host from smolvm docker containers by @BinSquare in #2091
      • Fix a port race in the leader-exit test by @BinSquare in #2096
      • Remove smolvm docker by @BinSquare in #2095
      • Hand supplied credential values to a running embedded machine at once by @BinSquare in #2097
      • Pin libkrunfw with UDP kept inside a TSI guest, and test it by @BinSquare in #2099
      • Publish ports below 1024 on macOS, add IPv6 loopback to live-forwarded ports, and lift the 64-mapping cap by @BinSquare in #2092
      • Return idle guest memory to the host within two minutes and cap new machines at half the host's RAM by @BinSquare in #2094
      • Install a root-owned agent-rootfs when root runs install.sh by @rdslw in #2082
      • Announce a changed file to the guest once per change by @BinSquare in #2102
      • Answer guest DNS from a host cache that coalesces bursts and resends lost queries by @BinSquare in #2098
      • Keep every disk chain under the branch depth limit: fold restored checkpoint layers and frozen-source chains by @BinSquare in #2103
      • Exec sessions: commands the node owns, resumable after a dropped connection by @BinSquare in #2101
      • Let a guest hold tens of thousands of connections on virtio-net and free their host sockets promptly by @BinSquare in #2104
      • Scope the usage journal to the test's own thread by @BinSquare in #2106
      • Pin libkrun 526be460 and libkrunfw f290c62b, rebuilt for every platform by @BinSquare in #2109
      • Build the agent rootfs as non-root on hosts with user namespaces again by @BinSquare in #2107
      • Answer a start missing the mediated interceptor with 400, not 500 by @BinSquare in #2108
      • Run tests that need a released file lock free at once in their own process by @BinSquare in #2110
      • Pin libkrun 9df62257 and libkrunfw 7f4d4950, rebuilt for every platform by @BinSquare in #2113
      • Stop resetting virtio-net connections a server closes first by @BinSquare in #2118
      • Upgrade rusqlite to 0.41 for the patched bundled SQLite (RUSTSEC-2026-0459) by @BinSquare in #2128
      • Keep a host memory reserve VMs cannot take and charge branch children for growth by @BinSquare in #2127
      • Ask before stopping a machine on delete, so a refused or declined delete leaves it running by @connorburgess in #2131
      • Prepare SmolVM v1.34.1 for release by @BinSquare in #2135
      • Bring a soft open-file limit above kern.maxfilesperproc down to the cap on macOS, so the limit raise_nofile_limit reports is the one in force by @connorburgess in #2132
      • Leave no data directory behind when exec, status or stop name a machine that does not exist by @connorburgess in #2129
      • Warn when --block-private keeps a named host unreachable by @BinSquare in #2146
      • Register Rosetta itself as the x86_64 interpreter when the host answers its start-up ioctl by @BinSquare in #2148
      • Make a mounted host directory belong to the workload user so a non-root workload can write to it by @BinSquare in #2149
      • Record the image platform on the machine so a Rosetta machine can be created from an amd64 image by @BinSquare in #2147
      • Bump libkrun so a Rosetta machine runs amd64 programs directly and a macOS machine stops promptly by @BinSquare in #2150
      • Keep a cache disk's chain on its shared base when compaction shortens it by @BinSquare in #2145
      • Satisfy Rust 1.100's needless_bool lint in connect_in_progress on Windows by @BinSquare in #2154
      • Bound branch admission and reported capacity by the VM slice's memory limit, not just host free memory by @BinSquare in #2152
      • Stop throttling the VM slice and reclaim it from the pressure guard instead by @BinSquare in #2153

      New Contributors

      Full Changelog : v1.34.0...v1.34.2

    13. 🔗 Jeremy Fielding (YouTube) I Built An Automated High Speed Camera Robot rss

      This work was supported by the Alfred P. Sloan Foundation, enhancing public understanding of science and technology in the modern era, in partnership with IMI: watch what matters. https://www.theimi.co/ & https://sloan.org/programs/public-understanding

      Order custom parts Send Cut Send 👉 http://sendcutsend.com/jeremyfielding

      PBC Linear Rail Shown in the video 👉 https://pbclinear.com/blogs/blog/mt-series-belt-driven-linear-actuators-which-one-should-you-choose?utm_source=youtube&utm_medium=video&utm_campaign=jf&utm_term=mtb-actuators

      If you want to join my community of makers and Tinkers consider getting a YouTube membership 👉 https://www.youtube.com/@JeremyFieldingSr/join

      If you want to chip in a few bucks to support these projects and teaching videos, please visit my Patreon page or Buy Me a Coffee. 👉 https://www.patreon.com/jeremyfieldingsr 👉 https://www.buymeacoffee.com/jeremyfielding

      Social media, websites, and other channel

      Discord 👉https://discord.gg/F3XuyhNRPc Instagram https://www.instagram.com/jeremy_fielding/?hl=en Twitter 👉https://twitter.com/jeremy_fielding TikTok 👉https://www.tiktok.com/@jeremy_fielding0 LinkedIn 👉https://www.linkedin.com/in/jeremy-fielding-749b55250/ My websites 👉 https://www.jeremyfielding.com 👉https://www.fatherhoodengineered.com My other channel Fatherhood engineered channel 👉 https://www.youtube.com/channel/UC_jX1r7deAcCJ_fTtM9x8ZA

      Notes:

      Technical corrections

      Nothing yet

    14. 🔗 Filip Filmar TxHDL today: a Rust HDL, its parts, and what runs on it rss

      TxHDL is a hardware description language that is a Rust library, and a complete system ready to use. Its standard library holds the parts a system on chip needs: buses, a network on chip, memory, an MMU, Ethernet, video, debug and system control. On top of them run a RISC-V core that boots Linux, a GPU and a FireSim host link. Simulation, formal proof and the official RISC-V tests check all of it. This page describes TxHDL as it stands in November 2026. The earlier posts show it at the stages it passed through.

  4. November 12, 2026
    1. 🔗 IDA Plugin Updates IDA Plugin Updates on 2026-11-12 rss

      IDA Plugin Updates on 2026-11-12

      New Releases:

      Activity:

      • cfiscope
        • 660de8aa: v0.1.18
        • e8a44829: Review s154 claims 1-6: CHANGELOG tailqty folded into the Callers bul…
        • de046190: README/CHANGELOG claims nits (review s153 claims 5-9): count row "che…
        • 81946a65: Count row: per-type sensitivity (review s153 claims 3, rest): a count…
        • a38418ba: IDA layer: in_cfi_runtime decides by name only when the function has …
        • 93e455d0: -sites: a slow-path-only site with no linked call keeps the v0.1.17 …
        • 3e78b11e: Tests: the __cfi_check name test alone, in the CLI (cli.runtime_test)…
        • 7c4ec5b2: Count row: a check whose range read at the check gives no candidates …
        • 0a5c0603: Runtime check needs the pointer in x1 too (review s153 code 3): no li…
        • b28a14ca: CHANGELOG: same wording for the +1 test (inline range-check parser only)
        • d362da14: README count row: the +1 test changed only the inline range-check par…
        • a017a42f: Callers: a kCFI check always counts as a call site, as before (review…
        • d669e9e7: Count row: 1,718 of the 2,488 pairs start with a range run (the only …
        • 4fe912c2: Count row: say it also leaves out the 11 linked checks with no type i…
        • 97bbe0d1: -sites labels the CFI runtime's own checks 'CFI runtime check (guard…
        • e2aef4b3: CHANGELOG: the README changes of this release (install by URL, order,…
        • f1c845f0: README: Status and Install come before Try it (judge s152 finding 5; …
        • 01d54ebe: README 5.x: the command-line summary for the 5.15 kernel and why its …
        • 786886f1: README: what the plugin writes into IDA, before and after, from tools…
        • 4a8499b1: README: vfs_read block is the full real output (3 lines, was 2 and co…
      • hrtng
      • idasql
      • kflow
        • ee1b168e: README: Hex-Rays added kflow to the plugin index (plugin-repository#4…
        • 181f1cd5: README: kflow is not in the plugin index yet (requested in HexRaysSA/…
        • 8833967a: Never use IDA placeholder names (unk_/byte_) for keys and handlers: g…
        • 59f33d44: README: 73 IDA API checks (was 64)
        • adcc6bfa: v0.0.2: key data references in CHANGELOG/notes/README (judge s149 ite…
        • dca26133: drefs: stub indexes data refs by source (GKI 5.10 stub run 6 s, was >…
        • fcabbcf8: WIP (branch drefs, NOT in v0.0.2): user data refs static-key site -> …
        • bc72d49d: Judge s149 item 5 (GKI): keys inside arrays named after the nearest n…
        • 81c98a2f: v0.0.2 (2026-11-13)
        • 247dd60c: New action: kflow: List static-key sites (key, likely/unlikely, jump …
        • 7dfb4629: README: who it is for + before/after of three real demo sites at the …
        • fbc15b7f: Judge s149: static-key comment says when the site jumps (key off/on b…
        • 37d9ac2a: IDA: no-tables warning names vmlinux-to-elf for a raw Image/vmlinuz l…
        • e7ea6909: README Try it: your own /boot/vmlinuz through vmlinux-to-elf (checked…
        • c7818bcd: README/manifest: seventh kernel (Ubuntu 24.04 x86_64 6.8.0-149-generi…
        • 03cc6c95: README/manifest: sixth kernel (Ubuntu 24.04 arm64 6.8.0-149-generic v…
        • ede7ffd1: CLI: raw arm64 Image / gzip vmlinuz / x86 bzImage get a hint naming v…
        • ae171c01: CHANGELOG wording: in-place relocation (no peak-memory claim)
        • a4cf7604: Modules: relocations patched in place (one copy less in memory); outp…
        • 5aa7c627: ELF extended section numbering (e_shnum 0 / SHN_XINDEX / .symtab_shnd…
      • plugin-ida
        • 806a79a0: fix: ask for the instance name instead of the realm (#38)
    2. 🔗 anthropics/claude-code v2.1.323 release

      What's changed

      • Added Code Mode, an experimental opt-in in which Claude writes JavaScript to call its tools; see https://code.claude.com/docs/en/code-mode to turn it on, or to turn it off for an organization
      • Added engines["claude-code"] to plugin.json: plugins outside their stated Claude Code version range are not installed, updated or loaded, and install and update pick the newest version that fits
      • Added type checking of a plugin's TypeScript hooks module to claude plugin validate; each finding is a warning, and --strict fails on it
      • Added to claude plugin validate the $ nouns a mod's engine.create hook adds, withholds or replaces
      • Added support for CLAUDE_CODE_AUTO_MODE_MODEL in managed settings for Claude Desktop sessions on third-party providers (takes effect once Claude Desktop includes this version)
      • Added an options menu (stop, switch to usage credits, upgrade) when a model needs usage credits that are turned off or used up
      • Added a progress heartbeat every 30 seconds while hooks run long in claude -p and SDK sessions, so a host such as Claude Desktop won't end the turn as hung (once it includes this version)
      • Added .docx support to Artifact tool asset uploads
      • Added a /diff to close hint to the diff panel, and the keys that focus and close a panel to the ? shortcut guide
      • Added a start-up warning for Bash allow rules with a * in a variable's value, such as Bash(PORT=* npm run dev)
      • Added a warning when a plugin's language server can't start, naming the server and what to check
      • Added a one-time startup notice naming CLAUDE_CODE_PERFORCE_MODE when Perforce settings are found and the mode is off
      • Added CLAUDE_CODE_DISABLE_AGENT_PROGRESS_SUMMARIES (available since 2.1.318): set it to 1 to turn off subagent progress summaries and the requests that write them (#86879)
      • Added CLAUDE_CODE_RESUME_HINT_COMMAND, which a program that starts Claude Code can set to have the exit hint name its own resume command
      • Added unsetOptionCount to the claude plugin install --json result: how many userConfig options are not yet set
      • Added isPromptCovered to the props a mod's pane is drawn with, telling it when a dialog or a field above the prompt covers the prompt
      • Fixed running /compact again, or after a command such as /context, summarizing away a message that Claude had not answered yet
      • Fixed a resumed session joining your next message to an old interrupted message that was not resumed
      • Fixed a memory spike at the next prompt after Claude changed a very large file
      • Fixed a setting saved in a running session undoing a hand edit made to settings.json moments earlier; a settings file you delete during a session now stays deleted
      • Fixed claude plugin commands and claude mcp list signing you out of a Console profile when they ended while the token was being renewed
      • Fixed Edit and Bash running out of memory on certain /proc files, and Edit hanging or running out of memory on devices and named pipes
      • Fixed Claude Code failing to start, or to clear stored credentials at sign-out, when saving its configuration file failed with "Out of memory"
      • Fixed requests sent without streaming failing on errors that streamed requests recover from, such as a rejected image, thinking block or beta header
      • Fixed ExitWorktree, the worktree exit dialog and /resume leaving the session in the wrong folder when the folder the shell was in before entering the worktree had been deleted
      • Fixed accents and other combining marks sometimes landing left of the text, leaving stale copies on screen, or silently disappearing when text wraps
      • Fixed the last key of a key chord, such as Enter in ctrl+x enter, acting on a dialog's text field when the chord's own action isn't available there
      • Fixed ps processes piling up when the process listing Claude Code runs before stopping a command takes too long
      • Fixed subagent transcripts and large tool results being saved apart from the session's transcript after entering a worktree created by a WorktreeCreate hook or belonging to a nested repository
      • Fixed a session on a named Anthropic profile moving to another sign-in when /fork, the Left arrow or --bg continued it in the background; reopen any session that was open during the update
      • Fixed a background session sending a conversation under another sign-in when its named Anthropic profile is missing, changed or overridden; it now stops and says so
      • Fixed a session on an API key, auth token or workload identity from its shell (not a setup token) moving to another sign-in in the background; it now stops and says so
      • Fixed MCP tool calls ending in the sign-in server's error, such as TOKEN_EXPIRED, instead of asking you to sign in again
      • Fixed an expired claude.ai login showing "Credit balance too low" when a saved Console key or ant auth login profile without credit was used instead
      • Fixed a session on a named Anthropic profile being handed to an older background service that could not keep its sign-in; it now says to restart the service
      • Fixed a background session's sign-in leaving the previous account's login or other credentials in place; it now clears them for every session on the computer, and a refused sign-in can leave no login
      • Fixed background sessions moving between a profile and the stored login when an update restarted them
      • Fixed sessions opened before a sign-in keeping signed-out feature flags after the sign-in
      • Fixed sessions that kept failing after a Claude apps gateway sign-in expired: once you sign in again with /login in another terminal, they carry on at the next message
      • Fixed the billing notice naming your ant auth login organization when a custom X-Api-Key header is set
      • macOS: Fixed "Not logged in · Please run /login" coming back right after a successful /login or a token refresh when the keychain was slow to answer
      • Fixed turns failing in Claude Desktop when an organization's gateway answers an expired token with 403: Claude Code now asks Desktop for a fresh token and retries
      • Fixed the error shown when Amazon Bedrock refuses your account a model: it no longer says to refresh your AWS credentials, it says to enable the model
      • Fixed the awsAuthRefresh or gcpAuthRefresh command sometimes running twice for one request when three or more sessions needed a fresh sign-in at once
      • Fixed the claude -p warning about an ended claude.ai login to say that claude auth logout also removes saved MCP server logins and plugin secrets
      • Fixed Bash permission prompts offering "don't ask again" for commands that write to sensitive paths such as .git or .claude, where the saved rule did not stop the next prompt
      • Fixed a case where some lsof commands ran without a permission prompt
      • Fixed Bash commands that write a file with `cat > file <
    3. 🔗 @HexRaysSA@infosec.exchange Marco ([@raptor](https://infosec.exchange/@raptor)) is back on the Hex-Rays mastodon

      Marco (@raptor) is back on the Hex-Rays blog 🔮

      His vulnerability research tools (rhabdomancer, haruspex and augur) have reached v1 and fully support IDA 9.5. New in this release: type definitions extraction, many fixes, and augur now runs 19x faster.

      👉🏽 Read the full post: https://hex-rays.com/blog/divining-vulnerabilities- contributor-program

      Marco is also a Hex-Rays Plugin Contest winner, and the contest is open again.
      Built something cool with IDA? Submit it before Nov 30: https://hex- rays.com/plugin-contest

      He’s also a member of our Contributor Program, which supports people who build IDA plugins, tools and content with a free IDA license. Apply here: https://hex-rays.com/contributor-program

    4. 🔗 HexRaysSA/plugin-repository commits sync repo: +12 releases, -1 release rss
      sync repo: +12 releases, -1 release
      
      ## New releases
      - [IDASQL](https://github.com/allthingsida/idasql): 0.0.20
      - [btf2ida](https://github.com/nightshift-labs-ai/btf2ida): 0.1.19, 0.1.18
      - [cfiscope](https://github.com/nightshift-labs-ai/cfiscope): 0.1.17, 0.1.16
      - [hrtng](https://github.com/kasperskylab/hrtng): 3.9.118
      - [memlens](https://github.com/nightshift-labs-ai/memlens): 0.3.24, 0.3.23, 0.3.22, 0.3.21, 0.3.20
      - [threatray](https://github.com/threatray/plugin-ida): 3.0.4
      
      ## Changes
      - [IDASQL](https://github.com/allthingsida/idasql):
        - removed version(s): 0.0.11
      
    5. 🔗 Hex-Rays Blog Divining vulnerabilities: powered by the Hex-Rays Contributor Program rss

      Divining vulnerabilities: powered by the Hex-Rays Contributor
Program

      "Real hackers were so multi-lingual they often knew more platforms than they had pants."
      -- Dave Aitel

      About the guest author

      Marco Ivaldi (raptor) is a seasoned security researcher and tech leader with over 25 years of experience in offensive security. He is the technical director and co-founder of HN Security, a boutique firm specializing in tailored offensive security services. A prolific exploit writer, Marco is also a Phrack author and a core developer of the OSSTMM, the open methodology for security testing. He has been recognized as one of Microsoft's Most Valuable Security Researchers and was selected to compete in its Zero Day Quest. He is a member of the Hex-Rays Contributor Program. His career began in the '90s, when he co-founded Linux&C, the first Italian magazine dedicated to Linux and open source.

      TL;DR

      In a hurry? I got you. Here's what's new in my vulnerability divination 🔮 suite:

      • Last May, I joined the Hex-Rays Contributor Program, which is supporting the development of my idalib-based tools with a free IDA license.
      • rhabdomancer, haruspex, and augur have reached v1 , with full IDA 9.5 compatibility , new features such as type definitions extraction , substantial performance optimizations , and a number of important fixes.
      • I've contributed type extraction , decompiler and IDA configuration , and Linux/Windows AArch64 support to the idalib Rust bindings 🦀, with more pull requests on the way.
      • I've benchmarked the old and new releases against real-world targets, and the results speak for themselves.

      As usual, you can get the latest releases from Hex-Rays community plugins, crates.io, or GitHub.

      A headless IDA-powered binary audit pipeline

      First, a quick recap of my previous work, for those who missed the earlier episodes.

      I've been doing binary vulnerability research against closed-source targets since the '90s, both professionally and as a hobby. Over the past couple of years, I've built a pipeline around IDA Pro's GUI-free automation capabilities to audit binaries at scale , across architectures. I described its building blocks in my previous article on this topic.

      Still waiting for the "automation takes over" part to kick in (https://xkcd.com/1319/)

      The centerpiece is haruspex, an idalib- rs based headless plugin that extracts IDA's decompiler pseudocode into per-function flat files. It's fast enough to process a 19 MB MIPS binary encompassing 7436 functions in less than 20 seconds (including the initial analysis stage) on my MacBook Air M3. Not bad!

      That output feeds a layered static analysis stack. My custom Semgrep C/C++ ruleset and weggli patterns treat the pseudocode as source code, flagging candidate vulnerability hotspots automatically. Interesting hits then go to LLM agents for deeper triage , before I move to manual static and dynamic confirmation. Its siblings rhabdomancer and augur complete my vulnerability divination suite, by marking calls to potentially insecure API functions in the IDB and extracting strings and related pseudocode as needed, respectively.

      Why IDA? Because of decompiler quality, performance, and integration capabilities , the latter courtesy of the award-winning idalib Rust bindings. Across x86, ARM, MIPS, and other architectures, the output is clean enough for pattern- matching tools to work on it reliably. Just last July, I batch-decompiled 280 binaries in less than 14 minutes, and Semgrep parsed more than 98% of the resulting pseudocode lines. Meanwhile, the idalib headless API lets Rust drive the whole analysis without a GUI in the loop.

      This pipeline finds real bugs , such as the Zyxel local privilege escalation I covered last year. And I've spoken with other researchers who use a similar setup to hunt for vulnerabilities at scale, so I guess I'm not the only haruspex in town. 🐑

      A license to divine

      Last May, I joined the Hex-Rays Contributor Program. In a nutshell, the program aims to recognize and support people who design, build, and maintain IDA plugins, applications, and content , idalib-based tools explicitly included. Contributors may get a free IDA license that includes all decompilers and dedicated support from the Hex-Rays team.

      For me, this means that I can keep developing my tools against the latest IDA releases on macOS, Windows, and Linux, without worrying about how to keep my license current. In return, contributors must keep their projects compatible with the latest IDA SDK within four months of each release. They must also maintain good installation, quality, and documentation standards, support their users, and provide product feedback to Hex-Rays. Sounds like a fair deal to me, especially since I was already doing most of these things anyway. 🤷

      The first tangible result of this collaboration is a major release of my cross-platform vulnerability divination suite, which is now fully compatible with IDA 9.5. If you're building something cool on top of IDA, I encourage you to apply as well!

      The new haruspex running on Windows 11

      Giving back to idalib-rs

      As customary, while working on my tools I kept contributing new features to the idalib Rust bindings, which in the meantime moved to their own home under the idalib-rs GitHub organization. My most relevant contributions since my last article are listed below:

      • Global and function-level type extraction (released in idalib-rs v0.10.0, alongside IDA 9.4 compatibility). This is the feature that powers the new .h files generated by haruspex and augur. It allows idalib-rs based tools to dump the type definitions that IDA has recovered or that you've applied to the IDB, both globally and for the types used by a specific decompiled function. Ever tried to make sense of a pile of pseudocode full of *(_DWORD *)(a1 + 0x48) without the corresponding struct definition? Well, me too 😵‍💫
      • Support for modifying the Hex-Rays decompiler configuration (released in idalib-rs v0.10.1). This is what allows haruspex and augur to turn off IDA 9.4's new argument name hints programmatically, without asking you to edit any configuration files by hand. This way, static analysis tools such as Semgrep can directly parse the generated pseudocode.
      • Support for modifying the IDA configuration (released in idalib-rs v0.11.1). It's the counterpart of the previous feature for IDA's kernel settings. This is what allows haruspex and augur to make IDA 9.5's verbatim names valid C identifiers again in the pseudocode (more on this below).
      • Support for Linux and Windows AArch64 targets and cross-compilation (released in idalib-rs v0.11.0, alongside IDA 9.5 compatibility). I've tested this patch with my tools on Linux/AArch64. Windows/AArch64 is also supported, but it's still untested (volunteers welcome).

      You can find the full history in the official changelog of the project. As always, I encourage you to contribute to idalib-rs!

      A sneak peek of rhabdomancer doing its magic on Linux/AArch64

      One year of divination

      A lot has happened since my last article on IDA 9.2. Back then, my tools were at v0.7.x. One year, a few hundred commits, and more than a dozen releases later, rhabdomancer, haruspex, and augur have all reached v1. Yes, I'm finally confident enough to call them stable. 🎉

      The full details are in each project's changelog (rhabdomancer, haruspex, augur). Here are the highlights.

      IDA 9.5 compatibility

      All three tools now officially support IDA 9.5 , via the v0.11.x releases of the idalib Rust bindings. Along the way, they also tracked IDA 9.3, 9.3sp1, 9.3sp2, 9.4, and 9.4sp1, with a compatibility matrix in each README.md that maps every IDA build to the latest compatible release of each tool.

      IDA 9.4 brought a couple of decompiler changes that directly affected my pipeline:

      • The Hex-Rays decompiler now generates argument name hints. They're great for humans reading pseudocode in the GUI, but they break pattern-matching tools such as Semgrep and weggli. Therefore, haruspex and augur disable them before decompiling, and a regression test makes sure they never sneak back into the extracted pseudocode.
      • The decompiler can now recover additional strings that the initial auto-analysis misses. To take full advantage of this, augur now decompiles all functions upfront , before it walks the string list.

      IDA 9.5 kept me busy as well. It no longer garbles names by default, so names that aren't valid C identifiers are kept verbatim, and the decompiler wraps them in backticks. That's more faithful to the binary, but once again it breaks Semgrep and weggli. I dealt with it by restoring IDA 9.4's behavior in haruspex and augur, via a new IDA configuration API I contributed to idalib-rs. In rhabdomancer, I handled the breaking change by improving the function name matching logic.

      New features

      • Type definitions extraction in haruspex (and augur), as requested by a user. Global and per-function type definitions are now dumped to .h header files alongside the pseudocode. This means that structs, enums, and typedefs recovered by IDA are available to downstream tools and LLM agents, which makes their analysis more accurate.
      • A stable public API for haruspex as a library. The new decompile function tells apart functions that can't be decompiled from errors that affect all functions, decompile_to_file now returns a DumpedFunction with the paths of the files it wrote, and DumpedFunction::copy_to copies the output elsewhere without decompiling again. augur is built entirely on top of this API.
      • A much smarter rhabdomancer. Calls through ELF .plt stubs are traced back to their callers, and calls in library code recognized by IDA (e.g., via FLIRT signatures) are labeled (lib). Function names are now matched regardless of platform decorations (e.g., the ARM64EC #memcpy kept by IDA 9.5, Apple's stat$INODE64, or 32-bit _WinExec@8), glibc aliases (e.g., __libc_system, __isoc23_sscanf), Universal CRT wrappers (e.g., __o_malloc), and IDA's numeric suffixes (e.g., memset_0).
      • A richer known bad API function list in rhabdomancer, with dozens of new entries, such as wordexp, chroot, syscall, ioctl, the *spawn*, CreateProcess, and LoadLibrary families, and many more. The default configuration is now embedded in the binary, and you can point the RHABDOMANCER_CONFIG environment variable to your own customized copy.
      • Elapsed time reporting in every tool, which came in handy for the benchmarks below.

      Performance optimizations

      • augur now decompiles each function only once , reusing its output files for any further strings it references. This is by far the biggest performance improvement of the bunch, especially on large binaries where a handful of functions reference hundreds of strings.
      • augur also stops retrying functions that already failed to decompile, and avoids repeated calls to the IDA strings API.
      • rhabdomancer uses a single lookup table for known bad functions, caches .plt segment address ranges to avoid repeated FFI round trips, and fetches each function's name only once.

      Important fixes

      • rhabdomancer no longer misses calls in PE binaries (import stubs with numeric suffixes and Universal CRT wrappers) and in statically linked binaries (glibc aliases). The same goes for ARM64EC binaries analyzed with IDA 9.5, macOS binaries (Apple's variant suffixes), and 32-bit Windows binaries (stdcall names). Turns out these were hiding in plain sight 🙈
      • rhabdomancer runs are now idempotent , even when a call site already has a bookmark of its own, and instructions that merely fall through into a bad function (e.g., alignment padding) are no longer marked as call locations.
      • XREF traversal in rhabdomancer and augur is now iterative , to avoid potential stack overflows with large XREF chains, and rhabdomancer's is hardened against cyclic .plt references in crafted or unusual binaries.
      • Function names that come from the analyzed binary are now escaped before they are printed to the terminal, and file names built from the binary's names and strings go through an allowlist. After all, these tools are meant to be pointed at potentially hostile binaries.

      Under the hood, I also enabled clippy restriction lints , added semver- checks to CI to enforce semantic versioning, pinned GitHub Actions to hashes, and wrote (with Claude's help) a lot of new unit, integration, and regression tests , with dedicated test binaries for edge cases such as binaries without functions, binaries without a decompiler, and functions too big to decompile.

      Benchmarks, or it didn't happen

      Talk is cheap, so I've put my claims to the test. I ran the old v0.9.3 releases on IDA 9.3 and the new v1.2.0 releases on IDA 9.5 against the same set of real-world targets, on the same MacBook Air M3. Times include IDA's initial auto-analysis, and each run started from a clean state, without any pre-existing IDB.

      Tool | Target | Arch | Size | v0.9.3 on IDA 9.3 | v1.2.0 on IDA 9.5 | Speedup
      ---|---|---|---|---|---|---
      rhabdomancer | 280 ELF binaries (batch) | AArch64 | 14 MB | 356 secs | 342 secs | +4%
      haruspex | 280 ELF binaries (batch) | AArch64 | 14 MB | 827 secs | 744 secs | +11%
      augur | 36 ELF binaries (batch) | AArch64 | 2.2 MB | 39.3 mins | 124 secs | +1802%

      The last figure in the table is especially remarkable: a staggering +1802% speedup means that augur is now 19x faster , thanks to single-pass decompilation.

      Finally, Semgrep 1.183.0 parses about 99.1% of lines in the pseudocode generated by haruspex v1.2.0, which marks a slight increase compared to the 98.3% measured with the older haruspex/IDA version.

      A word of caution: these numbers measure the combined effect of my code changes and of the IDA upgrade, so they don't tell you which side deserves the credit. Also note that augur now decompiles every function upfront to recover more strings, which costs some time on binaries with few string references, but pays off handsomely on large ones. Your mileage may vary, so please run your own benchmarks and let me know how they fare!

      __

      Looking ahead

      The v1 milestone is by no means the end of the road. My TODO list is as long as ever, and the most ambitious goals on my roadmap are tighter LLM integration , to make the triage of static analysis findings even smoother, and a LibAFL fuzzing stage downstream of static analysis, to confirm candidate vulnerabilities automatically.

      Meanwhile, you can download my updated tools from Hex-Rays community plugins, crates.io, or GitHub. Take them for a spin against your favorite targets, open issues, and submit pull requests!

      Acknowledgments

      I'd like to thank Hex-Rays for welcoming me into their Contributor Program and for inviting me to write on their blog once again. It's been an honor.

      As always, huge thanks to idalib-rs's maintainers , and especially to Sam L. Thomas (@xorpse), for reviewing my pull requests and for keeping this awesome project alive and kicking. ✊

    6. 🔗 The Pragmatic Engineer The Pulse: Details of incident.io’s AI spend rss

      Hi, this is Gergely with a bonus, free issue of the Pragmatic Engineer Newsletter. In every issue, I cover Big Tech and startups through the lens of senior engineers and engineering leaders. Today, we cover one out of five topics from the past issue of The Pulse . Full subscribers received the article below two weeks ago. If you 've been forwarded this email, you can subscribe here .

      incident.io (note: I'm an investor) is a software reliability platform founded in 2021, a year before ChatGPT, that's obsessed with measuring everything. In that spirit, the company has shared details about AI spending, changes to PR frequency, and the ROI at the company from using AI. Thank you to Lawrence Jones and the incident.io team for sharing the data!

      They have come up with the concept of the "effort point" as a way to analyse AI spend. One effort point is a medium-sized pull request written by a human or generated by an agent. The measurement is far from perfect, but it is one step more granular than looking at lines of code, and lets them compare the complexity of AI-generated PRs with those written by human devs in the past. Here's what has changed in the last two years:

      altWhat changed in two years for various metrics at incident.io

      Pull request stats

      At a glance:

      altChanges in numbers of PRs over two years

      AI agents started to generate production code in June 2025, which was around the same time as the first agent-generated got pushed at incident.io. The company has used AI-assisted IDEs since the beginning, such as GitHub Copilot and Cursor.

      altAgent usage exploded in June, when Claude Agents launched

      In June this year, a few things happened in quick succession, the incident.io team told me:

      • Claude Agents launched, making it easier to coordinate several agents running at once
      • Worktree tooling improved a lot, making it easier for agents to do parallel work on the same codebase with worktrees
      • Also around this time, more engineers realized that they should be running multiple agent sessions using different worktrees, rather than driving just one session at once.

      Today, nearly 80% of PRs that ship to production include code generated by an agent:

      altPercentage of all PRs with parts of the code generated by agents

      More:

      • 2.7x headcount growth in product engineering (engineers who ship to production numbered 18 in 2024, and 50 today)
      • 3.4x PR requests shipped to production in September compared to a year ago
      • 3.6x increase in PRs with no human reviewer shipped to prod (12% to 43%)
      • 4.8x increase in the size of PRs (from 22 to 111 lines)
      • 6x "effort points" shipped**** to prod: "effort points" awarded by an AI model estimating the complexity of a PR, and ranking it from XS to XL.
      • 80% decrease in human comments per "effort point"
      • 60% decrease in incidents per 1,000 pull requests

      Stats on release frequency:

      • 47% rise in releases/eng/day when taking headcount into account: an average of 2.8 releases/day/eng, up from 1.9 releases/day/eng in 2024
      • Oct 2026: 140 releases/day to production with 50 engineers. In Oct 2024, the figures were 35 releases/day to prod with 18 engineers

      AI spend

      This year, spending on AI tools is on track to be around $ 1.6M at the company - which is a lot! We're talking around $2,700 per engineer each month, which puts the reliability startup among the big spenders of companies mentioned in this article. Based on that, they've attempted to calculate a rudimentary ROI for the spend. At present, incident.io sees AI tools as mostly positive.

      AI spending peaked this summer and has been decreasing since. In July, the company spent more than $300K on AI (an annual projection of $3.6M, had it continued). Here's the allocation:

      altAllocation of spend on AI at incident.io , mostly on Claude

      Opus 5.5 brought a massive cost reduction. Before it, the company was spending around $4,500/engineer/month, mostly on Opus 5. But now, with the 5.5 version, the cost is down to circa $1,600. Here's the impact of Opus 5.5 on monthly spend:

      altOpus 5.5 is resulting in less than half the previous monthly cost on AI, per engineer

      Also, the adoption of Opus 5.5 has been rapid:

      altShare of models used by engineers inside incident.io

      Cost per "effort point" also peaked over the summer. The nice thing about the "effort point" metric is that it makes it possible to compare the cost of generating a PR to how much it cost a year ago, when the company started using AI agents. Here's the change:

      altCost of generating a medium-sized PR peaked in July-August with Opus 5 and Fable

      Infrastructure teams spend more tokens on the same "effort point." A fascinating detail from incident.io comes from separating the cost of an "effort point." The infrastructure team stands out, spending ~5x more on a medium-sized PR than almost every other team:

      altThe cost of an "effort point" (generating a medium-sized PR) varies based on team

      But why the big difference? Lawrence Jones, an engineer at incident.io, explains:

      "This is a great example of why it's hard to use a single target for cost per PR that applies universally.

      Our AI team, for example, does work that can be very token-intensive such as iterating on evals. Infrastructure teams might use Claude to explore production environments or do lots of analysis or run benchmarks etc which don't lead to PRs, so their cost per-PR looks higher.

      Different types of work will simply have different cost profiles."

      Measuring ROI

      Today, average spend is down at ~$1,600/engineer/month, of which around 80% is on Claude, with 20% going to Cursor. The big question: has AI made engineers more productive? Unfortunately, measuring engineering productivity in only a single dimension is fraught with hazard, but a combination of insights could give a sense of where things are headed. These are imperfect measurements with their own biases, but are still interesting.

      The number of PRs shipped per engineer weekly tracks with tenure. This is a very interesting finding from incident.io. Compared to two years ago:

      • The median engineer shipped ~10% more PRs (10.1 PRs in Oct 2024 with no AI; 10.7 PRs per week in Oct 2026 with AI). An eye-catchingly small change!
      • The mean engineer shipped ~30% more PRs (11.1 PRs in Oct 2024 vs 14.8 PRs in Oct 2026)
      • Tenured engineers shipped ~70% more PRs (11.1 PRs in Oct 2024 vs 19 in Oct 2026)

      New engineers are told to hold off on using AI for a month after they join. The AI SRE startup collected feedback from new engineers and found that new joiners using a lot of AI right after onboarding ended up performing worse in the medium/long term.

      What incident.io found is that it's worth ignoring expectations of shipping velocity during the first month. Instead, new devs learn how to navigate the codebase. This AI-abstinent approach skews the above numbers.

      Harder to quantify: shipping faster & incidents

      Compared to pre-AI, how important is it for PRs to be shipped faster to production? A benefit of AI agents and AI reviews is faster feedback than waiting on someone to review a PR. Here's how quickly the median PR makes it to production at the reliability startup:

      altFast turnaround times both for review readiness, and for deployments

      Let's take an average day - a Tuesday last month - when 185 changes were shipped to production, 75 of which without human review:

      altPRs shipping to production with & without human review at incident.io

      There are fewer incidents per change, but more overall. It would be quite the omission to not bring up reliability when talking about a reliability startup! This is both good and bad news: there's fewer incidents per PR, but more overall due to the existence of more PRs:

      altFew incidents per PR, but more overall incidents

      The good news is that the rate of incidents is lower than expected, given the PR volume:

      altTaking last year's PR "defect rate", there should have been more production incidents

      The team looked into why incidents occurred, and found that most outages were because of incorrect code that could have been caught in review. The team took steps to address this:

      • Improved the codebase for AI use
      • Started leaning more on Cursor's Bugbot, added stricter rules, and saw the tool start to give better feedback and catch more code-related bugs in review
      • Newer models produced better code.

      Today, most incidents are no longer due to faulty code, but because there's information absent about the production environment. The bad news is that if this continues and PR volume grows, then the number of incidents will also rise unless the team avoids outages related to production behavior. They are working on building feedback loops where agents can observe and learn from production.

      altCategorizing production incidents by root cause at incident.io

      I found these data points educational, especially looking at how the "cost per medium-sized PR" does (and probably should!) vary based on the complexity of work that goes into it.Thanks a lot to the incident.io team for sharing such detailed data!


      Read the full issue of The Pulse from two weeks ago. The latest The Pulse**** covers:

      1. What can we learn from the Railway hack? Cloud platform**** Railway has published an extremely detailed postmortem about their recent hack in which the attacker likely used 'abliterated' AI models (those with no safeguards). Railway has hardened its systems as a result. Also, a competitor tried to benefit from the incident by getting Railway's customers to migrate - but then got hacked itself in the exact same way.
      2. Native mobile and frontend jobs are disappearing. New data shows native mobile and frontend job listings are down by 50% at leading startups and Big Tech, while forward deployed engineer (FDE) listings have quadrupled in the same timeframe.
      3. How an extremely efficient engineering team works: Superlogical. Mitchell Hashimoto's new startup is "AI-native" and cares deeply about craft and developer tools. They skip code reviews and commit to main thanks to deep trust between team members.
      4. Industry pulse. Jensen Huang no longer the CEO of NVIIDA, OpenAI buys Pierre Computer, Carta starts selling a coding harness, Meta buys and shuts down Conductor (a T3Code competitor), and Binance hacked with $6.3B stolen after devs were tricked into downloading packages and attending fake interviews.
    7. 🔗 r/Harrogate How much do those workspaces cost? rss

      I need somewhere a couple of afternoons a week where I can camp with my laptop in private - the library won’t work for me - how much do the co-working spots mentioned in other posts actually cost?

      submitted by /u/Slipstream57
      [link] [comments]

    8. 🔗 exe.dev Backup and Restore on exe.dev rss

      A common question we see on our Discord and in support is how to back up exe.dev VMs. We've built a backup command (and its good friend, the restore command) to facilitate just that.

      We decided that the best place to store your backups is in your own S3 bucket. To set up backups, you first set up a WIF integration, granting us access to a bucket in S3. Our documentation walks you through the steps, and I'll let you in on a secret: your coding agent is the best way to follow that documentation. Then run the backup command, and voilà.

      Animation: a backup snapshots the VM's disk, cuts it into 1 MB chunks,
hashes each chunk, and uploads, compressed, only the chunks the S3 bucket
doesn't already have under chunks/. It then writes an index from each disk
offset to its chunk under indexes/. When the VM later writes, the next backup
hashes the changed chunks and uploads only the missing ones, so backups are
incremental.

      Our backup format is the same as Casync / Desync. In short, we take your disk, split it into 1 MB chunks, and hash those. We upload compressed chunks identified by hash to S3 (ignoring the ones that haven't changed), and upload an index of those chunks to represent the backup. A VM with a slow-changing disk might only need to update a few chunks at every backup iteration, which makes these backups incremental. Furthermore, because the format is open source, you can use existing tools to reconstruct your disk elsewhere, or even mount it in a lazy FUSE file system.

      Documentation at exe.dev/docs/vm-backups. Give it a try!

    9. 🔗 tintinweb/pi-subagents v0.24.0 release

      What changes for existing users

      • Nested spawns are refused once 10 nested subagents are running (#427). Set maxConcurrentNested to 0 to restore unbounded nesting.
      • FleetView rows show each agent's own tokens , the selection is marked ❯, and ● marks the view in front (#446).

      New

      • maxConcurrentNested caps running nested subagents (default 10) (#427).
      • FleetView lists nested subagents under their parent , with mouse support in fullscreen mode (#446).
      • showModel names the model and thinking level on fleet rows (#447).

      QA

      • 2590 tests passed (95 scripted e2e); live e2e against a real model: 92 passed.

      Full details in CHANGELOG.md.

    10. 🔗 backnotprop/plannotator v0.28.62 release

      Follow @plannotator on X for updates

      Missed recent releases? Release | Highlights
      ---|---
      v0.28.61 | Updates now update the Claude Code plugin too, an agent's chosen face shows on every icon of it, filter the Inbox list by pull request state, Modern dark shows section bands and the Reply button, one conversation no longer shows as two agents
      v0.28.60 | Click a word to highlight it, a one-time Themes dialog, Settings → Rows rebuilt, tell your agent how you want your rows, starred threads as pills above the list, a pill for new messages out of view, a half-circle face picker with ten Glass colours, a new phone sidebar and reply box
      v0.28.59 | A quieter Agents section in the sidebar, machine names only when agents run on more than one machine, agent icons that are always gently alive and lean toward your pointer
      v0.28.58 | Start Codex from New message, an Agents section in the sidebar, start an agent in a folder on any drive, play audio attachments and comment at a moment, Claude Code's Plannotator tools work on Windows
      v0.28.57 | Pin artifacts, and see every artifact on one page, filter the list by project, date or agent, a thread shows its pull requests and their state, choose what the sidebar shows, and in what order, Ask AI starts from Side in the selection bar
      v0.28.56 | Questions can show trade-offs and a prototype to try, a thread with many big pictures no longer crashes the tab, Escape closes New message and keeps your draft, read threads stop being bold and keep their place, agent messages that name no thread start a new one
      v0.28.55 | Floating reply drafts, now a setting under Experimental, open questions sit next to Reply again, a comment box that keeps unsent comments as Drafts, choose how your list looks: Minimal, Balanced or Detailed, update an older linked machine from this Inbox
      v0.28.53 | Start an agent in a new folder, or from a git URL, "+" on each project row starts a session there, a reaction tray, a thread's Links, Settings → Activity, New message offers the open thread's files, Bro mode: agents write to you in plain words
      v0.28.52 | Start agents from the Inbox, on by default, a new reply box, Ask AI for everyone, Insights in Settings → Decision data, Plannotator reloads itself after an update
      v0.28.51 | Starred threads, a note when an agent's session has ended, "Back from snooze", Ask about a past decision, expand arrows in guided reviews
      v0.28.50 | A faster, lighter Inbox, session names across the Inbox, initiatives on the Board, earlier comments on a file, global comments on Guided Reviews
      v0.28.49 | A checklist for each thread, a pill that shows who gets your reply, a calmer full screen, Inbox replies in T3 Code, --title for review and annotate

      What's New in v0.28.62

      TL;DR

      • Fixed: Agents started from the Inbox now work on Windows
      • New: Pick a model and effort when you start an agent
      • New: Rules for your agents, written in your own words
      • New: Post a thread's decisions on its pull request
      • Changed: The Inbox loads faster on a slow connection

      0.28.62 is a large release. Starting agents from the Inbox now works on Windows, you can choose a model and effort for a new session, and you can give your agents your own rules. It has 57 PRs. Five come from external contributors, and three of those are first contributions: welcome @ilyaZar, @solatis and @tommyent.

      Windows

      Agents started from the Inbox work on Windows

      On Windows, a session started from New message got an empty environment: no PATH, no user profile and no sign-in variables. Claude Code then showed "Not logged in" and never connected to the Inbox, even when the Inbox itself said Claude Code was signed in. Sessions now start with the Inbox's own environment, less Plannotator's own variables. Respawns get it too, and the settings file the Inbox writes for each launch carries PATH again. macOS and Linux are unchanged. #3154

      New message's folder box now reads the paths people type and paste on Windows. C:\Users\me\code, c:/users/me/code, ~\code and a file:///C:/... link all work, and a pasted path keeps its backslashes. A folder outside your home folder, a system folder such as C:\Windows, or a folder Windows hides (such as AppData) now gets a plain note that says why it isn't offered, where before each one said "That isn't a full path." Folders on other drives are still not offered. #3156

      No more console windows flashing up

      A console window opened by itself every few minutes while the Inbox was running. It came from the gh and glab lookups behind pull request marks and hover cards. Every command Plannotator runs in the background now starts hidden: in the Inbox, plan review, code review, annotate, Pi, and the OpenCode, T3 Code and Amp plugins. Things that are meant to open a window, such as your browser, your editor or Explorer, still do. #3143

      Paths with an apostrophe in Claude Code's slash commands

      In Claude Code on Windows, a path with an apostrophe, such as C:\Users\me\O'Brien\plan.md, lost the apostrophe when passed to /plannotator-annotate or /plannotator-review, and the rest of the line ran into one word. On Windows a single quote is now an ordinary character, and only double quotes group words with spaces, as on a Windows command line. Git Bash and PowerShell get the same words. macOS and Linux are unchanged. #3161

      Starting agents from the Inbox

      Pick a model and effort

      When New message starts a new session, the To line now ends with a quiet "Default model" button. If you leave it alone, nothing changes. Open it to pick a Model and an Effort for Claude Code or Pi; the lists come from the installed CLI's own help. Your choice is remembered per machine and agent, reused by Try again and respawn, and shown in the thread header (for example "· opus · high"). Settings → Agents → Claude Code has Model and Effort defaults.

      Settings → Agents also has a Claude settings file. Its keys are merged into the settings the Inbox writes for each session it starts, so a Claude Code profile that points at a company gateway also applies to sessions started from the Inbox. A missing or invalid file is reported on the run line by its path only, and its contents are never logged or sent anywhere. #3097, closing #3064 by @rqres

      A plugin turned on only in the project counts

      If you turned on Plannotator's plugin only in a project's .claude/settings.json or .claude/settings.local.json, the Inbox refused to start Claude Code there and said the plugin was off. It now reads the settings for the folder it starts in, in Claude Code's own order: managed settings, then the project's local file, then its shared file, then your user settings. A project can turn the plugin on for itself, or off. #3144, closing #3065 by @Arobotmaster

      The first agent on a new Inbox

      On a new Inbox with no projects yet, New message said "No agent is running" and offered nothing to start, so the first agent could never be started from the Inbox, on any platform. It now offers to start a new session in a new scratch folder. #3159

      Plannotator Inbox

      Rules for your agents

      Settings → Prompts has a new box at the top, Rules for your agents. Write how you want agents to use the Inbox in your own words, such as "Only message me when you are blocked or done" or "Keep messages under 10 lines", and choose who they are for: all agents, Claude Code, Pi or OpenCode. Plannotator's own reminder stays. Your rules come after it, with one line that tells the agent they come from you and win over the lines above. Agents get them at session start and again after a compaction. With no rules, agents get exactly the same text as before.

      The long built-in reminder is now folded into one row, "Reminder text · Default", and replacing it works as before. A one-time "Set the rules" dialog points to the new box, once you have used the Inbox for two days and have ten threads. In config.json the rules are prompts.inbox.rules, or prompts.inbox.runtimes.<agent>.rules for one agent. #3145, toward #2194 by @zane668

      Your Guided Review instructions, everywhere

      Settings → Prompts also has a Guided reviews row for your standing instructions, the text added to every guided review, whether it starts from the Inbox, the review page or VS Code. Before, the Inbox could not show or edit them. #3134

      A guide an agent writes through the Inbox now follows those instructions too. Before, only guides started from the review page or VS Code did. #2956 by @solatis

      Export a thread's decisions, or post them on its pull request

      A thread's ⋯ menu has Export decisions. It downloads every question in the thread with its state, as Markdown that reads well on GitHub or as one HTML file that makes no outside requests. Decisions come first, then the questions still open, skipped, set aside and so on. Session ids and machine names are left out, your home folder becomes ~, and local network addresses become "(local link)". #3080

      From the same menu, or the Post decisions button on a pull request in the thread's PR card, one click puts the thread's decisions on that GitHub pull request or GitLab merge request. By default they go into the description as one section at the end; posting again replaces only that section and leaves the rest of the description as it was. You can choose a comment instead, or a short section with the full version in a comment. When you can't edit the description, it posts a comment and says so. Agents and scripts can do the same with plannotator inbox export-decisions --thread <id>. #3083

      Your own agent icons

      The agent face picker has two new places. Your own… takes a picture you pick, drop or paste, and shows it as that agent's icon everywhere its face shows. An animated GIF moves in the sidebar only. #3087

      Sets offers four built-in icon sets you can search by name or number: Tiny Creatures, game-icons.net, Dungeon Crawl tiles and Noto Emoji 3D. More sets can be downloaded from the picker; your own Inbox fetches a set once and keeps it, so it works offline after that. #3090

      Under your own picture, Animate it opens New message with the request and the picture filled in. Send it to an agent, and the animated result replaces the icon in every window. Use the original puts your picture back. #3105

      The icon dialogs also got ten fixes from a phone, touch and slow-link pass. A tap now picks a face on an iPhone or iPad, and a still photo over 512 KB is shrunk instead of refused. #3122

      Rows show the latest message, and which session

      The grey line under a thread row now shows the thread's latest message instead of its subject, like a mail app: the newest unread agent message, your own reply as "You: …", "Asked: …" for a question and "You answered: …" for your answer. In Settings → Rows, "Subject preview" is now "Preview", and a saved choice carries over. #3006

      In a project with two or more live sessions, each row now shows the session's name in place of the project name, so you can tell them apart. Projects with one session look as before. #3095

      Mark read asks before setting questions aside

      Mark read can close a thread's open questions and action items and tell the agent not to wait on them. It did that without a word. Now the Inbox asks first, but only when something would be set aside; otherwise Mark read stays instant. This covers every way to mark read, including E and a project's Mark all as read. "Don't show this again" can be turned back on in Settings → General → When an agent asks you. #3079

      More in the Inbox

      • Click an agent to see its threads. A click on an agent in the sidebar's Agents section now filters the list to that agent's threads. Click it again to clear. Before, it opened the last thread the agent wrote in. #3081
      • Mark read and Snooze moved into the thread's ⋯ menu, to give the title more room. E and H work as before. #3126
      • Pictures on comments. Every comment box in the Inbox has the picture button Annotate has. The picture goes to the agent as an attachment of the reply that carries the comment. #3148
      • "Other" takes several lines. The "Other…" field under a question's choices grows with what you type, and the agent receives the lines as lines. #3078
      • Show a thread in the open window. plannotator inbox --open <thread> moves the Inbox window you used last on this computer to that thread, the same as a click on its row, or opens a new one. #3130, closing #2506 by @timmo001
      • Install the Inbox as an app with a sharp icon. The Inbox now has a web app manifest, so installing it from Chrome or Safari gives a sharp Dock icon in your favicon style. The unread count shows on the app's icon too, where the system allows it. #3056 by @tommyent, #3147
      • Tailscale publishes again by itself. With "Reach the Inbox over Tailscale" on, a publish that failed because Tailscale was off or still starting is now tried again until Tailscale is back, and Settings updates without a reload. #3128

      Your phone and other devices

      Fewer limits between your own devices

      Plannotator treated your phone, iPad and other computers on your tailnet as strangers in many places. Now, over Tailscale, they get what the computer gets: you can pair a phone, link or unlink a Mac, change tailnet settings, see first-run prompts and What's new, see project pictures, and delete a launched agent from a phone-width page. Open in, Open in Terminal and Choose in Finder still stay on the computer, since they would open on its screen.

      Several silent cuts are gone too. Long answers, long "Other" answers and long notes in a question arrive whole, a question keeps every choice, and agent names are no longer cut at 40 characters. Guided Review instructions can now be 12,000 characters (were 2,000) and the custom Inbox reminder 9,000 (was about 4,100), with a count near the limit. Ask AI reads up to 300,000 characters of a plan, document or diff.

      Over SSH, a request that comes through your own tunnel or editor port forward now gets what a local session gets, such as Ask this session and link hover cards. PLANNOTATOR_REMOTE=1 still means remote mode for every request. #3121

      On a phone or tablet

      • "Transcribing…" stays in the reply box. While dictation transcribed, the "Transcribing…" marker could run past the box's edge and under the ⌄ button. It now stays inside the box, on the next line when needed. #3208
      • Hold a row for its menu. On a touch screen, holding a thread row opens the same menu a right-click opens on a desktop: as a bottom sheet on a phone, under the row on an iPad. A tap still opens the thread at once. #3131
      • One tap opens a row on an iPad. On an iPad, opening a thread from the list, or a project or starred thread from the sidebar, could take two taps. One tap now does it, and the sidebar's ⋯ and + buttons always show on a touch screen. #3129, #3137
      • The pull requests sheet. On a phone, a thread's pull request list was drawn as a narrow strip with cut titles. It is now a proper bottom sheet, like the thread's ⋯ sheet, and a tablet gets the card under the button. #3127

      A faster Inbox on a slow connection

      Compression and caching used to apply only over Tailscale. They now cover every way you reach the Inbox, including a plain proxy or an SSH tunnel. On a test link with 300 ms delay and 1 Mbit/s, the first load went from 71 s to 25 s and a reload from 20 s to under 1.5 s. #3088

      The window also asks the server less. Typed answers save after a short pause instead of on every key, threads you click past are not loaded, and Mark read, Archive and Star show at once (on the same test link, Mark read went from 742 ms to 10 ms). When two windows answer the same question, the later click wins with no error. #3089

      Code review

      Call tree

      Code review's Call flow tab has a new Call tree view, and it opens there by default: the change's calls drawn as one indented tree, with red and green bands for removed and added calls. Hunks that have a tree get a "Call tree" entry that opens it, rooted at the function around the hunk. In the tree, Enter opens the line and C adds a comment. Paths and Raw are one click away. #3086

      Pictures and videos in a pull request open in Artifacts

      In a PR description and the Comments tab, a click on a picture now opens the Artifacts panel at that picture, large, where you can comment on a point. Before, nothing happened. A video GitHub saved as a bare link opens in Artifacts too, plays through the server (private repositories too) and takes comments at a moment; Cmd/Ctrl-click still opens GitHub. Screenshots written as &lt;img&gt; tags inside a description's table now show as pictures instead of raw text. #3149

      The server that fetches those pictures and videos now follows redirects only to GitHub's own hosts, sends your GitHub sign-in only to the first request's host, and serves only picture and video types. Nothing should change in what you see. #3166

      GitLab: request changes, and approve your own MR

      Request changes on a GitLab merge request now sets your reviewer state to "Requested changes", not only the comments. It also stays available on your own MR, since GitLab accepts it there. #2723 by @bendrucker

      Approve was greyed out on your own GitLab merge request. GitLab accepts an author's approval unless the project forbids it, so Approve now stays on and GitLab decides. When GitLab refuses, the review says so and why it may have refused, and you can still comment or request changes. GitHub is unchanged. #3132

      Plan review and annotate

      • Ctrl+C copies the highlight after the comment box opens. Once the comment box opened on a highlight, Ctrl+C / Cmd+C copied nothing. It now copies the highlighted text, in plan review, annotate, HTML documents, the version diff and code review's line comments. Text you select yourself, in the comment box or the page, still copies as usual. #2623 by @BenNewman100
      • Mod+Shift+Enter opens the note composer. In plan review and annotate, Mod+Shift+Enter opens "Send with a note" (or "Send a note") directly; Mod+Enter in it sends as before. #2913 by @ilyaZar, closing #2912 by @ilyaZar
      • A broken Mermaid diagram stays in its message. A failed render could leave a "Syntax error in text" graphic at the bottom of the page and make it scroll. Nothing is left outside the message now, and a diagram type that failed to load is tried once more before showing its source with a Reload line. This covers the Inbox, plan review, annotate, code review and the VS Code Guides. #3091

      Installing and updating

      A broken download now continues where it stopped instead of starting the large binary again from zero, on macOS, Linux and Windows. The checksum check is unchanged. The Claude Code plugin step also gets 10 minutes instead of Claude Code's own 2-minute limit, which slow links hit with "Git clone timed out after 120s". #3096

      After an update, when open Claude Code sessions will not pick up the new plugin by themselves, the installer shows one system notification and opens a short help page with the steps. It shows only while a Claude Code session is open and never on a fresh install, in CI or over SSH. PLANNOTATOR_INSTALL_NOTIFY=0 turns it off. #3074, #3073

      Inbox storage on SQLite: early, and off by default

      This release lays the ground for keeping the Inbox's records in SQLite. It changes nothing about where anyone's Inbox data lives: every Inbox, new installs included, keeps using its files as before. #3106, #3107

      There is an early, optional switch to try it: inboxSqlite in config.json, or PLANNOTATOR_INBOX_SQLITE=1. It is off unless you set it, and has no Settings row. When on, the next start moves your records into inbox.db after checking that it reads the same, and keeps your original files as a dated backup. Turn it off again and the next start moves everything back into files, including messages written in between. #3114

      Fixes

      • A stuckgh or glab no longer freezes the Inbox. Hovering a pull request mark could show "Loading…" forever, and after a few hovers no thread would open until the tab was closed. Lookups now end at their time limit, and the hover answers with what the Inbox already knows. #3082
      • A list read with nothing new no longer redraws the whole window. #3104

      Additional Changes

      • Smaller repository download. The site's demo videos are served from the site's storage instead of being kept in the repository. #3092
      • Site pictures for posted decisions. #3084, #3085
      • Test upkeep. #3094, #3125, #3164

      Install / Update

      macOS / Linux:

      curl -fsSL https://plannotator.ai/install.sh | bash
      

      Windows:

      irm https://plannotator.ai/install.ps1 | iex
      

      Claude Code Plugin: The install script above also updates the plugin when claude is on your PATH. Otherwise, in a terminal:

      claude plugin marketplace update plannotator
      claude plugin update plannotator@plannotator --scope user
      

      Then restart Claude Code. Inside Claude Code, run /plugin marketplace update plannotator, then open /plugin → Installed → plannotator → Update now.

      Pi:

      pi update npm:@plannotator/pi-extension
      

      OpenCode: Re-run the install script above. It also clears the OpenCode 2 plugin cache.

      What's Changed

      • Site: a help page for a Claude Code plugin left behind by an update by @backnotprop in #3073
      • Installers: tell the person when open Claude Code sessions need a manual step by @backnotprop in #3074
      • Site: host the Decisions banner pictures by @backnotprop in #3084
      • Site: Decisions banner sits flush left, shorter, no background by @backnotprop in #3085
      • Inbox: export a thread's decisions as Markdown or HTML by @backnotprop in #3080
      • Let a question's Other answer take several lines by @backnotprop in #3078
      • Inbox: clicking a sidebar agent filters the list to its threads by @backnotprop in #3081
      • Inbox: warn before Mark read sets open questions aside by @backnotprop in #3079
      • Code review: Call tree (phase 1) by @backnotprop in #3086
      • e2e: the thread menu's expected items include Export decisions by @backnotprop in #3094
      • Marketing videos are served from the site's storage, not kept in the repository by @backnotprop in #3092
      • Inbox: a thread row's grey line shows its latest message by @backnotprop in #3006
      • fix(inbox): a list read with nothing new sets no state, so it never draws by @backnotprop in #3104
      • Inbox: post a thread's decisions on its pull request by @backnotprop in #3083
      • Inbox: your own picture as an agent's icon by @backnotprop in #3087
      • Inbox: icon sets for agent icons by @backnotprop in #3090
      • Inbox: Animate it, for your own agent icon by @backnotprop in #3105
      • Inbox: a stuck gh or glab can no longer freeze the window by @backnotprop in #3082
      • Inbox e2e: measured times for the untimed specs by @backnotprop in #3125
      • Updates resume a broken download, and the plugin step gets more time by @backnotprop in #3096
      • feat(review): request changes on GitLab MRs by @bendrucker in #2723
      • feat: Mod+Shift+Enter opens the send-with-a-note composer by @ilyaZar in #2913
      • Diagrams: a failed Mermaid render never leaks outside its message by @backnotprop in #3091
      • Let authors approve their own GitLab MR; show GitLab's refusal by @backnotprop in #3132
      • Inbox: show a thread in the open window (plannotator inbox --open <thread>) by @backnotprop in #3130
      • Inbox icon dialogs: ten fixes from the phone, touch and slow-link sweep by @backnotprop in #3122
      • Feature: apply guide standing instructions in get_guide_brief by @solatis in #2956
      • Inbox: a web app manifest with the studio's large icons, and the count on the Dock icon by @tommyent in #3056
      • Inbox: Mark read and Snooze move into the thread header's ⋯ menu by @backnotprop in #3126
      • Inbox Settings → Prompts: Guided reviews row by @backnotprop in #3134
      • fix(ui): Ctrl+C copies the highlighted text once the comment box is open by @BenNewman100 in #2623
      • Inbox: on a touch screen the first tap on a row opens it by @backnotprop in #3129 (landed with #3137)
      • Inbox: on a touch screen the sidebar's ⋯ and + buttons always show by @backnotprop in #3137
      • Inbox: publish over Tailscale by itself once Tailscale is back by @backnotprop in #3128
      • Inbox: on a phone the thread's pull requests open as a bottom sheet like the ⋯ sheet by @backnotprop in #3127
      • Settings: the Favicon row mentions the installed app by @backnotprop in #3147
      • Windows: start agents with the Inbox's own environment by @backnotprop in #3154
      • Inbox: on a touch screen, hold a thread row for its menu by @backnotprop in #3131
      • Inbox e2e: the iPhone scroll-return case presses the tile where it is by @backnotprop in #3164
      • Keep a Windows path's apostrophe in slash-command arguments by @backnotprop in #3161
      • Review: the PR picture and video proxy follows only GitHub's own redirects by @backnotprop in #3166
      • Inbox launch: a plugin enabled in the project's settings counts as on by @backnotprop in #3144
      • Remove defensive limits: the same Inbox on every device, and no silent cuts by @backnotprop in #3121
      • Inbox: pictures on comments, sent with the reply as attachments by @backnotprop in #3148
      • Inbox: compress and cache on every listener by @backnotprop in #3088
      • Windows: the Inbox's background commands no longer flash a console window by @backnotprop in #3143
      • Let a fresh Inbox start its first agent in a scratch folder by @backnotprop in #3159
      • Inbox: pick a model and effort when starting an agent, and a Claude settings file by @backnotprop in #3097
      • Inbox: Rules for your agents (#2194) by @backnotprop in #3145
      • Code review: pictures and videos in PR text open in Artifacts by @backnotprop in #3149
      • Inbox: list rows tell sessions in one folder apart by @backnotprop in #3095
      • Read Windows folder paths in New message's folder box by @backnotprop in #3156
      • Inbox window on a slow link: fewer reads, writes show at once by @backnotprop in #3089
      • Inbox store: one interface in front of the record log by @backnotprop in #3106
      • Inbox: keep "Transcribing…" inside the reply box on a phone by @backnotprop in #3208
      • Inbox store: a SQLite log behind the interface (not used by anyone yet) by @backnotprop in #3107
      • Inbox store: import to SQLite, export back, behind an off switch by @backnotprop in #3114

      New Contributors

      Contributors

      @BenNewman100 kept running into a copy that did nothing: select words, open the comment box, press Ctrl+C, get nothing. He fixed it in all five places it happened, with tests for each and a check on Windows 11.

      @bendrucker made Request changes on GitLab set the reviewer state GitLab shows, and tested it against a real merge request.

      @ilyaZar asked for a shortcut to send with a note in #2912, then built it.

      @solatis wanted to shape the guided reviews agents write through the Inbox, found that the Inbox ignored the standing instructions file, and fixed it.

      @tommyent gave the installed Inbox app a manifest, sharp icons and an unread count on its Dock icon, and checked it in Chrome and Safari.

      Thanks also to the people whose issues shaped this release:

      • @rqres asked to change how the Inbox starts Claude Code sessions (#3064), which led to the Claude settings file
      • @Arobotmaster reported that a plugin turned on only in a project was refused (#3065)
      • @timmo001 asked for a way to show a thread in an open Inbox window (#2506)
      • @zane668 asked to customize how agents use the Inbox and write to it (#2194)

      Full Changelog : v0.28.61...v0.28.62

    11. 🔗 HexRaysSA/plugin-repository commits sync repo: +1 plugin, +1 release rss
      sync repo: +1 plugin, +1 release
      
      ## New plugins
      - [kflow](https://github.com/nightshift-labs-ai/kflow) (0.0.1)
      
    12. 🔗 MetaBrainz Picard 3.0.5 released rss

      Picard 3.0.5 is a maintenance release for the recently released Picard 3.0 with fixes for reported issues. This release fixes issues with saving the order of cover art providers, manually set artwork for multiple files not being saved, a potential crash when logging out of your MusicBrainz account and many more.

      The latest release is available for download on the Picard download page.

      The detailed changes for this maintenance release are below. For an overview of the new features since Picard 2.13 please see our detailed release announcement for Picard 3.0.

      Thanks a lot to everyone who gave feedback and reported issues.

      What’s new?

      Bugfixes

      • [PICARD-3511] - Saving embedded artwork fails when setting the artwork for multiple selected files
      • [PICARD-3525] - Restore Defaults uses wrong values for plugins
      • [PICARD-3538] - Unable to change cover art provider order
      • [PICARD-3541] - Views stay suspended and the pending files count never reaches zero when a file is removed while it is still loading
      • [PICARD-3542] - "Automatically cluster all new files" can skip clustering depending on which file finishes loading last
      • [PICARD-3543] - CD lookup reads a wrong drive name when the CD lookup devices setting has spaces or empty items
      • [PICARD-3550] - After filtering the "Unmatched Files" entry shows up for all loaded releases
      • [PICARD-3554] - Hovering over the closing % of a variable shows an empty tooltip
      • [PICARD-3556] - CLI: command alias "plugin uninstall" not working
      • [PICARD-3559] - Crash on logout error if option window was closed

      Improvements

      • [PICARD-3553] - Allow setting PICARD_FORCE_FUSION=0 to opt-out of using Qt's Fusion style

      Download

      Picard 3.0.5 is available for download from the download page of the Picard website. For Windows 10 and 11 users installing from the Microsoft Store and Linux users using the Snap Store will receive the update soon. The Linux Flatpak package is maintained separately and will also be updated soon.

      Please note that unfortunately we can no longer provide updates for the ARM64 versions of the Linux Snap package. See this forum post for more information. If you are currently using the Linux Snap on an ARM64 system consider installing the Flatpak or a native package, if available.

      Picard is free software and the source code is available on GitHub.

      Get in touch

      Please use the MetaBrainz community forums and the ticket system to give feedback, suggest new features or report bugs.

      Acknowledgements

      Code contributions by Laurent Monin, Philipp Wolfer and Shubham Prasad.

    13. 🔗 HexRaysSA/plugin-repository commits add nightshift-labs-ai/kflow to known repositories rss
      add nightshift-labs-ai/kflow to known repositories
      
    14. 🔗 Console.dev newsletter Sponsor: WarpBuild rss

      WarpBuild - Linux, macOS and Windows on x86-64 and ARM64. Unlimited macOS concurrency. Get $50 in free credits.

      Visit WarpBuild

    15. 🔗 Console.dev newsletter TextJS rss

      Full-stack console apps.

      What we like: Uses the browser console to render full applications. Supports React 19 and Flexbox (using Wasm). Flexibility over styling, routing, data handlers, tables, charts. Custom inputs and key mapping. Can also render to a terminal.

      What we dislike: Whilst this is fun, the project doesn’t really explain why you’d want to do this!

    16. 🔗 Console.dev newsletter AWS Emulator rss

      Official AWS API Emulator.

      What we like: Local, single (Rust) binary that emulates AWS APIs. Can easily point the CLI and SDKs at it. Supports being embedded for isolated test instances. Includes agent skills and can run as a server.

      What we dislike: Doesn’t have full fidelity with all AWS APIs and it’s not easy to find out, but you can ask your AI agent to check for you.

    17. 🔗 Console.dev newsletter Sponsor: ARCA rss

      Get paid for your AI coding

      Visit ARCA

    18. 🔗 Console.dev newsletter Sponsor: Token Custodian rss

      AI, governed

      Visit Token Custodian

    19. 🔗 Rust Blog Announcing Rust 1.100.0 rss

      The Rust team is happy to announce a new version of Rust, 1.100.0. Rust is a programming language empowering everyone to build reliable and efficient software.

      If you have a previous version of Rust installed via rustup, you can get 1.100.0 with:

      $ rustup update stable
      

      If you don't have it already, you can get rustup from the appropriate page on our website, and check out the detailed release notes for 1.100.0.

      If you'd like to help us out by testing future releases, you might consider updating locally to use the beta channel (rustup default beta) or the nightly channel (rustup default nightly). Please report any bugs you might come across!

      What's in 1.100.0 stable

      Never type

      After 10 years and 5 failed stabilization attempts, thenever type is finally stable! This also completes the project goal for this work.

      The never type, spelled ! in code, is the canonical uninhabited type. It represents the type of diverging computations – computations which never resolve to any value – where any code that follows is unreachable. Expressions that terminate control flow, such as return, break, and std::process::exit, also have the type !.

      Since having a value of the never type is impossible, Rust permits a never-to- any coercion, allowing to turn ! into any other type (this is what distinguishes it from any other uninhabited types). This can be used, for example, to not return a value from one of the branches of a match or an if:

      fn mrrrow(option: Option<u32>) {
          let value = match option {
              // `x` has type `u32`
              Some(x) => x,
              // `return` has type `!`, which is then coerced to `u32`,
              // allowing the `match` to pass type checking.
              None => return,
          };
          // ...
      }
      

      While the never type could already be used and observed this way, and even named in the return type of functions (-> !), this release allows naming the never type anywhere:

      fn infallible_unwrap<T>(res: Result<T, !>) -> T {
          // ^^ writing `Result<_, !>` was not allowed before
          let Ok(v) = res;
          v
      }
      

      Additionally this release changes Infallible to be an alias to the never type. That makes all old APIs that used Infallible be compatible with using !. This was the plan ever since the introduction of Infallible and is one of the reasons why the never type stabilization was so hard (waffle gave a talk about some of the troubles of the stabilization).

      Unfortunately, to allow changing Infallible, we had to introduce a breaking change. This release changes the "never type fallback" from () to ! in editions before 2024 (i.e. 2015, 2018, and 2021), similarly to what has already been done in edition 2024. This should largely be unnoticeable, but can affect code in some rare cases (for example when ignoring a result of a function returning a generic parameter). Note that this change might also make the compiler detect more code as unreachable.

      We tried to minimize the impact of this breaking change as much as possible, by providing future compatibility warnings far in advance and releasing fixes to public crates that have been broken by this. If a dependency is failing due to issues with the never type, consider updating it, as a fix might have already been released for it.

      Allocator API

      This release brings about the stabilization of the core parts of allocator_api, enabling library authors to define custom allocators that can be used together with certain standard library types - currently Vec and Box. These are enabled through the newly-stabilized Allocator trait.

      This is the foundation of the Allocators 1.0 project goal. A lot remains to be done still, including expanding the API surface usable with custom allocators and stabilizing their use on more collections and pointer types; with the core trait and design out of the way though, expect to see more being stabilized soon!

      DropGuard: run a closure on every exit path

      The Drop trait in Rust makes it possible to run code when a variable goes out of scope, regardless of whether we return, ?, or panic. Drop being a part of types means that in Rust you never have to close a socket.

      Implementing Drop can however feel a little inconvenient when all you want is to run some code unconditionally when a function exits. This is why we’re introducing core::mem::DropGuard: a new helper type that runs a closure when dropped.

      DropGuard takes two arguments: a variable and a closure. It implements Deref and DerefMut so you can keep working with the variable as normal. But when dropped it runs the closure and consumes the variable.

      DropGuard also implements a dismiss associated function[1] which returns the variable from the guard without running the destructor. This makes it possible to quickly implement all-or-nothing transaction-like APIs with a rollback. Here is an example implementing a parser which uses a guard to roll back mutations in case of failure:

      use std::mem::DropGuard;
      use std::num::ParseIntError;
      
      /// Attempt to parse all `strings` and push them into `nums`.
      /// If parsing any of them fails, `nums` remains unchanged.
      fn parse_all(nums: &mut Vec<u32>, strings: &[&str]) -> Result<(), ParseIntError> {
          let len = nums.len();
          let mut nums = DropGuard::new(nums, move |nums| {
              nums.truncate(len);    // ← 1. Reset the vec on failure
          });
      
          for s in strings {
              nums.push(s.parse()?); // ← 2. If `?` returns an error, roll back
          }
      
          DropGuard::dismiss(nums);  // ← 3. Parsing successful, dismiss the guard
          Ok(())
      }
      

      Conjuring zero-sized types

      As Rust's unsafe code guidelines are still being decided, it became clear that it would be very useful to decide what exactly it means to create zero-sized types in an unsafe way, and what we should recommend for people to do this.

      This question is answered in Rust 1.100 with a single function: std::mem::conjure_zst.

      Instead of transmuting (), MaybeUninit::uninit().assume_init(), or various other incantations, this is the dedicated way to create a value of a zero- sized type when you know that doing so is safe to do. If an inhabited type has no size, we know exactly what value it must be: nothing.

      Of course, APIs often rely on the inability to construct such types for safety, and that's why this function is unsafe. For example, PyO3's Python<'py> is a zero-sized marker token that represents holding the Python GIL (global interpreter lock). Many of Python's APIs require holding this lock to be safe, but conjuring a token from thin air would allow safe PyO3 calls to violate that precondition.

      Reporting unused dependencies in Cargo

      Building dependencies that are no longer used or are only needed for specific platforms can slow down builds. Rustc has the unused_crate_dependencies lint for this but it has false positives when used with Cargo because dependencies may be shared between multiple build targets, e.g. dependencies.tracing- subscriber being available for every bin in a package when only some may use it.

      Cargo now reports unused dependencies to users, e.g.

      warning: unused dependency `tracing-subscriber`
        --> Cargo.toml:23:1
         |
      23 | tracing-subscriber.workspace = true
         | ^^^^^^^^^^^^^^^^^^
         |
         = note: `cargo::unused_dependencies` is set to `warn` by default
      help: consider removing the dependency on `tracing-subscriber`
      

      A limitation of this warning is that it will only appear when building every build target that may use an entry in a dependencies table. For example, running cargo check --bin foo won't show warnings for unused [dependencies] because another bin may be present that uses them. No warning will be shown for unused dev-dependencies because there isn't a way to ensure every development build target is built.

      This warning is being introduced as part of a new linting system for Cargo, controlled by the [lints.cargo] table in Cargo.toml, completing this project goal. See also the other lints that have been introduced.

      Reducing Cargo cache collisions

      Cargo builds all libraries and binaries in the build-dir and then uplifts final artifacts to the target-dir. At this time, these share a common parent directory. Different build configurations, like --features, can lead to different copies of libraries and binaries in the build-dir. These copies are kept unique by a build-configuration hash but this hash was not always applied due to platform constraints. This can lead to extra rebuilds, missed rebuilds, confusion over what binaries or libraries are used, and so on. These problems get exacerbated when sharing a build-dir across git worktrees.

      The build-dir now consistently applies the build-configuration hash to all content by organizing the directories around their build step, rather than their file type, and moving the hash from a file's name to the parent directory.

      This work began with the build directory layout project goal in 2025, and its stabilization is a milestone toward a new project goal, unblocking future improvements such as cache garbage collection, cross- workspace cache de-duplication, cross-workspace caching, and fine grain locking.

      We previously published a call for testing for the changes that are now taking effect. While this is an internal change, this may break build processes and tests that had workarounds for missing or incomplete features. In some cases, the workaround is no longer needed. See cargo#17287 for possible solutions and to add any new use cases.

      Cargo min-publish-age a.k.a. dependency cooldowns

      Malicious versions of packages are often caught within hours or days after being published, by either automated scanners or by the community. Rust 1.100 stabilizes Cargo's min-publish-age aware dependency resolution, which lets you wait for that window before it picks up newly published versions. This practice is also known as dependency cooldowns.

      You can opt in via .cargo/config.toml:

      [registry]
      global-min-publish-age = "3 days"
      

      When selecting versions, Cargo now skips any version published more recently than that, and tells you what it held back:

      $ cargo update
          Updating crates.io index
           Locking 2 packages to highest compatible version as of min-publish-age
            Adding cc v1.11.0 (available: v1.18.0, published 3 hours ago)
            Adding clap 4.6.7 (available: 4.6.9, published 2 days ago)
      

      When a new version is needed right away, you can override the check for a single update:

      $ CARGO_RESOLVER_INCOMPATIBLE_PUBLISH_AGE=allow cargo update clap --precise 4.6.9
          Updating crates.io index
          Updating clap 4.6.7 -> clap 4.6.9 (published 2 days ago, minimum age 3 days)
      

      The newer version will be recorded in Cargo.lock and kept from then on until a later cargo update re-resolves it.

      A few things to keep in mind:

      • This depends on the registry recording when each version was published. Versions without a pubtime field in the index are never held back.

      • cargo install ignores the minimum publish age, for both the installed crate and its dependencies. Pin a version with cargo install foo@1.2.3 if needed.

      • Cooldowns reduce the risk from some supply chain attacks but are not a complete defense on their own. Please keep reviewing dependency updates as you otherwise would.

      Further work to protect the ecosystem is planned under the crates.io supply chain hardening project goal, including quarantine support and automated detection of suspicious releases.

      Stabilized APIs

      Other changes

      Check out everything that changed in Rust, Cargo, and Clippy.

      Contributors to 1.100.0

      Many people came together to create Rust 1.100.0. We couldn't have done it without all of you. Thanks!

      1. it has deliberately been chosen not to be a method to avoid name collisions with the DerefMut-enabled method resolution on the inner type. ↩
    20. 🔗 New Music Releases Bullet for My Valentine - I Don't Trust Tomorrow rss

      Bullet for My Valentine - a new release is available:

      • 2026-11-12: I Don't Trust Tomorrow (Single)

      Amazon: Canada | Deutschland | France | United Kingdom | United States

      Visit muspy for more information.

    21. 🔗 New Music Releases TesseracT - Crucible rss

      TesseracT - a new release is available:

      • 2026-11-12: Crucible (Single)

      Amazon: Canada | Deutschland | France | United Kingdom | United States

      Visit muspy for more information.

    22. 🔗 Ampcode News Bye Bye, Dial rss

      Today we're saying goodbye to the Dial and its four modes: low, medium, high, and ultra.

      A model selector takes its place:

      The model selector open below the prompt box. Opus 5.5 is at the top with a Staff Pick tag, then GPT-6 Astra, GLM-5.3-Flash, and GPT-6.1 Sol. An icon on each row shows who bills you: Claude, ChatGPT, or Amp. A card next to the list describes Claude Opus 5.5 and says it is served by your personal Claude subscription.

      You can now pick the model and its effort for each thread. And you can now also switch both in the middle of a thread.

      The model selector now also shows you which of your subscriptions or API keys will be billed for each model, or whether it uses Amp credits.

      If you don't want to pick the model yourself, use the Staff Pick, which is the model we would choose.

      Yes, We Changed Our Mind

      In January we explained why Amp does not have a model selector. In July we then shipped the Dial so you could focus on how hard a task is instead of thinking about model names and version numbers. And it worked: when we changed the default model behind the Dial, nobody complained.

      But then we added the ability to Amp to bring your own subscriptions and keys, and Amp became free when you do. That changed what the selected model does. Not only is it what produces the tokens, but it also started to decide who gets billed. medium on the Dial could use your Claude plan, or your ChatGPT plan, or Amp credits, and it became very hard to tell who's paying for which model when.

      And that's not to speak of all the settings we had to add to the Dial to make it work in every combination.

      So we decided to stop hiding the model and now have a model selector. Now, when you pick it yourself, you know where the tokens come from and who's paying.

      And yet, it's still not just a model you pick. An agent is more than a model. You pick the model, and we build the harness around it: each model in the selector gets a system prompt and tools optimized for it, and both switch when you switch models in a thread.

      Switch Models in a Thread

      With the Dial, a thread kept the mode (and model) it started with. We did that because a model became confused when it continued a conversation that another model had started. But now models are good enough to recover from that.

      Now you can change the model mid-thread by opening the selector and making the change. After your next message the new model will be used and the transcript will show a record: "Switched to GPT-6.1 Sol · High".

      But some things haven't changed. A model switch still has a price. Prompt caches belong to one model, so the new model reads the whole thread uncached, and the first message after a switch costs more.

      Threads that run an agent from a plugin keep that agent.

      Staff Pick

      New threads start on Staff Pick by default. (Except if you had previously configured the Dial to have a default mode.)

      Staff Pick is the model we would pick ourselves, which is Claude Opus 5.5 today. We keep benchmarking models, and we'll change the pick when another model does better.

      In Settings → Model Selector, under New Threads Start On, you can also start new threads on the model you picked last, or on one fixed model you choose.

      What Happens to Your Dial

      Until today everyone used the Dial, so this applies to you.

      New threads start on Staff Pick, whichever mode you used last.

      Existing threads keep working. A thread you started in high continues on the model it ran.

      Dial settings don't carry over. If you changed the model behind a mode in Tune Modes, pick that model in the selector now. If you put your own agents on the Dial in Build Dial, you find them under Other Models.

      If you never changed those settings, these are the models your modes ran. The first three are at the top of the selector, and Claude Fable 5.2 is under Other Models:

      • low: GLM-5.3-Flash
      • medium: Claude Opus 5.5
      • high: GPT-6 Astra
      • ultra: Claude Fable 5.2

      Pin your models in Settings → Model Selector, or leave the selector on Staff Pick.

      Read the Model Selector docs for everything the selector and its settings do.