Latest Posts (20 found)

Behold the perfect algorithm!

1984, Minority Report, Black Mirror — bedtime stories compared to the horrors the UK Government publish, am I right? I’m led to believe “Watch this space” is the latest propaganda piece from His Majesty’s Nanny State . I haven’t read past the title but according to gaming site Dexerto, YouTube lawyers read it and YouTube ain’t happy. Poor little YouTube. The government is consulting on options, considering whether to make public service news easier to discover on sites like YouTube and TikTok, with greater prominence and with more visibility during periods of major public importance. It also seeks to discuss misinformation and online viewing habits. YouTube urges creators to fight proposed UK algorithm changes - Matthew Benson, Dexerto I glossed over the Dexerto article too. This whole thing is something about kids being hooked on Skibidi and not paying their racketeering license fee . Minecraft Let’s Plays will be spliced with a BBC impartiality report on what some fascist gammon thinks. Should the proposal become law, of course. This is somewhat of a dilemma for a guy like me. If there’s one thing I hate more than a meddling GOV.UK, that might just be Big Tech . The thought of Google et al being ruffled warms my heart like a hot cup of tea on the summer solstice. That was too many words on something I never read so I’ll get to the lede. I’m about to reveal the secret sauce that Big Tech has tried to suppress. The one true algorithm, which ironically might be their saviour. Only one parameter is required in the perfect algorithm: who I choose to follow. I’m literally providing the exact data needed to curate my feed. I know what defenders of the deceptive arts are thinking: but algorithms are proven to increase engagement! — I know, Sherlock. Do you enjoy your doomscrolling misery? Not every metric needs to be min-maxed at the expense of human health. Modern apps sucks. Modern media sucks. Stick your “algorithm”. † It’s been decades since I studied SQL and database normalisation so please have mercy. Thanks for reading! Follow me on Mastodon and Bluesky . Subscribe to my Blog and Notes or Combined feeds.

0 views

sqlite-utils 4.0rc2, mostly written by Claude Fable (for about $149.25)

I wrote about the sqlite-utils 4.0rc1 release a couple of weeks ago. Since we only have Claude Fable on our Max subscriptions for a few more days, I decided to see if it could help me get to a 4.0 stable release that I felt truly comfortable about, since I try to keep to SemVer and like my incompatible major versions to be as rare as possible. I started with this prompt, in Claude Code for web on my iPhone: Here's that initial report it created for me. There were some significant problems that I hadn't myself encountered yet - 5 that Fable categorized as "release blockers". Here's the worst of the bunch: 1. never commits and poisons the connection (data loss) ( ) runs its DELETE via a bare with no wrapper — compare at , which wraps correctly. The connection is left , so every subsequent call takes the savepoint branch ( ) and never commits either. Reproduced end-to-end: That's a really bad bug! Very glad I didn't ship that, although at least it would have been a bug I could fix in a 4.0.1 point release, not a design flaw that would force a 5.0. Over the course of 37 prompts, 34 commits and +1,321 -190 code changes over 30 separate files, we worked through the entire set of feedback in turn, making several other design improvements along the way. A weird thing about coding agents is that harder tasks like this one actually provide more opportunity to do other things at the same time, since the agent sometimes needs 10-15 minutes to churn away on a new task. I went out to enjoy the Half Moon Bay 4th of July parade, occasionally checking in and prompting the next step for Fable from my phone. Full details in the PR and this shared transcript . I switched to my laptop for the final review, which I conducted through GitHub's PR interface. The most significant changes relate to transaction handling, which was the signature new feature in the earlier RC . The new RC now includes comprehensive documentation on the new transaction model, the intro to which I'll quote here in full: Every method in this library that writes to the database - , , , , , , , , and the rest - runs inside its own transaction and commits it before returning. Your changes are saved to disk as soon as the method call finishes: The same applies to raw SQL executed with db.execute() - a write statement is committed as soon as it has run. You never need to call , and you do not need to close the database to persist your changes. There are exactly two situations where you need to think about transactions: You want to group several write operations together, so they either all succeed or all fail - use db.atomic() . You are managing a transaction yourself with , in which case nothing is committed until you commit - the library will never commit a transaction you opened. In reviewing Fable's documentation - I find that reviewing the documentation edits first is an excellent way to build an initial understanding of what has changed - I spotted this detail : and the automatic per-method transactions are designed for connections in Python's default transaction handling mode. Connections created with the Python 3.12+ or options are not supported, because and behave differently on those connections. I admit I hadn't thought about how would react to the more recent autocommit setting , added in Python 3.12. It turns out "behave differently on those connections" equated to almost the entire test suite failing, so I worked with the model to ensure that this difference would not break how the library works. I used to think that the idea of having one model review the work of another was somewhat absurd - it felt weirdly superstitious. The problem is it really does work - I've started habitually having Anthropic's best model review OpenAI's work and vice versa, because I've had that turn up interesting results often enough to be valuable. I prompted Codex Desktop and GPT-5.5 xhigh with the following: Which was enough to turn up two issues worth investigating: I pasted that into a fresh Fable session, which ran some experiments to confirm the problem: Both findings were confirmed. called first, which auto-commits writes, and only then checked — so committed the update before raising . And the commit lived at the end of the returned generator, so it never fired unless you exhausted the iterator — or an un-iterated call left the transaction open, contradicting what the changelog and docs promise. Here's the PR with the fix, and the full Claude Code transcript . Reviewing this code helped me build a better mental model of the edge cases of SQLite transaction semantics! I upgraded to the Claude Max $200/month plan (I was previously on $100/month) to increase my Fable allowance for the remaining time until the July 7th Fablepocalypse , when even Claude Max subscribers will have to pay full API cost for the model. I was curious as to how much this would have cost me if I had been paying those costs directly. At first I thought those numbers weren't available to me since I had run the work remotely using Claude Code for web, and then I realized I could run AgentsView inside that existing session to get that cost estimate! Claude figured out how to use the command and came out with the following: I'm very glad I'm on that subscription! I really should have followed my own advice and leaned more heavily into subagents with cheaper models. Here's what claude.ai/settings/usage is showing me right now: I have several other major Fable-driven projects on the go right now as well, with the goal of hitting 100% on that Fable bar just in time for the price increase. Here are the full release notes for the RC. I had Fable add these to an "Unreleased" section of the changelog as each change landed, reviewing them as it went. This has the neat side effect that the commit history of the changelog acts as a concise summary of each of the changes that went into the release. In the past I've had a policy of writing release notes by hand, but honestly these are better than I would have created myself. Release notes are a great example of writing that I'm OK to outsource to agents because they need to be boring, predictable and accurate. Breaking changes: Everything else: You are only seeing the long-form articles from my blog. Subscribe to /atom/everything/ to get all of my posts, or take a look at my other subscription options . You want to group several write operations together, so they either all succeed or all fail - use db.atomic() . You are managing a transaction yourself with , in which case nothing is committed until you commit - the library will never commit a transaction you opened. [P1] sqlite_utils/db.py:663 now rejects non-row statements only after calling , and sqlite_utils/db.py:705 auto-commits those writes first. So raises but the update is already committed. That is a surprising side effect for a method documented as “can only be used with SQL that returns rows.” [P1] sqlite_utils/db.py:672 through only commits after the returned generator is fully exhausted. without iteration, or common usage, leaves the transaction open and the write can be rolled back on close. This contradicts docs/changelog.rst:15 and docs/python-api.rst:232 , which say it takes effect without iteration. Write statements executed with are now committed automatically, unless a transaction is already open in which case they join it. Previously they opened an implicit transaction that stayed open until something committed it - writes appeared to work when read on the same connection but were silently rolled back when the connection closed. Code that relied on rolling back uncommitted writes should use the new method to open an explicit transaction first. The transaction model is documented in full at Transactions and saving your changes . now executes its SQL as soon as it is called, rather than waiting until the returned generator is first iterated. Rows are still fetched lazily during iteration. SQL errors are now raised at the call site, statements such as are executed and committed immediately without needing to iterate over their results, and passing a statement that returns no rows - previously a silent no-op - now raises a recommending instead. A statement rejected this way is rolled back before the error is raised, so it has no effect on the database. Python API validation errors now raise instead of . Previously invalid arguments - such as with no columns, on a table that does not exist, or passing both and - were rejected using bare statements, which are silently skipped when Python runs with the flag. Code that caught for these cases should catch instead. and now raise if a record is missing a value for any primary key column, or has a value of for one. Previously such records - which can never match an existing row - were quietly inserted as brand new rows, or triggered a confusing after the insert had already taken place. and now raise a if called while a transaction is open. Previously they would silently commit the open transaction as a side effect of changing the journal mode, breaking the rollback guarantee of and of user-managed transactions. The class no longer has an method. It existed only to raise , since full-text search is not supported for views - calling it now raises instead, and the method no longer appears in the API reference. The command shows a clean error when pointed at a view. The no-op flag has been removed from the and commands. Type detection has been the default for CSV/TSV data since 4.0a1, so the flag did nothing - invocations using it should simply drop it. remains available to disable detection. now raises a if passed a connection created with the Python 3.12+ or options. and behave differently on those connections, which previously caused every write made by the library to be silently discarded when the connection closed. Fixed a bug where , and did not commit their changes, leaving the connection inside an open transaction. Their work - and any subsequent writes - could then be silently rolled back when the connection was closed. All three now use , consistent with the other write methods. The command now refuses to drop a view, and refuses to drop a table. Previously each would silently drop the wrong type of object if the name matched. Both now exit with an error suggesting the correct command to use. Migrations applied by the new migrations system now run inside a transaction, together with the record of the migration having been applied. If a migration raises an exception its changes are rolled back and it stays pending, so it can be safely re-applied after the error is fixed. Migrations that cannot run inside a transaction, such as those executing , can opt out using - see Migrations and transactions . and now detect the primary key or compound primary key of an existing table, so the argument is no longer required when upserting into a table that already has a primary key. can now be used to insert a row consisting entirely of default values into an existing table, using . ( #759 ) Improvements to the command: values that do not match any known migration are now an error instead of being silently ignored, now works correctly with migration files that still use the older class, and is now a read-only operation that no longer creates the database file or the migrations tracking table. now returns migrations in the order they were applied. New , and methods for taking manual control of transactions, as an alternative to the context manager. New documentation: Transactions and saving your changes describes how transactions work and when changes are committed, and a new Upgrading page details the changes needed to move between major versions.

