Show HN: Feather – a fresh Tcl reimplementation (WASM, Go)
feather-lang.devHey HN!
First time showing something here, but I've been furiously working over the holidays on Feather, a from scratch reimplementation of TCL designed for embedding in modern applications.
It's starting out as a faithful reimplementation of TCL without I/O, OOP features, or coroutines.
TCL has a special place in my heart because the syntax is so elegant for interactive use, and defining domain specific languages.
My motiviation is twofold: faster feedback loops for AI, and moldable software for users.
It turns out giving AI agents access to the runtime state of your program makes for really fast feedback loops, but embedding existing options in a world where shipping binaries for each platform is commonplace is tricky.
Embedding the real TCL is tricky because it comes with its own event loop (in 2025 you alreay have one), a GUI framework (you have a web framework already, or develop on mobile), and has access to the filesystem (don't forget to delete all commands with file system access!).
Feather just doesn't ship with those - expose only what you need from your application.
A WASM build comes out of the box and clocks in at ~120kb plus 70kb for connecting it to the browser or node.js.
And if embedding becomes easy, you can put a REPL everywhere: in mobile apps, in desktop software, as a control plane into web servers.
I want to imagine a world where all software is scriptable just like Emacs and nvim, with agents doing the actual work.
What, that's super cool! I've also been working on a from scratch implementation of TCL for firstclass multithreading, and it's been really fun learning all the edgecases that show up. I've gotten a lot of the core components working, but man is reference counting a pain in the neck or what. Are you doing a mostly one-to-one port, or something more novel? I've been working on my design to dramatically lower double indirections for lists. It's a little sad that a list contains a list of pointers pointing to another list. So much indirection! So I'm trying an experiment where all non-list/non-dict objects are contained directly after the head dict object in memory. It took a crash course in buddy allocators to finally figure out how to store objects, but it's really cool how I can allocate 8 contigious objects, set the first to the dict metadata, and all other items are the dict's objects. One cooler thing is if one of the dict's items is still borrowed somehere (ref_count > 1), the dictionary will dissolve into individual allocations, and all non-shared items are freed. Then, the new dict will reference them, as they're now normal objects.
Thank you!
> Are you doing a mostly one-to-one port, or something more novel?
Step 1 is a one-to-one port of all the non-I/O, non-OO stuff. I've got it down to a single skill for Opus 4.5 and now it's just a matter of turning the crank and keeping an eye on it.
Step 2: add more functionality for interactive use for humans/agents. Things like defining the syntax of commands, a completion engine, a help system. Essentially all the things you'd expect from a modern shell experience, but with a bring-your-own-UI approach.
> but man is reference counting a pain in the neck or what.
Maybe this is a bit more novel: since the only use case is embedding, and the host language already has dicts, lists, and other data structures, I'm just leveraging those. In the Go version of Feather, dicts are Go maps; in the JavaScript version they are backed by lists of pairs (to preserve insertion order)
Very interesting!
Note that the name might be confused with an old project: https://wiki.tcl-lang.org/page/Feather .
Ooh, it's got to be about 30 years since the Tcl plugin for Netscape; so perhaps we can have it back in the browser via WASM.