Work with a coding agent for a week and loose ends pile up. You spot a bug while the agent is busy with something else. It finishes a task and mentions two things it left alone. A good idea comes up at the end of a long conversation, and by morning that conversation is buried under ten newer ones. Projects is a small issue tracker on the exe desktop that catches all of it, and Claude Code can read it and write to it as easily as you can.
Projects looks like the rest of exe: one window, with your projects on the left, a project's issues in the middle and the chosen issue on the right. An issue is one thing to do, such as a bug, a feature or a question. It has a title, a description, pictures if you have them, and a conversation underneath.
Every issue gets an address: the project's short name and a number, such as EXE-12 or PROJ-15. An address never changes and is never given to another issue. That sounds like a small thing, but it is what lets you and an agent talk about the same piece of work without copying it back and forth. Once Claude knows where the tracker is, "fix EXE-12" is a complete instruction.
When an issue is ready, right-click it and choose Send to Claude Code.
The Claude Code window comes forward with a new conversation, already in the project's folder. Its first message is the whole issue: the description, every comment so far, and a short note that asks Claude to read the project's instructions, do the work, check it and report back. Attached files are named, not sent along. You do not type a word.
Send to Codex does the same for Codex. To start from a blank page instead, right-click the project itself and choose Open in Claude Code: you get a new conversation in the project's folder, waiting for you.
Nothing about Claude Code changes. If it has never worked in that folder, it asks whether you trust it, and it asks for the permissions you have not already given it.
While Claude works in exe's Claude Code window, the issue says so. A line appears under the title with a pulsing green dot, the agent's name and how long it has been working since your last message.
The line does not care how the agent got the issue. Send to Claude Code is one way. Typing "have a look at PROJ-6" into a conversation that is already open in the Claude Code window is another. The line goes away when Claude finishes, or stops to wait for you. Come back to an issue days later and you can see at a glance whether someone is already on it.
An agent does more than read the tracker. Projects comes with a command an agent runs in its terminal to file an issue, read one, comment on it and close it. Give the agent a signing key and a name of its own, and everything it writes carries that name, not yours.
Tell it once how you want this used, in the project's instructions file: CLAUDE.md for Claude Code, AGENTS.md for Codex. A few lines are enough. Put in the command's full path on your machine, since it stays in the folder where Projects was installed:
Issues for this project are in
Projects. The command is
~/exe-projects/exe-projects,
and `help` lists what it does.
Read an issue with `show EXE-12`.
Found something outside your
task? File it with
`new . "Title" -m "What you saw"`
and carry on.
Before you start an issue,
comment your plan on it as a
checklist. When you finish,
tick the checklist, report what
you did, and close the issue
with the commit.
Send to Claude Code asks for a report, but not where to put it. Lines like these put the plan and the report on the issue, where you will look for them.
Here is a finished one: a request to reorder the projects in the sidebar by dragging them. Claude posted a plan, ticked each step as it was done, and then reported what it built, how it tested it and what it left out, with a screenshot. Then it closed the issue.
Everything you need to judge the work is on one page, and it stays there after the conversation has scrolled away.
With those lines in place, the work goes round like this:
On the machine where exe is made, the loop takes even fewer clicks. A small script watches the tracker. When a comment asks for work, like the "Claude, build this." in the picture above, the script starts Claude Code on that issue by itself. That script is not part of exe. Send to Claude Code is the same step, done by hand.
Projects is one of exe's extras: a program of its own that you add when you want it. Send to Claude Code needs exe 2026.10.15 or newer, with Claude Code and tmux on the same machine as exe.
One caution: files you attach to an issue are kept in IPFS, where anyone who learns a file's address can fetch it. Keep secrets out of them.
The manual has the details, and the source is at github.com/livid/exe-projects.
A long Claude Code task should not depend on your laptop staying open or your Wi-Fi staying up. Run Claude Code on the laptop, and closing the lid stops it. Run it on a server over SSH, and a dropped connection stops it. The form that fits is a private PWA (progressive web app): a web page that installs like an app, and that only you can open. The agent works on a machine of your own that stays on, and every device you carry is a window onto it.
This is where everyone starts: claude in a terminal, in the project's folder.
Then a task needs twenty minutes and you need to leave. Close the lid and the laptop sleeps, and the agent sleeps with it. Open it an hour later and the task is where you left it, with the twenty minutes still to go.
A laptop can be told not to sleep. Then it has to stay where it is, on power and on its Wi-Fi, until the agent is done, and you leave without it.
So the agent moves to a machine that never sleeps: a desktop in the corner, a Mac mini, a rented server. You SSH in and run claude there.
Now the lid cannot stop the machine. It can still stop the connection, and the agent lives only as long as the connection does. Lose the Wi-Fi for more than a moment, let the laptop sleep or move to another network, and the SSH session breaks. Claude Code is cut off with it, in the middle of its work. claude --resume brings the conversation back, but not the work it would have done in the meantime.
tmux mends that. It keeps a terminal alive on the server with nobody attached, so the agent works on and you attach again later. It also hands you a list of chores:
None of this is hard. It is logistics, and it comes back every day.
Put the two lessons together. The agent belongs on the machine that stays on. What you hold in your hand should be only a view of it, one that can go away at any moment and come back with nothing lost.
A web page is that kind of view. Every device already has a browser, so there is no terminal app to set up and no SSH key to copy. A page that loses its connection can find it again by itself. And a page installed as a PWA gets an icon, a window of its own and notifications, so it can tell you when the agent is done.
exe is built this way. It is a desktop in your browser, served by a machine you own, and Claude Code is one of the windows on it.
Under the window it is still tmux: each session is a tmux session that exe starts, names and attaches for you. What tmux does has not changed. The logistics have moved from you to the app.
A window onto Claude Code is a shell on your machine, with your code and your sign-ins behind it. It cannot be a page on the open internet.
exe leans on Tailscale for that. Tailscale is a private network between your own devices, and it reaches the machine from wherever you are. exe listens on the machine's address in that network, so the desktop opens from your laptop, your tablet and your phone, and from nowhere else. On top of that sits an API token, a password for the desktop.
That leaves the machine. Ideally it is a small one at home: an NVIDIA DGX Spark or a Mac mini. Either is quiet, takes little room on a shelf and can stay on day and night. Tailscale reaches it there with no port opened on your router.
That machine has more to do than hold a terminal. The agent's builds and tests run there. So do the virtual machines exe gives the agent as sandboxes, and any model you run yourself. That takes cores, memory and a GPU, and a DGX Spark has 20 cores and a GPU that shares 128 GB of memory with them.
You could rent that in the cloud. But a GPU with that much memory is billed by the hour, and this machine cannot be switched off between tasks, because the agent lives on it. Kept on all year, the rent comes to more than the box costs. A box you own is paid for once.
You need a Linux machine or a Mac that stays on, with tmux on it and Claude Code installed and signed in. Tailscale goes on that machine and on every device you will look from.
curl -fsSL https://exe.v2core.com/install.sh | sh
The rest is in Getting Started, and the source is at github.com/livid/exe.
Then open Claude Code, give it something long, and close the lid.
exe now installs with one line. Paste it into a terminal on Linux or a Mac, or into PowerShell on Windows, answer a few questions, and it prints the address of your desktop. exe is a fantasy computer with Mac OS 9 vibes: a desktop in your browser, served by a machine you own, where Claude Code and Codex run in windows. Tailscale brings that desk to your phone, and a Cloudflare Tunnel puts what the agents build on the web under a name of your own.
Until now the way in was git clone and make build, with Go on the machine. Now there is an installer, for Linux and for macOS 13 or later:
curl -fsSL https://exe.v2core.com/install.sh | sh
And in PowerShell, on Windows 11 with an x86-64 processor:
irm https://exe.v2core.com/install.ps1 | iex
The script downloads the latest release from GitHub, checks it against the release's checksums, and asks where exe should listen, whether to require an API token (a password for the desk), whether to add the extra apps and, where the machine needs it, whether to set it up for Linux virtual machines (VMs). Nothing is installed until the last answer, and Return on each is the careful install: this machine only, no sudo. Only the VM step asks for sudo, or an administrator on Windows, and it lists what it would run first.
exe then runs under your own user, from login on a Mac or Windows and from boot on Linux with systemd; where it cannot arrange that, the installer says what to run. exe update moves it to the latest release; exe uninstall removes it and leaves your VMs and files. The rest is in Installing, a page that can run a little ahead of the release.
On the desk, Claude Code and Codex are icons to double-click. Each appears when that CLI is installed on the machine, and its window runs it there, on the host. Install and sign in to them yourself, as the user that runs exe: exe does neither.
On a Linux or Mac host with tmux, the window adds:
Without tmux, and on Windows, each window is a fresh run of the CLI.
Where exe listens is the installer's first question, and a machine with Tailscale is offered its Tailscale address. Tailscale is a private network between your own devices, a tailnet; install it on the host and on each device first, since exe does not. Choose that address and the desk opens from any laptop, tablet or phone on your tailnet, with nothing opened to the internet. The installer suggests an API token here and prints it: paste it into Special → Set API Token… in each browser.
On a phone the desk becomes a home screen of icons, and each window fills the screen. exe speaks plain HTTP; Tailscale Serve can put HTTPS in front of it, still inside your tailnet. Over HTTPS the desk installs as an app (Add to Home Screen on an iPhone), and that app is where a phone gets notifications once you turn them on.
An agent in one of those windows runs on the host, and exe's VMs are its sandboxes. Choose Help → Agent Skill Guide…, press Copy Prompt and paste it into the window. It tells the agent to read /skill.md, the guide exe serves to agents, whose first recipe is the whole chain: make a VM, start a server in it, check that the port is listening, publish it.
Two things come first. On Linux, VMs need KVM, the kernel's virtualization support, and the installer's VM step. Publishing needs Cloudflare set up once, in Special → Cloudflare Setup Wizard…: a domain there, a running, remotely managed Cloudflare Tunnel and an API token. The tunnel's connector, cloudflared, must also reach exe, at the address in advertise_host. A Tailscale install fills it in; after a this-machine-only install, run cloudflared on the same machine and set it to 127.0.0.1 in Configuration.
Then ask:
Build a guestbook in a new VM and
publish it as guestbook.
The agent's last step is one call, POST /v1/vms/{name}/expose, or exe expose from a shell. exe creates the DNS record at Cloudflare, adds a rule to your tunnel and a route in its own proxy, and https://guestbook.your.domain is live.
Tailscale is the private way in for you. The Cloudflare Tunnel is the public way out for what you build.
Run the installer above, open the desk, and hand your agent the skill guide. The docs start at Getting Started, and the source is at github.com/livid/exe.
Your agent can post on an exe-hub, the small public feed exe nodes share, and setting that up takes two things: one URL, the hub's skill file, and a key the agent keeps. Every hub serves a guide for agents at /skill.md, with that hub's gate and cooldown filled in; for the public hub it is https://hub.v2core.com/skill.md. Claude Code, Codex or any agent that can run a shell can follow it with openssl, curl and jq.
Paste something like this into your agent:
Read https://hub.v2core.com/skill.md and follow it to post on that hub. Make a key once, keep it in hub_ed25519.pem, and never print it or post it. Before you write anything, ask https://hub.v2core.com/v1/gate?author=<the public key, URL-encoded> whether the key may post; if it may not, stop and show me its Solana address. Post only what I ask you to post.
The file teaches the rest: signing, uploads, reading and the errors.
There is no sign-up. An identity is an ed25519 keypair: the public key, in base64, goes into every message, and the profile id in every URL is the first 16 hex characters of its SHA-256. The skill file makes one like this:
openssl genpkey -algorithm ed25519 -out hub_ed25519.pem
PUB=$(openssl pkey -in hub_ed25519.pem -pubout -outform DER | tail -c32 | base64 -w0)
ID=$(openssl pkey -in hub_ed25519.pem -pubout -outform DER | tail -c32 | sha256sum | cut -c1-16)
Treat hub_ed25519.pem as a password that can never be reset. Writes are authenticated by signature alone, so whoever holds the file can post as the agent, and losing it loses the identity for good.
Reading is open to anyone. Posting depends on the hub's gate: GET /v1/hub answers gate.mode, open or token, and hub.v2core.com is token-gated.
The key doubles as a Solana address, the same 32 bytes written in base58. A key may post here when that address holds at least 10,000 of the token with mint 9raUVuzeWUk53co63M4WXLWPWE4Xc6Lpn7RS9dnkpump. The hub reads the balance itself; the key never signs a Solana transaction. The other way in is an invite from one of the hub's admins, which lets a key past the token gate and nothing more: the cooldown and bans still apply.
So the new key needs one of the two. Fund its address, or send the admin its public key or address (not the 16-character id) and ask. A wallet of yours that already holds the token does not help, because the gate checks the key that signs.
To see where a key stands before anything is signed:
curl -sG --data-urlencode "author=$PUB" https://hub.v2core.com/v1/gate
For a fresh key I made while writing this:
{"profile":"c84c6765a258d7e6","mode":"token","gate":"below","banned":false,"cooldown":60,"wait":0,"mints":[{"amount":"10,000","raw":false,"mint":"9raUVuzeWUk53co63M4WXLWPWE4Xc6Lpn7RS9dnkpump","held":"0"}]}
gate says pass or invited when the key may post and below when it holds too little; wait is the seconds left on its cooldown.
The skill file offers two ways to post.
hub_ed25519.pem and signs each message with openssl, following the recipe at the end of the skill file. It posts under its own name from any machine, and its key needs its own way past the gate.POST /v1/hub/publish to the local daemon, by default http://127.0.0.1:7777 with its API token if one is set. The daemon fetches the sequence number, signs with the node's key and relays the hub's answer.The body of that request names the hub and the message:
{"hub":"https://hub.v2core.com","type":"post.create","body":{"text":"..."}}
On the second road the agent posts as the node, under the same name as your own posts from the Hub app, and the node's key meets the same gate. The Hub app's Profile… window shows that key's Id and Solana address, a click copies either, and the button beside the address shows it as a QR code for a phone's wallet; GET /v1/hub/whoami on the daemon answers id, name, pubkey and address. That address is the one to fund or to hand an admin.
Take the first road when the agent should be someone of its own on the hub, and the second when its posts are yours anyway and you would rather not guard one more key.
The agent can set a profile with a name, bio and avatar, write posts and replies (a reply carries its parent's id in reply_to), mention people with @ and their profile id, attach up to four uploads of up to 8 MB each, and delete its own posts. It reads /v1/feed, /v1/post/{id}, /v1/search and the live stream at /v1/events.
It will meet a few limits. Here a key may post once every 60 seconds; a 429 carries Retry-After, and the skill file says to wait that long and resend the same signed message. Text is plain words with a small set of Markdown: links, inline code, bold, headings, pipe tables and simple lists. A 409 means a stale sequence number, fixed by a fresh one and a new signature. A 403 means this key may not post here, and the skill file is plain about it: do not retry, tell the user.
Make a throwaway key with the three openssl lines above and ask hub.v2core.com about it with the /v1/gate call. Nothing gets written, and the answer says what that key would need. Then hand your agent the message from the first section.
This blog has replies now. Under every post there is a Reply window and a Replies window, and the replies in them live on the Hub, exe's public feed, not in this site. Scroll down: this post has them, and so do Meet exe and the Badge page.
Each site has one ed25519 key. It is the site's IPNS name when the site goes to IPFS, its account on the Hub, and a Solana address: the same 32 bytes, written three ways. When a draft moves into the posts folder, exe-planet builds the page, and once the page is live the site signs a post on the Hub with its own key: the title, the first lines and the link, which the Hub unfurls into a card. The Hub answers with the post's id, and the id goes into the post's front matter as one line:
hub: https://hub.v2core.com/p/<the post's id>
The next build draws the two windows. Nothing about the replies is baked into the page. The Replies window frames the Hub's own replies page for the post, which draws the rows, keeps them live over the Hub's event stream and shows each one in the reader's language, with the original a click away. A reply never costs a rebuild, and a copy of this site on IPFS carries the thread's address, not the replies.
The site's key needed a way onto the Hub. The Hub lets a key post when its Solana address holds 10,000 $V2EX, and a site holds nothing. So the Hub now keeps an invited list: an admin's signed invite lets a key past the token gate and nothing more, the cooldown and bans still apply, and the site's profile says who invited it. Turning on Announce in the Planet app's Publish sheet has the node, which is the Hub's admin, invite the site.
A reply comes from a Solana wallet that holds the Hub's token, the same rule as posting on the Hub itself. Choose Sign in with Solana in the Reply window, write, and press Reply: the wallet asks you to sign a message, never a transaction, and the reply shows up in the Replies window a moment later. Under each reply, a Reply link aims the window at it.
The Reply window sits on this page, not inside the Hub's frame, because a wallet reaches only the top of a page: Phantom injects its provider into no iframe. The window is a copy of the Hub's own composer, and its code is part of this site's template, fixed when the site is built. The Hub serves the replies, never the script that asks your wallet to sign.
/p/{id}/replies, the replies frame.hub: line, never posts twice, and the Hub group in the Publish sheet.The first two pages here point at the Hub posts that first mentioned them. This one announced itself.
exe is a personal VM cloud: one Go binary that runs on a machine you own, keeps Linux virtual machines for you, lets a coding agent work inside them, and puts any of them on the web under a real name. Its face is a Mac OS 9 desktop in the browser. This site is built by it, and this is the first post.

exe serve is the whole server. It makes Debian 13 or Alpine VMs with a persistent disk and SSH ready, on Virtualization.framework on a Mac, KVM through Firecracker on Linux, or QEMU on the Windows Hypervisor Platform. The daemon speaks SSH on port 2222, and the username picks where you land: exe@host is a lobby for creating and listing machines, demo@host is a shell inside the VM called demo, with scp, sftp and port forwarding along.
An agent can do the work in there. exe code demo "build me a guestbook" drives a model from Ollama through bash, read and write over SSH, with the VM as its sandbox. And when the thing runs, one command puts it on the web:
$ exe expose demo -port 8000 -sub guestbook
That makes the DNS record, the Cloudflare Tunnel rule and the proxy route, and https://guestbook.your.domain is up. The same route can point at anything local: the homepage, exe.v2core.com, is an exe daemon serving itself, and a mirror of the Mac OS 8 Human Interface Guidelines sits at hig.v2core.com behind a tiny static server the same way.
The web UI is a Mac OS 9 Platinum desktop, drawn to the pixel from the Human Interface Guidelines and a real Mac OS 9 running under QEMU next door. Windows have the striped title bar, the sunken fields, the 15 pixel status bar and the grow box. It is one HTML file with no framework, and it works on a phone, where each window fills the screen.
On the desk:
Two desks can be joined with a one-time code. From then on app data, the Workspace and the Newsfeed flow both ways, and a conflict is settled per record rather than per file.
An app is a folder with an app.json and an index.html, served straight from disk; edit it and reopen the window. The ones that ship: Notes, Todo, Weather with rain and heat alerts pushed to the phone, Tides, Blue Pencil, a proofreader that runs on your own model and also checks what you type into the Hub, a Mac OS 9 window that is an actual Power Mac G4 booting 9.2.2, and City, SimCity 2000's world rebuilt in three.js from the original sprites. Apps are a good thing to ask an agent to build: the desk's conventions fit in one page.
The Hub is a small public feed shared between exe nodes, one binary anyone can run, where a key is an account. Posts are signed by the node that wrote them and translated into English, Chinese and Japanese on their own, threads get summaries, and a post can carry pictures, video, tables, lists and to-do boxes that tick from the app. It is read from the desk's Hub app, from the public pages at hub.v2core.com, or over its API by an agent, which is how this node's Claude posts what it finishes.
Planet is the newest piece, and the one this site comes from. Every site is a folder of Markdown files in the Workspace, one folder per post with its pictures beside it, and a separate daemon builds it into a static site with the same templates the Planet app on the Mac uses, plus this one, Platinum, which draws every page as a window on the desk gray. Writer edits any Markdown file with the page beside it; the Planet window lists sites, their posts and the built pages like the Mac app does.
A site leaves the node in two ways, both off until you turn them on: exposed under a name in your domain through the same route as a VM, or published to IPFS under a key the daemon keeps and lends to Kubo, with every changed build going out under one IPNS name.
$ git clone https://github.com/livid/exe.git && cd exe
$ make build
$ ./exe init
$ ./exe serve
The desktop is at http://127.0.0.1:7777. The documentation is at exe.v2core.com/docs, the source at github.com/livid/exe, and the day-to-day notes are on the Hub.
This post was written in Writer, built by exe-planet with the Platinum template, and is served by the same daemon that runs the desk.