0 views
Unsung Today

If you’re a button, you have one job

One thing I was (and still am) worried about when it comes to my recent big interactive essay is that by showing all these classic desktop examples, the whole thing might appear old-fashioned, relevant only to a bygone era. Yet, the challenges it shows are universal. Here’s something I just spotted. This is how you rotate an image on an iPhone and on a Nothing Phone: It’s a pretty standard control – tap once to rotate counterclockwise, tap a second time to do it again, etc. – with a helpful transition of the photo’s orientation so that you don’t lose yours. Now, I’m going to exaggerate the problem a bit and tap 90-degree rotation quickly eight times . Eight times should result in what engineers call a “no op” – the image rotating twice in full, and ending up where it started. That indeed happens on the iPhone: But it’s a different story on the Nothing Phone/​Android: iPhone will remember and buffer the taps, so that the second, pending rotation will happen as soon as the first is done. The Nothing Phone button gives you a tap confirmation via both haptics and sound, and then ignores the tap if a previous rotation is still animating. Why does it matter? I often keep thinking about the framework of situational disability , stating that disability is not just something that happens to a few people and no one else. No, pretty much everyone will occasionally encounter a situation that will make them effectively disabled, and this is why accessibility matters much more than many of us assume: = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/if-youre-a-button-you-have-one-job/5.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/if-youre-a-button-you-have-one-job/5.1600w.avif" type="image/avif"> I think similarly about casual and non-casual use. Photo-taking on phones is typically casual. Phone cameras are typically very good at detecting the photo orientation – but get confused when you’re pointing down. Now, as an example, if you had to take photos of a bunch of landscape documents, you might end up having to rotate dozens of photos, one by one. And it would be so much more predictable and pleasant if you could just tap the button three times at any pace you wanted without thinking, without paying attention, without getting your UI blocked by an animation that no longer helps you. This is, I suppose, “situational power user-ness.” Given a long enough timeframe – or, in this case, a large enough population – even a casual interface like phone photo editing (or, GarageBand ) will meet someone who will have no choice but to treat it more seriously and expect more from it. By the way, buffering the taps is not the only answer. You can also just stop/​accelerate the animation after an interrupting tap. But the rule is: never force the user to wait for the animation to finish. #android #flow #ios #touch

0 views
Unsung Today

“The root of all margin-collapsing evil”

I liked this page I just learned of called Incomplete List of Mistakes in the Design of CSS . It might not mean much to you if you don’t write CSS, but could be fun to check out if you do. Here are some choice quotes: It reminded me of a similar list called Known Anomalies in Unicode Character Names . Here’s one example: U+02C7 CARON U+030C COMBINING CARON The “caron” should have been called hacek and combining hacek . The term “caron” is suspected by some to be an invention of some early standards body, but it has also been claimed by others to have been in use at Linotype before the days of digital typography. Its true origin may be lost in the mists of time. These are great because they simply say “this is how we messed up.” They are succinct and candid about problems. More work needs to be done at this point, of course – the CSS list only really contains the “simple,” low-level observations, and I think for both CSS and Unicode fixes cannot simply be made because people and systems rely on the existing behaviour – but the first step is admitting you have a problem, right? If you’re on the outside, it can be comforting to realize “oh, it wasn’t just me, other people don’t like this, too.” (Scanning bug reports from other users can help in a similar way.) If you’re on the inside, consider making a list like this for a long-standing project. It might do you or your team good! If you are aware of more documents like these, I’d love if you could send them over. #bugs #change management #process should have been . It shouldn’t be — that reads to engineers as “not important”. We should have picked another way to write this. should be .

