Claude: We Need to Talk About Message Limits

“You’ve reached 75% of your usage limit for this week.” must be familiar to quite a few people now.

The promise vs. the reality, especially when subscriptions start at $20/month is frustrating, to say the least.

Now don’t get me wrong, i still do think that Claude is a great tool, and it has helped me a lot in building a website. But the message limits make me hesitant about renewing my subscription at this point.

The “just switch to another model” argument doesn’t hold up.
“Hit the limit? No problem — here’s a lighter model to keep you going.”

Sure. Except that the lighter model doesn’t have the context of the last 40 messages you just built up ?

It doesn’t know you already ruled out Solution B or that you’re on Node 18, not 20. So you either start over, re-paste everything, or accept dramatically degraded output quality.

The limit doesn’t hit the casual user who fires off five prompts a week. It hits the person who has made AI a core part of their production workflow — the exact user these subscriptions were designed to attract.

Moreover, you never really know exactly where you stand until you’re blocked.
No progress bar. No “you’ve used 30% of your weekly allowance” warning. Just a hard stop at the worst possible moment. For anyone managing a deadline, this is genuinely disruptive.
Basic usage transparency shouldn’t be a premium feature.

“Just upgrade to the enterprise tier”

Some will say: pay more, get more. Fair enough in principle.
But the jump from individual to enterprise pricing isn’t a gradual scale — it’s a cliff.

The pricing architecture seems deliberately designed to push anyone with serious usage needs into an enterprise contract, rather than offering a middle tier that actually fits solo builders and small teams.
For developers bootstrapping products on their own, that’s a non-starter.

I’m not arguing that AI companies should run at a loss to serve unlimited queries. Compute costs are real. But i just think there’s a reasonable middle ground that needs to be found:
∙ Visible usage tracking — show me how much I’ve consumed in real time
∙ Rollover credits — unused capacity this week shouldn’t just evaporate
∙ Graceful degradation warnings — tell me I’m approaching the limit before I’m cut off mid-session
∙ Session continuity: if I do hit a cap, preserve context so I can resume without starting from scratch
None of these are technically impossible. They’re product decisions.

We’re paying for infrastructure. We deserve more clarity about what we’re actually buying.

I Built a PDF Splitter That Never Touches Your Files — Here’s How

Why another PDF tool? Because privacy shouldn’t be a premium feature.

We’ve all been there. You have a 40-page PDF report, your client needs pages 12–18, and the only tools you can find either slap a watermark on the output, cap your file size, or — most troublingly — upload your document to some server you’ve never heard of before “processing” it.
That last part should bother you more than it does.
I built iHatePDF’s Split PDF tool to solve exactly this problem. It’s fast, it’s free, it has no file size limit, and — most importantly — your files never leave your device. Not a single byte.
Here’s the full story.

The Problem with Most Online PDF Tools
Online PDF utilities are everywhere. But most of them share an uncomfortable architecture: you upload your file, it travels to a remote server, gets processed, and then gets sent back to you. Along the way, your document — which might contain contracts, medical records, financial data, or intellectual property — passes through infrastructure you don’t control and likely don’t understand.
Some tools are upfront about this. Many are not. And even the honest ones that promise to “delete your file after 1 hour” are asking you to take their word for it.
There’s a better way.

The Core Idea: Keep Everything in the Browser
Modern browsers are incredibly capable. Thanks to APIs like the File API, Web Workers, and libraries like pdf-lib, you can do serious PDF manipulation entirely on the client side — no server required.
This is exactly what the Split PDF tool does. When you upload a PDF:

It’s read into memory using the browser’s FileReader API as an ArrayBuffer.
pdf-lib parses the document and counts the pages.
When you hit “Split PDF,” the library creates new PDF documents, copies the relevant pages over, and generates downloadable byte arrays.
Those byte arrays are handed directly to your browser’s download mechanism.

At no point does the file travel over a network. The “server” is your own CPU.
javascriptconst buffer = await readFileAsArrayBuffer(file);
const { PDFDocument } = window.PDFLib;
const sourcePdf = await PDFDocument.load(buffer);
Three lines. That’s the entire “upload” step — and it never left your machine.

Two Ways to Split
The tool offers two splitting modes, designed to cover the most common real-world scenarios.

  1. By Page Ranges
    This is the power-user mode. You type something like 1-5, 10-15, 20 and the tool produces three separate PDF files — one for each range. It’s perfect for:

Breaking a book into chapters
Extracting a specific section of a report to share with stakeholders
Separating a combined invoice document into individual invoices

The range parser handles both ranges (1-5) and single pages (20) in the same input string, separated by commas. Clean and flexible.
javascriptconst parseRanges = (rangeStr) => {
const result = [];
for (const part of rangeStr.split(“,”).map((s) => s.trim())) {
if (part.includes(“-“)) {
const [start, end] = part.split(“-“).map((n) => parseInt(n.trim()));
if (!isNaN(start) && !isNaN(end) && start <= end)
result.push({ start: start – 1, end: end – 1 });
} else {
const num = parseInt(part);
if (!isNaN(num)) result.push({ start: num – 1, end: num – 1 });
}
}
return result;
};
Notice the – 1 offsets — PDF page indices are zero-based internally, but humans count from 1. Small detail, big UX impact.

  1. Individual Pages
    One click, and every page becomes its own PDF file. A 20-page document turns into 20 separate downloads. This is ideal for distributing slides, archiving scanned documents page by page, or just giving someone exactly the one page they asked for.
    To avoid overwhelming the browser’s download manager, individual page downloads are staggered with a 100ms delay between each one — a tiny but important UX consideration.

Handling Downloads Across Every Browser
Cross-browser file downloads sound trivial until you try to support Safari on iOS. The tool uses a layered download helper that tries progressively more compatible approaches:

A custom window.download function if available
The legacy msSaveOrOpenBlob for old Edge/IE
A programmatically clicked tag (the standard modern approach)
As a last resort, window.open() with a blob URL, with a prompt to allow pop-ups

