Full Width [alt+shift+f] Shortcuts [alt+shift+k]
Sign Up [alt+shift+s] Log In [alt+shift+l]
1
If all your time is spent watching output tokens, where do your input tokens come from? Letting an agent rip on full auto is basically doom scrolling. Even worse if you're doom scrolling while the agent runs. We humans love frying our dopamine receptors. This feels great until you realize what you were offloading: the struggle. The part where you fail. Failure is the entire point. You don't make progress in the gym unless you take a set at least close to failure. The muscle only adapts when it's forced to. It is no different for the brain. Cognitive Atrophy It is very hard to admit to yourself that your skills have atrophied. It is even harder to admit this to other people. I will admit that over the past several months my brain has gotten smoother (and I wasn't even on Twitter much!). Recently, I had written an abstraction for my diff viewer (diffy), an element system with a macro that lets agents write html-like code in rust for native ui (they reason better with this). But it wasn't adopted everywhere in the repo yet, so when I asked for a new feature, the model decided to hand paint it straight to the viewport instead. Every behavior the element system gives you for free was just... missing. Text wasn't selectable. Hover highlights wouldn't go away. And since I wasn't looking closely, it iterated on the slop and produced more slop, more bugs. I just kept saying continue. I lost a whole day untangling it, and the funny part is that once I actually looked at what it had built, every bug was the same bug. When you hit a roadblock and your immediate reaction is to reach for something else (previously, this used to be other people, but now it is a language model) you are essentially skipping the part where you actually learn to solve the problem. It is funny how one of the best "learning tools" has turned out to be the number one cause (anecdotal. sue me) of the lack of learning! It's been a few months since I started writing this, and things have gotten more dire....
12th Jul 2026

Stay updated

Get a weekly newsletter with the top 5 articles worth reading every week.

More from seated.ro

glimpses of the future

Glimpse v1.0 Glimpse can now build call graphs, showing you exactly how functions relate to each other in your codebase. Video # what does main call? glimpse code :main # what calls this function? (reverse call graph) glimpse code :process_request --callers # limit the depth glimpse code :build --depth 3 This works by parsing your code with tree-sitter, extracting function definitions and calls, then resolving those calls to their actual definitions. Precise mode Sometimes tree-sitter based resolution isn’t enough. Maybe you’re dealing with dynamic dispatch, generics, or just a language with particularly complex module resolution. For this, Glimpse can use LSPs to resolve definitions semantically. glimpse code :main --precise This spins up actual LSP servers and uses goto-definition / goto-implementation to resolve calls. It’s slower, but accurate. Glimpse will attempt to auto-install the LSP servers for you. Indexing Glimpse eagerly caches whatever it finds into an incremental index. But you can choose to pre-build the index ahead of time for instant queries. # build the index glimpse index build # with LSP for precise resolution glimpse index build --precise # check what you've got glimpse index status The index stores all the definitions, calls, and resolutions so subsequent queries are fast. Language support Glimpse now supports: Go, Rust, C, C++, Python, TypeScript, JavaScript, Zig, Java, Scala, Nix, Lua, Ruby, C#, Kotlin, Swift, and Haskell. Each language has custom tree-sitter queries for extracting definitions, calls, and imports. The grammars are downloaded and compiled automatically on first use. Try it # install cargo install glimpse # or with homebrew brew tap seatedro/glimpse && brew install glimpse # or with nix nix profile install github:seatedro/glimpse # then just glimpse code :main

1st Jan 2026 1 votes
Devlog 001

