> ## Documentation Index
> Fetch the complete documentation index at: https://docs.boxd.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Self-delete

> Let a machine delete itself from inside when its task is done, with `boxd machine remove --self` or the SDKs' `machines.delete_self()` / `deleteSelf()`. Always confirms first, and returns before the machine shuts down so it can be the last step of a job.

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.

```bash theme={"theme":"github-dark"}
boxd machine remove --self
```

Run it inside the machine, with the in-machine `boxd` that every machine has.

<Warning>
  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.
</Warning>

## It always asks first

`remove --self` always asks a yes/no question, and spells out that the target is the machine you are on:

```text theme={"theme":"github-dark"}
WARNING: SELF-DELETION

You asked to permanently delete the machine this command is running on:

  machine: job-42
  id:      7aea2e44-6d5d-4951-8282-7b7a8a33b691

This is not some other machine. It is the one you are on right now. If you continue:
  - this machine is destroyed, together with its disk and every file on it;
  - every process on it stops, including this shell and any agent that ran this command;
  - it cannot be undone and nothing on it can be recovered.

Answer y only if the task on this machine is finished and nothing on it is still needed.

Delete job-42, the machine you are running on, now? [y/N]
```

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:

```bash theme={"theme":"github-dark"}
echo y | boxd machine remove --self
```

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:

<CodeGroup>
  ```python Python theme={"theme":"github-dark"}
  from boxd import Boxd

  boxd = Boxd()                                      # inside a machine: no key needed
  result = boxd.machines.delete_self(confirm="job-42")
  result.deletes_in_secs                             # 2: the machine goes away after this
  ```

  ```typescript TypeScript theme={"theme":"github-dark"}
  import { Boxd } from "@boxd-sh/sdk";

  const boxd = new Boxd();                           // inside a machine: no key needed
  const result = await boxd.machines.deleteSelf({ confirm: "job-42" });
  result.deletesInSecs;                              // 2: the machine goes away after this
  ```
</CodeGroup>

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.

<Warning>
  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.
</Warning>

## 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.

```bash theme={"theme":"github-dark"}
echo y | boxd --json machine remove --self
# {"name": "job-42", "status": "destroying", "destroy_in_secs": 2, "vm_id": "..."}
```

## Recipe: run a task, then delete

```bash theme={"theme":"github-dark"}
#!/bin/sh
# job.sh: runs inside the machine
./run-task.sh
STATUS=$?

# The disk goes with the machine, so ship the results out first:
# copy them to another machine, upload them, push to git, call a webhook...
boxd machine cp /home/boxd/out/report.json results-vm:/data/job-42.json

echo y | boxd machine remove --self
exit $STATUS
```

Start it from your laptop so it keeps running after you disconnect, and give the machine a [delete-after](/guides/delete-after) timer as a safety net:

```bash theme={"theme":"github-dark"}
boxd machine fork base job-42 --delete-after 2h --auto-suspend-timeout 0
boxd machine cp job.sh job-42:/home/boxd/job.sh
boxd machine exec job-42 -- 'chmod +x /home/boxd/job.sh && nohup /home/boxd/job.sh > /home/boxd/job.log 2>&1 &'
```

`--auto-suspend-timeout 0` makes sure the machine stays awake. [Auto-suspend](/guides/suspend-resume) 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:

```bash theme={"theme":"github-dark"}
./run-task.sh && echo y | boxd machine remove --self
```

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](/guides/delete-after) 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](/use-cases/sandboxes) 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.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.