daily

2026-06-07
1

Show HN: Oproxy – inspect and modify network traffic from the browser

Hacker News · original →
oproxy is a local HTTP, HTTPS, and SOCKS5 proxy for inspecting, replaying, and modifying traffic. It is for developers testing browsers, CLIs, mobile apps, API clients, services, and test suites on…

oproxy is a local HTTP, HTTPS, and SOCKS5 proxy for inspecting, replaying, and modifying traffic. It is for developers testing browsers, CLIs, mobile apps, API clients, services, and test suites on their own machine or in a local Docker container. - Capture HTTP traffic and HTTPS traffic after trusting the local oproxy CA. - View requests, responses, headers, bodies, status, timing, tags, notes, and selected inspector data. - Replay captured requests and open them in Compose. - Build manual requests with headers, query params, auth, raw bodies, variables, collections, and cURL export. - Export captures as HAR or generated cURL, Fetch, and Python snippets. - Modify traffic with rule sets, map-remote, map-local, access rules, throttling, breakpoints, mock responses, DNS overrides, capture filters, Lua scripts, and upstream proxy chaining. - Use the authenticated Assistant to inspect state and prepare confirmed proxy changes through an OpenAI-compatible chat model. - Run from source or Docker with persistent volumes for CA material and local state. docker run --rm \ --name oproxy \ -p 127.0.0.1:8080:8080 \ -p 127.0.0.1:1080:1080 \ -e OPROXY_BIND_HOST=0.0.0.0 \ -e OPROXY_MITM_ENABLED=true \ -v oproxy-certs:/app/certs \ -v oproxy-storage:/app/storage \ ghcr.io/sauravrao637/oproxy:latest Open http://127.0.0.1:8080 . Or build locally: docker build -t oproxy:latest . docker compose up --build The included Compose file uses host networking, persists /app/certs and /app/storage , and sets OPROXY_BIND_HOST=0.0.0.0 . Requirements: - Rust 1.85 or newer - Node.js 22 or newer - Yarn via Corepack corepack enable yarn --cwd src/design install --frozen-lockfile yarn --cwd src/design build cargo run --release Open http://127.0.0.1:8080 . curl -x http://127.0.0.1:8080 http://example.com The request appears in the Sessions view. curl http://127.0.0.1:8080/admin/ca -o oproxy-ca.crt curl --cacert oproxy-ca.crt -x http://127.0.0.1:8080 https://example.com For browser HTTPS capture, install the CA from http://127.0.0.1:8080/admin/ca into the browser or OS trust store. - Act as a forward HTTP proxy on OPROXY_PORT /port , default8080 . - Serve the local management UI and API from the same listener. - Intercept HTTPS CONNECT traffic when MITM is enabled and the client trusts the generated CA. - Optionally listen for SOCKS5 CONNECT traffic on socks5_port . - Optionally run a second TLS listener with https_port . - Capture live sessions in memory with bounded session and body retention. - Save and load sessions explicitly with admin endpoints. - Export HAR, cURL, Fetch, and Python snippets, redacted by default. - Import HAR files and oproxy JSON session data. - Stream session-change notifications with server-sent events. - Inspect JWT, GraphQL, gRPC, and WebSocket frame metadata when matching traffic is captured. - Debug a browser or CLI request without changing application code. - Replay a captured request after editing headers or body in Compose. - Test a frontend against mock responses or local fixture files. - Route a subset of traffic to a staging service. - Reproduce slow or bandwidth-limited responses. - Pause matching requests or responses before they continue. - Validate how a client behaves when requests are blocked, redirected, or rewritten. - Getting started - Docker - HTTPS MITM - Compose - Assistant - Map Local - DNS overrides - SOCKS5 - Configuration - Troubleshooting - Security MIT

2

Zeroserve: A zero-config web server you can script with eBPF

Hacker News · original →
zeroserve is a small, fast, zero-config HTTPS server. You hand it a tarball of a website and it serves it - over HTTP/2 and TLS 1.3, with hot reload and a tiny resident footprint. The twist is that…

