Skip to main content
A machine can delete itself from inside. That’s what a fork → run → delete pipeline needs: the machine finishes its task and removes itself, with no process outside watching for completion.
Run it inside the machine, with the in-machine boxd that every machine has.
Deletion is permanent. The machine, its disk and every file on it are gone, and every process on it stops, including the shell and any agent that ran the command. Ship anything you need before you run it.

It always asks first

remove --self always asks a yes/no question, and spells out that the target is the machine you are on:
Only y or yes deletes. Anything else (n, Enter, anything you didn’t mean as yes) leaves the machine running. If there is no answer at all, because stdin is closed, nothing is deleted and the command exits with an error. There is no -y flag for --self. A script or an agent answers the question explicitly instead:
The question goes to stderr, so --json output on stdout stays clean.

From code: the SDKs

Code running inside a machine uses delete_self (Python) or deleteSelf (TypeScript). The SDK finds the machine’s metadata adapter on its own, with no API key needed, and instead of a y/N question it takes the machine’s name as confirm, so the decision is spelled out in the code:
The same rules apply as for remove --self: confirm must be this machine’s name, or nothing is deleted and the call raises with the reason. Only the owner can do it, and never on a shared machine. Outside a machine, the call raises before doing anything. The async Python client has await boxd.machines.delete_self(confirm=...). In TypeScript it needs Node: the web entry can’t reach the metadata adapter.
Inside a machine, don’t delete it with machines.delete(own_id). That goes through the public API like a delete from your laptop: no confirmation, and the machine can shut down before your code gets the answer, so the call may hang or fail even though the machine was deleted. delete_self / deleteSelf answer first.

It returns before the machine shuts down

The command gets its answer from boxd and exits 0 first. The machine is deleted about 2 seconds later. That makes it safe as the last line of a job script. A line after it still runs, but only has those 2 seconds: enough for an exit or a quick notification, not for an upload.

Recipe: run a task, then delete

Start it from your laptop so it keeps running after you disconnect, and give the machine a delete-after timer as a safety net:
--auto-suspend-timeout 0 makes sure the machine stays awake. Auto-suspend is off by default, but a fork inherits its source’s setting, and a job with no network traffic on a machine that has it on goes into standby and stops making progress. To delete only when the task succeeds, and keep a failed run’s machine around to debug, chain it:
The delete-after timer then cleans up the failed machine later, if you don’t.

Keep a delete-after timer as the safety net

Self-delete covers a task that finishes. A delete-after timer covers everything else: the task hangs, the script dies before its last line, or the deletion itself fails after the command has returned. Whichever comes first wins, so the machine never keeps running and billing.

When it isn’t available

  • Shared machines are refused: other members of your org depend on them. Delete them from outside with boxd machine remove <name> -y, or from the console.
  • Only the machine’s owner can delete it this way.
  • Isolated machines have no in-machine boxd, so they can’t delete themselves. Give them a delete-after timer instead.
boxd machine remove <name> from inside a machine refuses to delete the machine it runs on and points you to --self, so you can’t delete yourself by naming yourself by accident.