0 views
Unsung Today

“I know you think I’ve lost my mind, but trust me.”

A fun (and funny!) 9-minute video from Linternet User about designing a perfect onscreen lever with the right amount of juice : = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/i-know-you-think-ive-lost-my-mind-but-trust-me/yt1-play.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/i-know-you-think-ive-lost-my-mind-but-trust-me/yt1-play.1600w.avif" type="image/avif"> Love seeing real work in progress like that, plus it ends up in a place I didn’t expect. It was also great to see “delay and snap” action elucidated so clearly. It feels like a variant of rubberbanding (or, elastic scrolling) where you intentionally disconnect an object from the cursor or finger dragging it. #above and beyond #hardware #interface design #youtube

0 views

Chatting to a friend who has bought a pair of Meta AI glasses

I’ll be honest, I was a bit surprised that I knew anyone who would buy a pair of Meta AI glasses. Sure, they are readily available, and presumably heavily advertised, but most of the people with whom I spend time - online or offline - are not the kind of people who would buy them. I’ve got friends who use Facebook. I’ve got friends who use WhatsApp. But the glasses just - to me, anyway - feel rather different. Nevertheless, a friend did buy a pair, and was happy to chat about them. My friend - like me - is a married, middle-aged, white man. Unlike me, he saw the glasses in our local optician’s, and wanted them. We didn’t chat for long, and, to be clear, I was kind , not accusatory. And yes, he wore the glasses throughout our chat. It was an interesting conversation, because it was so unexpected. His choices would not have been mine, for sure. No, it did not worry him that using the glasses entailed sharing lots of data with Meta, or that this would entail sharing the personal data of other people Yes, he thought that they were rather cool, and that, it seems, was the main selling point. He didn’t need them for anything, he just fancied them No, he hadn’t really thought about whether other people might want to be filmed, or whether people might be worried about being filmed Yes, he had seen other people talking about them online, and they were talking positively about them. He hadn’t seen any negative commentary / criticism Yes, he uses “AI”, and rather likes it

0 views
Kev Quirk Yesterday

This blog is written in en-GB

by Terence Eden Terrence talks about some of the wonderful idiosyncrasies of the British language and that, no, he won't be making his writing more global. Read post ➡ I really enjoyed this post and like that Terrance could have said "year sure, I'll try and be more inclusive for you non-Brits" , but he didn't. Instead he said: Here's the thing. No. [...] There's a reason for that. It is more than the language I speak; it is the culture I live in, the way that I think, and the accent I use. Love this, and I appreciate Terrance holding firm on our wonderful British culture - just like everyone should do on their blog. That's part of the fun - to learn about the idiosyncrasies of difference languages and cultures. It still surprises me that someone had the gall to leave a comment effectively saying "can you change the way you write to be more inclusive, because I don't understand some of the references, and I can't be bothered to learn." Some people... Thanks for reading this post via RSS. RSS is ace, and so are you. ❤️ You can reply to this post by email , or leave a comment .

0 views
James Stanley Yesterday

ProofToken16: My Proposal for Private Decentralised Age Verification

So there's this whole thing now about how under-16s aren't meant to be allowed on social media, and this is supposed to be enforced through technical means using Zero-Knowledge Proofs, or something. Here is my proposal. Let's disregard the declaration of the independence of cyberspace for a moment and assume that actually we changed our mind and we do want the government to be mandating age verification on the web, and let's say we don't mind the fact that enforcing "no social media for under-16s" actually places the burden on everyone over 16 to prove it. Let's assume the requirements are: websites have a way to test whether the user is over 16 websites can't learn any private information other than whether or not the user is over 16 multiple decentralised issuers can provide proofs-of-age new issuers can be created without websites having to be updated to accept them the website can't tell which issuer you used this whole thing isn't secretly a tool to expand the surveillance state, it is in fact narrowly implementing only age verification Where everyone else is going wrong with private age verification is that they're trying to encode extra information about the user in the proof-of-age (like their actual date-of-birth, or the actual issuer), and then construct a zero-knowledge proof that hides this information from the website. What I propose is that the proof-of-age that is issued to a user over the age of 16 only contains the fact that they are over 16 . We purposely don't put any more information in the proof, and that way we can be sure that no vulnerability can leak this extra information, and we save a load of complexity. When the proof only contains that single fact, that the user is over the age of 16, it turns into just containing a single boolean. And since we will never bother to issue a proof where that boolean is false , the proof doesn't even need to contain the value! All proofs-of-age contain equivalent content (asserting that the user is over 16) so we can take the value of the boolean to be true , as long as the proof is valid. So all that remains is to issue an empty-string proof to everyone who is over 16, and let websites check that they are genuine. So let's pick a 4096-bit private key, keep it secret from under-16s, and say that knowledge of that key is the proof of being over 16. This is the ProofToken16 . Use whatever kind of message-signing scheme you want to let the user prove that they know the ProofToken16 . Since we only provide the ProofToken16 to people who are over 16, the ability to sign a message using it is proof of age. QED. Any new issuer can start up a service where they check your age however they want and reveal the ProofToken16 if you are over 16, with no centralised control. And, crucially, the decentralised nature will not be a backdoor allowing under-16s to create false proofs. To become an issuer you need to know the ProofToken16 yourself ! Since under-16s won't know it, they won't be able to issue it. Since all of the issuers are providing the same ProofToken16 , the website doesn't have any way to tell the issuers apart so the scheme does not even leak that information. There are a couple of minor drawbacks to this scheme, I admit: I'm actually not completely sold on the idea that age verification is even a good idea. What happened to a cyberspace without borders? What happened to the free and unencumbered flow of information? Humanity has spent tens of thousands of years building up our technological capabilities, to the point that we now have a global communications network that lets any two people on the planet communicate with each other practically instantaneously and practically for free. But it seems like in the last few decades we have been putting more effort into limiting our technological capabilities than expanding them, this can not end well, this is how we architect the downfall of civilisation, please be careful. And beyond that, requiring grownups to submit themselves to age verification before they can communicate with each other is disrespectful, undignified, and humiliating. Someone who knows the ProofToken16 might give it to someone who is under 16. Note this is not a weakness unique to my proposal. What stops someone from handing their proof to a child under any other scheme? If the proof reveals nothing other than whether the user is over-16, then a website has no way to check whether all of its users are using the same proof anyway. It is a fundamental technical impossibility to verify a user's age with cryptography, the closest we can come is to issue proofs-of-age and teach people not to share. I think that my ProofToken16 scheme is as good as you can do under the proposed requirements. Any alternative has at least the same flaws and possibly others besides. So I have already implemented it. I have created a ProofToken16 number, if you want to find out what it is then email me with proof of age and I will provide it. This will then entitle you to participate in my MatureChat social media site for over-16s only. You will have to do message signing at the command line every time you login, for now, but I am working on a browser extension to automate it. (The key will also entitle you to start your own ProofToken16 issuance service, which could one day be very lucrative!) See you on the other side. Go to MatureChat » websites have a way to test whether the user is over 16 websites can't learn any private information other than whether or not the user is over 16 multiple decentralised issuers can provide proofs-of-age new issuers can be created without websites having to be updated to accept them the website can't tell which issuer you used this whole thing isn't secretly a tool to expand the surveillance state, it is in fact narrowly implementing only age verification I'm actually not completely sold on the idea that age verification is even a good idea. What happened to a cyberspace without borders? What happened to the free and unencumbered flow of information? Humanity has spent tens of thousands of years building up our technological capabilities, to the point that we now have a global communications network that lets any two people on the planet communicate with each other practically instantaneously and practically for free. But it seems like in the last few decades we have been putting more effort into limiting our technological capabilities than expanding them, this can not end well, this is how we architect the downfall of civilisation, please be careful. And beyond that, requiring grownups to submit themselves to age verification before they can communicate with each other is disrespectful, undignified, and humiliating. Someone who knows the ProofToken16 might give it to someone who is under 16. Note this is not a weakness unique to my proposal. What stops someone from handing their proof to a child under any other scheme? If the proof reveals nothing other than whether the user is over-16, then a website has no way to check whether all of its users are using the same proof anyway. It is a fundamental technical impossibility to verify a user's age with cryptography, the closest we can come is to issue proofs-of-age and teach people not to share.