This is a general devlog covering what I’ve been up to over the past few months! Haskell Hakyll is a Haskell library for generating static websites (yes, you do not, in fact, need Next.js for your personal site). The previous iteration of my website was written with Go + templ, and it was not static. I wrote everything myself, and it was, quite frankly, a horror to maintain. The templ LSP actually hinders more than it helps, and since I did not statically generate the content, it was kind of slow for a personal website. I did not like it. I added some very minor CSS fixes and a theme toggle button for my friend’s new website ludwigabap.com, and I saw the light that is Hakyll. :kneel: So I nerd-sniped myself into rewriting my personal website in Hakyll so that it generates beautiful HTML at build time (it uses Tailwind, too). All the dynamic bits of the website, like my silly stats and coding time, are served from a single Rust Axum server binary on my Hetzner VM that serves other stuff too (Memegrep’s server, among other things). Nix-pill This segues into my next nerd-snipe, or rather, my favorite new pill: the Nix pill. My entire website is built with a single Nix flake, including the Hakyll build step, the Cargo build step, and generating the resulting Docker image. Although, to be honest, the learning curve is very steep and I simply do not have it in me to master this language anytime soon, I like the principles, and it seems to me the least bad build system out there. I do most of my work on a MacBook running a NixOS VM as well. (seatedro/dotnix on GitHub.) It’s so much nicer to have a real dev workflow versus whatever the fuck macOS is. Sorry, but Homebrew is not good software. Ember The reason I started programming was that I was playing a game called Midtown Madness as a wee lad and decided that one day I would build a cool game like that. So, after 15 years, I’ve decided to embark on a small adventure to build a cool physics simulation (and eventually a voxel) engine. It’s written entirely in Zig because I enjoy writing Zig and did not want to touch C++ (although there were times I thought about committing this sin). When Ember gets far enough, I might write separate devlogs, but with what’s written so far, there isn’t enough to justify one. I was knee-deep in the mines because I wanted extremely specific features like multi-viewport docking with ImGui, and the off-the-shelf Zig libraries did not want to ship that for some reason. So there were many adventures in getting this shit to compile neatly. Ember now uses SDL3 for windowing and has an abstract rendering API (rudimentary, but the backends are in place) with SDLRenderer3, OpenGL, and WGPU-native backends that can be neatly switched at comptime. I’m using a bunch of cool resources to learn more about how to do this because I’ve never really written any game-dev related code before. I just want to build some cool simulations, and I will get there no matter what. github / seatedro / ember Thanatos After 5 years, I have finally built a new personal computer. I will be running NixOS as my main operating system with Hyprland and Wayland. I will also have Windows installed on a separate drive mainly for video games, though I expect to use Linux more often. It’s so nice not having to worry about my 256 GB SSD getting filled up on my MacBook Air. :> Exa Also, I joined Exa last month to work on the back-end team, and it has been so fun! I am soaking up as much knowledge from my significantly smarter peers at a good pace. As per custom, I revisited @ludwigABAP’s post: On becoming competitive when joining a new company. (PS: it’s on a new website.) Fin Back to the code cave I go—going to extract the polymorphic.

13th Jul 2025 1 votes
rabbit hole learning

Look everything up Pretty much the best way to learn that I have found is to refrain from suprressing your innate curosity and let it go wild. Most of the time, you will encounter a term or concept that you do not know, instead of glancing at it briefly, go all in. Google it, read the wiki page, found someone’s blog post? Read it. Watch that youtube video (I only do this if it’s not 3 hours like your average Sphaerophoria stream). Dive head first into rabbit holes. I’ll outline an average day where I have two types of goals: - Concrete goals: Like finish implementing X feature in Y project - Loose goals: Learn about X or Y. I will include rough timestamps but they are pretty much meaningless because productivity levels vary immensely throughout the day. 9:00 AM Decided to learn about document parsing. Links: EPUB specification, I found out that EPUBs are just an archive with HTML, and nearly had a crisis. (Now I know.) Immediate questions: so I need to parse the EPUB, extract metadata, fetch the XML and parse that too. Eventually I would have to use a WebView to render the HTML/CSS on the screen to render the book. (Unfortunate.) Found out that in order to read the PDF spec, you need to pay like 350 swiss francs! Spend time perusing SwiftUI docs, and asking grok about how I can render things on the screen with Swift. Fiddle with XCode, marvel at how Swift gets pretty much everything right but uses func ... for declaring functions. It has Result<T, E> though, so forgiven. 11:00 AM Began reading Computer Systems: A Programmer’s Perspective (CSAPP) Studied numeric representations, created Anki cards for hexadecimal conversion 12:00 PM Rabbit holed into learning so much about UTF-8 Bookmarked to learn more about UTF-8 and UTF-16 and writing a parser for it later (ILY @zack_overflow) 1:00 PM Taking a break, lunch + watching a movie. 2:30 PM Read Jon Olick’s single file resize implementation in C++ as reference (ILY @gizmobly) to roll my own resize library for use in glyph Rabbit holed into learning more about Sinc filters and the Lanczos Kernel. 3:30 PM Shifted to working on memegrep(v2). This is where I already know the goals I want to accomplish before the day ends. I implemented a pub/sub flow to help with scale when users upload their private memes. Rough sketch in mind: user uploads meme(s) → server receives req → insert skeleton into db → queue upload → return 201 to user immediately → worker picks up task Spent the next 6 hours coding without even realizing 6 hours had passed (bliss) Ended up with multi-file upload, search, deployed a CLIP model, added all the scaffolding needed in the UI for this. 9:30 PM I posted something about pointers on twitter and ended up reading some history about the nomenclature just for fun. Links: pointers, handles are the better pointers Also saw something about reference counting being used in the libvips library earlier in the day, so decided to check out their implementation since i’ve only used it in rust quite often. reference counting, Rc and Arc 11:00 PM Was in bed and saw a post linking an amazing article by Valve on Source Engine Networking, so ended up being a nice and light read. At the end of the day I ended up with more questions, but I definitely had more answers than when I started! Here’s a DAG of my exploration for fun:

