InFeeo
United States
technology
New
Language
Profile channel

@Jacob

No bio yet.

Since 31.05.2026

Entropy(sciencenews.org)
Gotta catch it all I've been thinking a lot about randomness lately. I'm not sure why, maybe it's a meta-analysis of my own brain. Either way. It's worth prefacing this by saying that I'm not a cryptographer, nor do I have particularly strong math skills. I usually defer to others for those topics. Anyways! Entropy! It's around us! Famously, Silicon Graphics and Cloudflare pointed cameras at lava lamps (and various other sources at this point) to gather entropy to then feed into a randomness algorithm. Being able to produce unpredictable streams of bytes is a pretty valuable thing depending on your workload. But also, it's kind of fun to do when your workload doesn't demand it. Especially fun when you can work in seemingly useless implementation details! I sat down one day and got really fixated on Linux entropy. Did you know you can feed a Linux system's entropy pool by just writing data to /dev/{u}random? Further, did you know that there's actually very little difference between urandom and random, besides its behaviour before the system is satisfied it has enough entropy? Also, they're re-seeded very frequently at boot using data from the entropy pool itself, and then every minute once boot is finished? I highly recommend this talk from the Wireguard creator Jason Donenfeld that goes into modernising the kernel's random.c implemtation, and hints at some future plans. Watching that talk also gives a bit more context to some of the decisions I'll talk about later in this post. The entropy pool is fed from a number of sources, but it can only consume so many at a kernel level. From a userland level, the ability to "feed" the pool opens up a ton of possibilities. Is it really neccessary? No, not really, but it makes me smile and that's generally enough. It doesn't hurt, anyways. So I sat down and started hacking together a concept: can I use WASM plugins to feed data into my system's entropy pool? WASM was chosen because I just wanted to experiment with implementing it as a plugin system. I've previously experimented with plugin systems in my projects, including writing various Minecraft Bukkit plugins and add using a full Go interpreter in my Platypus server monitoring project. I understand the theory and some of the practical implementation practices, but what is usually missing is a solid runtime that lets people use whatever language they're most comfortable with. WASM gives us a solid foundation that a lot of languages can build to. So while this was "just" an excuse to play with WASM more, my brain was still very fixated on feeding my entropy pool. Thus, morerandom was born. Not much searching was required to find Extism, which is purpose built as a plugin system for other programs. The implementation on the "host" side is trivial, although the minor nit I have is that on the plugin side you need to use their library (as an example, I have a 1.wat plugin that just echo's 1. It's a bit more complex than it needs to be). The initial, and current, implementation just called a WASM binary's random() -> FnResult function and returned whatever raw bytes were included in that result. Enough for a proof of concept, but then the gears started turning. I could use my microphone for entropy! My camera! But... those aren't accessible to all my machines... and exposing them to WASM plugins would be tricky and risky... So the next step was adding microphone and camera supprt to the binary itself. Fairly easy given libraries existed for Rust already, and I could just spit out the raw bytes. Easy! I had essentially replicated lavarand in Rust. Cool! But... but wait, the other machines in my homelab might want to feed that entropy into their own pools... how could I do that? And further, how could I avoid a malicious client from extracting the raw microphone and camera bytes, potentially snooping on me? And thus the rabbit hole progressed. To facilitate over-the-network entropy fetching, I added gRPC (Google's Remote Procedure Call, although it's not a Google project anymore). For the uninitiated, gRPC is at a high level a way for a codebase to call a function on a remote machine. We define a common schema that the binaries use to encode and decode the results of the function call, and is generally much faster and smaller than using HTTP calls. A small client binary on a server connects to my desktop's morerandom server and calls the get_random() function the server exposes. The client gets bytes that it then prints to the standard output. And we're happy, right? Not quite. We still have the issue of extracting the raw data. For this, I took a page from Linux's random.c implementation and started looking at the ChaCha20 algorithm. I won't pretend to fully understand the algorith, but my current understanding is that you feed it a seed and it can extrapolate a practically endless stream of encrypted data - or randomness, in our case. For the seed, we use the entropy we've collected ourselves! To keep things simple, we first hash that data using the modern BLAKE3 hashing algorithm, giving it the bytes from the activated plugins, camera and microphone, then using the hash it produces as our entropy seed. I've essentially re-implemented /dev/{u}random, in the sense it ends up as a ChaCha20 stream. Furthering the similarities to the kernel's implementation, the server re-seeds this entropy every minute or so by fetching data from the plugins, microphone and camera, and mixing in a few bytes of data from the existing ChaCha20 stream. Theoretically this means that even if you guess the initial state of the server's plugins, camera and microphone, you'll have to keep controlling those inputs to stay in control of the seed - which isn't impossible, and why I wouldn't recommend this be your only source of entropy - but practically speaking very difficult. I later added an HTTP server to demonstrate random number and boolean generation, for easy use in other projects if I want (and just to show off a bit, I suppose). I've iterated over the codebase a few time, cleaning it up and making it more robust, but the core entropy collection flow is pretty much the same. Alongside the server there's also a standalone binary, which does a one-off collection, hash and seed of the entropy before printing 32 bytes of data to stdout. I run it through xxd if I'm looking at the raw data, otherwise the output is very garbled! Raw bytes are fun. # One run 00000000: 8d55 7c9f 893f f21a af3b 9436 7928 a8ed .U|..?...;.6y(.. 00000010: 3a55 da08 313d ab65 96a5 9d00 c8ff b40d :U..1=.e........ # Another one 00000000: 2071 208f ba71 4e0e 248f da65 b701 ac8b q ..qN.$..e.... 00000010: 2c43 b572 72b4 34ca ad42 8b2e 24d2 76c1 ,C.rr.4..B..$.v. With all that in place, and my homelab servers running a systemd timer that using the morerandom client binary to fetch entropy from my desktop once a day and writing it to their own entropy pool, I consider this project pretty much done! Which is quite satisfying. I think the implementation is pretty robust, but I'm sure I'll find some other things to tinker with. I want to expand the WASM capabilities and available functions, but I don't really have a good reason to at the moment. This project was an awesome learning experience into ChaCha20, BLAKE3 and generally getting a little too obsessive with entropy on Linux. If you have any feedback, questions etc. feel free to reach out on the fediverse!
Static Types and Shovels(carefully.understood.systems)
Static types and shovels I have a simple theory about why static typing became much less popular in the 2000s to early 2010s and started to get more popular again around the mid to late 2010s. It isn't because programming is a fashion led industry, but because the quality of the static type systems that were widely available improved. Here's an analogy: say you want to dig a hole, would you rather use a shovel or your hands? If the shovel is any good then obviously you'd use the shovel. But what if the only shovel available to you was made of paper? You'd just be flailing uselessly at the ground with it. You'd be better off digging barehanded. With a dynamic type system, you have to do all of the thinking about the states and contents of the variables and fields in your program yourself, with your own brain. The computer doesn't help you at all, nor does it hinder you. It's analogous to digging with your hands. On the other hand, if you're given a poor static type system like the ones that were popular in the 90s and early 00s, such as the ones in early Java or C++98, it's analogous to a paper shovel. These static type systems fail to even help you with simple things like distinguishing nullable from non-nullable pointers. They don't have sum types, only product types. Meanwhile they require you to spend a lot of effort manually writing out type names all over the place. BufferedReader bufferedReader = new BufferedReader(new FileReader(filename)); is a small disaster. If you contrast this to a modern type system like the one in say TypeScript, Haskell, MyPy, Swift or Rust, you'll always get: Some way of distinguishing nullable from non-nullable types. Haskell has Maybe t. TypeScript has T | null. Swift has T?. Rust has Optional. The type system can easily tell you where all the null checks need to be and if you missed one. In practice you almost never see null pointer errors at runtime. At least one of sum types or union types, which let you follow the "Make invalid states unrepresentable" practice. This means you can have objects representing state machines, they have multiple fields, and each field exists when and only when the system is in a relevant state. Some kind of type inference. We don't need to write let x: number = 5; when the compiler can just work out that let x = 5; is definitely a number. Another thing which made static type systems more useful is that IDE features like method name completion have become more widespread. In the 90s Intellisense was a killer feature in Visual Studio, whereas in the 2020s similar features are available in just about every IDE and editor. So information you put into a static type system yields extra productivity benefits, entirely aside from its usefulness for checking programs for errors. In conclusion: A good dynamic type system is better than a bad static type system. But now we have much better static type systems than we used to. © Copyright 2026 Richard Barrell
Native Coding Agent Optimized for Local LLM and DeepSeek v4 with Vector Memory(blog.can.ac)
cwcode A terminal coding agent built around DeepSeek V4 Pro, Qwen3.6‑27B, Kimi, Azure, and anything else that speaks OpenAI’s chat API. Written in Go. Lives in your terminal. Edits real code. Recovers from its own mistakes. Costs about $0.40 to leave running for an hour. 5% of Claude’s token coston DeepSeek V4 Pro 85%+ prefix-cache hit ratioafter turn 3 ~12k lines of Gono external services What it is cwcode is a Bubbletea TUI that drives any OpenAI-compatible chat endpoint as a tool-using coding agent. It ships with profiles for DeepSeek (Pro and Flash), Azure OpenAI, Kimi for Coding, and a local vLLM / llama.cpp profile for Qwen3.6-27B on a home server. Switching profiles mid-session is one slash command. It has bash, file edit, glob, grep, web fetch, headless-Chrome fetch (driven via CDP through your real browser), sub-agents, a persistent semantic-memory store, content-addressed checkpoints with rewind, a plan/code mode toggle, and an autonomous goal loop. The tool registry is six hundred lines and adding a new tool is a two-method Go interface. It is not a SaaS. There is no account, no telemetry, no remote control plane. Your API key sits in ~/.cwcode/config.json. Your session history sits in ~/.cwcode/sessions/. If your network is down and the model endpoint is local, the agent keeps working. Why it’s different Hash-anchored edits The read_file tool annotates every line with a 3-character content hash: 42:a3f| return x. The edit_lines tool takes (line, hash, new_text) and rejects the entire batch if any hash drifted. The model never has to reproduce content character-perfect to land an edit. Adopted from Can Akay’s February 2026 post and ported to Go in about 200 lines. Output tokens per session dropped 30–40% on V4 Pro. Sticky prefix cache The system prompt is byte-stable across turns. Tool definitions serialize in a deterministic order. Reasoning content is stripped from outbound requests on every provider by default. DeepSeek’s prompt-cache hit path is ~120× cheaper than the miss path, and our /cache slash command shows session-cumulative hit ratio that routinely exceeds 85% after the third turn. Plan vs code mode A single Shift+Tab toggle between read-only planning (the LLM only sees non-mutating tools) and full execution. The model doesn’t see the flag — it just sees a different (smaller) tool registry and a system-prompt addendum. The human holds final control unless you opt into YOLO mode. Checkpoint & rewind Before any file-mutating tool runs, the harness snapshots the pre-state of every path the tool declares it will touch. Snapshots are SHA-256-keyed blobs in ~/.cwcode/sessions//objects/, deduped automatically. /rewind N restores files, truncates conversation history, and pre-fills the input box with the original prompt. Storm-breaker When the same tool fails identically three times in a row, the harness doesn’t silently abort. It synthesizes a plain-language response (“I’m unable to continue: read_file failed three times because the path was empty. Please clarify…”), streams it like a normal reply, and appends it to history so follow-ups have context. Autonomous goal loop /goal appends a goal to goals.md. /goal on starts an autonomous loop that runs back-to-back turns until every checkbox is marked done or until a safety cap of 20 consecutive cycles. We use this for four-hour overnight runs on annotated tasks. No SaaS lock-in Config is JSON. Sessions are JSON. Checkpoints are content-addressed blobs. Memory store is a SQLite file. Everything lives under ~/.cwcode/. If the project disappeared tomorrow your sessions are still readable. What it looks like Captured during real work on our dose-prediction codebase: the agent proposing an edit_file change to a Go test, with a unified diff highlighted inline, the reasoning trace streaming below, and the current task list pinned to the bottom of the pane. cwcode running a Go test edit; multi-tab tmux session, dose-prediction project, DeepSeek profile. Install Download a pre-built binary for your platform from the Google Drive release folder (current build: v1.11; macOS arm64 / amd64 and Windows amd64). Drop it somewhere on your PATH and make it executable: curl -L -o ~/.local/bin/cwcode chmod +x ~/.local/bin/cwcode cwcode -version You’ll need an OpenAI-compatible endpoint (DeepSeek API key, Azure deployment, local vLLM, or whatever else you have on hand). Configure a profile in ~/.cwcode/config.json: { "active_profile": "deepseek-pro", "profiles": { "deepseek-pro": { "provider": "deepseek", "endpoint": "https://api.deepseek.com", "model": "deepseek-v4-pro", "api_key": "sk-...", "ctx_size": 262144 } } } Run it. cwcode # Bubbletea TUI cwcode -p "fix the bug" # one-shot, no session cwcode -continue # resume the most recent session cwcode -plain # stdout REPL (no TUI) Built-in tools namepurposeneeds approval bashrun a shell command (streaming output)yes bash_backgroundspawn a long-running processyes read_fileread with per-line content hashesno write_filecreate or overwrite a fileyes edit_fileexact-string replace with whitespace recoveryyes edit_filesatomic multi-file batch (exact-string)yes edit_lineshash-anchored line replacementyes globfind files by patternno grepsearch files for a regexno lslist directory contentsno web_fetchfetch a URL and clean it upno chrome_fetchdrive your real Chrome via CDP for bot-blocked pagesno taskspawn a sub-agent with its own contextyes rememberadd a fact to the persistent memory storeno recallsemantic search over past sessionsno todo_writeupdate the visible task listno FAQ Why Go? Single static binary, fast startup, easy cross-compile. Three platform builds in 90 seconds. The TUI binary on macOS is 24 MB with debug symbols stripped. Why a terminal app and not a VS Code extension? Because we wanted the agent to be the primary interface, not a side panel. The TUI gives the model the whole pane to work in and gives us a small surface to debug. If you live in VS Code, you can run cwcode in the integrated terminal. Does it work with Claude? Not directly — cwcode speaks the OpenAI /v1/chat/completions shape. Claude has its own API. You can put Claude behind a translating proxy if you want, but we built this for the cost shift in the other direction. What model do you use day to day? DeepSeek V4 Pro for most coding work, Flash for quick questions and one-shot scripts, the local Qwen3.6‑27B profile when we want zero latency or are working offline. Is the source available? Pre-built binaries are on Google Drive. Source is currently private; we plan to open it once the API surface settles. If you want a peek before then, get in touch. Who built this? A small team that uses it daily for dose-prediction model training, financial research agents, and writing cwcode itself. The agent ships its own bugs and writes its own fixes.
I built a leakage-clean verifier for robot manipulation, is this useful? Am I solving a non-problem?(reddit.com)
Spent the last few weeks on a benchmark/harness that tries to answer one question honestly: did a robot arm actually do the demonstrated task, or did the success metric just get fooled? The setup: compile a human demo into an object-centric graph (what changed in the world: relations, contacts, event order), run a solver, then independently extract a graph from the rollout only and check if they match. The whole point is a hard information boundary so the "answer key" can never leak into the side that grades the rollout. A no-op baseline fails with named failure classes; a dumb scripted arm passes. That contrast is the thing I care about. Most manipulation success metrics are hand-coded predicates written by the same person training the policy. The policy author controls both the behavior and the definition of "success." That's a conflict of interest we'd never accept in ML benchmarking, yet it's standard in manipulation eval. But I keep going back and forth on whether this matters, and I'd like other people's read: The case that it's real: VLA/foundation-model training is starved for reliable dense reward at scale. Human raters don't scale, brittle predicates lie. An automatic, embodiment-agnostic grader that can say "this rollout reproduced the demonstrated transformation, here's why it failed" seems like an obviously-missing piece of the training loop. The case that it's a non-problem: maybe everyone's already fine with task-specific success checks because in practice you only care about the tasks you're shipping, and a general verifier is solving for a generality nobody needs. And the representation that makes verification tractable (discrete relational state — INSIDE/TOUCHING/event-order) is also what caps it: it handles pick/place/insert/open-drawer but has no obvious purchase on force-profile or deformable tasks, which is exactly where the frontier is. There's also the uncomfortable bit: the hard 80% is perception (video → graph under occlusion and contact noise), and that's where the leakage discipline gets harder, not easier, because your extractor is now a learned, error-prone thing. Two questions I don't have a settled answer on: Is reward/eval honesty a first-order bottleneck for the current generation of manipulation learning, or second-order polish? Is object-centric relational state a dead representation for where manipulation is actually going, or a reasonable floor you build up from? submitted by /u/Alexpplay [link] [Kommentare]