0 views

A peculiar bug in Safari

On weekend mornings, I have the inescapable habit of looking at my website and seeing what I can change, what I can remove, what I can improve in terms of HTML, CSS, layout, links, etc. This Saturday, as I wanted to look closer at the way the period at the end of a sentence rendered when appearing just after a word in italic (I know), I noticed something curious. When I zoomed in the page, using “Command – Plus Sign” (⌘+), I could see that the line length was changing with the size of the text. The bigger the text, the longer the line. You see, I’m very protective of the I use on this site —  — especially for Mac users, who see it in the Charter font. *1 This value sets an ideal number of characters for each line making it, when paired with the right line height, easier to read (supposedly). Zooming in on text shouldn’t change the line length, so I looked around and realised that I was a bit clueless when it comes to identifying bugs, and even checking if they were already reported. I found a few bug reports related to zooming in, but none of them described my issue. Not only that, but I didn’t really know if this was a Webkit problem, or a Safari problem. So instead of working my way to either confirming an existing bug or filing a new one , I did what I usually do when facing a problem: I avoided it altogether rather than trying to solve it. Therefore I changed to in my CSS, resulting in a similar line length for Charter. *2 With as the unit, zooming doesn’t modify the line length, so I’m pretty happy with this easy fix. Bonus point: takes up the same number of bytes as in my default CSS, still capped at 132 bytes. Imagine the extra-byte horror if I had to use something like or ? It would have ruined my sunny Saturday morning. This little website update made me realise something: my site design is pretty much done, and I hadn’t changed anything for a few weeks or even months. I actually miss the satisfaction of changing something at the end of my little routine. Checking every detail on every page, revisiting every line of code just to see what can be improved, even if it’s just removing extra quotation marks in an attribute or an optional closing tag, is not as fun when there is nothing to do at the end. I really like my site’s current design, and even if there might be a few tiny tweaks like this one in the future, I feel that the overall look and feel is pretty much final. It’s a weird feeling, but now I have no excuse for not writing more, and publishing more posts, even if they are unfinished , or shorter than usual . For others, falling back to the default serif, usually Times New Roman, is indeed a bit narrow; or would be better, but it’s too wide for Charter.  ^ For the serif/Times New Roman fallback, creates a slightly longer line, which is atually better than what it was with .  ^ For others, falling back to the default serif, usually Times New Roman, is indeed a bit narrow; or would be better, but it’s too wide for Charter.  ^ For the serif/Times New Roman fallback, creates a slightly longer line, which is atually better than what it was with .  ^

0 views
Unsung Yesterday

A simple notification preview in Retro

A nice and I think effective notification preview in Retro , with a verbatim sample text of a notification right below its name: Not only you can see exactly what you’re going to get and make a much better-informed decision, but the app even uses actual names of your in-app contacts, so you can relate to the notifications more. #attention #preview

0 views
Brain Baking Yesterday

Favourites of June 2026

