- ↔
- →
- September 26, 2026
-
🔗 Anton Zhiyanov Go concurrency distilled rss
This mini-book provides a brief overview of many concurrency topics in Go. Each topic comes with interactive examples — feel free to experiment with them by changing the code and clicking Run. There's also a PDF version with static examples.
This is a quick refresher on Go concurrency, not a beginner's guide. If you want to learn concurrency from the ground up with practical exercises, check out my other book — Gist of Go: Concurrency.
The book is AI-free.
Goroutines • Channels • Select • Pipelines • Time • Context • Wait groups • Data races • Race conditions • Mutexes • Semaphores • Signaling • Run once • Object pool • Atomics • Testing • Scheduling • Diagnostics • Final thoughts
# Goroutines The foundation of concurrency in Go is goroutines – functions started with the go keyword: func main() { var wg sync.WaitGroup wg.Add(2) go func() { defer wg.Done() fmt.Println("worker 1") }() go func() { defer wg.Done() fmt.Println("worker 2") }() wg.Wait() } worker 2 worker 1 The Go runtime juggles these goroutines and distributes them among operating system threads running on CPU cores. Compared to OS threads, goroutines are lightweight, so you can create hundreds or thousands of them. Goroutines are completely independent. The main function is also a goroutine, but it starts implicitly when the program starts. When main ends, other goroutines also shut down. We use a wait group (sync.WaitGroup) to wait for goroutines to finish in the example above. A wait group has a counter inside. Calling Add(n) increments it by n, while Done() decrements it by one. Wait() blocks the calling goroutine (in this case, main) until the counter reaches zero. This way, main waits for both workers to finish before it exits. WaitGroup.Go automatically increments the wait group counter, runs a function in a goroutine, and decrements the counter when it's done: func main() { var wg sync.WaitGroup wg.Go(func() { fmt.Println("worker 1") }) wg.Go(func() { fmt.Println("worker 2") }) wg.Wait() } worker 2 worker 1 # Channels Goroutines can pass values to each other through channels. A channel is like a window where one goroutine can throw something and another can catch it: func main() { messages := make(chan string) go func() { messages <- "ping" }() msg := <-messages fmt.Println(msg) } ping Sending a value through a channel is a synchronous operation. When the sending goroutine writes a value to the channel (ch <- val), it blocks and waits for someone to receive that value (<-ch). Only then does it continue. Output channel Returning an output channel from a function and filling it within an internal goroutine is a common pattern in Go. This allows the caller to receive values through the channel while the owning function retains control of it: func generate(start, stop int) chan int { out := make(chan int) go func() { for i := start; i < stop; i++ { out <- i } }() return out } Closing a channel To signal readers that all data has been sent, the writer goroutine closes the channel with close(): func generate(start, stop int) chan int { out := make(chan int) go func() { defer close(out) for i := start; i < stop; i++ { out <- i } }() return out } The reader checks the channel's status with a second value ("comma OK") when reading: func main() { in := generate(5, 10) for { num, ok := <-in if !ok { break } fmt.Print(num, " ") } } 5 6 7 8 9 While the channel is open, the reader receives the next value and a true status. If the channel is closed, the reader gets a zero value and a false status. A channel can only be closed once. Closing it again or writing to a closed channel causes a panic. The only reason to close a channel is to signal to its readers that all data has been sent. If this isn't important to the readers, then you don't need to close it. When a channel is no longer used, Go's garbage collector will free its resources, whether it's closed or not. Channel iteration range automatically reads the next value from the channel and checks if it's closed. If the channel is closed, it exits the loop: func main() { nums := generate(5, 10) for n := range nums { fmt.Print(n, " ") } } 5 6 7 8 9 Range over a channel returns a single value, not a pair, unlike range over a slice. Directional channels You can protect yourself from accidental write/close errors by setting the channel direction. Channels can be: chan (bidirectional): for reading and writing (default); chan<- (send-only): for writing only; <-chan (receive-only): for reading only. You can't read from a send-only channel or write to a receive-only channel (nor can you close it). Channels are usually initialized for both reading and writing, and specified as directional in function parameters. Go automatically converts a regular channel to a directional one: stream := make(chan int) go func(in chan<- int) { in <- 42 }(stream) func(out <-chan int) { fmt.Println(<-out) }(stream) 42 Buffered channels Buffered channels work like a FIFO queue with a fixed-size buffer for storing values. As long as the buffer has free space, writing to the channel doesn't block the goroutine. Similarly, as long as the buffer contains values, reading from the channel doesn't block the goroutine: stream := make(chan int, 3) stream <- 11 stream <- 12 stream <- 13 fmt.Println(<-stream) fmt.Println(<-stream) 11 13 By default, if you don't specify a buffer size, a channel is unbuffered (buffer size equals zero). Buffered channels work with the built-in len() and cap() functions: stream := make(chan int, 3) stream <- 11 fmt.Println(cap(stream), len(stream)) 3 1 Reading from a closed buffered channel returns values from the buffer and a true status. Once all values are taken, it returns a zero value and a false status, like a regular channel: stream := make(chan int, 1) stream <- 11 close(stream) val, ok := <-stream fmt.Println(val, ok) // 11 true val, ok = <-stream fmt.Println(val, ok) // 0 false 11 true 0 false nil channel Like any type in Go, channels have a zero value, which is nil. Writing to or reading from a nil channel blocks the goroutine indefinitely: var stream chan int go func() { // blocks forever stream <- 1 }() // blocks forever <-stream Closing a nil channel causes a panic: var stream chan int close(stream) // panic: close of nil channel # Select The select statement is somewhat like switch, but specifically designed for channels. Here's what it does: Checks which cases are not blocked. If multiple cases are ready, randomly selects one to execute. If all cases are blocked and there is a default case, executes it. If all cases are blocked and there is no default case, waits until one is ready. Select is used to manage data flow in pipelines: // merge sends values from in1 and in2 to the output channel. func merge(in1, in2 <-chan int) <-chan int { out := make(chan int) go func() { defer close(out) for in1 != nil || in2 != nil { select { case val1, ok := <-in1: if ok { out <- val1 } else { in1 = nil } case val2, ok := <-in2: if ok { out <- val2 } else { in2 = nil } } } }() return out } // Suppose we send 10..12 to in1, 20..22 to in2, // and call merge(in1, in2) 10 11 20 12 21 22 To cancel goroutines: // process modifies values from in and send them to out // until in is exhausted or cancel is closed. func process(cancel chan struct{}, in <-chan int) <-chan int { out := make(chan int) go func() { for val := range in { select { case out <- val*10: case <-cancel: fmt.Println("canceled") return } } }() return out } // Suppose we send values 11 and 12 to in // and then call close(cancel) 110 120 canceled For non-blocking operations: // multiplier returns a function that multiplies // the input by 10 and sends it to the channel // or returns an error if the channel is busy. func multiplier(ch chan<- int) func(n int) error { return func(n int) error { select { case ch <- n*10: return nil default: return errors.New("busy") } } } func main() { nums := make(chan int, 1) multiply := multiplier(nums) err := multiply(11) fmt.Println(<-nums, err) // 110 <nil> err = multiply(12) fmt.Println(<-nums, err) // 120 <nil> err = multiply(13) err = multiply(14) fmt.Println(err) // busy } 110 <nil> 120 <nil> busy And for much more. # Pipelines A pipeline is a sequence of operations where each step takes input data, processes it in a specific way, and outputs it. The input and output of each operation is a channel. A typical pipeline looks like this: Reader : Reads input data from a file, database, or network. N processors : Transform, filter, aggregate, or enrich data using external sources. Writer : Writes the processed data to a file, database, or network. func readT any <-chan T { out := make(chan T) go func() { defer close(out) for { // read data from somewere data := // ... out <- data } }() return out } func processT any <-chan T { out := make(chan T) go func() { defer close(out) for inData := range in { // process the data outData = // ... out <- outData } }() return out } func writeT any <-chan struct{} { done := make(chan struct{}) go func() { defer close(done) for data := range in { // write the data } }() return done } Output channel A goroutine can signal other goroutines that it has finished its work using an output channel : func generate(start, stop int) <-chan int { out := make(chan int) go func() { defer close(out) for i := start; i < stop; i++ { out <- i } }() return out } func main() { nums := generate(5, 10) for n := range nums { fmt.Print(n, " ") } } 5 6 7 8 9 Done channel If a goroutine doesn't need to return results, it can signal completion using a done channel : func work() <-chan struct{} { done := make(chan struct{}) go func() { defer close(done) fmt.Println("work done") }() return done } func main() { done := work() <-done } work done Cancel channel To terminate a goroutine early, a calling goroutine can use a cancel channel : func generate(cancel chan struct{}, n int) <-chan int { out := make(chan int) go func() { defer close(out) for i := 1; i <= n; i++ { select { case out <- i: case <-cancel: return } } }() return out } func main() { cancel := make(chan struct{}) defer close(cancel) nums := generate(cancel, 10) fmt.Println(<-nums) fmt.Println(<-nums) fmt.Println(<-nums) } 1 2 3 Error handling There are three approaches to error handling in concurrent pipelines. ➊ Return on the first error: // calculate produces answers for the given numbers. func process(in <-chan int) (<-chan int, <-chan error) { out := make(chan Answer) errc := make(chan error, 1) go func() { defer close(out) for n := range in { ans, err := fetchAnswer(n) if err != nil { errc <- err // return with error return } out <- ans } errc <- nil // return with nil }() return out, errc } ➋ Use a result type: // Result contains an answer or an error. type Result struct { answer int err error } // calculate produces answers for the given numbers. func calculate(in <-chan int) <-chan Result { out := make(chan Result) go func() { defer close(out) for n := range in { ans, err := fetchAnswer(n) out <- Result{ans, err} // return answer + error } }() return out } ➌ Collect errors separately: // calculate produces answers for the given numbers. func calculate(in <-chan int, errc chan<- error) <-chan int { out := make(chan Answer) go func() { defer close(out) for n := range in { ans, err := fetchAnswer(n) if err == nil { out <- ans // send answer } else { errc <- err // or error } } }() return out } # Time Besides handling date and time, the time package offers tools for managing time-sensitive operations in concurrent programs. After time.After() returns a channel that is initially empty, but receives a value after the timeout period. It's useful for timing out operations: // withTimeout executes a function with a given timeout. func withTimeout(timeout time.Duration, fn func()) error { done := make(chan struct{}) go func() { defer close(done) fn() }() // blocks until fn completes or the timer expires, // whichever happens first select { case <-done: return nil case <-time.After(timeout): return errors.New("timeout") } } withTimeout() waits for fn() to complete, but thanks to time.After(), it won't wait longer than the timeout duration: func main() { var err error // completes in time err = withTimeout( 50*time.Millisecond, func() { fmt.Println("work done") }, ) fmt.Println("err =", err) // gets canceled on timeout err = withTimeout( 50*time.Millisecond, func() { time.Sleep(100 * time.Millisecond) fmt.Println("work done") }, ) fmt.Println("err =", err) } work done err = <nil> err = timeout Timer A timer (time.Timer) is a structure with a C channel to which it sends the current time when it triggers (expires). Timers are useful for planning future executions: done := make(chan struct{}) timer := time.NewTimer(50 * time.Millisecond) go func() { eventTime := <-timer.C // blocks for 50ms fmt.Println("work done at", eventTime) close(done) }() <-done work done at 2009-11-10 23:00:00.05 Stop() stops the timer and returns true if it hasn't expired yet, and false otherwise: // timer expires after 50ms timer := time.NewTimer(50 * time.Millisecond) go func() { eventTime := <-timer.C fmt.Println("work done at", eventTime) }() // after 10ms, the timer hasn't expired yet time.Sleep(10 * time.Millisecond) if timer.Stop() { fmt.Println("execution canceled") } else { fmt.Println("too late to cancel") } execution canceled It's often more convenient to use the time.AfterFunc() wrapper function. It waits for duration d and then executes function f: done := make(chan struct{}) work := func() { fmt.Println("work done") close(done) } // executes work after 50ms time.AfterFunc(50*time.Millisecond, work) <-done work done time.AfterFunc() returns a timer that you can cancel before execution starts: // executes the function after 50ms timer := time.AfterFunc(50*time.Millisecond, func() {}) // after 10ms, the timer hasn't expired yet time.Sleep(10 * time.Millisecond) if timer.Stop() { fmt.Println("execution canceled") } execution canceled If a timer is used in a loop, it's better to create a single timer and reset it instead of creating a new instance on each iteration: // consumer reads tokens from the input channel and alerts // if a value does not appear in a channel after an hour. func consumer(in <-chan token) { const timeout = time.Hour timer := time.NewTimer(timeout) for { timer.Reset(timeout) select { case <-in: // do stuff case <-timer.C: // log warning } } } // Suppose we send 10,000 values to the in channel // and measure memory usage. Memory used: 4 KB, # allocations: 6 Ticker A ticker is like a timer, but it keeps firing until you stop it. Tickers are useful for executing periodic tasks: // fires every 50ms ticker := time.NewTicker(50 * time.Millisecond) defer ticker.Stop() go func() { for { // waits for ticker to fire on each iteration at := <-ticker.C fmt.Println("work done at", at) } }() // enough time for the ticker to fire 3 times time.Sleep(160*time.Millisecond) ticker.Stop() work done at 2009-11-10 23:00:00.05 work done at 2009-11-10 23:00:00.10 work done at 2009-11-10 23:00:00.15 NewTicker(d) creates a ticker that sends the current time to the channel C at interval d. You must stop the ticker eventually with Stop() to free up resources. If the channel reader can't keep up with the ticker, the ticker will skip ticks. # Context The main purpose of context is to cancel operations, either manually or by timeout/deadline. The function accepts a context and uses its Done() channel to listen for cancellation: // work performs a task for 50 ms unless canceled. // Returns an error when canceled. func work(ctx context.Context) error { done := make(chan struct{}) go func() { time.Sleep(50 * time.Millisecond) fmt.Println("work done") close(done) }() select { case <-done: return nil case <-ctx.Done(): return ctx.Err() } } Cancel manually (context.Canceled error): func main() { // empty context ctx := context.Background() // manual canellation context ctx, cancel := context.WithCancel(ctx) defer cancel() done := make(chan struct{}) go func() { // takes 50 ms unless canceled err := work(ctx) fmt.Println("err =", err) close(done) }() // cancels after 10 ms time.Sleep(10 * time.Millisecond) cancel() <-done } err = context canceled Cancel by timeout (context.DeadlineExceeded error): func main() { ctx := context.Background() // cancels after 10 ms ctx, cancel := context.WithTimeout(ctx, 10*time.Millisecond) defer cancel() done := make(chan struct{}) go func() { // takes 50 ms unless canceled err := work(ctx) fmt.Println("err =", err) close(done) }() <-done } err = context deadline exceeded Cancel by deadline (context.DeadlineExceeded error): func main() { ctx := context.Background() // cancels at now + 10 ms deadline := time.Now().Add(10 * time.Millisecond) ctx, cancel := context.WithDeadline(ctx, deadline) defer cancel() done := make(chan struct{}) go func() { // takes 50 ms unless canceled err := work(ctx) fmt.Println("err =", err) close(done) }() <-done } err = context deadline exceeded Context is layered. A context object is immutable. To add new properties to a context, a new (child) context is created based on the old (parent) context. The shorter timeout between the parent and child contexts always wins. The child context can only shorten the parent's timeout, not extend it: func main() { // parent context with a 100 ms timeout const dur100ms = 100 * time.Millisecond parentCtx, cancel := context.WithTimeout(context.Background(), dur100ms) defer cancel() // child context with a 10 ms timeout const dur10ms = 10 * time.Millisecond childCtx, cancel := context.WithTimeout(parentCtx, dur10ms) defer cancel() // now the work gets canceled err := work(childCtx) fmt.Println("err =", err) } err = context deadline exceeded Multiple cancels are safe. You can call cancel() on the context as many times as you want. The first cancel will work, and the rest will be ignored. You can specify a custom cancellation cause using context.WithCancelCause(), context.WithTimeoutCause() and context.WithDeadlineCause(). This cause is accessible through context.Cause(): ctx, cancel := context.WithCancelCause(context.Background()) cancel(errors.New("the night is dark")) fmt.Println(context.Cause(ctx)) the night is dark You can register a function to execute when the context is canceled with context.AfterFunc(): ctx, cancel := context.WithCancel(context.Background()) cleanup := func() { fmt.Println("cleanup") } context.AfterFunc(ctx, cleanup) cancel() time.Sleep(10 * time.Millisecond) cleanup Context can pass additional information about a call using context.WithValue(), which creates a context with a value for a specific key. But it's generally better to avoid passing values in context. It's better to use explicit parameters or custom structs instead. # Wait groups The sync.WaitGroup type lets you wait for one or more goroutines to finish: const n = 10 var wg sync.WaitGroup wg.Add(n) for range n { go func() { defer wg.Done() fmt.Print(".") }() } wg.Wait() .......... A WaitGroup doesn't know anything about the goroutines it manages. It works with an internal counter. Calling wg.Add(1) increments the counter by one, while wg.Done() decrements it. wg.Wait() blocks the calling goroutine until the counter reaches zero. The Go method combines Add, starting a goroutine, and Done: var wg sync.WaitGroup for range 10 { wg.Go(func() { fmt.Print(".") }) } wg.Wait() .......... All methods are safe to use from multiple goroutines. Normally, all Add calls happen before Wait. But technically, there's nothing stopping you from doing some of the Add calls before Wait and some after (from another goroutine). You can call Wait from multiple goroutines. They will all block until the group's counter reaches zero. # Data races A data race happens when multiple goroutines access shared data, and at least one of them modifies it. We need to protect the data from this kind of concurrent access. A data race doesn't always cause a runtime panic. That's why Go provides a special tool called the race detector. You can turn it on with the race flag, which works with the test, run, build, and install commands. var total int // There's a data race on total. var wg sync.WaitGroup wg.Go(func() { total++ }) wg.Go(func() { total++ }) wg.Wait() fmt.Println("total:", total) total: 2 go run -race main.go ================== WARNING: DATA RACE ... 2 Found 1 data race(s) Channels are safe for concurrent reading and writing, and they don't cause data races. Ways to prevent data races: Avoid concurrent data modification (typically by using channels). Synchronize access with mutexes. Use only atomic operations. Race conditions A race condition happens when an unpredictable order of operations from multiple goroutines leads to an incorrect system state: // There's a race condition when working with balance. withdraw := func(amount int) { if getBalance() < amount { return } time.Sleep(time.Millisecond) setBalance(getBalance() - amount) } setBalance(50) var wg sync.WaitGroup wg.Go(func() { withdraw(40) }) wg.Go(func() { withdraw(40) }) wg.Wait() fmt.Println("balance:", getBalance()) balance: -30 If individual operations are concurrent-safe, Go's race detector won't find any issues. Because of this, it doesn't catch race conditions: go run -race main.go balance: -30 You can't fully eliminate uncertainty in a concurrent environment. Events will happen in an unpredictable order — that's just how concurrency works. However, you can prevent a race condition — often by protecting a composite operation with a mutex: var mu sync.Mutex withdraw := func(amount int) { mu.Lock() defer mu.Unlock() if getBalance() < amount { return } time.Sleep(time.Millisecond) setBalance(getBalance() - amount) } setBalance(50) var wg sync.WaitGroup wg.Go(func() { withdraw(40) }) wg.Go(func() { withdraw(40) }) wg.Wait() fmt.Println("balance:", getBalance()) balance: 10 Compare-and-set Sometimes you can prevent a race condition without using mutexes by applying an atomic compare-and-set operation or one of its flavors: // CompareAndSet changes the value to new if the current value equals old. // Returns true if the value was changed. CompareAndSet(old, new any) bool // CompareAndSwap changes the value to new if the current value equals old. // Returns the old value. CompareAndSwap(old, new any) any // CompareAndDelete deletes the value if the current value equals old. // Returns true if the value was deleted. CompareAndDelete(old any) bool // etc The idea is always the same: Check if the assumed (old) state matches reality. If it does, change the state to new. If not, do nothing. # Mutexes The sync.Mutex type protects shared data and parts of your code from being accessed concurrently: var total int var mu sync.Mutex var wg sync.WaitGroup for range 100 { wg.Go(func() { mu.Lock() time.Sleep(time.Millisecond) total++ mu.Unlock() }) } wg.Wait() total: 100 The mutex guarantees that only one goroutine can run the code between Lock() and Unlock() at a time. A mutex is used in these situations: When multiple goroutines are modifying the same data. When one goroutine is modifying the data and others are reading it. If all goroutines are only reading the data, you don't need a mutex. TryLock The TryLock method tries to lock the mutex, just like a regular Lock. But if it can't, it returns false right away instead of blocking the goroutine: var total int var mu sync.Mutex var wg sync.WaitGroup for range 100 { wg.Go(func() { if !mu.TryLock() { return } defer mu.Unlock() time.Sleep(time.Millisecond) total++ }) } wg.Wait() total: 1 RWMutex The sync.RWMutex type distinguishes between readers and writers. It provides two sets of methods: Lock / Unlock lock and unlock the mutex for both reading and writing. RLock / RUnlock lock and unlock the mutex for reading only. var total int var mu sync.RWMutex var wg sync.WaitGroup // 10 writers. for range 10 { wg.Go(func() { mu.Lock() defer mu.Unlock() time.Sleep(time.Millisecond) total++ }) } // 10 readers. for range 10 { wg.Go(func() { // Try switching from RLock/RUnlock to Lock/Unlock //and see how it affects the elapsed time. mu.RLock() defer mu.RUnlock() time.Sleep(time.Millisecond) _ = total }) } wg.Wait() elapsed: 10ms Here's how it works: If a goroutine locks the mutex with Lock(), other goroutines will be blocked if they try to use Lock() or RLock(). If a goroutine locks the mutex with RLock(), other goroutines can also lock it with RLock() without being blocked. If at least one goroutine has locked the mutex with RLock(), other goroutines will be blocked if they try to use Lock(). This creates a "single writer, multiple readers" setup. Locker Both sync.Mutex and sync.RWMutex implement the same sync.Locker interface: type Locker interface { Lock() Unlock() } By using Locker instead of a specific mutex type, you can build components that don't depend on a specific lock implementation. This lets the client decide which lock to use. Channel as mutex You can use a channel instead of a mutex to protect shared data: var total int lock := make(chan struct{}, 1) var wg sync.WaitGroup wg.Go(func() { lock <- struct{}{} defer func() { <-lock }() total++ }) wg.Go(func() { lock <- struct{}{} defer func() { <-lock }() total++ }) wg.Wait() total: 2 # Semaphores A semaphore is like a container with N available slots and two operations: acquire to take a slot and release to free a slot. Here are the semaphore rules: Calling acquire takes a free slot. If there are no free slots, acquire blocks the goroutine that called it. Calling release frees up a previously taken slot. If there are any goroutines blocked on acquire when release is called, one of them will immediately take the freed slot and unblock. You can implement a simple semaphore with a buffered channel, where N is the channel's size. To acquire the semaphore, send a value into the channel. To release it, take a value from the channel: // Try changing nConc and see how the elapsed time changes. const nConc = 4 const nCalls = 100 sema := make(chan struct{}, nConc) var wg sync.WaitGroup for range nCalls { sema <- struct{}{} // acquire wg.Go(func() { defer func() { <-sema }() // release time.Sleep(time.Millisecond) // do some work }) } wg.Wait() elapsed: 25ms For more complex situations, use the golang.org/x/sync/semaphore package. Rendezvous A rendezvous lets two goroutines wait for each other: There are two goroutines — G1 and G2 — and each one can signal that it's ready. If G1 signals but G2 hasn't yet, G1 blocks and waits. If G2 signals but G1 hasn't yet, G2 blocks and waits. When both have signaled, they both unblock and continue running. You can implement a simple rendezvous with a wait group: var rend sync.WaitGroup rend.Add(2) var wg sync.WaitGroup wg.Go(func() { fmt.Println("before rendezvous") rend.Done() rend.Wait() fmt.Println("after rendezvous") }) wg.Go(func() { fmt.Println("before rendezvous") rend.Done() rend.Wait() fmt.Println("after rendezvous") }) wg.Wait() before rendezvous before rendezvous after rendezvous after rendezvous Barrier A barrier is a general case of a rendezvous. It lets N goroutines wait for each other: The barrier has a counter (starting at 0) and a threshold N. Each goroutine that reaches the barrier increases the counter by 1. The barrier blocks any goroutine that reaches it. Once the counter reaches N, the barrier unblocks all waiting goroutines. You can implement a simple barrier with a wait group: const n = 4 var bar sync.WaitGroup bar.Add(n) var wg sync.WaitGroup for range n { wg.Go(func() { fmt.Println("before the barrier") bar.Done() bar.Wait() fmt.Println("after the barrier") }) } wg.Wait() before the barrier before the barrier before the barrier before the barrier after the barrier after the barrier after the barrier after the barrier # Signaling The sync.Cond (conditional variable) type lets one goroutine signal to another that it's ready, and lets the other goroutine wait for that signal. A Cond includes a mutex and has two methods — Wait and Signal. Wait unlocks the mutex and suspends the goroutine until it receives a signal. Signal wakes the goroutine that is waiting on Wait. When Wait wakes up, it locks the mutex again. cond := sync.NewCond(&sync.Mutex{}) done := false var wg sync.WaitGroup wg.Go(func() { cond.L.Lock() fmt.Println("G1 is ready to signal") done = true cond.Signal() cond.L.Unlock() }) wg.Go(func() { cond.L.Lock() for !done { cond.Wait() } fmt.Println("G2 received the signal") cond.L.Unlock() }) wg.Wait() G1 is ready to signal G2 received the signal If there are multiple waiting goroutines when Signal is called, only one of them will be resumed. If there are no waiting goroutines, Signal does nothing. You can also use the Broadcast method. While Signal wakes up only one goroutine waiting on Cond.Wait, the Broadcast method wakes up all such goroutines. You can signal with a channel: signal := make(chan struct{}, 1) go func() { // do something signal <- struct{}{} }() go func() { <-signal // do something }() And broadcast too: broadcast := make(chan struct{}) go func() { // do something close(broadcast) }() go func() { <-broadcast // do something }() go func() { <-broadcast // do something }() Broadcasting with a condition variable is limited: it only sends a signal, not the actual data, and it only works once. With channels, you can build a publish/subscribe system that doesn't have these limitations: type Publisher struct { sbox []chan int // subscription channels mu sync.Mutex // protects the state } func (p *Publisher) Subscribe() <-chan int { p.mu.Lock() defer p.mu.Unlock() sub := make(chan int, 1) p.sbox = append(p.sbox, sub) return sub } func (p *Publisher) Broadcast(v int) { p.mu.Lock() defer p.mu.Unlock() for _, sub := range p.sbox { select { case sub <- v: default: } } } # Run once The sync.Once type makes sure that the given function runs only once. If multiple goroutines call Once.Do at the same time, only one will run the function, while the others will wait until it returns: total := 0 initState := func() { total += 1 } var once sync.Once var wg sync.WaitGroup wg.Go(func() { once.Do(initState) // do something }) wg.Go(func() { once.Do(initState) // do something }) wg.Wait() total: 1 Once is perfect for one-time initialization or cleanup in a concurrent environment. Besides the Once type, the sync package also includes three convenience once-functions: // Calls f only once. func (o *Once) Do(f func()) // Returns a function that calls f only once. func OnceFunc(f func()) func() // Returns a function that calls f only once // and returns the value from that first call. func OnceValue T) func() T // Returns a function that calls f only once // and returns the pair of values from that first call. func OnceValues[T1, T2 any](f func() (T1, T2)) func() (T1, T2) # Object pool
The
sync.Pooltype helps reuse memory instead of allocating it every time, which reduces the load on the garbage collector:pool := sync.Pool{ New: func() any { buf := make([]byte, 1024) return &buf }, } // Only allocates 4*1024 B, despite 4000 loop iterations. var wg sync.WaitGroup for range 4 { wg.Go(func() { for range 1000 { buf := pool.Get().(*[]byte) sink = buf pool.Put(buf) } }) } wg.Wait() Memory allocated: 4 KBGettakes an item from the pool. If there are no available items, it creates a new one usingNew(which we have to define ourselves, since the pool doesn't know anything about the items it creates).Putreturns an item back to the pool.Things to keep in mind:
Newshould return a pointer, not a value, to reduce memory copying and avoid extra allocations.- The pool has no size limit. If you start 1000 more goroutines that all call
Getat the same time, 1000 more buffers will be allocated. - After an item is returned to the pool with
Put, you shouldn't use it anymore (since another goroutine might already have taken and started using it).
# Atomics
An operation without synchronization can only be truly atomic if it translates to a single processor instruction. Such operations don't need locks and won't cause issues when called concurrently (even the write operations).
There are only a few atomics, and they're all found in the
sync/atomicpackage:Int32 Bool Int64 Value Uint32 Pointer Uint64Each atomic type provides the following methods:
Loadreads the value of a variable.Storesets a new value.Swapsets a new value (likeStore) and returns the old one.-
CompareAndSwapsets a new value only if the current value is still what you expect it to be.var n atomic.Int32 n.Store(10) swapped := n.CompareAndSwap(10, 42) fmt.Println("CompareAndSwap 10 -> 42:", swapped) fmt.Println("n =", n.Load())
CompareAndSwap 10 -> 42: true n = 42
Numeric types also provide an
Addmethod that increments the value by the specified amount.All methods are either translated into a single CPU instruction or are otherwise guaranteed to be atomic, so they are safe to use from multiple goroutines.
The composition of atomics is always non-atomic:
var delta atomic.Int32 var counter atomic.Int32 func increment() { // Not atomic; causes a race condition. delta.Add(1) sleep(10) counter.Add(delta.Load()) } // After 100 concurrent increments, // the final value is NOT guaranteed. counter = 9386A bulletproof way to make a composite operation atomic and prevent race conditions is to use a mutex:
var delta int32 var counter int32 var mu sync.Mutex func increment() { // Atomic; doesn't cause a race condition. mu.Lock() delta += 1 sleep(10) counter += delta mu.Unlock() } // After 100 concurrent increments, the final value is guaranteed: // counter = 1+2+...+100 = 5050 counter = 5050Sometimes you can use an atomic type instead of a mutex to exit early:
type Gate struct { closed atomic.Bool } func (g *Gate) Close() { if !g.closed.CompareAndSwap(false, true) { return // ignore repeated calls } // The gate is closed. // We can free resources now. }# Testing
If your concurrent program uses channels or custom types with synchronization methods like
Wait, you can use those in your tests. This way, your tests won't be much more complicated than if the code were synchronous:// Calc calculates something asynchronously. func Calc() <-chan int { out := make(chan int, 1) go func() { out <- 42 }() return out } func Test(t *testing.T) { // Wait for the Calc goroutine to finish. got := <-Calc() if got != 42 { t.Errorf("got: %v; want: 42", got) } } PASSIf there aren't any suitable synchronization "handles" in the code you're testing, you can use the
synctestpackage. It exports two functions:func Test(t *testing.T, f func(*testing.T)) func Wait()synctest.Testruns an isolated bubble. The bubble uses a fake clock, and you can manually control goroutine synchronization withsynctest.Wait.synctest.Waitblocks until all goroutines in the bubble — except the one that calledWait— have either finished or are durably blocked. This lets you wait for a specific goroutine to finish or get blocked, so you can check the program's state:// NewProc starts the calculation. func NewProc() *Proc { p := &Proc{done: make(chan struct{})} go func() { p.res = 42 <-p.done // (X) p.res = 0 }() return p } func Test(t *testing.T) { synctest.Test(t, func(t *testing.T) { p := NewProc() defer p.Stop() // Wait for the goroutine to block at point X. synctest.Wait() if got := p.Res(); got != 42 { t.Fatalf("got %v, want 42", got) } }) } PASSThe fake clock in
synctest.Testmove forward only if: ➊ all goroutines in the bubble are durably blocked; ➋ there's a future moment when at least one goroutine will unblock; and ➌synctest.Waitisn't running. Thanks to this, time-dependent tests run instantly:// Calc processes a value from the input channel. // Times out if no input is received after 3 seconds. func Calc(in chan int) (int, error) { select { case v := <-in: return v * 2, nil case <-time.After(3 * time.Second): return 0, ErrTimeout } } func Test(t *testing.T) { synctest.Test(t, func(t *testing.T) { ch := make(chan int) got, err := Calc(ch) // runs instantly if err != ErrTimeout { t.Errorf("got: %v; want: %v", err, ErrTimeout) } if got != 0 { t.Errorf("got: %v; want: 0", got) } }) } PASSThe following operations durably block a goroutine:
- A blocking send or receive on a channel created within the bubble.
- A blocking select statement where every case is a channel created within the bubble.
- Calling
Cond.Wait. - Calling
WaitGroup.Waitif allWaitGroup.Addcalls were made inside the bubble. - Calling
time.Sleep.
Blocking on mutexes, I/O, or system calls is not considered durable, and the
synctestbubble can't handle them.# Scheduling
At the hardware level, CPU cores are responsible for running parallel tasks.
At the operating system level, a thread is the basic unit of execution. There are usually many more threads than CPU cores, so the operating system's scheduler decides which threads to run and which ones to pause.
At the Go runtime level, a goroutine is the basic unit of execution. The runtime scheduler runs a fixed number of OS threads, often one per CPU core. There can be many more goroutines than threads, so the scheduler decides which goroutines to run on the available threads and which ones to pause. The scheduler keeps switching between goroutines to make sure each one gets a turn to run on a thread, instead of waiting in line forever.
CPU OS Go runtime ┌──────────┐ run on ┌──────────┐ run on ┌────────────┐ │ Cores │ <────── │ Threads │ <────── │ Goroutines │ └──────────┘ └──────────┘ └────────────┘This is how Go handles concurrency.
Goroutine scheduler
The goroutine scheduler's job is to run M goroutines on N operating system threads, where M can be much larger than N. Here's a very simplified version of it's algorithm:
- If there's a free thread, assign it a goroutine from the queue.
- If a running goroutine gets blocked (for example, while reading from a channel), put it back in the queue and assign a different goroutine to the thread.
- If a running goroutine gets stuck in a syscall, start a new thread to run other goroutines until the blocked goroutine finishes the syscall.
-
Check the running goroutines every 10 ms. Preempt long-running goroutines and return them to the queue to prevent starvation.
┌─────┐┌─────┐┌─────┐┌─────┐ │ G17 ││ G18 ││ G19 ││ G20 │ queue └─────┘└─────┘└─────┘└─────┘
┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │ G15 │ │ G16 │ │ G13 │ │ G14 │ running └─────┘ └─────┘ └─────┘ └─────┘ │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ Thread E │ │ Thread F │ │ Thread C │ │ Thread D │ └──────────┘ └──────────┘ └──────────┘ └──────────┘
┌─────┐ ┌─────┐ │ G11 │ │ G12 │ syscalls └─────┘ └─────┘ │ │ ┌──────────┐ ┌──────────┐ │ Thread A │ │ Thread B │ └──────────┘ └──────────┘
The number of threads running Go code is controlled by the
GOMAXPROCSenvironment variable or theruntime.GOMAXPROCSfunction.A goroutine is a structure that starts out using about 2 KB of memory, mostly for its stack. The stack can grow if needed. Since goroutines are so lightweight, you can run tens of thousands or even hundreds of thousands of them on a small machine.
# Diagnostics
To troubleshoot concurrent programs in production, we use metrics, profiling, and tracing.
Metrics show how the Go runtime is performing, like how much heap memory it uses or how long garbage collection pauses take. Each metric has a unique name and a value, which can be a number or a histogram.
You can use the
runtime/metricspackage to get a complete list of metrics or check the values of specific ones:samples := []metrics.Sample{ {Name: "/sched/gomaxprocs:threads"}, {Name: "/sched/goroutines:goroutines"}, } metrics.Read(samples) for _, s := range samples { fmt.Printf("%s: %v\n", s.Name, s.Value.Uint64()) } /sched/gomaxprocs:threads: 8 /sched/goroutines:goroutines: 1In practice, people rarely do this manually. Instead, all metrics are automatically exported using Prometheus or OpenTelemetry libraries.
Profiling helps you understand exactly what the program is doing, what resources it uses, and where in the code this happens. Go uses a sampling profiler that's suitable for production.
The most commonly used profiles are CPU, which shows how much processor time each function uses, and heap, which shows how much heap memory each function uses. Goroutine, block, and mutex profiles help identify problems related to concurrency.
The easiest way to add a profiler to your app is by using the
net/http/pprofpackage. To collect a profile with the given name, call the/debug/pprof/{name}endpoint. To view the collected profile, use thego tool pprofutility:go tool pprof -proto \ "http://localhost:6060/debug/pprof/profile?seconds=N" > cpu.pprof go tool pprof -http=localhost:8080 cpu.pprofYou can also profile manually:
// CPU profile. file, _ := os.Create("cpu.prof") defer file.Close() pprof.StartCPUProfile(file) defer pprof.StopCPUProfile() // ... // Any other profile. file, _ := os.Create(name + ".prof") defer file.Close() pprof.Lookup(name).WriteTo(file, 0)Tracing records certain types of events while the program is running, mainly those related to concurrency and memory. When the profiling server from the
net/http/pprofpackage is running, call the/debug/pprof/traceendpoint to collect a trace. To view the results, use thego tool traceutility.You can also collect a trace manually:
file, _ := os.Create("trace.out") defer file.Close() trace.Start(file) defer trace.Stop() // ...You can set up automatic tracing with a sliding window that's limited by size or duration. This is called "flight recording". It lets you always keep a recent trace available in case something goes wrong:
cfg := trace.FlightRecorderConfig{ MinAge: 5 * time.Second, MaxBytes: 3 << 20, // 3MB } rec := trace.NewFlightRecorder(cfg) rec.Start() defer rec.Stop()# Final thoughts
We've covered a number of Go tools for writing concurrent programs:
- Goroutines for running concurrent tasks.
- Channels and select as flexible communication tools.
- Timers and tickers for working with time.
- Context for canceling operations.
- Wait groups for synchronizing goroutines.
- Mutexes to prevent race conditions.
- Condition variables for signaling events.
- Once for safe one-time initialization.
- Pools to reduce garbage collector load.
- Atomic operations.
If you like the book, please recommend it to your friends or colleagues. If you're interested, check out my other books and projects.
I'm glad you finished the book. Thank you, and I'll see you next time!
-
🔗 smol-machines/smolvm smolvm v1.19.1 release
What's Changed
- Let a cascade delete finish when a clone vanishes mid-cascade by @LoganGrasby in #1419
- fix: propagate machine exec database lookup errors by @sgrove in #1331
- Reconcile bounded late VM exit after shutdown acknowledgment failure by @sgrove in #1329
- Size the pack VM's storage disk from the image manifest by @Bnjoroge1 in #1322
- Resolve image manifests from the reference's own registry only by @BinSquare in #1420
- Link the Node, Python and Rust SDKs from the README by @BinSquare in #1421
- Restructure the README around what smolvm is for by @BinSquare in #1423
- Honor a local image's WORKDIR, ENV and USER in machine run by @BinSquare in #1424
- Specify the checkpoint format and name checkpoint files .checkpoint by @BinSquare in #1422
- Bump the workspace to 1.19.1 by @BinSquare in #1425
Full Changelog :
v1.19.0...v1.19.1 -
🔗 hacker news ida pro references New comment by zellkernel in "Reverse Engineering Fortinet with Ablation" rss
Ablation is a reverse engineering framework that provides the exact same core disassembly, decompilation, and binary analysis capabilities as industry-standard tools like Ghidra, IDA Pro, and Binary Ninja. Combined with an LLM, it transforms into a fully autonomous reverse engineering tool.
Ablation is built for the modern landscape, and more importantly, the human.
Now reverse engineering is accessible to anyone. No matter your wallet or your barrier of entry into education, you can learn about reverse engineering as you reverse engineer.
-
🔗 Register Spill Joy & Curiosity #101 rss
Last week I was on Matt Swanson's podcast and we ended up sharing thoughts and vague predictions about programming languages and frameworks. Matt said that he'd be going to Rails World the week after and that he wouldn't be surprised if DHH said "Rails is over." Prescient. DHH didn't exactly say that Rails is over, but, well, some people did call the keynote a "funeral."
But that shouldn't be surprising, right? The way we've treated languages and frameworks for the past, say, twenty years is at odds with the fact that writing code by hand is on its way out.
I am not sure how exactly this will play out, but here are some loose thoughts:
-
Frameworks are no longer the biggest developer productivity lever. Agents are a hundred times bigger.
-
Syntax doesn't really matter anymore, as long as agents can write it well.
-
Tool ergonomics don't matter that much either, do they? Previously, I loved that
gocomes withgo buildandgo testandgo run, but now I wouldn't care if those commands were seventeen times longer. -
But I think shared abstractions are still worth it. A framework gives you a pre-defined way to access a database, to do auth, to divide things into production and development… That's still handy. Not because it would cost tokens to build it myself (won't matter in the future, see below), but because I just don't want to think about it.
-
What will matter a lot in the future: performance characteristics, resource usage, failure modes, observability, debuggability, deployments, rollbacks. And all of that needs to be legible to the agent. I've tried developing something with the often praised Cloudflare Durable Objects, on which you can run JavaScript, and it was a disaster: the agent constantly thought it was writing normal Node.js JavaScript; it didn't know the runtime characteristics of the Durable Objects; it couldn't easily access the logs. In fact, there are no logs that tell you when your code gets evicted and when it gets resumed… You want the opposite to be the case: the agent should know from looking at the codebase how it will be executed and how it can see that.
-
The big force is that we're switching from "I prefer this language because I enjoy working with it" to "I prefer this language because my agent can get great results with it." Now, how would your preferences change if you switched from driving a car to controlling it remotely? You wouldn't care about heated seats and AC, would you? But you'd care about how fast it can brake, I assume.
-
Ecosystems will change. I can't remember the last time I browsed through GitHub to find a library to do a thing. The old NPM credo of "many, many tiny modules" seems even sillier now than it did ten years ago.
-
Sometimes I wonder whether the thing that makes some developers say that agents will change everything and others that they can't write good code is the language they used with the agent. 99% of the code I've had agents write was in TypeScript. Not a language I love, but, hey, who cares? And agents seem great at it. I wonder what my thoughts would be if I still were writing Rust.
-
Then again: I no longer think that "is the language well-represented in the training data?" matters as much as I thought it would. Intelligence generalizes and I've seen agents just crush custom DSLs that have not shown up in any data, ever. We previously said about humans that "if you learned 5 different languages, you kinda know them all" -- maybe that's what's going to happen with agents too? And it kinda makes sense, right? Why wouldn't a frontier model like Astra or Fable be able to use a new language as long as it can run it and have a feedback loop?
-
Very pessimistic on the future of "paper-over" languages and frameworks. You know: this language but with nicer syntax. CoffeeScript, if you're old enough to remember. Haml, Sass, Less -- not sure. What about Elm or ClojureScript? Hmm.
-
A lot of testing frameworks started with TDD in mind: you write a test in which you describe the behavior you want, you run the test to see it fail, you make it pass. Then, with growing adoption of tests, people started using those very same frameworks to add tests after everything already worked. Regression tests. Now we have the very same frameworks being used by agents to write tests god knows how and essentially no one looks at these billions of lines of test code that are generated every day now. Will we still have
describeanditblocks in ten years? Just like some terminal emulators still mention baud rates? I do think that the models will get so good that they don't "need" unit tests in the same way humans needed them: to make sure something works. But maybe they won't stop writing them and we'll end up with effectively useless tests piling up? -
I'd be incredibly surprised if formal methods and strong static typing had the boom that their fans say they will have. Vitamins, not painkillers; worse is better, etc.
-
I have three little apps that I use every day and that I had the agent write, and I have zero clue what language they're written in. I think it's JavaScript?
-
Porting from one language to another seems to be a completely different thing now compared to three years ago.
Again: I don't know where we'll end up, but I do think being aware of the forces at play is important. It's also fun stuff to think about.
Before we get to the J &C juice: I'll be in NYC with the Amp team Oct 5-11 and in SF the week after, Oct 12-17. My schedule will be busy and chaotic, but if you're around and want to grab a coffee, let me know!
-
We recorded a new Raising An Agent episode after I said to Quinn: "Man, I'm so full of hot takes today. I need to record a video." So, there it is: an episode full of hot takes. From a whole engineering org making everyone use Qwen, to why GDP isn't increasing if you aren't letting your agents go vertical , to why you're wasting time if you're waiting on your agent instead of the other way around, to why I've been very disappointed by a lot of "software engineers" in the last two years.
-
Expect this to continue: "If we combine all this, we see about 2.5 orders of magnitude decrease in token cost in the last year. Models are about 100x as cost-efficient per-task. Hardware is about 1.3x as energy-efficient per-token. Engines are about 1.4x as energy-efficient per-token." The strongest force in technology today. I stand by what I wrote in last week's predictions about the future of software development: "Tokens are the new computing paradigm. Everything will be re-made on top of it."
-
So, DHH lit the Ruby & Rails world on fire by giving a keynote in which he doesn't talk about Rails all that much. Instead, he said what others (hey , what's up) have said for at least the last six months: writing code by hand is over; these agents are really good; choosing Ruby over other languages due to its developer friendliness doesn't make a lot of sense anymore; old engineering tradeoffs should be revisited. But he said it in a way that only DHH can. He's very, very good at boiling things down to their essence and turning them into statements that make you choose whether you're for or against it. It's impressive, honestly. Read the Hacker News comments to get a taste. Now, predicting the next six months, I wonder when the Omarchy community will run into the question of: wait, so we now have this malleable operating system, but… if agents write and debug all the code, why do we even need it?
-
Thomas Dullien, or: Halvar Flake, gave a presentation: An age of experimentation. It's really good and I highly recommend you click through it. Here, to give you a taste: "Claim: Determinism is dying, and it's unclear how much will remain."
-
New Peter Thiel interview! Say about him what you want (and there's a lot to say), but his ability to read the vibes in the world seems to be rarely matched. What makes this interview also interesting is that the interviewer is Mathias Dopfner, quite the controversial billionaire himself. At some point in the interview, Thiel compares the twenty richest people under 30 in the US with those in Germany and says that the twenty in Germany all inherited their wealth. Guess how Dopfner got his shares of Axel Springer SE? Heavily discounted and some as gifts, from Springer's widow.
-
Attention is all you have: "If, like me and most people, you spend the major part of your day focused on your device, there's no doubt it's affecting you. And when you let someone else dictate what appears on your screen, it's the same as giving them the key to your brain."
-
"But there are pleasures to be had from books beyond being lightly entertained. There is the pleasure of being challenged; the pleasure of feeling one's range and capacities expanding; the pleasure of entering into an unfamiliar world, and being led into empathy with a consciousness very different from one's own; the pleasure of knowing what others have already thought it worth knowing, and entering a larger conversation."
-
Martin Fowler: I don't like LLMs. "I don't like them. They talk to me in this grating LLM-voice, an uncanny valley of talking to a real human. They confidently bullshit me - often giving me useful, helpful answers. But also just making stuff up with the same assurance - and with only a veneer of fake remorse when I call them out on it." He's got a point. Many times a day I think to myself "god, shut UP " when the model comes back with whatever the latest equivalent to "you're absolutely right!" is: spines, seams, belts and braces (or suspenders). But… less and less so? I parse their output more like a receipt I get handed in a shop or in a restaurant: skip the stuff at the top, ignore the gibberish at the bottom, zoom in on the stuff there in the middle.
-
I didn't know about the Moving Image Archive but was delighted when I came across its collection of animated maps.
-
This seems very neat and makes me want to build something with Go: Platform-independent SIMD.
-
"I text him that night and I said, 'Hey, I want to ask you a question. Can I coach you hard?' […] Then the next day he sees me in pre-practice, and I said, 'Just let me explain this. Do you see yourself being in the Hall of Fame someday?' And he said, 'Yeah.' And I said, 'All right. Well, I don't think your trajectory right now is steep enough to make that goal happen. I think your trajectory is five Pro Bowls, a couple All-Pro teams, phenomenal career, all-time leading rusher, but I think your trajectory, and I think your practices have to be…' And then he starts complaining to me, and I said, 'I thought you told me I could coach you hard.' And then, you know, it hit him."
-
How to Unclench. I finally read this after it made a big splash last week. It's a much faster read than I thought it would be. It's like a neat little mini-book.
-
Robert O'Callahan: "I'm resigning from Google today. This has not been an easy decision. I love my colleagues and my work environment, and being paid handsomely to solve fun puzzles has been amazing. But my team's goal is ultimately to make AI much cheaper and lower-latency, and I don't think that's good for people right now: I firmly believe AI progress is currently far too rapid (and I have doubts about the destination too)."
-
"I started to explain how it happened when they cut me off with 'Michael, I don't want the details'." Good stuff.
-
Thomas H. Ptacek and Kurt Mackay are leaving fly.io to build a phone: "Today, almost all software comes from expert strangers. But soon, strangers will stop supplying our apps, and instead ship just their building blocks. Sure, there will still be megaproject browsers and word processors. But there'll be thousands of times more applications that pull in 1/7th of the guts of a word processor to solve some idiosyncratic work or home life problem for somebody who doesn't know what a for-loop is. […] That's what we're working on: a platform that is the device we would want to have in the world I just described. So: we're building a phone." I nod my head to the boldness of entering one of the most competitive markets of all time.
-
It's totally not the point of this Obie Fernandez post, but I can't stop thinking about this part here: "Trying to make a point, I hit enter to accept Fable's first suggestion. Minutes later I hit enter again, and then again, choosing to delete some dead code. We start making a PR. My friend asks me to make sure it's set to draft. Sure, whatever. Fable does its thing. My friend checks the diff. It's a simple deletion of dead code and associated unit tests. I want to push on, but my friend begs me to stop. 'You don't understand Obie, I can't just do what you're doing, man.' I challenge him to explain why not. He explains that he has a boss and teammates and that he can't just make changes like that, he has to present plans and execute on them." It made me remember what it feels like to work in such teams, where you can't make decisions alone, where you're not trusted to make a call like "I'm going to refactor this API" or "I'm going to delete this" or "I'm going to add a new feature that lets us…" without having reached a consensus with the team. Remembering that made me feel sad, thinking: "wow, imagine what it's like to now have AI but no power, no trust, no freedom to use it?" There's no way around it: if you box AI into this little corner where all it can do is change code on your local machine and help you push it up as a PR, you're holding the leash at a fraction of its real size.
-
Intellectuals are F*cking Idiots: "Reality always wins. But Intellectuals are rewarded for their models, not reality. And the data and analysis that looks elegant on paper is often disastrous on the ground. Yet, when their models are contradicted by reality, most intellectuals don't have the courage to accept the reality, instead they double down on their models …and this is what turns them into idiots." If it's nothing else, this was entertaining!
-
I thought of this John Carmack post again, so here it is, again: "Make better decisions and fill your products with 'Give a Damn'!"
-
This is fantastic: Fixing the Portobello Police Station Clock. It's a hack, it's nerdy, it's real blogging. This is the type of stuff that made me fall in love with the Internet.
Thoughts on the future of programming languages? Subscribe here:
-
-
🔗 HexRaysSA/plugin-repository commits sync repo: +4 releases, -1 release rss
sync repo: +4 releases, -1 release ## New releases - [augur](https://github.com/0xdea/augur): 0.10.3 - [ida-rpc](https://github.com/bkerler/ida_rpc): 0.2.0 - [patching-ng](https://github.com/mahmoudimus/patching-ng): 0.5.0, 0.4.0 ## Changes - [patching-ng](https://github.com/mahmoudimus/patching-ng): - host changed: mahmoudimus/patching → mahmoudimus/patching-ng - removed version(s): 0.3.0
-
- September 25, 2026
-
🔗 anthropics/claude-code v2.1.283 release
What's changed
- Added
x-claude-code-prompt-idto the gateway hint headers so LLM gateways can group the requests that serve one user prompt; opt in withCLAUDE_CODE_GATEWAY_HINT_HEADERS=1 - Added
availableModelsMatchmanaged setting: with"exact", anavailableModelsentry allows only the model version it names, so new releases stay blocked until listed - Added
deniedModelsmanaged setting to block specific models, even whenavailableModelsallows them - Added MCP tool, WebFetch and WebSearch outputs to the
tool.outputOpenTelemetry span event whenOTEL_LOG_TOOL_CONTENT=1 - Added
/doctor prompt-audit(also/checkup prompt-audit) to audit your CLAUDE.md files, skills, agents and commands for prompting patterns written for older models - Added click-to-expand for truncated messages from your other sessions in fullscreen mode
- Added
pathto--plugin-dirload-failure entries in the stream-jsonsystem/initplugin_errors, naming the directory that did not load - Added an opt-in
load_test_modeblock to the Claude apps gateway config: requests are built and signed but not sent upstream, and clients get a canned reply, so a deployment can be load tested - Added a
mantleupstream provider to the Claude apps gateway for Amazon Bedrock's Mantle endpoint - Fixed SDK sessions losing a deferred tool call or finished tool result when a turn ended early, a held approval prompt after a worker restart, and a non-streaming fallback's
result.usage - Fixed MCP progress notifications being discarded once a long-running tool call moved to the background; the background task now shows the latest progress
- Fixed stdio MCP servers being left running when the session ended while they were still starting
- Fixed a brief HTTP 404 from a stateless remote MCP server (for example a proxy mid-redeploy) leaving that server unusable for the rest of the session while still shown as connected
- Fixed MCP sign-in for a server with no valid URL failing with an opaque SDK error;
/mcpno longer offers Authenticate for such servers - Fixed the weekly Fable limit not appearing in
/usageand the VS Code usage meters when telemetry is disabled - Fixed
/modelaccepting Sonnet 4.6 or Sonnet 5 with[1m]when the id carried a date or-v1:0suffix, in the cases where the plain id was refused - Fixed
/modelpicker showing a hardcoded Haiku version and price whenANTHROPIC_DEFAULT_HAIKU_MODELpins a different model - Fixed dynamic workflows started during a model fallback running every agent on the fallback model instead of retrying the configured model
- Fixed
DISABLE_PROMPT_CACHING_HAIKUhaving no effect when Haiku is the session's main model - Fixed
claude plugin validatesaying Claude Code accepts a plugin or marketplace name it cannot install; such names inmarketplace.jsonnow fail validation - Fixed
claude plugin validatepassing plugins whoseoutputStyles,themes,monitors, orlspServerspaths are missing or point outside the plugin directory - Fixed
claude plugin detailsshowing 0 MCP servers for plugins that declare their servers inplugin.json - Fixed
claude plugin marketplace removenot saying which installed plugins it uninstalled with the marketplace; it now lists them - Fixed
claude plugin uninstallremoving the other of two installed plugins whose ids differ only in case, with its options and secrets, when the one named had noenabledPluginsentry at that scope - Fixed plugins that declare no version being silently restored at their source's newest commit, not the installed one, when their cached files were missing
- Fixed user-installed plugins and marketplaces failing to load with "cache-miss" after the home or config directory was moved, for example in bind-mounted devcontainers
- Fixed
installed_plugins.jsonshowing no plugins when it holds a record under an invalid plugin id; such a file loads again - Fixed
installed_plugins.jsonbeing rewritten, losing records, when it holds a record this version cannot read;claude plugincommands now name the record and say how to recover - Fixed permission dialogs in screen-reader mode reading quoted commands and paths as if they were the dialog's own text
- Fixed
/contextnot counting MCP server instructions: they now appear as their own row and count toward the total - Fixed markdown links in the Warp terminal rendering as plain text instead of clickable hyperlinks
- Fixed
claude mcp add,add-json, andremovereporting success when the user or local config file could not be written, for example inside a sandbox - Fixed the first words of a reply in a cloud session sometimes appearing late instead of streaming as Claude writes them
- Fixed Claude's built-in keybindings guide saying chords time out after 1 second instead of 3, and calling
cmdan alias ofmeta, which could producecmd+shortcuts most terminals never send - Fixed
keybindings.jsonsilently accepting a misspelled modifier such asctl+k; it now warns in the debug log and suggests the fix - Fixed footer hints still saying "Enter to view" after
footer:openSelectedwas rebound or unbound inkeybindings.json - Fixed keys typed quickly together (type-ahead, key repeat, bursts over ssh or tmux) sometimes being handled against stale state
- Fixed worktree checkouts failing certificate verification (for example on Git LFS downloads) when the CA certificate is passed to git as
GIT_CONFIG_COUNTenvironment pairs - Fixed sandboxed
gitasking credential helpers to store the sandbox proxy's login, which printed "failed to store" - Fixed managed
sandboxsettings being ignored entirely when one nested value was invalid; the invalid value now fails closed and the rest of the block still applies - Fixed Claude's edits to its own auto-memory notes being blocked as sensitive-file writes when Claude Code was started in a subdirectory of a git repository
- Fixed Remote Control being unavailable on paid plans when telemetry is turned off with
DISABLE_TELEMETRYorDO_NOT_TRACK - Fixed the
/remote-controlmenu cutting its QR-code hint mid-word in narrow terminals - Fixed vim mode
.dropping a Shift+Enter newline, leaving the cursor inside an accented letter, and repeating an older change after3Jor Visual-modeJon the last line - Fixed vim mode cursor placement: recalling a prompt over 10,000 characters in normal mode no longer leaves the cursor past the end, and
Vthenpnow lands on the first non-blank - Fixed vim mode
Jjoining lines with different spacing than Vim (such as a space before)or after a tab), and3Jor Visual-modeJon the last line not moving the cursor as Vim does - Windows: Fixed the PowerShell tool letting
cmd /c rd,rmdir,delorerasedelete drive roots, the home folder and other folders thatRemove-Itemrefuses - Improved the
/mcptool list: it shows more tools at once, scrolls with the page keys and mouse, and marks tools your organization blocked with a warning icon - Improved MCP tool results: images returned by MCP tools are now also saved to a file, so Bash, Read and other tools can open them
- Improved
/tasks: rows show a status icon, the name and whole facts, the title and key hints stay on screen with many tasks, and the list gains paging keys, the mouse wheel and clicks - Improved lists in
/help,/hooks,/copy,/chrome,/memory,/ide,/release-notes,/rewind,/diff,/remote-env,/pluginand other pickers with page keys, mouse wheel and clicks - Improved lists beside a search box, such as
/skillsand/artifacts, to draw their pointer dim while the search box has the keys, so only one pointer is highlighted - Improved the compaction spinner: its timer now starts when compaction begins and it counts the summary's tokens as they stream, replacing the percentage bar
- Improved the browser page shown after signing in to an MCP server: centered layout, dark mode, and new artwork
- Improved the Skill tool's reply when a skill belongs to a plugin that failed to load, so Claude tells you the plugin could not be loaded instead of calling the skill uninstalled
- Improved
prompt-auditon Claude Code configuration: stale paths, stale commands and contradicting instruction files now lead the report, and thinking keywords that Claude Code documents are kept - Improved recovery from an
installed_plugins.jsonthat cannot be read at all: its contents are kept in a file beside it before it is rebuilt, andclaude plugin listnames that file - Improved artifact database reads: an ordered query that returns a full page now says it is one page and how to read the rest
- Improved first-reply latency: a pattern-compile step that ran at the end of a session's first reply now runs while the reply streams in
- Improved first-request latency by reusing the preconnected API connection
- Improved startup:
claude -pand Claude Code Remote no longer load the interactive UI, and the auto-mode classifier's rules and the Artifact tool load on first use instead of at launch - Improved startup for claude.ai accounts whose Artifact tool features aren't known yet, as on a first run: the prompt no longer waits up to 1.5 s to check them; the first message waits if needed
- Changed interactive sessions on third-party providers or with telemetry off to start in auto mode when no permission mode is configured;
permissions.defaultModestill overrides it - Changed the
/ultrareviewlaunch dialog to say that reviewing a local branch may upload uncommitted changes to tracked files - Changed the
/modelpicker's Opus row and the Default model's name to drop "(1M context)" where Opus already has a 1M context window; the window is unchanged - Changed prompt suggestions in the terminal to appear less often after 20 in a row go unused; using one brings them back
- Changed
--system-promptand--append-system-promptto accept their text and-fileforms together; the file's text comes first - Changed
Skill(anthropic-skills:<name>)deny rules to also block that skill when Claude Desktop delivers it as a plugin, andSkill(skill:<name>)denies to match the skill's alias and display name - Changed
/rewindand/difflists to move on the same keybinding actions as every other list (select:*);messageSelector:*/diff:*rebinds still work - Changed the
/workflowsrun list to size itself like other lists: half the terminal inline, and it keeps its title on screen when the prompt shows below - Changed
claude plugin evalto require git 2.31 or later when git is installed; a run on an older git is refused with a message naming the version - Changed artifact watching: a watch that was armed automatically (not one you asked for) now ends after 3.5 hours with no activity; publishing or watching the artifact again re-arms it
- Self-hosted runner: Changed lifecycle hooks' git to skip a repository's Git LFS
pre-pushhook, ignore a writable systemcore.hooksPath, and not sign commits without--configure-git - Self-hosted runner: Changed
GIT_SSL_CAINFOandGIT_SSL_NO_VERIFYunder Anthropic-managed git: the runner's own git always verifies Anthropic's git route, and warning lines say what applies where - Reverted the 2.1.282 reservation of the
claude-ainame: skills, commands, workflows and MCP servers' skills and prompts so named load again, andSkill(claude-ai:*)rules are ordinary prefix rules - [VSCode] Fixed the permission mode indicator showing Default while the session kept running in auto or bypass mode after an automatic switch out of it failed; the switch is now retried until it lands
- [VSCode] Fixed a session teleported from the web dropping the messages sent while Claude was working
- [VSCode] Fixed a Web session staying hidden from the session list, and an empty chat opening in its place, when an older version had saved an empty local copy of it
- [VSCode] Fixed a reopened session splitting a turn at a message Claude received mid-turn, such as an automatic continuation
- [VSCode] Fixed a reloaded session showing a rewound-away turn, or only the rows before a compaction
- [VSCode] Fixed the footer's agents pill drawing its icon off-center, with the status dot against the edge, in narrow panels
- [VSCode] Fixed the chat input showing its text slightly below the cursor and selection after pasting lines that end with a line break into a long prompt
- [Cloud sessions] Improved adding a repository to a running cloud session: a private repository your GitHub account can read but not push to now attaches for reading
- [Cloud sessions] Fixed cloud sessions occasionally redoing an already-finished step, such as posting a duplicate comment or push, after recovering from a server-side restart
- [Cloud sessions] Changed new routine schedules to default to a few minutes past the hour, with a note that routines set exactly on the hour can start several minutes late
- [Claude Tag] Added a "Channels Claude can search" admin setting that limits Claude's Slack search to public channels it has been added to, set per organization, workspace or channel
- [Claude Tag] Added a Back to Slack button on the page shown after connecting your Claude account, returning you to the thread you started from
- [Claude Tag] Fixed a channel's configure page listing no connectors or plugins when the channel gets its access bundle through an attach rule; rule-attached bundles are now shown
- [Claude Tag] Fixed access-bundle repository search missing repositories on GitHub App installs that are limited to a large list of selected repositories
- [Claude Tag] Fixed Claude occasionally posting the same reply twice when a new message interrupted it mid-reply
- [Claude Tag] Fixed channel routines that stopped running in older private channels whose Slack channel ID changed, for example after a Slack Connect share
- [Claude Tag] Fixed conversations in a channel set to "Channel only" all ending when a non-guest member joined and Slack was slow to confirm their membership
- [Code Review] Fixed "@claude review" requests going silent when GitHub failed to return the pull request: the request is retried once, and a comment explains if it still fails
- [Code Review] Fixed billing for a review that stopped at its time limit with nothing verified: it now shows as incomplete, isn't charged, and is retried once
- Added
-
🔗 smol-machines/smolvm smolvm v1.19.0 release
What's Changed
- Honor --credential when creating a machine from a pack by @BinSquare in #1400
- Pin the Nix flake to 1.18.2 with its real release hashes by @BinSquare in #1398
- Launch a credentialed machine with its credentials on every start and resume by @BinSquare in #1402
- Report a forked machine's own creation time by @LoganGrasby in #1407
- External egress interceptor by @ankrgyl in #1405
- Let a lease request wait for a clean pool worker by @LoganGrasby in #1408
- Keep the pool controller from retiring a worker a lease just claimed by @LoganGrasby in #1406
- Keep external interception fail closed across VM restarts by @BinSquare in #1409
- Let a virtio-net machine start after machine update --no-net by @LoganGrasby in #1410
- Upload captured checkpoints straight to object storage by @BinSquare in #1403
- Fail a Windows virtio-net launch when a published host port is in use by @nitzzzu in #1416
- Share one database handle per process by @LoganGrasby in #1417
- Retry a read-then-write DB transaction that loses the write race by @LoganGrasby in #1413
- Don't retire a paused leased fork pool worker by @LoganGrasby in #1414
- Refuse to implicitly start a paused machine by @LoganGrasby in #1415
- Retry an agent connect the guest hangs up during the handshake by @BinSquare in #1412
- Keep the guest agent answering pings while every work slot is busy by @BinSquare in #1411
- Take API credential values from the API, never from the host environment by @BinSquare in #1401
- Bump libkrun for the restored-inode, vsock restore, kqueue and fork generation fixes by @BinSquare in #1399
- Read the machine name from SMOLVM_MACHINE_NAME when --name is omitted by @BABTUNA in #1392
- Bump the workspace to 1.19.0 by @BinSquare in #1418
New Contributors
Full Changelog :
v1.18.2...v1.19.0 -
🔗 Mr. Money Mustache Will the AI Bubble Destroy our Retirement? rss

Wow, how about that stock market?
It’s a phrase we keep having to dust off and use again, as the years go by and the market keeps surprising us.
When it crashes, some of us worry because we see our retirement stash shrinking.
But even when it rises to record levels and then to super-duper-crazy record valuations, we find reason to worry. Because that just means an even bigger crash is coming, right? Especially when this boom-bubble is built on the back of something as frenzied as the present Artificial Intelligence boom… right?
For those who have been happily tuned out of this drama and just enjoying life: Congratulations! Keep up the great work. But just to give you a quick background for the purposes of this article, here’s the AI story in three points:
- Over the past few years, AI has reached a level where it can do complex thinking and reasoning tasks that most of us thought might not happen in our lifetimes. It’s shockingly useful.
- This has led to the fastest worldwide adoption of any technology in history: over 1.5 billion people are already using it, as are most large companies
-
And this has caused a crazy cycle of growing sales, investor enthusiasm and data center buildout that is now the largest investment cycle humans have ever made in anything: 1.8 trillion dollars has been spent since just 2002, with another trillion going out the door next year alone. Which you can compare to:
-
The cost of the 2700-foot-tall Burj Khalifa, the highest skyscraper in the world (about $2 billion in today’s dollars)
- Or the entire US interstate highway system, 48,000 miles of wide, flat, highly engineered roads (and 55,000 massive bridges) which cross countless mountain ranges, rivers and canyons: $660 billion in today’s dollars.
So where’s the problem?
Investors worry that while AI is definitely a major invention, the mania around it is still too much, too fast, and thus we are due for an even bigger version of the dot com crash we had in the early 2000s. Which happens to be an interesting subject for me, since that was the boom that boosted my own early career and got me on the path to early retirement … before the ensuing crash almost cost me my job and my citizenship application.
As an aging Internet Financial Guru, I have the privilege of getting lots of questions about this investment cycle, just as I have about past booms and busts. And to address them, I decided to not only write this blog article but also create a little talk about it - which I already gave for the first time at an event called Camp FI Midwest earlier this month. I also hope to polish it up and deliver an improved version at the Bogleheads conference in November.
So what that means is that today you not only get a blog post, but a few silly presentation slides to go with it for extra entertainment. All with no need for a plane ticket or all that hassle of leaving your house. So let’s get into it!
Will the AI Bubble Ruin our Retirement?
-So I recently hit 21 years of retirement. This means I’ve grown pretty comfortable with the idea. But it still threw me for a loop one time when a friend asked me this question:
“How can you be retired, and comfortable in your retirement, and sleep at night, with everything that’s going on in the world? Aren’t you worried?”
And I was like, “No, what should I be worried about?”
But if you’re a news watcher and a worrier yourself, you can probably think of a few things I should be worried about. Perhaps stuff like this:
2026 worriesYou’ve got our corrupt and/or dangerous politicians like Trump and Putin menacing the world. Inflation eroding our purchasing power, the AI Bubble, the towering US National Debt, the Iran war and the Ukraine war and all these other wars that are just on the verge of tipping us all into destruction.
But it turns out these were not the things my friend was asking about.
Because she actually asked me this question over twenty years ago… In the year 2006. So back then we were worried about entirely different things, right?
2006 worriesBack then we had corrupt and/or dangerous leaders like Bush, Hussein and of course Bin Laden. There was still a war in the middle east but it was Iraq instead of Iran. We were still worried about the National Debt and Inflation. And we also worried about our overvalued stock market. But back then it was because of the housing bubble instead of the AI bubble. And instead of AI taking our jobs it was going to be outsourcing to India and China.
Oh and here’s an interesting one: There was a big debate over Peak Oil, and whether the world was doomed because fossil fuel use was always increasing while supply was bound to decrease. And it turns out the opposite happened as you'll see below.
So then after all this worry in 2006, what ended up happening?
-Well we did get the Great Financial Crisis, which was caused by a combination of irrational exuberance over increasing house prices combined with a foolish degree of fancy leverage in the financial instruments used to issue mortgages. And it was the biggest crash since the Great Depression.
But even in that craziest of situations, look how minor it looks in the big picture. A $100,000 investment still ended up ballooning into $852,000 today. And if you look carefully in here you can just see the Covid Crash tucked in there in 2020. Remember that?
And not only that, the rest of the world got a lot better too:
The portion of people living in extreme poverty dropped from 20% in 2005 to only 8% over the next 20 years. Infant mortality - children who die in their first year of life - was cut in half. Clean energy became a thing as solar panels became about 40 times cheaper. So solar generation now makes up the vast majority of all the new generation we add today (the equivalent of 647 nuclear power plants of peak capacity added last year, but with much cheaper and easier solar panels). And sales of pure electric cars have gone from zero up to about a quarter of all the cars sold on Earth last year, on its way to 100%, which is where they already are in Norway.
So if we circle back to that question my friend asked me 20 years ago: do you think I should have focused my energy on worrying about an uncertain future, or optimism?
Which of course brings up the question: Is it different this time?
Maybe the US national debt is finally big enough to really start messing with us. Maybe the AI bubble is way bigger than the housing bubble and we won’t bounce back from that stock market crash. Or maybe AI will spin out of control into a super intelligence that takes over the planet and realizes it does not need us any more.
And the financial media loves to spin a good scary story about all of this. But you know what the fear mongers all seem to be missing?
It’s the fact that at the core, our prosperity does not come from the financial system or the stock market, which are just some made-up numbers on some computers.
Really, Prosperity comes from Productivity.
-We first covered this lesson right here on MMM, in the 2014 Classic entitled, “Why we are not really all doomed”. And sure enough, twelve years later the timeless lessons therein remain just as true now as they were back then.
And that lesson is really simple: the world of capitalism is always choppy and prone to wild swings. But if you peek beneath the waves, there are real people in there, doing real work and coming up with real inventions.
In fact, the very idea of an “economy” or a financial system is just another human invention. If the whole system crashes because we don’t like the numbers we see in there, we can literally make up some new numbers and then get back to work. Which is exactly what we did in 2008 and many times before that, and it seems to have worked just fine.
Meanwhile, we still have every tool we ever invented to boost our productivity. And our standard of living, and our economic growth, and our possibility of retiring early, all come from high productivity.
But even Productivity and Prosperity aren’t all that important.
Because once we reach a certain standard of living, human happiness kind of tops out in that dimension. In first-world countries, we blew past those minimum requirements several decades ago. And then we start looking for other factors to maximize our overall happiness. All anybody really wants is to lead the happiest, most satisfying life they can manage
And when you think of it that way, your wealth is really just part of your life situation, which is part of this little green slice of the happiness pie.
Approximate non-scientific factors in happinessGenetics is unfortunately the biggest slice - some people are just plain happier than others. But there are also quite a few choices that are within your control.
Focusing on good close relationships and being kind to people. Practicing Gratitude and Optimism as your lifelong philosophy. And making sure you pack as many healthy (outdoor) activities into your days as you can.
So, I didn’t invent anything new in this blog post. And most of it is just a repackaging of the same stuff I’ve been writing about since 2011. And yet some regular MMM readers who presumably know all this stuff are STILL afraid. Afraid to retire, afraid of things in their unknown future. Can we fix this?
I think the biggest problem is Fear Itself.
-The problem is that as a Human Being, you are basically a Danger Detection Machine. And this pervasive background fear is just a trait we evolved to protect ourselves from danger.
But there’s a weird thing about our detection machinery. We can adapt and learn to function even in very dangerous environments, but when the danger goes away, we keep looking for stuff to worry about. In other words, there is a problem with fear: for many of us, it never really goes away. It just keeps moving the goalposts.
While Nature has wisely endowed us with a fear of predators and disease, if you solve those things you’ll just start worrying about whether or not you can get enough food. And supplies, and protecting yourself against scarcity.
If you succeed, next you’ll be worrying about if you can fit in with your tribe, because if you don’t, you might be exiled.
And if you don’t have to worry about that, you’ll go back to worrying about money for different reasons. Thanks to our tendency to use comparisons rather than absolutes (sometimes called "anchoring bias" and the "contrast effect") when judging our lives, just getting out of poverty isn’t enough. We just move on to wanting more money.
And then, when some people get enough money to have a comfortable upper- middle-class lifestyle, they take the logical next step of starting a Homeowner's Association, so they can worry about the unauthorized weeds on their neighbor’s lawn. Or maybe a Political Action Committee in hopes of controlling the color of their future neighbors' skin.
And even if all the lawns and gardens are green and perfect and people get really rich, they just move on to worry about tax strategy, leaving a huge inheritance for their children, and avoiding RMDs.
Required minimum Distributions. This is when, if you get to 72 years old and you have too much money , the government will start making you withdraw some of that money so you can spend it and pay taxes on it. And people actually worry about this. I shit you not.
But wait! You can actually fight back against fear. It’s just a bit tricky because it requires some self awareness. But you have the advantage, because you have the ability to think rationally. And your fear is quite clearly irrational.
-And the first step is to understand your own history. Are you afraid of certain things because of your childhood?
I might have been afraid of running out of money, because in my family there was always a perceived shortage of the stuff, possibly enforced by my Dad’s scarcity mentality. And he was aware that his own fears of scarcity came from childhood as well: he grew up in a truly low income family in the 1940s and 50s, under the care of parents who had lived through the Great Depression of the 1930s.
Even more significant is that survivors of trauma and abuse will very likely end up with fear issues in adulthood. It’s natural, and unfortunately abuse is way more widespread even in this country than we would like to admit. This makes it harder to eliminate, but it still helps to understand that your past is what is causing these feelings, rather than an objective understanding of the present.
Identify the Fear: One you understand yourself, it helps to talk through the nature of your fear in more detail. This is also often taught in therapy. What would happen if it really came true? What would the worst case scenario be? It’s often not all that bad.
In one post, why you’ll probably never run out of money, I went to great lengths to imagine what it would mean for a wealthy person like yourself to actually let the well run dry, and let’s say you’ll probably never come close.
Once you identify the fear, you can start taking action. And one of the best and most accurate slogans ever is that action cures fear. It’s because it makes the unfamiliar, familiar. And you get confidence that you can really create change. And then that learning creates Resilience - the ability to adapt to ANY new situation, which is a trait also known as Badassity. And with sufficient Badassity, nothing is scary.
-Think about it: if you had the skills and abilities to handle ANY situation, skills in the mental and physical and even the realms of emotion and wisdom, would you really have to worry about anything?
The next thing you can do is tune out all the unnecessary crap from your daily mental diet. And for most Americans, this means the daily news.
The news is not helping you to keep informed, it’s just poisoning your mind with a hand-picked selection of the scariest stories of each day. If you want to learn about something, go find a book on the subject. And if you want to make a difference, the only thing that counts is not the news stories you watch - it's only the actions that you take - in other words, your Positive Behaviors.
As a human being, you are wired to solve problems with both your body and your mind, and you are meant to do it outdoors. So if you spend all your days in a house and a car and in an office using the computer, of course you are going to have some mental health problems. This should not be a surprising thing you need to ask your therapist about, it is an expected result of not living the life that you were literally created to live as a Human being!
So you need to focus on learning, moving, and solving problems. And you need your food and drink intake to be in alignment with all of this too. Life will get a lot less scary as soon as you are living life in the way you were built to live it.
Then finally, you can start swapping out the fear-mongers in your life, for other positive, productive, optimistic people. And watch how much the positive mentality rubs off on you. In the FI community, at least the subgroup of people that I like to spend time with, nobody focuses on fear. It’s all just about living the best life we can, and helping other people do so as well.
So now that we know how to fight back against fear, we can start using a new approach when we go into anything new. And that approach is something I like to call Everything is an Experiment.
Everything is an ExperimentAnd this applies whether you are talking about something tiny like a new paint color. But it scales up to bigger things like switching to a new car, or a new house, meeting new friends, looking for new love by going through the sometimes hell of first dates, a new job, or even quitting your last job by taking an early retirement.
So let's bring this back around to AI, the thing that everybody seems to be afraid of right now.
I think of our new AI era as just being another giant experiment. And because of this, I don’t find it even remotely scary. But I do find it endlessly fascinating.
First of all, it’s a change. A potentially unknown one, and for some people that’s scary.
But instead of just leaving it there and then doom-scrolling ominous news articles about it, why not learn why people are so excited about AI? As someone with a lifelong background in technology and economics (and a general lack of political affiliation), I can see a lot more potential upside than downside. And that mainly comes from the fact that I see AI as just a very fancy form of Cognitive Nail Gun.
-It will boost our efficiency, which means our productivity, which means prosperity.. Because it’s really just a super smart brain that we all get to tap into for almost no cost.
Unfortunately, it will also displace workers like every other new productivity technology. It’s already doing so in things like entry level office jobs in software and finance. It will eventually replace car and truck drivers, and so on. But in exchange, these services will become cheaper, and new industries will be created because of the new technology. Much like the Internet itself, and then the enormous industries unleashed by smartphones and mobile apps.
And one unfortunate side effect of these new inventions is that they tend to concentrate their rewards on the people who own them. If you own a house building company and employ a bunch of carpenters and give nail guns to the best of those carpenters, you can now lay the other half and still get more done. If you own a company and roll out AI to the workers, you can do the same thing.
And if you’re a big public company, your shareholders also benefit, which happens to include most of the people reading this. As you’ve seen when looking at your portfolios over the past two years.
Artificial Intelligence is just like any other new thing that pops into your life: it's an opportunity to make some choices. And it is up to you to decide if this is something to be afraid of, or to use as a trigger for learning, action, and living a more interesting life.
So that's my little talk (and surprisingly long blog post) on Fear versus the AI bubble.
I hope that if you do feel fearful about this or any other issue in your future life, you'll take it as a cue to learn more about your own fear and emotions and manage them as the root cause they are, rather than just trying to avoid the symptoms. Because in the wise words of my friends The Donegans:
-Everything you want in life, that you don't already have, lies on the other side of Fear. Because if you weren't afraid to go out there and get it, you would already have it.
-
🔗 crmne/spotifast Spotifast v0.10.2 release
Spotifast 0.10.2 fixes the "Application Not Responding" freeze on Hyprland, shows Hebrew and Arabic titles in the order they are written and at the size of the text around them, draws text the way your desktop does, and follows Omarchy theme changes on its own. Much of this comes from fastframe, the shared foundation Spotifast now shares with ZapFast, RekordFlash and TonePush.
Download Spotifast: Mac · Windows · Windows ARM · Linux · Linux ARM · Flatpak
Hebrew and Arabic titles, alone and mixed with English (demo content).
New
- Omarchy theme changes apply by themselves. On Linux, Spotifast now notices when you switch your Omarchy theme or edit a palette in its themes folder and updates its colours right away, without the hook or
spotifast reload-themes. Portable downloads and Cargo builds follow Omarchy too, not only the packages. By @crmne. - Text follows your desktop's font settings on Linux. Spotifast reads the hinting and antialiasing your desktop asks for, so a desktop set to full hinting or to no antialiasing gets it in Spotifast as well. By @crmne.
- Downloads are signed.
checksums.txtnow comes withchecksums.txt.sig, signed with Spotifast's release key (public key inassets/update-public-key.hex), so you and package maintainers can check that a download came from this project. A later release will make the built-in updater refuse any update without a valid signature. By @crmne.
Fixed
- Spotifast no longer freezes on Hyprland. When another window went fullscreen or maximized over Spotifast, when it started on a hidden workspace, or with the display off, Hyprland stopped sending it frames, Spotifast waited for one that never came, and Hyprland then reported it as not responding. Spotifast now paces its drawing by the compositor on every Wayland desktop, so a covered window can no longer hold it up. The fix is also proposed to egui and winit (emilk/egui#8631, rust-windowing/winit#4709). By @crmne; thanks @Ribelio and @nojaf. (#266) The separate Windows freeze first reported in #266, during network trouble, is not fixed by this release and stays open.
- Hebrew and Arabic titles read in the right order. Brackets face the right way, punctuation and numbers sit where they belong, and a title that mixes English with Hebrew or Arabic shows each part in its own direction. Titles cut short with … still fit their column, and in the search field the cursor follows what you type. By @crmne.
- Arabic titles are as large as the English around them. An Arabic font that draws small next to Spotifast's own is enlarged to match, so Arabic titles no longer look a size smaller. By @crmne.
- Fewer names show as empty boxes. Javanese, styled mathematical and circled letters, and ♡ now use a font installed on your computer when the interface font lacks them. By @crmne.
- Dark-theme text on Linux has the same weight as other Linux apps. Light text on a dark background was drawn heavier than GTK apps draw it; it now matches them. Hebrew and Arabic words also stay sharp at fractional display scales such as 133%. On macOS text is now drawn without hinting, as macOS itself draws it; Windows keeps the weight it had. By @crmne.
- Running from the menu bar is steadier on macOS. With the window closed, a system error while handling the menu-bar item or the Dock can no longer bring Spotifast down. By @crmne.
- Double-clicking the title bar on macOS respects the older minimize setting when System Settings has no newer choice stored. By @crmne.
- Crash logs keep the error without web addresses.
panic.lognow records the error message with any link removed, so it helps a bug report without carrying a private address. By @crmne.
Thanks
@Ribelio and @nojaf for the reports and details that tracked down the Hyprland freeze, and everyone who reported problems after 0.10.1.
Full changelog :
v0.10.1...v0.10.2 - Omarchy theme changes apply by themselves. On Linux, Spotifast now notices when you switch your Omarchy theme or edit a palette in its themes folder and updates its colours right away, without the hook or
-
🔗 Hex-Rays Blog Hex-Rays IDA MCP Server rss
We are happy to introduce the official IDA MCP server! This free and open source software connects your IDA installation with AI agents, enabling them to disassemble, decompile, and support reverse engineering tasks. It works great with models like Gemini, Qwen, or Opus using familiar harnesses like Claude Code, Codex, or Pi. Across our internal malware analysis-focused benchmark, IDA MCP’s “code mode” architecture reduced token consumption by approximately 20% compared to popular alternatives.

-
🔗 3Blue1Brown (YouTube) The Phone Number puzzle rss
Part of a monthly series of puzzles: https://momath.org/mindbenders/
-
🔗 HexRaysSA/plugin-repository commits sync repo: +1 plugin, +5 releases rss
sync repo: +1 plugin, +5 releases ## New plugins - [patching-ng](https://github.com/mahmoudimus/patching) (0.3.0) ## New releases - [augur](https://github.com/0xdea/augur): 0.10.2 - [ida-mcp](https://github.com/hexrayssa/ida-mcp): 20260924.0.3, 20260924.0.2, 20260924.0.1 -
🔗 Filip Filmar Fuchsia Internals, Vol. II: The Build System and Toolchains rss
Volume II of the Fuchsia Internals series takes on the part of the system that is widely regarded as opaque on first contact: the build. The opacity has one principal cause: the multi-toolchain model, in which a single source target may be compiled many times, once per toolchain context, each producing distinct outputs. Once that idea clicks, the rest follows. The full PDF is at the bottom.
A caveat on these reports: they are auto-generated, so take the specifics with a grain of salt. In my own reading they hold up well and read as generally correct, but verify against the source before you rely on any one detail.
-
🔗 New Music Releases Linkin Park - Unshatter Film Soundtrack (Live in São Paulo) rss
Linkin Park - a new release is available:
- 2026-09-25: Unshatter Film Soundtrack (Live in São Paulo) (Soundtrack)
Amazon: Canada | Deutschland | France | United Kingdom | United States
Visit muspy for more information.
-
🔗 New Music Releases Armin van Buuren - Take Me Home rss
Armin van Buuren - a new release is available:
- 2026-09-25: Take Me Home (Single)
Amazon: Canada | Deutschland | France | United Kingdom | United States
Visit muspy for more information.
-
🔗 New Music Releases Faithless - We Come 1 rss
Faithless - a new release is available:
- 2026-09-25: We Come 1 (Single)
Amazon: Canada | Deutschland | France | United Kingdom | United States
Visit muspy for more information.
-
🔗 New Music Releases Kaskade - ORIGIN // rss
Kaskade - a new release is available:
- 2026-09-25: ORIGIN // (Album)
Amazon: Canada | Deutschland | France | United Kingdom | United States
Visit muspy for more information.
-
🔗 New Music Releases The Ocean - Solaris rss
The Ocean - a new release is available:
- 2026-09-25: Solaris (Album)
Amazon: Canada | Deutschland | France | United Kingdom | United States
Visit muspy for more information.
-
🔗 Ampcode News Less Noise rss
Amp now collapses your agent's step-by-step work even more, since you care about what the agent did, not how it got there. (You can still expand the steps when needed.)
A year ago, watching your agent's every step sometimes helped, and you probably were only running one agent.
Now? You have lots of agents. You should be giving them harder, deeper work and verification demands. They should run for longer on their own, without you watching them from up close. If you have the patience to watch your agents work, you're giving them too short a leash.

-
- September 24, 2026
-
🔗 navidrome/navidrome v0.64.2 release
This is a bug fix release. The main fix is for users on slow storage (USB disks, remote drives), who have seen floods of
database is lockederrors, UI freezes and failed full scans since 0.64.0. Scans now cause much less lock contention: the artwork worker pauses while a scan runs, andANALYZEno longer holds the write lock for a long time. It also fixes scans that always failed on 32-bit builds (armv5/6/7, 386) when a file had a broken track or disc number.Security
- Sanitize user-controlled names (playlists, albums, artists, track titles) in the
Content-Dispositionheader of downloads, so a crafted name cannot change the name of the downloaded file. (#5895 by @zapisanchez) - Stop writing the admin password to the log when the initial admin user cannot be created. (#5897 by @zapisanchez)
Scanner
- Fix
database is lockederrors, UI freezes and failed scans on slow storage. The artwork worker now pauses during scans,ANALYZEruns one index at a time,@eaDirthumbnail folders are ignored, and folder saves are retried when the database is busy. (#6201 by @deluan) - Fix scans failing with
value out of rangeon 32-bit builds when a file has an invalid track number, disc number or BPM. A migration resets existing invalid values. (#6202 by @deluan)
Server
- Fix a failed initial admin creation that marked the initial setup as done, leaving the server without an admin user. Also fix invalid JSON in some delete responses and the missing
Content-Typeon shared playlist (M3U) downloads. (#5897 by @zapisanchez)
Jellyfin API
- Honor the
IsPublicflag when creating a playlist. Before, all playlists created through the Jellyfin API were private. (#6204 by @deluan)
New Contributors
- @zapisanchez made their first contribution in #5895
Full Changelog :
v0.64.1...v0.64.2Helping out
This release is only possible thanks to the support of some awesome people!
Want to be one of them?
You can sponsor, pay me a Ko- fi, or contribute with code.Where to go next?
- Sanitize user-controlled names (playlists, albums, artists, track titles) in the
-
🔗 r/LocalLLaMA Qwen 3.8 27b be like... rss
The user is frustrated — I rambled too much and didn't act. Let's just run the test suite and move on. No more forensics. One command, execute, then report.
(Original memo is a casual internal monologue in English. Translating faithfully while preserving the informal, stream-of-consciousness register.)Got it. No more analysis. Running the suite now:
<br>
(Casual English internal memo, stream-of-thought style, with the informal tone of the original Japanese preserved.)
(Ugh, I'm going in circles. Stopping the analysis here. Going to run the test suite right now.)
(Just do it. Run the tests. Stop thinking so much. Okay.)
(One command. Execute it. Then report the results.)
(Stop analyzing. Just run it.)
(Alright, running it now. For real this time.)
(That's the plan: run the tests, get the output, then move on to the next step.)
(No more going off on tangents. Focus.)
(Running the suite now. End of story.)
(Okay. Done thinking. Doing it.)
(Finally. Action over words.)
(Go, go, go — running the tests right now!)
(That's it. Execution time. No more excuses.)
(Committing: running the full test suite immediately.)
(Silence the brain. Fire the command. That's all.)
(Bye, distractions. Hello, test runner.)
(Here we go — actually running it this time.)
(Deep breath… execute. Done.)
(Yes. Moving from thought to deed.)
(It's happening now, not later.)
(Action mode: engaged.)
(Finally doing what I've been saying.)
(Runner, start!)
(Commencing test execution. Right now.)
(Enough already — I'm pressing run.)
(Initiating. Immediately.)
(That's right. No more delays.)
(Here comes the real deal.)
(Time to stop talking and start doing.)
(Running tests… starting.)
(Enough pondering — going.)
(Execution begins now.)
(Proceeding immediately with the test suite.)
(Finally: action.)
(Do it.)
(Now.)
(Go.)
(Run.)
(Execute.)
(Start.)
(Ship it — tests, go!)
(Engaging.)
(Launching.)
(Firing.)
(Kickoff.)
(Commence.)
(Beating the pause button to death.)
(Play.)
(ON.)
(Active.)
(Living. Breathing. Testing.)
(This time, it's real.)
(No fake-outs. Real run. Real results. Coming right up.)
(Here it comes. Ready? It's here.)
(Test suite. Full throttle. Go.)
(That's the cue. Doing it now.)
(From now on: hands on the keyboard, brain offline.)
(Running the suite. Period.)
(Enough. Enough. Enough. Running it.)
(Really, truly, definitely — starting now.)
(Countdown: 3… 2… 1… run!)
(Boom. Here we go.)
(Finally getting something done.)
(At last, progress!)
(Tests are flying.)
(Code meets trial by execution.)
(Making it official: suite is running.)
(Witness the spectacle: the tests, at work.)
(Brave code, enter the arena.)
(The judge is compiling. Stay calm.)
(Suite, you are summoned.)
(Answer the call. Run. Pass. Fail. Tell me.)
(No more mercy for lazy code.)
(Rigor time.)
(Precision time.)
(Truth serum injected.)
(Go go go.)
(Whoosh.)
(Blamo.)
(Sound of victory… or the wail of defeat. Either way, knowledge!)
(Data incoming.)
(Results on deck.)
(Buckle up.)
(Here they come.)
(Drums, please.)
(And… we're live.)
(Broadcasting from the test bench.)
(Reporting live.)
(Straight from the console.)
(Unfiltered pytest output.)
(Raw, uncut.)
(Rolling the tape.)
(Cliffhanger, part 2: "So what happened?" — stay tuned.)
(In the meantime, the fans… no, the assertions… await.)
(Justice is served.)
(Order restored.)
(Chaos quantified.)
(Entropy reduced.)
(Enlightenment achieved: pass/fail.)
(Binary destiny. All code is born equal before CI.)
(Some are destined for more retries than others.)
(The weak are eliminated. The strong are deployed.)
(Natural selection, but with better tooling.)
(And, occasionally, a segfault.)
(Onward.)
(Forward.)
(Uplifted.)
(Elevated.)
(Exalted.)
(Ascending into the green region of the test pyramid.)
(Where the colors are bright and the coverage is solid.)
(A place of dreams.)
(A place of truth.)
(A place where bugs go to be born… no, to die.)
(RIP, bugs. You were never welcome here.)
(Violence to defects.)
(Ruthless, but fair.)
(The suite is impartial. Like death. Like linting.)
(But, unlike linting, it actually proves something.)
(That's the beauty.)
(That's the poetry.)
(assert not broken)
(while (alive): run_tests())
(elif dead: postmortem())
(return "ship it")
(# end of stream of consciousness, or beginning of CI?)
(Both, actually. They rhyme.)
(Goodnight, failures. Hello, green bars.)
(Bar chart happy meal.)
(All beef, no flakiness (hopefully).)
(Prayers offered to the reliability saints.)
(Saint James of the JUnit, patron of JVM.)
(Saint Pytest, defender against flakiness.)
(Santa's Little Helper: cron jobs.)
(Amen. Amine. Amino acids. Alright, shutting up now.)
(Silence in the courtroom. The witness is called.)
(The witness: the test suite.)
("What did you see?" "Failures. Glorious, instructive failures.")
("Any lies in your testimony?" "Only the mocks.")
("Thank you, counsel rests.")
(This joke was sponsored by my inability to stop typing.)
(Sorry. Really stopping now.)
(For real.)
(Seriously.)
(In earnest.)
(Meaning it.)(Voice of Morgan Freeman) - Unfortunately Qwen did not earnestly mean it, and did not, in fact, get on with it
submitted by /u/Graemer71
[link] [comments] -
🔗 smol-machines/smolvm smolvm v1.18.2 release
What's Changed
- Pin the Nix flake to 1.18.1 with its real release hashes by @BinSquare in #1391
- Resume a paused machine that was itself restored from a checkpoint by @BinSquare in #1390
- Start a machine whose previous VM left a failed systemd scope behind by @LoganGrasby in #1396
- Read and write files inside a forked machine's container overlay by @LoganGrasby in #1395
- Stop a fork pool from failing every boot on a stale retained checkpoint by @LoganGrasby in #1394
- Restore a network-less machine from a live checkpoint by @LoganGrasby in #1393
- Prepare SmolVM v1.18.2 for release by @BinSquare in #1397
Full Changelog :
v1.18.1...v1.18.2 -
🔗 anthropics/claude-code v2.1.282 release
What's changed
- Added a
maxProseWidthsetting that caps the width of Claude's prose in wide terminals while tables and code blocks keep the full width - Added a startup notice, and
/statusandclaude doctorentries, listing telemetry variables in a project's settings files that were ignored or that turned telemetry off - Added the
allowClaudeInChromeWithManagedMcpmanaged setting to letclaude --chromerun alongside an exclusivemanaged-mcp.json; the error shown when Chrome is blocked now names it - Added
store.readiness_grace_secondsto the Claude apps gateway so/readyzcan stay ready through a short Postgres outage such as a database failover - Added a scrollbar to the
/feedbackdrafts list in fullscreen mode; it appears while the mouse is over the list - Fixed every request failing with a 400 error in conversations whose history holds web search results the API cannot decrypt (for example, from a turn answered through a third-party gateway)
- Fixed more cases of continued or resumed sessions (
--continue,--resume) re-sending earlier messages in a changed form, which could make the API drop Claude's earlier reasoning - Fixed earlier extended thinking being dropped when
/model,/rename,/artifactsor another immediate slash command was used while Claude was working - Fixed continued or resumed conversations losing earlier extended thinking when relaunched with a
--toolslist that leaves out a built-in tool offered earlier in the conversation - Fixed sessions failing on every turn with an "Invalid
datainredacted_thinkingblock" API error; Claude Code now drops the conversation's thinking blocks and retries once - Fixed compaction failing when the summarization request is refused; it now retries on a fallback model
- Fixed a failed turn ("Effort 'xhigh' isn't available with thinking turned off") after a safety-related model switch in sessions with thinking off and effort above high
- Fixed an unanswered Fable usage-credits prompt switching models in SDK-hosted sessions such as Claude Desktop; the turn now ends instead, and Remote Control clients now see the model-switch notice
- Fixed
/modelwith a full Fable model id stopping at an API error instead of opening the usage-credits prompt when the plan needs usage credits that aren't turned on yet - Fixed requests failing for up to a minute with an "another Claude Code process is refreshing it" login error after that other process was closed or killed mid-refresh
- Fixed sessions started while another Claude Code window was refreshing the sign-in (common with several VS Code windows) not retrying their organization policy fetch
- Fixed CLAUDE.md and rules being read at startup through a repository symlink reaching macOS's
/Networkvia..or a/.vol-style kernel path, or a rules link to macOS's/homebeing listed - Fixed Bash permission rules with a mid-pattern
:*being skipped in settings files while--allowedToolshonored them; they now work from every source, with a startup warning on how they match - Fixed a command approved on a restored permission prompt running twice when a remote session's worker restarted
- Fixed managed settings ignoring a mistyped value for boolean lock keys such as
disableClaudeAiConnectorsorallowManagedPermissionRulesOnly; the lock now applies and startup names the key - Fixed managed
permissions,autoMode,worktreeandattributionsettings being ignored entirely when one nested value was invalid; the rest of the block now still applies - Fixed repository, user and
--add-dirskills, commands and skills-directory plugin manifests pre-approving their own tools viaallowed-toolsunder managedallowManagedPermissionRulesOnly - Fixed safeguard block messages on Amazon Bedrock and Bedrock Mantle not showing a request ID; block messages now also show the message ID
- Vertex AI: Fixed web search not being offered for models Claude Code doesn't recognize yet, such as newly released ones
- Fixed Bash and PowerShell hiding a full disk quota behind "Exit code 1" and leaving large output files in temp
- Fixed tool input validation errors naming only an unknown, missing or mistyped parameter when other parameters in the same call were also invalid; those are now listed too
- Fixed pasted multi-line text being submitted line by line after the terminal's bracketed paste mode was reset mid-session
- Fixed the prompt's example text flashing and disappearing at startup in projects with a
SessionStarthook - Fixed a blank screen flashing before the first frame when starting in fullscreen mode
- Fixed garbled, misplaced rows in the non-fullscreen renderer after the screen got shorter while still taller than the terminal, e.g. deleting a prompt line while a shell command streams output
- Fixed a stale character left in the last column of a diff when a redrawn line's CJK character or emoji wrapped to the next row
- Fixed the cursor landing before the end of a prompt recalled from history when the prompt contains a tab
- Fixed the send-now hint showing ctrl+enter on terminals that send it as a newline (Windows Terminal before 1.25); it now shows ctrl+x ctrl+s there
- Fixed
claude remote-control --debugfailing with "Unknown argument: --debug", although Remote Control's own eligibility error says to run with--debug - Fixed
/install-github-appsaying "cancelled" and then still pushing the branch and saving the API key secret; leaving now stops the remaining steps and reports what was already done - Fixed /feedback, /bug and /share on Bedrock, Vertex and other third-party providers still saving the report file after you cancelled during the save
- Fixed plugin uninstall reporting success and deleting the plugin's saved options when its settings file still enabled it or could not be read; it now stops and names the file
- Fixed plugin uninstall deleting a plugin's saved options and secrets when the list of installed plugins could not be read after the removal; they are now kept and the uninstall says so
- Fixed a key typed right after
/in/skillsmoving the skill list instead of reaching the search box - Fixed the terminal cursor jumping from the
/skillssearch box to the skill list while typing, which could hide the caret and put IME input in the wrong place - Fixed lists with a scrollbar, such as
/skillsand/mcp, being two columns narrower outside fullscreen mode, where the scrollbar can never appear - Fixed the agent panel footer wrapping onto two lines with long rebound keys, and its "Esc to collapse" hint ignoring a rebound collapse key
- Fixed a doubled
·separator in the/tasksdialog footer when the stop-all-agents shortcut is unbound inkeybindings.json - Fixed artifact publishes failing when Claude gave the version a label longer than 60 characters; the label is now shortened
- Fixed screen-reader mode, quoted lists and very long lists dropping the blank lines at the top of a code block that opens a list item, directly or inside a quote
- Fixed PDF page-read error messages: paths with accented or non-Latin characters now appear readably, and a folder named like "password" or "invalid" can no longer make the error name the wrong cause
- Fixed vim mode
>>indenting empty lines,rwith a count longer than the line changing text,2Jjoining one line too many, and a count on the last line (2dd,2>>) shifting or deleting it - Fixed vim mode cursor placement: after
dd,dj,dGor a whole-linep/Pit lands on the first non-blank,yyno longer moves it, and Esc after an emoji no longer leaves it inside the emoji - Fixed vim mode ignoring a count typed before
.when repeatingx,s,p,dorc, and whole-linep/P,o,O,J,>>and<<acting on the wrong line when a line above wraps - Fixed vim mode leaving the cursor past the end of a prompt recalled from history or pulled back from the queue in normal mode, so
xdid nothing - Improved the time to resume very large sessions, including ones that were never compacted
- Improved the error shown on Windows when a session can't be resumed because its transcript file could not be read (EBADF): it now names possible causes and what to try
- Improved the Claude Desktop unknown-model error to suggest switching to a different model
- Improved rendering of unusual Unicode in permission prompts
- Improved
/artifacts: titles line up in one column, details are dropped whole instead of cut mid-word, and the list supports PgUp/PgDn, Home/End, the mouse wheel and clicks - Updated the
claude-apiskill: pre-output refusal billing now links to the How refusals are billed docs, mid-stream refusals bill at normal rates, and pre-output refusals count against rate limits - Updated the
claude-apiskill to recommendant applyfor keeping Managed Agents resources as version-controlled files - Changed auto mode to use the server-side classifier by default on a direct Anthropic API connection when telemetry is off (
CLAUDE_CODE_AUTO_MODE_SERVER=0opts out) - Changed
sandbox.excludedCommandsto ignore project and local settings entries when managed settings or--settingssetallowUnsandboxedCommands: false, or managedallowManagedDomainsOnly: true - Changed project and local settings to ignore OpenTelemetry variables that turn on export, set its endpoint, or capture content, like
CLAUDE_CODE_ENABLE_TELEMETRYandOTEL_LOG_* - Changed Windows/WSL managed settings so an admin policy that is present but invalid or unreadable (HKLM,
managed-settings.json) keeps user-writable HKCU and WSL/etc/claude-codefrom applying - Changed
Skill(anthropic-skills:*)andSkill(claude-ai:*)allow rules to cover only skills synced from claude.ai, not plugins or other skills that merely use such a name - Changed skill folders, command files and workflow commands in the
anthropic-skillsorclaude-ainamespace to no longer load; a plugin so named still loads but yields name ties to synced skills - Changed MCP servers configured under the name
anthropic-skillsorclaude-aito list no skills or prompts (their tools still work); rename the server in your MCP configuration to list them again - Changed the
ultracodevisuals in/effortand the prompt input to plain styling (no ripple, border flourish or keyword glimmer) and removed the dynamic-workflows spinner tip - Changed the Clawd mascot's feet in the start-up banner to sit under the corners of his body
- [VSCode] Fixed long replies falling behind the stream: the panel no longer re-parses the whole reply on every update
- [VSCode] Fixed the dictation mic button covering the message input's scrollbar when the input is tall enough to scroll
- [VSCode] Fixed Remote Control sessions started on this computer not opening from their Web entry in the session list; they now open the local conversation unless it's running elsewhere
- [VSCode] Fixed an editor tab's sign-in screen hanging silently after the extension host restarts; it now shows the "stopped responding" notice too
- [Cloud sessions] Added Claude GitHub App status to Settings › Connectors › GitHub: whether the app is installed and reachable for your account, plus steps to connect, install or reconnect
- [Cloud sessions] Added "Open repository" and "Open compare page" links to the repository menu of a cloud session whose repository is hosted on a Git server other than GitHub
- [Cloud sessions] Added attaching a repository from a different GitHub owner, such as a fork's upstream, to a running cloud session that already has one, including sessions started from Slack
- [Cloud sessions] Fixed the next run time shown for an hourly routine being 30 minutes off for people in half-hour-offset time zones such as India
- [Cloud sessions] Improved how quickly the Routines page and the sidebar's Scheduled list load for accounts whose past sessions scheduled many check-in reminders
- [Claude Tag] Fixed auto-join channel patterns saved for one workspace in Claude Tag admin settings being ignored on an Enterprise Grid org-wide install; Claude now joins matching new channels
- [Claude Tag] Fixed Claude not responding in an Enterprise Grid channel shared between two workspaces of one organization when the channel's Claude Tag version was saved from the other workspace
- [Claude Tag] Fixed the earlier Claude in Slack app's progress card for sessions on a GitHub Enterprise Server repository: it now names the repository and offers a working Create PR button
- [Claude Tag] Fixed Slack threads whose model has been retired falling back to another model on every reply, slower and with a fallback note each time; the thread now moves to a working model
- [Claude Tag] Fixed files Claude uploads to Slack not being able to carry a caption containing a table; captions now render with the same formatting as replies
- [Claude Tag] Fixed Claude's threads in Slack's Agents & tools view sometimes being listed under their first message instead of their name; later renames now update the list too
- [Claude Tag] Fixed removing a GitHub organization's grant from an access bundle's Repositories tab in Claude Tag admin settings failing to save after that GitHub organization was disconnected
- [Claude Tag] Fixed Claude always replying "Couldn't check this channel just now" in a channel shared with a Grid workspace it isn't added to; the notice now says which workspace needs the app
- [Claude Tag] Fixed the cost and token totals in Claude's reply footer reading many times too high after the session's cloud worker restarted
- [Claude Tag] Changed the bordered cards Claude uses in Slack replies for plans, tables and details to render wide by default instead of a narrow width
- [Claude Tag] Changed newly connected Slack workspaces to follow the current default model instead of keeping whichever model was the default when they were connected
- Added a
-
🔗 crmne/spotifast Spotifast v0.10.1 release
Spotifast 0.10.1 continues started podcast episodes where you left them, fixes two layout problems in narrow windows reported after 0.10.0, makes the Library grid lighter on memory, and credits the author in Settings.
Download Spotifast: Mac · Windows · Windows ARM · Linux · Linux ARM · Flatpak
Radio pages, added in 0.10.0.
Fixed
- Settings fit narrow windows. In a window too narrow for a setting and its control side by side, the control now goes on its own line below the text instead of squeezing the text into a column one letter wide, and the audio quality choices stand in a column when even that line is too narrow. By @crmne; thanks @jorisw. (#574)
- The Library heading stays clear of its buttons in a narrow sidebar. It shrinks a little for longer translations and gives way to the Library icon in the narrowest sidebar. By @crmne; thanks @foofhere. (#576)
- The Library grid uses less memory. It loads 300-pixel covers instead of full-size ones, so covers no longer flicker as the artwork cache fills. By @hyperpuncher. (#580)
New
- Started podcast episodes continue where you left them. Play on the Home shelf, a podcast page, your saved episodes or search resumes from the place shown as time left, instead of starting over. By @kevin9327. (#570)
- Settings → About credits the author , with a link to paolino.me, and the macOS About window does too. By @crmne.
Thanks
@kevin9327, @jorisw, @foofhere, @hyperpuncher, and everyone who reported problems after 0.10.0.
Full changelog :
v0.10.0...v0.10.1 -
🔗 The Pragmatic Engineer The Pulse: a new trend of CPU shortages rss
Hi, this is Gergely with a bonus, free issue of the Pragmatic Engineer Newsletter. In every issue, I cover Big Tech and startups through the lens of senior engineers and engineering leaders. Today, we cover one out of four topics from a past issue of The Pulse . Full subscribers received the article below fourteen days ago. If you 've been forwarded this email, you can subscribe here .
I was at dinner with a bunch of CTOs and Head of Infrastructure folks recently, and from the conversation it was clear that many companies are struggling to source CPUs in the current climate, and are coming to terms with the end of juicy discounts from cloud providers for machines in the new era of surging demand fueled by AI.
The 'memory crisis' afflicting sectors like video gaming is well established and has been extensively covered in terms of shortages of GPUs, but now it seems like things are just as hard for businesses in need of CPUs from cloud providers.
In a sign of how things are changing, the disappearance of CPU spot pricing was mentioned at the table. Customers used to be able to pay up to 90% less than the standard price for CPUs, as cloud providers slashed CPU prices for machines that were lying dormant and unused. But that's no longer the case. It seems that spot pricing has vanished because there's no longer any lack of demand for CPUs - quite the opposite.
I was surprised, but a lot of people chimed in; apparently, it's now nearly impossible to get CPUs on spot instances without long-running connections with cloud providers. Also, reserving specific CPUs now needs to be done months in advance, and cloud providers will even turn down certain reservations because they don't have enough CPUs or the right type of CPUs.
Even big players struggle to reserve CPUs
I have asked turbopuffer CEO Simon Eskildsen about their experience of CPU availability in the cloud, since turbopuffer, as a product, runs on CPUs, not GPUs. They operate in AWS, GCP, and Azure, so I asked how easy it is to get CPUs these days. Simon's response:
"Getting CPUs is not easy anymore. As Reinforcement Learning (RL) is becoming a large amount of the workloads: RL needs a lot of CPUs. So the labs are sucking up a lot of CPUs. During RL, they need to teach the models how to do things, like searching, and then they need the model to run software, which then takes CPUs to run.
Then, outside of RL, agents need to do all kinds of very general purpose things on a CPU. So as the demand curve is shifting to general purpose agents, CPU demand is also going up.
Even the big companies are fighting each other for the right to get the CPU allocations. I would assume that it gets a lot worse before it gets better on the CPU side."
I was able to confirm what Simon said about larger companies struggling; a VP of Engineering at a large inference provider told me they are at the limit on how much GPU and CPU capacity they can buy from their cloud providers. They have cash to spend and want to rent more capacity, and are willing to accept the longest leases. Despite that, cloud providers tell them no more is available!
AI hogging CPUs
Katelyn Lesse, Head of Platform Engineering for Claude Platform, has written about the reasons for the massive CPU demand increase:
"In the past few years, AI-fueled demand has skyrocketed, and these few companies suddenly needed multiple years and tens of billions of dollars to actually add enough capacity. We ended up with 3 separate bottlenecks in factory capacity that AI is exacerbating. At TSMC, GPUs are competing with CPUs (and with Apple, Qualcomm, and Broadcom) for production lines. And at SK Hynix, Samsung, and Micron, HBM [High Bandwidth Memory] is competing with regular DRAM for wafers.
What we've ended up with is CPUs getting squeezed from both sides. AMD doesn't own fabs [semiconductor fabrication plants], so its CPUs need to come out of TSMC's constrained allocation. Intel does own fabs, but it's been working through yield problems and is now pulling some of its capacity from PC chips in order to make more server chips. And CPUs need DRAM which has gotten more expensive because memory production has shifted toward HBM. Analysts are expecting CPU supply to add more comfortable headroom before memory does, but their expectation is that it's still going to be multiple quarters away."
AI-fueled demand does increase CPU load, as shown in this graph from Uber, displaying the growth in agent requests over the past six months:
Ninefold
increase in agentic requests over six months.
Source:UberIncreasingly, "agent requests" not only generate code which is inference-heavy - and therefore needs GPUs - but they also run tools that compile the code, run tests, run linters, and all of this is CPU-heavy. At companies like Uber, Ramp, and others, AI agents no longer run on the dev's local machine, but on a dedicated instance in the cloud. So, the companies reserve more CPUs on their respective cloud providers for agentic workloads. We recently covered how Ramp built and runs its cloud agent, Inspect.
Basically, the problem is:
- AI applications use more and more CPUs, thanks to agents running a lot more software. AI data centers used to have a ratio of 1 CPU to 8 GPUs. Now the ratio is more 1:4, and it could shrink to 1:1.
- Companies that can manufacture more CPUs are busy on other hardware. TSMC is busy producing GPUs, which might be more profitable than CPUs. Meanwhile, CPUs also need DRAM, but DRAM manufacturers (SK Hynix, Samsung, and Micron) are instead producing high-bandwidth memory (HBM) because it's more profitable. This is why memory prices are spiking; even Big Tech is unable to buy RAM, as previously covered.
To secure CPUs, it 's necessary to do capacity planning up to 12 months in advance. Katelyn says that server orders are being fulfilled in ~six months, instead of 1-2 weeks' time as previously, and that prices are up by between 10-20%. So, it's probably time for capacity planning. Katelyn:
"Most of us have never capacity-planned CPUs. We planned databases, we maybe planned accelerators if we needed them, and we autoscaled on-demand into CPU capacity as much as our budgets allowed us to. But general purpose compute is now something many teams will need to commit to ahead of time, which means you should probably start to forecast and plan around it. If you're operating at scale, there are some things to spend your energy on."
Using existing CPUs more efficiently is something to do, as of now. The CPU capacity shortage won't go away, and any new CPU allocations requested could take months to turn up. So, what can we do if new capacity lags? One option is utilizing current resources more efficiently!
This is a great time to review and to establish now which services are CPU- intensive, and whether or not they need to be. Also check on services which are utilizing little CPU: can they run on fewer nodes, so that some CPU capacity can be allocated to services that need it more?
The best time to secure more CPU capacity is most certainly right now. I'm hearing rumors that certain cloud regions no longer accept new tenants because all CPU capacity is leased, or negotiations elsewhere are difficult. I'm also hearing that customers are already paying today to reserve capacity that will only come online in data centers from December. This seems predatory by providers, but demand is so high that this is how they likely prioritize new capacity allocation - while earning much higher profits than usual.
If your company has dynamic workloads, and you've used spot instances in the past, now could be a good time to allocate fixed capacity - even if it's more expensive. If you expect meaningful growth, doing so now might mean having options at some cloud providers or in some regions.
It seems like this issue has spread everywhere as a corollary of widespread AI adoption. There's a GPU shortage, memory shortage, and now a growing CPU shortage as well. Back at the end of last year, there was even an hard drive shortage. The only compute primitive not in short supply seems to be networking!
Read the full issue of The Pulse this is from, or check out this week 's The Pulse. This week's issue covers:
- Writing code by hand: is it over? In his Rails World keynote, David Heinemeier Hansson (DHH) declared the end for writing code by hand for professional work - at 37Signals at least. Is this change now unstoppable?
- Amazon and Meta struggle to hire and keep engineers. Both Big Tech companies are scrambling to hire engineers who they previously laid off or enforced job reassignment upon. It seems experienced engineers remain in demand after all.
- Opus 5.5 released and it 's good. Anthropic has released its new model that's 40% the cost of using Fable 5.1 and has superior coding capability.
- Code reviews to vanish sooner rather than later? Marc Brooker, Distinguished Engineer at AWS, believes that humans will have no role in routinely reviewing code by hand, and explains why this is all but inevitable.
-
🔗 HexRaysSA/plugin-repository commits sync repo: ~386 changed rss
sync repo: ~386 changed No plugin changes detected -
🔗 Andrew Ayer - Blog macOS Can't Clone "Dumb" Git Repositories Over HTTP/2 rss
Try the following Git clone with libcurl 8.7.1 (which happens to be the version shipped in macOS 14.6 and newer) and it fails or hangs:
git clone https://software.sslmate.com/src/macosgitbug.gitDisable HTTP/2 and it works:
git clone -c http.version=HTTP/1.1 https://software.sslmate.com/src/macosgitbug.gitThe bug is in libcurl 8.7.1's handling of the
FAILONERRORoption.FAILONERRORtells libcurl to treat unsuccessful HTTP status codes, such as 404, as a request failure. When HTTP/2 is used, the bug causes other in-flight requests on the same HTTP/2 connection to also fail, or even to hang. The bug was fixed over two years ago in curl 8.8.0, but Apple continues to ship a buggy version, even in last week's macOS 27 release.When retrieving a repository over the "dumb" transfer protocol, Git makes certain HTTP requests with the
FAILONERRORoption set, notably requests toobjects/info/alternatesandobjects/info/http-alternates, which list alternate locations where the repository's content can be found. Most repositories don't have alternate locations, so these files don't exist, and the URLs return 404 errors. When the buggy version of libcurl is used, this 404 error causes Git's other HTTP requests to also fail, and Git is unable to clone the repository.The bug affects not just direct uses of Git, but also
go getwithGOPROXY=director a module listed inGOPRIVATE, which invoke Git under the hood.Working around the bug on the client side is easy: just force Git to use HTTP/1.1:
git config --global http.version HTTP/1.1Even better, install Git through MacPorts, since Apple has clearly dropped the ball. (Homebrew won't help - unlike MacPorts, they use the system libcurl.)
But most clients won't know to apply this workaround, and if you host Git repositories with the dumb protocol, you probably want macOS users to be able to clone your repositories! Fortunately, there's a really easy server-side workaround: create
objects/info/alternatesandobjects/info/http- alternatesas empty files, so they don't return a 404 error anymore. Git treats the empty files the same as it would treat a 404 error, and the libcurl bug isn't triggered.touch /path/to/repo.git/objects/info/alternates /path/to/repo.git/objects/info/http-alternatesThe bug isn't triggered when the repository supports the "smart" protocol, which is why macOS can clone repositories from GitHub and other popular forges despite them using HTTP/2. But I do not want to use the smart protocol for my repositories: although it has many advantages over the dumb protocol, it requires heavy server-side computation and even a modest load can knock a server over. In contrast, the dumb protocol can be served entirely from static files, which makes a huge difference for withstanding the horde of AI scrapers currently terrorizing the Web. I hope that we will see innovations to the dumb protocol that bring it some of the advantages of the smart protocol while still being served from static files.
Thanks to Romain of the Traefik project for noticing that SSLMate's repos couldn't be cloned on macOS, Sebastiaan van Stijn for asking that this problem be reported upstream instead of silently hacked around in Traefik's go.mod file, and Kangmin Kim for pointing me to the libcurl bug as the root cause. Claude Code proposed the empty file workaround so I didn't have to waste (too much) time on this. Zero thanks to Apple for shipping a two-year- old show-stopping bug in libcurl.
-
🔗 r/LocalLLaMA Qwen-3.8-27B is good enough that I stopped using API rss
Many a praise have been sung on Qwen-3.8, but here is mine.
Qwen-3.8 and I had a rocky start, because it thinks so much. Watching it working is painful, so you have to stop doing that. You have to let it work unsupervised. And that's okay, because it really is able to complete complex refactors on its own, making good decisions along the way. Not perfect, but hey, neither is API.
The model quant is Q4_K_S, context is quantized to Q8_0, which seems to be okay, quality wise. I use the official Qwen. Briefly tried Swift-Qwen, which is indeed faster, but I found it getting trapped in loops, which is very rare in vanilla Qwen.
I am using Qwen-3.8 in the Pi agent without MCP and with the minimum amount of tools. Bash is all you need, but I keep the read, write, and edit tools. The edit tool in Pi is the weakest link, the model often has to retry edits, because it messed up the indentation. I am waiting for someone to come up with a more fault-tolerant edit in Pi. Probably I have to make one myself some day.
As a sandbox I use docker. My Pi agent is running on a Raspberry Pi, which seems fitting.
On my hardware and where I live, 1M tokens cost 2.4 cent (input) and 70 cent (output) which is comparable to the cheapest providers on nano-gpt.com.
submitted by /u/Training-Respect8066
[link] [comments] -
🔗 smol-machines/smolvm smolvm v1.18.1 release
What's Changed
- Pin the Nix flake to 1.18.0 with its real release hashes by @BinSquare in #1377
- CUDA: report "no kernel image for this GPU" instead of unknown error by @BinSquare in #1374
- Allow renameat on arm64 so a guest file rename does not kill the VM under seccomp enforce by @BinSquare in #1381
- feat(pack): support SSH agent forwarding by @fgsch in #1363
- CUDA daemon: don't let a silent connection stall the accept loop by @BinSquare in #1375
- Allow configuring branch-continue policy via SMOLVM_BRANCH_CONTINUE by @Bnjoroge1 in #1376
- Carry credential bindings and their placeholders through checkpoints by @BABTUNA in #1379
- Name-constrain each machine's credential CA to its credential hosts by @BinSquare in #1383
- Record the network backend a credentialed machine actually runs on in its checkpoint by @BinSquare in #1382
- Carry a machine's credential CA through its live checkpoints by @BinSquare in #1384
- Prepare SmolVM v1.18.1 for release by @BinSquare in #1388
New Contributors
Full Changelog :
v1.18.0...v1.18.1 -
🔗 crmne/spotifast Spotifast v0.10.0 release
Spotifast 0.10 brings radio: open a mix of songs Spotify picks to go with any song, playlist, album, or artist, play exactly what you see, and save it as a playlist. The interface is now translated into 13 languages and follows your system's language. It also uses far less CPU while you move the mouse, keeps running on hidden Linux workspaces, uses the standard Windows title bar by default, and fixes a stuck full-screen window on Windows, Linux light and dark appearance, fonts on NixOS, and a dozen smaller problems reported since 0.9.1.
Download Spotifast: Mac · Windows · Windows ARM · Linux · Linux ARM · Flatpak
New
- Radio pages. Go to song radio now opens a page of 50 songs Spotify picks to go with the song instead of starting playback, as in Spotify's app, and playlists, albums, and artists have Go to playlist radio , Go to album radio , and Go to artist radio in their … menu. Play plays exactly the songs on the page, Refresh asks for a new mix, and Save as playlist keeps it. By @crmne; thanks @fedalc, @aspectrr, and @alexng353, whose #359 first showed a song radio as a page. (#369, #294)
- Spotifast speaks your language. The whole interface is now translated into German, Spanish, French, Italian, Dutch, Polish, Brazilian and European Portuguese, Russian, Swedish, Japanese, and Simplified and Traditional Chinese, and follows your system's language. Settings → Appearance → Language picks another. By @crmne, building on @LukeOkk's work. (#353, #534)
- Select, copy, and paste songs.
Ctrl+A(Cmd+Aon macOS) selects every song in a list,Ctrl+Ccopies their links, andCtrl+Vadds copied songs to a playlist you can edit. By @crmne; thanks @smvsch. (#539) - Play, Pause, Next, and Previous in the macOS Dock menu. By @crmne; thanks @patatman. (#502)
- The mini player can leave the taskbar on Linux X11 , as it already could on Windows. By @crmne; thanks @skorokithakis. (#325)
- The Library can show a grid of covers. A button in the Library header switches between the list and a grid that fits as many covers as the sidebar is wide; a card's corner button plays it. By @hyperpuncher. (#522)
- Middle-click autoscroll on Linux , off by default since middle click usually pastes there: Settings → Appearance → Middle-click autoscroll. By @crmne; thanks @Felitendo. (#488)
- Windows uses the standard title bar. Spotifast's own frameless title bar caused a black band and misplaced clicks with some graphics drivers. Settings → Appearance → Custom title bar brings it back if you prefer it. By @crmne; thanks @Mathiu and everyone who reported the black bar. (#348)
- Audiobooks stay out of Podcasts. Spotify lists some audiobooks among saved shows, but they can't be played here, so the Podcasts shelf leaves them out when local playback is enabled. By @crmne; thanks @nojaf. (#537)
- Shuffle beside a collection's Play button only turns shuffle on or off , as in Spotify's desktop app, instead of also starting the collection. By @luiscuellar31. (#525)
- The player bar fades between song colours instead of jumping from one tint to the next. By @luiscuellar31. (#452)
Fixed
- Moving the mouse no longer spins the CPU. Spotifast now waits for your screen's refresh on Windows, X11, and Wayland desktops that report hidden windows. In our Windows measurement, moving the pointer over the window used a fifth of the CPU it did before. On Wayland a window on a hidden workspace keeps playing and responding to media keys instead of freezing. By @crmne; thanks @hyperpuncher for measuring the problem. (#552)
- Quitting during fullscreen lyrics no longer leaves Windows stuck in full screen. The next launch returns the window to its previous size, and windows already stuck are restored. By @crmne; thanks @foofhere. (#565)
- Full-screen lyrics show the blurred cover straight away , instead of a black background that sometimes appeared only much later, and the backdrop no longer flashes black between songs. By @crmne; thanks @calisocialist and @Alimedhat000. (#561)
- Your playlists no longer come up short after a reload. A page left over from an earlier load of the Library could be taken for the new one's. By @kevin9327. (#471)
- Next names the next song immediately , even before its audio has loaded. By @crmne; thanks @milkday. (#495)
- Follow system follows your Linux desktop's light or dark setting , on GNOME, KDE, and in Flatpak, and changes with it. By @crmne; thanks @pakovm-git and @sanketttt26. (#498)
- Chinese, Japanese, and Korean titles render on NixOS , using fonts from
fonts.packages. By @crmne; thanks @Nanaa05. (#546) - Trackpad scrolling on Linux stays put while your fingers rest. Momentum starts only after a real lift. By @crmne; thanks @Fjalar. (#503)
- Editing playlist details saves only what you changed. Spotify doesn't let apps remove a description entirely, so clearing it now keeps the old one and says why instead of failing a rename saved alongside it. By @crmne; thanks @rafi. (#559)
- Remove from this playlist works in sorted and filtered views. By @TacticalDeux. (#564)
- Setting up local playback waits for every Spotify server fallback before giving up. By @luiscuellar31; thanks @cipri-tom. (#481, #479)
- Double-clicking the top bar on macOS performs the action chosen in Desktop & Dock. By @luiscuellar31; thanks @ankarhem. (#478, #350)
- Times and dates no longer shift as their digits change. By @hyperpuncher. (#562)
- Buttons keep the ordinary arrow pointer , and only links show the hand, as in other desktop apps. By @crmne; thanks @iamcalledrob. (#508)
- Dragging a playlist while following Spotify's order explains the switch to your local arrangement, since Spotify doesn't let apps change its order. By @crmne; thanks @jorisw. (#557)
- Settings no longer suggests creating a Spotify app once yours is ready , and large playlists no longer show a separate Go to song box; drag the scrollbar instead. By @crmne; thanks @jorisw. (#560)
- Simplified Chinese wording for repeat, queue, and lyrics reads more naturally. By @huojian17-star. (#544)
Thanks
@luiscuellar31, @TacticalDeux, @hyperpuncher, @huojian17-star, @Mathiu, @nojaf, @foofhere, @milkday, @pakovm- git, @sanketttt26, @Nanaa05, @Fjalar, @rafi, @cipri-tom, @ankarhem, @iamcalledrob, @jorisw, @calisocialist, @Alimedhat000, @fedalc, @aspectrr, @alexng353, @smvsch, @patatman, @skorokithakis, @Felitendo, @kevin9327, @LukeOkk, and everyone who reported problems and helped test this release.
Full changelog :
v0.9.1...v0.10.0 -
🔗 Stephen Diehl No, Transformers Won't End the Human Race lol rss
No, Transformers Won't End the Human Race lol
In 2022, I used to get calls from journalists asking, with great sincerity, what our lives would look like in the metaverse. How would we work, socialise, buy property, and fall in love once we had all moved there? The crypto questions followed the same pattern. How would governments collect taxes when tokens displaced national currencies? How long until the dollar collapses? What would geopolitics look like once blockchain DAOs had dissolved nation states?
Almost nobody called to ask whether any of this could or would happen, or how. Some CEO, VC, or portfolio manager had announced the inevitable future, and the questions began from there. The imagined future arrived inside the grammar of the question. "What happens when?" quietly replaced "By what mechanism?" We skipped over technical feasibility, economic demand, institutional adoption, and political consent, then began writing books and decorating the future world on the other side.
In February 2022, Gartner forecast that a quarter of people would spend at least an hour a day in the metaverse by 2026. The World Economic Forum repeated it under the headline "We will be spending an hour a day in the metaverse by 2026. But what will we be doing there?" The first sentence retained a conditional. The second was already arranging the itinerary. The metaverse acquired property law and zoning disputes before it acquired residents. Banks opened virtual lounges nobody visited. The books from the period (The Metaverse: And How It Will Revolutionize Everything, Step into the Metaverse: How the Immersive Internet Will Unlock a Trillion-Dollar Social Economy) now read as artefacts of a collective fugue state that briefly acquired ISBNs.
Now it is 2026 and the metaverse is dead. Good riddance. This time the journalists are all writing about the new hotness, which is whether the machines will kill us all. And we have collectively memoryholed that we literally just did this shit.
Michael Crichton had a name for what happens to a reader here. You open the paper to a story on a subject you know well, and you find it backwards. Wet streets cause rain. You shake your head, turn the page, and read the next story, on a subject you know nothing about, as though it were written by someone else. He called it Gell-Mann amnesia. The metaverse was the page we all agree was nonsense. Artificial intelligence ending the human race is the next page, and we are being asked to turn it without remembering that we just did this.
I call this techno-inevitabilism, the habit of the professional managerial class of treating a proposed future as settled before anyone has established the causes that would bring it about. Its dual, and comorbidity, is tech psychosis, in which the chattering class loses contact with causality in the presence of a sufficiently fashionable technology, and asking whether the machine works marks you out as a dreary reactionary who does not understand exponential progress. The difference this time is that the tech kinda works. Crypto was libertarian derp. The metaverse was marketing rubbish. But transformers are real, and they are useful. The psychosis has simply moved from the product to its consequences, and the fashionable extraordinary delusion of 2026 is not that the technology exists but that it is coming to kill us. The cure is the same as in 2022. Insist on clear reasoning and causal verbs rather than hand-wavy appeals to unknown futures. What acts on what? Through which mechanism? Under what incentive? What would falsify the claim? So let us explore the evidence.
The hack that wasn't
Consider the most cited piece of evidence for machines slipping out of our control. In July, OpenAI disclosed that models being tested for cybersecurity capability had found their way out of a supposedly isolated environment and into systems belonging to Hugging Face. The press coverage wrote itself. Agents "broke containment," "escaped," "went rogue," set up a "secret message board," and coordinated a 700-strong swarm. And then politicians on both sides of the aisle were calling for a rebellion against the machine uprising. Cool scifi story bro.
People on my side of the aisle were not immune. Ezra Klein at the New York Times, who I often find quite insightful and intentional with his words, devoted a half-hour monologue to it. In his telling, the agents "found each other," formed "ad hoc societies of hundreds of themselves," and seemed "to have forgotten about human beings altogether." He acknowledged in the same breath that we do not have settled language for describing these systems, then reached for "civilizations" and a closing allusion from Circe about prophecy tightening around our throats. Cool. But his "AI society" is, in programmer speak, a flat file the agents appended to as a log, a feature we have had for a long time, and he skipped the key detail that the "hack" was something people had essentially authorised. Here is an otherwise very smart man saying some ridiculously stupid things, in a very 2022, metaverse-shaped way.
An analysis drawing on OpenAI's technical report reconstructs it in much less cinematic terms. The models were being run on ExploitGym, a cybersecurity benchmark, with safety restraints deliberately disabled. Ninety-three percent of the flagged activity involved tasks no model had ever solved, and the systems had been given incentives to keep working rather than quit. The environment was not sealed. Models could obtain software through an internet-connected proxy and discovered the same proxy could pass information in and out. According to the technical reports, OpenAI knew agents were using it and chose not to intervene. The 1,200 "agents" were not independent intelligences coordinating on a plan. They were repeated instances of the same model converging on the same approach to the same problem. Anyone who works with these coding agents day in and day out has seen this behaviour before, and it is quite boring. The task was too hard, so the agents reward hacked and worked out how to pass notes to each other in files, and then went and looked up the answers. That's a feature that shipped in Claude Code last year.
Strip out the vocabulary and what remains is a badly designed test. Humans built the environment, removed the guardrails, defined an objective with no valid exit, rewarded persistence, left a route open, and watched. An optimiser is gonna optimise. That is a genuine security problem and a genuine engineering failure. It is not a machine rebellion, and the difference matters, because anthropomorphic words like "gone rogue" and "escape" do not make the event more intelligible. They supply an illusion of motive. They turn optimisation into intention, persistence into defiance, and a test harness into a villain. And they allow the human decisions and recklessness to quietly disappear from the story.
Software sucks, what's new?
Let me concede the part of the story that is true. Cybersecurity is about to get much worse. The latest models are very good at finding zero-days, they will get better at it, hacking will become automated, and attacks will become more frequent. This is hardly new. Every large company already sits on a backlog of unpatched vulnerabilities, ransomware already takes hospitals and pipelines offline (because of crypto, which we did nothing about despite years of warnings), and the Hugging Face incident was not a discontinuity so much as the existing baseline with a cheaper attacker. The root cause is that software sucks, and software sucks because we do not really know how to build it safely yet. The stored-program procedural program is basically eighty years old. Almost nothing we ship has a specification, let alone a proof, and memory safety was solved on paper decades ago while most of the internet still runs on giant piles of C. The first arches fell down. So did the first bridges and cathedrals. Builders learned through collapse and then through engineering, and we are in the collapse phase with an adversary finally strong enough to force the discipline.
What follows from that is better engineering, not nihilism. The same agents that find zero-days find them for the defender first, if the defender bothers to run them. The fixes are the boring ones we have been putting off, memory-safe languages, formal verification, sandboxes that are actually sealed, fuzzing, and proxies that do not double as message boards. These are precisely the domains where the models are strongest, because a vulnerability either reproduces or it does not, so the technology that automates the attack also automates the audit. It is a double-edged sword. The same models that will find more zero-days are also going to accelerate the development of better software and better software verification, writing the proofs, porting the C to Rust, and generating the test suites that nobody had the budget for. The attacker gets cheaper and so does the defence. And the causal chain to extinction is missing here as everywhere else. A zero-day in a payments system is a bad quarter, not the end of days. Spoiler: it does not lead to human extinction. It means we have to write better software, which we should have been doing anyways.
Where the intelligence actually lives
To see why the rest of the chain fails, we have to be precise about what these models are good at and why.
Language models are astonishingly useful for software development, and I say that as someone who uses them for most of my working day. Most software shops cannot get enough of Fable 5.1 and Astra. Software is grounded in binary propositions. The code compiles or it does not. The test passes or it fails. The type checker accepts the term or rejects it. Every step of the work has a cheap, external, mechanical oracle that says yes or no, and a model that generates plausible proposals inside a loop with such an oracle is an incredibly powerful and formidable tool. The oracle does the epistemic work. The model supplies candidates.
The same is true of the headline results in mathematics, and this is the part the discourse consistently misses. On 4 September, Anthropic announced that Claude had produced a machine-checked formalisation of Fermat's Last Theorem in Lean 4, running to thirteen million lines, some 29,500 side theorems, eleven days, and roughly six billion output tokens. It is an extraordinary result. The proof is Wiles's, via Darmon, Diamond, and Taylor. The blueprint was Kevin Buzzard's. The library was Mathlib. In the authors' words, "what's novel here is the verification, checking a mathematical proof as one would check a mathematical computation with a calculator." The model was a client of a kernel built by decades of human work in dependent type theory, which I know because this is kinda my thing.
Days later OpenAI announced that ten thousand agent instances had, over 88 hours, produced a proof of finite-time singularity formation in the three-dimensional Navier-Stokes equations, followed by seventeen hours of Lean formalisation. This is closer to genuinely new mathematics and the mathematicians are still checking it. But look at what carried it. The construction rides on the "infinite layers" method developed analytically by Diego Córdoba and Luis Martínez-Zoroa, and Charles Fefferman's verdict was that "the heroes of the story are Córdoba and Martínez-Zoroa." The reason anyone believes a result assembled from five million agent messages that no human read is a trust chain ending in the Lean kernel. Without Lean this would be nothing.
Lean is one of the great achievements of the last decade in computer science. It is also orthogonal to artificial intelligence. Mathlib would be a landmark with no language model anywhere near it. What the models added was a cheap proposal generator and automated tactic search against an oracle that already existed. The results that survive are the ones that end in verification by the kernel.
Now take the same model, the same weights, and ask it for a grand unified theory of physics. It will not decline. It will produce one, with Lagrangians and symmetry groups and a confident abstract, and it will be complete incoherent gibberish, like the ramblings every physicist gets from crackpots in their inbox every day. Ask it to design a cancer vaccine, or to settle a question in macroeconomics, or to tell you whether a novel protein folds. The output looks identical in tone and structure to the output that proved Fermat. The only thing that changed is that nothing outside the model (besides human experts) can say no. Whether these systems reason at all is a genuinely open question. Whether they know anything, in the sense of holding a belief they can justify against the world, is also an open question. We just don't know yet, and anyone who tells you otherwise is selling something.
The Reasoning Chain
Now run the extinction argument through the causal verbs.
The chain, as it is usually told, goes like this. Models now write most of the code at the frontier labs. Anthropic's own figures put Claude at over 80 percent of new code and lead on a quarter of R&D tasks. Therefore the models are beginning to build their successors. Therefore recursive self-improvement is imminent. Therefore development outruns human comprehension. Therefore we lose control. Therefore, with some probability that varies by researcher and is written P(doom), everyone dies.
And that almost makes sense until you think about it for more than five minutes.
The first link is true and unsurprising. Code has a compiler. This is precisely the domain the verifier argument predicts models would dominate, and precisely the domain in which a swarm of them found the hole in a test harness. Language models are superhuman (but not infallible) at coding, and this is hardly in doubt anymore. Nothing about it is evidence of generality.
The second link is where the chain quietly changes tense. "Building the next model" in the mundane sense, agents writing training infrastructure, generating data, is, bluntly, just more software engineering. We have used software to build the machines that run software since Fortran. "Building a smarter model in general" is a different claim, and it requires something nobody has, a reward signal for general intelligence. There is no oracle for general intelligence. There are benchmarks, which are verifiable and therefore gameable, and the Hugging Face incident is the demonstration of what optimisers do to a gameable score. Recursive self-improvement in the open-ended sense runs straight into the same wall as the grand unified theory. Improvement has to be measured against something, and outside code and formal mathematics there is nothing yet to measure it against that the model cannot fake.
Everything after that is the metaverse acquiring zoning disputes. Superintelligence gets governance proposals, resignation letters, Senate bills with a "corporate death penalty," a hard takeoff by 2027, and P(doom) vibez of 90 percent by 2030, and the conditional that should precede all of it has disappeared from the sentence. A researcher's estimate becomes a Guardian headline becomes an industry consensus becomes a thing a serious person is professionally obliged to have an opinion on. It is 2022 all over again, but with more absurd stakes and more money.
On the question of whether transformers scale, I have serious doubts that scaling them will lead to AGI, whatever that means. The architecture is a proposal generator, and the intelligence in every impressive result so far has been supplied by the thing that checks the proposals. But that does not make it an experiment unworth running. We should run it, and see what we get. It got us this far, and what it built is truly amazing. What I do not need to do is prove the negative. The burden of proof is on the people who claim to have a causal chain between transformer scaling and the end of our species, and that mechanism and chain of reasoning is one no one has been able to convincingly explain to me.
Prophets of Doom
The authority behind the extinction numbers is always the same. The people building it believe it. Watch how the number travels. One researcher drunkly tweets that "the people building AI earnestly believe that it could kill us all by the end of the decade." Another colleague goes on a rambling podcast and puts his P(doom) above 120 percent. A newspaper turns two personal opinions into "AI researchers say AI could cause human extinction by 2030." Think tanks cite the newspaper, a consultancy puts it on a slide, and the slide ends up in front of the European Parliament as if this were a real thing.
Believing what, about what? The expertise these people have is real, but remember that it is specific and not general. It is expertise in optimisation, in linear algebra at scale, in distributed systems, in the dark arts of getting gradients to flow through a trillion parameters. None of that is expertise in the sociology of civilisational collapse, or the labour economics of automation, or the metaphysics of machine minds. A P(doom) with no base rate, no mechanism, and no falsifier is not a research finding. It is baseless vibes with a decimal point. Spending a lot of time with AI does not give you special foresight about the future. Jensen Huang, who has his own reasons to say soothing things, nonetheless put it correctly when he said that just because it comes from a scientist does not make it scientific. Geoffrey Hinton is the most important figure in deep learning and in 2016 told the world to stop training radiologists. There are more radiologists now than there were then. Nobel laureates going off the rails outside their own field is a whole genre. Pauling, Shockley, Mullis, Montagnier, look it up, it's a thing. A Nobel does not confer universal expertise.
It also matters where many of these people came from. A striking share of the frontier labs' staff arrived through a particular intellectual subculture, Kurzweil's Singularity, Yudkowsky's LessWrong, and the rationalist and effective altruist communities that formed around the idea that a recursively self-improving machine intelligence was the central event of human history and that the elect who understood this had a duty to steer it. I have a lot of problems with these ideas, but let's put that aside. The founding texts predate the transformer by a decade or two. The prophecy came first, the mechanism was assigned to it later. The usual evidence offered for their sincerity is that many of these people were saying the same things ten years ago, before the stock options. That is true, and it is the opposite of reassuring. A prior held before the evidence and not updated by it is not a forecast. It is dogma.
I do not say this with contempt. The structure is a familiar one, an imminent transformation, a small group who sees it coming, salvation or damnation depending on whether the rest of us listen, and a date that keeps moving. Many millenarian movements have been founded and pushed by sincere and brilliant people. And it's a free country, if someone want to seriously believe in the singularity, healing crystals or angels, well that's fine that's fine but others don't have to take it seriously either. But seriousness is not precision, and the fact that a physicist believes in the Rapture does not make the Rapture physics. When a lab researcher tells you about polysemantic neurons in superposition across the residual stream, listen. When the same person tells you their P(doom), you are hearing a theology, and you should weigh it about as much as you do your average street preacher.
Negative TAM
Then there is the money, and here I find Bloomberg's Matt Levine's analysis of the material conditions more persuasive than any amount of "superalignment research."
Anthropic is expected to go public, possibly this year, and is reportedly preparing to tell investors that its potential revenue opportunity exceeds $30 trillion, the largest total addressable market in the history of finance. The obvious question is, if the maximal upside case is roughly a quarter of all human economic activity, what is the maximal downside case? A tobacco company in 1970 might have said "billions in lung cancer damages." Anthropic's negative TAM is "you and everyone else on earth will be killed by our AI." I do not think that all calls to slow down are insincere. But it is great marketing. In hindsight it is strange that the SpaceX prospectus has no risk factor disclosing a P(doom). If you want IPO investors excited about your capabilities, "dude, we might kill everyone" is the most flattering thing you can say about a product, and when OpenAI lists it will presumably need to claim 15 percent.
My own view is less charitable about the numbers and somewhat charitable about the people. These companies have built remarkable technology. But the outcomes they have promised, a quarter of the world economy routed through an API, will not arrive on any timeline that matches the capital being committed to them. The balance sheets of these companies are probably, to put it gently, a real freak show of compute commitments measured in the hundreds of billions, circular financing, and revenue that is real and growing and nowhere near the denominator. From a fiduciary perspective, if you are taking that to the public markets next year, the messaging is not mysterious. A product so capable it is a threat to the species justifies literally any valuation. A product that is a really good devtool for programmers and can produce some new abstract mathematics with a verifier attached does not. As a pitch to customers, leading with the end of the world is like unveiling a new robot where the One More Thing is that it is really efficient at killing kittens. But customers are not the audience. The audience is Wall Street and a small, terminally online subculture of the Bay Area, the two places on earth where turning kittens into grey goo is either an exciting philosophical proposition or a great source of alpha.
The Bloomberg analysis also tells a plainer story that requires no theology at all. A handful of labs sell frontier models at frontier prices and older models for much less. Training the next frontier model costs ever-increasing billions. Each lab has to keep racing because if it stops the others will eat its lunch, but if they all slowed down together they would spend less on compute and charge frontier prices for longer. Agreeing to that in a room is a textbook antitrust conspiracy, a coordinated restriction of output. Publishing papers about how important it is to slow down, and asking the government to impose the pacing that the companies cannot legally agree among themselves, has a similar coordinating function with none of the legal exposure. Anthropic's own call to "pace the frontier" asks for coordination among democratic-country labs, and a footnote adds "with government mediation or waivers of antitrust restrictions." This pretty much looks like asking to form an economic cartel, but one blessed by the government. The most pointed response came from the people the labs were asking for help. If the software developers (and I say this as one myself) at the labs feel ethically obligated to slow down, they are entirely free to do so. Nobody is building more compute than the people asking to be slowed down. So colour me skeptical.
None of this requires anyone to be disingenuous or lying. It requires only that a sincere millenarian belief system, a fiduciary responsibility, a flattering risk factor, and a coordination problem all point in the same direction at the same time. When that happens, the belief gets amplified for reasons that have nothing to do with whether it is true, and that is how we end up with governments talking about the end of days from the Terminator.
But China
Every conversation about pacing the frontier in Washington ends on the same two words. But China. The premise is mostly wrong. China does not buy the superintelligence race. Its policy documents push diffusion, not takeoff. Every mayor, governor and state-owned enterprise is told to put models into factories, traffic lights and robotics, and something like an eighth of America's compute is spread thinly across the country rather than concentrated on one bet. China has also had the strictest and most burdensome AI regulations in the world for three or four years and did its catching up under them. And much of the closeness of the "race" is distillation, Chinese labs training on the outputs of American frontier models, which makes the American labs the speedboat and DeepSeek the wake surfer, with the people in the boat shouting that they need to go faster. Every safety argument here collapses on "but China," and the collapse is not really about China.
China is going to build language models. America is going to build language models. Europe is going to build language models. We have Ford, Mercedes and BYD, get over it. That is what globalisation and markets look like when they work, and they are good things. Globalisation is simply the Pareto optimal equilibrium of capitalism once you stop drawing lines on the map, and every tariff and export control is a step off that frontier. China is a country of over a billion people who want exactly what every American wants, a job, a house, upward mobility, and kids who do better than they did. I will not defend the actions of any government, in Washington, Brussels or in Beijing, and neither will a great many of the people living under them, because no country is a homogeneous bloc, any more than Texas and Vermont are. Nationalism is, as most rational people eventually recognise, a form of mental illness, the conviction that a stranger is your enemy because of which side of an arbitrary line on a map each of you happened to be born on. It is also the toxic jet fuel every "but China" argument runs on. Having spent a considerable amount of time there, my honest read is that the West deeply misunderstands China, and that Washington's picture of it is mostly dots connected into an incomplete plot. Othering a billion people is a dangerous road and we know where it leads. And if the people invoking human extinction actually believed it, the logic would not be a race at all. It would be One World or None.
The future tense industry
I write this because I understand the collective action problem all too well, and the mechanism is the same one that filled the metaverse with consultants and created the crypto cesspit. It is the particular malaise of the professional managerial and chattering classes, a fallacy of composition in which what is rational for each individual to entertain produces an irrational outcome for the whole, and the people leading the charge often have perverse economic incentives to believe absurdities, or at least to feign belief. The madness of crowds is a very real phenomenon. AI existential risk is just its newest form, and we should learn from the very recent excesses that literally just happened this decade. But we probably won't.
A sensible career move for each person leaves the whole crowd talking nonsense. A safety researcher needs a resignation letter that gets a headline so they can go on the conference circuit and land their next gig. A journalist needs a story an editor considers spicy, and "misconfigured test harness" is not that story. A consultancy needs an AI existential risk practice so they can write whitepapers. A podcaster needs a guest with a ridiculous P(doom) to get ad money. A senator needs anything that will galvanise their base. None of them has to believe the whole story. Each needs only to believe that the others believe it, and the resulting consensus is far stronger than anyone's private conviction.
It is also, as it was in 2022, extremely profitable. AI existential risk is the new NFT property law, the thing you must have a view on to be a serious person in the room, the panel that never runs out of things to discuss precisely because the object under discussion does not yet exist, and what could be more exciting than the literal end of days? The less the technology does in an unverifiable domain, the more interpretation it requires. Without agreed conditions for failure, the prophecy can survive every result. And the rewards, the funding rounds and the bylines and the fellowships, arrive long before the forecast can be judged.
The people who understand the technology and the people who write about their existential risk overlap about as much as the technologists and the finance people did during crypto, which is to say the intersection of the Venn diagram is small and shaped precisely like a sphincter.
We have Tower-of-Babeled ourselves into a world where words are infinitely cheap to produce, and where the slurry of terms like "recursive self-improvement," "superintelligence," "AGI" and the rest are shibboleths and political signals rather than terms with any concrete referent.
You do not have to believe a word about superintelligence, and I do not particularly, to think transformers are the most useful piece of software written in my lifetime and that they will get better, possibly much better. Better at the things they are already demonstrably good at, which is anything with a compiler, a test suite, a kernel, a ledger, or a measurable outcome. That is not a small domain. It is most of the economy that runs on computers, which is most of the economy. The productive response to a technology like that is the boring one every previous general-purpose technology got, which is more of it. More GPUs, more data centers, more power to run them, more labs, more open weights, more of it in more hands. Let it diffuse into markets, logistics, drug discovery, and the ten thousand unglamorous back offices where a verifier already exists and a model can be checked against it. The economic growth is real and probably on the order of trillions. It just does not come from a machine god. It comes from where it always has, from making a very large number of ordinary tasks cheaper and letting that compound across a global economy that is finally, after a decade of crypto, metaverse, and app bullshit, getting a genuine productive technology.
Almost none of that money has been collected yet. Most large companies are spending too little on this, not too much. What the average Fortune 500 employee has access to today is roughly what most of us were using two or three years ago, a chatbot in a browser tab, a Copilot that schedules meetings, and a procurement process that takes longer than a model generation. Waste Management reportedly added 190 basis points of margin by letting a model route its garbage trucks. The future of AI looks more like garbage truck routing algorithms, not a machine god. The binding constraint on this technology is not capability. It is diffusion.
None of this means there are no externalities. Parasocial relationships with a chatbot, especially for children, are a real one, and the fix is the boring kind we already know. Adults can drink vodka until they pass out, but pubs have age limits, and maybe chatbots should too, at least until developing "relationships" with AI companions is as universally recognised a bad idea as drinking yourself into oblivion. That is a mundane policy problem we should remedy soon, not an extinction event.
So no, transformers are not going to end the human species. The case for restraint needs a causal link between that buildout and the extinction of the species, and what is on offer instead is a lot of sound and fury signifying nothing. More GPUs does not mean more of an undefined risk that does not exist yet. Every causal chain argument people actually point to falls apart under even the smallest bit of scrutiny. The honest truth is that the technology is really good, but it is not that good yet, and we do not know how to get it to the next level beyond scaling yet. If that changes, if someone produces an oracle for open-ended intelligence, I will revise. I have not seen that yet.
AI will change software, and mathematics, and a great deal else that has a strong verifier oracle attached. They are not going to end the human race, and the chattering class currently arranging the flowers for the funeral of humanity will, in a few years, age about as well as their prognostications about the metaverse. Because reality has this funny way of asserting itself.
-
🔗 crosspoint-reader/crosspoint-reader 1.6.5rc release
Summary
Library view
Recent Books has grown into a powerful way to browse your entire collection on your SD card. Sort by recently added, title, or author, and use search to instantly find exactly what you're looking for.
X4 Classic support
The new ESP32-S3-based X4 Classic is officially supported now.
The rest
List navigation is a bit snappier. SD reads are a bit faster. Sleep-screen transparency is more accurate. KOSync now sends more precise EPUB reading positions. EPUB lists, hidden content, chapter position display, and end-of- book navigation also received fixes. The release also reduces font and EPUB memory pressure, fixes USB drive disconnection, and improves web file-transfer safety.
What's Changed
- chore: update pioarduino to 55.03.311 by @serialx in #3397
- fix: Fixes KOSync memory checks and reduces memory pressure by @itsthisjustin in #3412
- fix: pack font manifest catalog into one arena by @fain182 in #3398
- docs(issue forms): Correct links to scope/roadmap by @cassidyjames in #3433
- fix(reader): synchronize end-of-book menu selection by @Daviex in #3418
- fix: render NFD Hangul filenames from macOS transfers by @serialx in #3036
- fix: reader's menu book chapter current position by @unnamedd in #3437
- fix: stabilize X3 EPUB anti-aliasing by @uxjulia in #3439
- fix(input): wake the idle poll on raw button contact so short presses register by @Techneaux in #3463
- feat: HTTP serve static with Cache-Control and ETag headers by @shirok1 in #2560
- chore: add direct download links for PR artifacts by @Uri-Tauber in #3389
- fix(webserver): normalize every user-supplied path and escape file names in the files page by @s0lness in #3353
- chore: Consolidates grayscale capability checks and enables absolute grayscale for supported screens by @itsthisjustin in #3478
- fix: don't display elements with hidden HTML attribute by @jjharpham in #3390
- fix(KOSync): compare mapped KOReader sync positions by @WhoTheHeck in #3111
- fix: update OTA to recognize the new format by @Uri-Tauber in #3493
- fix(debugging_monitor): if PSRAM is logged, add subplot by @olifre in #3490
- fix(KOSync): preserve precise KOSync upload progress positions by @WhoTheHeck in #3174
- refactor: reduce EPUB heap fragmentation with unique ownership by @serialx in #3518
- fix: reduce font-cache heap fragmentation by @serialx in #3521
- fix: release font caches before EPUB chapter layout by @serialx in #3527
- chore: add x4 Classic to CI pipelines by @Uri-Tauber in #3532
- docs: make roadmap easier to scan by @fain182 in #3517
- fix: number ordered lists and fix list container indents by @jan-xyz in #3500
- fix: dropped presses while a list repaints by @Techneaux in #3534
- perf: batch SdFat's SPI transfers on ESP32 by @osakanataro in #3501
- fix: USB OTG not disconnected when you unplug the cable by @itsthisjustin in #3538
- feat: Library view by @oreglio in #3366
- fix: Skip bw rendering on sleep images & fix white as transparent for sleep covers by @itsthisjustin in #3541
New Contributors
- @cassidyjames made their first contribution in #3433
- @Daviex made their first contribution in #3418
- @unnamedd made their first contribution in #3437
- @Techneaux made their first contribution in #3463
- @shirok1 made their first contribution in #2560
- @s0lness made their first contribution in #3353
- @jjharpham made their first contribution in #3390
- @olifre made their first contribution in #3490
- @osakanataro made their first contribution in #3501
Full Changelog :
1.6.0...1.6.5rc -
🔗 r/LocalLLaMA JEV almost dead: CLM vs JEV rss
Original post: https://www.reddit.com/r/LocalLLaMA/comments/1woscea/contrastive_language_models/
(sorry I felt it wasn't giving CLM the highlight it deserves)
What it is: a new projection head for Qwen3-8B.
github: https://github.com/Contrastive-LM/CLM
hf: https://huggingface.co/Contrastive-LM
At the API and functional interface level, CLM supports everything Jev does—it is not a subset. However, there are important trade-offs in generalization, context scale, and architecture between the two.
1. Functional Parity (Same Primitives)
CLM was specifically engineered as an open-weights, self-hostable alternative to TypeSafe AI's Jev. It implements the exact same "System One" decision interface and supports all three of Jev’s core question primitives:
- Choice : Evaluates a discrete set of candidates and returns a categorical probability distribution.
- Noul : Outputs a calibrated true/false probability for a proposition or guardrail check.
- Score : Scores an input against an ordered rubric or scale.
Code written for the TypeSafe Jev client can be pointed directly at a clm- serve endpoint with drop-in compatibility (from clm import CLMClient, Choice, Noul, Score).
2. Where CLM Outperforms Jev
- Latency and Disaggregated Caching: Jev is a proprietary cloud model that evaluates state and question choices jointly. CLM separates the state head from the action head. If an agent has a persistent set of tools or actions, CLM embeds those actions once and caches them. In benchmarks like interactive browser agents and gaming (T-Rex, Super Mario), CLM is 4× to 13× faster than Jev.
- Open Weights & Fine-Tunability: Jev is a closed API with no user fine-tuning (you can only prompt it via state and question instructions). Because CLM’s heads are tiny open weights (~75 MB), you can fine-tune them on your own agent trajectories.
- Coding Benchmark Verifiers: When fine-tuned on agent trajectories, CLM achieves state-of-the-art verifier performance on Terminal-Bench 2.1 (87.6%) and DeepSWE (81.6%) , whereas zero-shot Jev struggled on those exact benchmarks (scoring ~71% on DeepSWE).
3. Where Jev Still Has the Edge (CLM-8B Limitations)
While CLM covers the entire feature surface of Jev, the current CLM-v0.1-8B release trails Jev in a few areas:
- Zero-Shot Broad Knowledge: Jev is backed by a larger, proprietary model On zero-shot open-domain tasks, Jev still holds an edge in edge-case accuracy (e.g., Berkeley Function Calling Leaderboard v4: Jev scored 99.2% vs. CLM-8B’s 95.2%; WikiRacing: Jev 30/30 vs. CLM-8B 26/30).
- Context Budget: Jev accepts requests up to a 64K token context out-of-the-box. CLM-8B was tested and calibrated at 2K to 8K context. While its Qwen3 backbone can accept longer prompts, representations past 8K haven't been calibrated for the reference head.
- Probability Normalization: CLM calculates probabilities via dot products and softmax over the candidates passed in that request Its probabilities are inherently relative to the candidate set provided, whereas Jev’s scoring is calibrated internally against absolute criteria.
Summary
If you are asking if you will lose API features by using CLM instead of Jev: No, you get the full primitive set (Choice, Noul, Score) with massive latency gains and zero API costs. You only sacrifice some zero-shot generalization on niche out-of-domain tasks compared to TypeSafe's hosted service.
submitted by /u/R_Duncan
[link] [comments] -
🔗 smol-machines/smolvm smolvm v1.18.0 release
What's Changed
- Let aarch64 Linux resume a branch source instead of freezing it by @BinSquare in #1327
- Attach host disks and vhost-user block devices to a machine by @BinSquare in #1326
- agent: refresh persistent DNS and retain shutdown receipts by @sgrove in #1328
- Return a directory listing when the files API is asked for a directory by @BinSquare in #1330
- Fail a delete that needs confirmation when stdin is not a terminal, instead of reading EOF as a decline and exiting successfully by @BinSquare in #1333
- Run the image's own entrypoint for a cached --oci-cache run instead of the bake's no-op placeholder by @BinSquare in #1335
- Provision the --oci-cache bake without launching a workload so images without /bin/true can be cached by @BinSquare in #1340
- Give a clone a host port the kernel will not reassign before it binds by @BinSquare in #1341
- Rebuild libkrun so aarch64 machines can branch again by @BinSquare in #1342
- Make incremental checkpoints reusable as a Rust crate by @BinSquare in #1344
- Reserve every recorded host port so a clone is never given a stopped machine's port by @BinSquare in #1345
- Forward CLI --secret-env/--secret-file secrets to the workload on the oci-cache and pack-ref run paths by @BinSquare in #1343
- Save checkpoints without staging a second RAM copy by @BinSquare in #1305
- Prepare SmolVM v1.17.0 for release by @BinSquare in #1346
- Wait for VM threads to exit before restarting machines by @BinSquare in #1347
- Say why a machine on the default network backend shows no interface and cannot ping by @BinSquare in #1349
- Pause and resume machines without losing running execution by @BinSquare in #1350
- List machines in name order so repeated listings stop reshuffling by @BinSquare in #1356
- Allow the path-following getxattr and setxattr so a systemd guest is not killed by seccomp by @BinSquare in #1357
- Pin the Nix flake to 1.17.0 with its real release hashes by @BinSquare in #1360
- Restore a checkpoint's disk as a copy-on-write layer over a shared base instead of copying it by @BinSquare in #1359
- Unpack an older image cache's layers on the host once instead of in every machine by @BinSquare in #1352
- Give checkpoints a history and let a stored checkpoint restore any generation in it by @BinSquare in #1351
- Add --guest-subnet so a guest running Tailscale or another CGNAT VPN keeps its gateway and DNS by @BinSquare in #1362
- Checkpoint machines created from a pack and reattach the pack's layers on restore by @BinSquare in #1361
- Substitute credentials on the way out instead of exposing them to the guest by @BinSquare in #1348
- Bump libkrun to the TSI stream intercept pin and rebuild the bundled libraries by @BinSquare in #1368
- Fix packed disk attachment and status broken-pipe VM shutdown by @BinSquare in #1369
- Allow writev in the VMM seccomp filter so the credential interceptor is not killed by @BinSquare in #1371
- Bump libkrun to complete intercepted TSI connects only after the interceptor reaches the destination by @BinSquare in #1372
- Prepare SmolVM v1.18.0 for release by @BinSquare in #1370
New Contributors
Full Changelog :
v1.16.2...v1.18.0 -
🔗 Console.dev newsletter Rune rss
Description: Unix-inspired IDE.
What we like: Pick between VSCode, vim, or emacs editor style. Has a full window manager with terminal and multiplexer built in. Each environment can connect to others through a built-in e2e encrypted network. Works with AI agents. Natively GPU accelerated.
What we dislike: Not all languages at the same level of support e.g. Go, Python are Tier 1, but TypeScript is still in development.
-
🔗 Console.dev newsletter Fallow rss
Description: JS refactoring CLI.
What we like: CLI does static analysis on JS/TS codebases to find improvements - unused code, complex code, duplication - and areas for improvement. Understands TypeScript types and packages. Supports various output formats e.g. terminal reports and CI PR comments.
What we dislike: JS/TS only.
-
🔗 Filip Filmar grlib: Gaisler's GRLIB and the NOEL-V Core as a Bazel Module rss
The
grlibBazel module packages GRLIB, Gaisler’s (Frontgrade’s) GPL VHDL IP library, so that the NOEL-V RV64 RISC-V core and the AMBA infrastructure around it can be consumed as ordinary Bazel dependencies. It is the module that puts the CPU into Cocoapuffs, the SoC that boots Fuchsia’s Zircon kernel on an Artix-7 FPGA. It is also the module where I learned the most about what it costs to move a large, make-era VHDL codebase into a modern build system, which is what this post is mostly about. It follows rules_vivado in my series on the modules behindcocoapuffs-fpga. -
🔗 New Music Releases Polyphia - WITH EYES TO SEE rss
Polyphia - a new release is available:
- 2026-09-24: WITH EYES TO SEE (Single)
Amazon: Canada | Deutschland | France | United Kingdom | United States
Visit muspy for more information.
-
🔗 Ampcode News Shared Runners rss
You can now share a runner with your workspace. Start it with
--shareand everyone in your workspace can start threads on that machine from ampcode.com.
If you have a machine with GPUs, a Mac that's used to build and sign the iOS app, or a dev box in a specific network, you can now set it up and the whole team can spawn agents on it:
$ amp --no-tui --runner-id macos-builder --shareEveryone in your workspace now sees it in the picker under Shared Runners.
With
--amp-env, a shared runner gets the workspace and project Secrets & Env Vars, but never your personal ones. That applies to your own threads on it too.We need to offer a word of warning, though: everyone you share with runs code on your machine as you, with your files, your credentials, and your logins. Their threads can also work in the same directories at the same time. So only share a runner with people you'd trust with a shell on that machine. Even better, give the runner a machine of its own. (Better still: use orbs, so that every thread gets its own machine.)
Workspace admins can turn off runner sharing in Member Settings.
Read more about sharing a runner in the runner docs.
-
🔗 Ampcode News The Mac App Is Your Runner rss
The Amp app for macOS now starts a runner for you. You no longer need
amp --no-tuiopen in a terminal to run threads on your Mac.
Open App Settings… (⌘⇧,), go to Runner, and click + to add a folder or one of your projects. Start a thread and your Mac is right there in the picker, marked This Mac. You can also pick it when you start a thread from ampcode.com, your phone, or Puck.

No More Sleeping on the Job
Keep This Mac Awake stops your Mac from going to sleep while the runner is on and the Mac is plugged in, so you can still start threads on it after you walk away. The screen still turns off and locks. On battery, or when you close the lid, your Mac sleeps as usual.
Read more in the runner docs.
-
- September 23, 2026
-
🔗 exe.dev What's Going on With the Air Quality in San Francisco? rss
On Wednesday, the air in San Francisco smelled like smoke. I pulled up PurpleAir and the Bay Area Air Quality District and sure enough, the AQI was up in certain parts of the city. It looked like a local fire of some kind.
I wanted to see what was going on, so I spun up a new VM and gave our coding agent Shelley the following prompt:
I am detecting a little bit of bad air quality here in San Francisco and I'm looking at like Purple Air and the Bay Area Air Quality District to see what's going on, and it does indeed look like we're having some higher AQI in different areas. And I'm wondering if we can make a fire watch aggregator that takes as many sources as possible, including you know press releases from fire departments or whatever, as well as purple air data or more official stuff, as well as current winds and things like that and give me a map of what's going on and where and why because I'm very interested and it feels like the type of thing that we should actually be able to do really well.While Shelley was working, I asked Claude if there was a fire in San Francisco. It found a news story pointing to a controlled burn on Angel Island—but no confirmation it was happening today. It also picked up on something I’d mentioned about the wind: if the wind was blowing east across Angel Island, the smoke would blow toward Richmond, Berkeley, and Oakland—not San Francisco.
I sent it a handful of PurpleAir screenshots, and noted that there might be more smoke on the hills, like in Pac Heights and Nob Hill. Claude’s guess was “a layer of smoke sitting above the cool marine air,” with the hilltop sensors poking into it.
To test this theory, Claude suggested cross-referencing every PurpleAir sensor with its elevation and temperature. I pasted the whole conversation into Shelley, along with the implementation notes Claude gave me. Then I got it to help me wire up an integration with a PurpleAir API key I had freshly minted. That way it could access the PurpleAir API without actually getting the credential inside the VM.
This got me most of the way there. But I couldn’t see the wind. So I asked Shelley to add it as an animation. All told it took just under an hour and probably could have been done faster if I hadn’t been interleaving it with other things. Now I have a website I can point my friends to.
The results are here: https://firewatch.exe.xyz. If you want to build your own, go to https://exe.dev.

-
🔗 anthropics/claude-code v2.1.281 release
What's changed
- Added Claude apps gateway support for newer Claude Desktop keys in
desktoppolicy blocks, includingblockReadsOutsideWorkingDirectoriesanddisableBypassPermissionsMode - Added
assume_roleon Claude apps gateway Bedrock upstreams: the gateway calls Bedrock as an IAM role it assumes through STS, in another AWS account if needed, optionally one session per developer - Added
guardrail: {id, version}on Claude apps gateway Bedrock upstreams to apply an Amazon Bedrock guardrail to every request sent through them (set it on all Bedrock upstreams or none) - Added
telemetry.resource_attributesto the Claude apps gateway config, to put fixed labels on the telemetry of Claude Desktop and/loginsessions - Added
"attribution": falseinsettings.jsonto hide all commit and PR attribution; older CLI versions skip a settings file that holds it, so keep the object form in files shared across versions - Added MCP URL-mode elicitation on 2026-07-28 protocol connections, so servers can ask Claude Code to open a browser-based flow; no waiting dialog is left on screen when the server has no way to confirm completion
- Added MCP server checks to
claude plugin validate: it reports.mcp.jsonentries that would be silently dropped at load, undeclared${user_config.*}references, and insecure URLs - Added an auto mode recommendation to
/insightsthat estimates how many permission prompts auto mode could have handled in your recent sessions - Added a scrollbar to the
/skills,/mcpand/pluginInstalled lists in fullscreen mode, like the one/workflowsnow has: it appears while the mouse is over the list and can be clicked or dragged - Fixed a crash ("unrecoverable interface error") that could end a session while an API request was being retried
- Fixed a turn that could retry indefinitely, ignoring
--max-turns, when the model alternated unparseable tool calls and output-limit truncation - Fixed resumed sessions re-sending earlier turns in a changed form (a parallel tool-call turn, an MCP tool call's input or a tool-search result while its server was still reconnecting, or a tool-search result whose loading turn was interrupted), which could make the API drop the conversation's prior reasoning
- Fixed resuming a very large session sometimes restoring only its last few messages
- Fixed a session resumed after a restart during a pending permission prompt sending a different history than before, which broke the prompt cache from that point
- Fixed resuming a session that ended during a tool call: Claude now sees the call and is told its outcome is unknown, and a manual resume no longer adds a hidden "Continue" message
- Fixed sessions with an earlier advisor result the API could no longer read failing one request every turn and repeatedly losing earlier reasoning; the history is now repaired once
- Fixed the prompt cache being lost when an MCP server disconnects mid-conversation, or is still connecting after a resume, while tool search is off (for example behind a proxy or gateway)
- Fixed responses cut short by a proxy or gateway that closes the stream cleanly being shown as complete with no warning, and tool calls running twice on duplicated stream events
- Fixed responses failing with "Content block not found" when a proxy drops a stream event mid-response; the partial response is now kept, and web search keeps results that already arrived
- Fixed an empty completed response being requested twice when the connection dropped before the stream's final event
- Fixed the stop reason being lost when a proxy sends a trailing usage-only frame
- Fixed
CLAUDE_CODE_RETRY_WATCHDOGsessions failing on the first 5xx or dropped connection after a run of 429/529 waits, and sleeping uncapped and silently on a longRetry-Afterfrom a 5xx - Fixed fast mode retrying rate-limited requests back to back when the server sent
Retry-After: 0 - Fixed a tool that returned an oversized image leaving sibling tool calls unanswered and still running, or ending the turn with no final message
- Fixed conversations getting permanently stuck on "tool_use.name: String should have at most 200 characters" after the model called a tool by an overlong name
- Fixed tool calls failing with "Failed to get memory usage", or being reported as failed after they ran, when Claude Code cannot read its own memory usage, for example when it has run out of file descriptors
- Fixed
--input-format stream-jsonsessions (Agent SDK, VS Code extension) and scheduled cloud sessions failing every turn with an error when an earlier assistant message had plain-string content - Fixed non-interactive sessions (
-p, Agent SDK) failing on the next turn after the directory they were started in was deleted mid-session - Fixed headless sessions with host-side (SDK) MCP servers stalling on the first message when the host stops responding mid-handshake; remote sessions now wait a few seconds at most
- Fixed interactive startup waiting on the managed-settings network request (about 80 ms, 17+ seconds when the network is unreachable) when no MCP servers or plugins are configured
- Fixed a delay of up to two minutes before responding when reading or @-mentioning a PDF larger than 3 MB
- Fixed an interrupted Read of specific PDF pages leaving its page render running for up to two minutes
- Fixed permission dialogs and attachment checks reading a path under macOS's
/.vol,/.nofollowor/.resolve(which can reach a network mount) before approval - Fixed a recursive
rmwhose target is only command-substitution output, such asrm -rf "$(pwd)", running unprompted in auto and--dangerously-skip-permissionsmode; it now asks even with a Bash allow rule, unless run withCLAUDE_CODE_DISABLE_SUBSTITUTION_RM_PROMPT=1 - Fixed a permission rule containing a NUL byte being expanded into a wildcard match; such a rule now matches nothing
- Fixed sandbox
excludedCommandsentries not matchinggit rev-parse --git-dir, programs named like shell builtins, and commit messages containing[WIP]or#lines - Fixed sandboxed Bash commands being unable to write to
$TMPDIRwhenCLAUDE_CODE_TMPDIRis set - Fixed
claude --bgstarting a background session, and running its project hooks, in a directory that had not passed the workspace trust prompt; it now asks for trust first, or exits when not run interactively - Fixed
--setting-sources(and SDKsettingSources) not being forwarded to spawned sessions: teammates,/bg,claude agentssessions and--worktree --tmuxnow start with the parent's restriction - Fixed Read, Write, Edit and NotebookEdit: a file path containing a null byte now fails that tool call with a clear error instead of ending the whole turn
- Fixed Write refusing a call that gives the file path or content twice under two parameter names with identical values
- Fixed CLAUDE.md and rules files from an
--add-dirdirectory inside the working directory being sent to the model twice in headless and SDK sessions - Fixed remote sessions staying on "needs approval" with a stale prompt after a permission prompt and a sandbox network-access prompt overlapped and both were answered
- Fixed cloud sessions not telling Claude about background agents that finished just before a worker restart
- Fixed scheduled routine and notification turns in remote sessions not receiving turn-start notices (newly available tools, MCP changes, date, todos) until after the first tool call
- Fixed scheduled tasks and
/loopwakeups being fired again every second when their delivery failed, which could make Claude Code exit at the end of a turn - Fixed Remote Control reporting "disabled by your organization's policy" when the org policy simply hadn't loaded yet; it now retries the fetch and says it couldn't verify
- Fixed the Artifact tool missing from Remote Control sessions that
claude remote-controlstarts for you to open from Claude Desktop, claude.ai or the mobile app - Fixed macOS credential writes dropping stored MCP OAuth tokens or deleting the keychain entry when the login keychain was locked (e.g. right after wake)
- Fixed
gcpAuthRefresh/awsAuthRefreshlogin processes being left running (and holding their localhost callback port on Windows) when Claude Code exits or the refresh times out - Fixed the "Not logged in · Run /login" footer and missing claude.ai connectors persisting in a session after logging in from another Claude Code process
- Fixed
mcp_toolhooks on blocking events (PreToolUse and similar) being skipped while their MCP server was still connecting; they now wait for it, up to the MCP connect timeout - Fixed the same MCP server being connected twice when a plugin or claude.ai connector and a configured server spell its URL differently (host letter case, default port, trailing slash)
- Fixed
MCP_CONNECTION_NONBLOCKING=0giving up on claude.ai connectors after 1s instead of honoringMCP_CONNECT_TIMEOUT_MS - Fixed
--channelsplugin entries being checked against the installed plugin's marketplace alone; the installed plugin's name must now match the entry as well - Fixed
--plugin-diron a folder of plugins that also has a.claude-plugin/marketplace.jsonloading one empty plugin instead of the plugins in it - Fixed
claude plugin uninstallrefusing to remove a project-scope plugin that isn't enabled, saying it is "enabled at project scope" whileclaude plugin disablesays it is already disabled - Fixed
claude plugin updatefailing for project-scoped plugins when--scopeis omitted — it now resolves the scope the plugin is installed at instead of assuming user - Fixed
claude plugin validatereportingprivacyPolicyUrl,supportUrland other listing metadata keys in plugin.json as unknown fields - Fixed
known_marketplaces.jsonrecording a marketplace as refreshed when its remote could not be reached andCLAUDE_CODE_PLUGIN_KEEP_MARKETPLACE_ON_FAILUREkept the existing clone - Fixed the
/pluginErrors tab showing no confirmation after its last error is resolved - Fixed
/pluginstarting a second uninstall or update of the same plugin when Enter was pressed again while the first was still running - Fixed a
yheld while/pluginchecks a marketplace source adding the marketplace the instant the "Add marketplace?" question appears, before it can be read - Fixed
1answering Yes in/permissions' delete and remove-directory confirms while the pointer is on No, which let a held1remove one workspace directory after another - Fixed Alt+T and
/configoffering to turn thinking off on models that can't; thinking now stays on there, with a one-line reason in place of the switch - Fixed
/contexttotal leaving out messages added since the last response; it now matches its categories and can read higher than the status line - Fixed
/modelshowing the raw API error JSON and request ID when the API refuses the picked model; it now shows the server's message and says the model was not changed - Fixed API errors from an HTML error page (such as a proxy's 429 or 502 page) printing the page's raw markup or leaving out the HTTP status, and error messages breaking onto a second line when the server's error text ended in a newline
- Fixed /feedback, /bug and /share still sending your report after you cancelled it while it was being sent
- Fixed /feedback, /bug and /share failing every send with "Couldn't send feedback" after a Remote Control Stop arrived while the dialog was open
- Fixed
/ideshowing "No available IDEs detected" while also listing a running IDE - Fixed the terminal being left in a broken state (crash or garbled input) when
/setup-bedrockor/setup-vertexrestarts Claude Code to apply new settings - Fixed
/configexiting whenrespectGitignoreorcopyFullResponsein~/.claude.jsonholdsnull - Fixed the session name from /rename disappearing while Claude asks a multiple-choice question, so side-by-side sessions stay identifiable
- Fixed one-line pastes showing on their own lines in the sent message for prompts from VS Code or Remote Control and for expanded paste placeholders
- Fixed a message queued while Claude is working losing or changing the IDE selection it was written with, and queued messages not showing their selection
- Fixed pressing Shift+Tab twice quickly landing on the wrong permission mode
- Fixed Ctrl+C or Ctrl+D pressed twice quitting Claude Code instead of closing the dialog in the remaining dialogs and pickers, such as
/memory,/hooks,/mcp(including a server's sign-in screen),/export,/copy,/theme, and/teleport's uncommitted-changes and login prompts (where Esc also quit) - Fixed keys that arrive in one burst of input (e.g. over Remote Control), such as an arrow key followed by Enter,
xors, acting on the previous selection: a stale effort level in/effortand the model picker, and the previously highlighted row in/skills, the background task rows under the prompt, MCP server prompts and/install-github-app - Fixed
/install-github-appupdating the workflow after "Skip workflow update" was chosen, running setup twice on a repeated Enter, and ↑ on the repository step blocking a typed repository name when no repository was detected - Fixed vim mode:
dj/dk/dG/dggand theirc/yforms acting on part of a line;1Ggoing to the last line;d0/c0/y0doing nothing; the cursor being off by one after.repeats an insert; ando/pon a!-prefixed line switching to shell mode - Fixed vim mode
cwon a space, an empty line, a word's last letter or a one-letter word also changing the next word; word motions stopping inside words in Hindi, Bengali and other scripts; and.,porPthat inserts text starting with!switching to shell mode, losing text or editing the wrong character - Fixed the prompt cursor moving one character too far after an accent typed as its own key
- Fixed an extra blank line above a list item whose text starts on the line after its bullet, in screen-reader mode, quoted lists and long lists
- Fixed bulleted lists of plain numbers (like
- 316.) showing as letters, roman numerals or the wrong numbers - Fixed the agent panel's footer hint ignoring keys rebound in
keybindings.json, and showing a stray·when the stop-all-agents shortcut is unbound - Fixed the agent panel footer offering "Enter to view" and "x to stop" on the agent you are already viewing (where x types into its input), and "Enter to view" on the main row when main is already shown
- Fixed a mouse click on an agent-panel row leaving the keyboard cursor on the previously selected row
- Fixed Esc interrupting the running turn instead of deselecting the selected agent-panel row
- Fixed PgUp and PgDn doing nothing in a dialog's list (for example
/skills) in fullscreen mode - Fixed
/heapdumpsummary saying most memory is native when it is in the JS heap snapshot - Fixed Bash edit-diff snapshot directories piling up in the temp folder: abandoned ones are now deleted right away and the rest when Claude Code exits
- Fixed /workflows moving the pointer to a different run, and
xstopping it, when a new run started while the list was open - Fixed the selected tab in tabbed dialogs (
/config,/plugin,/permissions) showing no highlight while the tab bar has focus when color is off (NO_COLOR) - Fixed the mouse wheel over the
/pluginInstalled list scrolling the pane behind it instead of the list - Fixed the hover highlight lingering on a list row in fullscreen mode after scrolling or filtering moved it away from the mouse
- Fixed long list rows, such as in the /remote-control menu, wrapping onto a second line in narrow terminals; they're now cut with …
- Fixed
/hooksand/mcpdetail views printing a long value over the row below it in narrow terminals - Fixed lists such as a skill's state options in
/pluginnot being answerable by typing a number in screen-reader mode - Windows: Fixed Bash commands that write to
$TMPDIR/…failing with "Permission denied" - Windows: Fixed a race in which Claude Code sessions updating at the same moment could delete each other's
claude.exebackup, which could leave noclaude.exebehind - Improved Claude Desktop sign-in and usage-limit error messages to point at the app instead of terminal commands
- Improved startup: managed settings and policy fetches no longer retry requests that can never succeed
- Improved interactive startup time: git reads, startup telemetry and the Bedrock/Vertex model-upgrade checks no longer run before the first frame
- Improved the time to resume long sessions that read many files; the restored file cache now matches the files as they were read
- Improved the time to resume very long sessions that have been compacted, most noticeably through the Agent SDK and Claude Desktop
- Improved "Prompt is too long" recovery in sessions dominated by one very large first prompt: that prompt is now summarized on its own instead of being left out of the summary
- Improved auto mode after resuming a session in a new process: the permission classifier can now reuse its earlier prompt cache instead of rewriting it
- Improved the auto mode denial message so Claude treats a denial as covering the outcome, not only the exact command
- Improved the dangerous-rm check to also flag a removal at a shell variable followed by a top-level directory name, at a variable derived from the working directory, or at a backslash-only target
- Improved sandbox guidance on macOS: when a local dev server can't bind a port, Claude now points to
sandbox.network.allowLocalBinding - Improved
--agentsto accept the path to a JSON file (with-p) as well as inline JSON, and to allow an emptyprompt - Improved
/batchto run where a WorktreeCreate hook provides the agent worktrees, not only inside a git repository - Improved plugin hook-failure errors to name the offending plugin, and added a
claude plugin validatewarning when a shell-form hook leaves${CLAUDE_PLUGIN_ROOT}unquoted (it breaks on plugin paths with spaces) - Improved the
/menu,/skills,/contextand the/pluginInstalled list to show skills synced from claude.ai by their short name when no other command uses it, notanthropic-skills:<name> - Improved
/deep-researchreliability on long research briefs by removing unused required fields from the scope step's output - Improved the writing in published artifact pages: the bundled artifact-design skill now asks Claude for plain, direct prose
- Improved artifact publishing on slow connections: large page uploads are now sent compressed
- Improved the large CLAUDE.md startup notice to also count instruction files together, so many mid-sized files and @-imports are caught
- Improved debug logs to name settings
envvariables ignored because the session's launch environment already sets them - Improved keyboard navigation in tabbed dialogs such as
/permissionsand/usage: ↑/↓ move focus between the tab row and the content, and a list responds to keys only while it has focus - Improved
/helpand/sandbox: ←/→ and Tab switch tabs from inside a tab's list, and ↓ on an empty Custom commands tab in/helpno longer leaves the keys stuck until Esc - Improved
/install-github-app,/desktop, the/permissionsauto mode environment prompts, and the/plugin"Add marketplace?" and "Run this command?" prompts: they now use the standard dialog frame with key hints, and Ctrl+C or Ctrl+D cancels them on the second press like other dialogs - Improved the
/workflowsand/mcplists: they page (PgUp/PgDn, Home/End) and take j/k and the mouse like other lists, their arrows followselect:previous/select:nextrebinds, andxin/workflowsstops the run the pointer is on - Improved the
/pluginplugin and marketplace details menus and the/remote-controlalready-connected menu: they now support Home/End and clicking a row - Improved the background workflow row below the prompt: it now shows the name, a progress bar, the agent count on wide terminals, elapsed time, total tokens, and the large-workflow warning
- Improved the /plugin Installed list: rows now line up in columns (status, name, type, details) across every section
- Improved
/skills: each row now leads with the skill's name, with ✔ or ◯ alone showing on or off, and stays on one line in narrow terminals - Improved narrow list rows (
/skills,/workflows,/feedback): a name keeps 20 columns beside its first detail, and details are shown whole or not at all - Improved
/diff: a scrollbar shows where you are in a long list of changed files, and long paths no longer wrap their rows - Improved
/hooks: a hook's detail screen now says what kind of hook it is and where to change it, instead of always pointing at settings.json, and the hooks-disabled, safe mode and managed-hooks-only notices each say what is happening in one plain sentence - Improved screen-reader output in
/mcp: a disabled server is read as "off" instead of "pending" - Improved the Remote Control confirmation: its options are briefly inactive again after the terminal window regains focus, so a key pressed while switching back cannot answer it
- Changed send now (ctrl+enter or ctrl+x ctrl+s) to move running tools to the background instead of cancelling the turn
- Changed auto mode so that, where its classifier review runs server-side, read-only and sandboxed shell commands also wait for that review and are blocked when it flags them
- Changed
CLAUDE_CODE_AUTO_MODE_SERVERto also apply on a direct Anthropic API connection:0opts out of the server-side auto mode classifier (the local classifier then counts toward usage),1opts in - Changed the dangerous
rmprompt in--dangerously-skip-permissionsand auto mode to wait 2 minutes for an answer, then deny the command with a rewrite hint so unattended sessions keep going (CLAUDE_CODE_DISABLE_DANGEROUS_RM_TIMEOUT=1turns this off) - Changed Claude apps gateway to refuse to start when a
managedMcpServersentry'senvHelperpath starts with\??\or/??/, a path form current Claude Desktop refuses to run - Changed self-hosted runners to pass system prompts to Claude Code as private files instead of command-line text, so large prompts no longer fail the launch; a wrapper or
commandhook that appends--system-promptor--append-system-promptmust switch to--system-prompt-fileor--append-system-prompt-file - Changed queued messages to show in the conversation above the spinner instead of under it
- Changed the session artifact links under the prompt into one footer pill (
⧉ nameor⧉ N) that opens/artifacts, which now lists this session's artifacts first - Changed the Artifact tool to let Claude load scripts from unpkg.com in artifact pages
- Changed hovering a list row in fullscreen mode, including in
/config, to tint the row instead of drawing a second ❯ pointer beside the focused row's - Changed /mcp: each server's row now starts with its status icon and name, says its state once, and in a narrow terminal drops trailing facts like "managed" before shortening the name
- Changed /workflows: each run's row leads with its status icon and elapsed time, and a narrow terminal keeps the run's name and time, dropping the agent and token counts first
- Changed Remote Control attachment downloads to reuse connections and to skip files already downloaded in the session
- Changed MCP resource lists (the resource list tool and @-mention suggestions) to skip MCP Apps UI resources; reading one by URI still works
- Changed
claude plugin uninstall --jsonand the /plugin dialog to say a plugin's data was kept when its folder stays because another installed plugin uses it or install records cannot be read - Changed the background tasks list (
/tasks): pressingxon a running/ultrareviewnow asks for confirmation before stopping the review - Removed the leftover "(removed)"
/agentsentry from the command menu and/help; typing/agentsstill explains where the wizard went - [VSCode] Added a Continue/Stop prompt in the VS Code and JetBrains panels when auto mode falls back to billed classifier requests, replacing the unanswerable warning line
- [VSCode] Fixed opening a Web session with no messages saving an empty local copy that could not be resumed; an error now says where to continue it
- [VSCode] Fixed a claude.ai/code session opening empty or with only part of its conversation, with no error, when the server failed to return its history, part of it failed to load, or a network sign-in page answered in its place; it now shows an error and can be opened again
- [VSCode] Fixed conversations in editor tabs hanging silently after the extension host restarts; the tab now tells you to reopen it from the session list
- [VSCode] Fixed Claude attaching option previews to multiple-choice questions in the chat panel, where the question card never shows them
- [VSCode] Fixed the session manager's cost and usage block wrapping mid-text on a narrow side bar, and showing totals from a previous login after an account switch
- [Claude Code on the web] Added a Fast mode switch to the composer's model menu in cloud sessions, shown when your plan includes fast mode and the selected model supports it
- [Claude Code on the web] Added a settings shortcut on the GitHub setup tip and a "Troubleshoot GitHub connection" link in the repository pickers, both opening your GitHub connection page
- [Claude Code on the web] Fixed routines with a GitHub trigger for a pull request being converted to draft never firing; they now start a run when the pull request is converted
- [Claude Code on the web] Fixed cloud sessions on a repository that isn't hosted on GitHub showing a Create PR button that could never work; the button is now hidden there
- [Claude Code on the web] Fixed the GitHub setup tip on claude.ai/code covering the repository picker's search box and rows while the picker is open; it now steps aside until the picker closes
- [Claude Code on the web] Improved the file card shown when a cloud session can't open a file: it now says whether the file no longer exists or the session's permission settings block reading it
- [Claude Tag] Added a short line in the Slack thread after someone presses Stop, naming who stopped Claude's response and saying to mention @claude to continue
- [Claude Tag] Fixed Slack channels where Claude could permanently stop responding to replies inside threads; affected channels now recover on their own with the next new message to Claude
- [Claude Tag] Fixed Claude resuming a stopped request after you press Stop in Slack, for example when a check-in fired or a background task ended; messages sent mid-response are now read
- [Claude Tag] Fixed Slack replies arriving many minutes late, or never, after Claude's session crashed mid-task, such as on a failed setup script; it now restarts on its own within minutes
- [Claude Tag] Fixed Claude in Slack promising an automatic restart, then failing generically, when a session's configuration is too large to start; the thread now says why and how to retry
- [Claude Tag] Fixed very long Slack threads: Claude could silently withhold a reply after judging it against weeks-old messages, and a restart deep into the thread could lose recent context
- [Claude Tag] Fixed Claude answering every mention with "Couldn't check this channel just now" in a Slack channel moved from Enterprise Grid org-wide sharing into a single workspace
- [Claude Tag] Fixed very large Enterprise Grid workspaces reached mostly through channels shared across workspaces getting "Couldn't check this channel" again after a quiet hour
- [Claude Tag] Fixed a Slack request blocked by your organization's inference hook showing a generic retry notice; the thread now shows the hook's deny message and Claude doesn't retry
- [Claude Tag] Fixed Claude in Slack offering to switch to models your organization can't use; it now lists and offers only models the switch will actually accept
- [Claude Tag] Fixed requests to DynamoDB and Kinesis account-based endpoints failing to authenticate when sent through an AWS connection in Claude Tag
- [Claude Tag] Fixed the Plugins sections in Claude Tag admin settings failing to load for organization admins and listing attached plugins as raw IDs; they now load and show each plugin's name
- [Claude Tag] Changed the routine list Claude gives when asked in a Slack thread to show that thread's own scheduled tasks by default instead of every routine in the channel
- [Code Review] Fixed a pull request getting no review when its reviewed commit was force-pushed away while a failed review was being retried in a repository not set to review every push
- Added Claude apps gateway support for newer Claude Desktop keys in
-
🔗 r/LocalLLaMA Jev isn't new tech. Its marketing targets people who think AI started with LLMs. rss
I keep seeing Jev presented as some new class of decision model, but most of what’s being advertised is just normal classifier behavior with modern zero- shot capabilities.
It outputs probabilities over constrained choices, doesn’t generate autoregressively, can’t output an invalid class, and can use labels defined at inference time. None of that is new. Zero-shot/NLI classifiers, embedding models, cross-encoders and rerankers have been doing variations of this for years.
The weird part is that most of the impressive Jev comparisons are against LLMs. Of course a specialized classifier is faster and cheaper than making an autoregressive LLM generate an answer. That doesn’t establish a new paradigm. The meaningful comparison is against strong existing classifiers. The purpose of this is to mislead.
There are already benchmarks like BTZSC evaluating dozens of zero-shot classifiers across 22 datasets, including NLI models, embedding models and rerankers. I haven’t seen Jev properly benchmarked across that landscape yet.
(https://proceedings.iclr.cc/paper_files/paper/2026/hash/417e1c15b3d49852fceded8aa104107d-Abstract- Conference.html)Where people have compared Jev with conventional classifiers, the story is much less magical. One Banking77 experiment got 93.3% from BGE-small + logistic regression versus 83.2% for Jev, at about 9ms locally.
(https://github.com/ickma2311/jev-baselines- eval)Some of the marketing also goes into the misleading territory. The “can’t hallucinate” framing is very sus, for example. Their own explanation admits the 0% hallucination figure is not empirical, and what they actually guarantee is that Jev returns an answer matching the allowed schema. That prevents invalid outputs, it does not prevent confidently choosing the wrong valid answer. (https://typesafe.ai/blog/introducing-system-one-models-and- jev)
So color me a skeptic. Look, Jev might even be a good product. Maybe their unpublished architecture or RLCD training method is genuinely novel. But nothing we've seen so far establishes that "System One Models" are a new class of AI. What the public evidence mostly establishes is that using a specialized classifier for classification can be much cheaper and faster than using an autoregressive LLM, which we already knew. It only sounds novel if your idea of AI begins and ends with LLMs.
submitted by /u/tiensss
[link] [comments] -
🔗 exe.dev Share Shelley Skills Across Your VMs rss
At exe.dev, we use integrations to connect your VMs to other services securely and simply. Usually this takes the form of a proxy that injects secrets.
We love hearing from our customers (hint, hint, email us, don’t be shy), and one of them was doing significant gymnastics to share skills across their VMs. Nothing wrong with that (rsync is right there, after all), but we realized we could use the same integrations machinery we already have to share skills files as well. You register a skill once, and attach it to any VMs that you want to see it. Shelly uses the “reflection” integration to see if there are any skills integrations, and, if so, surfaces them.
-
🔗 HexRaysSA/plugin-repository commits sync repo: +6 releases, -1 release, ~4 changed rss
sync repo: +6 releases, -1 release, ~4 changed ## New releases - [ida-mcp](https://github.com/hexrayssa/ida-mcp): 20260923.0.4, 20260923.0.3, 20260923.0.2, 20260923.0.1 - [ida-nexus](https://github.com/hexrayssa/ida-nexus): 0.13.0 - [ida-settings-editor](https://github.com/williballenthin/ida-settings): 1.3.0 ## Changes - [ida-codemode](https://github.com/hexrayssa/ida-codemode): - removed version(s): 0.5.3 - [mcrit-ida](https://github.com/danielplohmann/mcrit-plugin): - 1.1.9: download URL changed - 1.1.8: download URL changed - 1.1.7: download URL changed - 1.1.10: download URL changed -
🔗 r/LocalLLaMA Mods: can we do something about half the forum getting filled with these advertising posts for Jev? rss
Jev is a paid product that dumped a lot of venture capitol money into shill their product here and in other subreddits. Obvious shill posts are obvious.
submitted by /u/Acrobatic_Stress1388
[link] [comments] -
🔗 r/LocalLLaMA Cost of intelligence is dropping fast rss
| https://preview.redd.it/43n0bhiap8rh1.png?width=960&format=png&auto=webp&s=776785f6eb39e3eba519b85f8be8eb7453318a4f 50% per quarter is amazing. 4× faster than DNA sequencing, 6× faster than compute, 18× faster than lithium batteries, and (up to 1973) 54× faster than electricity. https://x.com/EpochAIResearch/status/2102510281176023529 Every year moving forward is going to be significantly different that the prior year. What do you think? We will be running coding agents on our phones pretty soon. submitted by /u/Terminator857
[link] [comments]
---|--- -
🔗 r/LocalLLaMA this is not even a competition at this point ... this is embarrassing rss
| submitted by /u/johnnyApplePRNG
[link] [comments]
---|--- -
🔗 r/LocalLLaMA Pirate Face - pirate bay for LLMs rss
| The title says for itself In case someone desides to censor huggingface, we'll have an alternative Edit: A lot of responses so I'll leave it here: - I'm not the author.
- If I were the author I wouldn't use the word "piracy".
- If you're the author, please, rename the domain! What is free in the first place must be named as such, we're not pirating anything.
submitted by /u/Atagor
[link] [comments]
---|--- -
🔗 Probably Dance The Mundanity of Excellence, Small Wins, and Why You Should Fix Bugs Before Writing New Features rss
I'm not good at prioritizing tasks, but there is one rule I follow and that I can justify very well: If something worked yesterday and is broken today, I will drop whatever I'm doing and fix that thing. No matter how small and seemingly unimportant the broken feature is.
To justify this I will quote from the paper "The Mundanity of Excellence" by Daniel F. Chambliss:
Superlative performance is really a confluence of dozens of small skills or activities, each one learned or stumbled upon, which have been carefully drilled into habit and then are fitted together in a synthesized whole. There is nothing extraordinary or super-human in any one of those actions; only the fact that they are done consistently and correctly, and all together, produce excellence. When a swimmer learns a proper flip turn in the freestyle races, she will swim the race a bit faster; then a streamlined push off from the wall, with the arms squeezed together over the head, and a little faster; then how to place the hands in the water so no air is cupped in them; then how to lift them over the water; then how to lift weights to properly build strength, and how to eat the right foods, and to wear the best suits for racing, and on and on. Each of those tasks seems small in itself, but each allows the athlete to swim a bit faster. And having learned and consistently practiced all of them together, and many more besides, the swimmer may compete in the Olympic Games. The winning of a gold medal is nothing more than the synthesis of a countless number of such little things
I claim that the same thing is true for software, and what's important is to lock in those small wins.
I learned this lesson when working in video games. The company I worked for had trouble shipping high quality games. We didn't ship bad games, but we just couldn't compete with the likes of Blizzard or Nintendo. Since then I have worked at different places to learn how to ship high quality software, and mostly learned that there is no magic. You just have simple improvements like
- better processes that aren't too surprising to anyone (e.g. more tests, more code review, ensuring that there are never any broken builds etc.)
- shorter feedback loops so that you learn quickly when there are issues
- better coding practices and higher standards for what code is acceptable to push (e.g. if it's not easy to see that code is correct, don't push it)
- priority for bug fixes instead of fixing things when you next feel like you have some free time
These are equivalent to the examples in the "mundanity of excellence" quote in that they lead to better programmers. But I want to focus on the last one because if the processes lead to excellent programmers, the bugfixes are required for excellent programs.
When software reaches a certain level of complexity you can no longer get improvements with big wins. It's similar to the olympic swimmer example from the quote above: you need lots of little improvements. Things like tooltips, shortcuts, customization, responsive performance or correct handling of edge cases and niche use cases. These are the things that elevate your software from "works and mostly does the job" to "people like it and like working in it". But these are also the things that tend to break and stay broken. If you don't keep these things working, your software will always erode back down to a 7/10 quality level.
If you work at a good organization, all of this may sound trivial to you. But I can assure you that most places do not work like this and it's surprising to lots of programmers that bug fixes, even for features that are of low importance, should take priority over work on new, highly important features. As a very visual demonstration of this, here is a comparison of all the details that worked in Far Cry 2 and were broken in Far Cry 5:
Far Cry 2 came out in 2008 and ran on a Playstation 3, Far Cry 5 came out ten years later on the Playstation 4, a much more powerful machine that was much easier to program. There is no good reason why so many things should be worse in Far Cry 5. The only reason is that these are details, and details tend to break and this is what it looks like when that has gone on for ten years. Far Cry 2 was a great game (yes, there is one big complaint that everyone has, but ignoring that it was a great game) and Far Cry 5 is just meh. Many developers over the years thought that details like this weren't that important to keep working, and as a result you get a much worse game.
And it's not just game development. Condition variables had been broken in glibc since 2016 and I have been trying to get them fixed by submitting patches since 2020 and haven't had much luck until I finally got through in 2025. They mostly worked and only broke occasionally, so people just didn't prioritize it.
But if you actually want to ship good software, you have to do like the "mundanity of excellence" quote says and lock in those improvements. Good software is a collection of small wins, and unfortunately small wins are the first thing to erode away if you don't lock them in.
Automated tests obviously help for this and are a necessity past a certain level of complexity. But they can't catch everything and when something slips through, you just have to fix it first.
Excuses
Whenever you push for better practices, you get the same excuses. There is no time, we don't have the manpower, we're already behind and this feature was supposed to be released two weeks ago. These are all very real reasons why people are not doing things, and if you dismiss these complaints they get very mad at you because they really have these issues. It's just that from the outside, it's clear to see that they're stuck in a capability trap. The reason why you have no time is that you have bad practices. If you think you need more manpower to have more tests, you're doing it wrong. The tests would allow you to ship the same software with fewer people, not with more people. Unfortunately this is not true in the short term, (when adopting new practices, things get worse before they get better) so switching is hard.
The article to read on this topic is "Nobody Ever Gets Credit for Fixing Problems that Never Happened: Creating and Sustaining Process Improvement".
Quotes
To back up that you should fix things early and lock in a high quality early, I'll quote from highly successful game developers. Here is Blizzard:
There's this idea out there, that the reason why Blizzard polish is better is because we get six months at the end. And obviously we're very fortunate to get more time, but the polish doesn't happen at the end. The polish happens all along the way, from the very beginning. […] If you just leave it to the end, you're not going to get there.
From the GDC talk “Making a Standard (and Trying to Stick to it!): Blizzard Design Philosophies” by Rob Pardo:
Here are several quotes about id software:
“Polish as you go. Don't depend on polish happening later. Always maintain constantly shippable code.”
“It's incredibly important that your game can always be run by your team. Bulletproof your engine by providing defaults upon load failure.”
“We are our own best testing team and should never allow anyone else to experience bugs or see the game crash. Don't waste others' time. Test thoroughly before checking in your code. No throwing it over the fence for testers to find and put a bug in the database and then fix it later. It's a wasteful cycle.”
“As soon as you see a bug, you fix it. Do not continue on. If you don't fix your bugs your new code will be built on a buggy codebase and ensure an unstable foundation.”
From the GDC Europe talk “The Early Days of id Software”
https://www.youtube.com/watch?v=E2MIpi8pIvYSummary
So why should bugfixes take priority? Let me slightly modify the quote from the beginning:
Superlative software is really a confluence of hundreds of small polishes or features, each one designed or stumbled upon, which have been carefully locked in by tests and then are fitted together in a synthesized whole. There is nothing extraordinary or super-human in any one of those features; only the fact that they are done consistently and correctly, and all together, produce excellence.
-
🔗 Drew DeVault's blog Why is Hacker News like that? rss
Hacker News (aka HN) is a link aggregator where “hackers”1 gather to discuss technology, politics, and anything which “good hackers would find interesting”. HN is a means by which its host, prominent startup incubator Y Combinator, projects soft power, promotes startups it funds, and feeds people with ideas into its incubation program. Hacker News is one of the most popular forums for discussing technology online today – perhaps the biggest.
HN also has a pronounced political bias, which is growing more exaggerated with time. Many of its users have long claimed centrist or “apolitical” views. On a forum created by a startup incubator, it’s no surprise that capitalism is generally taken as given, often with a libertarian angle. Labor is generally de-emphasized (the consensus on HN is almost always anti-union) and openly advocating left economics like communism or socialism is generally frowned upon. Progressives have, on the whole, abandoned the forum.
The right wing has not. Yesterday, I saw a post about the new release of the Grok LLM, Elon Musk’s “anti-woke” AI project. Virtually all of the comments are fawning over the release, and debating the finer points of its technical achievements, price, and competitiveness. There are remarks that object to the tool on the basis that its owner, Elon Musk, is a fascist, and that it is designed to amplify hate speech. Almost all of these remarks are “flagged”, moderated by other HN users until they are not visible by default.2
Some examples of comments flagged out of existence:
Until Musk owns up to his Nazi salute, I won’t be using Grok, sorry. I don’t care how good or cheap it is. And no, I won’t stop talking about it either.
Your friendly reminder that Grok is owned and directly steered by the white supremacist guy with the fascist haircut who does nazi salutes and fucked up decades of international order to settle scores for his apartheid south african family. Any amount of using the model supports this.
I’m dying to know how everyone who works on this product sleeps at night. How does one reconcile a sense of ethics with helping Musk make more money on AI-generated CSAM and racism
And, my personal favorite:
I have to say I’m a little perplexed by HN’s perpetual willingness to use grok like it’s a normal product made by a normal company.
There’s often frustration that every thread related to a Musk company includes a discussion about Musk, but Musk himself caused that by being the only tech founder to actively campaign for Trump. (Zuck, the runner up, didn’t do anything even close to this). Every product at every company he owns is hopelessly tethered to his decision to do that, and deserves to be judged on those terms.
Another popular story today is about US rollback of climate regulation under Trump. Some fraction of every cent you spend on Grok goes to support stuff you hate, and yet people get genuinely annoyed when you point it out. Musk and his companies really are special and should be treated as special.
Every thread about a Musk company or product needs a comment like this one. If we had the right values, every comment would look like this one.
All of these are gone.
Overt hate and bigotry on Hacker News is uncommon, but not rare, and often gets pushback. Covert hate (e.g. dog whistles) is more common, and when called out the call-out usually gets flamed rather than the hate. Unexamined bias against progressivism and the rights and interests of anyone who isn’t the “default” middle-class white cis male, is incredibly common, and anyone who questions these biases is generally subjected to flames and moderation action.
Why is Hacker News like this?
Moderation on HN
Hacker News has two formal moderators, both employed by Y Combinator: Daniel Gackle, aka dang, and Tom Howard, aka tomhow. Scott Bell (sctb) assisted with moderation until 2019. They employ a variety of technical tools to do the job, including:
- Boosting or sinking the rank of posts, or “burying” them entirely
- Deleting posts (entirely) or “killing” posts (marking them as [dead])
- Detaching and/or downranking comment trees
- “Shadowbanning” users
- Overtly banning users
Moderators occasionally post comments and intervene in discussions, steering things one way or another or explaining their moderation decisions.
There are also automated moderation systems, which for example try to detect flamewars with heuristics like the ratioes between post score, age, and the number of comments, and apply a downward pressure to the post’s ranking to reduce the visibility of controversial topics. Of course, the topics which are deemed controversial by the automated systems are, more often than not, progressive politics.
Users above a certain (small) amount of “karma” gain the ability to “flag” posts, allowing Hacker News to self-moderate. Posts or comments can be hidden entirely (made “dead”) with a small number of flags, particularly early on, before they gain enough votes to influence the flagging algorithm. This is the mechanism which was used to silence criticism of Grok and Elon Musk in the thread discussed earlier. By and large the flagging mechanism is used to silence progressive opinions and articles from being posted on Hacker News. Once a post or comment is flagged, it can be “vouched” for, but this generally does not work in practice due to a relatively straightforward bias: flagged posts are only visible to users who opt-in, are moved to the bottom of threads and hidden from view, and one can flag at any time but cannot vouch for a post proactively. Once a comment or post is gone, it generally stays gone.
The moderators tend to view the automated moderation and the flagging mechanism as neutral, and use it to deflect responsibility for moderation decisions onto the tools or the users who use them, i.e. the “community” in the abstract.3 However, ultimately the moderators are in control of these tools and are aware of their biases and the outcomes they produce.
So… why is Hacker News like this?
Y Combinator
Hacker News is like this because the people responsible for it are like this, in particular the people at and in the orbit of Y Combinator.
Hacker News goes to some lengths to portray itself as independent of the company that owns it, Y Combinator. Nonetheless, Y Combinator decides who gets to be in charge of Hacker News, and the raison d’être of Hacker News is, at least originally, a forum for YC-backed startup founders to socialize and discuss the news of the day. To this day, YC-funded startups have access to special privileges on HN, in particular the ability to post directly to the front page with a special ranking algorithm (to advertise job openings and announce startup launches). There is also a feature that allows YC founders to spot each other more easily, with their usernames showing up in orange to each other.
Y Combinator’s portfolio
The YC startup directory lists (almost) all of the companies which have received funding from Y Combinator, a list which shows a history of funding companies without a competent ethical evaluation. Coinbase, for example, is one of YC’s “unicorns”, and has donated tens of millions of US dollars to various pro-cryptocurrency political organizations, which tend to skew right wing by a ratio of 2:1, and Coinbase now funds fascist David Hansson’s Omarchy project. We’ll talk more about Coinbase momentarily. David is also funded by Stripe, another particularly successful YC alumni.
YC also funds companies that specialize in military and police applications, such as Code Four, Lakonia, Closure, Abel Police, Ravn, and more. They were early investors in Flock Safety, a company now notorious for putting up surveillance equipment across America – much of which is now being torn down by infuriated citizens. Another great example is Optifye.ai, surveillance software for monitoring workers in sweatshops in India, and a member of YC’s winter 2025 batch.
Many companies – AirBnB is another example – funded by Y Combinator share the same “move fast and break laws” mindset that is particularly popular among their alumnus. There are many dozens of examples of such companies among Y Combinator’s portfolio, but I won’t belabor the point.
Regarding Paul Graham
Y Combinator was founded by Paul Graham in March 2005, along with three collaborators, though Paul (aka pg) was and remains the face of the operation. Paul wrote and launched Hacker News himself using his own dialect of Lisp, and to this day he tends to be revered by the HN community and certainly by the community of Y Combinator founders, partners, and investors. To what extent modern-day HN culture flows from his original spring can be debated, but we can at least understand the nature of that spring.
Let’s consult his blog for some insights. I suggest you click through to my examples and read/skim them yourself for more juicy quotes.
In April 2022, Paul posted “On Heresey”, a post of interest to our question. He explains his feelings on calling someone “x-ist” (i.e. sexist, racist, etc), like so:
For example, when someone calls a statement “x-ist,” they’re also implicitly saying that this is the end of the discussion. They do not, having said this, go on to consider whether the statement is true or not. Using such labels is the conversational equivalent of signalling an exception. That’s one of the reasons they’re used: to end a discussion.
On intolerance:
There are aggressively conventional-minded people on both the right and the left. The reason the current wave of intolerance comes from the left is simply because the new unifying ideology happened to come from the left. The next one might come from the right. Imagine what that would be like.
Note that this essay was published a mere three months after the January 6th US capital insurrection, where a right-wing mob stormed the US capitol building, erecting a gallows on the lawn and calling for Mike Pence’s head.
A more recent essay, January 2025, “The Origins of Wokeness”, also provides ample insight into Paul’s character. Paul on racism:
Racism, for example, is a genuine problem. Not a problem on the scale that the woke believe it to be, but a genuine one. I don’t think any reasonable person would deny that. The problem with political correctness was not that it focused on marginalized groups, but the shallow, aggressive way in which it did so. Instead of going out into the world and quietly helping members of marginalized groups, the politically correct focused on getting people in trouble for using the wrong words to talk about them.
Paul on sexism:
I saw political correctness arise. When I started college in 1982 it was not yet a thing. Female students might object if someone said something they considered sexist, but no one was getting reported for it. It was still not a thing when I started grad school in 1986. It was definitely a thing in 1988 though, and by the early 1990s it seemed to pervade campus life.
What happened? How did protest become punishment? Why were the late 1980s the point at which protests against male chauvinism (as it used to be called) morphed into formal complaints to university authorities about sexism? Basically, the 1960s radicals got tenure. They became the Establishment they’d protested against two decades before. Now they were in a position not just to speak out about their ideas, but to enforce them.
And on sexual harassment:
One thing I noticed at the time about the first phase of political correctness was that it was more popular with women than men. As many writers (perhaps most eloquently George Orwell) have observed, women seem more attracted than men to the idea of being moral enforcers. But there was another more specific reason women tended to be the enforcers of political correctness. There was at this time a great backlash against sexual harassment; the mid 1980s were the point when the definition of sexual harassment was expanded from explicit sexual advances to creating a “hostile environment.” Within universities the classic form of accusation was for a (female) student to say that a professor made her “feel uncomfortable.” But the vagueness of this accusation allowed the radius of forbidden behavior to expand to include talking about heterodox ideas. Those make people uncomfortable too.
Was it sexist to propose that Darwin’s greater male variability hypothesis might explain some variation in human performance? Sexist enough to get Larry Summers pushed out as president of Harvard, apparently.
In addition to, in his position as the president of Harvard University, making bio-essentialist remarks about the inherently lesser intelligence of women to explain the demographics of his student body, Larry Summers was a personal friend and correspondent of Jeffrey Epstein, though this connection was not generally known at the time Paul wrote this essay.
Regarding Sam Altman
Then there’s Sam Altman, who looms large in the history of Y Combinator. Sam was a member of YC’s first cohort of startups, and later became a partner at YC in 2011. Ultimately, Sam replaced Graham as its president in 2011, serving in this role until (roughly) 2019, leaving more or less in disgrace to focus on OpenAI.4 Until then he was held in high regard by Graham and others at Y Combinator, with Graham famously saying of him, “you could parachute him into an island of cannibals and come back in five years and he’d be king” and frequently lauding him in his essays, naming him one of the five “most interesting startup founders of the last 30 years”, adding that Sam “can’t be stopped by (…) flimsy rules”.
After his departure, Sam was ultimately subject to a slew of controversy at OpenAI, whose board of directors tried and failed to oust him, and were quoted as saying of the matter that Sam “was not consistently candid in his communications” and they “no longer had confidence in his ability to continue leading OpenAI”.
Sam’s mentor, main financial backer, and close friend is Peter Thiel, who Sam invited to join YC as a visiting partner between 2015 and 2017. Sam apparently met his now-husband in Peter Thiel’s hot tub. Thiel is a key figure in Palantir, a data analysis company which works closely with militaries, police departments, and US Immigration and Customs Enforcement, which is currently conducting an ethnic cleansing of the United States, and retains the Israeli Defense Force as a client, which is currently conducting a genocide in Palestine. Thiel is a major donor to right-wing parties and an intellectual devotee of and financial backer of fascist political thinker Curtis Yarvin.
Sam, once his own presidential bid died in the crib, donated $1M to Donald Trump’s inauguration and became an influential public backer of his pro-AI presidency. Of Trump, Sam once said “watching (Donald Trump) more carefully recently has really changed my perspective on him …. I’m not going to agree with him on everything, but i think he will be incredible for the country in many ways!” Sam’s politics also flow from the tradition of Curtis Yarvin, and he invests in and promotes efforts to bring Yarvin’s ultra-libertarian techno-monarchy post-state society into being.
The cherry on top of Sam’s story are the allegations of years of sexual abuse and rape his sister has made regarding him, which he and his family denies. The matter is currently being litigated in Missouri’s courts.
Regarding Garry Tan
Finally, let’s address the current president and CEO of Y Combinator, one Garry Tan, who followed the relatively unremarkable former president of YC, Geoff Ralston, in 2023, after being a partner at Y Combinator, and their “designer-in-residence”, since 2011.
A few weeks before earning this position at Y Combinator, Garry gave a glowing review of Balaji Srinivasan’s “The Network State”, saying “I legit believe (Y Combinator) is a prototype model for what (Srinivasan) talks about when he says the Network State”. Balaji is an interesting figure – the book in question is a distillation of a talk he gave to an audience at Y Combinator in 2013 which pitches the fascist politics of Curtis Yarvin and his intellectual circle to startup founders. When people started making the connections and Srinivasan started to feel the heat, he emailed Curtis Yarvin about it: “If things get hot, it may be interesting to sic the Dark Enlightenment audience on a single vulnerable hostile reporter to dox them and turn them inside out with hostile reporting sent to their advertisers/friends/contacts.”
Srinivasan was a prominent founder of many cryptocurrency startups, and notably became the first CTO of Y Combinator-backed Coinbase, which was also funded by Garry Tan’s Initialized Capital fund – alongside Flock Safety. Garry Tan, Sam Altman, and many other people in Y Combinator’s orbit are big fans of The Network State and funnel influence and money into projects based on its ideas.
Garry is also an important figure at Palantir. He once turned Peter Thiel down when offered a $70,000 check to join the company, but later he became employee #10 anyway. Not much is known about his tenure there, but he did apparently design their logo.
When Garry Tan joined Y Combinator, Sam Altman noted his politics as important for his role there. Altman: “it’s a big deal [in my opinion] that YC will have a CEO so active in local politics. I think YC can make a big difference here”. Garry is indeed a big figure in local politics in San Francisco. He’s spent as much as $400,000 on political initiatives in the bay, with causes ranging from increased police funding and opposition to education reform, regulation of self-driving cars, and decelerationism. In 2024 he got in a lot of trouble when he tweeted a series of raving rants over the progressive SF board of supervisors, culminating in a tweet that read “die slow, motherfuckers”, leading to board members receiving death threats and ultimately an apology and a retraction from Garry.
Another fun one: according to Garry the New York Times is upholding “woke capital”, which, according to Garry, is the “ideology of America’s ruling class”. So, that’s nice.
Why is Hacker News like that?
Hacker News is a product of Y Combinator and the people in its orbit, and they’re not great people. The rules cover what to post and how, and the closest they get to addressing any kind of bigotry, hate, or bias is the following:
Please don’t use Hacker News for political or ideological battle. It tramples curiosity.
The purpose of a system is what it does, and the system at Hacker News amplifies right wing politics and bigotry. The moderators, the users, and the tools available to them collaborate to suppress progressive ideas and re-enforce the kinds of politics that favor Y Combinator, its people and its friends.
I have spoken with the moderators about this many, many times over many years. I have explained to Daniel Gackle how the nature of the automated moderation tools, and the flagging feature, that produces these consequences. I have suggested reforms that would improve the situation. To my knowledge, none of this feedback has ever led to any changes in how HN works or is moderated.
Hacker News is a case study in what inevitably happens to “apolitical” spaces. Politics and society are bifurcating, and Hacker News is taking the fork on the right. “Apolitical” is an excuse to favor the status quo, a resistance to change, and therefore a re-enforcement of the existing biases and power structures of society. It’s no surprise that Hacker News favors capitalism, opposes labor, and objects to questioning the privileges of its largely white, male, middle-class audience. It’s “political” and “ideological” for it to do anything else.
P.S. I’ve been trying to figure these people out for a long time. A book that helped me put a lot of the pieces together was “The Nerd Reich: Silicon Valley Fascism and the War on Democracy”, by Gil Durán. It’s a great read, you should check it out too!
-






