7032 stories
·
166 followers

Fat Tire Brakes Get Wireless Upgrade

1 Comment

At first glance, wireless brakes seem like a recipe for disaster. For something as critical as braking, many bicyclists might prefer a physical connection to their method of safely controlling speed. But there are a number of surprising benefits of electronic or wireless braking systems. For one, they can enable systems like anti-lock braking systems and for another they can eliminate cabling or hydraulics on a bicycle. For these reasons, and just for the thrill of it, [Berm Peak] built a set of wireless brakes for his fat tire bicycle to test out the possibilities.

The system uses a set of ESP32 microcontrollers to handle inputs from the braking lever and outputs to the front and rear brakes, as well as a central control unit and display. The brakes themselves are controlled by actuators from car door locks, which when combined with the springs from the stock calipers work to apply a wide range of braking force to the wheels. These did take a bit of prototyping to get working right, by changing to higher quality calipers, increasing the angle of the actuator, and adding longer levers, but eventually a working braking system started to appear.

But replacing a hydraulic system with an electronic one isn’t where something like this shines. [Berm Peak] was able to add in a number of features impossible in traditional braking systems. Not only does this have an ABS system and the possibility to remotely slow down his children’s bikes when they’re riding, but there’s also a braking equalizer that allows the rider to control how much braking there is at certain positions of the brake lever, and another setting called “derp” which doesn’t engage the brakes at all until a certain threshold has passed. This might end up being the next big trend in mountain biking, unlike airless tires.

Read the whole story
jepler
5 hours ago
reply
I'll join the chorus of "no never"s from over here.
Earth, Sol system, Western spiral arm
Share this story
Delete

Your AGENTS.md file doesn’t actually do anything

2 Comments

AI coding bot vendors tell you to use a context file with instructions for the chatbot on how to edit your project. Claude Code wants a CLAUDE.md, or there’s AGENTS.md in general. [Anthropic]

But does your AGENTS.md do anything? A team at ETH Zurich tested AGENTS files. They ran the bots over some test projects with and without AGENTS.md: [arXiv, PDF; presentation, video]

Surprisingly, we find that providing context files does not generally improve task success rates, while increasing inference cost by over 20% on average. This observation holds across different LLMs, coding agents, and for both LLM-generated and developer-committed context files.

A chatbot-generated AGENTS file makes the coding agent succeed at coding tasks about as well as having no AGENTS file — or slightly worse. A human-written AGENTS file gives slightly better success rates, but not much better.

Having an AGENTS.md increases the token cost quite a lot — whether the file is chatbot-generated or human-written. (Anthropic probably considers this a feature.) The bot churns through more stuff, but it’s no more likely to finish your task successfully.

Overviews of the file structure of the code repository are not useful to the agent. They don’t help the bot get on with editing the listed files any faster.

Does the AGENTS file do anything? If you mention particular tools in the AGENTS file, the coding agent will use them more often. That’s about it.

So when Anthropic recommended CLAUDE.md, they clearly didn’t measure if the instruction file actually does anything. They just chucked it in as a magical incantation you can invoke so you can hope the robot gets it right. This time. At least you might feel like you’re doing something.

This is very like how Anthropic writes Claude Code, which is mostly a pile of magical incantations telling the robot not to screw up yet again. Anthropic doesn’t know any other way to steer the bot.

The researchers’ recommendation: keep the instructions short. Be minimal. Or, of course, you could write a nice long file and chug through those tokens!

The closest anyone can come to a use for the AGENTS.md file is so you clarify your own thinking on how the project works, One developer on Reddit said: [Reddit, archive]

The actual token-level context it provides matters less than the fact that writing it forces you to articulate things about your codebase that were previously just in your head.

Yeah, that’s what we used to call writing. Be right back, just starting the project wiki. I call it HUMANS.md.

Read the whole story
jepler
1 day ago
reply
BRB writing the word "DEVELOPERS" repeated 112 times in AGENT.md
Earth, Sol system, Western spiral arm
tante
2 days ago
reply
Researchers at ETH Zurich show that "Agents.md" files don't do much. "AI" is cosplay all the way down.
Berlin/Germany
Share this story
Delete

3D-Printed Skin Gives Robots the Sensation of Touch