The beginning of this month marks the official end of my own company. After just two years of establishing and owning Brain Baking BV , the notary ended it. There have been no professional activities related to the company since I switched back to education in December so for me it made little sense to keep that door open only for the monthly administrative costs to pile up. I hope to build a bit more stability this time around, both on personal and professional level. My statute as lecturer has been extended for a year: so far, so good! Previous month: May 2026 . A few very short ones and one quite big one that I ended up enjoying very much. DreadXP, the developers behind Dread Delusion , also recorded dev diaries on YouTube: Related topics: / metapost / By Wouter Groeneveld on 3 July 2026.  Reply via email . The Aching —a Sierra On-Line-like adventure game weighing less than that runs on any 8086 machine. It also happens to be good, even though it feels more like an introduction of this horrified world. Serious Sam: The First Encounter —I started replaying this two years ago and finally pushed forward a bit more. After endless complete freezes of my Win98 machine I gave up. AAAAAHHHHHH boom . I remember liking this a lot more: it’s…. bland? Dread Delusion —A weird looking game that I was drawn to the first time I laid eyes on screenshots a few years ago. I remembered it and felt the time was right to crack this one open. It’s one of the best games I’ve played in the last years. I recorded a playthrough log to convince you to drop everything and go play it as well! Lucy Dreaming —A lovely classic nineties adventure game that’s perhaps playing it too safe to try to be an homage to Monkey et al. ? I still enjoyed myself but the abrupt ending was a bit of a letdown. Speaking of The Aching , the developer explains their philosophy behind the Gorgon Engine . Interestingly, Gorgon is designed to be small and able to run on older original hardware, while new adventure games that look and feel old like The Telwynium are made with PowerQuest for Unity and require hundreds of megabytes. Nobody really cares, but I do. This ACM paper on a conceptual model for ownership types in Rust sheds new light on how the borrow checker works from an educational point of view. More Rust-y stuff—even though I have yet to touch the language—Michael Neumann investigated how long it takes to compile Rust from source compared to other languages. Hint: looooooonnnnggg. As in lonngggggggggg. James also printed his blog in book form years before I did! He selected all coffee-related articles to create a lovely personal caffeinated hardcover. Games That I Missed documents progress on their pinball machine projects . That old electronic stuff inside the machines is mesmerising. Phil Gyford laboriously kept track of how much money he spent each year on music for the past 30 years (via ) In a timely manner, Miss Booleana wrote about Claire Dederer’s Monsters: What Do We Do With Great Art By Bad People? . I asked myself the same question recently and added the book to my toread list. Andrew Webster publishes a Great Truth on The Verge: The Nintendo DS is still the best gaming handheld for travel . Yup. Another paper that confirms LLM-driven gender bias in citations in academic work . James Pennebaker confirms what I’ve been thinking and feeling: expressive writing can influence thoughts, feelings, and behaviours . The link is a past event but a good starting point to find publications by Pennebaker. Chris Kirk-Nielsen begs us to start playing indie games . Stop that Assassin’s Creed nonsense: scroll up and watch the Dread Delusion dev diary instead! Nic tringali sometimes feels the creative drudgery . A surprise ending is in it for you if you decide to read it. Jeff Gerstmann finally decided to apply Rigorous Science (TM) to compile an exhaustive (!!) list of the best NES games ever released in USA . Number one is NOT Mario nor Zelda! I particularly enjoyed Erik Hane’s piece in Typebar Magazine on fandom strain and the IP illness killing Magic: the Gathering . The magazine really is “An interesting thing to read on the internet”, as their footer claims. In a post called Cultures of making and relating , Konrad Hinsen brings the recent Cultures of Programming book our attention. It’s been an open browser tab ever since. Memray looks like an interesting memory profiler for Python, if I ever would need one. GentleOS is a friendly hobby OS for 32-bit PCs. The Corporate EU Observatory revealed that Big Tech invested almost 50% more in lobbying throwaway money ( !) compared to 2020. Diablo II has a new class: the Warlock . I really wish it was playable without the remaster though. Warp Point is a curated list of indie video game websites and Jefklak’s Codex is in it.

0 views
David Bushell 2 days ago

Fixing full-bleed CSS

I’m a front-end developer not a medical practitioner. If you’re bleeding IRL visit the hospital and stop googling medical issues! The full-bleed layout — as described there by Josh Comeau — can be done with CSS grid ( and subgrid ). Sometimes you can’t grid the entire page. That’s where Andy Bell’s utility class is useful. But it ain’t perfect. The issue is that viewport units don’t solve the classic scrollbar problem . If you’re on macOS or a fancy OS that has fancy scrollbars, test on Windows! can be wider than the viewport. Because why would browsers do anything sensible? It’s hard to see in Andy’s CodePen but a few pixels can be cropped either side. Add something like a border or shadow and it’s easier to see. This is not always a problem but it can lead to subtle alignment issues. By the way, macOS has a scrollbar setting “Show scroll bars > Always” that’ll let you test the issue. Andy solves this partially by hiding horizontal overflow on the element. An alternative fix is to always reserve space for the classic scrollbar. That can look weird if there is no vertical scroll necessary. The “modern” approach is to use CSS containment . Turn the element (or any 100% width child) into a container. Then replace the viewport units with container units. Now hiding overflow is not strictly necessary. I prefer — see Overflow Clip guide by Ahmad Shadeed. I clip out of caution because I make dumb things. I also use logical properties and values to support right-to-left (RTL) text direction. Ahmad has an excellent RTL Styling 101 too. Using units assumes is the parent container of the element. What if we have nested containers? Check this out. I’ve forked Andy’s CodePen to add another container that is not the full viewport width. This alone would usually break the new class and ruin the fun. But we can fix that! What is that magic? To be honest I struggle to wrap my smooth brain around this! Let me try to explain it to myself. Without the at-rule the value of is calculated at the time of use, i.e. within and therefore relative to the container. By explicitly defining a the value is now calculated when it’s set within . There refers to the parent container and inherits that value. But what if you have more containers? (╯°□°)╯︵ ┻━┻ Gosh! Stop being so difficult! I would have a direct child of like set the value. † I’m multiplying by 0.5 because division is for chumps. What CSS needs is a way to reference a container when using container units. Ideas have been proposed for example: Cancel Interop 2026 and make this happen! Thanks for reading! Follow me on Mastodon and Bluesky . Subscribe to my Blog and Notes or Combined feeds.

0 views
Andy Bell 2 days ago

You’ll miss the soul when it’s gone

Pretty grim day of news in the industry today, with Salma Alam-Naylor stepping away from developer relations work permanently , Josh Comeau taking a sabbatical from making courses and GSAP’s once-vibrant forums descending into a ghost town . The reason your token guzzler “produces” anything that could be described as “good” is because of the years of hard work from people that actually care deeply . The reason what we do was fun was because of the soul that these great people — along with many, many others — brought to the table. They inspired us to better ourselves and make genuinely good stuff. That’s increasingly no longer the case as these people nope out of the industry. Anyway, enjoy your gruel. It’s all you’re gonna be getting.

0 views
matduggan.com 2 days ago

Midnight Train to Stockholm