zeroserve is a small, fast, zero-config HTTPS server. You hand it a tarball of a website and it serves it - over HTTP/2 and TLS 1.3, with hot reload and a tiny resident footprint. The twist is that you can drop eBPF programs into the tarball and they run on every request, in userspace, as sandboxed middleware - rewriting, authenticating, and rate-limiting requests, or reverse-proxying them to a backend when you want it to act as a gateway in front of your app. In short: - Fast: on one core it beats nginx across most workloads - small and large static files, scripted middleware, and small-response proxying, all over HTTPS. - Efficient eBPF scripting: scripts are JIT-compiled to native code and sandboxed in userspace, cheap enough to run on every request. - Program-as-configuration: your eBPF program is the whole configuration, deciding what happens to each request. io_uring throughout: every network and disk operation is submitted throughio_uring .- Modern TLS in the box: TLS 1.3, HTTP/2, Encrypted Client Hello, SNI certificate selection, and JA4 fingerprinting. - Simple to operate: serve a whole site from one tarball and hot-reload it (and the TLS material) with a SIGHUP . It's meant to be an alternative to nginx and Caddy, and the design bet is about configuration. Those servers give you a declarative config language - location blocks, rewrite rules, map directives, try_files - and then, once the declarative language hits its limits, an optional scripting runtime bolted on the side (Lua, or Caddy's plugins). Behavior ends up split across two layers: directives that quietly grow their own control flow, plus scripts that run somewhere in the request lifecycle you have to keep in your head. zeroserve collapses that into one thing. There is no config file. The eBPF program is the configuration - a single, ordinary, sandboxed program that sees every request and decides what happens: routing, headers, auth, rate limiting, proxying. I want the whole request path in one program I can read top to bottom. One tarball, served in place The whole site is a single tar file. zeroserve indexes it on load - building a path -> byte-range map - and then serves files by issuing byte-range reads against the tarball itself. Nothing is ever unpacked to disk. The site lives entirely in that one file, so there's no document root for a stray location rule to expose, and a deploy is a single atomic file swap. To package a directory: zeroserve --pack ./public > site.tar zeroserve --addr 0.0.0.0:8080 site.tar Deploying a new version is "replace the tarball and send SIGHUP ". The reload swaps the site, the scripts, and the TLS material atomically, in the same process, with no dropped connections: killall -SIGHUP zeroserve All network and disk I/O goes through io_uring (via the monoio runtime). Each instance is a single-threaded event loop. That sounds like a limitation, and per-process it is - but it's the right shape when your scaling unit is "more processes", and it's why many of them coexist happily on one box. Scripting with eBPF, in userspace This is the part I find most fun. Any .c file you put under .zeroserve/scripts/ gets compiled to an eBPF object at pack time (with clang and llc ) and runs on every request. The eBPF runs entirely in userspace: zeroserve loads the bytecode into a runtime (async-ebpf) inside its own ordinary, unprivileged process, so the kernel's BPF subsystem and CAP_BPF stay out of it. async-ebpf JIT-compiles the bytecode to native machine code (it vendors uBPF), so your "config" runs as native x86-64. A pointer cage does the job the kernel verifier normally would, keeping the program from reading or writing memory it shouldn't: every memory access in the JIT-compiled code is masked into the program's own arena, so a stray access stays confined to the script's own memory. The script runs directly on zeroserve's single event loop. To keep one slow script from stalling every other connection, the runtime is fully preemptible: a timer can interrupt JIT-compiled native code mid-execution and hand control back to the event loop. The programming model is a chain of scripts, run in sorted filename order, sharing a per-request metadata map. If a script calls zs_respond or zs_reverse_proxy , the chain short-circuits. Here's a script that runs first and enriches every request: #include ZS_ENTRY zs_u64 entry(void) { char peer[64]; if (zs_req_peer(peer, sizeof(peer)) <= 0) zs_strcpy(peer, "unknown"); // publish values for the HTML template pass zs_meta_set(ZS_STR("visitor"), ZS_STR(peer)); // attach a header to *every* response: static files, zs_respond, proxied zs_meta_set(ZS_STR("zs.response.header.x-served-by"), ZS_STR("zeroserve-ebpf")); return 0; } The metadata it sets does two things. Keys under zs.response.header.* become response headers on everything. And other keys feed a tiny template pass: a visitor placeholder in an HTML file gets substituted on the way out. So you get dynamic-ish static pages without a template engine. The helper surface a script can call is broad: - Request inspection and mutation: read the method, path, query params, headers, and peer address; rewrite the URI or set and remove headers before the response goes out. - Crypto and encoding: SHA-256, HMAC-SHA256, base64, hex, and getrandom . - JSON: parse a request body, build and mutate a document tree, and reply with zs_json_respond . - Rate limiting: per-key token buckets keyed on anything from a peer IP to an API key, with state that survives hot reloads. - AWS SigV4: signed Authorization headers and presigned URLs for talking to S3 and other AWS services. - OIDC login: a complete relying-party flow (Authorization Code + PKCE) that carries the entire login session in sealed XChaCha20-Poly1305 cookies, so you can gate a static site behind "log in with Google" while the server stays stateless. A dynamic endpoint is just a script that responds: ZS_ENTRY zs_u64 entry(void) { char path[64]; zs_req_path(path, sizeof(path)); if (zs_strcmp(path, "/health") != 0) return 0; zs_meta_set(ZS_STR("zs.response.header.content-type"), ZS_STR("application/json")); zs_respond(200, ZS_STR("{\"status\":\"ok\"}\n")); return 0; } Each script runs under a memory-footprint cap (256 KB by default), the runtime time-slices long-running scripts off the executor and throttles the runaways, and scripts can even call each other (zs_call ) up to a bounded depth. A script that spins forever stalls only its own request - the preemption timer interrupts it and the server keeps serving everyone else. The TLS story underneath is more complete than the zero-config framing suggests: TLS 1.3 only, terminated by BoringSSL, with native Encrypted Client Hello (so the real SNI never appears in cleartext), SNI certificate selection from a directory, JA4 client fingerprinting exposed to scripts, and a transparent ECH relay mode that byte-for-byte forwards undecryptable handshakes to a real upstream so a protected name blends in behind a public one. That's a lot of transport security to ship in a single zero-config binary. How fast is it? I benchmarked zeroserve against nginx 1.26 and Caddy 2.11 over HTTPS on an 8-core Ryzen 7 3700X, each serving the same content with the same self-signed certificate. Because a zeroserve instance is single-threaded by design, the only fair comparison is per core: I pinned every server to one CPU with taskset (and held nginx to worker_processes 1 and Caddy to GOMAXPROCS=1 ; zeroserve is single-threaded already) and drove load with wrk -t4 -c100 from other cores, taking the median of three 10-second runs. wrk speaks HTTP/1.1, so these are HTTP/1.1-over-TLS-1.3 numbers with the handshake amortized across long-lived keep-alive connections: the steady-state cost of serving an already-open HTTPS connection. Small static file (174 B) - the bread and butter of static sites: | server | req/s | p99 | |---|---|---| | zeroserve | 36,681 | 5.4 ms | | nginx | 31,226 | 7.8 ms | | Caddy | 12,830 | 22 ms | zeroserve serves small files about 17% faster than nginx on a single core, with a tighter tail. HTML pages, small JSON, CSS - this is the case zeroserve is tuned for. Large static file (100 KB): | server | req/s | throughput | p99 | |---|---|---|---| | zeroserve | 8,000 | 782 MB/s | 22 ms | | nginx | 7,600 | 773 MB/s | 28 ms | | Caddy | 6,084 | 590 MB/s | 44 ms | All three are close here, with zeroserve a hair ahead at around 780 MB/s on one core. nginx's usual trump card for large files is sendfile() , which splices file pages from the page cache to the socket with zero userspace copies. Under TLS that path goes unused: the bytes have to be encrypted in userspace anyway (short of kernel TLS, which all three leave off), so every server is bound by the same encrypt-and-write loop, and zeroserve's io_uring read-and-write path is a touch faster at it. eBPF vs Lua The obvious comparison for the scripting is nginx + LuaJIT (ngx_http_lua_module ), the usual way to run fast code inside a web server. So I wrote the equivalent Lua for two cases and put them head to head. One tuning knob matters a lot here. zeroserve ships with a conservative default: it arms the script-preemption timer every 2 ms. Fine granularity makes it quick to throttle a misbehaving script, but it taxes every well-behaved one - at the default, eBPF trails nginx Lua on a fully dynamic response (about 32k req/s against 41k). Bumping --preempt-timer-interval-ms to 10 recovers ~40% of scripting throughput and turns that around: Per-request header-injection middleware (script runs, static file is still served): | engine | req/s | p99 | |---|---|---| | zeroserve eBPF (10 ms) | 43,709 | 5.1 ms | | zeroserve eBPF (2 ms default) | 31,334 | 6.7 ms | nginx Lua (header_filter ) | 28,653 | 8.4 ms | Fully dynamic JSON response: | engine | req/s | p99 | |---|---|---| | zeroserve eBPF (10 ms) | 46,945 | 4.5 ms | nginx Lua (content_by_lua ) | 41,231 | 6.4 ms | | zeroserve eBPF (2 ms default) | 32,393 | 6.7 ms | At the 10 ms interval, tuned eBPF wins both cases. On the middleware case - a script shaping an otherwise-static response - it beats nginx Lua by about 50%, with a tighter tail. On the fully synthetic response it edges nginx's heavily-tuned content_by_lua too (47k against 41k). Both engines compile to native code (LuaJIT is a tracing JIT; async-ebpf JITs the eBPF through uBPF), and with TLS encryption as a shared per-request cost, the tuned eBPF path comes out ahead on throughput. At the 2 ms default, eBPF keeps the middleware win but gives up the synthetic-response lead, so I'd run production scripts at 10 ms. As a reverse proxy Serving files is half the job; the other half is proxying to a backend, which is the main reason most people reach for nginx or Caddy in the first place. zeroserve does it from a script - zs_reverse_proxy("http://127.0.0.1:9000") - and keeps a pool of upstream connections (up to 128 per backend, 30 s idle) and reuses them across requests. Getting a fair fight here takes care: nginx's famous default closes upstream connections after each request, so keep-alive is enabled explicitly (keepalive 128 , proxy_http_version 1.1 , and a cleared Connection header), with Caddy reusing connections as it does by default. Each proxy terminates TLS on a single core and forwards to a shared plaintext backend, a separate 2-core server that sustains 100k req/s on its own, so the measurement isolates the proxy's own overhead. Proxying a small (174 B) response: | proxy | req/s | p50 | p99 | |---|---|---|---| | zeroserve | 26,486 | 3.3 ms | 8 ms | | nginx | 21,761 | 4.2 ms | 10.5 ms | | Caddy | 7,683 | 10.3 ms | 33 ms | zeroserve's pooled io_uring proxy leads here, about 22% ahead of nginx (26.5k against 21.8k) and roughly 3.4× Caddy. For the typical proxy workload - forwarding API calls, small JSON, an app server's HTML - zeroserve terminates TLS and shuttles the request to the backend faster than the reference implementation. Large bodies tip the balance back. Proxying a 100 KB response: | proxy | req/s | throughput | |---|---|---| | nginx | 5,882 | 585 MB/s | | Caddy | 4,285 | 406 MB/s | | zeroserve | 3,631 | 359 MB/s | Once the proxied body is large, nginx's buffering moves bytes more efficiently and pulls ahead, with Caddy slotting in between and zeroserve trailing. If your proxied responses are large, nginx is the better tool; if they're small and numerous, zeroserve is faster. Memory Idle, a single zeroserve instance sits around 15 MB PSS - more than nginx's ~6 MB, less than Caddy's ~60 MB. On its own that's unremarkable. What makes it matter is that the unit is a whole process: when you run a copy per core, they all map the same binary, so the code pages are shared, and each extra process adds little beyond its own working set. zeroserve is open source on GitHub - try it yourself!

