I believe AI in the hands of a less a experienced developer will cause them to produce much worse code. Or non-functional code. It's like giving a motorcycle to someone who only knows how to ride a bicycle. They will run it off the road to catastrophe. However if someone has strong and thorough expertise of their domain to micromanage the AI, and they are comfortable going quick in complex areas of that domain, then an AI lets them go faster and be more thorough.
I've been driving the clankers pretty hard for about 3 months now.
I feel like I have internalized the proper way to interface with them where I'm no longer compromising on anything. Nor am I 'vibecoding'. I'm simply going multiples faster and producing code the same way I would have if I had done so manually. It's not 'agentic' coding either. I have thorough awareness of everything it is doing and producing. I use it more like an active assistant, or a kind of super-resharper or dynamic validation layer. As much as I hate to admit it the term 'copilot' is very appropriate.
Really, I am ultimately compromising less. Because previously things I would not do because they'd be too time-consuming and are more-trivial, I can now do them. More exhaustive performance tests. More exhaustive scanning through technical specs of prior research. Widespread refactors which are trivial but could be time consuming. Just lots of stuff I'd typically punt on due to time management I can now just do all of that.
I'm sitting here wondering. How many others are there? I have only noticed two others from their posts that seem to be 'getting it'. How you drive the clanker, not to vibecode, not to send off into an agentic rabbit hole you are clueless about, but how to actively weave it into workflow to simply do more of better quality and compromise less on things you'd typically punt on due to time constraints. Who else feels they are getting sense of this?
This was a significant improvement in being able to deal with vulkan.
https://t.co/gFMG1cPAvF
I think in my mentality of it, I'm not letting it invent anything of it's own agency so much as I am instructing it to distill subsets of already explicitly defined things. Either from vulkan spec, or a system I have manually written out enough for it follow. Basically getting it to maintain high quality is ensuring you prevent it from trying to invent anything. Or 'extrapolate' into territory without explicit definition. It can only interpolate between existing things which explicitly defined to high quality. I'm liking the term 'Interpolation Coding' for this.
I could probably make a claude skill with some instructions on that. Basically any session requires several prompts of me telling it 'Stop doing that!' until it gets more obedient.
So... claude code would not allow you to ssh into anything through it. While codex does.
So currently I'm ssh'd into my openbsd webserver as root through codex and am letting it config everything and vibe code my blog directly in the production www folder as a CGI application programmed with C.
Look. Don't judge me. Look a this cool tree it made with my X posts as apples...
https://t.co/6zbUFFmqwh
@yacineMTB It's like giving a Harley to someone who only knows how to ride a bicycle. It's probably going to end up bad. But at least it's all virtual so they can't hurt anyone.
I've had a few non-programmer friends come to me with some app or website they've vibecoded. To which they are so happy with, but always with the caveat of, "I have no idea what the code is doing, I'm sure it's absolute shit, but it's working!"
Too which I am genuinely elated. I don't see why some people get so upset about this. Maybe it's because I don't feel threatened at all by it?
I imagine if you are in a problem domain where someone could vibecode half-decent results it might set off alarms. But if you feel like vibecoding is encroaching on your territory maybe that is a sign you need to do something more difficult?
It reminds me of when Unity started to pick up momentum. Around version 2 or 3. Too many seasoned gamedevs were having freakouts about all the "unity slop" being pumped out. Then the iOS app store getting flooded with "amateur unity trash". I find there is still a deeply embedded resentment in those who were apart of older established gamedev companies during that time. Where they'll ignore you or be hyper-critical if you have too much Unity or C# on your resume. They were just so upset the bar got lowered and other less skilled people could now make stuff that might pass as comparable to what they felt was such hard difficult work.
Which I also loved that era when amateur half-finished Unity experimental games were all over the web and app store. I did not get why some were so threatened and upset by it. Do something more difficult or stake your ego on something more meaningful if it's that big of an issue.
I am very amused with creative cultures in any form. Not everyone needs to make some highly polished and perfectly crafted masterpiece to contribute to a creative culture. All the half-baked experiments, flaws and failures that come out of the churn of a frenetic creative culture is part of what makes things like that interesting.
- Use clang C++23.
- Disable exceptions and related.
- Disable RTTI.
- Disable libstdc++ linking.
- Disable all the warnings about using C99 features.
- Use plain libc headers and clang builtins directly.
- Make minimal versions of containers you need tailored to your exact need.
- Selectively use c++ template-only headers for syntactical sugar with std::initializer_list or std::atomic or C++ attributes.
- Make minimal use of templates where you'd otherwise go overboard on a macro. Ensure to use the compile time metric of clang periodically to make sure you've not done anything which makes compile time go off the rails.
- no virtual methods.
- no access modifiers.
- never use 'class' only use 'struct'.
- C++ 'requires' constraints are useful.
- For your general application state prefer a fat struct with namespace or global scope methods. Only put methods on struct when they are utility methods to operate on a POD struct. Such as clear or push to a list. Or invert a matrix.
- Prefer static create methods rather than constructor. Only use constructor if its for some kind of syntactical sugar on a POD type or template.
- Always prefer a static allocation or the stack over heap allocation. Malloc and free are just fine for when you need bigger chunks. If you are calling these so many times that it becomes complicated to deal with you are doing something else wrong.
Then you get the best of C and the best of C++. Generally it is better because strategic template use can make a codebase better.
The ONLY thing you lose is the way compound literal lifetimes work in C. Which is unfortunate. But you can still take a pointer to a compound literal within a method call and rely on that temporary value existing for the lifetime of that single call. Which can cover most of the scenarios where you'd need to do that.
I've been calling this `GNU C+-`
I know we have like several flavors of notions in this direction floating around. But that is mine.
@SebAaltonen I'm glad you post little notes about ways to properly use AI that you discover, rather than hopping on the anti-AI bandwagon. I find it much more useful.
An explicitly defined jump to an explicitly defined label in a single method is bad because the control flow is difficult to reason about statically...
So let's implement try catch blocks and exceptions which let control flow jump backwards from anywhere in any level of nesting with unpredictable overhead?
I find it very difficult to apply the word "solves" to that.
The LLM being so good at debugging and catching errors made me less concerned with the language having features built-in to check that. Can feed the AI any ASAN error, or callstack error, or validation error and it pinpoints exactly what is wrong in a few seconds and can fix it.
It's made me want my code extremely compact and minimal. So the portion exposed to me is the least amount of text possible I need to read to get the gist of it. I'd rather all the extra syntax and other stuff related to that be pushed to something else that mostly keeps it from taking up space in my code and my mind.
The truth is... it is not "AI Programming" vs "Non-AI Programming".
It is:
"AI Programming"
vs
"Massive Bureaucratic Corporation to Manage the Massive Tedious Slog of Maintenance and Implementation Work No One Wants to Do."
One of the things that stood out to me among the vocal programmer community is Andreas Kling, making laydbird browser, jumped on AI and agentic coding. I assume because he's in a problem domain where that "Massive Tedious Slog of Maintenance and Implementation Work No One Wants to Do" is overt and clear. And the competition to any independent open source effort is obviously a "Massive Bureaucratic Corporation".
Conversely those who seem to be most adamantly anti-AI and convinced they can manually write every line of code to a higher quality. It's because your project is not as ambitious nor as large. You are working on smaller scoped, niche, projects. Albeit very cool and important things in some cases, but they are smaller projects. Things where you can fully grok the entire project and keep strict overview of every little detail. You aren't trying to do something which would typically need a "Massive Bureaucratic Corporation" to manage and maintenance.
The ironic thing of it too, I also don't know anyone who is leaning in the anti-AI camp who is also simultaneously greatly in-love with making contributions to something like Chromium codebase. Or any other codebase that has turned into such a monstrosity it needs a big corporation with a passive money printer to subsidize it's management and development cost. That generally you've deferred to smaller scoped niche specialized projects because you'd probably hate having to work in one of those Massive Bureaucratic Corporate codebases. Which means you don't demonstrate any solution to offer towards people in that problem domain. It comes off as hypocritical. You need to take on a comparably big effort and prove that you can actually corral a huge army of open source contributors to methodically go through and build everything line-by-line manually. Or demonstrate you love pushing through the slog of a Massive Bureaucratic Corporate codebase by making lots of meaningful commits to one of them.
Personally I don't think either will happen.
The Rust Servo project still sitting there in a barely usable condition is proof that you can't corral an army of open source contributors to take on something that big and ambitious.
Then if you cloned chromium or some other codebase under Massive Corporate Bureaucracy and had to spend a year trying to push some meaningful change through it. Unable to work on a smaller niche project which you can keep nicely curated and perfected. I think pretty quickly you'd start believing that passing a lot of that punishment onto AI sounds like a great idea.
Regularly now, for any thought about politics or general worldview, I will paste my notion into AI and ask it to critique it. To which rarely does it validate it. It typically tear it down, or highlights things that make me re-think something.
Sometimes I present these thoughts or arguments to other people. Also mentioning that I use an AI to validate my thoughts and perspective. To which a common response is that AI is sycophantic and it will just validate whatever your predisposition is.
I always ask back, what would you ask the AI? Not everyone has a subscription to run endless queries on supergrok or whatever. Which they might respond. Or just give me back an argument.
To which I copy/paste that to the AI and give them the link back. Never has it actually validated any such persons argument. In most cases it completely tore it apart for being factually incorrect and logically inconsistent.
At which the exchange goes from, "You are wrong because you used an AI to sort through your reason and AI just validates anything because it is sycophantic".
To, if you believe that is true. Well then. Here is your argument given to the AI which it thinks is nonsensical. Which means you have to consequently believe you are severely incorrect if you cannot even get a supposedly sycophantic AI on your side.
I am sure this depends on the exact model but the latest ChatGPT thinking and SuperGrok thinking models. Any question which can factually validated in anyway, or relies on any kind of sound logic, they can be absolutely brutal if you ask for a simple 'Critique' of some thought of yours.
Even if they are sycophantic. People going from worldviews so distorted that not even a sycophantic AI will validate them, to worldviews at least in the ballpark of reality such that a sycophantic AI might be able to validate them. That seems like a collective upgrade to me.
Everyone should probably argue their worldview and politics with AI more.
One of the things I have always preferred to do is copy slimmed down versions of my dependencies into my project.
If I can get away with forward declaring several types in my file directly, then linking, I'll do that.
Or if I only need several methods, or a few files of something, I will copy them out.
Or sometimes I might make an amalgam of the library if it can fit nicely in one file.
I really don't like having lots of "Stuff" in the project. Aside from the potential it could bloat something in the project. Compile time or binary size. More so the reason is I want to keep a grip on it and keep the project minimal. It makes searching the project and relying on a LSP simply work better. It explicitly defines exactly what you are allowed to use from some third party dependency, and if it turns out a project needs more, then that is an explicit decision which must be made by pulling in more of the library. Less surface area is always better. If you are concerned with being judiciously anti-slop and wanting to keep a strong grip on your projects you should always consider doing this.
There are some libraries I fully import or git submodule in simply because I use a lot from them and it's not worth the trouble. But I am always on the lookout to discern the absolute minimum I need to pull in.
Because of this I am discovering that Claude Code is essentially the greatest packager manager to ever exist. I do not mean that jokingly at all. Because it can automatically do this. I can clone some library outside my project. Start building some things off of it. Then prompt claude to copy over the absolute minimal necessities to make it work with only what I utilized. Which it will do. Perfectly. Since it's not inventing or extrapolating into novelty. Such an operation is constrained within what is explicitly defined.
Then if later on it turns out I need something more. Just another prompt to pull in the absolute minimum of only what I need.
I've been leaning on this heavily for the past few weeks and it just works. Because your not creating code you are collating subsets of existing code.
I'm starting to believe this is the better way to pull dependencies into a project. I never got how people can be comfortable with including chains of dependencies automatically through a package manager. It's one of the reasons I have been hesitant about rust. I expect cargo to turn into NPM in the long term. It's a major slop incentive inserted into the middle of an ecosystem which overtime compounds dependencies on dependencies on dependencies.
While conversely the big struggle of not having a package manager is you then have to manually pull in and watch over your packages.
The bigger pain of manually slimming them down, as I like to do, is then you encounter greater friction if you ever wanted to update them in the future or pull in more. It can be a time sink.
But not anymore. Now its as automated and quick as an actual package manager thanks to AI.
@segun_os_ Catching all those weird esoteric technical nuances and quirks you'd never keep top-of-mind concerning compiler differences or ways to use C++ templates are one of the things LLM's are remarkably good at.