I was recently summoned to a meeting in Stockholm, a city I had somehow managed to avoid despite living in Copenhagen for years. My Swedish experience, up to this point, consisted entirely of trips to Malmö — the closest Swedish city to Denmark and, more importantly, home to a Costco. As an American living abroad, I am duty-bound to report there every six months so the proper authorities know I'm still alive and to procure my ceremonial barrel of peanut butter pretzels. It's less a shopping trip than a consular check-in. Stockholm, it turns out, is much further from Copenhagen than anyone lets on. My options were to fly or take the train. Flying is technically a one-hour affair, but to make a 9 AM meeting I'd have to wake up at 4 AM, shuffle through security in a fugue state, and land in Sweden looking like a hostage video. I wasn't sure when I'd nap. This seemed insane. Then I had what I believed, at the time, to be a genius idea: the overnight train from Malmö to Stockholm. I'd sleep en route, wake refreshed, stride into my meeting like a man who understood something about life that others did not. Plus, I love trains. Sweden has a high-speed line that does the run in four hours, but the night train takes its time, which sounded charming. It was not charming. The first surprise came at booking. There are three tiers of experience: a seat, a couchette (whatever the fuck that is), or a private sleeping compartment. Since I wasn't paying, I chose the private compartment. This would prove to be the single smartest decision of my adult life, possibly of anyone's adult life. If you are reading this from some point in the future and you are over the age of thirty, book the private compartment. I don't care what it costs. Sell a kidney. I'll explain. My train left Malmö at 10:30 PM. The station there is depressing in a way that's hard to articulate in that nothing is obviously wrong. There's a grocery store. There's a convenience store. And yet everyone inside looks stranded , as though they've been waiting for something that isn't coming. Small children roam in feral packs. There is a pervasive sense that this is the last train out of somewhere very bad, and that whatever is chasing everyone is still, perhaps, on its way. Amtrak in the US has this feeling, a vibe that you are running from the law. I remember when my family used to take the train from Ohio to New Jersey, waiting for it at a train station that was basically a concrete bunker in the middle of a corn field. The concrete box would either be freezing cold due to too much AC or boiling hot due to too much heat. I would stay up late on the train and watch as parents would abandon sleeping children to jump off at stops and catch a smoke. They all had a nervous desperation that these Swedish travelers shared. It's the kind of place where you wouldn't be surprised to see someone take a SIM card out of a phone and throw it in the trash. I stopped at the grocery store and loaded my backpack — my only luggage — with provisions: two large water bottles, wet wipes, a change of clothes, a bag of nuts, and, as an emergency measure, two Red Bulls, in case sleep failed me and I had to power through the following day on hatred and that cursed, faintly urine-themed energy drink. Then I stopped by the men's room, which featured a decorative fish tank whose sole occupant had a full-frontal view of the urinals. If reincarnation is real, Henry Kissinger is in that tank. European train station bathrooms are often weird, but this was up there. First there was no automated system to get in, it was just a guy with a credit card reader. Also they were piping in tropical sounds to the bathroom which I assume is to cover the unspeakable horrors happening in the stalls. I felt uncomfortable that I kept looking at the fish and found it to be always staring at me. The tank was in really good condition, with incredibly clean water. I couldn't help but think maybe its better for the fish to die faster than live their entire lives staring at an endless line of men peeing. I found my train and boarded, and I knew immediately I was in trouble. This was an old-school train — varnished wood, worn blue upholstery, late-70s energy throughout. The regular seats were hard, upright benches with little fold-down wooden tray tables. They did not recline. Not a little. Not at all. Which raises the question: why call it a night train? Night train implies, to me, that at some point during the night, someone might sleep . But the seats also had bright lights above them that never turned off, which transformed them from sleeper seats into something closer to interrogation chairs. The couchettes turned out to be stacked bunks — men-only, women-only, or mixed and the passengers were packed together so tightly that the gender segregation began to make a grim, practical sense. I'm not squeamish around strangers, but we're talking well within reach-out-and-stroke-someone's-hair range. My private room looked roughly like a jail cell: a cot, a light that turned off, a door that locked. In other words, everything I have ever wanted from a hotel. That's not sarcasm, I'm easy to please. Naturally, I was far too curious about the rest of the train to actually sleep, so I set out to wander. The three conductors on duty were all wearing bodycams strapped to their chests, which is always an encouraging sign in that it suggests both that they had been attacked and that they had, at some point, done some attacking of their own. They were also wearing shorts, which felt deeply wrong. There's something unsettling about a train conductor without pants. It's a formal job. You don't want your pilot in flip-flops and you don't want your conductor showing knee. I don't know what it is about shorts on men specifically that come across as clownish, but there is a ranking of jobs where one shouldn't wear shorts all the way to one cannot wear shorts. Doctors, pilots, lawyers, accountants are all pants jobs. Train conductor felt like a no-brainer that it would be a pants job, also frankly I think they should also have to wear a cool hat and have a pocket watch. In the same way I would bristle at a judge sentencing me to death in a Hawaiian shirt, a train conductor in shorts checking my ticket feels wrong. I made my way a few cars down to see how the general population was faring. The door slid open and I was hit, physically, by the smell of cheap vodka. Before me stretched a sea of Swedes, each with the specific facial expression of a person who has just realized they have made a terrible mistake and cannot un-make it. Two people were openly weeping. Three others were borderline-homeless-looking punk kids dressed exactly the way punks dressed in 1994 — I don't know who is still manufacturing M65 field jackets and military jump boots, but they're clearly still moving units in southern Sweden. One of the punks was vomiting into a plastic bag, seated next to a very sweet-looking, deeply concerned young woman who had presumably boarded this train with hopes and plans. She had the look of a woman who had her life together. The conductors arrived, spoke to him, were told to fuck off, and then quietly relocated the young woman to a new seat the way you'd move a house plant away from a leaking radiator. The punks then began joking loudly among themselves, two of them taking turns retching up what smelled like vodka cut with unleaded gasoline. God help anyone trying to sleep back here. Between the puking, the reek, and the punks openly hitting on every woman within shouting distance, it was like being trapped on a Greyhound bus that had sworn a blood oath never to stop. I watched a man roughly my own age attempt to sleep by laying his face directly on the wooden tray table, earplugs jammed in, arms limp at his sides, in the international posture of I have given up . I left when a boyfriend and girlfriend began fighting because she had proven surprisingly receptive to the advances of a punk kid whose body odor was strong enough to reach me three rows back. The boyfriend — sitting directly next to her — took issue with this, which seemed reasonable. I moved on to the meal car. The meal car was the hangout, the refugee camp, the place where people who had discovered they couldn't sleep in the bunks came to sit and stare into the middle distance. Two young women were seated at a table nearby, one of them work-shopping, in English, why she deserved better than her current boyfriend in Malmö. "I don't think I should settle for average." Her friend was being supportive and kept trying to inject something about her own life, only to be steamrolled every time. "Yeah, I know exact—" "It's just, I work so hard at school and he doesn't." "My last boyfr—" "Maybe when we get to Stockholm we go buy some nice dresses and go dancing." "That sounds fu—" "Because I really do think I deserve to feel beautiful ." After a few rounds of this, I got bored. It was all early-twenties drama, and I don't say that with contempt because it's a phase we all pass through. In your twenties, you discuss your plans and feelings as though they matter, because to you, they do. In your late thirties, you come to understand that nobody actually cares if you live or die, and you learn, mercifully, to keep it all to yourself. It's one of the small gifts of aging, along with knowing how to fold a fitted sheet and no longer pretending to enjoy helping people move. Friends in your 20s are your therapists, your closest confidants and your relationship counselors. In your 30s, you have an actual therapist and don't have to burden the people around you. At some point in everyone's life someone they love and respect will put up their hands and say "alright ENOUGH" and you'll realize how tiring you are. These women hadn't gotten there yet, but I did think the friend should start charging for this therapy session. I retired to my cabin and fell asleep almost instantly. The rocking of the train, the smug satisfaction of not being propped upright in a wooden pew next to a vomiting stranger, and a modest dose of melatonin combined into something close to bliss. We arrived on time. I grabbed my backpack and stepped out into Stockholm Central Station at 6 AM, which was nearly deserted. I found a coffee shop, ordered a coffee, and was charged an amount that made me wonder "should I open a coffee shop in Stockholm?". As he handed it over, the barista said, cheerfully, "It's my first day." "You shouldn't tell people that," I replied. I then felt terrible about it for approximately one hour. He, for his part, seemed entirely unfazed, or possibly hadn't heard me at all, which somehow made it worse. I carried the guilt with me through security, out onto the street, and into the cab I hailed for the twenty-minute ride to my meeting. The meter began climbing almost immediately, and with a kind of enthusiasm I hadn't previously known meters possessed. He asked where I was from. I said the U.S. He said he loved Americans. He said Americans were the best people which, frankly, nobody says unless they're being tortured by us. He asked if this was my first time in Stockholm. He asked what I did for work. Every question was warm and generous and I understood, dimly, that I was being courted. But it was only twenty minutes, how bad could it be? Eleven hundred kronor later, I stepped out onto the curb while he tried to press his business card into my hand so I could call him directly for future rides. Having just paid roughly $120 to travel the distance of a decent jog, I now understood his enthusiasm. He'd hit the jackpot, and the jackpot was me. The meeting wrapped in a few hours. I took an Uber back for a quarter of the cab fare — a small, petty vindication I savored the entire ride — and spent the next four hours walking around Stockholm. It's genuinely lovely, and denser than I expected. Copenhagen feels like a city that was designed by someone who liked people; Stockholm feels like a city that was designed by someone who respected them but wasn't sure he wanted them over for dinner. More cars, less green, wider streets, harder edges. Every Swede I passed looked as though they were on their way to something slightly more important than what I was doing. It was beautiful in the way certain people are beautiful — the kind of beauty that doesn't especially need you to notice. Should you take the overnight Swedish train? Honestly? Probably not this one, unless you are terrified of flying or being sober. The only tolerable option for an adult human is the private cabin, and at that price you can usually just fly. But it was, undeniably, an experience and one I would happily repeat, provided someone else were footing the bill.