3

I design with Claude more than Figma now

Hacker News · original →
For a long time I was skeptical of LLMs—whenever I reached for them I was disappointed by the results. Last year I tried Copilot and Cursor to tweak a game I’d built, and neither generated working…

For a long time I was skeptical of LLMs—whenever I reached for them I was disappointed by the results. Last year I tried Copilot and Cursor to tweak a game I’d built, and neither generated working changes. At a previous job I tried Gemini to outline product briefs and generate wireframes, but ended up throwing them all away. Every time I tried LLMs it was for something I was already good at, and they did a worse job than I would have. Having joined Jane Street this past summer, I’m finding AI support indispensable. There’s just so much that’s new to me, and so much I’m not good at yet, like OCaml and Bonsai. But one big surprise is how much it’s changed the thing I’m best at: my design workflow. Instead of laboring over spec docs, building Figma mockups, writing proposals, and reviewing the implementation with devs, I find myself building prototype features that just do the exact thing I have in mind. What that looks like in practice is: - Write something describing the problem and my proposal - Open my editor, start a build, the server, and Claude, using that description I wrote as the prompt - Get the basic functionality working to prove to myself that it’s possible - Iterate on that as much as I want - Push changes to a development environment and ask users what they think - Submit a feature (our version of a pull request) that looks and behaves exactly the way I want A prototype feature in the actual codebase has felt better in almost every way compared to mockups and docs. Take a prototype I made recently that added LLM prompting to a JSQL input (JSQL is an internal SQL dialect that we use for lots of different user-facing tools). This prototype really works, and I spent days living with it and testing it. Claude gave me free, unlimited iteration, unbothered when I changed my mind for the 50th time or asked for a small tweak. I refined the Submit button, added keyboard shortcuts, tweaked copy, adjusted the prompt, and added generated confirmation messages. These are workflow improvements that would have taken days or weeks of engineering and design back-and-forth at my previous job, or more likely would just never have happened. All the effort spent on this feature went into improving the real artifact, and none on ancillary in-between work like creating Figma components or formatting docs. It took me a while to arrive at this workflow. When I joined last summer, I only approached smaller-sized tasks with AI, like UX papercut fixes. For bigger ideas I was still using Figma and docs, and when I tried making those things with Claude it failed. But in the past 2 months the situations where I’ve reached for Figma have fallen off a cliff. Through some combination of improved models, my own facility with them, and carefully choosing the right scope, AI is now working for big stuff too—not just the JSQL prompt but a half dozen other prototypes that make user-facing, data model, and library changes, including some that are 2000+ line diffs; I’m using it to implement interactive prototypes for brand new apps after designing them in Figma; and for some new apps I’m even skipping Figma entirely, iterating on the visual design from the beginning with Claude. As a designer this has been empowering. Engineers have the ability to create working proofs of concept when they have an idea. Designers have to convince other people to do that for us. For an idea like “direct LLM prompting in the JSQL input” I’d be proposing something whose feasibility is not even clear at the outset; getting someone to build a prototype might waste their time. In other cases I might propose something that doesn’t clearly fill a user need. By using Claude to make these ideas real I’m making it a lot easier for others to evaluate them—they can just use it. But there’s a downside: in this workflow, the reviewer is given a fully baked feature. Does that mean they have zero input on the functionality and are just supposed to review the code? Review is not the most fun work—the equivalent in the design world would be getting a detailed wireframe from a PM and being asked to make it look good. I want to make my proposal as clearly and completely as possible, but I still want my engineering teammates to treat it the same way they’d treat a mockup in Figma, as something they and I can iterate on together in design-space. Our solution for now is just to think about these features differently. I write a short reminder in the description: prototypes are living proposal docs, the code is disposable, and a reviewer’s job is to give feedback about the design and user experience. Eventually, reviewers still take over the idea and implement it in a separate feature, referencing the prototype but owning the production code. In practice we’re still figuring out what makes sense and feels good with this new workflow. There’s also a fear I have that designing with Claude keeps me out of a fluid, creative mindset and stuck in an iterative one, constrained to the outcomes I think Claude can produce. That’s fine for mature tools, where changes are iterative, but might mean I miss ideas when working on something new. This is a familiar tension. When I was getting started professionally in 2011 there was a lot of discourse about whether designers should code. Critics argued that once you’ve started programming you’re less likely to make big changes to an idea. But I liked making websites, and I liked programming, so I kept writing code. Then, when frontend frameworks like React became common and frontend development got more complicated, like others I decided to specialize. I still made personal projects in React—that certainly helped me interact with devs—but I spent almost all my time at work in Figma and docs. Had I joined Jane Street before LLMs, I think I would have become even more entrenched in Figma. With JavaScript I at least have some experience; OCaml and Bonsai are entirely new, and contributing on a technical level would have felt out of reach. Instead I’m back to making the real thing, and it feels amazing to be working in the medium again. I feel more free than ever to just try things.