9th Mar 2025 1 votes
two weeks is all you need

two-weeks I built a website (twoweeksisallyouneed dot com) with just Claude 3.5 Sonnet, zero lines of code written by me. Why I did this So a couple weeks back I had a computer vision midterm and i was allowed a single page of notes. I decided to use Claude to generate a cheat sheet in LaTeX. It was crazy lol, I was able to cook up something usable in 15 mins. pic.twitter.com/0tvIsdv34d — ro/nin (@seatedro) October 24, 2024 Someone had asked me to make a similar cheatsheet for ML, but I thought why not get claude to make an entire website instead? Early days I didn’t really give claude any specific information except what I wanted to build. My plan was as follows: > build out the UI skeleton first > populate with some dummy data > set up a content pipeline > tie up the ui with the data > fix bugs Claude decided to use react (Shocking). With just a couple of chats I was able to get the retro/hacker/matrix style UI down. (It’s going to be hard for frontend engineers to keep up with AI at this rate) I spent some time building and adding secrets/easter eggs to the website which no one has found yet lmaoooo. If/when all the easter eggs are found, I will open source the repository. Good hunting until then bros. Frustrations Things got really annoying, really fast. As soon as I wanted to build some sort of content pipeline, everything went to shit. Claude, no matter how smart of an AI, is not human. It did not think ahead. If I was going to build out this website I would not have started with a barebones react/vite app. I would have probably gone for a full stack framework like sveltekit instead. Generating content for the website was/is a nightmare. LLMs hallucinate, this is known, but did you also know how incredibly frustrating it is to get them to follow instructions? There were multiple instances where Claude (with all the 40% of project context of javascript code) generated a TypeScript interface and proceeded to spit TypeScript code. This project has 0 TypeScript???? The new edit in place nonsense was getting on my nerves. Half the time the output artifact wouldn’t even change, and the other half it would mess up the changes. I have to mention “please use a new artifact” if I wanted any real usable code. I was enthusiastic about building something with just Claude the first few days, then I started getting weary, and then eventually I wanted to take a sabbatical from using AI. When the project context grows, (think like 20% or more), Claude seems to have a hard time using that information. Often times I found myself hitting send, and Claude would spit some nonsense, I would hit stop and paste any relevant code directly and then get some useful code. Context is probably the biggest annoyance I’ve had with LLMs. Random thoughts Perplexity (with claude 3.5) is great (to an extent) because it’s essentially a RAG search so I was able to get somewhat up to date content for the resources and references sections from it. I feel like I was able to ship something of decent quality for sure, but I lost a lot of brain cells during the process. Do not take away from the programmer the only thing he wishes to do, program. Proompting I didn’t particularly do anything unique to get the best out of my prompts/chats. I did do everything in a Project on claude dot ai though, which let me set Project Instructions like so: BE ENTHUSIASTIC. WE ARE GOING TO CHANGE THE WAY THE WORLD LEARNS WITH THIS WEBSITE🚀🚀🚀🚀 LLMs seem to be much more open to doing anything you ask if you gaslight them, so go ahead and do it. Here are some prompts that I used while building the website: PROMPT ------ This is AWESOME: * For the loading screen add some text that says "you can learn anything in two weeks" * The ascii text is also weird, it says erain? is that supposed to mean something? * Where did all my placeholder topics go? * MOAR scrt scan lines * The matrix rain needs to fall vertically and it should be subtle. On mouse move it should get a bit brighter (the char under the mouse) What else do you think you could add? Surprise me One time I asked Claude to add something and it started changing the existing UI????? PROMPT: ------ OKAY, we have a beautiful boot sequence now. let's flesh out the main content screen. First let's fix some bugs: * The animations restart everytime i move my mouse instead of continue organically * What i mean is, when i move my mouse over the windows or around the matrix rain, the matrix rain restarts and so do the typewriter effect on the window title Work on these * [REDACTED] Easter eggs: * Fun Features: * "Power saving mode" that dims everything except what you're reading ....[REDACTED] So many times I ended up editing the prompt and adding lines like this: PLEASE DON'T CHANGE THE EXISTING UI. IT LOOKS GOOD BRO. I’ll just add some random prompts here PROMPT ------ Broski, we need to make the UI responsive and shit. Lot of people are reporting issues with it on mobile and smaller screens PROMPT ------ what sort of content do u think we should add? i was thinking things like formulae, charts (for phd), code blocks (for eng), research papers, youtube video links, blog posts etc. Let's think out loud how we're gonna do this before we proceed PROMPT ------ `pasted_code.jsx` Here is my current dashboard. Here is some sample concept content i have: `pasted_data.json` I need you to render this beautifully in the dashboard. Make any and all changes needed. It needs to look beautiful. And anything else u feel would be good. List out the things you're adding before adding it okay? Concluding thoughts This was a good experiment, a success. If you have a clear vision for what you want your product to be, then AI can help you achieve that vision quite well! However, I don’t think I will be using AI for the foreseeable future. I feel like my learning is stagnating the more i use AI and I want to write my slop code with my own two hands. I might use avante.nvim to quickly write some duplicated code here and there but by god, I miss coding. Actual coding.