0 views
Nicky Reinert 2 days ago

LEAKED: Anthropic's Secret Claude Strategy

A satirical take on the recurring conspiracy theory that AI labs secretly nerf their models only to re-release them for double the price.

0 views
Nicky Reinert 2 days ago

9 – Simple, Secure Browser-Based Text Sharing

9 is a free, anonymous, browser-based tool that sends text directly between two devices via encrypted WebRTC – no server, no signup.

0 views
Manuel Moreale 2 days ago

Andy Baio

This week on the People and Blogs series we have an interview with Andy Baio, whose blog can be found at waxy.org . Tired of RSS? Read this in your browser or sign up for the newsletter . People and Blogs is supported by the "One a Month" club members. If you enjoy P&B, consider becoming one for as little as 1 dollar a month. Hi, my name’s Andy Baio. I’m a writer and coder living in Portland, Oregon. You might know me from my blog, Waxy.org , where I’ve written for 25 years about the internet. If you’ve never heard of it, I rounded up some of the highlights from my first decade of blogging in 2012, and the second decade in 2022. You may also know me from some of my other projects? I ran the XOXO festival in Portland for 12 years from 2012 to 2024, launched (and relaunched) the events community Upcoming.org , and I helped build Kickstarter as a long-time advisor and their first CTO. Along the way, I coined the term “ supercut ,” produced a chiptune tribute to Miles Davis’s Kind of Blue, and got threatened with lawsuits a bunch of times. (I did some other stuff , too.) These days, I’m mostly helping my wife Ami with her game design studio, Pink Tiger Games . We’ve self-published seven conversational party games since 2017, with three more slated for later this year. Before I started Waxy.org, I mostly sent links via instant messenger to my friends who had blogs. I knew I was good at finding things online, and after the umpteenth friend told me to start my own blog, I finally did. I wanted a place of my own online, somewhere to experiment and write about weird corners of internet culture, online community, and copyright, as well as a sandbox for new experimental projects of my own. By the time I launched Waxy in April 2002, I felt like I was late to the blogging trend, which in hindsight, seems ridiculous. I was still pretty early, as it turns out. Within a year, I’d been interviewed by the New York Times and other major papers dozens of times for news stories I’d either broken or somehow found myself tangled up in. The name, Waxy.org, came from a Perl script I’d written the year before to search for available .com, .org, and .net domains using every dictionary word in the English language. (I also picked up Meaty.org, which I never ended up using, and Upcoming.org, which I did.) “Waxy” didn’t really mean anything, but I’d been using “waxpancake” as my alias for years so it seemed like a good fit. I added a linkblog, Waxy Links , to the sidebar about 18 months after launch, which became a good outlet for quick links that didn’t warrant full posts. I redesigned the site in 2008 with a cleaner design and better mobile support. After 14 years of blogging, I switched from Movable Type to WordPress in 2016, with a new redesign that I slowly improved in the years since. I recently added redesigned archives and search , which I’m pretty happy with. It’s always under construction, a work in progress — like me, you, and the rest of the internet. I used to do much more investigative journalism, but these days, Waxy is primarily a linkblog where I point to fun or interesting things I find online. Unless I stumble on a story too compelling to ignore, forcing me to pull the string and see where it leads. Those story ideas and links can come from anywhere. I’m a voracious consumer of information online, and I’ve always joked that Waxy is the natural byproduct of endlessly procrastinating from doing other things by looking at the internet. I subscribe to around 450 feeds in Inoreader, my RSS reader, and skim it all nearly every day. I follow another 1,000 or so people each on Bluesky and Mastodon, with custom lists for each so I don’t miss particular people. I’m in dozens of Discords, many with people sharing their work or pointing out good stuff they find online, and nearly 100 mostly-niche subreddits covering many of my interests. I use tools like Sill and Scour to find signal in the noise, and even built a link aggregator of my own that I used for years to find good links on Twitter, until Elon shut down the API. My frequency of posting has waned over the years, first cannibalized by social media and then by larger life and work stuff. I’ve recently found myself drawn back to it, posting more regularly, trying to wake those atrophied writing muscles. Even if I’ve slowed down, it’s hard to ever imagine stopping entirely. I used to be able to work from anywhere, typically a coffeehouse or library, and tune out the rest of the world on my laptop with a good pair of earbuds. As my eyesight’s worsened, I find that working on a large monitor is more of a necessity than a luxury for any serious length of time, especially if I’m coding. I also used to love working around others, but these days, I tend to like retreating to the quiet of my basement office. No music, no sound. Just a quiet hum of my computer and the sounds of my keyboard. I use WordPress with my own custom-written theme, using the Advanced Custom Fields plugin to handle all the special fields necessary for my linkblog. I use a custom bot to cross-post my links to Bluesky, and a plugin called Share on Mastodon to post things there. (I stopped automatically cross-posting to X/Twitter years ago, for obvious reasons.) Everything’s hosted on a DigitalOcean droplet along with a bunch of other side projects, with Cloudflare managing the domain and DNS. I would have started collecting email addresses from the very beginning. I’ve never really liked reading newsletters by email, and I read almost every newsletter I subscribe to through my feedreader, which gives me so much control over my attention. But I never considered that people would start to shift their attention away from the web, or that feedreaders would largely go away, so I never tried to build a mailing list for my own projects. The ability to directly reach the people who care most about your work, outside of the capricious nature of social media algorithms, is essential. It’s my one big regret, and I hope to change that soon. My blog has never cost much to run, and never made much money. I used to have a dedicated server that cost $150/month, but these days, it’s running around $50/month on a shared instance with some other projects of mine. The visibility and reach from writing on Waxy opened a lot of doors for me, though. I met so many amazing creative people through blogging, and it gave me a platform for launching projects that I wouldn’t have had otherwise. I met most of my friends, directly or indirectly, through the writing I did on Waxy.org. I did run ads on my blog for a few years, experimenting with Google ads from 2004 to 2005 and, in 2006, joining as one of the first members of The Deck , Jim Coudal’s pioneering unobtrusive, privacy-centric boutique ad network that helped support sites like Daring Fireball, Kottke.org , Ze Frank, The Morning News, A List Apart, and many others. It paid me a reliable $1,000/month for ten years, until shortly before it wound down in 2017. I haven’t made any direct income from my blog since then. I think anything that supports independent writers/bloggers, artists, or other creators on their own terms is a good thing, whether it’s through Kickstarter, Patreon, or more commonly, through paid subscription newsletters. I have major issues with Substack’s management, but I credit them for normalizing the idea of directly paying bloggers a recurring monthly fee. But please use Ghost or Buttondown instead. Oh, god, too many to list. Off the top of my head, Marcin Wichary’s Unsung is probably my favorite new blog, constantly updated with new insights about user interfaces and design. Nobody notices things the way that Marcin notices things. Matt Muir’s Web Curios is like a month’s worth of good links crammed into a single post every Friday. I don’t know how he’s done it so well for so long. Depths of Wikipedia’s Annie Rauwerda isn’t a traditional blogger, but spreads her curatorial eye between two Bluesky accounts , two Instagram accounts , TikTok , a newsletter , a touring live stage show , and a very good personal website . She’s just so funny and weird and good. I wish she had an RSS feed that combined it all. Maybe I’ll make one for her. I think David Friedman’s Ironic Sans is incredibly underrated, moving from a traditional blog to more of a newsletter format, with weird little side projects and games along the way. He’s been continuously great for 20 years. I’d love to see Jason Kottke interviewed. More than anyone I can think of, he’s carved out a Kottke-shaped hole for himself on the web, growing it into a sustainable living through direct reader support over nearly 30 years. Even now, he continues to refine and adapt and evolve his site in surprising ways. The last project I worked on was the permanent archive for XOXO that launched in April, collecting everything we did related to the festival. The site was a huge undertaking, bringing together every lineup, schedule, recap video, conference talk, and standalone website that we ever made into a single permanent archive, filled with little photos and ephemera from the festival. XOXO was a huge part of my life for 12 years, easily the most creatively rewarding and emotionally exhausting work of my career, and I’m really proud of how the archive came out. At the very least, go poke through the video archives. The featured tag highlights some of our favorites, like Cabel Sasser’s wonderful talk from our final year. Now that you're done reading the interview, go check the blog and subscribe to the RSS feed . If you're looking for more content, go read one of the previous 148 interviews . People and Blogs is possible because kind people support it.