1 Comment
Schematic diagram of the touch-sensitive skin. (Credit: Haofeng Chen et al., ArXiv, 2026)
Schematic diagram of the touch-sensitive skin. (Credit: Haofeng Chen et al., ArXiv, 2026)

Hypoesthesia, more commonly referred to as numbness, is one of the more distressing ailments that can affect us humans, primarily because it reminds us of just how much we rely on our sensation of touch in daily life. From experiencing the world around us, handling objects, noticing when you just bumped into that side table again and the comforting hug of a fellow human being, touch is perhaps the most important of our senses.

In that regard the recently published research by [Haofeng Chen] et al. on giving robots a skin that can experience touch seems rather important as it would give especially humanoid robots a more natural way to interact with their environment, using feedback from touch.

Poking the artificial skin. (Credit: Chen et al., arXiv, 2026)
Poking the artificial skin. (Credit: Chen et al., arXiv, 2026)

One of the essential parts of biological skin is that it is teeming with sensors, at a density level that provides excellent resolution as required, down to sensing e.g. small surface imperfections with one’s finger tips. Replicating this with an artificial skin for robotics has always been a problem, due to the wiring and/or reliability nightmare this poses with typical approaches. Instead of focusing on many individual sensors, [Chen] et al. focused on effectively creating the equivalent of a resistive touch screen in skin format.

The basic principle underlying the demonstrated artificial skin is electrical impedance tomography (EIT), which uses surface electrodes to form a tomographic image based on measures electrical resistivity. Core here is the flexible TPU layer with electrodes and the conductive fabric patches attached to the top TPU cover layer. The electrodes continuously measure the resistivity, with disturbances from those patches due to touch events on the cover layer altering these values. From this EIT can be used to reconstruct the location and strength of the touch event.

The results from the created prototypes were promising, with only 16 electrodes sufficing to create a fairly accurate pressure map. Hardware-wise this makes it thus quite uncomplicated, with the characterization of the TPU porosity and such along with the EIT algorithm (provided in the paper) probably being the biggest hurdles for hobbyist recreations.

Read the whole story
jepler
5 days ago
reply
congratulations, you've invented resistive touchscreens. maybe with multitouch, which is cool since resistive touchscreens never supported it?
Earth, Sol system, Western spiral arm
Share this story
Delete

Linux Fu: Improving FTP

1 Comment

FTP isn’t exactly cutting-edge technology. These days, if you control both ends of a connection, you’re probably using scp, SFTP, rsync, or something even fancier. But FTP refuses to die, especially if you are perusing old public FTP servers or talking to retrocomputers. Every now and then, you still need an FTP client. Naturally, there are plenty of graphical clients. But some of us would rather stay at the command line. You could just type ftp, of course. It works, and if you haven’t used it lately, it is probably better than you remember. However, I’ve long been a fan of NcFTP. While some other FTP clients have caught up, it still has unique features that make FTP a lot more productive.

Not Your Father’s FTP

Before maligning the standard ftp command, though, we should point out that it probably isn’t the FTP client you remember from 30 years ago. For example, on openSUSE Tumbleweed, /usr/bin/ftp is really tnftp, a portable version of NetBSD’s enhanced FTP client. Debian uses it too; the ftp package in both Bookworm and Trixie leads you to tnftp. Since current Raspberry Pi OS is based on Debian Trixie, you’ll encounter tnftp there, too. That’s significant because tnftp has already fixed many of the irritations you might associate with old-fashioned FTP.

You get command-line editing, history, and filename completion, things that are also in ncftp. Both understand passive FTP and IPv6. The tnftp client can also retrieve HTTP, HTTPS, and file: URLs, so commands such as:

ftp https://example.com/something.tar.gz

aren’t necessarily typos, although ncftp lacks this ability. But ncftp does have some killer features.

Remember Me?

One of NcFTP’s nicest creature comforts is bookmarks. Connect to a machine, move to a useful directory, and save it:

ncftp /pub/micros> bookmark oldstuff

Then later you can simply type:

ncftp oldstuff

The bookmark can remember more than just the hostname, making frequently used FTP sites feel much more like named resources than anonymous servers you repeatedly have to navigate.

NcFTP also maintains a cache of remote directory listings. If you’ve ever used FTP over a slow link, you know how annoying it is to ask for the same directory listing over and over. NcFTP can often work from what it already knows instead. Neither feature sounds earth-shattering, but together they make an interactive FTP session considerably more pleasant.