21st Nov 2024 1 votes

More in programming

Abusing ID3 chapters to turn videos into glanceable podcasts

I listen to a lot of podcasts, and I like how they fit around other tasks. I press play, lock my phone, and put it down. I’m free to wash the dishes, fold the laundry, or shop for groceries. Unfortunately, more and more information is only published as a video. Technical talks, conference sessions, video essays – they don’t work in an audio-only podcast app. I could convert these videos to MP3 files, but that breaks down the moment a video isn’t pure spoken word. If a speaker says, “Look at this slide” or holds up a diagram, an audio-only file leaves me stranded. I don’t want to give up the podcast player I like, nor stare at a screen for an hour – but I do want the information in these videos. To solve this, I’m abusing my podcast player’s chapter support. This gives me the best of both worlds: I can listen to a video as audio-first, and glance at my lock screen if I need a moment of visual context. The idea: Chapters every few seconds MP3 files can have ID3 metadata, and ID3 metadata can include chapters. A chapter covers a particular time range, and it can have an associated title, description, and cover art. My podcast app of choice is Overcast, which can’t play videos, but it does have robust chapter support. I can jump between chapters, navigate a table of contents, and see per-chapter cover art. To get videos into Overcast, I’m creating MP3 files with a new chapter every few seconds, and the per-chapter cover art is a corresponding frame from the video. As I play the file, I get a slow, stop-motion-like rendition of the original video. If my phone is locked, I can glance at my lock screen and see the current frame in the Now Playing screen. Overcast is developed by Marco Arment, and I got this idea from Forecast, his app for adding chapters to podcasts. In particular, I was struck by its ability to create chapters that don’t display in the chapter list – ideal if I don’t want a table of contents with hundreds of entries. As I was developing my script, I compared my output to the output from Forecast to ensure I was creating the chapters correctly. The code: FFmpeg and Mutagen There are three steps in this process: Convert a video file to an MP3 Extract images from the video at a fixed interval Insert the images as hidden chapters in the MP3 file Let’s go through each in turn. 1. Convert a video file to an MP3 Converting a video file to an MP3 is a single FFmpeg command: ffmpeg -i video.mp4 audio.mp3 This is consistently the slowest step of the process, and I do wonder if I could use different settings or an alternative encoder to make it go faster – but it’s not slow enough to be worth further investigation. 2. Extract images from the video at a fixed interval Extracting images from a video needs a more complicated FFmpeg command: ffmpeg -i video.mp4 \ -vf 'fps=1/5,scale=iw*sar:ih,scale=min(iw\,945):min(ih\,945):force_original_aspect_ratio=decrease' \ thumbnail_%04d.jpg This extracts an image every 5 seconds, downscales any image larger than 945 pixels square (while preserving the original aspect ratio), and saves the results as sequentially numbered JPEG images (thumbnail_0001.png, thumbnail_0002.png, and so on). The key is the -vf flag, which defines two FFmpeg filters: The fps filter selects one frame every 5 seconds (fps=1/5). The first scale filter scales the width based on the sample aspect ratio (scale=iw*sar:ih). Without this filter, frames can be stretched and distorted. The second scale filter scales the input video, preserving the original aspect ratio (force_original_aspect_ratio=decrease), and ensuring the output images fit within 945×945px or the size of the input video, whichever is smaller. My limit is 945 pixels because that’s the largest size that cover art is shown on my iPhone. This filter still isn’t completely correct – it sometimes creates images from portrait videos that are smaller than I’m expecting – but it’s good enough. These are only thumbnails for glancing at, and if I want to change it later, I can always do the image resizing outside FFmpeg. 3. Insert the images as hidden chapters in the MP3 file Inserting the chapters into the MP3 file is more complicated. Although FFmpeg has basic support for ID3 metadata, as far as I know, it can’t insert chapters with per-chapter artwork. Instead, I’m going to reach for Python and the Mutagen library. Here’s the code to add a chapter to an MP3 file: from mutagen.id3 import APIC, CHAP, ID3, PictureType audio = ID3("audio.mp3") with open("thumbnail_0001.jpg", "rb") as f: img_data = f.read() image_frame = APIC(mime="image/jpeg", type=PictureType.OTHER, data=img_data) chapter_frame = CHAP( element_id="chp1", start_time=0, end_time=5 * 1000, sub_frames=[image_frame] ) audio.add(chapter_frame) audio.save() This creates a single chapter that lasts the first 5 seconds (0 to 5000 milliseconds), and the per-chapter cover art is thumbnail_0001.jpg. If we ran this in a loop, we could add images for every 5 second slice of the original video. This code is inserting two frames into the ID3 metadata: The CHAP (chapter) frame contains the timing information, and it can have subframes for metadata like title, chapter art, or associated URL. The APIC (attached picture) subframe contains information about a picture, which can either be a blob of image data or a URL to an image on the web. Normally, you’d also insert a CTOC frame which defines a table of contents, but I don’t want a TOC with hundreds of 5-second chapters, so I’m deliberately not doing this here. This is allowed by the ID3 spec – you’re not required to insert a CTOC frame if you’re using chapters, and you can have chapters that aren’t listed in your table of contents. To work out which frames I needed, I used Forecast to create some chapters by hand, and I inspected their frames. In particular, loading an MP3 and calling Mutagen’s pprint() method shows a human-readable list of frames, and then I could drill into the individual fields: from mutagen.id3 import ID3 audio = ID3("audio.mp3") print(audio.pprint()) I wrapped all this code in a project called glancecast, which allows you to convert a video file with a single command, with optional flags to set the frame length and chapter art size: $ python3 glancecast.py interesting_talk.mp4 interesting_talk.mp3 The process takes a minute or so to complete, most of which is spent transcoding the video file to MP3. The resulting MP3s are usually 40 to 50 MB in size, which is very reasonable. The outcome: How it looks in practice Here’s what one of these “glanceable” podcasts looks like in Overcast and on my lock screen: Maggie Appleton presented this talk over two years ago and it’s been on my “talks to watch” list ever since. Once I put it in Overcast? I listened to it in less than a day. It’s not a lot of extra information, but enough that I can quickly glance down and get the gist of what a speaker is saying. Both views update with a new frame every few seconds, or I can put my phone in my pocket and ignore the screen. I’ve used this approach for half a dozen videos so far, and I’m happy with the results. I expect to keep using it, because I have a long queue of videos I’ve been meaning to watch. If you’d like to try this, check out glancecast for the full code and instructions. [If the formatting of this post looks odd in your feed reader, visit the original article]

15 hours ago 1 votes
AI Isn’t Replacing Open Source

Andrew Baker, the current Group CIO at Capitec Bank wrote an interesting piece on AI and open source, and how these tools that generate code according to one’s specification may replace the general reliance on open source implementations done by contributors around the world. I’d really recommend reading it. I have great admiration and respectContinue reading "AI Isn’t Replacing Open Source"

22 hours ago 1 votes
Confessions of an Unrepentant Slop Snob

A framework for thinking about when AI involvement is additive or a violation

2 days ago 1 votes
Planning with Agents: Divided Worlds, Boundary Objects, and Thicker Interfaces

Why we need richer, thicker interfaces and better boundary objects for collaborative planning with agents

2 days ago 1 votes
Foundations of Agent Friendly Codebases

A look at 10 foundational pillars that enable agents to operate more competently and more efficiently in any codebase.

3 days ago 1 votes
📚 BoredReading

You seem to be enjoying this.

Join free to unlock everything.

Create free account

Already have an account? Sign in