4

Tokenomics: Quantifying Where Tokens Are Used in Agentic Software Engineering

Hacker News · original →
Computer Science > Software Engineering [Submitted on 20 Jan 2026] Title:Tokenomics: Quantifying Where Tokens Are Used in Agentic Software Engineering View PDF HTML (experimental)Abstract:LLM-based…

Computer Science > Software Engineering [Submitted on 20 Jan 2026] Title:Tokenomics: Quantifying Where Tokens Are Used in Agentic Software Engineering View PDF HTML (experimental)Abstract:LLM-based Multi-Agent (LLM-MA) systems are increasingly applied to automate complex software engineering tasks such as requirements engineering, code generation, and testing. However, their operational efficiency and resource consumption remain poorly understood, hindering practical adoption due to unpredictable costs and environmental impact. To address this, we conduct an analysis of token consumption patterns in an LLM-MA system within the Software Development Life Cycle (SDLC), aiming to understand where tokens are consumed across distinct software engineering activities. We analyze execution traces from 30 software development tasks performed by the ChatDev framework using a GPT-5 reasoning model, mapping its internal phases to distinct development stages (Design, Coding, Code Completion, Code Review, Testing, and Documentation) to create a standardized evaluation framework. We then quantify and compare token distribution (input, output, reasoning) across these stages. Our preliminary findings show that the iterative Code Review stage accounts for the majority of token consumption for an average of 59.4% of tokens. Furthermore, we observe that input tokens consistently constitute the largest share of consumption for an average of 53.9%, providing empirical evidence for potentially significant inefficiencies in agentic collaboration. Our results suggest that the primary cost of agentic software engineering lies not in initial code generation but in automated refinement and verification. Our novel methodology can help practitioners predict expenses and optimize workflows, and it directs future research toward developing more token-efficient agent collaboration protocols. Current browse context: cs.SE References & Citations Loading... Bibliographic and Citation Tools Bibliographic Explorer (What is the Explorer?) Connected Papers (What is Connected Papers?) Litmaps (What is Litmaps?) scite Smart Citations (What are Smart Citations?) Code, Data and Media Associated with this Article alphaXiv (What is alphaXiv?) CatalyzeX Code Finder for Papers (What is CatalyzeX?) DagsHub (What is DagsHub?) Gotit.pub (What is GotitPub?) Hugging Face (What is Huggingface?) ScienceCast (What is ScienceCast?) Demos Recommenders and Search Tools Influence Flower (What are Influence Flowers?) CORE Recommender (What is CORE?) arXivLabs: experimental projects with community collaborators arXivLabs is a framework that allows collaborators to develop and share new arXiv features directly on our website. Both individuals and organizations that work with arXivLabs have embraced and accepted our values of openness, community, excellence, and user data privacy. arXiv is committed to these values and only works with partners that adhere to them. Have an idea for a project that will add value for arXiv's community? Learn more about arXivLabs.

