🏑


  1. August 06, 2026
    1. πŸ”— earendil-works/pi v0.84.0 release

      New Features

      • Fullscreen TUI mode β€” Switch between regular and fullscreen modes at runtime, with a sticky editor and footer, independently scrollable transcript, and draggable scrollbars. See UI & Display.
      • Mermaid and LaTeX rendering β€” Render Mermaid diagrams and terminal-friendly Unicode math in interactive transcripts. See Markdown settings and TUI Markdown.
      • Per-directory context overrides β€” Use AGENTS.override.md to replace context files for a specific directory. See Context Files.
      • Advanced custom model sampling β€” Configure arbitrary OpenAI-compatible samplingParams and opt-in vLLM thinking_token_budget values. See Sampling Parameters.
      • Baseten provider β€” Use built-in Baseten authentication and model support. See API Keys.

      Breaking Changes

      • Renamed the inherited pi-ai ModelsStreamTransforms interface to ModelsRequestTransforms because its header transformation now applies to all authenticated provider requests.

      • Changed JSON and RPC message_update events to emit only assistantMessageEvent deltas, removing the cumulative message and assistantMessageEvent.partial fields that caused quadratic output growth. Clients that need partial messages must assemble deltas between message_start and message_end; the latter remains authoritative (#7290).

      • ModelRegistry.getApiKeyAndHeaders() now returns ProviderHeaders with string | null values and preserves null header-deletion markers. Extensions that inspect returned headers must handle null; extensions forwarding them to pi-ai streams should pass them through unchanged. This prevents placeholder OpenAI credentials from being sent through Cloudflare AI Gateway (#7030).

      • Changed ModelRegistry.refresh() to accept ModelsRefreshOptions and return ModelsRefreshResult instead of discarding cancellation and provider errors.

      • Changed ModelRuntime.setRuntimeApiKey() to accept auth cancellation options rather than catalog refresh options. Call refresh({ providers: [providerId], signal }) separately when remote freshness is required.

      • Required config-form extension OAuth refreshToken(credentials, signal) callbacks to accept and honor a concrete abort signal.

      • Replaced dynamic provider refresh context store access with the read-only context.stored snapshot and generation-checked context.publish() transaction.

      Providers built withcreateProvider({ fetchModels }): no catalog- publication migration is required. Before and after, return the fetched models and register the resulting provider; createProvider() owns restoration, persistence, and in-memory publication.

          // Before
      const beforeProvider = createProvider({
        // ...
        fetchModels: async ({ signal }) => {
          const response = await fetch(catalogUrl, { signal });
          return parseModels(await response.json());
        },
      });
      pi.registerProvider(beforeProvider);
      
      // After: unchanged
      const afterProvider = createProvider({
        // ...
        fetchModels: async ({ signal }) => {
          const response = await fetch(catalogUrl, { signal });
          return parseModels(await response.json());
        },
      });
      pi.registerProvider(afterProvider);
      

      Handwritten nativeProvider.refreshModels(): replace direct store access and pre-publication mutation with generation-guarded publications.

          // Before
      refreshModels: async (context) => {
        const stored = await context.store.read();
        if (stored) currentModels = stored.models;
        if (!context.allowNetwork) return;
      
        const refreshed = await fetchModels(context.signal);
        currentModels = refreshed;
        await context.store.write({ models: refreshed, checkedAt: Date.now() });
      },
      
      // After
      refreshModels: async (context) => {
        if (context.stored) {
          const restored = context.stored.models;
          if (!(await context.publish({
            update: () => { currentModels = restored; },
          }))) return;
        }
        if (!context.allowNetwork) return;
      
        const refreshed = await fetchModels(context.signal);
        if (context.signal.aborted) return;
        await context.publish({
          persist: { models: refreshed, checkedAt: Date.now() },
          update: () => { currentModels = refreshed; },
        });
      },
      

      For the config-form pi.registerProvider(name, { refreshModels }), callbacks that only return models remain unchanged; pi publishes the returned list. If such a callback previously used context.store for custom persistence, read context.stored and call context.publish({ persist: entry }). In publish(), omit persist to leave storage unchanged, pass a ModelsStoreEntry to write it, or pass persist: null to delete it.

      • Replaced the inherited pi-agent-core harness session model with the v4 lane-based Session, SessionStorage, and SessionRepo APIs, including durable operation records, global facts, shared sequence numbers, and tree-scoped lane views.

      • Promoted the inherited v2 session and AgentHarness API from pi-agent-core's experimental entrypoint to its default export and removed the experimental subpaths.

      • Removed the inherited legacy JSONL and in-memory repository APIs. Use pi-agent-core's v4 JsonlSessionRepo or InMemorySessionRepo, both implementing the new SessionRepo contract.

      • Added the inherited required pi-agent-core FileSystem.renameFile() operation for atomic JSONL publication; custom harness file-system implementations must provide same-filesystem replacement semantics (#7707 by @davidbrai).

      • Replaced experimental remote-session list summaries with durable SessionMetadata; RemoteSession.sessions no longer exposes runtime phase, model, thinking, attachment, or lock state, which remains available from acquired SessionSnapshot values (#7708).

      Added

      • Added built-in Baseten provider support with BASETEN_API_KEY authentication and zai-org/GLM-5.2 as the default model.
      • Added experimental remote-session client APIs: the transport-neutral PiClient, CBOR protocol, Unix-socket transport, and @earendil-works/pi-coding-agent/client RemoteSession controller with transcript reducers. See Pi Client and Remote Protocol (#7344, #7348, #7371, #7409).
      • Added CredentialSynchronizationError for credential changes that commit successfully but fail to synchronize local model state.
      • Added chainable pi.registerMarkdownTransformer() hooks for display-only transformation of user and assistant Markdown. See pi.registerMarkdownTransformer() (#7231 by @xl0).
      • Added an experimental fullscreen TUI mode, selectable through --tui-mode fullscreen or /settings (#7304).
      • Added runtime switching between regular and fullscreen TUI modes through /settings.
      • Added a sticky editor, status, widget, and footer dock to fullscreen mode while keeping the transcript independently scrollable.
      • Added a draggable transcript scrollbar to fullscreen mode with configurable auto, always, and hidden modes through /settings; always reserves the rightmost column.
      • Added page scrolling and marked-message navigation shortcuts to fullscreen mode.
      • Added an optional scrollbarThumb theme color for fullscreen scrollbar thumbs, falling back to selectedBg.
      • Added configurable themed Unicode rendering for supported Mermaid diagrams in interactive messages, including optional rendering while streaming. See Markdown settings (#7624 by @xl0).
      • Added opt-in Ctrl+P/Ctrl+N prompt history navigation, with explicit history bindings taking precedence over application shortcuts while the editor is focused.
      • Added per-directory AGENTS.override.md context files, which replace AGENTS.md or CLAUDE.md in the same directory while preserving context from other directories. See Context Files (#7681 by @Marvae).
      • Added AI_AGENT=pi to CLI and RPC child-process environments for generic agent attribution. See Environment Variables (#7493 by @renaudhartert-db).
      • Added inherited terminal-friendly Unicode rendering for LaTeX expressions in Markdown. See TUI Markdown.
      • Added stacked transient notifications in fullscreen mode.
      • Added arbitrary OpenAI-compatible model sampling parameters through samplingParams in models.json, model overrides, extension providers, and stream options. See Sampling Parameters (#7568 by @mrexodia).
      • Added inherited opt-in vLLM thinking_token_budget support for OpenAI-compatible models, reserving output tokens for the final answer (#7638 by @bnsd55).
      • Added inherited support for OpenAI-compatible streams that omit finish_reason, using compat.supportsFinishReason to infer normal and tool-use stops when the stream ends. See OpenAI Compatibility.
      • Added inherited deferred provider request contracts, durable response handles, authenticated fetch/cancel dispatch, and faux-provider support for pending, ready, failed, and cancelled responses (#7339 by @davidbrai).
      • Added inherited vendor-neutral telemetry contracts plus agent-owned typed AI-request and harness schemas, composed span starters, and callback helpers. See the agent telemetry schema reference.
      • Added inherited structured Amazon Bedrock failure diagnostics with HTTP status, modeled error code, and AWS request id when available (#7286 by @brianstanley).
      • Added inherited AgentOptions.shouldStopAfterTurn for gracefully stopping after a completed turn before queued messages or another model call are processed. See Agent Options (#7367 by @acmerfight).
      • Added inherited v4 JsonlSessionRepo support for append-only JSONL harness sessions (#7611 by @davidbrai).
      • Added inherited bounded branch-entry and indexed open-operation recovery queries to the v4 session API (#7448, #7646).
      • Added the inherited compile-complete AgentHarness v2 scaffold; unfinished operation paths reject with HarnessNotImplemented while durable execution is implemented.

      Changed

      • Added inherited optional cancellation to pi-ai ModelsStore reads, writes, and deletions; catalog orchestration binds these waits to the provider refresh signal.
      • Reduced the inherited default fullscreen mouse wheel step from three lines to one for finer scrolling.

      Fixed

      • Fixed the footer showing (sub) for generic OAuth/OpenID sign-ins without a known subscription; extension OAuth providers can opt in with isSubscription.
      • Fixed inherited OAuth token refreshes so stalled requests release the credential-store lock (#7508).
      • Fixed inherited tool argument validation to preserve values that already match an anyOf/oneOf union arm before coercion, avoiding nullable unions converting null to another primitive value (#7328).
      • Fixed inherited Fireworks GLM 5.2 requests sending the unsupported prompt_cache_retention field when long cache retention is enabled, and enabled session affinity for automatic prompt caching (#7676).
      • Fixed inherited JsonlSessionRepo enforcing session IDs globally across working directories; IDs are now unique within each working directory.
      • Fixed inherited JSONL session forks and torn-tail repairs to publish atomically, avoiding partially written or corrupted sessions after interrupted writes (#7707 by @davidbrai).
      • Fixed path-containing find globs returning no results on Windows (#6817).
      • Fixed messages queued during manual /compact failing instead of being sent after compaction completes.
      • Fixed Git Bash, MSYS, Cygwin, and WSL drive paths passed to built-in file tools resolving against the current Windows drive instead of their native drive (#7064, #7547).
      • Fixed project-level nested provider retry settings replacing unmodified global provider retry settings (#7572).
      • Fixed inherited GitHub Copilot Grok 4.5 requests to use the supported Responses API (#7560).
      • Fixed fullscreen shutdown leaking terminal capability-query replies into the parent shell prompt.
      • Fixed bare exact --model IDs shared by multiple providers choosing the first catalog entry instead of the sole authenticated provider or a clear ambiguity error (#7327).
      • Fixed standalone x64 binaries requiring Haswell-era AVX2/BMI2 instructions by compiling release executables against Bun's baseline runtime (#7390 by @davidbrai).
      • Fixed Ctrl+X copy confirmations in fullscreen mode adding a transcript status line instead of showing the transient Copied! marker.
      • Fixed Kitty image previews in fullscreen mode overlapping the sticky editor and footer dock while scrolling.
      • Fixed image-heavy fullscreen sessions lagging when layout changes retransmitted visible Kitty image payloads and rendered the transcript twice per frame.
      • Fixed spaces in /settings searches toggling the highlighted setting while typing multi-word queries such as TUI mode or Quiet startup.
      • Fixed custom editors not inheriting the default editor's autocomplete dropdown item limit (#7333).
      • Fixed malformed resource arrays in package manifests crashing session startup (#7187).
      • Fixed the DOOM overlay example downloading its shareware WAD from a dead URL.
      • Fixed setToolsExpanded(false) to be a no-op when tool output is already collapsed, avoiding redundant Tool output: collapsed startup notices from extensions (#7292).
      • Fixed extension-driven model calls in custom compaction, handoff, and Q&A examples to dispatch through the coding-agent model runtime so custom providers and resolved auth options are preserved (#7325).
      • Fixed long-running sessions using stale credentials after another process updates auth.json without serializing concurrent credential reads and delaying startup (#7319).
      • Fixed concurrent models-store.json reads forming a file-lock convoy and delaying startup.
      • Updated the packaged brace-expansion dependency to 5.0.8 to address GHSA-mh99-v99m-4gvg (#7316).
      • Fixed forced model availability refreshes remaining blocked behind a stalled earlier refresh (#7301, #7421 by @a-yeyang).
      • Fixed /model catalog refresh failures to identify every catalog that failed.
      • Fixed provider login remaining stuck after saving credentials when a model catalog refresh stalls by separating local credential consistency from bounded background freshness (#7027, #7113, #7418).
      • Fixed /scoped-models waiting for remote catalogs before rendering instead of showing cached models and cancelling refresh on close (#7153).
      • Fixed /model <name> waiting for catalog refresh before checking cached model matches (#7443).
      • Fixed stale availability snapshots and errors publishing after a newer availability pass.
      • Fixed stale pi.dev, Radius, llama.cpp, and extension catalog refreshes publishing after a newer provider refresh.
      • Fixed cancellation while waiting for file-backed credential or model-catalog locks, preventing cancelled mutations from running or committing later.
      • Fixed concurrent in-memory credential mutations losing unrelated provider updates by serializing their read-modify-write sections.
      • Updated undici to 8.9.0 and the packaged brace-expansion to 5.0.9 to address GHSA-8xcm-r25x-g524, GHSA-4cwx-7wf7-3272, GHSA-m8rv-5g2x-5cg5, GHSA-jr45-8vmc-qm54, GHSA-v3r7-h72x-cjcm, and GHSA-rgw5-rvv9-x895.
      • Fixed GitHub Copilot compaction and branch summaries using the Individual endpoint instead of the credential-resolved Business or Enterprise endpoint (#6768).
      • Fixed extension model calls dropping credential-resolved endpoints when forwarding request authentication, including custom compaction with GitHub Copilot Business and Enterprise accounts (#7579).
      • Fixed fullscreen transcript navigation leaving no editor-accessible Home, End, PageUp, or PageDown variants by adding Ctrl-modified editor bindings (#7574).
      • Fixed extension event-bus listeners surviving session reloads and disposal (#7656 by @tudoroancea).
      • Fixed /copy failing to read clipboard text on Wayland when no X11 clipboard is available (#7387).
      • Fixed slow connections failing during the initial connection attempt by increasing the connect timeout (#7435 by @muyiyr).
      • Fixed oversized images returned by extension and built-in tools bypassing automatic image resizing. See Image settings (#7330 by @tizmagik).
      • Fixed session discovery missing sessions stored through symlinked directories (#7552 by @muyiyr).
      • Fixed manual compaction racing with threshold auto-compaction (#7370 by @davidbrai).
      • Fixed responses truncated below their intended output limit ending the run instead of compacting and retrying once (#7540 by @davidbrai).
      • Fixed Git package updates leaving dependencies missing when git clean cannot remove an ignored dependency directory (#7570 by @mrexodia).
      • Fixed find results from POSIX and Windows filesystem roots losing the first path segment or gaining duplicate trailing separators (#7569 by @petrroll).
      • Fixed transient version-check, catalog, managed-tool, and package-management HTTP failures not being retried (#7632 by @petrroll).
      • Fixed interactive errors ignoring the configured output padding.
      • Fixed the inherited OpenCode Go provider display name.
      • Fixed inherited provider error normalization treating arrays and class instances as structured response bodies instead of preserving their original errors (#7205 by @erikogenvik).
      • Fixed inherited Anthropic streams dropping text or thinking included in the initial content-block event (#7358 by @davidbrai).
      • Fixed inherited Google history conversion dropping signed empty text and thinking blocks required for replay (#7362 by @jingtao-wisdomgraph).
      • Fixed inherited OpenAI Codex cached WebSocket sessions being shared across different account credentials (#7364).
      • Fixed inherited transient Google Generative AI and Vertex AI provider errors bypassing automatic retries (#7471 by @vish-pr).
      • Fixed inherited Gemini 3 tool call ids being discarded during history conversion, breaking signed multi-turn replay (#7494 by @muyiyr).
      • Restored inherited GitHub Copilot models returned through account-specific policy responses (#7672 by @muyiyr).
      • Replaced the inherited retired Qwen Token Plan qwen3.8-max-preview model with qwen3.8-max (#7670 by @QuintinShaw).
      • Fixed inherited terminal width accounting for Indic conjunct grapheme clusters (#6987 by @petrroll).
      • Fixed inherited nested fullscreen stack layouts ignoring child minimum sizes.
      • Fixed inherited batched terminal color-scheme reports being parsed as one malformed response (#7550).
      • Fixed inherited terminal progress clearing to emit the complete OSC 9;4 sequence (#7581).
      • Fixed inherited iTerm2 image payloads omitting the size metadata required by the xterm.js image addon (#7612).
      • Fixed inherited width truncation leaving OSC 8 hyperlinks unterminated (#7657 by @xXJSONDeruloXx).
      • Updated inherited GPT-5.6 Terra and Luna pricing across OpenAI and passthrough model catalogs.
      • Fixed inherited Fireworks Kimi K3 models to use the OpenAI-compatible API with native reasoning-effort levels and deferred tools (#7199, #7230 by @XBeg9).
      • Updated the inherited Groq Qwen reasoning override for the replacement qwen/qwen3.6-27b model.
      • Fixed inherited Windows Shift+Enter detection by reading modifier state from the native Win32 helper.
      • Fixed the inherited pi-tui npm package omitting the source and build scripts needed to rebuild its Windows and Darwin native addons.
      • Fixed inherited Windows console truecolor detection when Windows Terminal does not provide WT_SESSION to child shells.
      • Fixed inherited phantom fullscreen text selection from unmatched mouse events when changing terminal pane focus.
      • Fixed inherited keyboard input rendering latency on Windows by letting input preempt the throttled render timer.
      • Fixed inherited agent harness path handling on Windows for file basenames, recursive skill loading, and prompt template names.
    2. πŸ”— smol-machines/smolvm smolvm v1.7.5 release

      What's Changed

      • Ship the disk templates zstd-compressed and expand them to sparse files on first use by @BinSquare in #771
      • Copy the storage template by seeking between its data extents instead of scanning its whole logical size by @BinSquare in #770
      • Harden fused rollout lifecycle by @BinSquare in #801
      • Avoid copying CUDA module state for clone channels by @BinSquare in #804
      • Load device-resident LoRA policies through managed executors by @BinSquare in #806
      • Reject a registry-image machine that has no network at create instead of failing every start with a raw DNS error by @BinSquare in #807
      • Perform machine file reads and writes inside the running workload container so uploads are visible to exec by @BinSquare in #810
      • Reuse CUDA module handoffs across clone workers by @BinSquare in #808
      • Cache pulled OCI images on the host so repeat ephemeral machine runs skip the registry pull by @BinSquare in #805
      • Signal guest boot-readiness with an event-driven vsock doorbell as the primary ready signal, keeping the marker file and control-channel ping as fallbacks by @BinSquare in #811
      • Map CUDA module handoffs across clone workers by @BinSquare in #814
      • Preserve per-device GPU admission headroom by @BinSquare in #826
      • Promote CUDA pool readiness and refill improvements by @BinSquare in #828
      • Bump the workspace to 1.7.3 by @BinSquare in #829
      • Install the zstd-compressed disk templates in the Arch package so the build no longer fails on the removed uncompressed storage template by @BinSquare in #830
      • Set the library search path on the boot subprocess before launch so libkrun can load libkrunfw when embedded without a wrapper script by @BinSquare in #832
      • Make fork-pool lease activation retry-safe by @BinSquare in #831
      • Bump the workspace to 1.7.4 by @BinSquare in #833
      • Avoid blocking restored container state probes by @BinSquare in #834
      • Harden privileged CUDA clone startup by @BinSquare in #839
      • Harden CUDA admission calibration by @BinSquare in #840
      • Stabilize restored forkpoint activation by @BinSquare in #835
      • Coordinate clone boots across fork pools by @BinSquare in #836
      • Preserve CUDA pool refill checkpoints by @BinSquare in #841
      • Wait for explicit CUDA daemon reconstruction by @BinSquare in #844
      • Adapt CUDA admission to available GPU headroom by @BinSquare in #846
      • Persist CUDA pool refill checkpoints by @BinSquare in #845
      • Bump libkrunfw to the guest kernel with the Landlock LSM enabled by @BinSquare in #847
      • Serialize concurrent VM updates by @BinSquare in #850
      • Retry transient batch fork boots by @BinSquare in #853
      • Expose identity for direct batch forks by @BinSquare in #856
      • Bump libkrun for the mount-socket concurrent-hang fix by @BinSquare in #837
      • Wake netns TAP bridge during shutdown by @BinSquare in #860
      • Harden device adapter server startup by @BinSquare in #861
      • Run an image machine's commands inside its image on the embedded path, so a locally created machine behaves like a cloud one by @BinSquare in #862
      • Gate leases on worker readiness by @BinSquare in #858
      • Preload prepared CUDA clone modules by @BinSquare in #854
      • Note which guest paths are memory-backed and reset on restart by @BinSquare in #869
      • Let an artifact-sourced machine run without network instead of demanding a registry pull by @BinSquare in #877

      Full Changelog : v1.7.2...v1.7.5

    3. πŸ”— backnotprop/plannotator v0.26.2 release

      Follow @plannotator on X for updates


      Missed recent releases? Release | Highlights
      ---|---
      v0.26.1 | GitButler 0.22.0 compatibility via capability-probed JSON flags
      v0.26.0 | Edit Mode (suggest by editing the diff), Guided Review virtualization, colorblind theme, safe uninstall, installer opt-outs, OpenCode 2 support
      v0.25.1 | Codex no longer launches on review open, annotate-last follows the live conversation, pi-todos mirror, Claude Opus 5, abandoned-gate dismissal
      v0.25.0 | Vim keyboard controls, Approve with Notes, scriptable annotate gates, persistent Guided Reviews, memory and file-watching hardening
      v0.24.2 | Annotate YAML/JSON/TOML config files, XDG data directory support, Codex model catalog update, Cursor sandbox escape hatch
      v0.24.1 | Annotate accepts parent-relative ../ file paths
      v0.24.0 | PR/MR artifact gallery, GitButler review support, port ranges, expanded comment editor, OpenCode + Pi fixes
      v0.23.1 | Startup no longer hangs on large or slow directory trees, Ask AI input stays visible after long responses
      v0.23.0 | Plan approval fix for Claude Code 2.1.199+, annotate mode version diff, binary-only --minimal install, reviews post without attribution
      v0.22.0 | Git-status "All changes" default review view, Commits panel with per-commit diffs, Guided Review, Pi + GitHub Copilot CLI review engines
      v0.21.4 | Markdown math rendering, PR Overview panel with annotatable description and comments, agent instructions in code review, media parsing fixes


      What's New in v0.26.2

      This release fixes two review regressions that shipped in v0.26.0, both reported by users within a day of release, and brings two visible improvements: pick separate light and dark themes, and code blocks that match your palette. Updating from v0.25.x? The full v0.26.0 feature notes are embedded in the v0.26.1 release notes.

      Fixed: single-file diff tabs render fully again

      In v0.26.0 and v0.26.1, opening a file as its own tab (clicking it in the file tree or sidebar, including PR review) showed only the changed hunks: the "N unmodified lines" bars between hunks had no expand controls and clicks did nothing, so surrounding code could not be revealed. The all-files scroll view was unaffected, which made the breakage feel random.

      The cause was the diff renderer upgrade in v0.26.0. The renderer began identifying content by cache key and defaulting that key to the file name, so when the tab swapped its initial partial diff for the full expandable one, the renderer saw the same name and kept serving the stale partial render forever. The single-file view now derives cache keys from content, the same invariant the all-files view already followed.

      Fixed: no more silently dropped files in review diffs

      The more serious of the two. In v0.26.0 and v0.26.1, certain files rendered as empty cards: listed in the tree with a modified badge but no counts, no hunks, and no way to see the change. The diff totals quietly excluded them, so nothing indicated content was missing. A reviewer could approve believing they had seen everything. Affected shapes included renamed files carrying uncommitted edits, and repositories where an object was absent from git's local object database (partial clones, for example).

      The cause sat in the large-file memory bound introduced in v0.26.0. Its size probe asks git's object database how big each changed object is, but git reports a computed hash for worktree content it examined during rename detection, a hash for content that was never stored as an object. The probe got "missing" and treated missing as infinitely large, so the file was excluded and stubbed as binary. The probe now treats content it cannot find in the object database by checking the file on disk instead, and "missing" is no longer assumed oversized. The memory bound itself is unchanged: genuinely oversized files still render as stubs, and those stubs now say so on screen ("This file is over the 5 MB review limit") instead of appearing silently empty.

      This was reported by a user on X with side-by-side screenshots comparing Plannotator against their editor's diff view, exactly the evidence that cracked it. Thank you.

      Pair a light theme and a dark theme

      Settings > Theme now assigns each half of a pair: pick which palette is your light theme and which is your dark theme, and System mode switches between your two choices as your OS scheme changes (Kanagawa Lotus by day, Kanagawa Wave at night). Previously, choosing a dark-only palette pinned the mode and disabled system switching entirely. The pair persists to ~/.plannotator/config.json, so it survives Plannotator's random ports and applies across every host. Existing theme choices migrate automatically.

      One syntax highlighter, palette-matched code blocks

      Plannotator shipped two syntax highlighters: highlight.js for markdown code blocks, and Shiki inside the diff renderer. Code blocks now use the same Shiki instance the diff pane already loads, which means they finally render in your active palette (all built-in themes, colorblind included, light and dark) instead of a fixed dark style. highlight.js is removed entirely, along with a never-executed WebAssembly engine the diff renderer bundled. The plan review bundle shrank by about 1.3MB and the code review bundle by about 2.2MB.

      Bare code fences (no language tag) now render as plain monospaced text instead of getting auto-detected highlighting, matching how GitHub and most markdown renderers behave. Prose quoted inside fences no longer gets colored like code.

      Additional Changes

      • Self-hosting docs corrected. The guide no longer claims the portal bundles Highlight.js (#1221)

      Install / Update

      macOS / Linux:

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

      Windows:

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

      Claude Code Plugin: Run /plugin in Claude Code, find plannotator , and click "Update now".

      OpenCode: Clear cache and restart:

      rm -rf ~/.bun/install/cache/@plannotator
      

      Then in opencode.json:

      {
        "plugin": ["@plannotator/opencode@latest"]
      }
      

      Pi: Install or update the extension:

      pi install npm:@plannotator/pi-extension
      

      What's Changed

      • fix: render language-less code blocks as plain text by @zeke in #1212
      • feat: pair a light theme and a dark theme, switched by mode by @backnotprop in #1217
      • perf: single Shiki highlighter, palette-matched code blocks, drop highlight.js by @backnotprop in #1218
      • fix: mint content-derived diff cache keys so single-file tabs render fully by @backnotprop in #1219
      • fix: stop stubbing files whose worktree content the size probe cannot find by @backnotprop in #1220
      • docs: self-hosting page no longer claims a bundled Highlight.js by @backnotprop in #1221

      New Contributors

      Community

      @zeke reported the auto-detected highlighting problem with a screenshot that made the case instantly (#1210) and fixed it himself the same day. First contribution.

      @kunaaal13 designed the theme pair system in a file-accurate proposal that was adopted nearly as written (#1211); parts 2 and 3 (custom user themes, separate fonts) remain open.

      And to the reporter on X whose side-by-side editor comparison exposed the silently dropped files: that report likely saved other users from approving reviews they could not fully see.

      Full Changelog : v0.26.1...v0.26.2

    4. πŸ”— jj-vcs/jj v0.44.0 release

      About

      jj is a Git-compatible version control system that is both simple and powerful. See
      the installation instructions to get started.

      Release highlights

      • Support for fetching and pushing tags has now been stabilized. Tags can be
        tracked or untracked just like bookmarks. Tracked tags are pushed by default.

      Breaking changes

      • jj git fetch now fetches tags the same way it fetches bookmarks. Tags are
        fetched as <name>@<remote>, and these remote tags are automatically tracked
        by local tags of the same name. Running jj git fetch in an existing
        repository will re-fetch all tags to initialize the tracking state.

      Git's tagOpt is no longer respected. To disable tag fetching, set
      remotes.<name>.fetch-tags = '~*' in the jj configuration.

      • jj git clone --fetch-tags=all|none|included is removed in favor of
        --tag=PATTERN.

      • jj git push --all now pushes all tags in addition to bookmarks.

      • The WorkspaceRef.root() and RepoPath.absolute() template functions now
        return Option<FsPath> and FsPath respectively, instead of String. The
        path keyword in jj config list templates now returns Option<FsPath>.

      • jj file search now prints every matched line prefixed by the file path,
        instead of only the file paths of files containing a match. Use
        --name-only for the previous behavior.
        #9399

      • Passing an argument more than once is no longer an error. The last occurrence
        wins, so jj --no-pager --no-pager version and jj log -n 5 -n 10 now work,
        and an argument baked into an alias or a wrapper can be given explicitly as
        well. Arguments that can be specified multiple times, such as --config and
        jj log -r, are unaffected and still collect all of their values.
        #8101
        #9859

      Deprecations

      None

      New features

      • New merge_point() revset function which (similar to fork_point) finds the
        point where multiple branches merge.

      • jj workspace list now shows workspace roots by default. The output can be
        customized with templates.workspace_list or -T, and WorkspaceRef.root()
        returns an optional FsPath value.
        #9713,
        #9826

      • New try(expr, fallback...) template function to suppress runtime errors.

      • jj run now processes revisions from oldest to newest by default. The start
        order is guaranteed: each revision begins execution only after the previous
        one has started, even with --jobs higher than 1.

      • jj run gained a --passthrough flag that connects the subprocess's
        stdout/stderr directly to the terminal instead of capturing output.

      • jj run gained a --ignore-changes flag to avoid editing any revisions even
        if the command modifies the working copy.

      • jj run gained a --ignore-errors flag to continue running against the
        remaining revisions even if the command exits with a nonzero exit code.

      • jj file search now supports -n/--line-number to prefix each match with
        its 1-based line number within the file.

      • jj git push gained a --allow-conflicts flag to allow pushing commits
        containing conflicts.

      • New jj tag track/untrack commands to associate local tags with remotes.
        Note that fetched tags are tracked by default.

      • Added builtin_log() revset alias for the built-in default jj log revset.
        revsets.log now defaults to builtin_log(), so custom log revsets can
        reuse the built-in default instead of copying its full expression.

      • Added config option diff.stat.max-bar-width for use with --stat to limit
        the ++-- bar width. In the templating language, diff.stat() can optionally
        take a second (positional or named) argument max_bar_width for an equivalent
        effect.

      • jj absorb now supports --interactive/-i/--tool to let you
        interactively choose which hunks from the source to consider for absorption.
        This is useful when you only want to absorb part of a commit without first
        splitting it. Any hunks that are not selected or cannot be absorbed remain in
        the source commit.

      Fixed bugs

      • Recursive alias definitions are detected more precisely. jj can now expand
        aliases that are simply repeated. For example, with the alias jj = [], the
        command jj jj jj will resolve to jj. Aliases can also fall back to the
        default command. For example, with the alias i = ["--ignore-working-copy"],
        jj i will resolve to jj --ignore-working-copy.

      • Git temporary files are now cleaned up more reliably in the presence of
        signals (e.g. Ctrl-C). This should reduce the rate of "Could not acquire
        lock for index file" errors.
        (#7530)

      • Fixed Git HEAD mismatch after the working copy became immutable.
        #9827

      • jj now creates a new working-copy revision as soon as the one of the current
        workspace becomes immutable, as well as during snapshotting. This brings the
        behavior closer to jj 0.42 and earlier.

      • Snapshotting no longer fails if the working copy contains a path whose name
        isn't valid UTF-8. Such paths can't be tracked, so they are now skipped and
        reported as a warning instead.
        #9774

      • Fixed failure when reading configuration in copied repo with an empty
        repo-level configuration directory.

      • jj diff and jj status no longer omit a rename or copy in a merge commit
        when the renamed source is present in more than one parent. The identical copy
        record reported for each parent was mistaken for a conflict and discarded.
        #9752

      • jj run no longer panics when its revset includes a conflicted commit. The
        conflict is now preserved in the rewritten commit.
        #9747

      • Fixed a panic when passing overly-large length parameters to ID templater
        functions (commit_id.short(), commit_id.shortest(), etc.).
        #9833

      • jj git import and export in colocated workspaces are now disabled by
        default. These commands usually do nothing, but they had a race condition.

      Contributors

      Thanks to the people who made this release happen!

    5. πŸ”— jj-vcs/jj v0.43.0 release

      About

      jj is a Git-compatible version control system that is both simple and powerful. See
      the installation instructions to get started.

      Release highlights

      • jj run allows you to run a command over a set of changes, each with their
        own private working copy; the commands may update the working copy and
        changes/conflicts are propagated accordingly, e.g., jj run -- cargo check --all-features or jj run -- cargo fix behaves as one might expect.

      Breaking changes

      • The deprecated git_head() and git_refs() functions have been removed from
        revsets and templates.

      • Git-like symbols (e.g. refs/heads/main) are no longer resolved to
        revisions. Use the bookmark/tag <name> or <name>@<remote> syntax instead.

      • The deprecated ui.revsets-use-glob-by-default option has been removed.

      • jj bookmark track/untrack no longer supports <kind>:<bookmark>@<remote>
        patterns. However, the <bookmark>@<remote> symbol syntax is still supported.
        #9226

      Deprecations

      New features

      • jj show now supports --reversed flag.

      • jj now looks for config files in /etc/jj.

      • jj config gc will delete configuration of deleted/moved repos from
        ~/.config/jj/repos folder.
        #9362

      • jj run allows you to run a command over a set of changes, each with their
        own private working copy; the commands may update the working copy and
        changes/conflicts are propagated accordingly, e.g., jj run -- cargo check --all-features or jj run -- cargo fix behaves as one might expect.

      • jj gerrit upload now supports the -o (--option) flag, which works like
        git push -o (--push-option).

      • jj git fetch now rebases the descendants of revisions that were rewritten
        based on their change IDs. Previously, when multiple bookmarked revisions
        existed in a stack, those rewritten revisions and their descendants wouldn't
        always be rebased. Note that immutable descendants will not be rebased.

      • Add a forks() revset function that yields all commits with more than 1 child.

      • colors config now supports crossed-out text styling with
        { crossed-out = true }.

      Fixed bugs

      • On Windows, querying a path's file identity no longer follows symbolic links,
        matching the behavior on Unix. Previously a symlink shared the identity of its
        target, so two symlinks pointing at the same target were treated as the same
        file. This identity check is used when writing the working copy to detect
        aliases of the reserved .git and .jj directories.
        #8924

      • jj now creates a new working-copy revision during snapshotting if the
        working copy was immutable. Previously, the new revision was created
        immediately after the working copy became immutable.
        #7751
        #9338

      • jj git remote add now warns if the new remote exactly matches an existing
        remote's fetch URL or effective push URL.
        #413

      • Fixed corrupt loose Git objects on Intel Raptor Lake CPU and aarch64.
        Previously, jj could report a successful commit even though git fsck would
        later fail with incorrect data check, corrupt loose object, or missing blob, and later jj operations could fail with corrupt deflate stream.

      Contributors

      Thanks to the people who made this release happen!

    6. πŸ”— Console.dev newsletter syncular rss

      Description: Offline-first SQL sync.

      What we like: Gives every client a local SQLite database with a server-side commit log. Reads & writes are local, then sync’d (offline outbox). Blobs stored as content-addressed on object storage. CRDT conflict resolution. Optional per-column E2E encryption.

      What we dislike: C FFI for non-supported languages.

    7. πŸ”— Console.dev newsletter Mu rss

      Description: Local tools for agents.

      What we like: MCP server with various tools for agents - news, weather, search, mail. Provides auth and a web UI for using the tools via a browser. Also provided as a CLI. Open source and self-hostable, or available via the author’s cloud service.

      What we dislike: Publicly available by default, but has options to turn off signups or just put it on a private network.

    8. πŸ”— Ampcode News Portals into Orbs rss

      For remote development in orbs to be better than local dev, you need to be able to easily try out the agent's changes in your app, with live reloading. No VPN, no port juggling, and no waiting for preview deployments.

      Today, we're shipping portals, which let you access anything running in an orb that listens on a port and speaks HTTP.

      All you need to do is ask Amp: show me in a portal. Or words to that effect.

      Obviously, you can use portals to try out the features or fixes made by the agent:

      You can also annotate and comment on anything:

      But you can also have the agent build ad-hoc web apps for you to debug or understand the system:

      Portals are accessible to anyone with access to the thread. They go to sleep and wake along with your orb.

      Make a thread multiplayer with on the web, and your team members can also make changes and see them live in the portal.

      Services

      When you say show me in a portal, the agent knows to create or look for a .amp/services.yaml file and then run amp orb services <ensure|start> to run your app and expose it via HTTPS. Your app needs to respect the PORT and PUBLIC_URL env vars it's given.

      Amp will handle all of this for you; agents are really good at that kind of stuff. Commit the .amp/services.yaml file and Amp's changes to your dev server config so it's faster next time.

      What about my app's sign-in flow? What about ...?

      You don't want to waste time signing into your dev server each time. We recommend adding a way for humans and agents to bypass sign-in flows (such as username/password or OAuth) in your dev server, by visiting a URL like:

      https://localhost:2000/__dev/log-me-in/{email}?returnTo={path}
      

      We've documented this pattern and more in the portals documentation. Also see Putting an Agent in an Orb for more about how we're using portals. Tell us how else you and your agents are using portals!

  2. August 05, 2026
    1. πŸ”— HexRaysSA/plugin-repository commits sync repo: +1 plugin, +1 release rss
      sync repo: +1 plugin, +1 release
      
      ## New plugins
      - [ida-codemode](https://github.com/hexrayssa/ida-codemode) (0.2.0)
      
    2. πŸ”— r/LocalLLaMA you can now buy llm's at your local supermarket rss

      you can now buy llm's at your local supermarket | submitted by /u/ECrispy
      [link] [comments]
      ---|---

    3. πŸ”— Evan Schwartz Notes from the AI Coding Transition rss

      Like many other software engineers, my coding workflow has changed dramatically since the start of 2026. And like many others, I've felt some mix of awe, grief, frenetic productivity, atrophying skills, and understanding less while shipping more. In this moment where the field is undergoing this rapid shift, I've found it helpful to read others' takes on their processes, what they're doing to keep their brains engaged, and their genuinely mixed feelings.

      Before writing up my own thoughts, I went back through the relevant essays and blog posts from the last ~7 months to find the ones that resonated with me the most. Below are the posts that I especially liked and lines that stuck out from them, either because they gave me some idea about how I might want to use AI or just because they had a particularly incisive description of our field's situation. (Quotes are exact and the bold text is my added emphasis.)

      If you've read others that you thought were particularly on point, please send them my way!

      February 7, Nolan Lawson:

      I didn’t ask for the role of a programmer to be reduced to that of a glorified TSA agent, reviewing code to make sure the AI didn’t smuggle something dangerous into production.

      If you would like to grieve, I invite you to grieve with me. We are the last of our kind, and those who follow us won’t understand our sorrow. Our craft, as we have practiced it, will end up like some blacksmith’s tool in an archeological dig, a curio for future generations.

      February 9, Margaret Storey:

      Even if AI agents produce code that could be easy to understand, the humans involved may have simply lost the plot and may not understand what the program is supposed to do, how their intentions were implemented, or how to possibly change it.

      Peter Naur reminded us some decades ago that a program is more than its source code. Rather a program is a theory that lives in the minds of the developer(s) capturing what the program does, how developer intentions are implemented, and how the program can be changed over time.

      Cognitive debt tends not to announce itself through failing builds or subtle bugs after deployment, but rather shows up through a silent loss of shared theory. As generative and agentic AI accelerate development, protecting that shared theory of what the software does and how it can change may matter more for long-term software health than any single metric of speed or output.

      February 15, Simon Willison:

      the sense of psychological ennui leading into existential dread that many software developers are feeling

      Simon: All of the chess players and the Go players went through this a decade ago and they have come out stronger.

      February 15, Tom Wojcik:

      The Shen-Tamkin study identified six distinct AI interaction patterns among developers. Three led to poor learning: full delegation, progressive reliance, and outsourcing debugging to AI. Three preserved learning even with full AI access: asking for explanations, posing conceptual questions, and writing code independently while using AI for clarification. The differentiator wasn’t whether developers used AI, it was whether they stayed cognitively engaged.

      metrics don’t capture what’s happening underneath. The mental fatigue of reviewing code you didn’t write all day. The boredom of babysitting an agent instead of solving problems. The slow, invisible erosion of the hard skills that made you good at this job in the first place. You stop holding the architecture in your head because the agent handles it. You stop thinking through edge cases because the tests pass. You stop wanting to dig deep because it’s easier to prompt and approve. There’s no spark in you anymore.

      February 25, Ivan Turkovic:

      Here is something that gets lost in all the excitement about AI productivity: most software engineers became engineers because they love writing code.

      Not managing code. Not reviewing code. Not supervising systems that produce code. Writing it. The act of thinking through a problem, designing a solution, and expressing it precisely in a language that makes a machine do exactly what you intended. That is what drew most of us to this profession. It is a creative act, a form of craftsmanship, and for many engineers, the most satisfying part of their day.

      this is different because it is not asking engineers to learn a new way of doing what they do. It is asking them to stop doing the thing that made them engineers in the first place and become something else entirely.

      a mid-level backend engineer is now expected to understand product strategy, review AI-generated frontend code they did not write, think about deployment infrastructure, consider security implications of code they cannot fully trace, and maintain a big-picture architectural awareness that used to be someone else’s job.

      That is not empowerment. That is scope creep without a corresponding increase in compensation, authority, or time.

      From my experience building and scaling teams in fintech and high-traffic platforms, I can tell you that role expansion without clear boundaries always leads to the same outcome: people try to do everything, nothing gets done with the depth it requires, and burnout follows.

      Now the only limit is your cognitive endurance. And most people do not know their cognitive limits until they have already blown past them.

      Set explicit boundaries around role scope. If you are asking engineers to take on product thinking, planning, and risk assessment in addition to their technical work, name it. Define it. Compensate for it. Do not let it happen silently and then wonder why your team is burned out.

      talk about what you are experiencing. The isolation of feeling like you are the only one struggling with this transition is one of the most damaging aspects of the current moment. You are not the only one.

      February 27, Carson Gross:

      Computer programming is, fundamentally, about two things:

      • Problem-solving using computers
      • Learning to control complexity while solving these problems

      I have a hard time imagining a future where knowing how to solve problems with computers and how to control the complexity of those solutions is less valuable than it is today, so I think it will continue to be a viable career even with the advent of AI tools.

      I try not to use LLMs to generate full solutions that I am going to need to support.

      March 11, Xe Iaso:

      Whenever I have Claude do something for me, I feel nothing about the results. It feels like something happens around me, not through me.

      the default output has no soul. It's correct. It's competent. It's fine. And "fine" is the enemy of everything I care about as a writer and an engineer.

      March 15, Colin Brek:

      find it hard to believe that supervising a set of agents is going to lead to an optimal flow experience, because we are more passive, it doesn’t stretch our abilities in the same way, and it requires far less concentration. Will we find flow elsewhere? Solving problems and delivering value will always be rewarding, but I wonder if the optimal flow experience offered by programming has, for the most part, disappeared forever, and many of us will simply find less enjoyment at work.

      March 25, Mario Zechner:

      You realize you can no longer trust the codebase. Worse, you realize that the gazillions of unit, snapshot, and e2e tests you had your clankers write are equally untrustworthy. The only thing that's still a reliable measure of "does this work" is manually testing the product. Congrats, you fucked yourself (and your company).

      You let them run free, and they are merchants of complexity. They have seen many bad architectural decisions in their training data and throughout their RL training. You have told them to architect your application. Guess what the result is?

      An immense amount of complexity, an amalgam of terrible cargo cult "industry best practices", that you didn't rein in before it was too late.

      All of this compounds into an unrecoverable mess of complexity. The exact same mess you find in human-made enterprise codebases. Those arrive at that state because the pain is distributed over a massive amount of people. The individual suffering doesn't pass the threshold of "I need to fix this". The individual might not even have the means to fix things. And organizations have super high pain tolerance. But human-made enterprise codebases take years to get there. The organization slowly evolves along with the complexity in a demented kind of synergy and learns how to deal with it.

      With agents and a team of 2 humans, you can get to that complexity within weeks.

      And I would like to suggest that slowing the fuck down is the way to go. Give yourself time to think about what you're actually building and why. Give yourself an opportunity to say, fuck no, we don't need this. Set yourself limits on how much code you let the clanker generate per day, in line with your ability to actually review the code.

      March 27, Matheus Lima,

      When people say β€œtaste,” what they actually mean is experience. Pattern recognition built up over years of doing the work. But calling it β€œtaste” instead of β€œexperience” does something subtle and harmful: it makes a learnable skill sound like a gift.

      May 1, Sid Sundharam:

      Doing tasks manually naturally builds up the context required for the decisions involved later because you have time to process everything along the way and construct your mental model of the project's structure.

      This process requires more attention and context switching, along with way more decisions per hour. Making constant architectural, big-picture decisions while overseeing the work of a cracked junior dev is fundamentally harder than executing standard programming tasks yourself.

      Decision fatigue is, in my opinion, the next invisible friction point for developers.

      May 6, Simon Willison:

      The problem is that as the coding agents get more reliable, I’m not reviewing every line of code that they write anymore, even for my production level stuff.

      But I’m not reviewing that code. And now I’ve got that feeling of guilt: if I haven’t reviewed the code, is it really responsible for me to use this in production?

      There’s an element of the normalization of deviance hereβ€”every time a model turns out to have written the right code without me monitoring it closely there’s a risk that I’ll trust it at the wrong moment in the future and get burned.

      May 27, Vardan Torosyan:

      When you stop fighting with hard problems directly, the mental models fade. You stop building intuition. You start pattern-matching on outputs instead of reasoning from first principles. And the worst part –> you don’t notice it happening. The code still ships. The PR still merges. Everything looks fine until the incident at 2am where you genuinely cannot reason about what the system is doing because you never really had to learn it.

      There’s a good analogy here from aviation. Pilots trained heavily on autopilot gradually lose the ability to fly manually and this isn’t theoretical, it’s contributed to real crashes.

      I think judgment is built from a specific loop: you form a view, you commit to it, you see what happens, and you update. That cycle, repeated enough times, is what builds calibration. The problem with AI is that it short-circuits the first step. You skip forming your own view and go straight to evaluating someone else’s. Do that enough and the muscle atrophies and again, not dramatically, just quietly. You become a better reviewer and a worse thinker.

      • Write before you look. Before opening a tool, before asking the model, write down what you think. Not a design doc necessarily, just your current understanding of the problem, your instinct about the solution, where you think the tricky part is. Even a few sentences. This forces you to articulate your reasoning rather than pattern-match on someone else’s output. It’s also surprisingly useful as a diagnostic: if you can’t write anything, you probably don’t understand the problem well enough to evaluate any answer.
      • Form a view before reading the suggestion. When reviewing AI-generated code or design, read it critically with your own opinion already in hand. What would you have done? Where does this differ? Why might the model have gone this direction and is it right? This sounds small but it’s the difference between passive consumption and active evaluation. One builds judgment, the other just builds familiarity with AI output.

      May 27, Matheus Lima,

      I did the software engineering equivalent of forwarding an email with β€œthoughts?” and then going to lunch.

      The job is the part where your fucking brain has to be in the room.

      You paste the issue into the machine before reading it. You accept the explanation before forming your own. You create a PR before even understanding what the problem you’re fixing is (!). You request a PR review before reading the diff. You merge because the checks passed and the reviewer approved it and the whole thing smells like progress.

      here’s the new hard rule I’m following after this β€œincident”: if I still can’t explain the change, I can’t ship it. No exceptions.

      June 4, Sean Goedecke:

      many software engineers labor under a delusion that their job is to be excellent at their craft. Of course, wanting to be an excellent programmer is not a delusion; it is a completely legitimate value to hold, and a legitimate purpose to pursue. It’s just not what you’re paid to do at work. Your job, unfortunately, is producing shareholder value. This delusion has been punctured by the end of ZIRP, and again more recently by the rise of AI coding.

      June 9, Candost:

      Today, the ownership mindset defines the role.

      Although unintuitive, limiting the amount of work that runs in parallel is actually producing better outcomes and outputs. I believe the idea of WIP limits must be emphasised more strongly than before.

      moving from building features in parallel to building a single feature end-to-end faster.

      June 12, Niko Uusitalo:

      But for me, prolonged use becomes insidious. It's easy to become lazy and hand over thinking to the machine in looking for the next hit of cognitive offload when coding becomes even a smidge difficult. Why type your search and read half a short blog post to understand the problem when the same keystrokes give you the (possible) answer right there and then.

      June 17, Elio Struyf:

      When you ask a person to do something, you don’t expect them back in five minutes saying it’s done and ready for the next task. With an agent, that’s exactly what happens. Done. Next. Done. Next.

      There’s no breathing space. There’s always a next thing to think about. The work used to have a rhythm to it. You’d struggle, you’d get stuck, you’d finally figure it out, and there was this moment of joy when it clicked. Hours in the code, and then done. Figuring it out was the whole reward.

      That’s what AI can quietly take from me. Not the joy itself, but the sense that the thing was mine, which is where the joy was coming from all along. It hands me the finished thing, the finished thing works, and somewhere in there, I stop being the person who made it and become the person who approved it.

      AI didn’t take the joy out of coding, I gave it away.

      June 22, Vardan Torosyan:

      a quieter admission: the work isn’t teaching me much anymore, and it’s stopped being fun.

      That’s a description of becoming a manager. What AI did was give every engineer a small team of tireless, fast, occasionally-wrong direct reports. And with the team came the manager’s problem. The discomfort engineers are feeling right now isn’t an AI problem. It’s a delegation problem, and delegation is the oldest unsolved problem in our discipline.

      The good news: it’s not unsolved because nobody tried. Managers have been failing at it and slowly adapting for decades.

      What is in your control is small and it is everything: where you point your attention, what standard you hold, what you decide not to do, and whether you’re honest about which is which. The whole reason β€œthere is too much” feels like drowning is that we keep trying to exert control over the size of the ocean. You can’t. You can only decide where to swim.

      1. Separate ownership from authorship....You can own code you didn’t write. You cannot own code you refuse to understand. Those are different statements, and the gap between them is the whole job.
      2. Decide what you must understand deeply - then triage the rest without guilt.
      1. The discomfort is the job, not a bug in it. Acting on incomplete information, sitting with the unease of not-fully-knowing, and committing anyway - that is judgment. Managers don’t feel more certain than you; they’ve made peace with feeling uncertain and moving regardless....
      2. Keep something you understand deeply....
      3. Track what you’re learning, not just what you’re shipping....

      June 23, Armin Ronacher:

      I want to be able to explain what the system does without first having to ask a clanker to explain it to me.

      Present-day models tend to produce code that is too defensive, too complex, too local in its reasoning. They avoid strong invariants. They add fallbacks instead of making bad states impossible. They duplicate code, invent bad abstractions, and paper over unclear design with more machinery.

      If each iteration adds another small defense, the system slowly becomes less understandable while appearing more robust.

      we may no longer understand the whole system in the same way. We treat it, we monitor it, we stabilize it, but we do not necessarily comprehend it.

      Some domains will punish sloppiness and demand trust and responsibility, but a lot of software lives in a world where raw speed, quick experimentation, and vast coverage matter enormously.

      Better visualizations of changes or orchestration or agents will not restore our understanding. Either we need to find clever ways to jolt the human back into the loop and make the changes of the loops legible long term, or we need to find better ways to compose these ever more complex systems.

      June 28, Andrew Diamond:

      In the old workflow, the creative process happened mostly in your mind. In the new process, you supervise the creative process that unfolds inside the AI’s internal machinations.

      Now, let’s put the historical novelist in the position of the software developer. She gets a call from her publisher saying they’ve found a way for her to bring four books to market each year instead of one book every two years. They’ve recruited a bunch of top-notch high school and college students who can each crank out five pages a day of competent writing for dirt cheap. The publisher wants the historical novels to maintain the original writer’s level of excellence, or to at least be close, so they’re retaining her services as an editor.

      The novelist’s job is now to edit the work of the students, each of whom has been carefully prompted to write pages that should, with a little work, be stitched together into coherent chapters.

      Anyone who has ever graded the work of high school and college kids knows that this is generally not rewarding work. If you’ve ever had to grade a hundred papers in a week, you know what a grind that is.

      The novelist, like the software engineer, is no longer deeply engaged in her work. Editing is not creating. You do not give yourself over to your imagination. You do not immerse your mind and feelings in the process of invention. Instead, you’re rooting out problems, trying to clean up clumsy wording and redundant descriptions instead. The flow state is gone. You are now a cog in a larger process that doesn’t really value your creativity or your need to exercise it.

      Worse still–and I have felt this personally after months of reviewing AI-generated code–your skills drop off sharply. When a new issue arises–a feature to be implemented, or a tricky bug to fix–the idea of wasting several hours on it feels insulting. Why should I dig through all that code when Claude can locate the bug in five minutes and start drafting a fix?

      But I think that creative people choosing to hand over their most imaginative, flow-state thinking to an army of bots will be a mistake in the long run.

      July 1, Igor Kulman:

      The feature gets delivered, but I do not really feel like I built it.

      Maybe this is just another evolution of our profession and in a few years it will feel completely normal.

      Or maybe one day we will realize that somewhere along the way we stopped programming and nobody really noticed.

      July 6, Vini from GolemUI

      β€œI’m not sure I can do my daily job without Claude”

      The cost was never writing the code. The cost was owning it.

      A fix you cannot judge, in code nobody on your team understands, is not maintenance; it’s another spin of the roulette wheel. And when the bug comes back wearing a different hat, who do you escalate to?

      Your vibe-coded grid has no changelog, no support contract, and no team whose reputation depends on it. AI makes touching the code cheap; it does not make answering for it cheap.

      July 9, Rushabh Mehta:

      we are yet to see β€œmind blowing” software being churned out showing that it is still hard to build great software purely with agents. Coding using models can take you from 0 to 1 very fast. But what about 1 to 10, 10 to 100?

      July 11, Sean Goedecke,

      In sufficiently large codebases, everyone operates with an incorrect theory of the program.

      Like many software tools, LLMs are a double-edged sword: they make it harder to construct a detailed mental theory of the software, but they allow you to build a partial theory quickly and they can help you leverage that partial theory more effectively. This is a complex tradeoff that I’m still thinking about.

      July 13, antirez:

      our field is evolving in an incredible and painful (but also joyful) direction

      if you control the ideas of your software, looking at the code itself is suboptimal and often pointless.

      July 13, Armin Ronacher:

      large software projects have never been limited only by how quickly an individual can produce code. They are limited by how well people can coordinate their understanding of the system they are changing.

      The shared language of a software project is not English or Python but it is the common understanding of what its concepts mean, where the boundaries are, which invariants matter, who owns what, and why the system has the shape it does.

      Before agents, some of this shared understanding was maintained by friction....Some of it was the process by which your understanding became mine, and by which both of us discovered whether we still agreed about how the system worked.

      July 24, Sean Goedecke:

      The most important skill in prompting is expertise in the domain you’re prompting for.

      A good illustration of this is Terence Tao’s conversation with ChatGPT about the recently-discovered counterexample to the Jacobian Conjecture. This is not the same ChatGPT I talk to! I couldn’t get to where Tao gets, even with unlimited tokens to burn.

      There’s a lot to learn about good prompting from Tao’s conversation. Here are a few observations:

      • Tao’s messages are very short and to-the-point. He doesn’t respond point-by-point to the model, just to the gist
      • The model outputs are much more concise than when I try and talk to GPT-5.6 Sol about mathematics. By signalling expertise, Tao shunts the model into β€œtalking-to-mathematicians” mode, not β€œexplaining-to-amateurs” mode
      • Tao pushes back when the model’s responses look wrong, but he doesn’t directly contradict; instead, he says things like β€œthis looks more complex than I was hoping for”
      • Tao makes several leaps and suggestions himself. He almost never takes the model’s advice about where to go next

      July 24, Piotr Chmolowski:

      So why does software keep getting worse across the board?

      The bar for β€œuser experience” has kept rising, but everything has become increasingly fragile.

      July 25, Jacob O'Bryant:

      LLMs are useful for producing code that meets easily and objectively verifiable acceptance criteria which you provide explicitly

      I've found this simple instruction to vastly improve LLMs' output: "Never write READMEs, docstrings, or comments. I will write those myself later. And yes, I really mean this."

    4. πŸ”— Simon Willison One-shotting a Raccoon Heist game using Claude Fable 5 rss

      Back in 2024 I tweeted screenshots of a game concept generated by GPT-3 and some concept "art" created using DALL-E. Today, on the fourth anniversary of that tweet, I decided to see if Claude Fable 5 (running in Claude Code for web) could build the entire game from the content of that tweet. It did a pretty good job of it!

      You can play the game here. Here's the GitHub repo, and a short video demo:

      How I built this

      This is the August 5th, 2022 tweet:

      Simon Willison @simonw - New hobby: prototyping video games in 60 seconds using a combination of GPT-3 and DALL-E Here's "Raccoon Heist". Two images - the first is a screenshot of the GPT-3 playground, prompt below. On the right is a very clearly DALL-E generated image of an almost-isometric 3D computer game, with two raccoons sneaking down a street past a futuristic looking building, looking like they want to steal something.

      My GPT-3 prompt back then was:

      Write a detailed product description of a computer game where a team of raccoons go on heists.

      This was in the text completion days, where you asked GPT-3 to complete the rest of the text. It completed:

      In "Raccoon Heist", you and your team of thieving raccoons are tasked with pulling off a series of daring heists. From robbing banks to stealing priceless art, no job is too big or too small for your furry crew. You'll need to use your wits and your skills to avoid the police and make a clean getaway with the loot. With exciting gameplay and a charming cast of characters, "Raccoon Heist" is the perfect game for anyone looking for a light-hearted caper.

      My prompt to DALL-E was short:

      Screenshot from a video game where a team of raccoons go on a heist

      Today's experiment: can I dump those screenshots into Fable 5 with a prompt telling it to write a game, then leave it to its own devices and get a working game at the end?

      Setting Claude Code for web up to use GitHub Pages

      A frustrating thing about Claude Code for web is that it can be hard to test what it's working on while it's still working.

      I've been using GitHub Pages to work around that limitation, and found it to work really well.

      Here's my process:

      1. Create a new repository for the project at https://github.com/new - this can be public or private, the trick works equally well for both.
      2. Start a Claude Code for web session, in the Claude iPhone or Desktop apps or in the browser at https://claude.ai/code
      3. Tell Claude what to work on, and encourage it to commit an index.html page as quickly as possible. This will create a branch with a name like claude/3d-raccoon-heist-game-50n293
      4. Navigate to the Settings -> Pages area for the repository (github.com/simonw/raccoon-heist/settings/pages in my case), select "Deploy from a branch", pick the branch name, and hit Save.

      That's all it takes! Within about 30 seconds of each push the latest content will be visible at yourname.github.io/your-repo/.

      If you do this with a private repo, anyone who can guess the name of the repo will be able to view the published content. I don't worry much about this myself.

      The Fable 5 prompt

      Here's the prompt I gave Fable 5 (written in the notes app on my phone - this entire project was conducted on mobile). I accompanied it with the two images from the original tweet.

      Build this 3D game, for the browser.

      This repo is configured to serve static files so make sure there is an index.html that loads everything else.

      Make sure it is mobile-friendly (touch controls, works well on small screens).

      You have an OpenAI API key and access to their image generation model APIs, use that for textures to use with your 3D models. Docs here: https://developers.openai.com/api/docs/guides/image-generation - use gpt-image-2

      Work independently - do not ask me to make any further design decisions. Make sure the game is fun, a little surprising, has good raccoon heist vibes, and is visually pleasing.

      Commit and push as often as possible so I can preview your work - start with an index.html that presents a title screen, then build from there.

      Append to a notes.md file as you work, including your changes to that as part of every commit.

      I didn't make any technology choices. I assumed (correctly) that it would probably use Three.js based on previous experiments.

      Giving Claude access to an OpenAI key turns out to work really well for filling in gaps in its capabilities - in this case we needed some way to generate images to use as textures. Fable is very good at prompting image generators!

      I said "Work independently - do not ask me to make any further design decisions" because I wanted to see if it could produce a full, working game without any further input from me.

      I also said "Commit and push as often as possible so I can preview your work". When you use Claude Code in the Claude iPhone app you give it a GitHub repository and it works in a branch. Telling it to "push as often as possible" means commits start landing in that branch straight away.

      I like asking for notes.md as a bit of added flavor - here's that finished file, and the entry it made when it added the dog:

      New escalation: from night 3 the yards get a patrolling guard dog β€” a low-poly brown hound with a spiked red collar and a wagging tail. It wanders between random spots, and within 12 units it catches your scent and tracks you by smell (line of sight is irrelevant β€” it's all nose, shown by a πŸ‘ƒ over its head and barking). It gives up if you open a 17-unit gap. Getting caught messages are now source-specific: guard / headlights / hound. Verified wander β†’ track β†’ caught with an automated test.

      Reviewing the transcript

      You can access the Claude Code shared session, and I also used my claude-code-transcripts tool to export my own HTML version which you can find here.

      Fable started with an index page, vendored a copy of Three.js, then wrote its own gen_textures.py script (copy here).

      It generated the textures and spot-checked them to make sure they looked OK. The metal.jpg file it generated for the trash can looks like this, though I don't think it was applied exactly right in the game itself:

      A game texture atlas of dark blue-grey riveted metal panels, showing a circular hatch with a handle in the top left, ribbed corrugated panels across the middle, a plain circular plate bottom left, and flat banded strips at top and bottom. No text visible.

      Then it built out the first basic version of the game, then decided to "smoke-test in the pre-installed Chromium" using Playwright. This meant it could take screenshots of its own work and eyeball them. It did that for both desktop and mobile widths of the page, then noticed that the raccoon was invisible at mobile widths, so it fixed that:

      The raccoon, dumpster hideout, and both crew raccoons are now perfectly visible on mobile. Committing this critical fix.

      It decided to generate a title screen, which it did using this gen_title.py script. Here's the gpt-image-2 prompt it used for that:

      Video game key art, low-poly 3D render style, moody nighttime scene: a cute low-poly raccoon wearing a tiny black burglar mask sneaking on its hind legs carrying a glowing gold coin, next to a tipped-over metal trash can, suburban house with warm glowing windows in the background, deep blue night, full moon, fireflies, cinematic rim lighting, charming heist caper mood. No text, no words, no logos.

      And the resulting image (which Claude thought was "gorgeous") - though I note that when it's shown on desktop it gets cropped to just the top third without the raccoon!

      Polygon raccoon holding a gold coin next to an overturned trash can, a house and the moon in the background.

      Then my favorite change: it added the dog:

      export function makeDog() {
        const g = new THREE.Group();
        const BROWN = 0x8a6440, DARK = 0x5e4128;
        const body = new THREE.Mesh(new THREE.SphereGeometry(0.42, 10, 8), M(BROWN));
        body.scale.set(0.9, 0.8, 1.5);
        body.position.y = 0.55;
        body.castShadow = true;
        g.add(body);
        const head = new THREE.Mesh(new THREE.SphereGeometry(0.3, 10, 8), M(BROWN));
        head.position.set(0, 0.85, 0.62);
        g.add(head);
        const snout = new THREE.Mesh(new THREE.SphereGeometry(0.16, 8, 6), M(DARK));
        snout.scale.set(0.9, 0.7, 1.3);
        snout.position.set(0, 0.76, 0.9);
        g.add(snout);
        const nose = new THREE.Mesh(new THREE.SphereGeometry(0.06, 6, 6), M(BLACK));
        nose.position.set(0, 0.78, 1.08);
        g.add(nose);
        for (const s of [-1, 1]) {
          const ear = new THREE.Mesh(new THREE.SphereGeometry(0.12, 6, 6), M(DARK));
          ear.scale.set(0.7, 1.3, 0.5);
          ear.position.set(0.2 * s, 1.08, 0.55);
          g.add(ear);
          const eye = new THREE.Mesh(new THREE.SphereGeometry(0.05, 6, 6), M(0x1a1a1a, { emissive: 0x331111 }));
          eye.position.set(0.13 * s, 0.92, 0.86);
          g.add(eye);
        }
        const tail = new THREE.Mesh(new THREE.CylinderGeometry(0.05, 0.09, 0.5, 6), M(DARK));
        tail.position.set(0, 0.8, -0.62);
        tail.rotation.x = 0.8;
        g.add(tail);
        // spiked collar
        const collar = new THREE.Mesh(new THREE.TorusGeometry(0.22, 0.05, 6, 12), M(0xc0392b));
        collar.position.set(0, 0.78, 0.5);
        collar.rotation.x = Math.PI / 2.4;
        g.add(collar);
        const legGeo = new THREE.CylinderGeometry(0.07, 0.09, 0.34, 6);
        const legs = [];
        for (const [x, z] of [[-0.22, 0.35], [0.22, 0.35], [-0.22, -0.35], [0.22, -0.35]]) {
          const leg = new THREE.Mesh(legGeo, M(DARK));
          leg.position.set(x, 0.17, z);
          g.add(leg);
          legs.push(leg);
        }
        let phase = Math.random() * 10;
        return {
          group: g,
          animate(dt, speed) {
            phase += dt * (3 + speed * 10);
            const amp = Math.min(0.6, 0.1 + speed * 0.6);
            legs[0].rotation.x = Math.sin(phase) * amp;
            legs[3].rotation.x = Math.sin(phase) * amp;
            legs[1].rotation.x = -Math.sin(phase) * amp;
            legs[2].rotation.x = -Math.sin(phase) * amp;
            tail.rotation.z = Math.sin(phase * 1.5) * 0.4;
            body.position.y = 0.55 + Math.abs(Math.sin(phase)) * 0.04 * (0.3 + speed);
          },
        };
      }

      And did a round of testing on it using Playwright, including another screenshot.

        // walk near the dog
        await page.evaluate(() => { const d = window.__rh.dog; window.__rh.teleport(d.x + 6, d.z); });
        await page.waitForTimeout(2000);
        info = await page.evaluate(() => JSON.stringify({ dog: window.__rh.dog, state: window.__rh.state, player: window.__rh.debug().player }));
        console.log('after approach:', info);
        await page.waitForTimeout(3000);
        info = await page.evaluate(() => JSON.stringify({ dog: window.__rh.dog, state: window.__rh.state }));
        console.log('after chase:', info);
        await page.screenshot({ path: __dirname + '/shot-dog.png' });

      Screenshot of the game. Night 3, the raccoon is in the middle intersecting with the dog. A message reads Busted! The Guard shooed you off! The screen has a red tinge around the edges.

      It made a few more tweaks, then declared itself done:

      Raccoon Heist is built, tested, and pushed β€” 7 commits on claude/3d-raccoon-heist-game-50n293, all verified with automated Playwright playthroughs on desktop, portrait-phone, and landscape-phone viewports.

      The game: You're a masked raccoon sneaking out of your crew's dumpster hideout into a moonlit cul-de-sac. Grab coins, gems, rings, donuts, and fish (they visibly stack on your back and slow you down), then waddle home and bank them before dawn. Each night raises the goal and the heat: night 1 has one flashlight-sweeping guard, night 2 has two, night 3 adds a scent-tracking hound that ignores line-of-sight entirely. A police cruiser sweeps the street with headlights, homeowners randomly peek out of windows, a seagull periodically dive-bombs your unclaimed loot, pizza slices trigger a 6-second speed FRENZY, and a rare golden TV is worth 120 points if you can haul its weight home. Win ranks: TRASH PANDA ⭐ β†’ CAT BURGLAR ⭐⭐ β†’ MASTER OF DISGUISE ⭐⭐⭐, with your best run saved to localStorage.

      How it's built: Vendored Three.js (no CDN), procedural low-poly characters, and a procedural WebAudio soundtrack (sneaky walking-bass jazz plus all sound effects β€” zero audio files). All seven ground/wall textures and the title-screen hero art were generated with gpt-image-2 and committed as static assets, so the deployed game makes no API calls. Mobile gets a dynamic touch joystick (appears wherever you touch) plus a DASH button; desktop uses WASD/arrows and Space.

      Testing caught two real bugs worth mentioning: the canvas rendered at 2Γ— size on any real phone (a cssText assignment was wiping Three.js's inline sizing β€” desktop DPR-1 tests masked it completely), and the win screen's star-rating div inherited the title screen's full-screen .stars CSS and silently swallowed every tap on the "next night" button. Both are fixed and regression-tested, along with pickup, banking, chase/caught, dawn, night progression, and lose/retry flows.

      notes.md has the full build log. The game is live on the branch β€” just serve the repo root and open index.html.

      Is the game any good?

      It's an impressive starting point, but it's not a good game.

      You move your raccoon around a yard collecting items - donuts, fish, gold coins, jewels - while avoiding guards with flashlights and, in later levels, a dog. You have a limited carrying capacity, and once that's full you need to drop stuff off at the dumpster. If you pick up a pizza slice you get a temporary speed boost.

      There are no team mechanics at all - there are two other static raccoons next to the dumpster but they're purely decoration.

      It gets slightly more challenging as the levels progress - the dog introduced in level 3 is the most interesting new mechanic - but it's very, very easy to beat. It's also pretty boring - each night has a fixed duration and you can collect all of the items and then have nothing else to do while waiting for the dawn.

      I was impressed by the implementation. It's fully 3D, there are trash cans, the flashlight illumination cones are fun, and it has a reasonably coherent visual style. It works on mobile. The music ("a procedural WebAudio soundtrack (sneaky walking-bass jazz plus all sound effects β€” zero audio files)" according to Claude) is simple but feels about right.

      As a finished game project, it's mediocre. As a starting point from a single prompt I think it's very impressive.

      I've vibe coded up quite a few games now. They've all been deeply disappointing from a gameplay perspective - it turns out designing games that are fun remains a uniquely human trait, and one which requires significantly more skill and experience than either Claude or I can bring to bear.

      That said, I thoroughly recommend tinkering with game development projects as a way to explore the capabilities of agents. It's a fun, low-risk way to try out new things. If you stick at it long enough you might even produce something that's worth playing!

      You are only seeing the long-form articles from my blog. Subscribe to /atom/everything/ to get all of my posts, or take a look at my other subscription options.

    5. πŸ”— backnotprop/plannotator v0.26.1 release

      Follow @plannotator on X for updates


      Missed recent releases? Release | Highlights
      ---|---
      v0.26.0 | Edit Mode (suggest by editing the diff), Guided Review virtualization, colorblind theme, safe uninstall, installer opt-outs, OpenCode 2 support
      v0.25.1 | Codex no longer launches on review open, annotate-last follows the live conversation, pi-todos mirror, Claude Opus 5, abandoned-gate dismissal
      v0.25.0 | Vim keyboard controls, Approve with Notes, scriptable annotate gates, persistent Guided Reviews, memory and file-watching hardening
      v0.24.2 | Annotate YAML/JSON/TOML config files, XDG data directory support, Codex model catalog update, Cursor sandbox escape hatch
      v0.24.1 | Annotate accepts parent-relative ../ file paths
      v0.24.0 | PR/MR artifact gallery, GitButler review support, port ranges, expanded comment editor, OpenCode + Pi fixes
      v0.23.1 | Startup no longer hangs on large or slow directory trees, Ask AI input stays visible after long responses
      v0.23.0 | Plan approval fix for Claude Code 2.1.199+, annotate mode version diff, binary-only --minimal install, reviews post without attribution
      v0.22.0 | Git-status "All changes" default review view, Commits panel with per-commit diffs, Guided Review, Pi + GitHub Copilot CLI review engines
      v0.21.4 | Markdown math rendering, PR Overview panel with annotatable description and comments, agent instructions in code review, media parsing fixes
      v0.21.3 | File comments in code review, unified click-to-highlight comments, VS Code clipboard/keyboard bridge, Codex Ask AI on app-server transport, CLI subcommand help


      What's New in v0.26.1

      A single-fix patch: code review works again in GitButler workspaces running GitButler CLI 0.22.0. Because this patch landed a day after v0.26.0, the full v0.26.0 feature notes are included below; if you are updating from v0.25.x, everything in both sections is new to you.

      GitButler 0.22.0 compatibility

      GitButler's CLI changed its JSON output flag twice this year. Their June change removed --json in favor of a global --format json, which is the syntax Plannotator's GitButler integration used and the one GitButler 0.21.x accepts. Their July cleanup then reverted it: GitButler 0.22.0 accepts only --json and rejects --format outright, so opening a review in a GitButler workspace on 0.22.0 failed immediately with a contract error.

      Plannotator now probes capability instead of assuming a spelling. It tries --format json status first, and only when that fails with the specific unexpected-argument rejection does it retry once with --json status. Real status failures never retry and still fail loudly. The accepted spelling is remembered for the session, so 0.22.0 installs pay the failed probe once. If a future GitButler rejects both spellings, the error names both and the minimum supported version. The fix lives in the shared GitButler core, so the Bun and Pi runtimes both get it.


      What's New in v0.26.0

      v0.26.0 introduces Edit Mode, makes Guided Review fast on large changesets, adds a colorblind theme and a safe uninstall command, and hardens the installer, the review server, and the OpenCode plugin. Thirty-two PRs shipped in this release; seven came from external contributors plus one co-authored port, and four contributors landed their first PR.

      Edit Mode: author suggestions by editing the code

      A new experimental way to give review feedback: click Edit on a file in the all-files review view and fix the code right there in the diff. When you finish, your net changes become ordinary suggestion annotations, the same shape the suggestion editor produces, with the original code in a fenced Replaces: block and your replacement in Suggested code: so the applying agent can validate the anchor. You can also select text mid-edit and turn the selection into an annotation. The browser never writes to your files on disk; the agent applies the suggestions from your feedback.

      Edit Mode is off by default behind Settings > Editor > "Edit Code to Suggest". A one-time announcement dialog introduces the feature with an embedded screen recording of the flow and an explicit enable switch. The switch is deliberate design: the first draft used a primary "Turn it on" button, which reads as a generic continue and invites reflex clicks, so the opt-in became a switch you must consciously flip before the neutral Done button applies it.

      Two fixes landed before release from our own QA pass: Discard now repaints the pristine diff immediately instead of leaving edited pixels on screen until an async rerender, and the same repaint removes a brief flash of stale content on the Suggest path.

      Guided Review handles large changesets

      Guided Review used to mount a full code viewer for every file in the guide. On a large guide that meant hundreds of live viewers, around a million shadow DOM elements, 770MB of heap, and scrolling at 4 frames per second, with the view taking close to a minute to open. A shared viewport coordinator now keeps at most 8 file viewers mounted at once and swaps the rest for lightweight placeholders as you scroll. The same guide now opens in around a hundred milliseconds, holds ~140MB, and scrolls at full frame rate. Section reviewed- state, annotations, and search behave exactly as before.

      Colorblind theme

      A new built-in theme designed for red-green color vision deficiency, which covers most color blindness. Additions render blue and deletions orange across diff backgrounds, gutters, indicators, and syntax highlighting, in both light and dark. The palette was tuned with CIEDE2000 color-difference measurements under simulated deuteranopia and protanopia; the worst-case separation between "added" and "removed" improves from 1.7 (indistinguishable) to 9.0 (clearly distinct). A separate tritanopia variant was evaluated and skipped on the data: the default palette already reads correctly for tritanopes.

      Safe uninstall

      plannotator uninstall removes the binary, skills, hooks, and per-agent integrations, and walks through every host it recognizes (Claude Code, Codex, OpenCode, Gemini, Kiro, and friends) before touching the binary. Your data is preserved by default: plans, history, drafts, and settings stay unless you pass --purge. --dry-run shows the full removal list without deleting anything, and --yes skips the confirmation for scripted use. Host cleanup is required, not optional: if a host's cleanup fails, the uninstall stops with manual guidance rather than leaving a half-removed install behind.

      Review server memory stays bounded on huge files

      Staging a very large text file used to balloon the review server; a 51MB file drove resident memory to around 240MB. Tracked files above 5MiB are now excluded from the rendered diff and shown as bounded stubs, the same treatment untracked files already had. A follow-up fix hardened the failure path: the original implementation probed object sizes with one git cat-file --batch- check call, and if that single call failed, every file in the review rendered as "Binary files differ" with no visible error. The size bound is now enforced by git itself through core.bigFileThreshold, so a failed probe degrades gracefully instead of blanking the review.

      Installer: opt-outs, credential-free provenance, and honest failures

      The install scripts gained a family of opt-outs: --skip-codex, --skip- gemini, --skip-kiro, --skip-opencode, and now --skip-skills, each with a matching environment variable and skipInstall config key. Skipping means the installer writes nothing for that scope and never removes what a previous install wired. Attestation verification (--verify-attestation) now works with zero GitHub credentials by fetching the attestation bundle from GitHub's public API, falling back to authenticated gh only when needed. Both designs came from a single unusually rigorous report by @astradevkin, including the discovery of the public attestations endpoint.

      Two honesty fixes shipped alongside: a failed skills checkout used to report success because of a POSIX errexit subtlety (the failure now aborts loudly, which is exactly why --skip-skills exists for offline installs), and installs on Windows PowerShell below 7.2 no longer die on git writing progress to stderr. The installer also authenticates its version lookup when a GitHub token is present, avoiding the anonymous 60-requests-per-hour rate limit on shared networks.

      OpenCode 2 support (experimental)

      Plan review now works on OpenCode 2 through a V2 plugin adapter that shares the same host-independent plan submission path as every other agent, with OpenCode 1 behavior fully preserved. The plugin's packaging also got two weight reductions worth noticing: the prerelease @opencode-ai/plugin nightly is no longer a runtime dependency (it was pulling a 95MB, 101-package closure into every install), and the bun peerDependency is gone (npm auto-installed the entire 50MB Bun binary into every consumer's node_modules; the runtime requirement now lives in engines, which is informational). Known V2 limitations are documented in the plugin README: no tool abort signal, and agent switching after approval is manual.

      Annotate understands natural language arguments

      Slash-command hosts forward whatever the user typed, so /plannotator-annotate look at notes.md please used to fail with "File not found: look". The annotate CLI now probes each word and proceeds when exactly one resolves to a real file, URL, or folder. When two or more resolve, it errors naming every candidate rather than guessing, which also fixes a silent bug: annotate a.md b.md used to open a.md and drop b.md without a word. When nothing resolves, the CLI hands off to the reading agent with the words it tried, so the agent can re-run with a concrete target. A companion fix taught the token probe to recognize URLs wrapped in punctuation.

      Additional Changes

      • Markdown reference links render. [ref][1] style links now render as real links in plans instead of raw text, closing a long-standing request (#1168 by @rNoz, closing #923 reported by @Thraka)
      • Copy feedback shortcut. Cmd/Ctrl+Shift+Y copies the review feedback to the clipboard from anywhere in code review (#1155 by @rian-dolphin)
      • Pi review ports release on shutdown. Back-to-back reviews in Pi no longer hit EADDRINUSE (#1160 by @SyahrulBhudiF, closing #1159)
      • Clipboard works in remote HTTP sessions. Copy actions fall back to the legacy clipboard path in insecure browser contexts instead of failing silently (#1174, closing #1173 reported by @quanweiZhou)
      • Partial GitLab submissions surface. When some GitLab review comments post and others fail, the result reports exactly which ones failed instead of claiming success (#1164)
      • Archive is read-only everywhere. Archive mode now rejects mutating actions server-side on both runtimes (#1171)
      • Privacy and network docs corrected. The docs now accurately describe what leaves your machine and when (#1163)
      • Sharing article redirect fixed. A legacy marketing URL no longer chains through multiple redirects (#1180)
      • @pierre/diffs upgraded to 1.3.2. Staged through 1.2.12 and a theme major, with hover and line-background rendering verified across intensities and themes (#1188, #1190, #1191)


      Install / Update

      macOS / Linux:

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

      Windows:

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

      Claude Code Plugin: Run /plugin in Claude Code, find plannotator , and click "Update now".

      OpenCode: Clear cache and restart:

      rm -rf ~/.bun/install/cache/@plannotator
      

      Then in opencode.json:

      {
        "plugin": ["@plannotator/opencode@latest"]
      }
      

      Pi: Install or update the extension:

      pi install npm:@plannotator/pi-extension
      


      What's Changed

      v0.26.1

      • fix: fall back across GitButler JSON flag syntaxes (but 0.22.0) by @backnotprop in #1216
      • ci: auto-sync install scripts to their dedicated S3 bucket by @backnotprop in #1214

      v0.26.0

      New Contributors

      Contributors

      @alexanderkreidich rebuilt Guided Review's rendering around a viewport coordinator (#1158), turning minute-long opens of large guides into instant ones, and backed it with the performance measurements quoted above.

      @rNoz shipped two fixes this release: the tracked- file memory bound for the review server (#1167) and markdown reference link rendering (#1168), the latter closing a request that had been open since #923.

      @sergical brought plan review to OpenCode 2 (#1194) and filed the follow-up to move the adapter to the stable plugin API (#1196). First contribution.

      @SyahrulBhudiF reported the Pi port exhaustion bug and then fixed it himself (#1159, #1160). First contribution.

      @tbontb-iaq did the same for the installer rate limit: report (#1156) and fix (#1157). First contribution.

      @rian-dolphin added the copy-feedback keyboard shortcut (#1155). First contribution.

      @technicalpickles reported the natural- language annotate failure (#1182), authored a parallel fix whose URL-probe catch and test coverage were ported with co- author credit (#1187), and supplied the history that anchored the final design.

      @astradevkin filed the report that shaped the installer work in #1197: the per-agent opt-out design and the discovery that attestation bundles can be fetched credential-free from GitHub's public API, complete with negative controls.

      Community members who reported issues that drove changes in this release:

      Community

      @swushi reported the GitButler 0.22.0 breakage within hours of v0.26.0 shipping, with a complete reproduction, the upstream PR that caused it, and the capability-based fallback design the fix uses (#1215). Reports of this quality make same-day patches possible.

      Full Changelog : v0.26.0...v0.26.1 (patch) and v0.25.1...v0.26.0 (feature release)

    6. πŸ”— backnotprop/plannotator v0.26.0 release

      Follow @plannotator on X for updates


      Missed recent releases? Release | Highlights
      ---|---
      v0.25.1 | Codex no longer launches on review open, annotate-last follows the live conversation, pi-todos mirror, Claude Opus 5, abandoned-gate dismissal
      v0.25.0 | Vim keyboard controls, Approve with Notes, scriptable annotate gates, persistent Guided Reviews, memory and file-watching hardening
      v0.24.2 | Annotate YAML/JSON/TOML config files, XDG data directory support, Codex model catalog update, Cursor sandbox escape hatch
      v0.24.1 | Annotate accepts parent-relative ../ file paths
      v0.24.0 | PR/MR artifact gallery, GitButler review support, port ranges, expanded comment editor, OpenCode + Pi fixes
      v0.23.1 | Startup no longer hangs on large or slow directory trees, Ask AI input stays visible after long responses
      v0.23.0 | Plan approval fix for Claude Code 2.1.199+, annotate mode version diff, binary-only --minimal install, reviews post without attribution
      v0.22.0 | Git-status "All changes" default review view, Commits panel with per-commit diffs, Guided Review, Pi + GitHub Copilot CLI review engines
      v0.21.4 | Markdown math rendering, PR Overview panel with annotatable description and comments, agent instructions in code review, media parsing fixes
      v0.21.3 | File comments in code review, unified click-to-highlight comments, VS Code clipboard/keyboard bridge, Codex Ask AI on app-server transport, CLI subcommand help
      v0.21.2 | Custom reviews as Agent Skills, Cursor + OpenCode review engines, whole-file/general findings, deleted-annotation fix, Codex Ask AI outside git repos


      What's New in v0.26.0

      v0.26.0 introduces Edit Mode, makes Guided Review fast on large changesets, adds a colorblind theme and a safe uninstall command, and hardens the installer, the review server, and the OpenCode plugin. Thirty-two PRs shipped in this release; seven came from external contributors plus one co-authored port, and four contributors landed their first PR.

      Edit Mode: author suggestions by editing the code

      A new experimental way to give review feedback: click Edit on a file in the all-files review view and fix the code right there in the diff. When you finish, your net changes become ordinary suggestion annotations, the same shape the suggestion editor produces, with the original code in a fenced Replaces: block and your replacement in Suggested code: so the applying agent can validate the anchor. You can also select text mid-edit and turn the selection into an annotation. The browser never writes to your files on disk; the agent applies the suggestions from your feedback.

      Edit Mode is off by default behind Settings > Editor > "Edit Code to Suggest". A one-time announcement dialog introduces the feature with an embedded screen recording of the flow and an explicit enable switch. The switch is deliberate design: the first draft used a primary "Turn it on" button, which reads as a generic continue and invites reflex clicks, so the opt-in became a switch you must consciously flip before the neutral Done button applies it.

      Two fixes landed before release from our own QA pass: Discard now repaints the pristine diff immediately instead of leaving edited pixels on screen until an async rerender, and the same repaint removes a brief flash of stale content on the Suggest path.

      Guided Review handles large changesets

      Guided Review used to mount a full code viewer for every file in the guide. On a large guide that meant hundreds of live viewers, around a million shadow DOM elements, 770MB of heap, and scrolling at 4 frames per second, with the view taking close to a minute to open. A shared viewport coordinator now keeps at most 8 file viewers mounted at once and swaps the rest for lightweight placeholders as you scroll. The same guide now opens in around a hundred milliseconds, holds ~140MB, and scrolls at full frame rate. Section reviewed- state, annotations, and search behave exactly as before.

      Colorblind theme

      A new built-in theme designed for red-green color vision deficiency, which covers most color blindness. Additions render blue and deletions orange across diff backgrounds, gutters, indicators, and syntax highlighting, in both light and dark. The palette was tuned with CIEDE2000 color-difference measurements under simulated deuteranopia and protanopia; the worst-case separation between "added" and "removed" improves from 1.7 (indistinguishable) to 9.0 (clearly distinct). A separate tritanopia variant was evaluated and skipped on the data: the default palette already reads correctly for tritanopes.

      Safe uninstall

      plannotator uninstall removes the binary, skills, hooks, and per-agent integrations, and walks through every host it recognizes (Claude Code, Codex, OpenCode, Gemini, Kiro, and friends) before touching the binary. Your data is preserved by default: plans, history, drafts, and settings stay unless you pass --purge. --dry-run shows the full removal list without deleting anything, and --yes skips the confirmation for scripted use. Host cleanup is required, not optional: if a host's cleanup fails, the uninstall stops with manual guidance rather than leaving a half-removed install behind.

      Review server memory stays bounded on huge files

      Staging a very large text file used to balloon the review server; a 51MB file drove resident memory to around 240MB. Tracked files above 5MiB are now excluded from the rendered diff and shown as bounded stubs, the same treatment untracked files already had. A follow-up fix hardened the failure path: the original implementation probed object sizes with one git cat-file --batch- check call, and if that single call failed, every file in the review rendered as "Binary files differ" with no visible error. The size bound is now enforced by git itself through core.bigFileThreshold, so a failed probe degrades gracefully instead of blanking the review.

      Installer: opt-outs, credential-free provenance, and honest failures

      The install scripts gained a family of opt-outs: --skip-codex, --skip- gemini, --skip-kiro, --skip-opencode, and now --skip-skills, each with a matching environment variable and skipInstall config key. Skipping means the installer writes nothing for that scope and never removes what a previous install wired. Attestation verification (--verify-attestation) now works with zero GitHub credentials by fetching the attestation bundle from GitHub's public API, falling back to authenticated gh only when needed. Both designs came from a single unusually rigorous report by @astradevkin, including the discovery of the public attestations endpoint.

      Two honesty fixes shipped alongside: a failed skills checkout used to report success because of a POSIX errexit subtlety (the failure now aborts loudly, which is exactly why --skip-skills exists for offline installs), and installs on Windows PowerShell below 7.2 no longer die on git writing progress to stderr. The installer also authenticates its version lookup when a GitHub token is present, avoiding the anonymous 60-requests-per-hour rate limit on shared networks.

      OpenCode 2 support (experimental)

      Plan review now works on OpenCode 2 through a V2 plugin adapter that shares the same host-independent plan submission path as every other agent, with OpenCode 1 behavior fully preserved. The plugin's packaging also got two weight reductions worth noticing: the prerelease @opencode-ai/plugin nightly is no longer a runtime dependency (it was pulling a 95MB, 101-package closure into every install), and the bun peerDependency is gone (npm auto-installed the entire 50MB Bun binary into every consumer's node_modules; the runtime requirement now lives in engines, which is informational). Known V2 limitations are documented in the plugin README: no tool abort signal, and agent switching after approval is manual.

      Annotate understands natural language arguments

      Slash-command hosts forward whatever the user typed, so /plannotator-annotate look at notes.md please used to fail with "File not found: look". The annotate CLI now probes each word and proceeds when exactly one resolves to a real file, URL, or folder. When two or more resolve, it errors naming every candidate rather than guessing, which also fixes a silent bug: annotate a.md b.md used to open a.md and drop b.md without a word. When nothing resolves, the CLI hands off to the reading agent with the words it tried, so the agent can re-run with a concrete target. A companion fix taught the token probe to recognize URLs wrapped in punctuation.

      Additional Changes

      • Markdown reference links render. [ref][1] style links now render as real links in plans instead of raw text, closing a long-standing request (#1168 by @rNoz, closing #923 reported by @Thraka)
      • Copy feedback shortcut. Cmd/Ctrl+Shift+Y copies the review feedback to the clipboard from anywhere in code review (#1155 by @rian-dolphin)
      • Pi review ports release on shutdown. Back-to-back reviews in Pi no longer hit EADDRINUSE (#1160 by @SyahrulBhudiF, closing #1159)
      • Clipboard works in remote HTTP sessions. Copy actions fall back to the legacy clipboard path in insecure browser contexts instead of failing silently (#1174, closing #1173 reported by @quanweiZhou)
      • Partial GitLab submissions surface. When some GitLab review comments post and others fail, the result reports exactly which ones failed instead of claiming success (#1164)
      • Archive is read-only everywhere. Archive mode now rejects mutating actions server-side on both runtimes (#1171)
      • Privacy and network docs corrected. The docs now accurately describe what leaves your machine and when (#1163)
      • Sharing article redirect fixed. A legacy marketing URL no longer chains through multiple redirects (#1180)
      • @pierre/diffs upgraded to 1.3.2. Staged through 1.2.12 and a theme major, with hover and line-background rendering verified across intensities and themes (#1188, #1190, #1191)

      Install / Update

      macOS / Linux:

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

      Windows:

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

      Claude Code Plugin: Run /plugin in Claude Code, find plannotator , and click "Update now".

      OpenCode: Clear cache and restart:

      rm -rf ~/.bun/install/cache/@plannotator
      

      Then in opencode.json:

      {
        "plugin": ["@plannotator/opencode@latest"]
      }
      

      Pi: Install or update the extension:

      pi install npm:@plannotator/pi-extension
      

      What's Changed

      New Contributors

      Contributors

      @alexanderkreidich rebuilt Guided Review's rendering around a viewport coordinator (#1158), turning minute-long opens of large guides into instant ones, and backed it with the performance measurements quoted above.

      @rNoz shipped two fixes this release: the tracked- file memory bound for the review server (#1167) and markdown reference link rendering (#1168), the latter closing a request that had been open since #923.

      @sergical brought plan review to OpenCode 2 (#1194) and filed the follow-up to move the adapter to the stable plugin API (#1196). First contribution.

      @SyahrulBhudiF reported the Pi port exhaustion bug and then fixed it himself (#1159, #1160). First contribution.

      @tbontb-iaq did the same for the installer rate limit: report (#1156) and fix (#1157). First contribution.

      @rian-dolphin added the copy-feedback keyboard shortcut (#1155). First contribution.

      @technicalpickles reported the natural- language annotate failure (#1182), authored a parallel fix whose URL-probe catch and test coverage were ported with co- author credit (#1187), and supplied the history that anchored the final design.

      @astradevkin filed the report that shaped the installer work in #1197: the per-agent opt-out design and the discovery that attestation bundles can be fetched credential-free from GitHub's public API, complete with negative controls.

      Community members who reported issues that drove changes in this release:

      Full Changelog : v0.25.1...v0.26.0

    7. πŸ”— crosspoint-reader/crosspoint-reader v1.5.0-rc-4 release

      Note

      This version contains the fixes for the latest X3 variants with new display drivers

      Changes in RC-4

      • fix: load Settings page's Wi-Fi/OPDS/settings data sequentially by @obra in #2831
      • fix: add support for new x3 display, x3 battery drain fix, and crypto support by @itsthisjustin in #2864
    8. πŸ”— Locklin on science The tools of Dan Gelbart rss

      One of the cult youtube channels of machinists is the channel of Dan Gelbart. Youtube’s suggestion algorithm found him for me, and it made me nostalgic for all the talented machinists (often with similarly funny accents) I used to run into at Berkeley Labs. I paid more attention afterΒ  watching one about a home made […]

    9. πŸ”— HexRaysSA/plugin-repository commits Snapshot GitHub metadata for legacy api-plugins repos too rss
      Snapshot GitHub metadata for legacy api-plugins repos too
      
      The snapshot script only walked the HCLI index (plugin-repository.json),
      so the ~140 legacy api-only plugins never got GitHub repo metadata in
      combined.json: no fresh stars, no owner avatar, and no owner type β€” which
      the UI needs to label publishers as Organization vs Individual (e.g.
      atredispartners showed a letter-tile avatar and 'Individual' despite being
      a GitHub organization).
      
      Add --api api-plugins.json to also snapshot those repos; wired into the
      justfile and the deploy workflow. Per-repo 24h caching and 404 skipping
      apply unchanged.
      
      Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
      
    10. πŸ”— The Pragmatic Engineer The Pulse: Bending Spoons' Acquisition Strategy rss

      Bending Spoons has announced buying Airtable for $1.285B in cash this week - which is less than the $1.4B in total funding Airtable has raised in the past, and well below the $11B valuation it had during its last fundraise in December 2021.

      Selling to Bending Spoons is a company admitting defeat, and its inability or unwillingness to turn its business around, and wanting to get the highest possible cash for the business. Because this is what Bending Spoons is excellent at: they pay the highest cash value for a struggling business with a well-known brand, then take over operations, and operate the product with a fraction of the staff. They often let go most or all of the original team as they move over product operations to their in-house engineering team based in Italy and Europe.

      Evernote: what happens when a new team takes over a legacy application

      And having talked with Bending Spoons' engineering team on the podcast: they have done impressive engineering work after a takeover, in the past! For example, upon acquiring Evernote, the Bending Spoons engineering team discovered that the note-taking service was running as a Java 11 monolith (!!), with user data sharded across 750 manually provisioned virtual machines (!!!) on top of Google Cloud - in 2023! At a time when running cloud-native setups (managed databases, microservices) was common knowledge for years.

      Evernote's existing setup was weirdly inefficient and operationally very heavy, with manual interventions needed to keep the service running. Needless to say, performance was poor because some VMs were regularly overloaded. Also, oncall was brutal!

      The Bending Spoons engineering team rationalized the architecture:

      • Migrated user data sharded from the 750 manually provisioned VMs to a managed database
      • Split up the Java 11 monolith to microservices
      • Did all of the above without disrupting user experience
      • Improved performance of the backend by a wide margin
      • Reduced oncall load after finishing the migration to a cloud-native setup vs the previous manual provisioning setup
      • Did all the above in about 6 months.

      It's a fair question: would long would have the original Evernote engineering team have taken to do the same changes that made the service more reliable, more performant, and cheaper to operate? I would guess it would have taken them many years: in fact, if they did not make this change until 2023, who knows if they would have ever made these pretty rational changes? And so the "shock therapy" of Bending Spoons starting with a blank page, and a new team taking over operating the full product, with a laser focus on efficiency: well, this approach can be pretty efficient, as the Evernote example shows.

      You can listen to the full podcast episode I did with the Bending Spoons team:Twisting the rules of building software: Bending Spoons .

      Price increases and the existing team let go: the two most typical

      complaints

      Bending Spoons taking over an existing product has two major criticisms:

      1. Price increases. Evernote was the biggest example of price hikes: after Bending Spoons took over operating the product - and improving its performance - price hikes followed. Being Spoons kept investing in Evernote, adding new features (including AI ones), but customers paying $37/year for the Pro plan pre-2023 were charged $250/year by 2026. My take is that this is what happens when a product starts working a business maximizing profits: lots of customers will leave for competition, while others will pay more, valuing a more reliable service that gets more investment than before. Bending Spoons keeps improving Evernote since the acquisition, alongside the price increases. Clearly, the company is optimizing for maximizing revenue, not maximizing the number of customers, though.
      2. Layoffs. Bending Spoons let go most/all of the Evernote team in the US, briging operations in-house. This is part of the "usual" playbook of Bending Spoons: they buy products to operate them as efficiently as possible. The re-architecting example shows benefits of starting from scratch, and not needing to deal with internal resistance for changes that result in more efficient operations. Knowing that with a Bending Spoons acquisition, letting go of all the existing team is on the table is something that comes with selling to this company.

      With this, let me share my analysis of a past Bending Spoons acquisition: when they bought SteamYard from Hopin.


      Below is the now un-paywalled excerpt from** The Pulse #89: The end of Hopin** , from April 2024, sent to paid The Pragmatic Engineer subscribers. If you'd like to get analysis like this in your inbox, weekly, subscribe to The Pragmatic Engineer .

      The End of Hopin

      It's been a real rollercoaster ride for the virtual events provider:

      • 2019 : founded with a mission to provide a solution for hosting virtual events.
      • 2020-2021: raised a total of $1B in funding during a seed round in Feb 2020, Series A in June, Series B in November, and then a Series C in March-June 2021. The company was valued at $7.75B and acquired several startups, the biggest of which was video streaming platform, StreamYard, for $250M.
      • 2022 : layoffs in February, when Hopin was one of the early scaleups to do large cuts (12%), followed by more in July (29%), and November (17%)
      • 2023 : Hopin sold its core event tech business to RingCentral for $50M. We analyzed this at the time.
      • 2024: Last month, Hopin's UK entity entered liquidation. Insiders told me it was merely a restructure, with Hopin UK employees joining StreamYard. Basically, Hopin became the business it had purchased back in 2021.

      This week, Italian mobile app developer Bending Spoons acquired the remains of Hopin, which is basically the StreamYard product. All Hopin staff will soon be laid off.

      The Bending Spoons acquisitions strategy

      Bending Spoons has previously acquired apps such as the notes app Evernote in 2022, events app Meetup in 2024, and video-recording app FiLMiC in 2022. Their approach to these acquisitions was the same each time:

      1. Take over operating the product
      2. Fire most staff immediately
      3. Have some remaining staff hand over services, then fire them as well
      4. Operate the app with a much smaller team and raise prices.
      5. Profit!

      I talked with current Hopin employees for details on what will happen next, and if this model will be followed again. Unfortunately, it will.

      All existing Hopin staff will be let go, eventually. This affects around 80 staff working on StreamYard, and another 70 on other Hopin products, Streamable (video sharing) and Superwave (community platform.) I'm told severance packages are generous enough, at around 3-4 months' salary.

      As with other Bending Spoon acquisitions, a subset of the team was requested by Bending Spoons to help with the transition (and then be let go afterwards.) Understandably, morale is very low for this reason, and the certainty that everyone will lose their jobs.

      How much did StreamYard sell for?

      From talking with current employees, I gather that circa 95% of Hopin's revenue comes from StreamYard, and not more than 5% from Streamable and Superwave. So the only valuable asset that this acquisition priced in is StreamYard.

      In 2021, Hopin paid $250M for it. Back then, the video streaming service generated about $40M in annual revenue. This has risen to about $70M per year and keeps growing in an increasingly crowded market. StreamYard was at around break even and can be easily made profitable, I'm told.

      A good question is whether Bending Spoons paid $250M or more for this asset. In 2023, RingCentral paid $50M for the "core" virtual events offering which was making $20M in annual recurring revenue (ARR) at the time, I've confirmed with insiders. However, ARR was falling steeply, and was forecast to hit $10-15M within a year. So RingCentral paid a 2.5x multiple for an asset losing revenue.

      StreamYard brings in $70M per year, and this is increasing. I'd assume the purchase price would be at least the same 2.5x multiplier, if not more. So there's a fair chance this sale's value is close to $200M.

      Why did Hopin sell to a buyer which wants to lay off everyone?

      I have exclusively learned that StreamYard's founders actually offered to Hopin's board of directors to buy the company back, and operate independently, as before. This would've been a better outcome for employees, most of whom would surely have kept their jobs. Some of StreamYard's staff knew of this plan and naturally supported it. The Bending Spoons sale has taken everyone by surprise.

      But why would Hopin choose a buyer that is guaranteed to sack existing staff? Well, the board might have had no real choice, due to Hopin having raised too much money.

      Hopin raised $1B in funding, during which it almost certainly offered board seats to investors including a16z, General Catalyst, Coatue, Northzone, Salesforce Ventures, Tiger Global, Accel, and others. It's safe to assume investors control the board, and as Hopin will never live up to its $7.75B valuation, the board-level rationale has evidently been to maximize the amount of money clawed back.

      Of that $1B, here's what's left:

      • $50M from selling Hopin's core business
      • Whatever StreamYard sells for
      • Residual cash left over from the fundraising

      The board serving investors' interests had to shop around for the highest bidder, and minimize losses. I have to assume the decision on whether StreamYard's founders could buy back their own company came down to whether or not someone else was offering more money for it. Unfortunately for Hopin's staff (and fortunately for investors,) Bending Spoons probably offered more.

      The risk of raising too much venture capital

      Hopin is a reminder that raising too much venture capital can have unexpected, seemingly irrational, outcomes.**** Firing all staff from a company making $70M/year while being break-even or profitable sounds irrational from the company's perspective. But it is rational for investors and a buyer:

      • Hopin's investors realized the company is a "failed bet." They want to cash out their losses: get back whatever money they can - which is still in the hundreds of millions of dollars! - and use this capital to make new bets.
      • Hopin's buyer - Bending Spoons - wants to maximize their return. They pay $X for the company, and the goal is to generate $Y over the next several years in profit from it, where $Y > $X. So, the acquisition pays for itself. Bending Spoons has a working model that involves firing all existing staff, and operating the product more efficiently.

      The biggest losers in this story are:

      • Some investors. Collectively, investors poured $1B into Hopin. In October 2023, Hopin returned $581M of capital to investors (so 58% of all amount raised). It is unclear if the StreamYard purchase that could be another $200-300M, will be returned to them. It is safe to assume that investors will lose about 20-42% of the amount they invested, depending on how much proceedings of the StreamYard purchase they get paid. This is much better than in the case of one-click checkout startup Fast going bankrupt _ a year after raising $100M in funding, where investors most likely lost all their investment! In the case of Hopin: it's still a loss, but it's far from a 100% loss like with Fast._
      • Employees who expected a better outcome. Shares issued to staff by Hopin are now officially worthless. At the same time, Hopin did pay above-the-market base salaries, and offered generous severance during redundancies. Unfortunately, a reality of fast-growing startups is that they can grow fast, but also go down fast.

      Winners of this sale are:

      • The original founders of StreamYard who sold the company for $250M cash. Even though these founders are also departing, they netted a healthy return in 2021.
      • Bending Spoons, which has acquired a market-leading streaming product generating $70M per year and growing. StreamYard would normally not be available to buy, but the need of the Hopin board to "cash in" the company's remaining assets made this sale possible.

      I assume the biggest winner of the Hopin story stands to be Hopin's founder and former CEO, Johnny Boufarhat. He sold more than Β£100M ($127M) of his shares in 2021 as secondaries. He probably netted more money than Hopin - excluding StreamYard - generated in its lifetime! Selling a good chunk of his shares in 2021, at the peak of hype for virtual events is a good reminder that when everyone is buying, it can be a profitable strategy to sell!

      What happened to other fast-growing startups in Europe?

      In 2020, Hopin was known as the fastest-ever growing startup in Europe by valuation. This visualization by Sifted went viral, and was widely shared by Hopin staff on social media:

      altGraph showing Hopin 's growth to $7.75B in under 2 years. Source: Sifted .

      Hopin's current value is now zero, having sold its valuable assets. But how have other, formerly fastest-growing startups in Europe performed? I visualized this:

      altHow the group of fastest-growing startups in Europe in 2020 are doing today. Wolt and Revolut were the only two to remain on a "hockey stick-growth," valuation- wise.

      Excluding Hopin, the car sale website Cazoo did worst; it's currently close to bankruptcy, valued at about $60M. The companies that managed to grow above than their 2020 valuations are:

      • Food delivery service Wolt was acquired by DoorDash for €7B ($8.1B) in 2022
      • Ride-hailing app Bolt was last valued at $8.5B, and is supposedly preparing for an IPO in 2025
      • Neobank, Revolut, was valued at $33B, even though some investors cut their valuation of the company to around $20B in the summer of 2023
      • Spotify's current market cap is nearly $60B, and the company is trading close to its 2021 all-time-high

      This chart confirms what we already know: 2020-2022 was a time when startup and scaleup valuations hit all-time highs, fueled by zero interest rates, and widespread changes in consumer spending caused by the Covid-19 pandemic. We have covered what the end of rock bottom rates could mean for the tech industry.

    11. πŸ”— exe.dev Botiquette rss

      There are lots of bots floating around exe, helping us organize and monitor and maintain our world. (Agents and bots and any LLM output are all synonyms for this post.) We’ve organically developed some etiquette around bots that work well for us.

      • Bots do not post to human spaces. Attention is precious, and bots are (currently?) incapable of gauging the cost of their posts.

      • There is no expectation that other humans will read human posts to bot spaces. Or even bot posts to bot spaces.

      • Humans write their own words.

      • If a human pastes bot output into a post, that output is clearly marked as such, typically in block quotes or a code block.

      • Bot posts always include where the bot is running and where its source code is.

      • Bots have names, because it makes it easier to talk about them, but they are computer programs. Their pronouns are always β€œit/its”.

    12. πŸ”— exe.dev Simpler GitHub Integration URLs, Plus Read-Only Access rss

      exe.dev integrations let you keep secrets outside of your VM; a proxy injects the secrets. Sometimes this is as simple as adding an HTTP header, and sometimes the integration is bespoke.

      We recently gave our GitHub integration two new features:

      • One URL for any repo: Any repo that a VM has access to (including team integrations) can be accessed at https://github.int.exe.xyz/OWNER/REPO. We automatically pick the appropriate integration, saving you the trouble of remembering the integration name as well. We take compatibility seriously, so your old git remotes will work just fine.
      • Read-only integrations: You can mark a GitHub integration as read-only, both for git operations (fetch, not push) and GitHub API operations.
  3. August 04, 2026
    1. πŸ”— IDA Plugin Updates IDA Plugin Updates on 2026-08-04 rss

      IDA Plugin Updates on 2026-08-04

      New Releases:

      Activity:

      • claude-marketplace
        • 0abba7f9: Rename ida-codemode-mcp to ida-mcp
      • diffIDA
      • ida-codemode
        • 8c21e8cc: Make sure a matching ida-codemode plugin is installed
        • 4c627b34: Workaround IDAUSR split bug in idapro and fix analysis hook lifecycle
        • 1f69d63b: Add HCLI_DEBUG to improve error reports for plugin installation
        • d220125e: Slight cleanup of top-level #16
        • d91cf913: Prepare for PyPI release
        • 9d2f1ad6: Do not show anything to the user when starting the plugin
        • fea1ca44: Switch to consuming ida-domain from pypi
        • df28696a: Fix pylance problems
        • bfea39d5: Fix type checking
      • ida-domain
        • dd30f47d: Expand the Instructions class API functionality (#105)
        • f41b8d87: 0.5.1-dev.2
      • ida-hcli
        • 6c3bf3fc: docs: fix formatting
        • 008f0f18: fix: handle version strings with patch component (e.g. 3.9.10)
        • d7e471ce: feat: warn when IDA Python is 3.9 or older in explain-environment
        • 63efaad7: fix: detect old pip missing -dry-run and suggest upgrade
      • ida-pro-mcp
        • 539ae082: fix(test): grace-window tests flaky on freshly-booted runners
        • fce143b7: fix(schema): register reranker_status + function_families in intellig…
        • c345e1d6: build(deps): bump yara-python, requests, pytest-timeout floors
        • 5c7f342c: build(deps): bump actions/setup-python from 5 to 7 (#58)
        • ee032169: build(deps-dev): update pytest requirement from >=8.0.0 to >=9.1.1 (#54)
        • 89b1cf10: build(deps): update tomli-w requirement from >=1.0.0 to >=1.2.0 (#53)
        • 06897d09: build(deps): update numpy requirement from >=1.26.0 to >=2.4.6 (#52)
        • f3e5d6ed: build(deps): bump actions/checkout from 4 to 7 (#51)
        • 7b83545c: chore(lint): fix all ruff errors so CI is green
        • eed2dccd: ci: native-backend build check, CodeQL, dependabot, issue/PR templates
        • 7074e194: docs(readme): rewrite for native retrieval backend + batched decode + Q4
        • 9feb4b39: feat(retrieval): batched native decode + Q4_K_M models
        • 50428419: feat(retrieval): in-process native llama.cpp backend (embed + rerank)
        • 3413144c: fix(semantic-index): preserve partial index on batch failure; bound s…
        • 2ae8262b: fix(rerank): 5GiB RSS floor clears measured peak; live-reload dev loop
      • IDA-Source2Forge
        • 38f3aa1f: fix: stop the rename offer returning with nothing to name
      • Luc-Nhan
        • 7c6a9b48: feat(skill): add IDA 8.x to 9.0 porting guide reference
      • mcrit-plugin
        • ffffca60: bump 1.1.9
        • 3dbebc98: minimcrit: lazy filtered_* lists, replacing the eager deepcopy
      • quokka
        • 6ac3e743: Merge pull request #137 from quarkslab/dependabot/github_actions/acti…
    2. πŸ”— Simon Willison New release of LLM adds support for reasoning traces, OpenAI Responses, server-side tools, and smarter logging rss

      I released LLM 0.32 this morning, the most significant new version of LLM since the initial launch of the project. The new version includes support for visible reasoning traces, server-side provider tools, redesigned content-addressable SQLite logs, new models, and new features enabled by the OpenAI Responses API. I also released a new version of the llm-anthropic plugin with substantial updates of its own.

      Headline features for LLM CLI users

      Running LLM against reasoning models now displays their reasoning traces to standard error, so you can see what they are "thinking" without that information being included in the standard output that you might pipe to another tool. Add -R/--hide-reasoning to turn this off.

      Running llm "think about the best thing about pelicans" in the macOS terminal window - grey text outputs saying Exploring pelican qualities, then after a paragraph of that a white paragraph of text comes out saying: The best thing about pelicans is their wonderfully oversized, practical design: that enormous bill and pouch look comical, but they make pelicans remarkably skilled fishers. Even better, many species cooperateβ€”working together to herd fish before scooping them up. They’re a great mix of goofy, graceful, and surprisingly clever.

      LLM includes support out-of-the-box for the GPT-5.6 model family, and the new default model used with llm "prompt" is now the inexpensive but capable GPT-5.6 Luna.

      LLM calls can now use server-side tools from various providers. OpenAI provide a code execution environment as a server-side tool; LLM can now run prompts that benefit from that like so:

      llm --tool CodeInterpreter 'Show current python and SQLite versions'

      OpenAI also gets a WebSearch tool.

      The llm-anthropic plugin adds WebSearch, WebFetch, CodeExecution, and AnthropicMCP, which looks like this:

      llm -m claude-sonnet-5 -T 'AnthropicMCP("https://datasette.simonwillison.net/-/mcp")' \
        'how many rows in the blog_blogmark table?'

      That causes Anthropic to execute MCP calls against my new datasette-mcp plugin as part of a single request/response interaction with their API.

      The new llm openai endpoint command provides a tool for executing prompts against any OpenAI compatible endpoint as a one-liner. These aren't logged, which makes this a handy tool for running one-off prompts against anything that speaks the lingua franca of the LLM API world.

      Here's how I use that to run prompts against Gemma 4 12B running in my localhost LM Studio API, via uvx (no LLM installation required) and mixing in the llm-tools-quickjs tool plugin for good measure:

      uvx --with llm-tools-quickjs \
        llm openai endpoint http://localhost:1234/v1 -m google/gemma-4-12b \
        -T QuickJS 'Use QuickJS to multiply 3434 * 2434' --td

      Output reads Tool call: QuickJS_execute_javascript({'javascript': '3434 * 2434'})  8358356 The result of 3434 * 2434 is 8,358,356.

      New features in the Python API

      LLM's Python API previously required you to create a conversation and then send messages to it one at a time. This was an abstraction over the true nature of LLMs, where each request carries a complete history of the messages that came before it. That abstraction started to get in the way for some more advanced cases, so the new release introduces a model.prompt(messages=[]) parameter that can be used like this:

      import llm
      from llm import user, assistant, system
      
      model = llm.get_model("gpt-5.6-luna")
      
      response = model.prompt(messages=[
          system("You are a helpful pirate."),
          user("What is the capital of France?"),
          assistant("Paris, matey."),
          user("And Germany?"),
      ])
      print(response.text())

      LLM previously returned an iterable sequence of strings from each prompt. This worked great when models returned a string response, but failed to predict the weird shape that models would evolve towards. Today many models return a mix of reasoning text, output strings, tool calls, and even image attachments. With LLM 0.32 you can do this instead:

      for event in model.prompt("Explain cats").stream_events():
          if event.type == "reasoning":
              print(f"[thinking] {event.chunk}", end="", flush=True)
          elif event.type == "text":
              print(event.chunk, end="", flush=True)
          else:
              print(f"Other event: {event}")

      Combine these features and we can finally provide a robust implementation of the semi-standard OpenAI chat completions API, which I've now released as the llm-chat-completions-server plugin:

      llm install llm-chat-completions-server
      llm chat-completions-server --port 9000
      # Server is now running on http://127.0.0.1:9000/v1

      Now you can run prompts against LLM via that server, using the new llm openai endpoint command!

      llm openai endpoint http://127.0.0.1:9000/v1 'hello' -m gpt-5.4-mini

      The bigger challenge with that kind of API concerns logging. If we're going to support the pattern where the message sequence is appended to on every request, ideally we can avoid logging all of that duplicate JSON for every turn.

      The solution is the new content-addressable message store, modeled after Git. You can see the new schema for that in the documentation, but the llm logs and llm logs --json commands have both been upgraded to convert that format back into something that's easy to consume.

      And the rest

      There is a whole lot more in this release. The 0.32 release notes are pretty comprehensive, and the notes for 0.32rc2, 0.32rc, 0.32a3, 0.32a2, and 0.32a0 should fill in any gaps.

      Existing LLM plugins should all continue to work, but plugins that provide extra models will need to be upgraded to 0.32 in order to participate fully in the new streaming events system. There's a guide to implementing plugins with Structured messages and streaming events in the documentation.

      I've updated some of my own plugins:

      I guess LLM is an agent framework now

      Quite a few of the lower-level tools changes in this release were driven by the needs of Datasette Agent. When I started work on LLM, the term "agent" had such a vague definition that I refused to use it. In September 2025 I came around to the idea that "An LLM agent runs tools in a loop to achieve a goal" is well established enough now that I could stop avoiding the term entirely.

      Tool chains can now pause for human approval and resume from a stored message history - both needed by Datasette Agent.

      Looking at LLM today it's beginning to look very agent-shaped to me. There's something neat about having a CLI utility that can mix and match different tools from different sources with different models all as a one-liner, and that includes a Python library powerful enough to build systems like Datasette Agent and llm-coding-agent.

      Maybe the next version of LLM will bake the concept of an "agent" into the core library. I'm still trying to figure out what that would look like.

      You are only seeing the long-form articles from my blog. Subscribe to /atom/everything/ to get all of my posts, or take a look at my other subscription options.

    3. πŸ”— r/LocalLLaMA Kimi K3 full model running on 16x GB10 cluster at 20+tps rss

      Kimi K3 full model running on 16x GB10 cluster at 20+tps | Kimi K3 full model running on 16x GB10 cluster at 20+tps average (llama-benchy coherent corpus) 38tps peak, 750tps prefill. This is the first run of full k3 with dspark on my cluster. I will be doing some tests and try tp speed this up. As soon as it looks ready I'll publish the vllm image and instructions.
      https://forums.developer.nvidia.com/t/full-kimi-k3-running- on-16x-gb10-cluster/379174 submitted by /u/ciprianveg
      [link] [comments]
      ---|---

    4. πŸ”— MetaBrainz MusicBrainz Server update, 2026-07-30 rss

      We're happy to release our first MusicBrainz Server update since the schema change, following our migration of user accounts to the MetaBrainz website, which we've been spending most of our development time on until now. (This blog post also lags a bit behind the date we tagged the release, as you can tell from the title.)

      In case you're running a local MusicBrainz Server for development purposes, know that you can preserve the ability to log in without OAuth by adding sub LOCAL_ACCOUNTS_ENABLED { 1 } to lib/DBDefs.pm. (It's already enabled by default if DEVELOPMENT_SERVER is.)

      We've also made changes to digest authentication in the web service, detailed in the blog post linked above. If you don't use digest authentication or any apps that do, it's recommended you disable it from the Applications page.

      A new release of MusicBrainz Docker is also available that matches this update of MusicBrainz Server. See the release notes for update instructions.

      Thanks to julian45 and rinsuki for having contributed to the code. Thanks to affronttonature, Anesidora, arsinclair, chirlu, DarkAdonis, jesus2099, julian45, Lotheric, practik, rinsuki, and wileyfoxyx for having reported bugs and suggested improvements. Thanks to 7Stars, ApeKattQuest/MonkeyPython, Denatura, Early6431, EmO686, Flavia Telcean, GABG, Jeluang, JerryBest, KevinOpperman, LAY.JOSHI97, Lummerkurt, MFreedom89, Philipp Wolfer, ROManceJP, RalfZhang, The
      ParaziT, afterthemagic, blueday, coffeeicus, cuhsy, jerry155756294, julian45, karpuzikov, meze, mfmeulenbelt, mr_monkey, salo.rock, sashimi3433, scientists360, silentbird, soonaf, sq, welikeheon, wileyfoxyx, and
      zatto13 for updating the translations. And thanks to all others who tested the beta version!

      The git tag is v-2026-07-30.1.

      Fixed Bug

      • [MBS-14308] - "RangeError: Attempt to access memory outside buffer bounds" in the template renderer
      • [MBS-14322] - Dailymotion /user channel URLs are blocked
      • [MBS-14344] - git_info on beta borks non-ASCII characters in tooltip
      • [MBS-14402] - Some pages fail to load properly when a UI language is set
      • [MBS-14413] - LoadReplicationChanges leaves sir live indexing disabled after catching up

      Improvement

      • [MBS-7520] - Allow YouTube links for interview relationships
      • [MBS-12379] - Delete user tags and ratings of deleted users via hourly cron
      • [MBS-14295] - Filter irrelevant anchor from vkdb links
      • [MBS-14321] - Support Niconico Shorts
      • [MBS-14337] - Update the Soundcloud logo used in the sidebar
      • [MBS-14346] - Allow ra.co 'promoter' links to be added to labels
      • [MBS-14352] - Support @ handles for Youtube Music artists
      • [MBS-14353] - Clean up UTM parameters from Yandex Music links
      • [MBS-14360] - Use a separate password for HTTP Digest authentication
      • [MBS-14371] - Add Music in Africa to other databases whitelist

      New Feature

      • [MBS-9209] - Allow individual users to opt out of HTTP Digest auth

      Other Task

      • [MBS-13490] - Drop Napster URL handling
      • [MBS-14327] - Remove laboiteauxparoles.com from the lyrics whitelist
      • [MBS-14328] - Remove DirectLyrics.com from the lyrics whitelist
      • [MBS-14361] - Disable HTTP Digest authentication for new accounts
      • [MBS-14364] - Drop handling of (now closed) Juno Download links
    5. πŸ”— r/LocalLLaMA Hugging Face CEO says China is winning the AI race and dominating on open models rss

      Hugging Face CEO says China is winning the AI race and dominating on open models | This is something that was spoken here and there, and now it is like writing on the wall. The main additional point is that China has created an independent supply chain. Starting from raw materials and home-made lithography equipment, through their own GPU manufacturing, and to the AI models and training. Plus, there are tons of cheap energy, and it looks like they are also on track to launch the first thermonuclear reactor. I saw a similar pattern with robotics and EVs. The history does not repeat itself, but it rhymes. Does the US have what it takes to turn the tables, or should we just buy the popcorn and enjoy the show? submitted by /u/Miriel_z
      [link] [comments]
      ---|---

    6. πŸ”— r/LocalLLaMA Has anyone tried Mach-1 Additive? 95% of performance of Qwen 3.6 35B while being 10x smaller rss

      Has anyone tried Mach-1 Additive? 95% of performance of Qwen 3.6 35B while being 10x smaller | Why nobody is talking about this? Seems pretty significant to the community submitted by /u/MuzafferMahi
      [link] [comments]
      ---|---

    7. πŸ”— HexRaysSA/plugin-repository commits sync repo: +1 release rss
      sync repo: +1 release
      
      ## New releases
      - [mcrit-ida](https://github.com/danielplohmann/mcrit-plugin): 1.1.9
      
    8. πŸ”— @HexRaysSA@infosec.exchange We're heading to [@defcon](https://defcon.social/@defcon) this week and still mastodon

      We're heading to @defcon this week and still have seats available for our workshop at @malwarevillage Details below!

      "Follow the Execution: A DLL Sideloading Teardown Intro in IDA"
      πŸ“ Malware Village, Hall 2
      πŸ—“οΈ Sat Aug 8, 12:55–14:05
      🎫 Reg closes Fri Aug 6, 11:59pm
      πŸ‘‰ Sign Up: https://www.eventbrite.com/e/follow-the-execution-a-dll- sideloading-teardown-intro-in-ida- tickets-1994828069455

    9. πŸ”— mwemuorg/mwemu map files release

      This release contain the test.zip which is use for integration testing.

    10. πŸ”— r/LocalLLaMA SK hynix, In Collaboration With SanDisk, Unveils The New High Bandwidth Flash (HBF) Standard, Helping To Resolve AI Inference Bottlenecks, Targeting Up To 3TB/s Bandwidth rss

      SK hynix, In Collaboration With SanDisk, Unveils The New High Bandwidth Flash (HBF) Standard, Helping To Resolve AI Inference Bottlenecks, Targeting Up To 3TB/s Bandwidth | Hopefully this would let us have faster local models....but it will probably be out of our price range. submitted by /u/giveen
      [link] [comments]
      ---|---

    11. πŸ”— jesseduffield/lazygit v0.64.0 release

      What's Changed

      This release has massive changes, but most of them should hopefully not be visible: I completely overhauled lazygit's concurrency model, which was, let's say, less than robust; there were lots of data races, and we were just lucky that this didn't result in crashes or misbehavior more often. We now have a robust concurrency model with no known data races, and in fact we run our integration test suite on CI with the -race flag to prove that. The user visible part of this is that some operations run a little more smoothly now; for example, there used to be an ugly spinner freeze at the end of checking out a branch, which is now gone.

      However, since the changes were so massive there's a higher-than-usual chance of regressions, so please report any that you find.

      Apart from that, we also have a few useful enhancements; the most notable one is probably that we now show the Github checks status of pull requests in the branches panel.

      Enhancements πŸ”₯

      Fixes πŸ”§

      • Fix stuck inline status when pushing/fetching by @stefanhaller in #5768
      • Escape the merge conflicts view before prompting to continue the rebase by @stefanhaller in #5822
      • Fix side panel rendering when branches/commits are not their panel's first tab by @stefanhaller in #5825
      • Suppress output from a few git commands that pollute the command log by @stefanhaller in #5834
      • Fix stall with ctrl+z and fg by @stefanhaller in #5830
      • Fix more problems related to concurrent repo switch and background refresh by @stefanhaller in #5839
      • Fix Windows crash when switching to fullscreen mode with a custom pager by @stefanhaller in #5838
      • Fix multi-selection of files with common prefix not working in commit files panel by @stefanhaller in #5868
      • Support absolute paths when detecting edit preset from EDITOR env var by @stefanhaller in #5876
      • Exclude more commit trailers from auto-wrapping by @stefanhaller in #5871
      • Prevent stale index.lock files from diffs rendered through a pty on Windows by @stefanhaller in #5888
      • Fix orphaned processes on Windows when quickly navigating between commits by @stefanhaller in #5885

      Maintenance βš™οΈ

      Docs πŸ“–

      I18n 🌎

      Performance Improvements πŸ“Š

      • Make scrolling down a very long diff with the scroll wheel much smoother by @stefanhaller in #5780

      New Contributors

      Full Changelog : v0.63.1...v0.64.0

    12. πŸ”— r/LocalLLaMA More Qwen 3.8 sizes coming rss

      More Qwen 3.8 sizes coming | submitted by /u/appakaradi
      [link] [comments]
      ---|---

    13. πŸ”— Rust Blog Enabling the next iteration of the borrow checker on nightly rss

      TL;DR We are enabling the next iteration of the borrow checker (coined Polonius Alpha) on nightly in preparation for stabilization in the next few months.

      Whaaaaaat?

      Yes! You heard it right! The next iteration of the Rust borrow checker is coming! Rust's first borrow checker ("AST borrowck") was very limited and was phased out in 2019 in favor of NLL, other than a "migrate mode" that was used to provide nice error messages. That migrate mode was finally removed in 2022.

      The Polonius borrow checker spun out of the NLL effort in 2018. The initial formulation passed the NLL test suite and accepted (sound) code that NLL did not. However, performance was a critically- limiting factor; generally borrow check was slower than NLL, but certain programs were considerably slower than NLL to the extent that using that implementation/formulation of Polonius was a non-starter. Attempts were made over the years to implement the Polonius formulation in a performant manner, without much luck in addressing the core issues.

      In 2023, a new formulation of a Polonius-style borrow checker was imagined that required minimal rearchitecture of the existing NLL implementation and could be extended to allow more code to compile. We had hoped, to try to stabilize this new formulation in 2024; but, various things popped up that delayed this.

      But! We're nearly there now! At this point, there are no known remaining issues with the subset coined Polonius Alpha that we intend to stabilize. And, performance is generally acceptable for stabilization (will discuss that a bit below).

      So, we are enabling the Polonius Alpha borrow checker on nightly for testing until we stabilize fully later in the year. We're doing this in order to help find:

      • Any serious performance regressions we're unaware of
      • Unsoundness in the formulation that we haven't thought about
      • Any weird diagnostic issues that we need to improve
        • Note: we have not yet seen any diagnostic changes

      You can report any issues on Github or on Zulip.

      Okay, what's new?

      The key thing that Polonius Alpha enables that NLL does not is flow- sensitive borrow checking of lifetime outlives relationships.

      Perhaps the smallest example demonstrating what will pass with Polonius Alpha but not the current NLL is:

      fn reborrow(a: &mut u8) -> &mut u8 {
          let b = &mut *a;
          if true { b } else { a }
      }
      

      However, the example you will see more often is:

      fn get_mut_or_default<'r, K: Hash + Eq + Copy, V: Default>(
          map: &'r mut HashMap<K, V>,
          key: K,
      ) -> &'r mut V {
          match map.get_mut(&key) {
              Some(value) => value,
              None => {
                  map.insert(key, V::default());
                  map.get_mut(&key).unwrap()
              }
          }
      }
      

      The issue is that the Some(value) => value branch causes the borrow checker to think that the borrow returned by map.get_mut(&key) lives for the entire function (because of the &'r mut V return type), even though that borrow isn't live in the None branch. NLL's analysis is flow-insensitive.

      Polonius Alpha passes this because its analysis is flow-sensitive , and it knows that the borrow isn't live in the None branch.

      Now, Polonius Alpha is not perfect ; some programs that would compile under legacy Polonius (the slow original implementation) don't compile with Polonius Alpha. (This is of course why we call it "Polonius Alpha"). For example:

      struct X { next: Option<Box<X>> }
      
      fn conditional() {
          let mut b = Some(Box::new(X { next: None }));
          let mut p = &mut b;
          while let Some(now) = p {
              if true {
                  p = &mut now.next;
              }
          }
      }
      

      (As a slight note: we have also found programs that compile with Polonius Alpha but not legacy Polonius, so it's not really a full subset.)

      So, what about performance?

      Polonius Alpha currently does strictly equal or more work compared to NLL, so we have been paying particular attention to potential performance regressions.

      From the top ten thousand crates by downloads on crates.io, we have seen relatively few "significant" regressions, and even crates that have a "significant" regression are typically relatively minimal:

      top10k_leaf_graph

      Each point represents a crate within the 10,000 most-downloaded crates. The black line is an arbitrary threshold of significance, set to a 1% regression and quadratically scaled below 30 seconds. Red points are crates that pass this arbitrary regression threshold. X-axis is compile time (for the leaf crate only without dependencies) under NLL; Y-axis is the ratio of compile time under Polonius Time compared to NLL.

      If you look at the top five crates, they are:

      top10k_leaf_table

      Outside the top ten thousand crates, we have focused mainly on crates with many borrows. The worst case we've seen is a 2-3x regression.

      We have done some initial triage of the causes of these regressions and are thinking about the best way to fix them. Though, overall we think these regressions are fairly reasonable even if we can't fix them, given how rare and relatively minimal they are compared to the additional power Polonius Alpha brings over NLL.

      I really don't want this. How do I opt-out?

      To reiterate: this is only being enabled on nightly. But if you want to disable Polonius Alpha, and only use the stable NLL, you can pass -Zpolonius=off to rustc, use RUSTFLAGS=-Zpolonius=off, or with a project's .cargo/config.toml configuration file:

      [target.x86_64-unknown-linux-gnu]
      rustflags = ["-Zpolonius=off"]
      

      If you have to do this, for some reason, please do tell us why on Github or on Zulip.

      What's next?

      Over the next few months, we will be monitoring Github and Zulip for any reported issues about Polonius Alpha. We will also be working to address known performance regressions. Finally, we will be working on internal documentation about the implementation. All prior to stabilization. Then, we are aiming to stabilize prior to the end of the year!

      Although some programs that we want to compile don't work with Polonius Alpha (nor NLL today), we don't currently have any concrete plans to continue active feature work on the Polonius implementation after the stabilization of Polonius Alpha. We expect to continue to optimize the implementation and address any performance regressions for a little while. We will likely come back to Polonius feature-work at some point , but given that Polonius Alpha solves the most-encountered borrow-check issues, we are shifting our time to other high-priority work for the near future.

    14. πŸ”— New Music Releases Northlane - CUT_it rss

      Northlane - a new release is available:

      • 2026-08-04: CUT_it (Single)

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

      Visit muspy for more information.

    15. πŸ”— Ampcode News Attach Anything rss

      You can now upload any file to your orbs for Amp to see and use: videos, logs, PDFs, spreadsheets, datasets, and more.

      What new stuff can you do? Here's what we've found useful so far:

      • Screen-record your app and ask Amp to fix or improve what it sees.
      • Debug issues from log files.
      • Turn presentations and spreadsheets into interactive websites.
      • Generate videos and CAD files from media inputs.
      • Transcribe video and audio.
    16. πŸ”— exe.dev Ghostty in the Machine: The Saga of exe-scroll rss

      Architecture diagram of exe-scroll: a browser running a ghostty wasm
terminal talks over an HTTPS WebSocket (via exeprox) to an exe-scroll attach
client on the user's VM. The attach client exchanges input/output/resize
frames over a unix socket (session.sock) with the exe-scroll session
process, which owns the pty, runs the shell, and embeds a ghostty-vt emulator
so it can replay screen and scrollback on attach. SSH clients attach through
the same socket.

      When you use the mobile or web-based terminals on exe, there are two ghostty instances involved. One is rendering the terminal in the app or the browser (via a ghostty build compiled to WebAssembly). The other is on the VM in the session manager, providing scrollback on reconnection. (Scrollback is more complicated than just replaying all the received bytes, so it helps to re-use Ghostty's excellent terminal support.)

      Whoa! What? Why!?!

      Screen recording of the exe.dev iOS app terminal: flicking through
scrollback of a numbered-lines listing, smoothly scrolling up through earlier
output.

      To make remote terminals work well, you need 4 ingredients:

      1. Network roaming: when the client switches networks, the terminal should reconnect automatically and seamlessly.
      2. Session management: you need to be able to resume a session that you started on your laptop on your phone and vice-versa.
      3. Scrollback: scrolling up should work.
      4. Modern terminal support: colors and so on.

      On exe.dev, a login shell is one to one with an "exe- scroll" session manager process on your VM. We can re-connect to this session by running an "exe-scroll" client (identified by a unix domain socket). We expose this over HTTPS to our clients (whether on the web or a mobile device), and you can connect to those sessions over SSH as well if that's your jam. Clients survive network roaming by retrying when the websocket disconnects. Session management is provided by having multiple exe-scroll processes, each with its own name. Scrollback is provided by that ghostty inside exe-scroll: when you re-connect, we replay the scrollback into your terminal. Modern terminal support is provided by the client, which, in the case of iOS and <vm- name>.xterm.exe.xyz is also Ghostty.

      There has been much prior art on this. Mosh establishes a connection secret over SSH and then the server (which stays put) and the client (which can move around) talk UDP to each other. Its "State Synchronization Protocol" synchronizes the state of the terminal between client and server. Eternal terminal is similar to mosh. It requires running an et server (typically port 2022), uses TCP, establishes a secret over SSH, supports native scrollback, the tmux control protocol, and ssh agent forwarding. Terminal multiplexers like screen, tmux, and zellij manage multiple ptys, and you can re-connect with them remotely. The drawback with terminal multiplexers is that you have to remember to invoke them (or panic install reptyr later) and using them has a learning curve. Tools like dtach, atch, zmx, and abduco all skip the "window management" part of screen/tmux, but just handle attaching and detaching sessions. upterm and tmate let you run a command on one terminal and access it from another. They do this with a relay server. If you don't trust the public relay servers, you need to run your own. tmate has shut down but I've used it to log into GitHub action runners in a pinch. You can also use a different network stack: if you use Tailscale, your SSH session won’t die when you roam networks, because Tailscale is an overlay. autossh is essentially a while true loop that reconnects SSH; you can pair that sort of thing with dtach or tmux. Many web-based terminals are available. gotty or gotty (yes, there are two with the same name) work. ttyd is another. To run these, you need secure HTTPS access to your host. A standard for HTTP-based terminal streams would be a boon to our industry, but right now it’s ad- hoc/unique protocols all the way down (e.g., here’s k8s).

      It seems ridiculous to build something new with so much prior art. We are much indebted to the prior art, especially dtach and zmx. And yet exe-scroll fills a particular exe.dev-shaped niche for our users: it manages only a single session with scrollback and nothing else. It can be paired with exe- ssh (run it with uvx --from 'exe-ssh @ git+https://github.com/boldsoftware/exe.dev.git#subdirectory=exe-ssh' exe-ssh vm-name) to have a connection to an exe.dev VM that survives network roaming. If you’re on an older exe.dev VM, you may need to ssh exe.dev exe-scroll install vm-name or download the binary directly. Give it a whirl!

    17. πŸ”— exe.dev Introducing Auto-Purchasing for Shelley Tokens rss

      We’re happy to announce that you can now enable auto-purchasing of Shelley Tokens. Previously, you had to manually purchase more credits every time you exhausted your token store. With auto-purchasing, you no longer have to take time out of your day to click through the UI.

      We also added safeguards to this feature to avoid runaway spend. There are three options you can configure:

      • A floor amount that triggers a purchase.
      • The number of tokens you wish to purchase each time.
      • A monthly spending cap.

      You can access this feature via the SSH lobby:

        billing auto-purchase status
        billing auto-purchase
        billing auto-purchase --floor=10 --amount=25 --cap=200 --yes
        billing auto-purchase disable
      

      Or from the newly redesigned Shelley page in the dashboard:

      For our friends on Team plans, we are still working on a solution for shared tokens and payment methods. In the meantime, we’ve also enabled auto- purchasing for teams, but remember, it will use your own payment method.

      Go build something!

  4. August 03, 2026
    1. πŸ”— IDA Plugin Updates IDA Plugin Updates on 2026-08-03 rss

      IDA Plugin Updates on 2026-08-03

      New Releases:

      Activity:

      • diffIDA
        • fe0976a7: Rebrand as diffIDA and add agent-oriented binary diffing
      • distro
        • c9238ff6: Add signed manalyze 1.0.0-noble source descriptor (uploaded to PPA)
        • 411df498: Patch Manalyze 1.0.0 to report its real version
        • a4ae8c7b: Add Manalyze 1.0.0-noble PPA package for Noble
      • goldsrc_trackerui
      • hrtng
      • ida-pro-mcp
        • a6ba8eee: perf: vectorized semantic search + embedding-layer cleanup
        • 4d10015b: feat: opt-in Gemini cloud embedding backend
        • 09d6ef59: feat: per-agent SSO and idb-targeted python execution over shared con…
      • IDA-Source2Forge
        • 9304fbbe: feat: name engine functions, recover command handlers, add screenshots
        • 52ea1ec5: feat: source 2 convar and command recovery for ida pro 9.x
      • Luc-Nhan
        • a882ca93: fix(agent): correct indentation, type mutation_log, and fix /case arg
        • 6bee8929: fix(state): preserve nested metadata structure across save/load
        • 44c0a507: fix(annotations): rename RUGUGAN_EVIDENCE_TAG typo to RIKUGAN_EVIDENC…
        • b4d6e022: fix(mutation): add write_file reverse-record + capture_pre_state entry
        • af62fc8c: chore(deps): update tomli requirement from >=2.4.0 to >=2.4.1 (#12)
        • 116960af: chore(deps): update portalocker requirement (#10)
        • cf8c6c6a: chore(deps): update requests requirement from >=2.31.0 to >=2.34.2 (#9)
        • 28760754: chore(deps): update pyyaml requirement from >=6.0 to >=6.0.3 (#8)
        • 30423a0a: chore(deps): bump actions/setup-python from 6 to 7 in the actions gro…
      • pharos
        • 782492fe: Change contact from Cory Cohen to Ed Schwartz
        • b3fba8bd: Merge pull request #339 from sei-eschwartz/master
        • e5700335: Merge pull request #338 from sei-eschwartz/itanium-thunk-splitter
      • twdll
    2. πŸ”— r/LocalLLaMA Only 3 days ago... rss
    3. πŸ”— r/LocalLLaMA Qwen3.8-Max matches Kimi K3 and DeepSeek V4 Flash rss

      Qwen3.8-Max matches Kimi K3 and DeepSeek V4 Flash | Qwen3.8-Max (2.4T) is another massive contribution to the open weight community. On benchmarks, it performs closely to Kimi K3 and DeepSeek V4 flash across all categories and is better at coding and software tasks. Qwen3.8-27B will also be open weight soon too. Weights are being released next week. Pricing:
      Input: $2.0 / M tokens
      Output: $6.0 / M tokens
      Implicit Caching: $0.25 / M tokens submitted by /u/davidthesong
      [link] [comments]
      ---|---

    4. πŸ”— @HexRaysSA@infosec.exchange "In this new world of hacking, how do we optimize the way information is mastodon

      "In this new world of hacking, how do we optimize the way information is relayed and validated in an agent-human hacking environment?"
      @mahaloz explores how LLMs killed the old decompiler-collaboration playbook β€” and what could replace it.

      πŸ‘‰ Check out our latest guest blog: https://hex-rays.com/blog/llms-have- reshaped-how-we-think-about-decompilation-and-collaboration

    5. πŸ”— r/LocalLLaMA The Chinese labs everyone lumps together are making four pretty different bets. I work at one of them. rss

      The Chinese labs everyone lumps together are making four pretty different bets. I work at one of them. | Every time a model drops from a Chinese lab the thread fills with people who already know who made it, and the guess is usually Alibaba. There was a thread here recently asking what separates the open source labs from the frontier labs. It ran to nearly sixty comments and hardly anyone in it separated out the labs on the open source side. They aren't one bloc and haven't been for a while. I work on the Ling models at Ant, so I'm one of the ones getting lumped in. Discount the paragraph about my own employer accordingly. Qwen's bet is distribution. Alibaba ships in every size class and every quantization with day one support in most runtimes, and the result is that a lot of the fine-tunes people build start from a Qwen base. DeepSeek is betting on architecture instead, publishing the paper and the weights the same day and letting the design do the arguing. Moonshot looks like it's playing a longer horizon, willing to look odd for a release cycle if the thing pays off two cycles later. (Zhipu, MiniMax and StepFun are each their own thing again, but four is enough to make the point.) Ant's bet, since I should be specific about my own: serving cost. Ant runs payments, and it's a separate company from Alibaba, which is the mix-up I see most often. The model I work on, Ling-3.0-flash, is 124B total parameters with roughly 5.1B active per token, KDA plus MLA hybrid attention, 262k context. That is a design for running a lot of long agent loops cheaply. It is not a design for topping a leaderboard, and I don't think we'd claim it is. The part of our own version I'd criticize is the release order. We announced first and are opening weights after. SGLang had support on day one, vLLM is waiting on the weights, llama.cpp is still an open PR. DeepSeek would have dropped the weights first and let the serving stack catch up. Ours is the safer sequencing for an infra team and it costs us the goodwill of exactly the people who would otherwise be running it at home. So the thing I'm curious about here: when you see an announcement out of a Chinese lab, does knowing which lab change how you read it, or is that distinction only interesting from the inside? submitted by /u/AcanthisittaOk1699
      [link] [comments]
      ---|---

    6. πŸ”— r/LocalLLaMA I CANNOT believe I've got DeepSeek-V4-Flash-0731, a frontier model, running on my home PC. Insane! rss

      So this is the stuff of absolute insanity. In less than 20 months we've gone from super expensive cloud models only, to being able to run a Q3 quant of DeepSeek on an Intel Windows PC with a very average 24GB of VRAM. No wonder the big boys are panicking (and yes it's slow as porridge). https://ibb.co/zTvqR8YR

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

    7. πŸ”— Anton Zhiyanov Going Backward rss

      Go's standard library has a slices package with a function called Backward. It lets you iterate over the elements of a slice in reverse order:

      // Backward returns an iterator over index-value pairs in the slice,
      // traversing it backward with descending indices.
      func Backward[Slice ~[]E, E any](s Slice) iter.Seq2[int, E]
      

      If you're not deeply familiar with generics and iterators, the natural reaction to this signature (and to the others in the slices package) is: "couldn't this have been made simpler somehow?"

      To answer that, let's run a thought experiment. Let's picture ourselves as a distant ancestor, living in the pre-iterator era, who decided to implement Backward from scratch.

      Our imaginary ancestor doesn't work at Google, so don't project their decisions onto the Go development team. They had their own reasons β€” and no Jira.

      1. A slice in reverse A pleasant, sunny summer day, birds singing. You're at the keyboard as usual, and suddenly you decide to write a function for walking a slice in reverse order. Anything beats working on yet another Jira ticket. // Backward returns the slice in reverse order. func Backward []T { n := len(s) res := make([]T, n) for i := n - 1; i >= 0; i-- { res[n-1-i] = s[i] } return res } Usage example: s := []int{11, 22, 33, 44, 55} b := Backward(s) fmt.Println(b) // [55 44 33 22 11] The implementation is simple and works reliably. There's one drawback, though: Backward creates a copy of the slice, which can be wasteful for large slices. Besides, the sun has hidden behind a cloud, and it looks like rain is coming. You decide to work a bit more. 2. Gimme, gimme, gimme

      To avoid copying the slice, you decide to return a closure that knows the current position in the original slice and returns the next element on each call:

      // Backward returns a function that, on each call, returns the next
      // element of the slice (in reverse order) and a flag indicating
      // whether to continue iterating (false means done).
      func Backward[T any](s []T) func() (T, bool) {
          i := len(s)
          return func() (T, bool) {
              if i == 0 {
                  var zero T
                  return zero, false
              }
              i--
              return s[i], true
          }
      }
      

      Usage example:

      s := []int{11, 22, 33, 44, 55}
      next := Backward(s)
      for {
          v, ok := next()
          if !ok {
              break
          }
          fmt.Print(v, " ")
      }
      fmt.Println()
      // 55 44 33 22 11
      

      Now it allocates O(1) memory instead of O(n). That's better.

      Before moving on, you glance out of the window. Yep, sure enough, the rain has started, and the sky is even cloudier than before. Excellent working weather!

      3. A callback-based iterator Something about the calling code keeps bothering you. It came out rather imperative. You'd like to hand the loop mechanics over to Backward and leave the caller with nothing but the application logic (whatever it is you do with the slice elements). You decide to complicate Backward's signature a little. Now it will return an iterator function that takes a callback as an argument and applies it to each element of the slice: // Backward returns a function that takes a yield callback. // The callback is invoked for each element of the slice (in reverse order). func Backward func(yield func(T) bool) { return func(yield func(T) bool) { for i := len(s) - 1; i >= 0; i-- { if !yield(s[i]) { return } } } } The yield function returns a bool β€” that's so the callback can signal when it wants to stop the traversal early. Now you can turn the for loop body in the calling code into a callback, and you don't need the loop anymore: work := func(x int) bool { if x < 30 { return false // early exit } fmt.Print(x, " ") return true } s := []int{11, 22, 33, 44, 55} it := Backward(s) it(work) fmt.Println() // 55 44 33 Mmm, very functional. One small nuance: Backward's signature looks a bit heavy. You add a separate type for the return value: // Seq is an iterator over sequences of individual values. // When called as seq(yield), seq calls yield(v) for each value // v in the sequence, stopping early if yield returns false. type Seq[T any] func(yield func(T) bool) The function looks much better now: func Backward[T any](s []T) Seq[T] { // body unchanged } Praising yourself for inventing the iterator, you walk over to the window. It looks like the weather's gotten worse. The rain is coming down in buckets, and the sky is so overcast that it's grown as dark as evening. 4. Iterator 2: Return of the Iterator

      It's all great, but then it hits you: an ordinary range over a slice returns both the index and the element's value. Your iterator returns only the value. You decide to fix this vexing oversight:

      func Backward[T any](s []T) func(yield func(int, T) bool) {
          return func(yield func(int, T) bool) {
              for i := len(s) - 1; i >= 0; i-- {
                  if !yield(i, s[i]) {
                      return
                  }
              }
          }
      }
      

      Usage example:

      work := func(i int, x int) bool {
          fmt.Print(i, ":", x, " ")
          return true
      }
      
      s := []int{11, 22, 33, 44, 55}
      it := Backward(s)
      it(work)
      fmt.Println()
      // 4:55 3:44 2:33 1:22 0:11
      

      Since the result's signature has changed, it no longer fits the Seq type. What can you do β€” you'll have to add a new type. After ten minutes of deliberation, you decide to call it Seq2:

      // Seq2 is an iterator over sequences of key-value pairs.
      // When called as seq(yield), seq calls yield(k, v) for each pair
      // (k, v) in the sequence, stopping early if yield returns false.
      type Seq2[K any, V any] func(yield func(K, V) bool)
      
      
      
      func Backward[T any](s []T) Seq2[int, T] {
          // body unchanged
      }
      

      You get up to stretch your legs, and go to the window. The downpour is so heavy you can't make anything out. Lightning is flashing. Hail the size of your fist is falling β€” you've never seen anything like it in your life. Well, these things happen!

      5. Not quite a slice

      Have you thought of everything? Seems so. But you're not going back to Jira tickets just yet. Refreshing your memory of the Go spec, you realize that besides ordinary slices there are "user-defined" ones β€” types whose underlying type is a slice:

      // IDs is a slice of identifiers.
      type IDs []int
      

      Backward works perfectly well with IDs β€” the compiler accepts a value of type IDs since its underlying type is []int:

      ids := IDs{11, 22, 33, 44, 55}
      it := Backward(ids)
      it(work)
      fmt.Println()
      // 4:55 3:44 2:33 1:22 0:11
      

      But what about this?

      // backwardIDs builds an iterator over a slice of identifiers
      // in reverse order.
      var backwardIDs func(IDs) Seq2[int, int] = Backward[int]
      // ERROR: cannot use Backward[int]
      // (value of type func(s []int) Seq2[int, int])
      // as func(IDs) Seq2[int, int] value in variable declaration
      

      Here's where the difference between IDs and []int shows up.

      When you assign the function itself, it's the signatures that get compared: func(IDs) Seq2[int, int] versus func([]int) Seq2[int, int]. Signatures match only if the parameter types are identical. But IDs and []int are different, even though one is based on the other. The signatures differ β†’ you get an error.

      Scratching your head, you turn to the spec once again and find a special generic syntax: ~T. It represents the set of all types whose underlying type is T. Just what you need!

      Now you'll have to parameterize not only the element type (E) but the slice type (Slice) as well. E is needed for the returned values, while Slice lets the function accept not just []E, but any types based on it:

      func Backward[Slice ~[]E, E any](s Slice) Seq2[int, E] {
          return func(yield func(int, E) bool) {
              for i := len(s) - 1; i >= 0; i-- {
                  if !yield(i, s[i]) {
                      return
                  }
              }
          }
      }
      

      Now the example:

      var backwardIDs func(IDs) Seq2[int, int] = Backward[IDs, int]
      
      ids := IDs{11, 22, 33, 44, 55}
      work := func(i int, x int) bool {
          fmt.Print(i, ":", x, " ")
          return true
      }
      it := backwardIDs(ids)
      it(work)
      fmt.Println()
      // 4:55 3:44 2:33 1:22 0:11
      

      It works! You've ended up with something similar to Backward from the slices package.

      You exhale wearily and walk over to the window. The downpour and hail have given way to a hurricane. Trees and billboards go flying past. Toads, for some reason, are falling from the sky.

      6. Iterator 3: Judgment Day

      To take your mind off the strange events outside the window, you keep pondering.

      An ordinary Backward is already great. But it would be even better if the traversal logic itself were configurable. On the other hand, if you end up with a lot of parameters, a strategy would suit better. And, by the way, it wouldn't hurt to add a factory that produces iterator factories according to given criteria...

      Before you can finish the thought, the ground outside the window tears open with a deafening roar. An enormous black hand, streaming molten lava and flickering flames, bursts out of the fissure, seizes you, and drags you straight down to hell.

      P.S. Despite the article's tongue-in-cheek tone, the "complicated" version in the standard library is justified (Backward just follows suite with other package functions). But if you're doing something similar in a project that solves a specific problem β€” it might make sense to stop at the simpler option.

    8. πŸ”— r/LocalLLaMA Daniel Han of Unsloth validates Qwen3.8-27B will run only 17GB VRAM rss

      Daniel Han of Unsloth validates Qwen3.8-27B will run only 17GB VRAM | Super excited about this release for the new 27B. Who else is with me. Only 17GB VRAM needed 😍😍 submitted by /u/quantier
      [link] [comments]
      ---|---

    9. πŸ”— r/LocalLLaMA MiniMax-H3 now on huggingface rss

      MiniMax-H3 now on huggingface | MiniMax H3 is a general-purpose, omni-modal generative system. It supports unified understanding of multimodal contexts composed of text, images, video, and audio, and can generate video with native stereo audio at resolutions up to 2K and durations of up to 15 seconds. Thanks to its task-generalization-oriented system design, H3 already possesses broad multimodal context understanding and generation capabilities at the pre-training stage, enabling outstanding performance in following complex multimodal instructions. submitted by /u/Mobile-Pumpkin7944
      [link] [comments]
      ---|---

    10. πŸ”— smol-machines/smolvm smolvm v1.7.4 release

      What's Changed

      • Ship the disk templates zstd-compressed and expand them to sparse files on first use by @BinSquare in #771
      • Copy the storage template by seeking between its data extents instead of scanning its whole logical size by @BinSquare in #770
      • Harden fused rollout lifecycle by @BinSquare in #801
      • Avoid copying CUDA module state for clone channels by @BinSquare in #804
      • Load device-resident LoRA policies through managed executors by @BinSquare in #806
      • Reject a registry-image machine that has no network at create instead of failing every start with a raw DNS error by @BinSquare in #807
      • Perform machine file reads and writes inside the running workload container so uploads are visible to exec by @BinSquare in #810
      • Reuse CUDA module handoffs across clone workers by @BinSquare in #808
      • Cache pulled OCI images on the host so repeat ephemeral machine runs skip the registry pull by @BinSquare in #805
      • Signal guest boot-readiness with an event-driven vsock doorbell as the primary ready signal, keeping the marker file and control-channel ping as fallbacks by @BinSquare in #811
      • Map CUDA module handoffs across clone workers by @BinSquare in #814
      • Preserve per-device GPU admission headroom by @BinSquare in #826
      • Promote CUDA pool readiness and refill improvements by @BinSquare in #828
      • Bump the workspace to 1.7.3 by @BinSquare in #829
      • Install the zstd-compressed disk templates in the Arch package so the build no longer fails on the removed uncompressed storage template by @BinSquare in #830
      • Set the library search path on the boot subprocess before launch so libkrun can load libkrunfw when embedded without a wrapper script by @BinSquare in #832
      • Make fork-pool lease activation retry-safe by @BinSquare in #831

      Full Changelog : v1.7.2...v1.7.4

    11. πŸ”— r/LocalLLaMA Qwen3.8-27B announced alongside Qwen3.8-Max rss
    12. πŸ”— smol-machines/smolvm smolvm v1.7.3 release

      What's Changed

      • Ship the disk templates zstd-compressed and expand them to sparse files on first use by @BinSquare in #771
      • Copy the storage template by seeking between its data extents instead of scanning its whole logical size by @BinSquare in #770
      • Harden fused rollout lifecycle by @BinSquare in #801
      • Avoid copying CUDA module state for clone channels by @BinSquare in #804
      • Load device-resident LoRA policies through managed executors by @BinSquare in #806
      • Reject a registry-image machine that has no network at create instead of failing every start with a raw DNS error by @BinSquare in #807
      • Perform machine file reads and writes inside the running workload container so uploads are visible to exec by @BinSquare in #810
      • Reuse CUDA module handoffs across clone workers by @BinSquare in #808
      • Cache pulled OCI images on the host so repeat ephemeral machine runs skip the registry pull by @BinSquare in #805
      • Signal guest boot-readiness with an event-driven vsock doorbell as the primary ready signal, keeping the marker file and control-channel ping as fallbacks by @BinSquare in #811
      • Map CUDA module handoffs across clone workers by @BinSquare in #814
      • Preserve per-device GPU admission headroom by @BinSquare in #826
      • Promote CUDA pool readiness and refill improvements by @BinSquare in #828

      Full Changelog : v1.7.2...v1.7.3