Get All The Things

Another difference becomes obvious when you want an entire directory. NcFTP supports recursive transfers:

get -R foo

or:

put -R foo

That seems obvious if you’re accustomed to modern tools, but traditional FTP is fundamentally organized around transferring individual files. NcFTP does the tedious directory walking for you. It also handles resuming interrupted transfers more naturally, something particularly welcome when the file in question is a multi-gigabyte disk image rather than README.TXT. With tnftp, you have to explicitly ask to resume an interrupted file. NcFTP will detect it and, depending on configuration, either resume or, at least, offer to resume the transfer.

Go Away, I’m Busy

NcFTP also has a clever background-transfer system. Commands such as:

bgget giant-file.iso

Hand a transfer to NcFTP’s spooler rather than tying up your interactive session. There are corresponding facilities for uploads. That’s an interesting distinction from simply detaching a shell command. NcFTP knows that this is a transfer job and maintains a queue of FTP work that can be retried and processed independently.

Shell Games

But perhaps the biggest reason to know about NcFTP is that NcFTP isn’t just one program. The package includes commands such as ncftpget, ncftpput, and ncftpls. These perform FTP operations directly from the Unix shell without starting an interactive FTP command interpreter. For example:

ncftpget ftp.example.com /tmp /pub/widget.bin

or:

ncftpput ftp.example.com /incoming widget.bin

This is much nicer in a script than sending commands to ftp using, for example, a here document and automating login with .netrc. For example:

ftp <<EOF
open ftp.example.com
cd incoming
put widget.bin
quit
EOF

Sure, it works, but any time you send input to an interactive program it is, at best, messy. The ncftpput program expresses what you actually wanted to do in the first place: put this file there. That’s much more Unix-like.

Don’t Do This At Home

None of these conveniences change FTP’s fundamental problem: ordinary FTP is not secure. Usernames, passwords, and data can travel without encryption. If you’re designing a new system and control both ends, you usually have much better choices. But sometimes you don’t control both ends. If FTP is something you run into, ncftp is worth knowing about. Bookmarks, cached directories, recursive and background transfers, and especially the script-friendly companion commands turn an antique protocol into something that feels surprisingly at home on a modern Unix command line.

Of course, just as you can use FUSE to mount an ssh server, you can use ftpfs, to make a remote server look like part of your file system. You never know when FTP is going to crop up.

Read the whole story
jepler
13 days ago
reply
I remembe ncftp but I consider lftp to be better (and it supports http and ssh too)
Earth, Sol system, Western spiral arm
Share this story
Delete

Turning a Toy Game Boy into a Real Game Boy

1 Comment

In the world of children’s toys there are many offerings which are meant to look like devices used by older kids or even adults, with the Fisher Price Laugh & Learn Lil’ Gamer toy bearing quite the resemblance to Nintendo’s iconic Game Boy. Although this factoid could be filed away as amusing trivia before passing said toy to a child for its requisite physical abuse by said child, a purported adult can still have a lot of fun with this toy by modding it into a real Game Boy, as [KOUZEX] recently did.

Part of the challenge here is to not just treat it as an unconventional replacement shell for a genuine Game Boy, but to retain as much of the child toy’s look and feel as possible. This includes things like buttons and even the weird sliding blocks on the side.

For the functional components a Game Boy Color with a busted screen was chosen as a donor, with the GBC mainboard fitting almost perfectly inside its new shell. Wires were then soldered to bridge Nintendo’s PCB with the toy’s PCB to make the original buttons and speaker work. After blowing a fuse on the GBC mainboard due to likely some power back feeding, the toy’s PCB had its non-essential parts stripped, but fortunately without further damage to the grafted in electronics.

Most of this mod is quite straightforward, just with some creativity required to add a Select and Start button as these were notably absent from the original. The new, rather large replacement OLED screen is a nice upgrade too and actually fits pretty well with the chunky look of the child’s toy. Even as mostly a joke mod, it seems surprisingly functional.

Read the whole story
jepler
18 days ago
reply
I'm a real (game) boy
Earth, Sol system, Western spiral arm
Share this story
Delete

Caller-specific coverage

1 Comment

I’ve had an idea rattling around to get more detail from coverage measurement. Can we measure the coverage in a function separately for each caller of the function?