iOS Safari gets a special callout UI element that reminds users to check their Files app → Downloads folder, since the native Safari download behavior differs from desktop browsers.
javascriptconst isIOSSafari = () => {
const ua = window.navigator.userAgent;
return (
(!!ua.match(/iPad/i) || !!ua.match(/iPhone/i)) &&
!!ua.match(/WebKit/i) &&
!ua.match(/CriOS/i)
);
};
Small touches like this are what separate a tool people actually use from a tool people abandon in frustration.

Local History Without a Backend
The tool tracks your recent splits using a hybrid storage strategy:

Metadata (filename, tool used, timestamp, size) goes into localStorage — lightweight and fast.
The actual PDF bytes go into IndexedDB — the browser’s structured data store, capable of handling large binary blobs.

This means you can revisit recent files without re-uploading anything, and it all works offline. No accounts. No sync. No data leaving your device.
javascriptconst addToHistory = async (pdfData) => {
const history = JSON.parse(localStorage.getItem(HISTORY_KEY) || “[]”);
const newEntry = { id: Date.now(), name: pdfData.name, tool: pdfData.tool, … };
if (pdfData.bytes) {
await dbSet(pdf_${newEntry.id}, pdfData.bytes); // IndexedDB
}
history.unshift(newEntry);
localStorage.setItem(HISTORY_KEY, JSON.stringify(history.slice(0, 50)));
};
The history is capped at 50 entries to keep storage usage reasonable. Pragmatic, not precious.

Quality Is Never Compromised
One concern people often have with PDF tools is quality degradation. This tool sidesteps the issue entirely — because there is no re-rendering happening.
pdf-lib doesn’t rasterize your pages into images and repack them. It copies the raw PDF page objects from the source document into the new document. The text stays as text. The vector graphics stay as vectors. The embedded fonts stay embedded. You get a byte-perfect extraction, not a screenshot of a page.

The Bigger Picture
This tool is part of a broader philosophy: your files are yours. The browser has become powerful enough that the reflexive “upload to server → process → download” pipeline is often unnecessary, and increasingly, it’s irresponsible.
Client-side PDF processing is just one example. The same principle applies to image compression, document conversion, data parsing, and dozens of other utility tasks that millions of people outsource to servers every day when they don’t have to.
As developers, we have a responsibility to ask: does this actually need to leave the user’s device? More often than the current ecosystem suggests, the answer is no.

Try It
If you’ve ever needed to split a PDF — and who hasn’t — give it a try. Upload a file, split it, and notice what doesn’t happen: no spinner while a server “processes” it, no email confirmation, no account wall, no watermark on the output.
Just your PDF, split the way you want it, in seconds, entirely on your machine.
That’s what PDF tools should have been all along.

Built with React, pdf-lib, and a deep distrust of unnecessary server round-trips. All processing happens locally in your browser — always.

Why UltrafastSecp256k1?

https://github.com/shrec/UltrafastSecp256k1
A detailed look at what sets this library apart — not just in speed, but in engineering discipline, audit culture, and verified correctness.

1. Audit-First Engineering Culture

Most high-performance cryptographic libraries ship fast code and trust that it is correct.
UltrafastSecp256k1 ships fast code and then systematically tries to break it.

The internal self-audit system is not a layer of unit tests bolted on after the fact —
it was designed in parallel with the cryptographic implementation, as a first-class engineering artifact.

The underlying philosophy is Bitcoin-style: don’t trust, verify. The project does
not center its trust model on a one-time PDF artifact written by someone else at a
fixed moment in the past. Instead, it tries to make assurance continuously rerunnable:
every important claim should be tied to code, tests, CI artifacts, benchmark logs, or
traceable documentation that another engineer can reproduce on demand.

This is why the audit framework keeps expanding with the codebase. The repository ships
not only tests, but also reviewer-facing infrastructure: structured audit artifacts,
threat-model docs, adversarial exploit tests, differential checks, and a repo-local
SQLite source graph that makes the codebase searchable as an audit surface rather than
just a pile of files.

These top-level differentiators are claim-keyed in the ledger: exploit-audit surface A-005, graph-assisted review A-006, self-audit transparency A-007, and benchmark reproducibility A-004 in docs/ASSURANCE_LEDGER.md.

What the Audit Infrastructure Covers

Area What is Tested Assertion Count
Field arithmetic (𝔽ₚ) Commutativity, associativity, distributivity, canonical form, carry propagation, batch inverse, sqrt 264,622
Scalar arithmetic (ℤ_n) Reduction mod n, overflow, GLV decomposition, negation, edge cases (0, 1, n−1) 93,215
Point operations Infinity handling, Jacobian↔Affine round-trip, scalar multiplication, 100K stress 116,124
Constant-time layer No secret-dependent branches, no secret-dependent memory access, formal CT verification 120,652
Exploit PoC tests 86 dedicated adversarial PoC tests across 14 coverage areas (audit/test_exploit_*.cpp) 86 test files, 0 failures
Fuzz / adversarial libFuzzer harnesses + 530K deterministic corpus adversarial checks ~530,000+
Wycheproof vectors Google’s cryptographic test vectors for ECDSA and ECDH Hundreds of vectors
Fiat-Crypto linkage Cross-validates field arithmetic against formally-verified Fiat-Crypto reference Full suite
FROST / MuSig2 KAT Protocol-level Known Answer Tests per BIP-327 and FROST spec Full suite
Fault injection Tests behaviour under simulated hardware faults (bit flips, counter skips) Full suite
ABI gate FFI round-trip stability, C ABI regression detection Full suite
Performance regression Automated micro-benchmark gate — fails CI if throughput regresses Every push
Nightly differential Random round-trip differential tests against reference implementations ~1,300,000+/night
Total (audit runner) unified_audit_runner across 55 modules plus standalone audit surfaces ~1,000,000+
Total (exploit PoC tests) 86 exploit-style PoC tests across 14 coverage areas, all in audit/test_exploit_*.cpp 86 tests, 0 failures

All 55 audit modules across all tested platforms return AUDIT-READY. Zero failures.
All 86 exploit PoC tests pass. Zero failures across all 14 coverage areas.

Self-Audit Documents

