Software, AI and getting things done
How AI streamlined my digital life
My road to a more productive digital life started when I asked Claude Code (CC) to build a web server for me. It's called mdserve (short for markdown server), a full-stack web application in a single file, that has grown into the control panel for my whole desktop. Its generic core is on GitHub, for you to build your own on.
It started with wanting a more pleasant reading experience than what CC produces. Instead of reading a long answer inside CC itself, I tell it to write the answer to a markdown file and open it in the browser for me. CC will do that without any help. The problem mdserve solved was where the page turns up: I wanted it to always be in a known browser's window, on the workspace I'm working in.
It has grown since then. A "personal agent", one that goes off and does things for you while you're not there, isn't something I want. But I do like the convenience such agents promise, and this is how I get it. Anything I find myself doing a lot gets streamlined. Sometimes that's a small ~/bin command, sometimes a button or page in mdserve, and sometimes just a rule CC follows for me, such as always backing up a file before changing it.
When I start mdserve from the command line, it opens several browser windows, each with many tabs. I have three areas of focus at the moment, so I work across three workspaces. The one step I haven't been able to automate is moving each window to its workspace, but that only takes a few seconds.
About the videos: they're screen recordings, and the text in them is small. Open a panel, then go full screen before you press play. YouTube picks the picture quality from the size of the player, so a small player gets a blurry picture.
Why a web server and not a desktop application? Because everything talks HTTP. CC shows me a page with a single curl to mdserve, with no plugins or plumbing needed. mdserve in turn drives the browser with web requests too, through the Chrome DevTools Protocol. The server holds the state, so closing a tab loses nothing. And it isn't tied to one machine: CC sends documents to my tablet over the LAN with the same kind of request.
As you saw in the video, I start mdserve.sh from workspace 2. That's the workspace I use for control, and for anything that isn't a programming project. The idea is that mdserve bootstraps the machine. After that, all the work I need to do is on an mdserve browser tab somewhere.
When I want to work on mdserve itself, I start a new CC session and ask it to read MDSERVE.md, where its documentation lives. If you haven't worked with CC, or a similar coding agent such as Codex CLI or Gemini CLI: maintenance documents like this are written by the AI itself, from the conversations you have with it at its prompt.
Browser tabs are just URLs. On startup mdserve reads them from an EDN file, and that file gets changed during my conversations with CC.
It's interesting to see how tabs come to be there. There are three ways:
Each tab also gets a coloured dot as its icon, so I can tell at a glance what kind of tab it is. Ordinary websites keep their own icons, but they're just as much part of mdserve: remembered and reopened with the rest, and CC can put one up in the correct window as easily as a document. The idea is to keep it down to one browser window per workspace.
The last video showed "Refresh" for how much memory is in use, and "Remember Tabs", which saves the open tabs.
One rule Claude follows for me is to always make a backup before changing a markdown file. That makes a mess of backup files, which of course can be tidied up.
The next video shows the tidying up.
Imagine having your own programmable version of Windows Explorer per workspace. You just saw that in the last video! There's always at least one of these tabs in each workspace. The video doesn't show it, but clicking a file opens a new tab that displays that type of file. Markdown files matter most, so they're listed with the most recently changed first.
Many of mdserve's buttons don't do the work themselves. They run a small command from my ~/bin directory, the same command I could type at a shell prompt, or that CC can run for me. The "Flotsam" button in the video runs archive-flotsam, a script that moves backup files and screenshots into a timestamped archive folder. Most of the commands behind buttons are just a few lines of bash. A few buttons, such as the memory "Refresh" and "Remember Tabs", are built into mdserve itself.
Working as a developer or a support person, you end up with terminals everywhere, some temporary and some running permanently, and they clutter your desktop. There are plenty of ways to tame them: tmux, tiling window managers such as i3, and on macOS, iTerm2.
The terminals that cluttered my desktop were mostly long-running processes: servers, build watchers and the like. Those now run in the background, each terminal having been replaced by a row of buttons ("Launch", "Stop" and "Log") on an mdserve dashboard, one at a time or a whole group at once. "Log" opens the output in a tab, which I close when I'm done. All I keep is one tabbed terminal window per workspace, for my CC sessions and the occasional one-off terminal session.
That occasional one-off terminal session I mentioned is often a runbook, often on another machine.
Some jobs need me, rather than CC, to type the commands, because they need my password or a console. For those, CC writes a runbook: a plain file of shell commands, with comments saying why each step is there. I press Alt-n and the next step appears at my prompt, already typed, and nothing runs until I press Enter. No more copying commands out of the chat. The tool is called cmdq, and it's a gist you can install in a minute.
Each step's output is saved for CC to read back, and my place is saved too, so a job can span reboots. When the job is on another machine, CC copies the runbook there, and I log in and keep pressing Alt-n. Each runbook is a dated file kept with its output, so there's a history of what ran on each machine.
At this stage I've written the main points I wanted to make. Please read on if you are still curious...
Buttons aren't only for small jobs. Our point-of-sale system (POSES) is four webapps (chat, till, prods and pos) that run on one production server, and deploying them is a job with several steps. It now lives in mdserve in a Deploy panel on the POSES dashboard tab, as five buttons in the order they're used:
Each step has a coloured dot showing whether it has run and how it went, and a "Log" button for its output.
The same habit works away from the desk. Four examples, and how each one works.
Reading on the couch. When I say "put it up on the tab", CC adds a document to a reading list, which a second, deliberately tiny web server shows on my tablet. That server can only show the list and the documents on it. mdserve itself only listens on the machine's own internal address, so nothing on the LAN can reach it. The terminal, editor and money pages simply don't exist on the tablet's server, so nothing I add to mdserve later can leak onto the network by accident. A web page can go on the list too; it's just a link to the real site.
The big screen. "Put it on the big screen" opens a page on the TV. Behind that phrase is bigscreen, a small command on my desktop: give it a web address and the page appears on the TV. CC runs it when I ask, and I can type it myself too. The TV is really just an HDMI screen for a Linux laptop. That beats a smart TV: the laptop is a normal computer, so it can run a web server and a fully controllable Chrome. A page on the TV is no use if you can't scroll it from the couch, so the TV runs its own little web server, tvremote, and my phone is the remote control. In reading mode it scrolls the page up and down, makes the text bigger or smaller, reloads it, and plays the page's YouTube videos; the same remote also does Netflix. tvremote shows pages in a separate Chrome with its own profile, because Chrome won't let a program take control of your everyday one. It's on GitHub if you have a spare laptop and a TV.
What makes tvremote work is the trick mdserve uses, stretched across two devices. In mdserve, the pages I click on and the browser being driven are one and the same: a button on a page asks mdserve, and mdserve drives that same browser through the Chrome DevTools Protocol. With tvremote there are two browsers. My phone's browser shows the remote, but it has no power over the TV at all, because Chrome only accepts that kind of remote control from programs on its own machine. So each press goes to the web server on the laptop, which sits right next to the TV's Chrome and drives it. A web page can't control another browser, but it can ask a web server that can. Any device on the LAN can be the remote, and bigscreen on my desktop is just one more of them.
Email and messages. When I need an email written, CC drafts it straight into Gmail and leaves it open on my screen: a new message, or a reply at the end of the correct thread. Slack messages work the same way. There's no email integration behind this. Gmail and Slack are just tabs in mdserve's browser, already logged in, and CC works inside them through the Chrome DevTools Protocol, the same remote control mdserve uses to open its windows.
Errands. My second favourite (behind the TV remote): I needed an official photo from one of several local photo shops. CC made me a one-page guide with the questions to ask and the spec, and the shops in order, each with a button that opened Google Maps to it. As I rode from shop to shop, the next one was always a tap away. This one couldn't be served from home: my web servers there reach only my own machine and my LAN, and out on the bike my phone was on mobile data. So CC published it on the web server I rent on the internet, the one that hosts this blog, as a temporary page under my own domain. That's a single command for CC, and the page needs no login to read.
Money gets the same treatment. My mdserve pages only ever talk to the mdserve backend, which in turn makes the calls to Binance, holds the secret API keys, and signs each request, so a key never appears in a web page, and the browser never talks to the money.
The main flow:
Every trade is saved locally, as an EDN file, so the history is mine and doesn't depend on Binance.
You don't need mdserve to start. Each of these is something to say to your own coding agent, and each one stands alone.
bigscreen command puts a page on the TV, and you scroll it from the couch with your phone.AI, or rather the software it can build quickly, has finally let me get rid of most of the friction involved in controlling computers. I've never looked at mdserve's code, nor at the EDN file its tabs come from. I know what it does from using it every day.
Now imagine arriving for work at a new job, as a developer or a production support person, and being told to run one thing from the command line. Up comes everything that role needs: the dashboards, the logs, the runbooks, the documents, each in its place. Each role could have its own mdserve. A turnkey introduction to a job, long desired, is finally practical.
The next stage is, of course, doing some of these things in a loop, without a person driving each step. That's already happening in software development: agents make several attempts, and the best are kept. Two products now arriving work like this. Both take an evolutionary approach.
samizdat is an agentic harness for Clojure that splits larger tasks among several agents, and each sub-agent gets a contract plus tests as its spec. Several attempts can run side by side, and the winner is chosen by ranking each attempt on checked evidence. The loop itself is a state machine written as data, and the agent can rewrite it while it runs, behind a validate-and-rollback gate.
simmis is a self-hosted app where people and agents share one memory, including the code repository, and its central idea is cheap forking. Every change an agent makes to shared knowledge, documents or the code lands on its own copy-on-write branch, so agents can make several attempts at the same thing side by side. Whoever holds merge authority, a person or another agent, reviews the differences and merges the ones worth keeping. That's what makes it safer to let agents work on software in a loop. Two things stay off the branches: chat, where people and agents talk and the work gets asked for, and actions with outside effects, such as sending an email, which a branch can't undo. simmis is an early public release; the overview and roadmap are at simm.is.
Waterfall plans everything up front, then builds; agile builds in small steps and changes course as it learns. Waterfall's weakness is going back up: once building starts, changing the spec is expensive. The evolutionary approach allows both, and removes that weakness. Each attempt can start from a spec, as in a waterfall, and what the attempts reveal goes back into the spec before the next round, as in agile. samizdat gives each sub-agent a contract and tests as its spec and ranks the attempts on evidence; in simmis, attempts sit on forks until a person or agent with merge authority keeps the good ones. And when the code takes hours rather than months, going back up is cheap.
# for a heading and * for emphasis. Easy to write, and easy to turn into a web page.Comments or questions? Email me at (turn on JavaScript to see my address).
Published: 2026-10-08