Here’s why I want it: in Acidica, my toy BASIC interpreter, I had code to implement the built-in functions that looked something like this:

match func_name:


    case "LEN":
        if len(args) != 1:
            raise TypeError(f"Wrong arguments for LEN, got {len(args)}")
        return len(args[0])

    case "LEFT$":
        if len(args) != 2:
            raise TypeError(f"Wrong arguments for LEFT$, got {len(args)}")
        return args[0][:args[1]]

    # ... 19 other built-ins ...

I didn’t like the repeated code here: each different func_name has to check that it got its expected number of arguments and perhaps raise an error. So I refactored:

def expects(nargs: int, func_name: str, args: tuple) -> None:

    if len(args) != nargs:
        raise TypeError(f"Wrong arguments for {func_name}, got {len(args)}")

match func_name:
    case "LEN":
        expects(1, func_name, args)
        return len(args[0])

    case "LEFT$":
        expects(2, func_name, args)
        return args[0][:args[1]]

Nice. The code is tighter, easier to read, and common behavior is implemented in one place.

But the old code had an advantage: because each error condition had its own raise line, coverage measurement could tell me whether I had tested every func_name for the wrong number of arguments. With the error handling happening in a helper function, that information is lost. I’ll know that some func_name had a test for the wrong number of arguments, but not that all of them did.

Here’s where the new idea comes in. What if I could indicate that for the expects function, I want separate coverage data for each distinct calling site? Then I could see that every func_name had a test for both the wrong number of arguments and the right number of arguments. The simple branch inside expects would be measured separately for each caller.

I have a quick proof-of-concept. A decorator on expects does the work. Coverage.py already has dynamic contexts which are used for things like tracking which tests called which code. The decorator starts a new context named for the calling location, then restores the context when the function returns:

def coverage_per_caller(func):

    @functools.wraps(func)
    def _wrapper(*args, **kwargs):
        cov = coverage.Coverage.current()
        name = func.__name__
        caller = inspect.currentframe().f_back
        file = caller.f_code.co_filename
        lineno = caller.f_lineno
        prev_context = cov.switch_context(f"per_caller:{name}:{file}:{lineno}")
        try:
            ret = func(*args, **kwargs)
        finally:
            cov.switch_context(prev_context)
        return ret

    return _wrapper

I had to make one tiny (unreleased) change to coverage.py for this: switch_context used to return None, but now it returns the previous context so that we can nest them properly.

To my delight, this works! I can look at the HTML coverage report and see the caller contexts for the lines in expects. I can see that 20 callers ran the if line, but only 2 ran the raise, and the context names show the file and line number of the callers for each:

HTML report showing the contexts that ran each line of expects()

This isn’t the whole solution yet. Things to improve:

  • I’d like to post-process these contexts to show which callers were missing lines inside expects. What I’m looking for is the same kind of “this line is missing” information that I got from the original inlined logic.
  • These per-caller contexts overwrite the contexts we were already collecting (the test names). Ideally we’d have some kind of sub-context so that we could track both (or many) at once.
  • It’s not great that I had to add a decorator to the source code. Driving this through the coverage configuration would keep these kinds of details out of the source.

But it’s a start, and gives me other ideas. I could use some aspect of the data passed into a function as the context name. In this example, we could have used func_name as the context instead of the caller’s location. Maybe you have ideas for other uses.

Read the whole story
jepler
19 days ago
reply
This is an interesting situation I had not considered.

I'm most tempted to push back on the question of whether (when you've factored out "check for correct # of arguments") like this, one benefit is .. you can stop worrying about this!

The second piece of push-back I have is in two parts: First, that you have to manually check that the number of sites on line 430 and 431 are equal, not different, so it's not that great. Second, this is likely to miss the most likely mistake I can see: Failing to have a call to 'expects' at all. In this case, the line 430 and line 431 counts would be equal. so actually you have to manually count the expected number of call sites and compare to them to the number of line 430 hits...

In my own recent interpreted language implementation, I chose to use decorators *on the functions implementing each operation* to perform argument validation by function wrapping. It just so happens that the non-wrapped function would most likely fail to work at all, so I'm not too worried about missing one in testing.
Earth, Sol system, Western spiral arm
Share this story
Delete
Next Page of Stories