5

Ntsc-rs – open-source video emulation of analog TV and VHS artifacts

Hacker News · original →
ntsc-rs is a free, open-source video effect which accurately emulates analog TV and VHS artifacts. Other popular effects eyeball the look of VHS tapes using simple color lookup tables and overlays.…

ntsc-rs is a free, open-source video effect which accurately emulates analog TV and VHS artifacts. Other popular effects eyeball the look of VHS tapes using simple color lookup tables and overlays. ntsc-rs uses algorithms that model how NTSC transmission and VHS encoding actually work, based on algorithms developed in composite-video-simulator, zhuker/ntsc, and ntscQT. ntsc-rs is written in Rust, and is multithreaded and SIMD-accelerated. Unlike similar effects such as ntscQT, it can run in real time at much higher resolutions than actual NTSC footage. ntsc-rs is available not just as a standalone and web application, but also as a plugin for After Effects, Premiere, and all OpenFX-compatible software. This includes DaVinci Resolve, Hitfilm, and Vegas.

6

Moving beyond fork() + exec()

Hacker News · original →
Moving beyond fork() + exec() [LWN subscriber-only content] LWN needs youLWN counts on its subscribing readers to support its mission of creating relevant human-written news coverage of the Linux…

Moving beyond fork() + exec() [LWN subscriber-only content] LWN needs youLWN counts on its subscribing readers to support its mission of creating relevant human-written news coverage of the Linux and free-software communities. Please subscribe to LWN and help to keep us on the net. As a special offer, subscribe to LWN now for at least six months, and receive a 25% discount on your subscription. fork() is a relatively expensive system call; it must copy the entire process state (including memory) for the child process. Many optimizations have been made over the years, but a fork is still a fundamentally costly operation. To make things worse, a fork() call is often immediately followed by an exec(), which will discard all of that memory that was so carefully copied for the child. Attempts (such as vfork()) have been made over the years to optimize for this case, but the pattern still is more expensive than it could be. Chen's patch set takes an interesting approach to optimize the fork() and exec() pattern. It is focused on applications that repeatedly launch processes running the same executable; imagine, for example, a program that must run Git repeatedly to obtain information about the contents of a repository. In such cases, the program could establish a template to accelerate those invocations, spreading the setup cost across multiple operations. This template would be created with the spawn_template_create() system call: This call will return a file descriptor representing a template for the executable file, which can be specified as either a file descriptor (execfd) or an absolute path (filename), but not both. To create the template, the kernel will open the indicated file and cache a bunch of information that will allow a process to run that file more quickly in the future. The application in question may run a given executable many times, but each invocation is different in a number of ways. The details of a specific invocation must be placed into an instance of this structure: The argv field is a pointer to the argument list to be passed to the program, while envp points to its environment. Changes to file descriptors and signal handling, instead, are passed through actions, which is a pointer to an array of: If, for example, file descriptor four should be closed in the child, the associated spawn_template_action structure would have type set to SPAWN_TEMPLATE_ACTION_CLOSE and fd set to four. Other actions exist for duplicating file descriptors, opening files, changing the working directory, and changing signal handling. Once the spawn_template_spawn_args structure has been filled in, the new process can be run with: Internally, this system call follows something close to the normal fork()/exec() path. Chen is careful to point out that all of the normal checks applied when executing a new file remain in place. But the cached information in the template makes the whole process faster than it was before. How much faster? Benchmark results provided in the cover letter show an improvement of about 2%, which may not seem like a lot, but it may make a difference for applications that fit the expected pattern. The most detailed review of this work was posted by Mateusz Guzik, who said: " Christian Brauner was favorable toward the goal, saying: " An important objective for a new interface, Brauner said, would be the ability to support an implementation of posix_spawn() in user space. posix_spawn() is well suited as a replacement for the fork()/exec() pattern; developers would likely welcome a native implementation that isn't (unlike the current implementation) hiding fork() and exec() under the covers. Chen agreed that the API as broadly sketched out by Brauner seemed better, and said that future work would be in that direction. So there will be no spawn templates in the Linux kernel but, if Chen's future work comes to fruition, Linux may finally gain a proper posix_spawn() implementation instead.Proceed to the article Since the earliest days of Unix, two of the core process-oriented system calls have been fork(), which creates a child process as a copy of the parent, and exec(), which runs a new program in the place of the current one. In Linux kernels, those system calls are better known as clone() and execve(), but the core functionality remains the same. While there is elegance to this process-creation model, there are shortcomings as well. A recent proposal from Li Chen to add "spawn templates" to the kernel will not be accepted in its current form, but it may point the way toward a new process-creation primitive in the future. Spawn templates struct spawn_template_create_args { __aligned_u64 flags; __s32 execfd; __u32 exec_flags; __aligned_u64 filename; /* Some fields elided */ }; int spawn_template_create(struct spawn_template_create_args *args, size_t args_size); struct spawn_template_spawn_args { __aligned_u64 flags; __aligned_u64 pidfd; __aligned_u64 argv; __aligned_u64 envp; __aligned_u64 actions; __aligned_u64 actions_len; __aligned_u64 reserved[4]; }; struct spawn_template_action { __u32 type; __u32 flags; __s32 fd; __s32 newfd; __aligned_u64 arg; }; int spawn_template_spawn(int template_fd, struct spawn_template_spawn_args *args, int args_size); Toward posix_spawn() This problem is dear to my heart and I have been pondering it on and off for some time now. The entire fork + exec idiom is terrible and needs to be retired ". He pointed out that the focus of the patch set was a bit strange in that it left the fork() part of the problem untouched. That is where most of the cost lies, he said, so optimization efforts should seek to remove it from the picture. Rather than copying the current process, "creating a pristine process is the way to go ". The idea of having a builder api for exec isn't all that crazy ". His suggestion, though, was that a new API should be built on top of the existing pidfd abstraction. Without getting into any degree of detail, he said that the right approach would be to create an option to pidfd_open() to create an empty process. A series of calls to a new pidfd_config() system call would then configure this new process as desired, setting up its environment, image to execute, and more. pidfd_config() would thus be analogous to fsconfig(). Index entries for this article Kernel System calls/clone() Kernel System calls/execve() Did you like this article?? Subscribe now at the special discounted rate to get a lot more like it.

