Show HN: Fresh – A new terminal editor built in Rust
Posted by _sinelaw_ 6 days ago
I built Fresh to challenge the status quo that terminal editing must require a steep learning curve or endless configuration. My goal was to create a fast, resource-efficient TUI editor with the usability and features of a modern GUI editor (like a command palette, mouse support, and LSP integration).
Core Philosophy:
- Ease-of-Use: Fundamentally non-modal. Prioritizes standard keybindings and a minimal learning curve.
- Efficiency: Uses a lazy-loading piece tree to avoid loading huge files into RAM - reads only what's needed for user interactions. Coded in Rust.
- Extensibility: Uses TypeScript (via Deno) for plugins, making it accessible to a large developer base.
The Performance Challenge:
I focused on resource consumption and speed with large file support as a core feature. I did a quick benchmark loading a 2GB log file with ANSI color codes. Here is the comparison against other popular editors:
- Fresh: Load Time: *~600ms* | Memory: *~36 MB*
- Neovim: Load Time: ~6.5 seconds | Memory: ~2 GB
- Emacs: Load Time: ~10 seconds | Memory: ~2 GB
- VS Code: Load Time: ~20 seconds | Memory: OOM Killed (~4.3 GB available)
(Only Fresh rendered the ansi colors.)Development process:
I embraced Claude Code and made an effort to get good mileage out of it. I gave it strong specific directions, especially in architecture / code structure / UX-sensitive areas. It required constant supervision and re-alignment, especially in the performance critical areas. Added very extensive tests (compared to my normal standards) to keep it aligned as the code grows. Especially, focused on end-to-end testing where I could easily enforce a specific behavior or user flow.
Fresh is an open-source project (GPL-2) seeking early adopters. You're welcome to send feedback, feature requests, and bug reports.
Website: https://sinelaw.github.io/fresh/
GitHub Repository: https://github.com/sinelaw/fresh
Comments
Comment by giancarlostoro 6 days ago
Comment by Barathkanna 6 days ago
Comment by ljm 6 days ago
Eventually it'd wangle it's way into homebrew or the unstable branch of another package registry.
But that's me, because I really dislike installing binaries via a language's package manager, because they don't get updated unless I frequently run the upgrade commands for each package manager.
Comment by _sinelaw_ 6 days ago
The other thing it gives you is the ability to easily upgrade and uninstall so just a script to copy stuff is not on par.
Comment by ljm 6 days ago
I wouldn’t, because I might be in a repo and it starts upgrading all my local dependencies, and I’m not gonna add a text editor as a dev dependency. I’ll happily take the binary, or a tar.gz with the binary in it, though.
(Btw I love how it’s following the old DOS aesthetic)
Comment by Aldo_MX 6 days ago
I do, religiously, as part of my routine to check for updates.
n lts && npm uninstall -g corepack && npm update -g && n prune
Sometimes things break (that's how `npm uninstall -g corepack` became a part of my one-liner), but it is easier to update often than to neglect updates for years.Comment by _sinelaw_ 6 days ago
Comment by shunia_huang 6 days ago
But I totally get the idea behind this, it's greatly combined with the cargo toolchain and is widely installed than cargo (which by the way npm is much easier to install than cargo with my personal experience), npm handles update nicely, and it can handle multiple arch too. I would still prefer npm install because I have installed a lot recently so it's ok.
Comment by tough 4 days ago
Comment by johannesrexx 5 days ago
Comment by Aeolun 6 days ago
Comment by krageon 6 days ago
Comment by Gormo 5 days ago
Why not use the various standard and commonplace packaging and distribution methods for application software? Distro repos, tarballs, Homebrew, AppImage, Flatpak, etc.
Comment by knowitnone3 6 days ago
Comment by hnarn 6 days ago
Comment by anthk 5 days ago
Comment by johannesrexx 5 days ago
Comment by hnarn 4 days ago
Comment by Shorel 4 days ago
Comment by _sinelaw_ 4 days ago
- Homebrew (MacOS)
- Arch Linux AUR
- Debian/Ubuntu .deb
- Fedora/RHEL .rpm
as well as cargo install (which builds from source), npm, npx or building from source by cloning
Comment by psvn 1 day ago
Comment by port11 5 days ago
Comment by _sinelaw_ 5 days ago
Or you can use npm
Or you can download release binary packages from Github releases.
The problem is which option to make more prominent / first
Comment by port11 4 days ago
Comment by _sinelaw_ 6 days ago
Comment by LoganDark 6 days ago
Comment by _sinelaw_ 6 days ago
Comment by ulbu 6 days ago
strange thinking!
Comment by giancarlostoro 6 days ago
Comment by apatheticonion 6 days ago
https://github.com/alshdavid/install-scripts/releases?q=node...
https://github.com/alshdavid/install-scripts/releases
All of the binaries here are expected to be standalone/portable installations, so you can download/extract the archive and just run the binary.
curl -L --url https://github.com/alshdavid/install-scripts/releases/download/terraform-1.14.1/terraform-1.14.1-linux-amd64.tar.gz | tar -xvzf - -C $HOME/.local/bin
$HOME/.local/bin/terraform --help
I haven't yet written a package manager yet, but I was planning for it to just do the same thing as above but figure out your OS/ARCH, handle extraction and also offer a PATH update system so you can run `eval $(xpkg env)` and PATH is updated automatically.Comment by craftkiller 6 days ago
That would be Nix. Runs on any Linux distro and OSX. Also particularly useful for NixOS and NixBSD.
Comment by freeopinion 6 days ago
Or do you just mean something like Guix?
Comment by venturecruelty 6 days ago
Comment by baq 6 days ago
Comment by alienpingu 5 days ago
Comment by fcoury 6 days ago
https://www.youtube.com/playlist?list=PL9KpW-9Hl_het1V3_dLhG...
Comment by dualogy 6 days ago
One of my long-standing "would make if I had the time and perseverance" themes has been a terminal text editor that's hugely VSCode-like + compatible, so always glad to hear anyone going anywhere near that, and hence I perked up from these:
> Prioritizes standard keybindings and a minimal learning curve.
> Extensibility: Uses TypeScript (via Deno) for plugins, making it accessible to a large developer base.
Because where you are now with Fresh, you're probably really not far from supporting say `settings.json`, `launch.json`, `tasks.json`, `keybindings.json`, `.tmTheme`s and theme `.json`s, and indeed bringing up a VSCode-API-implementing "extension host" that can load up and run/host most `.vsix`es. Now, being terminal-based you'd skip over certain feature subsets such as webviews, custom (non-text) editors and the like... and might postpone Notebooks and such fancies initially, but:
Consider! 1000s of high-value, capable, tech-specific dev extensions out there, all readily supported by your just-spawned new editor. Doesn't that sound pretty exciting?
After all, there's a huge subset of VSCode fans who'd always switch in a heartbeat to a just-simply-non-Electron version (whether native or terminal) of the very same feature-scape & extensions & UI dev experience if only it was made and to max compatibility (and MS won't ever do so).
All that's missing (from screenshot glance) is the other sidebars & panels in addition to File Explorer =)
Will be putting your Fresh on my Github Watch list, but then again, I never really read the GH feed anyway.. but maybe I'll remember to check back in every quarter or so =)
Comment by _sinelaw_ 6 days ago
Also, there are nuances like VSCode exposing APIs that force the entire file to be in-memory (which is how VSCode works), this is fine but in my editor I'm trying to get extensions to work well even if the file is huge (encouraging incremental / partial stuff).
But yes, it's a very compelling vision... and part of the reason I chose TypeScript.
Thanks for the input :)
Comment by dig1 6 days ago
Now try opening it in Emacs with vlf [1] ;) Great work overall — looking forward to seeing further development!
Comment by _sinelaw_ 6 days ago
It loads instantly, and memory usage is minimal <80 MB.
It does seem like vlf requires configuration and adjustment, e.g. navigation with the normal keys works differently (jumps to beginning/end of current chunk instead of the whole file). Basically it exposes the chunk concept to the user.
In Fresh it's designed into the core and should be more transparent (although there are still limitations).
Comment by arkensaw 6 days ago
I'm on MacOS and I have remapped the fn and command keys so it can be more like Windows (I can't undo 20+ years of muscle memory, and also I just don't wanna)
Anyway, Fresh seems to ignore the remapping - it's back to the command key for copy/paste and the command palette.
Is there a way to access the dropdown menus by keyboard? I can see F underlined for File but no modifier key seems to make it happen
Comment by _sinelaw_ 6 days ago
Also I'm already working on a ui for customizing the key bindings so you could do whatever you wanted. (Currently managed by undocumented json)
Thanks for reporting!
Comment by 20after4 6 days ago
Comment by yearolinuxdsktp 6 days ago
Comment by _sinelaw_ 6 days ago
Comment by arkensaw 3 days ago
Comment by _sinelaw_ 3 days ago
Comment by 20after4 6 days ago
Great work on this! Very good performance but also a very good UX and you really nailed the discoverability / accessibility - basically everything works intuitively and needs very little explanation - this is something that I can't say about really any other editor I've tried.
This may finally replace nano as my default utility editor, if not my main IDE.
Comment by _sinelaw_ 6 days ago
Thank you :)
Comment by az09mugen 6 days ago
Keep up the good work !
Comment by _sinelaw_ 6 days ago
Comment by Findecanor 6 days ago
I once started writing a text editor on Linux, and first went down a similar route: a piece table over a mmap()'d file. But I abandoned using mmap, because Linux file systems typically don't have mandatory locking enabled, so you can't be sure that the file data won't be modified by another program.
(Then I got bogged down in Unicode handling... so 95% of the code became just about that, and I tired of it)
Comment by _sinelaw_ 6 days ago
So I opted for explicit management of chunks, also gives me more control and consistent cross platform behavior.
Comment by capv 6 days ago
Comment by bakul 6 days ago
Comment by capv 5 days ago
Comment by Shorel 4 days ago
Thanks Santa.
Comment by wg0 6 days ago
Because configuring an editor that comes with different plug-in systems in a third programming language is a lot of hassle for people who are too focused at getting the job done and don't want to be distracted with a whole another configuration framework in yet another programming language.
Comment by AlecSchueler 5 days ago
Comment by amadeuspagel 6 days ago
I searched for that desperately until I discovered micro[1].
Here's a quick comparison between micro and fresh:
- Fresh implements more standard keyboard shortcuts, like Ctrl+ArrowLeft and Ctrl+ArrowRight to skip to the next and previous word, Ctrl+Backspace to delete the previous word and Ctrl+Delete to delete the next one.
- Fresh is extensible in typescript, Micro in lua.
- Fresh is able to open the wikidata json dump (1.7T).
- Micro is included in most repos, so if you rent a new VPS you can immidiately dnf install it.
Comment by _sinelaw_ 5 days ago
Getting included in distributions is a worthy goal... So many things to do
Comment by Gormo 5 days ago
OP, I'm playing around with it a bit, but notice it only supports mouse input when running in terminal emulator under X, and doesn't support mouse events from GPM (in the way that mcedit does, for example).
Comment by _sinelaw_ 2 days ago
Comment by _sinelaw_ 5 days ago
Comment by satvikpendem 6 days ago
Comment by winterrdog 5 days ago
But the developer is clearly talented, no doubt about that. They know their stuff very well. Having tried writing a text editor myself, I could quickly tell they know their stuff by analysing the program design
Comment by lionkor 5 days ago
so many commits authored by `claude` with 100+ lines each, that extent is not "some".
Comment by satvikpendem 5 days ago
Comment by simlevesque 6 days ago
Comment by lionkor 5 days ago
extract_config_structs in build.rs (https://github.com/sinelaw/fresh/commit/a9f2fbc74b86840fe441...) does not, in fact, do what the comment says.
Comment by ivanjermakov 6 days ago
Comment by desireco42 6 days ago
I was settled on NVim and VSCode, then I discovered Zed, which is fantastic.
I guess you should not keep your life closed for new experiences. Everybody loves fast and responsive software, what can I say.
Thank you for your work, I will enjoy using it, it isn't for everything but that is how I started with Zed.
Comment by _sinelaw_ 6 days ago
Comment by Sn0wCoder 6 days ago
Comment by _sinelaw_ 6 days ago
Thanks for reporting!
Comment by az09mugen 6 days ago
Comment by _sinelaw_ 6 days ago
Comment by rglover 6 days ago
Comment by user- 6 days ago
I feel like thats the opposite behavior. For example, I use https://github.com/zyedidia/micro as my main editor in terminal, where it says `Save changes to filename before closing? (y,n,esc)”` when you try to quit.
Comment by _sinelaw_ 6 days ago
Comment by jlundberg 6 days ago
What are the reasons behind going with GPL-2 instead of a more permissive license like MIT or 0BSD?
You will probably at minimum build some neat helper functions and maximum code reuse is IMHO the best thing for the world.
I would for instance be curious on the ANSI routines but hesitate to invest mental energy when the code has limitations on usage.
Lastly cool to see new open source programs being built with heavy help from a code generation model. Inspiring!
Comment by _sinelaw_ 6 days ago
Comment by 20after4 6 days ago
Comment by Klasiaster 6 days ago
I've found https://github.com/gphalkes/tilde to work quite well, it also supports the system clipboard. Nice to see a Rust alternative.
Comment by _sinelaw_ 6 days ago
In VSCode it adds multiple cursors directly above/below.
In other editors I think it moves (shifts) the current line up or down.
Comment by Klasiaster 5 days ago
Comment by esafak 6 days ago
2. Thank you for running builds on ubuntu 22.04 so it's compatible with it. You might want to compile with cross or zig to support even older operating systems.
Comment by _sinelaw_ 6 days ago
Comment by lionkor 5 days ago
I'm not sure where you got this idea. The binary you distribute is dynamically linked:
> fresh: ELF 64-bit LSB pie executable, x86-64, [...], dynamically linked, [...]
and it links with libc, libm, and libgcc_s, which means the distro will matter, because GLIBC is not compatible that way.
How did you, after building this entire app, come to the conclusion that its statically linked? Rust apps typically aren't, by default.
Comment by gettingoverit 5 days ago
I remember your nickname from the Infernu project of yours. It was one of the best attempts at typechecking JavaScript I've ever seen, and it's as needed in modern days of TS team going insane as it never has been.
The things we don't really need more of are editors, CLI software, or Rust software.
Please reconsider your goals.
Comment by zozbot234 5 days ago
Comment by _sinelaw_ 5 days ago
Tree-sitter is supported and used internally for a subset of languages for syntax highlighting (other languages use textmate grammars). What exactly do you mean by support for tree-sitter parsers?
I wasn't aware of Debug Adapter Protocol! I'll take a look at that.
Comment by zozbot234 4 days ago
It's a great start of course, but even just documenting anything that's clearly still missing would be helpful.
Comment by jatins 6 days ago
I feel like sublime text got most of it right and every editor since then has been a reskin of the same (just written in a different stack)
Comment by benrutter 6 days ago
Since the original post was about a TUI editor, its worth mentioning Helix which supports most modern language out the box. That's amazing and wouldn't have been possible 10 years ago.
Comment by _sinelaw_ 6 days ago
For terminal based, there are also many options but not so much in the direction of "VSCode style". They're mostly focused on being "vi-style". And also the huge file support isn't as good in any of the others that I've tried.
Comment by venturecruelty 6 days ago
Comment by _sinelaw_ 6 days ago
Comment by venturecruelty 5 days ago
Comment by _sinelaw_ 5 days ago
Comment by createaccount99 5 days ago
Comment by Uptrenda 6 days ago
Comment by yearolinuxdsktp 6 days ago
Comment by Aeolun 6 days ago
Comment by _sinelaw_ 6 days ago
Comment by skylurk 5 days ago
Comment by Shorel 4 days ago
Add them to your comparison benchmarks.
Comment by zozbot234 4 days ago
Comment by Shorel 3 days ago
Neovim is there!
(Neo)Vim is the quintessential modal editor. If your comment is generated by an AI, please don't post comments again.
Comment by ericb 6 days ago
Comment by yoavm 6 days ago
Comment by AbuAssar 6 days ago
Comment by _sinelaw_ 6 days ago
I don't have a particular reason. Maybe I should switch.
Comment by joshka 4 days ago
A very real example of that is that Ratatui (MIT license) and Codex (Apache2). I feel comfortable reading and using code and ideas from either side and have them influence the design of the other side [1][2]. I don't feel comfortable in the same way reading any GPL licensed code (2 or 3) due to the inherent legal risk that entails.
Your personal views on software freedoms definitely trump my personal opinion as a developer here, so I'm not too stressed if you disagree with this. A solid amount of crates in the rust ecosystem are MIT or Apache 2 (or both), and I really encourage authors of new libs, apps, to choose the same licenses for giving back in the same spirit.
[1]: https://github.com/openai/codex/blob/main/codex-rs/tui/src/c...
Comment by 20after4 6 days ago
Comment by aerzen 6 days ago
Comment by _sinelaw_ 6 days ago
Comment by WhereIsTheTruth 6 days ago
Modern developers have lost their mind
Comment by wg0 6 days ago
Comment by _sinelaw_ 6 days ago
For extensions, the choice was either TypeScript (and get this bloat) or go with Lua and a much smaller binary (but less popular language).
But - I just realized stripping it brings it down to 76MB so I guess that's ok! Will push a commit :)
Comment by WhereIsTheTruth 6 days ago
Incredible, the technical choice got overridden by popularity, leading straight to bloat
Comment by _sinelaw_ 5 days ago
Comment by WhereIsTheTruth 5 days ago
What ever suits you, you didn't mind shipping a 400mb executable after all, so what do i know
Comment by wg0 6 days ago
Comment by _sinelaw_ 6 days ago
Comment by 20after4 6 days ago
Speed. Bun starts fast and runs fast. It extends JavaScriptCore, the performance-minded JS engine built for Safari. Fast start times mean fast apps and fast APIs.
Elegant APIs. Bun provides a minimal set of highly-optimized APIs for performing common tasks, like starting an HTTP server and writing files.
Cohesive DX. Bun is a complete toolkit for building JavaScript apps, including a package manager, test runner, and bundler.
Bun is designed as a drop-in replacement for Node.js. It natively implements thousands of Node.js and Web APIs, including fs, path, Buffer and more."- From the homepage[1] - it's a shame they use semantic html but no anchors for direct linking.
Comment by Defletter 6 days ago
Comment by 20after4 6 days ago
License compatible, probably safe from a rug pull?
Comment by winterrdog 5 days ago
Great work!
Comment by _sinelaw_ 5 days ago
Comment by winterrdog 5 days ago
Comment by zeeeeeebo 6 days ago
Comment by _sinelaw_ 3 days ago
no ansi color rendering
Comment by gigatexal 6 days ago
Comment by byyoung3 6 days ago
Comment by _sinelaw_ 6 days ago
Or maybe try using a single tab in your terminal, maybe that will let the key pass through?
Anyway I need to add keybinding UX or maybe a different default set of keys for MacOS? hmm.
Comment by webnrrd2k 5 days ago
Comment by _sinelaw_ 5 days ago
I hate it, and I'll keep working on reducing it
Comment by badmonster 4 days ago
Comment by qazswx 5 days ago
Comment by qazswx 5 days ago