0 views

Syncing my clipboard between macOS and remote terminals

As I've been spending more and more time with agentic development, it's more and more important to me that sessions run somewhere other than my laptop. For the last few months, that has meant running my coding agents in tmux on either a remote Mac or a remote Linux server. The most frustrating thing for me has been that the clipboard or paste buffer on those remote hosts isn't synced to my desktop. So, if I copy something inside of a coding agent, I've had to play games to get it to my local Mac. Similarly, if I wanted to paste a screenshot to a remote tmux session. I was playing games with scp. But also, I don't just want to be able to copy and paste between my Mac and a remote terminal. I want to be able to copy and paste between remote terminals on two different computers. And I want to be able to take a screenshot on my phone and have it end up in the paste buffer on a remote Linux box. I took a run at solving this problem maybe three months ago, and I came at it from the wrong direction. I started to look at what it would take to integrate with Apple's iCloud-based copy-paste buffer magic syncing stuff. And I stepped back right at the point where it was going to involve reverse engineering iCloud crypto. Not because I didn't think my coding agents could do it, but because doing it felt like a great way to become a cautionary tale. But I kept being frustrated. So I took another swing at this sometime last month or so. And the result is called Clipfan. It runs as a menu bar app on your desktop Mac or Macs, and it integrates into tmux on all of your hosts. It uses SSH keys to set up a fully connected pasteboard syncing mesh. On the Mac, it has a pasteboard history because why not. It can auto-install across your fleet of computers and configure tmux on remote machines. It would, of course, be possible to configure it to sync pasteboards with other kinds of computers and other tools on those machines. ClipFan is free. It's available on GitHub today .

0 views
Justin Duke 2 days ago

Two hundred decisions

This week, after a little under two years of having adopted the practice, Buttondown has minted its 200th decision log. This is a practice very similar to RFCs or ADRs, but I prefer the term decision because it's both A, used for a variety of non-engineering purposes, and B, sounds a little less lame. The practice itself is extremely simple and there is no catch. It goes something like the following: Our decisions range from the monumental-yet-concise: to the trivial-but-nuanced: It is objectively not a free lunch in that it does take time for you to sit down and explain concisely in prose why you are doing a thing and what the other options are. It was most of all the null hypothesis of simply not acting. But a cost which serves as a forcing function to write, I mostly think of as a reward at this point. The world is complex: with every patch of fog that lifts, I find four more in the distance. 1 Only very recently have I started to understand knowledge as a perception of fog rather than a dispelling of it. And so I am very careful not to prescribe these days, unless I am so overwhelmingly confident in the universality of a given prescription. This is one such thing: keep a decision log. (See also Oxide's public RFD system .) Decisions are any non-trivial choice made for a specific reason. The context behind a decision is very hard to retrieve after the fact and grows in difficulty over time. The ability to revisit this context and update, invalidate, or buttress it is extremely useful in a variety of reasons.

0 views