7

Sem: New primitive for code understanding – not LSPs, but entities on top of Git

Hacker News · original →
Semantic understanding on top of Git. Diff, blame, impact, log. Functions, not lines. Left: what git shows you. Right: what actually happened. diff --git a/src/auth/login.ts b/src/auth/login.ts @@…

Semantic understanding on top of Git. Diff, blame, impact, log. Functions, not lines. Left: what git shows you. Right: what actually happened. diff --git a/src/auth/login.ts b/src/auth/login.ts @@ -12,6 +12,18 @@ +export function validateToken(token: string) { + const decoded = jwt.verify(token, SECRET); + if (!decoded.exp || decoded.exp < Date.now()) { + throw new TokenExpiredError(); + } + return decoded; +} + @@ -24,8 +36,10 @@ export async function authenticateUser( - const user = await db.findUser(email); - if (!user) return null; + const user = await db.findUser(email); + if (!user) throw new UserNotFoundError(); + await rateLimiter.check(email); @@ -45,12 +59,0 @@ -export function legacyAuth(user, pass) { - return db.query('SELECT * FROM users - WHERE email = ? AND password = ?', - [user, pass]); -} ┌─ src/auth/login.ts ──────────────── │ │ ⊕ function validateToken [added] │ ∆ function authenticateUser [modified] │ ⊖ function legacyAuth [deleted] │ └──────────────────────────────────── 3 entities changed across 1 file AI agents are 2.3x more accurate when given sem output vs raw line diffs. See the benchmark. Everything works in any Git repo. No config. No plugins. sem diff │ ⊕ function validateToken [added] │ ∆ function authenticateUser [modified] │ ⊖ function legacyAuth [deleted] sem blame │ ⊕ render_inline_diff a1a6fbf Rohan 04-03 │ ⊕ format_terminal a1a6fbf Rohan 04-03 sem impact ⊕ function authenticateUser → depends on: db.findUser, rateLimiter ← used by: loginRoute, authMiddleware ! 42 entities transitively affected sem log │ ae576ab Rohan 02-05 added │ a105183 Rohan 02-08 modified (logic) │ a1a6fbf Rohan 04-03 modified (logic) sem entities entities: src/auth/login.ts function validateToken (L12:24) function authenticateUser (L26:45) interface AuthConfig (L47:52) sem context context for authenticateUser (budget: 8000) target: ~705 tokens dependencies: ~256 tokens dependents: ~812 tokens All commands support --json for machine-readable output. Full reference. 26 languages. 5 data formats. One binary. $ brew install sem-cli $ sem setup ✓ Created wrapper script ✓ Set git config --global diff.external = sem ✓ Pre-commit hook installed Done! Running git diff in any repo will now use sem. To revert, run: sem unsetup One command. Every git diff becomes a sem diff . No config files. Also: cargo install --git https://github.com/Ataraxy-Labs/sem sem-cli

8

Show HN: TakoVM – Isolated model and tool execution used by enterprises

Hacker News · original →
Run untrusted Python safely. Job queues and Docker isolation built-in. Used by enterprises. Run AI-generated code in isolated Docker containers with optional gVisor sandboxing. Job queues, retries,…

Run untrusted Python safely. Job queues and Docker isolation built-in. Used by enterprises. Run AI-generated code in isolated Docker containers with optional gVisor sandboxing. Job queues, retries, and execution history included. Documentation · Quick Start · API Reference # Install (requires Docker + Python 3.10+) pip install "tako-vm[server]" tako-vm setup # pull the executor Docker image tako-vm server # start server (auto-starts PostgreSQL via Docker) # Execute code curl -X POST http://localhost:8000/execute \ -H "Content-Type: application/json" \ -d '{"code": "print(1 + 1)"}' Sandbox solutions like e2b and microsandbox give you isolated code execution—but that's it. You still need to build: | You build | With sandbox-only | With Tako VM | |---|---|---| | Job queue | Redis + Celery/Bull | Built-in | | Execution history | Postgres + schema | PostgreSQL included | | Retry logic | Custom code | Automatic | | Idempotency | Deduplication logic | idempotency_key | | Replay/debugging | Custom tooling | Rerun/fork API | Tako VM is the complete package: - Job queue + workers - Async execution with worker pool, no Redis/Celery setup - Execution history - Every job persisted with stdout, stderr, timing, artifacts - Replay to debug - Rerun past jobs with exact same code and inputs - Docker isolation - Each job in its own container with seccomp filtering - Network isolation - No network by default, optional allowlist per job type - Self-hosted - Your machine, offline-capable, zero per-execution cost tako-vm setup # Pull executor image and verify Docker tako-vm server # Start the API server tako-vm server --port 9000 # Custom port tako-vm dev up # Start local PostgreSQL for development tako-vm dev up --with-server # Start PostgreSQL + API server tako-vm dev status # Check local PostgreSQL status tako-vm dev down # Stop local PostgreSQL tako-vm config # Show current configuration tako-vm config --json # Output as JSON tako-vm validate # Validate current config tako-vm validate my.yaml # Validate specific file tako-vm status # Check server health tako-vm version # Show version tako-vm --config my.yaml server # Use specific config file | Topic | Link | |---|---| | Installation | docs/getting-started/installation.md | | Quick Start | docs/getting-started/quickstart.md | | Configuration | docs/getting-started/configuration.md | | REST API | docs/api/rest.md | | Python SDK | docs/api/sdk.md | | Job Types & Environments | docs/guide/environments.md | | Security | docs/deployment/security.md | | Deployment | docs/deployment/how-to-deploy.md | | Config Reference | tako_vm.yaml.example | Apache License 2.0

9

Pokemon Emerald Ported to WebAssembly (100k FPS)

Hacker News · original →
Comments
10

I’m one of the developers behind Sable, this is my new game! 🪐

r/indiegaming · original →
[image →] Hi guys! I’m Daniel, one of the creators of Sable. I’ve been working on my next project for a while behind the scenes now, and it’s finally ready to be shared. This is In the Drift, a…
[image →]

Hi guys! I’m Daniel, one of the creators of Sable. I’ve been working on my next project for a while behind the scenes now, and it’s finally ready to be shared. This is In the Drift, a dreamy narrative platformer about human connections and fixing the internet in space.

You play as a young engineer called Luna, whose job it is to maintain internet connections across humanity’s home asteroid belt. Affected by a phenomenon known as The Drift, these asteroids are slowly drifting apart and dispersing into space. It’s your job to drive across drifted asteroids in your truck, repairing rusted radio towers and other crumbling infrastructure in an attempt to keep people connected.

You’ll return home after each job, able to explore the space and connect with the rest of the crew. Learn their stories and uncover a narrative about finding your place in a slowly unravelling world.

I just announced the game in Wholesome today, would love to hear what you think of it! You can wishlist the game here if you like 💖

https://store.steampowered.com/app/4712630/In_The_Drift/

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