I wonder why it’s opt-in. Maybe it’s part of the whole “you only pay for what you use” ethos, i.e. you shouldn’t have to pay the cost for a static emergency pool if you don’t even use dynamic memory allocation.
Respectfully, it feels like your position requires a very low, if not brain-dead level of incompetence on the part of LLM users, in order for your conclusion to be correct.
My personal anecdote: I used an LLM recently to basically vibe code a password manager.
Now, I’ve been a software engineer for 20 years. I’m very familiar with the process of code review and how to dive in to someone else’s code and get a feel for what’s happening, and how to spot issues. So when I say the LLM produced thousands of lines of working code in a very short time (probably at least 10 times faster than I would have done it), you could easily point at me and say “ha, look at ninkendo, he thinks more lines of code equals better!” And walk away feeling smug. Like, in your mind perhaps you think the result is an unmaintainable mess, and that the only thing I’m gushing about is the LOC count.
But here’s the thing: it actually did a good job. I was personally reviewing the code the whole time. And believe me when I say, the resulting product is actually good. The code is readable and obvious, it put clean separation of responsibilities into different crates (I’m using rust) and it wrote tons of tests, which actually validate behavior. It’s very near the quality level of what I would have been able to do. And I’m not half bad. (I’ve been coding in rust in particular, professionally for about 2 years now, on top of the ~20 years of other professional programming experience before that.)
My takeaway is that as a professional engineer, my job is going to be shifting from doing the actual code writing, to managing an LLM as if it’s my pair programming partner and it has the keyboard. I feel sad for the loss of the actual practice of coding, but it’s all over but the mourning at this point. This tech is here to stay.
This whole reply, and every other "anecdote" reply is more worthless than the pixels its printed on, without a link to your "actually did a good job" password manager.
(wow funny how these vibe code apps always are copies of something theres many open source versions of already)
Ugh, you made me spend the 20 minutes it takes to spin up a new github account to share this (my existing one uses my real name and I don't really want to doxx myself that much. Not that it's a huge deal, my real identity and the "ninkendo" handle have been intertwined a lot in the past.)
I'm not saying it's perfect, there's some things I would've done differently in the code. It's also not even close to done/complete, but it has:
- A background agent that keeps the unsealed vault in-memory
- A CLI for basic CRUD
- Encryption for the on-disk layout that uses reasonably good standards (pbkdf2 with 600,000 iterations, etc)
- Sync with any server that supports webdav+etags+mTLS auth (I just take care of this out of band, I had the LLM whip up the nginx config though)
- A very basic firefox extension that will fill passwords (I only did 2 or 3 rounds of prompting for that one, I'm going to add more later)
Every commit that was vibe-coded contains the prompt I gave to Codex, so you can reproduce the entire development yourself if you want... A few of the prompts were actually constructed by ChatGPT 5.2. (It started out as a conversation with ChatGPT about what the sync protocol would look like for a password manager in a way that is conflict-free, and eventually I just said "ok give me a prompt I can give to codex to get a basic repo going" and then I just kept building from there.)
Also full disclosure, it had originally put all the code for each crate in a single lib.rs, so I had it split the crates into more modules for readability, before I published but after I made the initial comment in this thread.
I haven't decided if I want to take this all the way to something I actually use full time, yet. I just saw the 1password subscription increase and decided "wait what if I just vibe-coded my own?" (I also don't think it's even close to worthy of a "Show HN", because literally anybody could have done this.)
> Did you investigate prior art before setting out on this endeavor
Lol no, I had no idea there was any other password managers! Thanks for the google search link! I didn't know search engines existed either!
> Wisdom means knowing when and where to apply cleverness, and where not to. like being able to recognize existing sub-components.
It says literally in the README that part of this is an exercise in seeing what an LLM can do. I am in no way suggesting anyone use this (because there's a bazillion other password managers already) nor would I even have made this public if you hadn't baited me into doing it.
The fact that there's a literal sea of password managers out there is why I'm curious enough to think "maybe a one that I get to design myself, written to exactly my tastes and my tastes alone could be feasible", and that's what this exercise is about. It literally took me less time to vibe-code what I have right now, than to pour through the sea of options that already exist to decide which one I should try. And having it be mine at the end means that I can implement my pet features the way I want, without having to worry one bit about fighting with upstream maintainers. It's also just fun. I thoroughly enjoy the process of thinking about the design and iterating on it.
applies when there is a sea of "prior art" on the topic requested. And that request (prompt) is actually framed/worded properly to match that prior art.
Which may be perfect if the target is reduceable to prior-art. Re-use, Mix-and-match, from opensource or stackoverflow, into my-own-flavour-hot-water, finally!
No, this is not sarcasm. i hate to (catch myself a month later) reinventing hot-water. Let something else do it.
The question that stays with me is, How to keep the brain-bits needed for that inventing / making new stuff , alive and kicking.. because they will definitely deteriorate towards zero or even negative. Should we reinvent each 10th thing? just for the mental-gym-nastics?
If you didn't like me telling you about search engines you probably won't like me telling you how git clone works BUT...
For all intents and purposes, (in the context of diddling around with a password manager you might use yourself and wouldn't recommend to anyone), Any/all of those existing open source password managers can ALSO be yours just as much as the output from any LLM.
I'm serious, not only can you tweak them to "your tastes and your tastes alone", you don't have to even tell upstream maintainers what you're doing let alone get it merged.
So if you’re just going to complain about me reinventing the wheel (even though I already explained this is literally an exercise to see what an LLM can do), can we at least recognize the goalpost shift here?
I’m just going to assume that you’ve completely conceded your original point then, since you have absolutely zero to say about whether you agree the LLM did good work or not. Since the moment I showed you its work, you immediately shifted to insulting my intelligence for bothering with a password manager in the first place.
I honestly don’t know why I bother feeding trolls like you when it’s clear your only goal here is to find fault.
If we're talking about goalposts, lets also recognize the Motte and Bailey of initial claims of "20 years professional software engineer actually good password manager" to "hee hee toy project testing how LLms work not complete not even for personal not recmmond for others"
I don't think your password manager is good, and I don't think you think it's good either or you'd be using it.
I'm not trolling. It's way cheaper and faster to just clone an existing project if you want to mess around with making a password manager suit your taste.
My goal is to mess around with an LLM, not just to mess around with a password manager. If you read literally any of my posts in this thread without the intention of throwing shade, maybe you would have gotten that point by now. I’ve certainly repeated it enough times.
> I don't think your password manager is good, and I don't think you think it's good either or you'd be using it.
Lol I am using it now though. In the time from yesterday’s post to now I have an iOS app, an iOS Password Autofill extension, a Mac app and the existing Linux CLI and Firefox browser extension. Automatically syncs conflict-free between everything too, using a simple web server for sync. It now covers every use case 1Password did for me, and no, none of the “rust password manager site:github.com” results do any of this.
It was an experiment to see if the effort of vibe coding a password manager would be easy enough that it would be worth doing, and guess what: resounding success. Cope more.
I don't deny it. When I said "mess around with making a password manager suit your taste" feel free to append " while using and getting experience with an LLM". nothing changes.
im glad you're dogfooding your pw manager now. I'm glad vibe coding met your own standard of quality.
I will leave it as an exercise to you to think about all the edge cases and usability issues that have been solved in mainstream pw managers that you've never thought about. I hope you keep your LLM subscription active so you can fix them as they come up. And to keep up with updates from IOS and firefox as they come out.
My experience is similar to yours: LLMs can write excellent code, though you really have to drive them the right way. I use a harness to drive long-run autonomous agents to create production code. (Not open source, but it is an actual product used by companies.)
The key is understanding how they fail, then driving them in a way that sidesteps this. If you let them run too long, they become self-contradictory. However, if you break long work into discrete chunks, then they can still fail, but it changes: they forget things. But that is a much easier thing to catch, because you can use things like lint or even a simple regex for "// TODO" to find them.
Once you set up your pipeline to orchestrate the agents so the errors become easily detectable, and you have gates that check for those errors, the quality goes way, way up.
If you measure the productivity of the system that is “you, using an LLM” in terms of the rate at which you can get actually-reviewed code completed (which, based on your comment, seems to be what you were doing) that seems like a totally reasonable way of doing things. But in that case the bottleneck is probably you reviewing code, right? Which, I bet, is faster than writing code. But you probably won’t get the truly absurd superhuman speed ups.
What would you say is your multiplier, in terms of throughly reviewing code vs writing it from scratch?
Yeah, I guess that's kinda my point. LLM detractors on HN seem to straw-man what they think the average LLM user is doing. I'm an experienced programmer who is using an LLM as a speed boost, and the result of that is that it produces thousands of lines of code in a short time.
The impressive thing isn't merely that it produces thousands of lines of code, it's that I've reviewed the code, it's pretty good, it works, and I'm getting use out of the resulting project.
> What would you say is your multiplier, in terms of throughly reviewing code vs writing it from scratch?
I'd say about 10x. More than that (and closer to 100x) if I'm only giving the code a cursory glance (sometimes I just look at the git diff, it looks pretty damned reasonable to me, and I commit it without diving that deep into the review. But I sometimes do something similar when reviewing coworkers' code!)
I don't know if it is incompetence - if anything i doubt it, someone else pointed out that pg also used that metric and i don't think pg is incompetent. However at the same time i think it is misleading at best.
My impression is that, as someone else wrote, we do not have an actual metric for such things as productivity or quality or what have you, but some people do want to communicate that they feel (regardless of if that matches reality) using an LLM is better/faster/easier and they latch to the (wrong) assumption about more LoC == better/faster that non-programmers already believed for years (intentionally or not, they may also deluding themselves) as that is an easy path to convince them that the new toys have value that applies to the non-programmers too (note that i explicitly ignore the perspective of the "toymakers" as those have further incentives to promote their products).
Personally i also have about 2 decades of professional experience (more if counting non-professional) and i've been toying with LLMs now and then. I do find them interesting and when i use them for coding tasks, i absolutely find useful cases for them, i like to have them (where possible) write all sorts of code that i could write myself but i just don't feel like doing so and i do find them useful for stuff i'm not particularly interested in exploring but want to have anyway (usually Python stuff) and i'm sure i'll find more uses for them in the future. Depending on the case and specifics i may even say that in very particular situations i can do things faster using LLMs (though it is not a given and personally that is not much of a requirement nor something i have anywhere high in my interest when it comes to using LLMs - i'd rather have them produce better code slower, than dummy/pointless/repetitive code faster).
However one thing i never thought about was how "great" it is that they generate a lot of lines of code per whatever time interval. If anything i'd prefer it if they generated less line of code and i'd consider an LLM (or any other AI-ish system) "smarter" if they could figure out how to do that without needing hand holding from me. Because of this, i just can't see LoCs as anything but a very bad metric - which is the same as when the code is written by humans.
How can you say that when all these models are externally sourced by companies that actively make a loss per token? When they finally need to make a profit, how can we be sure these models as well as their owners will remain as reliable and not enshittified? Anthropic has been blacklisted in the last 24 hours so its a turbulent industry to say the least
When enshittification happens we would just simply go back to code by hand, then. We programmers don't lose the ability to do so when we use LLM, right ?
(This post is directed to all software that shoves features like this in my face, and especially Microsoft more than Firefox.)
My problem with all software that shoves these AI features in my face, is that I don’t use features under duress.
If you interrupt what I’m doing to push me to use a feature, I won’t use it. If you’re a web designer and you block the page to tell me to sign up for an account, I close the tab and vow to never create an account. If you stop what I’m doing to ask me to rate your app, I’m going to give it 1 star. Et cetera.
Now I’ll be the first to admit this is childish… it’s a flaw in my character. When I feel pushed, I push back, and software pushing me makes me irrationally angry for reasons I can’t quite articulate. In some ways I wish I wasn’t like this. But I can’t be alone. I’m certain there is a non-negligible number of people like me, and when a browser immediately shoves AI features in my face on first launch, well, the first thing I’m going to do is disable them.
The especially tragic part is that I personally find LLMs useful! And I’m at the point where I sorta want to install a Firefox extension for ChatGPT now. But the actual browser AI features were pushed on me in a way that made me feel violated, so I can’t use them on principle. Maybe in a few years I guess.
If instead these companies would just dial it back several notches, I would have had the curiosity to try these features out myself, and I’d likely be using them by now. But the way they’ve tried so hard to force them on me has destroyed my trust and now, not only am I not using whatever feature they promote, I hate their product more than I otherwise would.
Firefox isn’t actually that bad here, and now that there’s a simple kill switch, I may actually try their chatbot sidebar thing. But for companies like MS, I will never, ever, ever use any of their AI features for the reasons above. (I’ve literally uninstalled Windows now, it’s gotten so bad.)
How is a company supposed to accommodate your personality while also showing other user new features that Firefox just added to the browser? If you're a contrarian by nature Firefox can't help you nor change their strategy to suit you, because the majority of users aren't like you.
You never, ever need to interrupt the user or stop them from what they’re doing in order to show them some new feature.
Here’s what you do:
- Make a “what’s new” section in settings.
- Put a link in there that takes me to a webpage where I can see what’s new.
- That’s it.
Instead what always seems to happen is that I’m in the middle of trying to do something with the software and in order to do that I must close whatever popup you’re shoving in my face to tell me about the new feature. I don’t have time to read it now because I opened the software with an intention to finish a task and I don’t have time to read it now. And then later when I finally do have the time to look at your new feature? Nobody bothers actually putting that information anywhere persistent, so I guess I’m out of luck even if I care about the feature.
Updating to a new iOS version is a perfect example of this. Say there are a dozen apps that have a new feature popup on first launch when you update iOS. Imagine a typical day waking up and trying to use my phone. I have to drive somewhere so I try to put an address into Maps and have to immediately fend off the “what’s new in maps” dialog so I can type the address I need to go to. Then I want to put on the song my kid is yelling at me to play and have to fend off the “what’s new in Music” popup. Later I’m trying to respond to an important text and have to fend off “What’s new in messages”, etc etc etc.
That first day using iOS is an absolute nightmare because of this.
Now imagine the alternative: a simple badge icon in the settings app, and I tap it and see a link to “what’s new in iOS”, and guess what, it can be a fucking webpage! I can bookmark it! I can add it to my reading list and see it later! Hell, I can even share it with my friends!
But no, instead apps insist on trying to increase “engagement” with their new feature, because some PM’s promo packet wants to include “this many users used my new feature” and the only way they can think to do this is to (1) stop the user from accomplishing their task until they tap the cutesy “Got It!” button, and (2) don’t bother with persisting it anywhere, because the idea that the user doesn’t have time to check out the feature now is so foreign to these sociopaths it never even crossed their mind.
Whatever works for large numbers is what will happen.
But overall, you and I (and many) will try to push back and insist on consent.
The sign-up form with an unchecked "sign me up for your newsletter" option.
The first-run experience with a question... "do you want us to notify you of new features?"
But this is not the norm, and even if good actors get rewarded by a few childish customers, bad actors seem to get rewarded much more by a massive infusion of funds.
IME, a 1.0 version is usually when a project starts taking backwards compatibility seriously. A pre-1.0 library may be plenty stable enough in terms of bugs, but being pre-1.0 means they’re likely going to change their mind on the API contract at some point.
That is the major problem for me… I don’t actually mind that much if a library has bugs… those can always be fixed. But when a library does a total 180 on the API contract, or removes things, or just changes their mind on what the abstraction should be (often it feels like they’re just feng shui’ing things), that’s a major problem. And it’s what people mean when they say “immaturity”: if I build on top of this, is it all going to break horribly at some point in the future when the author changes their mind?
People often say “just don’t update then”, but that’s (a) a sure fire way to accumulate tech debt in your codebase (because some day may come when you must update), and (b) you’re no longer getting what could be critical updates to the library.
I don’t think GP is moving the goalposts at all, rather I think a lot of people are willfully misrepresenting GP’s point.
Rust-to-rust code should be able to be dynamically linked with an ABI that has better safety guarantees than the C ABI. That’s the point. You can’t even express an Option<T> via the C ABI, let alone the myriad of other things rust has that are put together to make it a safe language.
It would be very hard to accomplish. Apple was extremely motivated to make Swift have a resilient/stable ABI, because they wanted to author system frameworks in swift and have third parties use them in swift code (including globally updating said frameworks without any apps needing to recompile.) They wanted these frameworks to feel like idiomatic swift code too, not just be a bunch of pointers and manual allocation. There’s a good argument that (1) Rust doesn’t consider this an important enough feature and (2) they don’t have enough resources to accomplish it even if they did. But if you could wave a magic wand and make it “done”, it would be huge for rust adoption.
Since Rust cares very much about zero-overhead abstractions and performance, I would guess if something like this were to be implemented, it would have to be via some optional (crate/module/function?) attributes, and the default would remain the existing monomorphization style of code generation.
Swift’s approach still monomorphizes within a binary, and only has runtime costs when calling code across a dylib boundary. I think rust could do something like this as well.
You could maybe say that a pointer can be transmuted to an Option<&T> because there’s an Option-specific optimization that an Option<&T> uses null as the None value, but that’s not always guaranteed. And it doesn’t apply to non-references, for instance Option<bool>’s None value would be indistinguishable from false. You could get lucky if you launder your Option<T> through repr(C) and the compiler versions match and don’t mangle the internal representation, but there’s no guarantees here, since the ABI isn’t stable. (You even get a warning if you try to put a struct in your function signatures that doesn’t have a stable repr(C).)
You're right that there isn't a single standard convention for representing e.g. Option<bool>, but that's just as true of C. You'd just define a repr(C) compatible object that can be converted to or from Option<Foo>, and pass that through the ABI interface, while the conversion step would happen internally and transparently on both sides. That kind of marshaling is ubiquitous when using FFI.
Right, that's the whole point of this thread. The only stable ABI rust has is one where you can only use C's features at the boundaries. It would be really nice if that wasn't the case (ie. if you could express "real" rust types at a stable ABI boundary.)
As OP said, "I don't think deflecting by saying "but C is no safer" is super interesting". People seem intent on steering that conversation that way anyway, I guess.
> IMO, it's best to keep things that are "your fault" (e.g. produced by your editor or OS) in your global gitignore, and only put things that are "the repository's fault" (e.g. build artifacts, test coverage reports) in the repository's gitignore file.
Very well put. This should be in the git-ignore manpage.
I'll note that when I convert code between languages, I often go out of my way to minimize on-the-fly refactoring, instead relying on a much more mechanical, 1:1 style. The result might not be idiomatic in the target language, but the bugs tend to be a bit fewer and shallower, and it assists with debugging the unfamiliar code when there are bugs - careful side-by-side comparison will make the mistakes clear even when I don't actually yet grok what the code is doing.
That's not to say that the code should be left in such a state permanently, but I'll note there's significantly more changes in function structure than I'd personally put into an initial C-to-Rust rewrite.
The author of this rewrite appears to be taking a different approach, understanding the codebase in detail and porting it bit by bit, refactoring at least some along the way. Here's the commit that introduced that fn, doesn't look like automatic translation to me: https://github.com/Ragnaroek/iron-wolf/commit/9014fcd6eb7b10...
Look into rust iterators and their associated functions for rust specific implementation. Additionally look into functional programming à la lambda calculus and Haskell for the extreme end of this type of programming if you’d like to learn more about it
It probably would.
But this port was mostly done to understand Wolfenstein 3D in detail, not for the source port itself.
I could have generated big parts of the code. But I would have learning by doing that.
> The question is: Whose job is it to manage the nulls. The language? Or the programmer?
> These languages are like the little Dutch boy sticking his fingers in the dike. Every time there’s a new kind of bug, we add a language feature to prevent that kind of bug. And so these languages accumulate more and more fingers in holes in dikes. The problem is, eventually you run out of fingers and toes.
I'm going to try to best to hide my rage with just how awful this whole article is, and try to focus my criticism. I can imagine that reasonable people can disagree as to whether `try` should be required to call a function that throws, or whether classes should be sealed by default.
But good god man, the null reference problem is so obvious, it's plain and simply a bug in the type system of every language that has it. There's basically no room for disagreement here: If a function accepts a String, and you can pass null to it, that's a hole in the type system. Because null can't be a String. It doesn't adhere to String's contract. If you try to call .length() on it (or whatever), your program crashes.
The only excuse we've had in the past is that expressing "optional" values is hard to do in a language that doesn't have sum types and generics. And although we could've always special-cased the concept of "Optional value of type T" in languages via special syntax (like Kotlin or Swift do, although they do have sum types and generics), no language seems to have done this... the only languages that seem to support Optionals are languages that do have sum types and generics. So I get it, it's "hard to do" for a language. And some languages value simplicity so much that it's not worth it to them.
But nowadays (and even in 2017) there's simply no excuse any more. If you can pass `null` to a function that expects a valid reference, that language is broken. Fixing this is not something you lump in with "adding a language feature for every class of bug", it's simply the correct behavior a language should have for references.
One thing that distinguishes macOS here is that the mach kernel has the concept of “vouchers” which helps the scheduler understand logical calls across IPC boundaries. So if you have a high-priority (UserInitiated) process, and it makes an IPC call out to a daemon that is usually a low-priority background daemon, the high-priority process passes a voucher to the low-priority one, which allows the daemon’s ipc handling thread to run high-priority (and thus access P-cores) so long as it’s holding the voucher.
This lets Apple architect things as small, single-responsibility processes, but make their priority dynamic, such that they’re usually low-priority unless a foreground user process is blocked on their work. I’m not sure the Linux kernel has this.
That it actually quite simple and nifty. It reminds me of the 4 priorities RPC requests can have within the Google stack. 0 being if this fails it will result in a big fat error for the user to 3, we don’t care if this fails because we will run the analysis job again in a month or so.
IIRC in macOS you do need to pass the voucher, it isn’t inherited automatically. Linux has no knowledge of it, so first it has to be introduced as a concept and then apps have to start using it.
Being explicit is a good thing. Especially for async threads they may handle work for many different clients with different priorities and may delegate work to other processes.