This is a fantastic write-up of a truly monumental effort. I have huge respect for the author's persistence. The line "Like gardening, but with more segfaults" really resonates. It’s this kind of deep-dive hobby project where you learn the most.
The experience with `c2rust` is particularly interesting. It reminds me of a similar shift I saw years ago with automatic code translators between other languages. They're incredible for getting a project off the ground and proving feasibility, just as the author found, but you often end up with code that's completely "un-idiomatic" for the target language. The decision to throw it all away and do a manual port, while surely gut-wrenching, was the right call. You just can't automatically translate the intent of the original C code into safe, idiomatic Rust.
The "Interesting Bugs" section gave me flashbacks. Bug #2, with the mismatched struct layout due to a missing `*`, is a classic FFI (Foreign Function Interface) nightmare. I once spent the better part of a week debugging a similar issue between C++ and C# where a single change in struct packing alignment was silently corrupting data downstream in very subtle ways. It's one of those bugs that makes you question your sanity. Finding that requires some serious debugging grit, so kudos to the author.
This project is a great case study in the real-world challenges of modernizing critical infrastructure code. The author mentions the next big goal is to convert the codebase from `unsafe` to safe Rust. I'm really curious about the strategy for that.
Refactoring away the raw pointers and complex control flow (like the `goto` patterns) into safe, idiomatic Rust without breaking everything seems like it would be even more challenging than the initial port. Will the approach be to introduce lifetimes and the borrow checker module-by-module? And what's the plan for the intrusive data structures? Replacing them with standard library collections like `BTreeMap` is the obvious choice, but I wonder if that will have performance implications that the original intrusive design was meant to avoid.
In any case, amazing work. Thanks for sharing the journey in such detail. I'll be following this project on GitHub for sure.
I will be amazed once it materializes, i.e. becomes a real, Rust rewrite of tmux, which I highly doubt is going to happen, but here is to hoping, right?
In any case, I am perfectly fine with OpenBSD's tmux. I had no issues whatsoever, ever. I will continue to stick to that, and I hope OpenBSD will never adopt Rust, they have many reasons to not do that. Their C projects have been pretty great. They are the living embodiment of that C code can be safe.
---
Edit:
Let me summarize it for the down-voter:
1. I will be glad if it becomes a real, working rewrite of tmux (highly doubt it is going to happen anytime soon).
2. So far I am fine with OpenBSD's tmux.
3. Their C projects have been great, and the CVEs (or lack thereof) speak for themselves.
What do you think is wrong with these statements that warrant your dislike? You do not like OpenBSD? You do not like their projects? You think a c2rust project full of unsafe and unreadable mess is great? What is it? I am looking for your answers, dear down-voter. Please answer. I beg.
This person built a really cool project and documented how and you're throwing negative predictions about it for no reason. No one is down voting your opinions on OpenBSD
Just for the record, I have nothing against the project. The only issue I may have is it being c2rust (or something related, be it an LLM or whatever). If it indeed materializes and becomes an actual rewrite of tmux, then I will celebrate, but from what I can see in the source code, I do not have high hopes.
But it's _not_ c2rust. It started that way but this approach was abandoned in favor of a manual port.
From the comment you replied to:
> The decision to throw it all away and do a manual port, while surely gut-wrenching, was the right call. You just can't automatically translate the intent of the original C code into safe, idiomatic Rust.
From the second paragraph of TFA:
> I threw away all of the C2Rust output and decided I would translate all of the files into Rust manually from C.
Please at least read the source before shit-talking it.
It is still pretty much c2rust (or something related), just as I have been trying to tell people but they do not ever listen. Clone the repository. It has at least 5115 "unsafe". Look at random source files, you will see what I mean when I say it is still c2rust (or something related).
Funny how no one gives a shit, they just blindly down-vote (when it comes to comments against Rust (even though it is not it), of course) without even bothering to check out the source code. If they did, they would have known I am not wrong.
---
Edit:
I do not care if it is not "c2rust" (could be some other transpiler), but check out the source code and tell me that it is Rust code people would write.
It is funny how y'all got it wrong just by failing to read the source code. Next time please do bother reading the source code before engaging in a fight, directly or indirectly (down-vote).
I usually don't comment because I am fine with reading stuff on here during my breaks and don't engage in discussions.
Your poo-pooing of a hobby project that has no ambitions of being enterprise grade really rubbed me the wrong way though.
If it brings you joy to call me a bot, go ahead though.
I do not care if you are a bot or not, but it is quite suspicious, especially after many people who have commented with fresh / new accounts.
Please, feel free to check out the source code of the project and let me know (seriously, please do) if you think people who write Rust would write anything remotely similar. My guess is that they would not. Let me tell you, this project will never materialize, and it will never replace OpenBSD's tmux. For a hobby project, it might be fine.
You are right, it is very far off from idiomatic Rust. It could have been done in virtually any programming languages. I am not sure why Rust was chosen if they decided to go against everything Rust stands for.
This is how a lot of rewrite projects start out, particularly in the hobby space. They focus on a 1:1 translation between the two languages until they're able to drop the original language's dependencies (compiler, etc). Then from there you start translating into idiomatic rust.
I've been working on a Rust-based tmux session manager called rmuxinator (i.e. tmuxinator clone) for a few years now. It (mostly) works and been slow going because ... life but I've recently picked it back up to fix some bugs. One of the last new features I'd added was the ability to use rmuxinator as a library in other Rust programs. I'd like to try forking tmux-rs, adding rmuxinator as a dependency and seeing if it would ... just work as a way to start sessions using per-project config files. I'm definitely not advocating for adding rmuxinator upstream but it would be very nice to have this sort of session templating baked into the "terminal multiplexer" itself.
The other interesting possibility I could foresee is doing things the other way around and having rmuxinator use tmux-rs as a library in order to setup and manage sessions instead of just dumping out shell commands -- which is fraught with edge cases. (Not sure if this is currently possible with tmux-rs, though.)
Once I wrap up the bugfixes I'm currently working on, I may fork this project and give one or both of the above a try.
> You might be asking: why did you rewrite tmux in Rust? And yeah, I don’t really have a good reason. It’s a hobby project. Like gardening, but with more segfaults.
I love this attitude. We don’t necessarily need a reason to build new things. Who knows what will come out of a hobby project. Thanks to the author for the great write up!
Also, my gardening is full of segfaults, coding a new project is definitely safer to my yard.
Completely agree. Not every project has to be out there to change the world.
I recently rewrote `fzf` [1] in Rust. Did I have any particular reason to do so? No, not really, regular `fzf` is fine, but I thought it would be a fun excuse to learn how fuzzy search algorithms work and how to exploit the channels in Rust. It was fun. There's no question that regular fzf is better but that wasn't the point, the point was to play with stuff and learn.
Nice, I do think fzf is a really good candidate for something that could be better if written in Rust. The fzy[1] C-rewrite is really fast, but I couldn't get it to give me as useful results when searching bash history.
Yeah, I think Rust makes some sense, and I do think I've done a few clever things like getting a linear-time "sort" by exploiting the fact that there's a discrete and finite number of "scores" [1], and avoiding copies by taking the indexed values and explicitly moving them into the source channel to avoid extra copies [2].
Someone smarter than me who is more familiar with TUI programming could almost certainly augment and improve what I wrote; I worked on it for as long as it was interesting to me. I use it for my home-built program launcher thing Sway, though most people would probably get better results with real fzf.
First time hearing anyone say fzf can be slow. I mostly use it for filtering relatively small lists (few K items), for example git reflogs, is speed an issue when searching the whole filesystem or something on these lines?
And assuming speed is not an issue, why would Rust make it better?
I didn't call it slow, but I'm sure it could be a little bit faster in Rust still. Fzy is noticeably faster for me, but it's bad at giving me the useful results first.
For command line tools I just appreciate if they're as fast as possible. And rg, fd, etc just show that Rust implementations can be correct and fast.
Honestly, I often hate how people ask "why?", and don't understand how "for fun" is a legitimate answer. I get it for work or other things, but hobbies? We do lots of things for fun! Humans were born to play, just like every other animal. It's how we learn and explore the world around us.
And frankly, to quote Knuth
> In fact what I would like to see is thousands of computer scientists let loose to do whatever they want. That's what really advances the field.
This is true for any field, or any project. We're creative creatures. We dream and explore. Major changes almost never come from doing things the way they've always been done. A lot of times "just because" gives you the freedom to try new things and challenge those paradigms. Weirdly, if you always have to justify everything you slow down progress.
I still believe that my #1 think that stunted my growth as a junior SWE was overthinking my personal projects and languages to use for them, instead of just building whatever I felt it's interesting or intriguing to build.
It's always hard to tell. But have you considered you might be measuring the wrong way?
To me it sounds like you learned a real important lesson one that some people never seem to learn.
I think one of the most beneficial aspects of doing things "just because" is these other skills or information you get along the way. It is very easy to miss all of this progress if you're too focused on the progress of the more tangible things. But that doesn't make any of that not progress. So don't put yourself down for that, because I'm sure you learned a lot. The only reason you can look back and see a better way is because you made that progress and learned those lessons. These are things mentors can usually help you get through faster but not everyone has a mentor nor access to one. But don't undermine your own progress just because you didn't finish projects or because you did things differently than others
Asking “why” can still be a legitimate question, and “for fun” can also be a legitimate answer.
I treat projects differently if they want to launch a product, they want to replace an established open source tool, done for fun for themselves, or if it’s a hobby project.
The complaint isn't about being asked why, it is about "for fun" not being acceptable.
Follow up questions are totally cool but the context is different, right?
If it isn't acceptable then there's a negative tone and questions are focused on utility and usually them "trying to help you" find utility.
If it is acceptable they ask you about your interests and what you're learning. Sometimes that can turn into utility but that's more natural.
It's a lot about culture to be honest. Some people are just toxic and if things don't make sense in their heads then it doesn't make sense in any head.
'For fun' is a perfectly reasonable answer. But sometimes the answer to 'why' comes after you do it. I'm sure that everyone has learned something without realizing its utility until the end. Nobody is obligated to answer that question, unless you're pitching something.
A lot of things that C will let you do (even if you enter the realm of undefined behaviour) will simply not compile to C. As the author states, there are semantic differences between pointers and Rust's references.
C pointers can have as many owners as you want, may be subjected to mathematical operations, and can be cast to any type without even an error message. The compiler will just assume you know what you're doing. If you enable enough compiler warnings, it might warn you, but C compilers don't generate a lot of those by default.
Rust will let you only generate one mutable (exclusive) reference at a time. This means straight C to Rust ports simply don't compile.
By switching to pointers, which work pretty much like their C equivalent, you can port the code much easier, but you do of course lose the benefits of Rust's safety mechanisms, because most pointer operations throw away all the safety guarantee that Rust provides.
It is rewritten to a different language and many people find Rust easier to read, it has better type hint support for IDE etc. Also, you do not lose all the safety, there are still many rules enforced, such as safe linking, no undefined functions.
Unsafe Rust means that all parts of code which do illegal pointer magic are explicitly marked with an "unsafe" keyword. You can now go one by one and fix them.
You think C does not? I would say it has even better type hint support, considering it has been available for way longer, among a hundred other reasons.
Once the codebase is all Rust you can start introducing Rust idioms and patterns. Basically step 1 is to get it working in Rust then step 2 is to clean up the Rust to actually take advantage of the language.
Rust is like walking across a mine field with all the mines flagged for you. You can dig up the mine and remove the flags over time. Or at least know to avoid stepping carelessly around them.
In C you only see the flags people know of or remembered to plant. There's an awful lot of mines left unflagged and sometimes you step on them.
It's very obvious to me which would be more safe and I find myself questioning why it is isn't so obvious to others.
Hmm...I like when the compiler don't steps in my way and assumes that I know what I'm doing. Thats the reason why I don't like Rust. But when you like it, have fun!
"Hmm...I like when the assembler don't steps in my way and assumes that I know what I'm doing. Thats the reason why I don't like C, and prefer assembler. But when you like it, have fun!"
I was about to post a snarky comment because I have a knee jerk reaction whenever someone implies a rust application is intrinsically better than C. Sometimes I forget people do things for fun.
Screen couldn’t do vertical splits for the longest time. That started to be a bigger problem when screens got bigger and wider. I believe that’s why I started using tmux. Tmux also has more facilities for automation. Nowadays, screen is primarily in maintenance mode, and I’m used to tmux, so no reason to switch back.
I think a lot of it is that tmux had friendler, sane defaults and clearer command design (eg. status bar out of the box). And, I suspect, people not already knowing screen.
The latter reason is why Helix is slow in doing similar to vim, I think, despite being far more consistently designed and saner defaults. Everyone knows vim exists.
I've still never switched from screen, personally, though I'm only a light user.
Defaults matter. I've had my screenrc with a status line but I still ended up preferring tmux in the end, because not needing a config file was a small but pleasant advantage when working with different machines. I also didn't like ctrl+a as the leader combination, because it conflicts with "go to the beginning of the line" in bash. ctrl+b is a much nicer default.
The status bar displays key information to the user. Do you think people would prefer a video player with no play/pause, volume, seekbar or one with them? The interface is the most important part of any application.
Sometimes that's exactly what one needs. As long as there's not forced schedule for the work and you can do it when you want and at the pace that you want, it can feel good.
Maybe my understanding of one or more concepts involves is wrong, but that "more segfaults" bit confuses me. Shouldn't the rust compiler prevent code that can segfault from compiling? Unless there was a lot of unsafe blocks involved.
Edit: apparently it did turn out to be a lot of unsafe code
I didn't interpret that it's 100% unsafe, but I do expect that to mean there is probably a lot of unsafe blocks used. A good amount of the example code in the post alone is unsafe blocks as well.
My understanding is that, even though tmux-rs is written in a safer language, it still can't beat the stability of an old battle-tested well-maintained project written by a group of highly competent developers.
Every new project is bound to have bugs that need to be ironed out during the time.
They wrote everything in unsafe rust where its very possible to segfault. This is not a normal C to Rust port. In a normal port you would never aim to have 100% unsafe rust code - rather you would hive off small parts of your application where you need unsafe so its highlighted and auditable. This is clearly an excerise for fun.
No, the issue is that doing a direct translation from a fundamentally unsafe language like C can't fix safety issues.
You'd have to do a proper rewrite, in which case you could write safe code from the start.
> Every new project is bound to have bugs that need to be ironed out during the time.
Not on the level of the kind of critical security and reliability bugs that unsafe languages foster. That's why CISA and the FBI both strongly recommend memory-safe languages.
Just curious. I'm a Rust developer. But I don't see myself discriminating between tools written in C, C++, Rust, Zig, etc. They all seem easy to install and use, as long as they're reasonably bugfree. Scripting languages are slightly different as they require me to maintain their respective interpreters and tools on my system. What difference do you see between applications written in Rust and those written in other compiled languages?
I agree the underlying technology doesn’t ultimately matter, but as user of a lot of fairly modern rust-based cli tools there definitely is something in the air worth mentioning.
I suspect it’s a couple of things. A new generation of programmers are hitting the scene, wanting to do things in new ways. Not inherently good or bad, but the new tools sure usually are at least very _pretty_, and have a lot of affordances and usability improvements over the ancient tools that can never be changed for the sake of compatibility. Rust and Go make this nicer, and are the languages de jour with good cli ecosystems and performance characteristics around them.
I genuinely do like most of my replacements. ripgrep for grep, eza for ls, zoxide for cd, fd for find, podman for docker, and a few more. Developer tooling is a rich and interesting space to be in, but there’s plenty of bandwagons I’m not getting on, like this or zellij for tmux, or jj for git.
Build Systems for C(++) are a mess, no package manager often means git submodules. Whereas Rust is actually easy, just requiring an `cargo install`. Don't know about Zig though Zig hasn't really taken of just yet imo.
> my feeling is that I’d still reach for it if my hands are really physically hurting, and I need to keep working. Usually once I reach the point where I’ve got blisters on my fingers I think it’s better to just take a break
I'm dumbfounded, and impressed in an unhealthy way. Do some of you regularly type so much that you develop blisters?
Every day when I look in the mirror, and I don't have this problem.
Then again, by the time I had a touch typing course at age ten using an old typewriter, I already had taken piano lessons for a couple of years. My music teacher was very strict on proper hand positioning, saying that future me would hate him if I didn't learn that right. I stopped taking piano lessons soon after, but I imagine that the skills involved with properly playing the piano transfer quite well to typing.
So the primary (or rather: only) reason for using Rust over C (memory safety) is out the window.
> I’d like to share the process of porting the original codebase from ~67,000 lines of C code to ~81,000 lines of Rust
And the codebase got bigger.
So yeah, as the author explains, hobby project, and kudos to that, but nothing that I will install on any box of mine any time soon.
Besides, applications like tmux would much rather be prime candidates for a rewrite in a garbage collected systems language (aka.; Go) than in Rust. tmux spends 99% of its time waiting for the user to hit a key, there is nothing performance critical in such an app that wouldn't be 100% adequately served by Go.
Just appalling. Someone publishes a post about their WIP project reaching an important milestone, and here comes the naysayers whining about the fact it's not finished yet.
Did you even the article? He clearly states his aims to convert it to safe rust. And for the code size, he clearly hasn't needed to optimize it yet and I don't think you necessarily want to code golf codebase like this.
Check out the source code. I will stick to OpenBSD's tmux.
This Rust project is not something any Rust programmer would write, I presume, especially if they want safety. Why use Rust to begin with if it is 100% unsafe? He is not going to learn (safe) Rust this way.
I love the attitude on this project and most of the comments are supportive. While rewriting a mature application to another language always sounds like a bad idea, there are so many learnings along the way. It's not about the end it's about the process.
Given the traction you got here and the advancements in AI, I'm sure this can become a very attractive hobby project for Rust beginners, there's probably a lot of easy bugs to fix. Fixing bugs, adding new features, and optimizing the code is all you need.
Here's an idea to get the ball rolling: Create a scratch buffer for Gemini CLI (or your favorite LLM) and enable it to interact with the various windows and panes of the tmux session.
Here's my use case, I use synchronized panes to send the commands into multiple servers, but some commands sometimes fail for various reasons. What if I can just ask the AI to send a series of commands and react based on the output and adjust along the way. It's like a dynamically generated custom shell script on the fly.
I'm all for people doing whatever hobby project they want to do for learning and entertainment purposes. But I don't really understand the appeal of straight porting something from one language to another.
For example, I'm a daily gvim user. If I were going to do a hobby project text editor, I would emphatically not make a clone of gvim, I'd make a text editor with exactly the features I want that behaves exactly how I want. If you're going to invest that much time in a project, why not do something creative and unique?
It's probably foolish, but I have the idée fixe that there's really no solid alternative for graphviz and dot (yes, there are UI versions, and mermaid and whatnot, but nothing that works on really big graphs and has the same expressivity), and I suspect that soon all the people that wrote graphviz will die off or retire. I like to see a port to a newer language as well, so ongoing maintenance will bercome easier.
Again, probably an idée fixe, and all is really well.
Some of that video is about stuff you have no use for if you're not a Rust developer, but, some of it is things that would be just as useful to anybody who is comfortable with, as it says, a command line interface.
Yeah, this seems like a huge missing feature for C2Rust. IIUC the main idea is to serve as a base for then porting to idiomatic Rust. But if you lose all of the constants that is a huge productivity loss.
This seems like an excellent future use case for a fully automated process by a large language model that translates a non-trivial C codebase to Safe Rust in under an hour with high accuracy. However, as the author noted, even after some attempts with Cursor at the end of development, the tool wasn't able to accelerate the translation effectively (in mid-2025). So while the potential is promising, it appears we're still some way off.
> This seems like an excellent future use case for a fully automated process by a large language model that translates a non-trivial C codebase to Safe Rust in under an hour with high accuracy.
I walked through the code again. Inside of the Rust function (*c).bar has a valid address, like 0x60302764, but out the function, the value received from the calling C code was 0x2764.
...
That’s right, the C code was using the implicit declaration which is:
int get_addr();
That explains why the value was incorrect! The C compiler was thinking a 4 byte int was returned not an 8 byte pointer. So the top 4 bytes were being truncated or ignored.
That's weird as an explanation. 0x60302764 is 4 bytes and 0x2764 is 2 bytes. Why would an address get truncated to 2 bytes? Is int 2-bytes according to any intermediate compilation stage? (Been at least 25 years since I saw int be 2 bytes, if ever).
Nice, hope it will become cleaner code in time. I tried zellij multiple times but despite years of development it still misses many things tmux provides. Inability to show/hide status bar[1] is the most annoying.
You can't rebind key maps to its session manager plugin, making it a no-go since I bind the same key that the plugin uses to select a directory or something. Thus, I can't create new sessions through it, have to do it from the command line.
Nice, I like tmux, I use it daily, I live in it. I hope this version makes it easier to just scroll with the scroll wheel or ctrl-page-up/down, or ctrl tab through your panes, or just show the whole unconcatenated title in the bottom left ;)
Sorry I know this is not the place to complain, but it would be so nice!
I use byobu which is basically an opinionated distribution of tmux. Scroll wheel works fine, as does Alt-PgUp/PgDn.
Ctrl-Tab probably won't work because terminals tend not to recognize it as different from Tab. But you might be able to bind Alt-Tab or some other such combo to cycle through panes in the tmux config. It should just be a one-liner.
Tmux is a gamechanger for me. Being able to start a dozen different projects with one line (using tmuxinator): the server, tailing logfiles, activating venvs, running the docker container, all within one line of code: Awesome. Hadn’t worked with it for years, just started again two days ago as I migrated from iTerm to Ghostty. And am loving the setup. Plus nvim. Pure awesomeness.
Surprised to hear you migrated from iTerm. It actually has a tmux integration mode (using -CC) that's awesome. You then don't have to remember any tmux specific shortcuts. Switching window is just Cmd+` just like everywhere else.
I entirely stopped using tmux when I couldn't use iTerm.
Have you checked out the website? This is a c2rust project. The Rust code is full of unsafe code and probably buggier than the C version, and let us not even mention readability and maintainability. Maybe there is a joke somewhere.
Wonder if anyone has tried these over flourishing AI code assist tools to supercharge the speed these porting projects? If so, what's the experience has been?
"Despite the generated code working, it was basically unmaintainable and 3x larger than the original C."
Which makes C2Rust seem pretty useless?
"I’ve recently reached a big milestone: the code base is now 100% (unsafe) Rust. I’d like to share the process of porting the original codebase from ~67,000 lines of C code to ~81,000 lines of Rust (excluding comments and empty lines)."
And yet somehow a hand-ported (and still unsafe) rewrite of a C program in Rust is still almost 20% larger?
If I recall, the Go gc compiler was automatically converted from 80K lines of C to 80K lines of Go. A hand-ported version would have been much smaller.
It does what took him 6 months in seconds. Of course it isn't perfect, failing to keep the name of constants being an obvious flaw. But presumably with a few improvements you could then spend some of that 6 months cleaning up the code and still save time. Sounds like C2Rust is almost there, but not quite yet.
> And yet somehow a hand-ported (and still unsafe) rewrite of a C program in Rust is still almost 20% larger?
Size is not a very useful metric. But the port is still half-done. He has got it working in Rust, so now he is ready to do the "hard" part of the port and actually rewrite the "basically C" code into idiomatic Rust. That is where you expect to get safety improvements and hopefully more readable code.
It generated unusuable garbage code in seconds, which is nothing like what he wrote by hand in six months.
"Size is not a very useful metric."
Size is a very useful metric. Counting tokens is more accurate estimate of "size" but lines of code is a good first approximation.
The entire purpose of high level languages is to make it possible to do more with less code. Size isn't all that matters but it's very important.
Rust code is not only more verbose than C it's also much more irregular and complex. That 20% increase in lines of code is probably more like 50% increase in code complexity, and this is without safety.
Zellij has interesting ideas, but it has a ways to go. You can arbitrarily rebind the base modes and their actions, but you're F'd if those conflict with a plugin's, which seem to all have hardcoded key binds.
why is that funny? I’ve done exactly this (in a processional setting): c2rust to get something functional and then incrementally rewrote the code while producing unit tests (approval tests via insta are particularly handy). The end result was a codebase which was much easier to maintain, with much better tooling and tests.
> the code base is now 100% (unsafe) Rust. I’d like to share the process of porting the original codebase from ~67,000 lines of C code to ~81,000 lines of Rust
Sounds to me that this was a C -> Rust transpiler. :D
I don't think anyone is suggesting that the generated Rust is nicer than the original C.
It is auto-generated with the purpose of maintaining the exact same semantics as the C code, with no regard to safety, best practices, etc.—of course it is messier than actual, handwritten Rust.
As c2rust says in its documentation [1], it's meant to be the first step in an otherwise manual and incremental port of a codebase from C to Rust, and the author recognizes this in their closing remarks:
> The next goal is to convert the codebase to safe Rust.
You should read one paragraph further. They did use c2rust but found it really bad and threw that out of the window. Then did it manually. So in the end it is not c2rust.
I was stating facts. It is a c2rust project. I do not care about some image they used. I want to see results. For now, it is definitely a c2rust project.
It is not a good look on the community that comments that quote this get flagged:
> 120 comments and nobody has mentioned the use-after-free triggered by closing a window. Rust truly is the safest language.
Whatever floats your (or their) boat though.
If you have anything against the quote, engage instead of down-voting, or am I expecting much?
And for what it is worth, let me quote the article:
> For the 6 months or so I’ve been quietly porting tmux from C to Rust. I’ve recently reached a big milestone: the code base is now 100% (unsafe) Rust. I’d like to share the process of porting the original codebase from ~67,000 lines of C code to ~81,000 lines of Rust (excluding comments and empty lines). You might be asking: why did you rewrite tmux in Rust? And yeah, I don’t really have a good reason. It’s a hobby project. Like gardening, but with more segfaults.
Don't you think this is slightly amusing? :D I cannot tell if this is satire or not, by the way.
I like the initiative, but all this effort for ... unsafe Rust?
I know it's a hot topic, and I hope the end goal is to have a memory-safe (and faster) tmux. I just hope the author doesn't stop here :)
Edit: As pointed out below, I'm stupid, it's stated in the article and I didn't read that part
1. Rewrite in (unsafe) Rust.
2. Update the code over time, moving towards safe Rust.
It's the old, "get it working then fix it" process. In business that's normally a bad idea because you end up wasting more time than if you'd just done things correctly from the start but for a hobby project it's fine. Because then you're more likely to learn something and possibly—ultimately—end up with a better end product.
To a business, time your developers spend learning things (the hard way) is wasted.
To a hobbyist, taking the time to learn things is time well-spent.
In business it can also be a good idea, because if you're waiting for it to be done correctly you may never have a delivered product even if you have a working (but not 100% ideal) product. A compromise is to get a subset of your target capabilities working correctly and the rest unimplemented and deliver that before continuing on.
It seems automatically translating Rust to C is not a very good idea: "I threw away all of the C2Rust output and decided I would translate all of the files into Rust manually from C.". Neither seems doing it manually: "I introduced many bugs while translating the code. I’d like to share the process of discovering and fixing a couple." Or using AI: "That’s because when using cursor to translate the code it would still occasionally insert bugs, just like me. So, I spent as much time reviewing the generated code as it would have taken me to write it myself."
As a hobby project, all power to you. But otherwise, maybe better not rewrite working code....
It comes from the fact that nearly every useful program written in C has multiple security vulnerabilities just waiting to be found. In the unlikely event that you have a codebase that's free of them, you risk introducing one with any significant change.
Instead of just dogmatically asserting that any C program has security vulnerabilities, and changing C programs is also a security problem, you should look at what tmux's record actually is.
tmux has existed for approaching 18 years, and M. Marriott is still actively improving it as of last week. One can actually look at its record over that time, and, if that record is poor, replace proof by unsupported generalized assertion with proof based upon actual evidence.
That is still quite a good record, but my statement stands. It is supported by decades of my experience working in C-derived languages. You don't have to accept my experience or believe my statement, of course, it's all the same to me.
That's a little like closing the barn door after the horse has already bolted because if you're concerned about security, then running any untrusted software in your terminal multiplexer is already a bad idea, regardless of whether your multiplexer is written in a memory-safe language or not.
...and before someone moans that I'm a C-fanboy, I'm really not. I've been writing software exclusively in memory-safe languages for 10+ years now. But I'm also pragmatic about when arguments about a RiR (rewrite-in-rust) are sensible and when they're not. In tmux's specific case, arguing about security misses the point.
Seeming as I'm getting downvoted, let me explain my point better -- and please hear me through because I'm genuinely making some balanced arguments here rather than just viewing things as "black and white":
If you care about security enough to be concerned about memory-safety bugs in tmux, then tmux is already a fail, regardless of whether it's written in Rust. I detailed some features in another comment about some of tmux's features that basically make it spyware for untrusted code. And that's got nothing to do with the language it is written in.
But assuming you only care about terminal output and trust the software you execute, then you still have a hundred other libraries written in C between and tmux and the internet: openssh, libcurl, openssl, glibc, and so on and so forth. I'd actually welcome seeing many other those rewritten in Rust (or another memory safe language). So rewriting tmux before them is a lot like closing the barn door after the horse has already bolted.
Thus if you're genuinely concerned about memory safety security vulnerabilities then the only safe way to work with untrusted output is in a VM.
As it happens, this is exactly how highly secure systems operate. Their developers work on VMs which are tightly locked down by the vendor and easy to destroy if they become compromised.
Literally the only way to solve the problem you describe is to assume the entire stack is already compromised and thus run it in a sandbox.
So does rewriting tmux in Rust improve security? Yes, technically you're right. But it makes almost zero practical benefit compared to everything else. Memory-safety in tmux is not your weak link here. Not even remotely.
Disclaimer: I've developed terminal emulators, shells and terminal multiplexers in memory safe languages. My latest project makes heavy use of tmux integrations (again, in a memory safe language) so I'm very familiar with tmux's quirks. I also have a background in DevSecOps. You could almost say this topic is my specialist subject ;) The Rust hype is a generally good thing but misplaced in this very specific discussion.
Do you run your web browser in a VM and skip security updates for it since it doesn’t matter anyway?
I know you say you’re not viewing things in black and white, but “run in a VM or don’t care about security and vulnerabilities don’t matter” is exactly that.
I don’t need to access untrusted sources from tmux. I do from Firefox.
Tmux has a smaller, easier to audit code base. Browsers are large, complicated and sprawling projects. That makes browsers a much larger attack surface.
Browsers already have sandboxing and other mitigations. Tmux doesn’t. Which means there are lower hanging fruit to fix in the terminal vs web browser.
Browsers are used by more people than tmux. So it’s a juicer target for zero-days.
We also already have Rust-based multiplexers for people who are worried about memory safety. There isn’t for web browsing.
Security is a scale of risk rather than something that is black and white. At some point the scales will tip and rewriting tmux in rust makes sense. But as said earlier, we already have Rust-based multiplexers for that eventuality. Whereas the need to harden browsers is much more urgent.
Context matters when it comes to InfoSec. At this point in time, rewriting tmux in Rust offers marginal gains vs rewriting a browser in Rust.
The browser having a larger attack service is an argument for the browser being more important to run in a VM, not less.
Maybe you never expose your terminal to untrusted data, but that’s not the norm. Most people occasionally do things in their terminals like clone repositories and look at their READMEs, ssh to computers they don’t own, read email, even browse the web.
Note that I’m not arguing that tmux must be rewritten in rust for security. I’m saying that C code is virtually guaranteed to have vulnerabilities, and this is a major reason why people want to rewrite things in rust.
If you want to argue that tmux doesn’t have any vulnerabilities, I find that very unlikely, but you do you.
If you want to argue that rewriting tmux in rust isn’t worth the effort, you may be right, but you’re arguing against something I didn’t say.
This conversation is about the merits of rewriting in Rust due to memory safety.
My replies have been specifically about that those merits.
The only reason other arguments have been included is because people like to expand that scope. For example where you said (and I’m paraphrasing) that tmux isn’t free from bugs. Clearly I don’t believe that any software is 100% bug free. But that doesn’t mean that rewriting tmux in rust brings any pragmatic improvements to the table when weighed up against all the other options and concerns.
That might be what you’re talking about but it sure isn’t what I’m talking about and I never said a single word about the actual merits of rewriting vs keeping something in C.
I summarized my actual statements in the previous comment. You might infer (and quite reasonably so) a claim that a rust rewrite would be more secure. But any statement about the overall usefulness of such an endeavor is solely in your imagination.
As someone using rust for over 7 years and recently switched to zig for personal projects, there is a lot of nuance. Yes rust is very reliable, it is really good even if you set memory safety aspect aside. But developing in rust is just so painful compared to using a simple language like c or zig and just enjoying the process.
Also dev time is massively shorter and the time I gain is spent on adding more features and tests.
Would recommend building low level projects in something like zig, if you care about build time and don’t want to use a dependency for everything.
I like C and various parts of C++ and I'm still writing new code in those languages. But for any component that could be exposed to malicious data, security is a never-ending game of whack-a-mole. I'm not saying everyone must move away, just that when people do, this is a big reason why.
Things can seem irrational when you don't understand them.
Another comment in this thread hoped for "a brand new bulletproof tmux-resurrect". The reason there's a desire for such things is closely related to the limitations of non-trivial programs written in C.
They're harder to extend without bugs, harder for new team members to understand, and so on.
The "irrational obsession" has to do with advancing the state of the art beyond a primitive high-level assembler that was developed in the 1970s.
I understand them very well, I just do not think it trumps all other considerations. Also I do not believe that Rust is easier than C. It is also less fun, less portable, and has another annoying ecosytem costs.
There's a lot of subjectivity here. The last serious C code I wrote was in the early 1990s, and I don't miss it at all, because I don't like spending time on low-level details unrelated to the problem domain I'm working on.
I find Rust fun and easy for writing system-level code, and I have enormous appreciation for the degree of correctness-by-construction that it can provide. Generally, if it builds, it works, as long as you're making proper use of the type system - make illegal states unrepresentable, as the saying goes. That's very difficult to do with C.
Rust isn't perfect. For most things, I'd rather be using Haskell, ML, or something on that level. But it's still on a completely different level from C, and rewriting the software ecosystem in it can only be an improvement.
Rust is far more portable in practice than C. Your average C program is written either for Unix or for Windows, while Rust has sufficient abstraction power to be able to write most business logic once.
I maintain cargo-nextest, a widely-used test runner for Rust. It is possible to write nextest's runner loop in C, but it would be extraordinarily difficult — each test's state machine has dozens of states, there are several dynamic event sources as inputs, and the event loop relies heavily on epoll/kqueue/the equivalent Windows thing, as abstracted out by Tokio. So most test runners written in C don't even try to approach the quality, reliability, or portability of nextest.
I think you have no idea how big the C ecosystem is. I am not sure what cargo-nextest is, but I have seen people solve the most challenging programs in C.
As I mentioned, cargo-nextest is a widely used test runner for Rust -- you're welcome to check out its website for its feature set.
It is possible to do this in C, because it compiles to machine code in the end. But would be out of reach for all but the most talented of C teams working over many years, and the portability costs would be massive. As a result, I don't know of a test runner that comes anywhere close to the feature set and portability of nextest that's written in C.
> I think you have no idea how big the C ecosystem is.
I'm definitely aware that the C ecosystem is much larger than the Rust ecosystem.
I also doesn't seem like anything most people would spend a lot of time on. I run my tests using "make" which somewhat poor but does the job. So from a programming side, what exactly do you think would be difficult to implement in C?
> I also doesn't seem like anything most people would spend a lot of time on.
That's because the conditions created by C make solving this problem very hard, not because the problem isn't worth solving.
It is still a hard problem with Rust, requiring heavy use of async state machines to manage a rather extraordinary level of complexity. But at least it is possible for essentially a solo dev like myself to do in a robust, largely bug-free manner.
> I run my tests using "make" which somewhat poor but does the job.
Right, "make" is indeed not quite a high-performance enterprise-grade test runner with parallel test execution, high-quality reporting, signal handling, dynamic status querying, timeouts, retries, flaky test detection, mutual exclusion between tests, a DSL that lets you specify sets of tests, flexible configuration, archiving tests to run on another computer, sharding test runs, JUnit support, wrapper scripts, setup scripts, and several other features. Make doesn't even properly support Windows, which is table stakes for a portable test runner.
Looks like you think only in windows and linux. Ok, but how much of your rust runs on freeRTOS or bare metal and on how many processor families? C? Runs on all of them. 6502? No Problem? 8051? Clearly! CRC16C? Yes. Eco32? yup. i386? Is developed to run C. Arm64, Arm? They too. They run Minix in their internal controlling hardware. Written in C...
Nextest works on a variety of platforms and architectures -- a lot more than x86_64 Windows and Linux. Porting to new platforms tends to be quite straightforward as long as someone's made Tokio work on that platform. (This is the power of abstraction! Turning MxN portability problems into M+N ones.)
C definitely has a place, but "Rust is not portable at all compared with C code" is simply not correct. A lot more Rust code works across Windows and Unix than C code does. Rust's portability story is different from C's, much better in many ways but worse in others. In practice I do think Rust ends up being more portable than C in most practical scenarios -- for example, look at how things like `eza` work on Windows, the number one developer platform worldwide.
No, that is likely not true. There are platforms today for which C-based tmux runs but Rust never will. It's not that we are simply waiting for the backport of Rust to magically appear for them, it's quite a certainty that it will basically never appear.
> It's not that we are simply waiting for the backport of Rust to magically appear for them, it's quite a certainty that it will basically never appear.
Abstraction happens on the level where tmux requirement is irrelevant. When the usage of Rust gets wider, people start adding support on compiler level for other needs. It is inevitable.
> Another comment in this thread hoped for "a brand new bulletproof tmux-resurrect". The reason there's a desire for such things is closely related to the limitations of non-trivial programs written in C.
I don't follow; tmux-resurrect isn't written in C and is mostly useful to keep sessions across reboots.
It was born in the 1970s and was standardized in the 80s and 90s. It continues to develop. Numerous data types have been added, along with unicode and threads. The C23 standard was released last year.
The same kinds of things that are wrong with all languages originally designed more than 50 years ago (75 years in Fortran's case) and that have accreted features since then. You end up with long-term fads like class-based object orientation embedded in the language, and that inhibits them evolving towards more principled designs. C++ is in a similar situation.
All of these languages are Turing complete. So ultimately, if you're happy writing code in some language and don't want to change, that's your choice. But the reason Fortran or C or C++ isn't many people's first choice for new projects are closely related to the reasons I've mentioned. There will always be people who want to stick to what they know, but it's not only science that advances one funeral at a time.
It's also not about sticking to what I already know for me. I don't currently know FORTRAN but wish to learn FORTRAN.
There are more factors to language use than design pattern fads. Like efficiency for example, which almost any modern garbage collected or managed language cannot meet beyond a certain level. And that usually gets worse the more "powerful abstractions" one adds. I want to learn FORTRAN because I have been told it has real benefits in terms of ergonomics for efficient code, ie normal looking FORTRAN code is faster than normal looking C/C++/Rust.
Efficiency is a real, concrete and measurable quantity. It is not subject to the fad of the day.
>You end up with long-term fads like class-based object orientation embedded in the language, and that inhibits them evolving towards more principled designs.
And what makes you think today's "principled designs" won't get the boot a few years down the line too? These things are cyclical and rarely based on any real mathematical reasoning.
It’s hard to actually define what Fortran means. There’s features in the standard that are not portable, and many portable features that are not standard. It’s kind of a mess, and getting worse.
FORTRAN means what it's always meant. The standard is a guide for the implementor. The user needs to code to the implementation.
It's a different way of thinking about languages than most people usually do, but it's been true for FORTRAN since the 1950s and is true to some extent of every language with multiple implementations today.
What in your mind are the fundamental issues of C? Because memory safety clearly isn't one of them as brand new systems languages are being written without it (Zig).
Memory safety is certainly a pretty fundamental problem with C. Zig actually addresses some of those issues, even if it's not fully "memory safe" by definition. Besides, the fact that new systems languages are being written without memory safety doesn't make it a good idea. People write all sorts of languages for all sorts of reasons.
C's lack of memory safety covers a broad range of concerns, including manual memory management, unrestricted pointers, null pointers (Tony Hoare's "billion dollar mistake"), buffer overflows, use-after-free, integer promotions, and so on.
Its weak type system is another fundamental limitation, closely related to its limited support for abstraction. The weakness of the standard library reflects this. The weak type system means that the static guarantees it provides are minimal. There were excuses for all this in 1975, there aren't any more.
Undefined behavior is more of an issue in C than in most languages. Again, not something you ideally want in a systems language.
Language-level concurrency support is virtually nonexistent.
Use of textual preprocessing, with limited semantic integration, as a language feature. Aside from the effects on the meaning of source code, it also makes building C programs more complex.
And again, the reason C23 hasn't addressed any of this significantly is because of fundamental limitations in the nature of the language. You can't "fix" these things without developing a new language.
I think this narrative of the unfixable fundamental flaws in C is a lot of nonsense. There are certainly a lot of dangerous aspects, but most are rather easily avoided. Rust has an advantage, with temporal memory safety. I do not think C++, Zig, or Go have a fundamental advantage. There is certainly a lot of bad C code out, but instead of changing language, you could also just write modern C code.
> There are certainly a lot of dangerous aspects, but most are rather easily avoided.
This is an almost childish claim. If they're so easily avoided, how do you explain the enormously long list of CVEs for C and C++ programs?
> I do not think C++, Zig, or Go have a fundamental advantage.
We agree on that. They objectively do not. They're all an attempt to continue the C legacy. Go specifically is particularly ridiculous, having been designed quite recently by people from the 1970s who steadfastly refused to learn any lessons from the last 50 years of programming language development.
To be clear: I'm from the 1970s as well. I learned FORTRAN in 1977. But unlike the designers of Go, I didn't allow my understanding of programming language design to stagnate in the 1970s. I learned things. I studied things. I discovered things.
Do you believe that C is the ultimate in system programming language design? If you agree that it's not, then what are we arguing about exactly?
How many users and eyes do these "low CVE" Rust, Go whatever projects have?
While I'd hardly disagree C and even C++ is lacking in memory safety compared to some newer languages, you are forgetting to normalize for sheer scale and userbase. If you have a Go project with the scale of popularity of Linux or Chrome or so on, then we can compare bug counts directly.
Absolutely zero shade to Zig, because it is still pre-1.0, but if you look at which new systems languages have gained wide adoption recently, instead of languages that are just created, you end up with Rust. And the stated reason industry is adopting it is memory safety.
What adoption? Blog posts? Echo chambers? Rust peaked. The hype pushers don't want to believe it but that is the reality. Absolutely zero shade to Rust.
zig is trying its best to also be memory safe (at runtime, if you want it) whereas c is stuck in the past (you can add on sanitizers, but they arent built into the language)
tmux doesn’t really gain anything from memory safety because:
1. anything running in tmux already has execution rights and typically for the same user as tmux anyway.
2. Anyone who wanted to exploit tmux could just run ‘tmux -C’ and automatically get access to literally every interaction within tmux.
3. The software itself is already damn stable. I've never had it crash.
If you’re worried about someone exploiting your terminal then tmux is a terrible option, irrespective of whether it’s with written in C or Rust. And I say this as someone who absolutely loves tmux and uses it every day.
[edit]
And if you're worried about non-security related bugs affecting UX, then a rewrite in any language, regardless of the language, is a worse solution if your application has already been battle-tested for close to two decades. You're much better off creating something entirely new instead of porting code from one language to another because at least then you have new ideas instead of the same application but with new bugs in different places.
I don't say this because of some bias that Rust fanboys will assume I have. I love memory safe languages and think Rust is a great option for new projects. The point I'm making here is that a rewrite doesn't gain much for tmux SPECIFICALLY because tmux is already extremely stable.
There are reasons to be worried about additional safety beyond just security. My first thought when reading the article was it would be a huge bummer if a bug in tmux brought down a long-running or particularly stateful session. Of course, I’ve never encountered such a thing in my own usage, but if you could make it less likely that alone seems like a value add
If tmux was a new project then I'd agree with you. But, like yourself, I've using tmux for probably close to 15 years now and never had it crash once.
In fact the author of this project has admitted that they've introduced bugs with their rewrite. I know it's a hobby project so I'm not being critical of their work. But if we're only interested in reducing bugs then rewriting an existing project isn't the right way to go. Something like Zellij makes more sense because it's offering something new in addition to being written in Rust.
You forget that tmux is a terminal emulator. Trusted programs can have untrusted/attacker-controlled terminal output. If the program running inside tmux (e.g. cat, curl -s, weechat) can output malformed unicode or escape commands that trigger crashes or code execution, it is actually a huge problem.
> can output malformed unicode or escape commands that trigger crashes or code execution, it is actually a huge problem.
I agree.
And to go back to an earlier point, when was the last time you experienced tmux crash? Because I’ve been using it 15 years and yet to see that happen to me.
I get the need to protect against theoretical attacks, but what you’re advocating is throwing the baby out with the bathwater.
I’m not going to deny that memory safety bugs are completely avoidable in C. However if the best example in tmux you can find is a bug that was patched promptly 5 years ago. That that’s does also say something favourable about tmux as well.
As I said elsewhere, if memory safety is a major concern then there are Rust multiplexers too. But there’s plenty more lower hanging fruit to worry about before tmux.
Any program gains from memory safety. Memory safety is not just about security. It's about eliminating an entire class of bugs - buffer overflows, null pointer errors, use-after-free, the list goes on. They just so happen to be the kind of bugs that also tend to have serious security consequences.
I honestly don't get this relentless defense of 1970s-style programming. Do you think C is the pinnacle of programming language design? No? Then what's your point, exactly?
You are regurgitating the same old tiring story. Use Ada / SPARK if you care about security that much, and it eliminates entire CLASSES of bugs, not just memory-related bugs.
FWIW, from the article:
> For the 6 months or so I’ve been quietly porting tmux from C to Rust. I’ve recently reached a big milestone: the code base is now 100% (unsafe) Rust. I’d like to share the process of porting the original codebase from ~67,000 lines of C code to ~81,000 lines of Rust (excluding comments and empty lines). You might be asking: why did you rewrite tmux in Rust? And yeah, I don’t really have a good reason. It’s a hobby project. Like gardening, but with more segfaults.
6 months! For what exactly? Can you please be so kind as to tell me, from your perspective?
> Any program gains from memory safety. Memory safety is not just about security. It's about eliminating an entire class of bugs - buffer overflows, null pointer errors, use-after-free, the list goes on. They just so happen to be the kind of bugs that also tend to have serious security consequences.
Have you actually ever encountered such a bug in tmux though? Because I've been using it for around 15 years and can honestly say I haven't.
Yet this rewrite has introduced bugs. I know it's a hobby project so I'm not being critical. But if you're just trying to reduce bugs then rewriting code battle tested code in another language, regardless of that language, isn't the right way to go.
> I honestly don't get this relentless defense of 1970s-style programming. Do you think C is the pinnacle of programming language design? No? Then what's your point, exactly?
Where was I defending 1970s style programming? I wasn't even defending C. In fact the last project I've worked on based in either C or C++ was 10 years ago. Believe me, I'm a fan of memory safe languages ;)
My point was very clear and very specific to tmux. You're just trying to read between the lines and create a whole new argument where there was none.
>Have you actually ever encountered such a bug in tmux though? Because I've been using it for around 15 years and can honestly say I haven't.
Since you asked, once every few months or so the whole server crashes which takes out all my windows. I don't know what exactly triggers it, other than it being something to do with pasting, and it's so infrequent that I haven't bothered to investigate it. Obviously the trivial repro of just pasting the same thing I tried to paste the first time doesn't repro it; I'd need to gdb the coredump, which is :effort:
I wouldn't expect this Rust rewrite or any other rewrite to fix it in any case; it would be more efficient to figure out the crash and fix it in the original C version.
It is intended as a incremental step to now write revise the unsafe rust into more idiomatic and safe rust. I haven't done rust port yet, but when translating other projects between languages I've also found it useful to first do a 1:1 port to ensure you have a system that works as intended, then refactor from there to clean things up.
I'll take a rust tmux if it runs on Windows. I'm currently kind of stuck on Windows and I didn't realize how much tmux means to me until Bill took it away :(
Yep I've been doing this since WSL 1 was available, it's rock solid.
My dotfiles at https://github.com/nickjj/dotfiles have an install script to automatically get everything (including tmux w/ plugins) set up on Debian, Ubuntu, Arch Linux or macOS. This includes native Linux and WSL 2 support.
WSL is not Windows. Unless you can work entirely in WSL (and if I could I'd just use Linux) having to juggle fake filesystems, incompatible symlinks, two PATHs, three shells is a bit much.
Some programs only run on Windows, this isn't a new problem. Personally, the only reason I have a Windows installation on my desktop is because Ableton doesn't run (well) via Wine, so not a lot of options really.
My understanding is that tmux is primarily an OpenBSD project, and rust isn't a good fit for them (for reasons that summarize to portability problems), so it is extremely unlikely. Also, this is a hobby project that currently is all unsafe, so there's not even any particular point. (EDIT: Of course, as it gets rewritten the latter point is likely to diminish)
> This project is still early in its developement. Bugs, crashes and miscompilations are expected. DO NOT USE IT FOR ANYTHING SERIOUS.
> rustc_codegen_clr is only tested on Linux x86_64, with the CoreCLR runtime (more commonly known as simply the .NET runtime), on .NET 8. It should work on other platforms, but it is not guaranteed.
I guess it could eventually be an option, but today it looks more like a neat tech demo.
This would require first for the Rust implementation to grow beyond a POC with code translation. In its current state I doubt it could entice any of the original authors or maintainers. But if it became capable and hardened and picked up velocity, then it would pose some major questions for having two similar pieces of software.
Taking a look at the source earlier, I'd guess probably not.
If you're going to move a project to rust, you'd want to actually make it look like rust. Currently it looks like C written in rust. That doesn't make anyone happy really.
(Obv. not a slight on the maintainer here, it's a personal project with a specific approach)
Seems like you didn't read the article at all. The author talks about writing it themselves after finding the automatically generated code not up to snuff.
It is a legitimate and serious issue, FWIW. I wonder what kind of other bugs there are.
Feel free to check out the source code yourself at https://github.com/richardscollin/tmux-rs/tree/main/src. It has around 5115 unsafe code, and that is just unsafe code, I cannot even begin to fathom the logic errors it might contain, which means, no thanks, I will stick to OpenBSD's tmux, they have a much better record. You disagree? Do not down-vote, engage in a discussion. I am open minded. I can be convinced.
[1] I thought Rust prevented "use-after-free" bugs. Apparently it does not. Funny that.
LLM's are really good at translating one programming language into another.
In fact, I sometimes port code to another language and back just as a way to do code cleanup (or at least give ideas for things that could be cleaned up)
I wonder why OP didn't start from that as a starting point?
This is discussed in the article? They tried cursor, but the bug rate was no better than their manual effort, so at least in this context, it did not work out.
Because he didn't want to? He mentioned that for him, this is like a "gardening" project, so why take away the joy of programming just to become an AI operator?
Slightly OT: it didn’t dawn on me until recently that terminal multiplier (like tmux) is a terminal itself.
And as a result, you could be running the greatest / fastest / most feature rich desktop terminal … but if your multiplier doesn’t support something - it hinders your fancy desktop terminal.
Interesting, this article and the comments make no mention of LLMs for the initial translation. Really surprising given that would be the first thing I'd reach for for a translation/porting task (though verification could get tricky).
Now I really wonder how a good model like Sonnet 4 would have performed.
> I did start trying out Cursor towards the end of the development process. I ended up stopping using it though because I felt like it didn’t actually increase my speed. It only saved me from finger pain. That’s because when using cursor to translate the code it would still occasionally insert bugs, just like me. So, I spent as much time reviewing the generated code as it would have taken me to write it myself. The only thing it saved was my hands. Doing this large amount of refactoring is really hard on your fingers.
Using Cursor to refactor the unsafe code is quite a different task than using an LLM to translate into safe rust. I was just curious how it would perform.
What do you mean by this? I'd assume the process would be very very incremental. One function + accompany tests at a time, verify and continue and keep moving up the tree.
It's an interesting problem because I imagine in the future lots of things will be ported like this.
The experience with `c2rust` is particularly interesting. It reminds me of a similar shift I saw years ago with automatic code translators between other languages. They're incredible for getting a project off the ground and proving feasibility, just as the author found, but you often end up with code that's completely "un-idiomatic" for the target language. The decision to throw it all away and do a manual port, while surely gut-wrenching, was the right call. You just can't automatically translate the intent of the original C code into safe, idiomatic Rust.
The "Interesting Bugs" section gave me flashbacks. Bug #2, with the mismatched struct layout due to a missing `*`, is a classic FFI (Foreign Function Interface) nightmare. I once spent the better part of a week debugging a similar issue between C++ and C# where a single change in struct packing alignment was silently corrupting data downstream in very subtle ways. It's one of those bugs that makes you question your sanity. Finding that requires some serious debugging grit, so kudos to the author.
This project is a great case study in the real-world challenges of modernizing critical infrastructure code. The author mentions the next big goal is to convert the codebase from `unsafe` to safe Rust. I'm really curious about the strategy for that.
Refactoring away the raw pointers and complex control flow (like the `goto` patterns) into safe, idiomatic Rust without breaking everything seems like it would be even more challenging than the initial port. Will the approach be to introduce lifetimes and the borrow checker module-by-module? And what's the plan for the intrusive data structures? Replacing them with standard library collections like `BTreeMap` is the obvious choice, but I wonder if that will have performance implications that the original intrusive design was meant to avoid.
In any case, amazing work. Thanks for sharing the journey in such detail. I'll be following this project on GitHub for sure.
I will be amazed once it materializes, i.e. becomes a real, Rust rewrite of tmux, which I highly doubt is going to happen, but here is to hoping, right?
In any case, I am perfectly fine with OpenBSD's tmux. I had no issues whatsoever, ever. I will continue to stick to that, and I hope OpenBSD will never adopt Rust, they have many reasons to not do that. Their C projects have been pretty great. They are the living embodiment of that C code can be safe.
---
Edit:
Let me summarize it for the down-voter:
1. I will be glad if it becomes a real, working rewrite of tmux (highly doubt it is going to happen anytime soon).
2. So far I am fine with OpenBSD's tmux.
3. Their C projects have been great, and the CVEs (or lack thereof) speak for themselves.
What do you think is wrong with these statements that warrant your dislike? You do not like OpenBSD? You do not like their projects? You think a c2rust project full of unsafe and unreadable mess is great? What is it? I am looking for your answers, dear down-voter. Please answer. I beg.
---
Edit #2:
The source code is available here: https://github.com/richardscollin/tmux-rs/tree/main/src
It is still c2rust (or something else), and it contains ~5115 unsafe blocks.
You do not need to be familiar with Rust to be able to tell that this is indeed c2rust (or something else).
---
Edit:
Please feel free to read its source code here: https://github.com/richardscollin/tmux-rs/tree/main/src
It is still c2rust (or something related), with ~5115 "unsafe" blocks.
From the second paragraph of TFA: > I threw away all of the C2Rust output and decided I would translate all of the files into Rust manually from C.
Please at least read the source before shit-talking it.
> Please at least read the source before shit-talking it.
Please at least check out the readily available source code, which is available here: https://github.com/richardscollin/tmux-rs/tree/main/src
It is still pretty much c2rust (or something related), just as I have been trying to tell people but they do not ever listen. Clone the repository. It has at least 5115 "unsafe". Look at random source files, you will see what I mean when I say it is still c2rust (or something related).
Funny how no one gives a shit, they just blindly down-vote (when it comes to comments against Rust (even though it is not it), of course) without even bothering to check out the source code. If they did, they would have known I am not wrong.
---
Edit:
I do not care if it is not "c2rust" (could be some other transpiler), but check out the source code and tell me that it is Rust code people would write.
It is funny how y'all got it wrong just by failing to read the source code. Next time please do bother reading the source code before engaging in a fight, directly or indirectly (down-vote).
Please, feel free to check out the source code of the project and let me know (seriously, please do) if you think people who write Rust would write anything remotely similar. My guess is that they would not. Let me tell you, this project will never materialize, and it will never replace OpenBSD's tmux. For a hobby project, it might be fine.
If you still think they are using a transpiler rather than doing rote hand translation, please point out some specifics.
You are right, it is very far off from idiomatic Rust. It could have been done in virtually any programming languages. I am not sure why Rust was chosen if they decided to go against everything Rust stands for.
Have fun reading the source code.
> I threw away all of the C2Rust output and decided I would translate all of the files into Rust manually from C.
> My hand translated code isn’t that much better than the output from C2Rust.
It may look like C2Rust but it was all done by hand
I've been working on a Rust-based tmux session manager called rmuxinator (i.e. tmuxinator clone) for a few years now. It (mostly) works and been slow going because ... life but I've recently picked it back up to fix some bugs. One of the last new features I'd added was the ability to use rmuxinator as a library in other Rust programs. I'd like to try forking tmux-rs, adding rmuxinator as a dependency and seeing if it would ... just work as a way to start sessions using per-project config files. I'm definitely not advocating for adding rmuxinator upstream but it would be very nice to have this sort of session templating baked into the "terminal multiplexer" itself.
The other interesting possibility I could foresee is doing things the other way around and having rmuxinator use tmux-rs as a library in order to setup and manage sessions instead of just dumping out shell commands -- which is fraught with edge cases. (Not sure if this is currently possible with tmux-rs, though.)
Once I wrap up the bugfixes I'm currently working on, I may fork this project and give one or both of the above a try.
Regardless, nice work by richardscollin!
I love this attitude. We don’t necessarily need a reason to build new things. Who knows what will come out of a hobby project. Thanks to the author for the great write up!
Also, my gardening is full of segfaults, coding a new project is definitely safer to my yard.
I recently rewrote `fzf` [1] in Rust. Did I have any particular reason to do so? No, not really, regular `fzf` is fine, but I thought it would be a fun excuse to learn how fuzzy search algorithms work and how to exploit the channels in Rust. It was fun. There's no question that regular fzf is better but that wasn't the point, the point was to play with stuff and learn.
[1] https://github.com/Tombert/rs-fzf-clone
[1] jhawthorn/fzy: :mag: A simple, fast fuzzy finder for the terminal https://share.google/TBp3pVaFngBTfaFyO
Someone smarter than me who is more familiar with TUI programming could almost certainly augment and improve what I wrote; I worked on it for as long as it was interesting to me. I use it for my home-built program launcher thing Sway, though most people would probably get better results with real fzf.
[1] https://github.com/Tombert/rs-fzf-clone/blob/main/src/helper... [2] https://github.com/Tombert/rs-fzf-clone/blob/main/src/proces...
And assuming speed is not an issue, why would Rust make it better?
For command line tools I just appreciate if they're as fast as possible. And rg, fd, etc just show that Rust implementations can be correct and fast.
And frankly, to quote Knuth
This is true for any field, or any project. We're creative creatures. We dream and explore. Major changes almost never come from doing things the way they've always been done. A lot of times "just because" gives you the freedom to try new things and challenge those paradigms. Weirdly, if you always have to justify everything you slow down progress.To me it sounds like you learned a real important lesson one that some people never seem to learn.
I think one of the most beneficial aspects of doing things "just because" is these other skills or information you get along the way. It is very easy to miss all of this progress if you're too focused on the progress of the more tangible things. But that doesn't make any of that not progress. So don't put yourself down for that, because I'm sure you learned a lot. The only reason you can look back and see a better way is because you made that progress and learned those lessons. These are things mentors can usually help you get through faster but not everyone has a mentor nor access to one. But don't undermine your own progress just because you didn't finish projects or because you did things differently than others
other people use the stupidest possible javascript to launch product and really focus on product and marketing
yet other people stay as far away from computers as possible and focus on more human activities
you just do what you're drawn to naturally
I treat projects differently if they want to launch a product, they want to replace an established open source tool, done for fun for themselves, or if it’s a hobby project.
Follow up questions are totally cool but the context is different, right?
If it isn't acceptable then there's a negative tone and questions are focused on utility and usually them "trying to help you" find utility.
If it is acceptable they ask you about your interests and what you're learning. Sometimes that can turn into utility but that's more natural.
It's a lot about culture to be honest. Some people are just toxic and if things don't make sense in their heads then it doesn't make sense in any head.
interesting, I'm new to rust. what are you doing that necessitates using unsafe?
C pointers can have as many owners as you want, may be subjected to mathematical operations, and can be cast to any type without even an error message. The compiler will just assume you know what you're doing. If you enable enough compiler warnings, it might warn you, but C compilers don't generate a lot of those by default.
Rust will let you only generate one mutable (exclusive) reference at a time. This means straight C to Rust ports simply don't compile.
By switching to pointers, which work pretty much like their C equivalent, you can port the code much easier, but you do of course lose the benefits of Rust's safety mechanisms, because most pointer operations throw away all the safety guarantee that Rust provides.
Safe Rust includes many forms of shared mutability, including Cell<> which is perhaps the closest comparison to typical patterns in C code.
Than C? chuckles.
> it has better type hint support for IDE
You think C does not? I would say it has even better type hint support, considering it has been available for way longer, among a hundred other reasons.
jesus christ, you’re not light yagami—please stay on /g/
I have no idea what "light yagami" and /g/ are. Seems like you do. It might be your community, not mine.
In C you only see the flags people know of or remembered to plant. There's an awful lot of mines left unflagged and sometimes you step on them.
It's very obvious to me which would be more safe and I find myself questioning why it is isn't so obvious to others.
But tmux isn't new
Is a reason necessarily needed to rewrite software in other languages
Screen, tmux, byobu, dvtm, mtm, Twin, and most of all Zellij, which is basically "tmux but redone in Rust".
I tried to compare them all a month ago:
https://www.theregister.com/2025/06/24/tiling_multiplexers_s...
Screen for when I need things ti behave and work a certain way
The latter reason is why Helix is slow in doing similar to vim, I think, despite being far more consistently designed and saner defaults. Everyone knows vim exists.
I've still never switched from screen, personally, though I'm only a light user.
Software packages win over other packages for the silliest reasons.
Edit: apparently it did turn out to be a lot of unsafe code
> the code base is now 100% (unsafe) Rust
I didn't interpret that it's 100% unsafe, but I do expect that to mean there is probably a lot of unsafe blocks used. A good amount of the example code in the post alone is unsafe blocks as well.
Every new project is bound to have bugs that need to be ironed out during the time.
You'd have to do a proper rewrite, in which case you could write safe code from the start.
> Every new project is bound to have bugs that need to be ironed out during the time.
Not on the level of the kind of critical security and reliability bugs that unsafe languages foster. That's why CISA and the FBI both strongly recommend memory-safe languages.
Or copies of old things apparently.
Here I want to call out zellij. Zellij is rust based terminal multiplexer.
I am user not creator. I love everything rust and finding and migrating to rust based solutions where feasible.
I suspect it’s a couple of things. A new generation of programmers are hitting the scene, wanting to do things in new ways. Not inherently good or bad, but the new tools sure usually are at least very _pretty_, and have a lot of affordances and usability improvements over the ancient tools that can never be changed for the sake of compatibility. Rust and Go make this nicer, and are the languages de jour with good cli ecosystems and performance characteristics around them.
I genuinely do like most of my replacements. ripgrep for grep, eza for ls, zoxide for cd, fd for find, podman for docker, and a few more. Developer tooling is a rich and interesting space to be in, but there’s plenty of bandwagons I’m not getting on, like this or zellij for tmux, or jj for git.
i'm sorry WHAT
https://github.com/ajeetdsouza/zoxide
Well I never.
> my feeling is that I’d still reach for it if my hands are really physically hurting, and I need to keep working. Usually once I reach the point where I’ve got blisters on my fingers I think it’s better to just take a break
I'm dumbfounded, and impressed in an unhealthy way. Do some of you regularly type so much that you develop blisters?
Then again, by the time I had a touch typing course at age ten using an old typewriter, I already had taken piano lessons for a couple of years. My music teacher was very strict on proper hand positioning, saying that future me would hate him if I didn't learn that right. I stopped taking piano lessons soon after, but I imagine that the skills involved with properly playing the piano transfer quite well to typing.
So the primary (or rather: only) reason for using Rust over C (memory safety) is out the window.
> I’d like to share the process of porting the original codebase from ~67,000 lines of C code to ~81,000 lines of Rust
And the codebase got bigger.
So yeah, as the author explains, hobby project, and kudos to that, but nothing that I will install on any box of mine any time soon.
Besides, applications like tmux would much rather be prime candidates for a rewrite in a garbage collected systems language (aka.; Go) than in Rust. tmux spends 99% of its time waiting for the user to hit a key, there is nothing performance critical in such an app that wouldn't be 100% adequately served by Go.
Did you even the article? He clearly states his aims to convert it to safe rust. And for the code size, he clearly hasn't needed to optimize it yet and I don't think you necessarily want to code golf codebase like this.
A little harsh. Rome wasn't built in a day.
Check out the source code. I will stick to OpenBSD's tmux.
This Rust project is not something any Rust programmer would write, I presume, especially if they want safety. Why use Rust to begin with if it is 100% unsafe? He is not going to learn (safe) Rust this way.
Given the traction you got here and the advancements in AI, I'm sure this can become a very attractive hobby project for Rust beginners, there's probably a lot of easy bugs to fix. Fixing bugs, adding new features, and optimizing the code is all you need.
Here's an idea to get the ball rolling: Create a scratch buffer for Gemini CLI (or your favorite LLM) and enable it to interact with the various windows and panes of the tmux session.
Here's my use case, I use synchronized panes to send the commands into multiple servers, but some commands sometimes fail for various reasons. What if I can just ask the AI to send a series of commands and react based on the output and adjust along the way. It's like a dynamically generated custom shell script on the fly.
For example, I'm a daily gvim user. If I were going to do a hobby project text editor, I would emphatically not make a clone of gvim, I'd make a text editor with exactly the features I want that behaves exactly how I want. If you're going to invest that much time in a project, why not do something creative and unique?
Works great and it's totally memory safe
It's probably foolish, but I have the idée fixe that there's really no solid alternative for graphviz and dot (yes, there are UI versions, and mermaid and whatnot, but nothing that works on really big graphs and has the same expressivity), and I suspect that soon all the people that wrote graphviz will die off or retire. I like to see a port to a newer language as well, so ongoing maintenance will bercome easier.
Again, probably an idée fixe, and all is really well.
Try to port it. Maybe it'll just work
https://www.youtube.com/watch?v=rWMQ-g2QDsI
Some of that video is about stuff you have no use for if you're not a Rust developer, but, some of it is things that would be just as useful to anybody who is comfortable with, as it says, a command line interface.
0. https://codemod.com/ 1. https://martinfowler.com/articles/codemods-api-refactoring.h...
That’s specific.
From now on, it's like gardening, but in hell :-)
[1] https://github.com/zellij-org/zellij/issues/694
I was surprised to learn tmux had such a "large" codebase, where does the complexity come from?
Sorry I know this is not the place to complain, but it would be so nice!
Ctrl-Tab probably won't work because terminals tend not to recognize it as different from Tab. But you might be able to bind Alt-Tab or some other such combo to cycle through panes in the tmux config. It should just be a one-liner.
bind-key -n C-Space select-pane -t +1
I have often executed `pkill -9 tmux` and saved my day. I hope the rust version can help a bit here?
Also, in 2017-2018 I contributed a few fixes for memory leaks related to buffer history, so make sure you are using a recent version.
Love it. You definitively deserve your +350 points!
Looking forward to check out tmux-rs.
I entirely stopped using tmux when I couldn't use iTerm.
Have you checked out the website? This is a c2rust project. The Rust code is full of unsafe code and probably buggier than the C version, and let us not even mention readability and maintainability. Maybe there is a joke somewhere.
> I threw away all of the C2Rust output and decided I would translate all of the files into Rust manually from C.
The talk about starting with it, realizing it was too rough and changed approach. It's unsafe rust now but next goal at end was a safe version.
Have you read the conclusion, BTW?
Which makes C2Rust seem pretty useless?
"I’ve recently reached a big milestone: the code base is now 100% (unsafe) Rust. I’d like to share the process of porting the original codebase from ~67,000 lines of C code to ~81,000 lines of Rust (excluding comments and empty lines)."
And yet somehow a hand-ported (and still unsafe) rewrite of a C program in Rust is still almost 20% larger?
If I recall, the Go gc compiler was automatically converted from 80K lines of C to 80K lines of Go. A hand-ported version would have been much smaller.
It does what took him 6 months in seconds. Of course it isn't perfect, failing to keep the name of constants being an obvious flaw. But presumably with a few improvements you could then spend some of that 6 months cleaning up the code and still save time. Sounds like C2Rust is almost there, but not quite yet.
> And yet somehow a hand-ported (and still unsafe) rewrite of a C program in Rust is still almost 20% larger?
Size is not a very useful metric. But the port is still half-done. He has got it working in Rust, so now he is ready to do the "hard" part of the port and actually rewrite the "basically C" code into idiomatic Rust. That is where you expect to get safety improvements and hopefully more readable code.
It generated unusuable garbage code in seconds, which is nothing like what he wrote by hand in six months.
"Size is not a very useful metric."
Size is a very useful metric. Counting tokens is more accurate estimate of "size" but lines of code is a good first approximation.
The entire purpose of high level languages is to make it possible to do more with less code. Size isn't all that matters but it's very important.
Rust code is not only more verbose than C it's also much more irregular and complex. That 20% increase in lines of code is probably more like 50% increase in code complexity, and this is without safety.
Just compare tokens in the post's example:
120 comments and nobody has mentioned the use-after-free triggered by closing a window. Rust truly is the safest language.
Sounds to me that this was a C -> Rust transpiler. :D
Edit: I was right, they used c2rust.
And then there is "// generated Rust code".
As for the code snippets on https://richardscollin.github.io/tmux-rs/, I can read the C version better than the generated Rust code.
Please let me know which one is more readable to you.It is auto-generated with the purpose of maintaining the exact same semantics as the C code, with no regard to safety, best practices, etc.—of course it is messier than actual, handwritten Rust.
As c2rust says in its documentation [1], it's meant to be the first step in an otherwise manual and incremental port of a codebase from C to Rust, and the author recognizes this in their closing remarks:
> The next goal is to convert the codebase to safe Rust.
[1] https://github.com/immunant/c2rust/raw/master/docs/c2rust-ov...
It is not a good look on the community that comments that quote this get flagged:
> https://github.com/richardscollin/tmux-rs/issues/9
> 120 comments and nobody has mentioned the use-after-free triggered by closing a window. Rust truly is the safest language.
Whatever floats your (or their) boat though.
If you have anything against the quote, engage instead of down-voting, or am I expecting much?
And for what it is worth, let me quote the article:
> For the 6 months or so I’ve been quietly porting tmux from C to Rust. I’ve recently reached a big milestone: the code base is now 100% (unsafe) Rust. I’d like to share the process of porting the original codebase from ~67,000 lines of C code to ~81,000 lines of Rust (excluding comments and empty lines). You might be asking: why did you rewrite tmux in Rust? And yeah, I don’t really have a good reason. It’s a hobby project. Like gardening, but with more segfaults.
Don't you think this is slightly amusing? :D I cannot tell if this is satire or not, by the way.
6 months!
What a legend.
Edit: As pointed out below, I'm stupid, it's stated in the article and I didn't read that part
To a business, time your developers spend learning things (the hard way) is wasted.
To a hobbyist, taking the time to learn things is time well-spent.
The only reason this is at the top of HN is because of where Rust is on the Gartner Hype Cycle right now.
It's neat, but I wouldn't say useful.
It seems automatically translating Rust to C is not a very good idea: "I threw away all of the C2Rust output and decided I would translate all of the files into Rust manually from C.". Neither seems doing it manually: "I introduced many bugs while translating the code. I’d like to share the process of discovering and fixing a couple." Or using AI: "That’s because when using cursor to translate the code it would still occasionally insert bugs, just like me. So, I spent as much time reviewing the generated code as it would have taken me to write it myself."
As a hobby project, all power to you. But otherwise, maybe better not rewrite working code....
Except that the eventual result allows for extension and improvements in a memory-safe language.
tmux has existed for approaching 18 years, and M. Marriott is still actively improving it as of last week. One can actually look at its record over that time, and, if that record is poor, replace proof by unsupported generalized assertion with proof based upon actual evidence.
* https://cvedetails.com/product/20683/Nicholas-Marriott-Tmux....
That is still quite a good record, but my statement stands. It is supported by decades of my experience working in C-derived languages. You don't have to accept my experience or believe my statement, of course, it's all the same to me.
...and before someone moans that I'm a C-fanboy, I'm really not. I've been writing software exclusively in memory-safe languages for 10+ years now. But I'm also pragmatic about when arguments about a RiR (rewrite-in-rust) are sensible and when they're not. In tmux's specific case, arguing about security misses the point.
Not against untrusted URLs, no.
> You never cat or less a file you downloaded?
I don’t download untrusted files.
> You never ssh to servers run by other people?
100% no.
——-
Sounds like what you need more is a VM ;) executing anything untrusted in a secure environment is a dumb move.
If you care about security enough to be concerned about memory-safety bugs in tmux, then tmux is already a fail, regardless of whether it's written in Rust. I detailed some features in another comment about some of tmux's features that basically make it spyware for untrusted code. And that's got nothing to do with the language it is written in.
But assuming you only care about terminal output and trust the software you execute, then you still have a hundred other libraries written in C between and tmux and the internet: openssh, libcurl, openssl, glibc, and so on and so forth. I'd actually welcome seeing many other those rewritten in Rust (or another memory safe language). So rewriting tmux before them is a lot like closing the barn door after the horse has already bolted.
Thus if you're genuinely concerned about memory safety security vulnerabilities then the only safe way to work with untrusted output is in a VM.
As it happens, this is exactly how highly secure systems operate. Their developers work on VMs which are tightly locked down by the vendor and easy to destroy if they become compromised.
Literally the only way to solve the problem you describe is to assume the entire stack is already compromised and thus run it in a sandbox.
So does rewriting tmux in Rust improve security? Yes, technically you're right. But it makes almost zero practical benefit compared to everything else. Memory-safety in tmux is not your weak link here. Not even remotely.
Disclaimer: I've developed terminal emulators, shells and terminal multiplexers in memory safe languages. My latest project makes heavy use of tmux integrations (again, in a memory safe language) so I'm very familiar with tmux's quirks. I also have a background in DevSecOps. You could almost say this topic is my specialist subject ;) The Rust hype is a generally good thing but misplaced in this very specific discussion.
I know you say you’re not viewing things in black and white, but “run in a VM or don’t care about security and vulnerabilities don’t matter” is exactly that.
I’ve already said there are other applications I do think benefit from a memory safe rewrite.
I don’t need to access untrusted sources from tmux. I do from Firefox.
Tmux has a smaller, easier to audit code base. Browsers are large, complicated and sprawling projects. That makes browsers a much larger attack surface.
Browsers already have sandboxing and other mitigations. Tmux doesn’t. Which means there are lower hanging fruit to fix in the terminal vs web browser.
Browsers are used by more people than tmux. So it’s a juicer target for zero-days.
We also already have Rust-based multiplexers for people who are worried about memory safety. There isn’t for web browsing.
Security is a scale of risk rather than something that is black and white. At some point the scales will tip and rewriting tmux in rust makes sense. But as said earlier, we already have Rust-based multiplexers for that eventuality. Whereas the need to harden browsers is much more urgent.
Context matters when it comes to InfoSec. At this point in time, rewriting tmux in Rust offers marginal gains vs rewriting a browser in Rust.
Maybe you never expose your terminal to untrusted data, but that’s not the norm. Most people occasionally do things in their terminals like clone repositories and look at their READMEs, ssh to computers they don’t own, read email, even browse the web.
Note that I’m not arguing that tmux must be rewritten in rust for security. I’m saying that C code is virtually guaranteed to have vulnerabilities, and this is a major reason why people want to rewrite things in rust.
If you want to argue that tmux doesn’t have any vulnerabilities, I find that very unlikely, but you do you.
If you want to argue that rewriting tmux in rust isn’t worth the effort, you may be right, but you’re arguing against something I didn’t say.
My replies have been specifically about that those merits.
The only reason other arguments have been included is because people like to expand that scope. For example where you said (and I’m paraphrasing) that tmux isn’t free from bugs. Clearly I don’t believe that any software is 100% bug free. But that doesn’t mean that rewriting tmux in rust brings any pragmatic improvements to the table when weighed up against all the other options and concerns.
I summarized my actual statements in the previous comment. You might infer (and quite reasonably so) a claim that a rust rewrite would be more secure. But any statement about the overall usefulness of such an endeavor is solely in your imagination.
Also dev time is massively shorter and the time I gain is spent on adding more features and tests.
Would recommend building low level projects in something like zig, if you care about build time and don’t want to use a dependency for everything.
Another comment in this thread hoped for "a brand new bulletproof tmux-resurrect". The reason there's a desire for such things is closely related to the limitations of non-trivial programs written in C.
They're harder to extend without bugs, harder for new team members to understand, and so on.
The "irrational obsession" has to do with advancing the state of the art beyond a primitive high-level assembler that was developed in the 1970s.
I find Rust fun and easy for writing system-level code, and I have enormous appreciation for the degree of correctness-by-construction that it can provide. Generally, if it builds, it works, as long as you're making proper use of the type system - make illegal states unrepresentable, as the saying goes. That's very difficult to do with C.
Rust isn't perfect. For most things, I'd rather be using Haskell, ML, or something on that level. But it's still on a completely different level from C, and rewriting the software ecosystem in it can only be an improvement.
Embed, designated initialization, and constexpr are really nice adds.
I maintain cargo-nextest, a widely-used test runner for Rust. It is possible to write nextest's runner loop in C, but it would be extraordinarily difficult — each test's state machine has dozens of states, there are several dynamic event sources as inputs, and the event loop relies heavily on epoll/kqueue/the equivalent Windows thing, as abstracted out by Tokio. So most test runners written in C don't even try to approach the quality, reliability, or portability of nextest.
https://nexte.st/docs/design/architecture/runner-loop/
It is possible to do this in C, because it compiles to machine code in the end. But would be out of reach for all but the most talented of C teams working over many years, and the portability costs would be massive. As a result, I don't know of a test runner that comes anywhere close to the feature set and portability of nextest that's written in C.
> I think you have no idea how big the C ecosystem is.
I'm definitely aware that the C ecosystem is much larger than the Rust ecosystem.
That's because the conditions created by C make solving this problem very hard, not because the problem isn't worth solving.
It is still a hard problem with Rust, requiring heavy use of async state machines to manage a rather extraordinary level of complexity. But at least it is possible for essentially a solo dev like myself to do in a robust, largely bug-free manner.
> I run my tests using "make" which somewhat poor but does the job.
Right, "make" is indeed not quite a high-performance enterprise-grade test runner with parallel test execution, high-quality reporting, signal handling, dynamic status querying, timeouts, retries, flaky test detection, mutual exclusion between tests, a DSL that lets you specify sets of tests, flexible configuration, archiving tests to run on another computer, sharding test runs, JUnit support, wrapper scripts, setup scripts, and several other features. Make doesn't even properly support Windows, which is table stakes for a portable test runner.
You're welcome to peruse the design documents:
https://nexte.st/docs/design/architecture/runner-loop/ (already linked above)
https://nexte.st/docs/design/architecture/signal-handling/
https://nexte.st/docs/design/architecture/input-handling/
Rust is not portable at all compared with C code.
C definitely has a place, but "Rust is not portable at all compared with C code" is simply not correct. A lot more Rust code works across Windows and Unix than C code does. Rust's portability story is different from C's, much better in many ways but worse in others. In practice I do think Rust ends up being more portable than C in most practical scenarios -- for example, look at how things like `eza` work on Windows, the number one developer platform worldwide.
Statistically it is the most fun language there is, based on Stackoverflow. Portability is just a matter of time like with any language.
Abstraction happens on the level where tmux requirement is irrelevant. When the usage of Rust gets wider, people start adding support on compiler level for other needs. It is inevitable.
I don't follow; tmux-resurrect isn't written in C and is mostly useful to keep sessions across reboots.
It was born in the 1970s and was standardized in the 80s and 90s. It continues to develop. Numerous data types have been added, along with unicode and threads. The C23 standard was released last year.
There comes a point at which it becomes necessary to move on.
All of these languages are Turing complete. So ultimately, if you're happy writing code in some language and don't want to change, that's your choice. But the reason Fortran or C or C++ isn't many people's first choice for new projects are closely related to the reasons I've mentioned. There will always be people who want to stick to what they know, but it's not only science that advances one funeral at a time.
There are more factors to language use than design pattern fads. Like efficiency for example, which almost any modern garbage collected or managed language cannot meet beyond a certain level. And that usually gets worse the more "powerful abstractions" one adds. I want to learn FORTRAN because I have been told it has real benefits in terms of ergonomics for efficient code, ie normal looking FORTRAN code is faster than normal looking C/C++/Rust.
Efficiency is a real, concrete and measurable quantity. It is not subject to the fad of the day.
And what makes you think today's "principled designs" won't get the boot a few years down the line too? These things are cyclical and rarely based on any real mathematical reasoning.
It's a different way of thinking about languages than most people usually do, but it's been true for FORTRAN since the 1950s and is true to some extent of every language with multiple implementations today.
C's lack of memory safety covers a broad range of concerns, including manual memory management, unrestricted pointers, null pointers (Tony Hoare's "billion dollar mistake"), buffer overflows, use-after-free, integer promotions, and so on.
Its weak type system is another fundamental limitation, closely related to its limited support for abstraction. The weakness of the standard library reflects this. The weak type system means that the static guarantees it provides are minimal. There were excuses for all this in 1975, there aren't any more.
Undefined behavior is more of an issue in C than in most languages. Again, not something you ideally want in a systems language.
Language-level concurrency support is virtually nonexistent.
Use of textual preprocessing, with limited semantic integration, as a language feature. Aside from the effects on the meaning of source code, it also makes building C programs more complex.
And again, the reason C23 hasn't addressed any of this significantly is because of fundamental limitations in the nature of the language. You can't "fix" these things without developing a new language.
This is an almost childish claim. If they're so easily avoided, how do you explain the enormously long list of CVEs for C and C++ programs?
> I do not think C++, Zig, or Go have a fundamental advantage.
We agree on that. They objectively do not. They're all an attempt to continue the C legacy. Go specifically is particularly ridiculous, having been designed quite recently by people from the 1970s who steadfastly refused to learn any lessons from the last 50 years of programming language development.
To be clear: I'm from the 1970s as well. I learned FORTRAN in 1977. But unlike the designers of Go, I didn't allow my understanding of programming language design to stagnate in the 1970s. I learned things. I studied things. I discovered things.
Do you believe that C is the ultimate in system programming language design? If you agree that it's not, then what are we arguing about exactly?
While I'd hardly disagree C and even C++ is lacking in memory safety compared to some newer languages, you are forgetting to normalize for sheer scale and userbase. If you have a Go project with the scale of popularity of Linux or Chrome or so on, then we can compare bug counts directly.
1. anything running in tmux already has execution rights and typically for the same user as tmux anyway.
2. Anyone who wanted to exploit tmux could just run ‘tmux -C’ and automatically get access to literally every interaction within tmux.
3. The software itself is already damn stable. I've never had it crash.
If you’re worried about someone exploiting your terminal then tmux is a terrible option, irrespective of whether it’s with written in C or Rust. And I say this as someone who absolutely loves tmux and uses it every day.
[edit]
And if you're worried about non-security related bugs affecting UX, then a rewrite in any language, regardless of the language, is a worse solution if your application has already been battle-tested for close to two decades. You're much better off creating something entirely new instead of porting code from one language to another because at least then you have new ideas instead of the same application but with new bugs in different places.
I don't say this because of some bias that Rust fanboys will assume I have. I love memory safe languages and think Rust is a great option for new projects. The point I'm making here is that a rewrite doesn't gain much for tmux SPECIFICALLY because tmux is already extremely stable.
In fact the author of this project has admitted that they've introduced bugs with their rewrite. I know it's a hobby project so I'm not being critical of their work. But if we're only interested in reducing bugs then rewriting an existing project isn't the right way to go. Something like Zellij makes more sense because it's offering something new in addition to being written in Rust.
No I don’t forget that.
> can output malformed unicode or escape commands that trigger crashes or code execution, it is actually a huge problem.
I agree.
And to go back to an earlier point, when was the last time you experienced tmux crash? Because I’ve been using it 15 years and yet to see that happen to me.
I get the need to protect against theoretical attacks, but what you’re advocating is throwing the baby out with the bathwater.
CVE-2020-27347 is exactly the kind of memory safety bug exploitable by terminal output that I was talking about.
As I said elsewhere, if memory safety is a major concern then there are Rust multiplexers too. But there’s plenty more lower hanging fruit to worry about before tmux.
I honestly don't get this relentless defense of 1970s-style programming. Do you think C is the pinnacle of programming language design? No? Then what's your point, exactly?
FWIW, from the article:
> For the 6 months or so I’ve been quietly porting tmux from C to Rust. I’ve recently reached a big milestone: the code base is now 100% (unsafe) Rust. I’d like to share the process of porting the original codebase from ~67,000 lines of C code to ~81,000 lines of Rust (excluding comments and empty lines). You might be asking: why did you rewrite tmux in Rust? And yeah, I don’t really have a good reason. It’s a hobby project. Like gardening, but with more segfaults.
6 months! For what exactly? Can you please be so kind as to tell me, from your perspective?
Have you actually ever encountered such a bug in tmux though? Because I've been using it for around 15 years and can honestly say I haven't.
Yet this rewrite has introduced bugs. I know it's a hobby project so I'm not being critical. But if you're just trying to reduce bugs then rewriting code battle tested code in another language, regardless of that language, isn't the right way to go.
> I honestly don't get this relentless defense of 1970s-style programming. Do you think C is the pinnacle of programming language design? No? Then what's your point, exactly?
Where was I defending 1970s style programming? I wasn't even defending C. In fact the last project I've worked on based in either C or C++ was 10 years ago. Believe me, I'm a fan of memory safe languages ;)
My point was very clear and very specific to tmux. You're just trying to read between the lines and create a whole new argument where there was none.
Since you asked, once every few months or so the whole server crashes which takes out all my windows. I don't know what exactly triggers it, other than it being something to do with pasting, and it's so infrequent that I haven't bothered to investigate it. Obviously the trivial repro of just pasting the same thing I tried to paste the first time doesn't repro it; I'd need to gdb the coredump, which is :effort:
I wouldn't expect this Rust rewrite or any other rewrite to fix it in any case; it would be more efficient to figure out the crash and fix it in the original C version.
https://github.com/dotnet/runtime/pull/115762
https://github.com/dotnet/runtime/pull/115743
https://github.com/dotnet/runtime/pull/115733
https://github.com/dotnet/runtime/pull/115732
Or was that comment just a cop-out because Copilot’s results were complete nonsense?
My dotfiles at https://github.com/nickjj/dotfiles have an install script to automatically get everything (including tmux w/ plugins) set up on Debian, Ubuntu, Arch Linux or macOS. This includes native Linux and WSL 2 support.
Transitioning more software from C to Rust is a great idea.
These problems are largely solved now that there's a working transpiler from Rust to C - https://github.com/FractalFir/rustc_codegen_clr
> rustc_codegen_clr is only tested on Linux x86_64, with the CoreCLR runtime (more commonly known as simply the .NET runtime), on .NET 8. It should work on other platforms, but it is not guaranteed.
I guess it could eventually be an option, but today it looks more like a neat tech demo.
I wonder, I don't expect.
This would require first for the Rust implementation to grow beyond a POC with code translation. In its current state I doubt it could entice any of the original authors or maintainers. But if it became capable and hardened and picked up velocity, then it would pose some major questions for having two similar pieces of software.
If you're going to move a project to rust, you'd want to actually make it look like rust. Currently it looks like C written in rust. That doesn't make anyone happy really.
(Obv. not a slight on the maintainer here, it's a personal project with a specific approach)
Do not worry, there is a fix: https://github.com/richardscollin/tmux-rs/commit/54cf38be76e...
It is a legitimate and serious issue, FWIW. I wonder what kind of other bugs there are.
Feel free to check out the source code yourself at https://github.com/richardscollin/tmux-rs/tree/main/src. It has around 5115 unsafe code, and that is just unsafe code, I cannot even begin to fathom the logic errors it might contain, which means, no thanks, I will stick to OpenBSD's tmux, they have a much better record. You disagree? Do not down-vote, engage in a discussion. I am open minded. I can be convinced.
[1] I thought Rust prevented "use-after-free" bugs. Apparently it does not. Funny that.
you want to re-implement a well known project, fine
call it something else
I was hoping for the announcement of a brand new bulletproof tmux-resurrect.
But no, it is (just) tmux-(recodedIn)rust.
Like they’ve basically thrown away all the rust patterns and just wrote a c program in rust (eg all the raw pointers)
In fact, I sometimes port code to another language and back just as a way to do code cleanup (or at least give ideas for things that could be cleaned up)
I wonder why OP didn't start from that as a starting point?
And as a result, you could be running the greatest / fastest / most feature rich desktop terminal … but if your multiplier doesn’t support something - it hinders your fancy desktop terminal.
Short 3 min video explained by Ghostty creator
https://youtu.be/o-qtso47ECk
Now I really wonder how a good model like Sonnet 4 would have performed.
> I did start trying out Cursor towards the end of the development process. I ended up stopping using it though because I felt like it didn’t actually increase my speed. It only saved me from finger pain. That’s because when using cursor to translate the code it would still occasionally insert bugs, just like me. So, I spent as much time reviewing the generated code as it would have taken me to write it myself. The only thing it saved was my hands. Doing this large amount of refactoring is really hard on your fingers.
https://richardscollin.github.io/tmux-rs/#ai-tools
What do you mean by this? I'd assume the process would be very very incremental. One function + accompany tests at a time, verify and continue and keep moving up the tree.
It's an interesting problem because I imagine in the future lots of things will be ported like this.
-edit Good luck reading 100k lines of Claude generated Rust that you know nothing about lol. LLMS are not the tool for this.