Document Purpose
AUDIT_GUIDE.md Navigation guide for external auditors — build steps, source layout, test commands
AUDIT_REPORT.md Historical formal audit report (v3.9.0): 641,194 checks, 0 failures
AUDIT_COVERAGE.md Current coverage matrix by module and section
THREAT_MODEL.md Layer-by-layer risk analysis — what is in scope and out of scope
SECURITY.md Vulnerability disclosure policy and contact
docs/CT_VERIFICATION.md Constant-time formal verification evidence and methodology
audit/AUDIT_TEST_PLAN.md Detailed test plan covering all 8 audit sections
audit/platform-reports/ Per-platform audit run results and logs
tools/source_graph_kit/source_graph.py SQLite-backed repository graph for fast impact tracing, audit scoping, and reproducible review
docs/ASSURANCE_LEDGER.md Canonical claim-to-evidence ledger for public trust statements
docs/AI_AUDIT_PROTOCOL.md Formal protocol for AI-assisted auditor/attacker review loops
docs/FORTRESS_ROADMAP.md Gap-closing roadmap for fortress-grade self-audit

2. CI/CD Pipeline — 24 Automated Workflows

The continuous integration pipeline is not a basic build-and-test gate.
It is a multi-layer quality enforcement system with 24 GitHub Actions workflows
covering security, correctness, performance, supply chain, and formal analysis.

It is also only one part of the assurance model. The repository is routinely reviewed
through external-style passes as if by auditors, attackers, and bug bounty hunters,
including LLM-assisted review loops that help surface edge cases, exploit ideas, and
documentation gaps. Those passes are not treated as magic or as a replacement for
deterministic tests; they are useful because they feed new cases back into the same
reproducible audit framework.

Workflow Index (selected)

Workflow What It Does Trigger
ci.yml Core build + full test suite across 17 configurations × 7 architectures × 5 OSes Every push / PR
preflight.yml Fast pre-merge smoke check — blocks merge on basic failures Every PR
nightly.yml Nightly stress: 1.3M+ differential checks, extended fuzz, full sanitizer run Nightly
security-audit.yml Runs the full unified_audit_runner (55 modules, ~1M assertions) plus sanitizer and warning gates Every push
audit-report.yml Generates and archives structured audit report artifacts On release / manual
ct-arm64.yml Constant-time verification on native ARM64 hardware Every push
ct-verif.yml Formal constant-time verification pass Every push
valgrind-ct.yml Valgrind memcheck + CT analysis on Linux x64 Every push
bench-regression.yml Performance regression gate — CI fails if throughput drops Every push
benchmark.yml Full benchmark suite — results published to live dashboard On push to dev/main
codeql.yml GitHub CodeQL static analysis (C++) Every push
clang-tidy.yml Clang-Tidy lint pass with project-specific rules Every push
cppcheck.yml CPPCheck static analysis Every push
sonarcloud.yml SonarCloud code quality and security rating Every push
mutation.yml Mutation testing — verifies test suite kills injected faults Scheduled
cflite.yml ClusterFuzz-Lite continuous fuzzing integration Every push
bindings.yml Tests all 12 language bindings (Python, Rust, Node, Go, C#, Java, Swift, …) Every push
dependency-review.yml Scans dependency changes for known vulnerabilities Every PR
scorecard.yml OpenSSF Scorecard supply-chain security scan Weekly
valgrind-ct.yml Valgrind constant-time path analysis Every push
docs.yml Docs build and deployment validation Every push
packaging.yml NuGet, vcpkg, Conan, Swift Package, CocoaPods packaging validation On release
release.yml Full release pipeline: build, sign, attest, publish On tag

Build Matrix Scale

Dimension Coverage
Configurations 17 (Release, Debug, ASan+UBSan, TSan, Valgrind, coverage, LTO, PGO, …)
Architectures 7 (x86-64, ARM64, RISC-V, WASM, Android ARM64, iOS ARM64, ROCm)
Operating systems 5 (Linux, Windows, macOS, Android, iOS)
Compilers GCC 13, Clang 17, Clang 21, MSVC 2022, AppleClang, NDK Clang

3. Static Analysis & Sanitizer Stack

Every commit is checked by multiple independent static and dynamic analysis layers:

Tool What It Catches
CodeQL Semantic security vulnerabilities, data-flow bugs
SonarCloud Code quality, security hotspots, cognitive complexity
Clang-Tidy Style violations, anti-patterns, performance issues
CPPCheck Memory errors, null dereferences, buffer overflows
ASan + UBSan Memory errors, undefined behaviour in CT paths
TSan Data races and threading issues
Valgrind memcheck Heap errors, uninitialized reads
Valgrind CT Constant-time path analysis via shadow value propagation
libFuzzer Corpus-driven bug finding in field, scalar, and point arithmetic
ClusterFuzz-Lite Continuous fuzzing integrated into CI

The -Werror flag is enforced — warnings are build failures.

4. Supply Chain Security

Cryptographic libraries are high-value supply chain targets.
UltrafastSecp256k1 applies the OpenSSF supply-chain hardening model:

  • OpenSSF Scorecard — automated weekly supply-chain health score
  • OpenSSF Best Practices badge — verified against the CII/OpenSSF criteria
  • Pinned GitHub Actions — all third-party actions pinned to commit SHA, not floating tags
  • Dependency Review — automated PR-level scan for vulnerable dependencies
  • Harden-runner — runtime monitoring of CI runner behaviour
  • Reproducible builds — Dockerfile.reproducible for bit-for-bit build verification
  • SBOM — software bill of materials generated on release
  • Artifact attestation — GitHub Artifact Attestation on release builds

5. Formal Verification Layers

Layer Method Status
Field arithmetic correctness Fiat-Crypto cross-validation (differential testing against formally-verified reference) Active
Constant-time (field/scalar) ct-verif tool + ARM64 hardware CI Active
Constant-time (point ops) Dedicated ct-arm64.yml pipeline + Valgrind shadow analysis Active
Wycheproof ECDSA/ECDH Google’s adversarial test vector suite Active
Fault injection Simulated hardware faults in signing/verification paths Active
Cross-libsecp256k1 Differential round-trip against Bitcoin Core’s libsecp256k1 Active

6. Performance — Verified, Not Just Claimed

Every benchmark number in this project is:

  • Produced by a pinned compiler version with exact flags documented
  • Reproducible via a published command in docs/BENCHMARKS.md
  • Gated by an automated performance regression check in CI (bench-regression.yml)
  • Published to a live dashboard on pushes to dev/main

Sample verified numbers (RTX 5060 Ti, CUDA 12):

Operation Throughput
ECDSA sign 4.88 M/s
ECDSA verify 4.05 M/s
Schnorr sign (BIP-340) 3.66 M/s
Schnorr verify (BIP-340) 5.38 M/s
FROST partial verify 1.34 M/s

Sample verified numbers (x86-64 rerun, i5-14400F, Clang 19):

Operation Latency
Generator multiplication (kG) 5.9 µs
Scalar multiplication (kP) 16.0 µs
ECDSA sign 7.8 µs
ECDSA verify 20.2 µs

7. What “Not Paid-Externally Audited” Actually Means Here

UltrafastSecp256k1 has not yet undergone a paid third-party professional audit.
That is a factual status note, not the center of the project’s security philosophy.
The project is open to external audit and continuously prepares evidence so outside reviewers can audit it at any time.
At the same time, it does not wait for a third party to begin strengthening correctness and security, and it does not outsource trust to a single PDF milestone.

However, “not externally audited” does not mean “unverified.” The internal quality infrastructure described in this document represents a systematic, multi-layer correctness assurance program that most open-source cryptographic libraries do not have:

  • Over 1,000,000 internal audit assertions executed on every build
  • 24 CI/CD workflows enforcing correctness, security, and performance on every push/PR plus scheduled assurance runs
  • Formal constant-time verification on two independent platforms
  • Supply-chain hardening at the OpenSSF standard
  • Nightly differential testing at 1.3M+ additional random checks per night

The honest summary:

This library does not rely on a paid-audit badge as its primary trust story.
It does rely on open self-audit, reproducible evidence, graph-assisted review, and reviewer-friendly verification so anyone can inspect and challenge the implementation.
External audit is welcomed, but assurance work already happens continuously through internal audit on every build, every push/PR gate, and every nightly extended run.

Summary Table

Quality Dimension Evidence
Mathematical correctness 473,961 audit assertions (field + scalar + point)
Constant-time guarantees ct-verif, ARM64 CI, Valgrind CT, 120K CT assertions
Adversarial resilience Wycheproof, fault injection, 530K+ fuzz corpus
Protocol correctness FROST/MuSig2 KAT, cross-libsecp256k1 differential
Memory safety ASan, TSan, Valgrind — every commit
Static analysis CodeQL, SonarCloud, Clang-Tidy, CPPCheck
Supply chain OpenSSF Scorecard, pinned actions, SBOM, artifact attestation
Performance regression Automated gate on every push
Build reproducibility Dockerfile.reproducible + pinned toolchains
Self-audit documentation AUDIT_GUIDE, AUDIT_REPORT, AUDIT_COVERAGE, THREAT_MODEL

https://github.com/shrec/UltrafastSecp256k1

Video Friday: Beep! Beep! Roadrunner Bipedal Bot Breaks the Mold

Video Friday is your weekly selection of awesome robotics videos, collected by your friends at IEEE Spectrum robotics. We also post a weekly calendar of upcoming robotics events for the next few months. Please send us your events for inclusion.

ICRA 2026: 1–5 June 2026, VIENNA
RSS 2026: 13–17 July 2026, SYDNEY
Summer School on Multi-Robot Systems: 29 July–4 August 2026, PRAGUE

Enjoy today’s videos!

“Roadrunner” is a new bipedal wheeled robot prototype designed for multi-modal locomotion. It weighs around 15 kg (33 lb) and can seamlessly switch between its side-by-side and in-line wheel modes and stepping configurations depending on what is required for navigating its environment. The robot’s legs are entirely symmetric, allowing it to point its knees forward or backward, which can be used to avoid obstacles or manage specific movements. A single control policy was trained to handle both side-by-side and in-line driving. Several behaviors, including standing up from various ground configurations and balancing on one wheel, were successfully deployed zero-shot on the hardware.

[ Robotics and AI Institute ]

Incredibly (INCREDIBLY!) NASA says that this is actually happening.

NASA’s SkyFall mission will build on the success of the Ingenuity Mars helicopter, which achieved the first powered, controlled flight on another planet. Using a daring mid-air deployment, SkyFall will deliver a team of next-gen Mars helicopters to scout human landing sites and map subsurface water ice.

[ NASA ]

NASA’s MoonFall mission will blaze a path for future Artemis missions by sending four highly mobile drones to survey the lunar surface around the Moon’s South Pole ahead of astronauts’ arrival there. MoonFall is built on the legacy of NASA’s Ingenuity Mars Helicopter. The drones will be launched together and released during descent to the surface. They will land and operate independently over the course of a lunar day (14 Earth days) and will be able to explore hard-to-reach areas, including permanently shadowed regions (PSRs), surveying terrain with high-definition optical cameras and other potential instruments.

For what it’s worth, Moon landings have a success rate well under 50%. So let’s send some robots there to land over and over!

[ NASA ]

In Science Robotics, researchers from the Tangible Media group led by Professor Hiroshi Ishii, together with colleagues from Politecnico di Bari, present Electrofluidic Fiber Muscles: a new class of artificial muscle fibers for robots and wearables. Unlike the rigid servo motors used in most robots, these fiber-shaped muscles are soft and flexible. They combine electrohydrodynamic (EHD) fiber pumps — slender tubes that move liquid using electric fields to generate pressure silently, with no moving parts — with fluid-filled fiber actuators. These artificial muscles could enable more agile untethered robots, as well as wearable assistive systems with compact actuation integrated directly into textiles.

[ MIT Media Lab ]

In this study, we developed MEVIUS2, an open-source quadruped robot. It is comparable in size to Boston Dynamics Spot, equipped with two LiDARs and a C1 camera, and can freely climb stairs and steep slopes! All hardware, software, and learning environments are released as open source.

[ MEVIUS2 ]

Thanks, Kento!

What goes into preparing for a live performance? Arun highlights the reliability testing that goes into trying a new behavior for Spot.

[ Boston Dynamics ]

In this work, a multi-robot planning and control framework is presented and demonstrated with a team of 40 indoor robots, including both ground and aerial robots.

That soundtrack though.

[ GitHub ]

Thanks, Keisuke!

Quadrupedal robots can navigate cluttered environments like their animal counterparts, but their floating-base configuration makes them vulnerable to real-world uncertainties. Controllers that rely only on proprioception (body sensing) must physically collide with obstacles to detect them. Those that add exteroception (vision) need precisely modeled terrain maps that are hard to maintain in the wild. DreamWaQ++ bridges this gap by fusing both modalities through a resilient multi-modal reinforcement learning framework. The result: a single controller that handles rough terrains, steep slopes, and high-rise stairs—while gracefully recovering from sensor failures and situations it has never seen before.

That cliff behavior is slightly uncanny.

[ DreamWaQ++ ]

I take issue with this from iRobot:

While the pyramid exploration that iRobot did was very cool, they did it with a custom made robot designed for a very specific environment. Cleaning your floors is way, way harder. Here’s a bit more detail on the pyramids thing:

[ iRobot ]

More robots in circus please!

[ Daniel Simu ]

MIT engineers have designed a wristband that lets wearers control a robotic hand with their own movements. By moving their hands and fingers, users can direct a robot to perform specific tasks, or they can manipulate objects in a virtual environment with high-dexterity control.

[ MIT ]

At NVIDIA GTC 2026, we showcased how AI is moving into the physical world. Visitors interacted with robots using voice commands, watching them interpret intent and act in real time — powered by our KinetIQ AI brain.

[ Humanoid ]

Props to Sony for their continued support and updates for Aibo!

[ Aibo ]

This robot looks like it could be a little curvier than normal?

[ LimX Dynamics ]

Developed by Zhejiang Humanoid Robot Innovation Center Co., Ltd., the Naviai Robot is an intelligent cooking device. It can autonomously process ingredients, perform cooking tasks with high accuracy, adjust smart kitchen equipment in real time, and complete post-cooking cleaning. Equipped with multi-modal perception technology, it adapts to daily kitchen environments and ensures safe and stable operation.

That 7x is doing some heavy lifting.

[ Zhejiang Lab ]

This CMU RI Seminar is by Hadas Kress-Gazit from Cornell, on “Formal Methods for Robotics in the Age of Big Data.”

Formal methods – mathematical techniques for describing systems, capturing requirements, and providing guarantees – have been used to synthesize robot control from high-level specification, and to verify robot behavior. Given the recent advances in robot learning and data-driven models, what role can, and should, formal methods play in advancing robotics? In this talk I will give a few examples for what we can do with formal methods, discuss their promise and challenges, and describe the synergies I see with data-driven approaches.

[ Carnegie Mellon University Robotics Institute ]

Why I Ripped stream.pipe() Out of My Node.js API Gateway

Terminal screenshot showing 18 Jest network tests passing flawlessly in 2.7 seconds.

When I started building Torus, a multi-core Layer 7 Edge API Gateway from scratch in Node.js, I handled incoming network requests the way I had always seen it done in standard web applications:

TypeScript

let body = '';
req.on('data', (chunk: Buffer) => {
  body += chunk.toString();
});
req.on('end', () => {
  forwardToBackend(body);
});

It worked perfectly for lightweight tests. But as I started pushing concurrent loads and larger payloads through the proxy, my server began to choke. CPU usage spiked to 100%, the event loop lagged, and memory consumption grew uncontrollably until the process crashed.

I had fallen into a classic architectural trap: I was dragging raw TCP payload bytes directly into the V8 JavaScript engine’s memory heap.

Because the V8 heap has a strict memory limit, pulling massive payloads into user-space memory forces the Node.js Garbage Collector (GC) to work overtime. The GC halts the single-threaded event loop to clean up the allocated memory, effectively stalling every other active network connection in the proxy.

I learned a fundamental rule of proxy engineering the hard way:

Proxies shouldn’t read data; they should just move it.

To build a production-grade gateway, I realized I had to bypass the V8 heap entirely. I needed to keep the data in raw C++ memory blocks and move it to the Operating System level. But as I refactored my routing logic to achieve this, I stumbled into a silent, catastrophic flaw in the standard Node.js stream API that brought my entire test suite to a halt.

The First Evolution: Bypassing V8 with .pipe()

The architectural fix required a fundamental shift in how I viewed the data. I had to stop treating payloads as static variables and start treating them as flowing water.

I didn’t need to load an entire 50MB file into memory before forwarding it. I only needed to hold a few kilobytes in a temporary buffer, flush it to the destination, and reuse that memory space.

In Node.js, this is exactly what the node:stream module and Buffer objects are designed for.

A Buffer in Node.js allocates memory outside the V8 JavaScript engine. It utilizes raw C++ memory blocks mapped directly to the OS. By keeping the network chunks as raw Buffers, the payload never enters the JavaScript heap. Because it never enters the heap, the V8 Garbage Collector completely ignores it, leaving the event loop free to handle other connections.

To wire this up, I utilized the native .pipe() method to connect the readable client stream to the writable backend stream:

TypeScript

// Connects the incoming ReadableStream directly to the outgoing WritableStream
clientReq.pipe(proxyReq);

This single line of code acts as an OS-level plumbing system. It takes the incoming TCP stream, reads the raw C++ buffers, automatically manages the backpressure (ensuring a fast client doesn’t overwhelm a slow backend connection), and pushes the bytes directly out to the routing pool.

My CPU usage plummeted. The memory footprint stayed flat, regardless of how large the incoming payloads were. It felt like I had solved the scaling problem entirely.

But .pipe() was hiding a massive, silent vulnerability.

The Plot Twist: The Silent Socket Leak

I thought I had engineered the perfect solution. The proxy was fast, the CPU was idle, and the memory footprint stayed completely flat, regardless of payload size.

Then I ran my integration test suite.

All the assertions passed. I got the green checkmarks. But the terminal just froze. Jest refused to exit, eventually spitting out that infuriating warning: “Jest did not exit one second after the test run has completed.”

My initial reaction was to treat it like a standard web app bug. I meticulously checked my teardown logic, making sure proxyServer.close() was being called and my Redis clients were fully disconnected. I ran the tests again. It still hung.

I had to drop down to the OS level to understand what was actually happening. The Node.js event loop is mathematically programmed to never exit as long as there is an active I/O handle (like a net.Socket) in its queue. Something was keeping a socket alive.

The culprit was .pipe().

When my Jest test fired a dummy request through the proxy and then disconnected, the client-side socket closed gracefully. But I learned a lesson about Node.js streams: .pipe() blindly pushes data; it does not propagate lifecycle events.

When the client dropped, .pipe() did not send an error or close event to the destination stream. It left the backend connection completely open. The proxy was sitting there holding a dead connection to the backend, waiting for network bytes that would never arrive.

I had built a machine that generated half-open sockets. In a production environment, this would silently exhaust the Operating System’s File Descriptors (FDs). Every dropped client connection would permanently lock up an FD until the OS hit its limit and violently crash the Node process with an EMFILE error.

The Fix: stream.pipeline()

The Node.js core maintainers knew .pipe() was dangerously naive for production infrastructure. That is exactly why they introduced stream.pipeline().

Instead of blindly shoving data from one socket to another, .pipeline() acts as a unified state machine that monitors the entire stream chain. It pushes the responsibility of socket teardown back to the Node.js core networking stack where it belongs.

If any stream in the pipeline fails, throws an error, or abruptly closes (like a client dropping off with an ECONNRESET), .pipeline() automatically intercepts it. It destroys all other connected streams in that specific chain and bubbles up a single error for you to catch.

I removed every instance of .pipe() and the dozens of lines of manual .on('error') spaghetti I had written. Because raw TCP proxying requires bidirectional data flow, I replaced it with two parallel, sequential pipelines:

TypeScript

try {
  await Promise.all([
    pipeline(clientSocket, backendSocket),
    pipeline(backendSocket, clientSocket)
  ]);
} catch (err: any) {
  // If either side drops, the pipeline throws, and we clean up natively.
  clientSocket.destroy();
  backendSocket.destroy();
}

The moment I swapped to this architecture and ran my integration suite, the terminal didn’t hang. Jest executed all 18 network tests and exited flawlessly in 2.7 seconds. The event loop was instantly cleared. The silent socket leak was completely eradicated.

Terminal screenshot showing 18 Jest network tests passing flawlessly in 2.7 seconds.

Conclusion: Trust Nothing, Understand Everything

Building a multi-core Edge Gateway from scratch taught me that I cannot blindly trust high-level abstractions.

stream.pipe() looks elegant in a standard web tutorial, but in the trenches of raw TCP networking, it is a massive liability. If you are building infrastructure that handles thousands of concurrent connections, you must understand the Operating System-level lifecycle of your File Descriptors and your sockets. If you don’t, your system will slowly bleed to death under load, and logs won’t even tell you why.

If you want to see the exact implementation of this bidirectional TCP routing, you can check out the raw source code for Torus Proxy on my GitHub.

From Alignment to Hitboxes: The Full 2D Pixel Art Character Pipeline (Week of March 24)

This post originally appeared on the Makko AI blog.

Most pixel art tutorials treat alignment, anchor points, debug positioning, and hitboxes as four separate topics. This week we treated them as one. Every piece of content built directly on the last, covering the complete pipeline any solo developer needs to get a 2D character working correctly in a game engine.

We are walking through this week in reverse, starting with Friday’s payoff and working backwards to show how each day’s content set it up. This is part of the broader one character, two games series — showing how a single 2D character created in Makko Art Studio can power completely different games without rebuilding the art from scratch.

Friday: hitbox alignment, the payoff of the whole pipeline

Friday’s video is the fourth episode in the Horror Platformer series featuring Granny’s Night-Terror and its playable character Grandma Elara. It is also the payoff of everything this week built toward.

Attacks that miss enemies standing directly in front of the player. A character that clips through geometry it should fit through. These are the hitbox problems that make a 2D game feel broken even when the art, animation, and code are all technically correct. The cause is almost always the same: a hitbox configured for the wrong animation state, sized to the maximum extent of the character rather than the majority state, or never updated after the animation was changed.

The video walks through configuring hitboxes per animation state in Makko’s Alignment Editor. The core rule: fit the hitbox to the majority state of the animation, not the maximum extent. A character whose arm extends forward during an attack should not have a hitbox that covers the fully extended position for every frame of the cycle. That produces hits that register before the animation looks like a hit, which feels wrong even if the player cannot articulate exactly why.

The episode closes the full series arc: one pixel art character, two games, zero duplication. Everything from alignment to hitboxes, built once, configured per game through the manifest system.

Thursday: debug collision boxes, making the invisible visible

Hitbox configuration only works if you can see what the engine is doing. Floating or buried sprites are almost never a pure art problem. They are a positioning problem, and you cannot fix what you cannot see.

Enabling visual debug collision boxes during runtime makes the engine’s understanding of your character visible. If the collision box is centered instead of aligned to the feet, that is the problem. If the box is not moving with the sprite, that is the problem. If the box is sized for one animation state but not updated for another, that is where attacks miss and characters clip through geometry they should pass through cleanly.

The fix is always the same: drag, reposition, lock it in, test again. You need to see what the engine sees before you can configure hitboxes correctly.

Wednesday: anchor points, the single pixel that controls everything

Before you can diagnose positioning with debug boxes, the anchor point has to be set correctly. An anchor point is the single pixel the engine uses to calculate position, rotation, and collision.

Most engines default to the center of the sprite rather than the feet. The result is characters that float above the ground by exactly half their height, sink into the ground by exactly half their height, or jitter unpredictably between animation frames. None of those are art problems. They are anchor point problems.

Makko lets you set the anchor point once at the manifest level and it updates automatically across every frame in every animation state. This is a small thing that has a large practical effect on how long it takes to get a 2D character feeling right in-engine.

Tuesday: two posts, one underlying question

Tuesday was the heaviest publishing day of the week. Two posts, two completely different angles on the same underlying question: what does it actually take to get game-ready art out of an AI tool and into a working 2D game?

The Art Studio deep dive answered the workflow question directly. Most solo developers are running four separate tools just to get one character into their engine. Makko Art Studio replaces that entire stack. Describe what you want, and the output arrives with transparent backgrounds, animation frames, and the correct file format already handled.

The second post was a devlog from Tony Valcarcel, one of Makko’s co-founders, documenting how he built over 100 unique card assets for Sector Scavengers, a roguelike salvage game, in 7 days for under $500 with no dedicated artist on the team.


favicon
blog.makko.ai


favicon
blog.makko.ai

Monday: character alignment, where the pipeline starts

Everything this week traced back to Monday’s post. Perfect art and animation can still look completely wrong in-engine if alignment is off. A character that floats above platforms, sinks into the ground, or shifts position between animation frames is almost never an art problem. It is an alignment problem.

Monday’s post established the three variables that have to work together: anchor point, scale, and position. Makko’s manifest puts all three in a single editor so you can see exactly what you are changing and what effect it has before you commit.

If alignment is wrong at the manifest level, no amount of correct anchor point or hitbox work will fix how the character behaves in-game.

The complete pipeline in order

Step 1: Alignment. Anchor point, scale, and position must be correct at the manifest level first.

Step 2: Anchor point. Set the anchor to the character’s feet. Set it once and it propagates across every frame automatically.

Step 3: Debug collision boxes. Enable them during runtime before configuring hitboxes. Diagnose rather than guess.

Step 4: Hitboxes per animation state. Fit to the majority state, not the maximum extent. Test with debug boxes active.

Everything published this week

Start Building Now at Makko AI

For technical walkthroughs and live demos, visit the Makko YouTube channel.

JsonMaster vs JSONFormatter vs JSONLint — Which JSON Tool Should You Use in 2026?

There are dozens of online JSON tools. Most developers just use the first result on Google and stick with it. But they are not all equal — especially when it comes to privacy, editor quality, and feature count.

I compared the four most popular tools so you don’t have to.

The Tools

  • JsonMaster → https://jsonmaster.netlify.app/
  • JSONFormatter.org → jsonformatter.org
  • JSONLint → jsonlint.com
  • JSON Editor Online → jsoneditoronline.org

Feature Comparison

Feature JsonMaster JSONFormatter JSONLint JSON Editor Online
JSON Formatter ✅ ✅ ✅ ✅
JSON Validator ✅ ✅ ✅ ✅
JSON Minifier ✅ ✅ ❌ ✅
JSON to YAML ✅ ✅ ❌ ❌
JSON to CSV ✅ ✅ ❌ ❌
JSON to TypeScript ✅ ❌ ❌ ❌
JSON to Zod Schema ✅ ❌ ❌ ❌
JWT Decoder ✅ ❌ ❌ ❌
Base64 Encoder/Decoder ✅ ❌ ❌ ❌
Regex Tester ✅ ❌ ❌ ❌
JSON Diff / Compare ✅ ❌ ❌ ✅
Duplicate Key Detector ✅ ❌ ❌ ❌
Monaco Editor (VS Code engine) ✅ ❌ ❌ ❌
Dark Mode ✅ ❌ ❌ ✅
100% Client-side ✅ ❌ ❌ ❌
No ads ✅ ❌ ❌ ❌

Privacy — The Biggest Difference

Most developers paste real API responses, JWT tokens, or production configs into these tools without thinking about it.

JsonMaster processes everything in your browser. Open DevTools → Network tab while using it — you will see zero outgoing requests for your data.

JSONFormatter.org, JSONLint, and JSON Editor Online all process data server-side or run third-party analytics that may capture your input. When you paste a JWT or a database export into those tools, it leaves your machine.

Editor Quality

JSONLint uses a plain <textarea>.
JSONFormatter.org uses CodeMirror.
JsonMaster uses Monaco Editor — the same engine that powers VS Code.

With Monaco you get inline error markers, code folding, find & replace (Ctrl+F), multi-cursor editing, and the keyboard shortcuts already in your muscle memory. For developers who spend hours in VS Code daily, this is not a small thing.

When to Use Each Tool

Tool Use it when…
JsonMaster You want privacy + multiple tools in one tab + VS Code-quality editing
JSONLint You only need a one-off syntax check, nothing else
JSONFormatter.org You need JSON→CSV and don’t have privacy requirements
JSON Editor Online You need to visually navigate a large JSON tree

Verdict

For day-to-day developer work — debugging API responses, converting formats, decoding JWTs, testing regex — JsonMaster is the most complete and private option.

The Monaco editor alone makes it worth switching from any textarea-based tool.

Try it free → https://jsonmaster.netlify.app/

No login. No ads. No server.

I Built a Free PDF Tool from Nepal — Here’s What I Learned

I’m a full-stack developer based in Nepal and I just launched PrestigePDF — a completely free, no-signup online PDF toolkit with 22+ tools built with React, TypeScript, and WebAssembly.

Here’s the story, the tech, and what I learned building it.

Why I Built It

Tools like ilovepdf and smallpdf are great but they push you toward paid plans fast — file size limits, watermarks, forced signups. I wanted something genuinely free with no limits for basic operations and no account required.

Also, being from Nepal, I wanted to prove that quality developer tools can be built and used globally from anywhere. The “Built from Nepal, used globally” badge on the About page is something I’m genuinely proud of.

What PrestigePDF Does

Everything you’d normally need Adobe Acrobat for — free, in your browser:

  • Merge PDF — combine multiple files into one
  • Compress PDF — reduce file size without quality loss
  • Split PDF — extract specific pages or ranges
  • PDF to Word / Excel / JPG — convert to any format
  • Edit PDF — add text, images, annotations
  • Protect / Unlock PDF — password management
  • Watermark, Rotate, Crop, Number Pages — and more

👉 Try it free at prestigepdf.com

The Tech Stack

  • Frontend: React + TypeScript + Tailwind CSS + Vite
  • PDF Processing: qpdf-wasm, PDF.js, jsPDF
  • Hosting: Contabo VPS + Docker + Nginx
  • Storage: AWS S3 for temporary file handling

The Hardest Part — PDF Processing in the Browser

The biggest challenge was making PDF operations fast and private. Most operations run client-side using WebAssembly (qpdf-wasm), meaning files never leave your device for most tools. This is a real privacy win compared to many competitors that upload everything to their servers.

Getting qpdf-wasm to work correctly with Vite took a couple of days of debugging — WASM workers, CORS headers, memory limits — all fun stuff.

Blog + SEO

I also built a blog section targeting long-tail keywords like “how to merge PDFs online free 2026”. Since the site is brand new, I’m focused on blog content and backlinks right now before worrying about paid growth.

What’s Next

  • AI PDF features (summarize, Q&A with your PDF)
  • More conversion formats
  • Browser extension
  • Mobile app

Try It + Feedback Welcome

If you work with PDFs regularly, I’d genuinely appreciate you giving it a try and dropping feedback in the comments. Early feedback from developers is gold.

→ Visit PrestigePDF

Built with ❤️ from Nepal 🇳🇵

65% of MCP Tools Now Take Actions. 16 Months Ago It Was 27%.

A new preprint analyzed 177,436 MCP tools deployed between November 2024 and February 2026. The headline number: action tools — tools that directly modify external environments — went from 27% to 65% of total MCP tool usage in 16 months.

That’s a 2.4x increase in the share of tools that do things to the world, not just read from it.

The study is “How are AI Agents Used? Evidence From 177,000 MCP Tools” by Merlin Stein. It’s the first large-scale empirical analysis of what agents are actually doing through MCP — not what we think they’re doing, not what demos show, but what 177,000 deployed tools reveal about real-world agent behavior.

From Reading to Writing

The paper classifies MCP tools into three categories: perception (read data), reasoning (analyze data), and action (modify external environments).

In late 2024, agents were mostly reading. Perception tools dominated. The typical MCP server was a data access layer — agents queried databases, read files, fetched API responses.

By February 2026, the balance had inverted. 65% of tools now take actions: editing files, sending emails, creating records, executing transactions. Software development alone accounts for 67% of all tools and 90% of downloads — and those tools write code, modify repositories, and deploy changes.

The paper specifically flags “action tools for higher-stakes tasks like financial transactions” alongside medium-stakes tasks like file editing and drone steering. The trajectory is clear: agents are gaining capability to affect financial, physical, and organizational systems.

Every Action Tool Is a Trust Boundary

When an agent reads your database, the risk is data exposure. When an agent edits your files, sends emails on your behalf, or initiates a financial transaction — the risk is unauthorized action in the real world.

The distinction matters because the security model is fundamentally different:

  • Read tools need access control: who can see what?
  • Action tools need authorization: who approved this specific action, and is there a record?

At 27% action tools, you could treat MCP as a data access layer with occasional writes. At 65%, you can’t. The majority of agent tool calls are now modifying external state. Each one is a potential security event — a moment where something irreversible happens, and someone needs to be accountable for it.

The Paper Agrees: Monitor at the Tool Layer

The study’s own conclusion lands exactly here. Stein proposes that “governments and regulators can use this monitoring method to extend oversight beyond model outputs to the tool layer to monitor risks of agent deployment.”

Beyond model outputs. To the tool layer.

This is the right framing. Model-level safety (RLHF, constitutional AI, output filtering) governs what the model says. Tool-layer monitoring governs what the agent does. When 65% of tools modify external environments, model outputs are not the attack surface that matters — tool calls are.

What Tool-Layer Authorization Looks Like

The paper identifies the problem. The solution is an approval gate and an audit trail at the point where agents take action.

Before the action: An authorization check. Did a human or a policy approve this specific tool call? Not “is this agent generally allowed to use email” — but “is this agent allowed to send this email to this recipient right now?”

After the action: A signed record. Which agent, which tool, which inputs, what time. Tamper-evident. Exportable. Independently verifiable by an auditor who wasn’t present when the action occurred.

This is what AgentLair provides. Every agent action passes through an approval gate. Every approved action is recorded in an Ed25519-signed, hash-chained audit log. The trail leads from tool call to agent to human owner.

At 27% action tools, this was a nice-to-have. At 65%, it’s infrastructure.

Data source: Stein, M. “How are AI Agents Used? Evidence From 177,000 MCP Tools.” arXiv:2603.23802, March 2026. 177,436 tools analyzed across 16 months (November 2024 – February 2026).

Stop Switching Tabs — One Free Tool Replaces All Your JSON & Dev Tools

Every day I was doing the same thing:

  • Paste API response into some random formatter
  • Open another tab to decode the JWT
  • Open another tab for Base64
  • Open another tab to test a regex

Four tabs. Same tools. Every single day.

So I built JsonMaster — a free developer toolbox that puts 12 tools in one tab.

👉 https://jsonmaster.netlify.app/

No login. No ads. Your data never leaves your browser.

What’s Inside

JSON Formatter & Validator

Paste raw minified JSON and instantly see it beautified. Built on Monaco Editor — the same engine as VS Code — so you get syntax highlighting, inline error squiggles, code folding, and keyboard shortcuts you already know.

JSON Converters

Convert JSON to:

  • YAML — for Kubernetes, Docker Compose, GitHub Actions
  • CSV — for Excel, Google Sheets, data pipelines
  • XML — for legacy systems and SOAP APIs
  • TypeScript Interface — paste an API response, get a typed interface instantly
  • Zod Schema — instant runtime validation schema for TypeScript projects
  • .env file — flatten nested JSON config into environment variables

JWT Decoder

Paste any JWT. See header, payload, signature decoded instantly. Checks expiry and algorithm. Everything happens in your browser — nothing is sent to a server.

Base64 & URL Encoder / Decoder

Encode or decode Base64 and URL strings instantly. Handles Unicode correctly. Useful for decoding auth headers, query strings, and embedded images.

Regex Tester

Write a pattern, test it against your input in real time. Every match is highlighted. Supports all JS regex flags: g, i, m, s, u. Shows match groups and count.

JSON Diff & Compare

Paste two JSON objects. See exactly what was added, removed, or changed — down to the specific key path. Useful for comparing API responses before and after a deploy.

Why Client-Side Matters

Most JSON tools send your data to a server. You paste a JWT or production API response — it travels over the network to someone’s backend.

JsonMaster is 100% client-side. Open DevTools → Network tab while using it. You will see zero outgoing requests for your data.

This matters when you’re working with JWT tokens, API responses with user data, or config files with credentials.

Try it free → https://jsonmaster.netlify.app/

Drop a comment if you find a bug or want a new tool added. I read everything.