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

# Host

> Run programs installed on your host, optionally confined by a sandbox.

A `host` machine runs programs installed on the host running Mirage, such as
`python3`, `node`, `tsx`, `ffmpeg` or a vendor CLI. A program sees the host's
files and network, not the workspace mounts; to reach the mounts, give it a
[FUSE folder](https://docs.mirage.strukto.ai/home/setup/fuse.md). Nothing confines it unless the machine has a
[`sandbox`](#sandbox). Python SDK and Node only.

## Installation

Install the programs you want to run on the host. `home` selects only the
Python interpreter. Without it, Mirage
uses `MIRAGE_LOCAL_HOME`, then the interpreter running Mirage (Python) or
`python3` on `PATH` (Node).

## Usage

`captures` defaults to `@python` (`python3` and `python`). Add names such as `node` or `tsx`, or
[`@external`](https://docs.mirage.strukto.ai/home/setup/machine/overview#captures) for every program
Mirage does not have itself. Mirage's own commands, pipes and redirects stay
in Mirage: `ffmpeg -i in.mp4 out.webm | wc -c` sends only `ffmpeg`.

> [tab] Python
>
> ```python theme={null}
> from mirage import RAMVFS, MountMode, Workspace
>
> ws = Workspace(
>     {"/data": RAMVFS()},
>     mode=MountMode.EXEC,
>     machines={"host": {"provider": "host", "captures": ["@python", "@external"]}},
> )
> await ws.shell("python3 -c 'print(1 + 1)'; echo hi | cksum")
> ```

> [tab] TypeScript
>
> ```typescript theme={null}
> import { MountMode, RAMVFS, Workspace } from '@struktoai/mirage-node'
>
> const ws = new Workspace(
>   { '/data': new RAMVFS() },
>   {
>     mode: MountMode.EXEC,
>     machines: { host: { provider: 'host', captures: ['@python', '@external'] } },
>   },
> )
> await ws.shell("python3 -c 'print(1 + 1)'; echo hi | cksum")
> ```

> [tab] YAML
>
> ```yaml theme={null}
> mode: exec
> machines:
>   host:
>     provider: host
>     captures: ["@python", "@external"]
>     home: /path/to/venv/bin/python
> mounts:
>   /data:
>     vfs: ram
> ```

## Sandbox

A `sandbox` block confines each program through
[Sandlock](https://github.com/multikernel/sandlock), with Landlock and
seccomp: it reads only the paths you grant and writes only the ones you
allow. Linux only. Install the `sandlock` CLI on `PATH`; the full ruleset
needs Linux 6.12 or later. With a sandbox, `captures` defaults to
[`@external`](https://docs.mirage.strukto.ai/home/setup/machine/overview#captures); name `@python` to run
the host's `python3` under it too.

```yaml theme={null}
machines:
  host:
    provider: host
    captures: ["@python", "@external"]
    sandbox:
      fs_readable: [/opt/tools]
      fs_writable: [/tmp/work]
      max_memory: 512M
```

### Sandbox behavior

| Capability | Under the sandbox |
| - | - |
| Command | The captured program and its words, as argv |
| Piped input | stdin |
| Environment | The session's, over the machine's `env`; none of the host's |
| Working directory | The shell's |
| Files it can read | `/usr`, `/lib`, `/lib64`, `/bin`, `/etc`, `/proc`, `/dev`, and `fs_readable` |
| Files it can write | `fs_writable` only |
| Memory | Capped at `max_memory`, when set |
| Workspace files | Only through a FUSE folder you grant; see [below](#connecting-the-workspace) |

* Under a [`system_time`](https://docs.mirage.strukto.ai/home/configuration/workspace#system-time), programs see
  that time through libfaketime when it is installed, and the host's
  clock without it.
* An interpreter installed outside the system paths needs an `fs_readable`
  grant.
* Host credentials are not passed to the program.
* A workspace whose [`network`](https://docs.mirage.strukto.ai/home/configuration/workspace#network) limits
  anything, or whose policies judge connections, runs nothing here: the
  program connects from this host, around both. It answers `Permission
  denied`, exit 126.
* Mirage does not create the FUSE folder or bind it to a session.
* Program lookup uses the sandbox's `PATH`, with the CLI's system default when
  the session does not set one. Add directories such as `/usr/local/bin` to the
  session's `PATH` when required. Missing-program diagnostics come from Sandlock.
* A working directory absent from the host refuses the command with exit 126.
* A [timeout](https://docs.mirage.strukto.ai/home/core/output-limits.md#limit-a-lines-time) kills the program.

## Connecting the workspace

A host program opens host paths, not the workspace's. To give it workspace
files, expose a mount as a [FUSE folder](https://docs.mirage.strukto.ai/home/setup/fuse.md), and under a
sandbox grant it in `fs_writable`, or `fs_readable` for read only:

```yaml theme={null}
mounts:
  /data:
    vfs: s3
    config:
      bucket: my-bucket
    backend: fuse
    mountpoint: /data
machines:
  host:
    provider: host
    captures: ["@python", "@external"]
    sandbox:
      fs_writable: [/data]
```

After the folder is mounted, run the shared
[workspace file check](https://docs.mirage.strukto.ai/home/setup/machine/overview.md#verify-workspace-file-access).

* Put the folder at the mount's own path when you can, so a path typed in
  the shell names the same file in the program.
* Calls into the folder follow mount modes and policies. A folder added in
  code with a session, `add_fuse_mount(prefix, mountpoint, session_id)` or
  `addFuseMount(prefix, mountpoint, sessionId)`, also follows that
  session's permissions.

## Python compatibility

`python3` is the same Mirage command on every Python runtime: Mirage reads
the script from the workspace and checks it like any file, and a host machine runs
it on the host's interpreter. Every other program is a plain host program.

Python module availability and file modes come from the host interpreter.
Mirage does not replace them with a subset. Workspace paths become host paths
only when exposed through a FUSE folder. Examples below assume that folder
is mounted at `/data`.

### `open()`

Files are host files, including any FUSE folders. Modes and modifiers follow
the host interpreter's Python version.

| Mode or modifier | Support |
| - | - |
| `r` | Host interpreter |
| `w` | Host interpreter |
| `a` | Host interpreter |
| `x` | Host interpreter |
| `b` | Host interpreter |
| `t` | Host interpreter |
| `+` | Host interpreter |

> [accordion] Example: append to a workspace file
>
> ```python theme={null}
> with open("/data/log.txt", "a") as f:
>     f.write("Job completed.\n")
> ```

> [accordion] Limitations
>
> | API or behavior | Limitation |
> | - | - |
> | File access | Opens host files. Workspace files are accessible only through a mounted FUSE folder. |

### File objects

| API | Support |
| - | - |
| File-object methods | Host interpreter |

> [accordion] Example: write, read and truncate a file
>
> ```python theme={null}
> with open("/data/example.txt", "w+") as f:
>     f.write("first\nsecond\n")
>     f.seek(0)
>     print(f.read(5))  # first
>     f.truncate(5)
> ```

### `os`

| API | Support |
| - | - |
| Filesystem APIs | Host interpreter |
| `os.environ` | ✓ |
| `os.getcwd()` | ✓ |

> [accordion] Example: list a workspace directory
>
> ```python theme={null}
> import os
>
> print(os.listdir("/data"))
> ```

> [accordion] Limitations
>
> | API or behavior | Limitation |
> | - | - |
> | Filesystem APIs | Operate on host paths, including FUSE folders. |
> | `os.environ` | The session's environment plus the machine's `env`; none of the host's environment. |
> | `os.getcwd()` | Starts in Mirage's own working directory. |

### `pathlib`

| API | Support |
| - | - |
| `Path` | Host interpreter |

> [accordion] Example: create and inspect a workspace file
>
> ```python theme={null}
> from pathlib import Path
>
> path = Path("/data/example.txt")
> path.write_text("hello\n")
> print(path.read_text())
> print(path.stat().st_size)
> ```

> [accordion] Limitations
>
> | API or behavior | Limitation |
> | - | - |
> | `Path` | Operates on host paths, including FUSE folders. |

### `sys`

| API | Support |
| - | - |
| `sys.argv` | ✓ |
| `sys.stdin` | ✓ |
| `sys.path[0]` | Host interpreter |

> [accordion] Example: read arguments and piped input
>
> ```python theme={null}
> import sys
>
> print(sys.argv[1:])
> print(sys.stdin.read())
> ```

> [accordion] Limitations
>
> | API or behavior | Limitation |
> | - | - |
> | `sys.path[0]` | The host's working directory. |

### Runtime globals

| API | Support |
| - | - |
| `__file__` | ✓ |

* `__file__`: The script's workspace path; tracebacks use that path too.

> [accordion] Example: print the script path
>
> ```python theme={null}
> print(__file__)
> ```

## Runtime behavior

| Capability | `python3` | Other programs |
| - | - | - |
| Program | The host's `python3`, given the script from the workspace | The name, found on the host's `PATH`; exit 127 if it is not there |
| Arguments | `sys.argv` | Its argv, with no shell |
| Piped input | stdin | stdin |
| Environment | The session's, plus the machine's `env`; none of the host's | The same |
| Working directory | Mirage's own | The shell's; exit 126 if it does not exist on the host |
| Files | The host's, and FUSE folders | The host's, and FUSE folders |
| Network | The host's | The host's |
| Time | The workspace's [`system_time`](https://docs.mirage.strukto.ai/home/configuration/workspace#system-time) when it sets one and libfaketime is installed, on Linux; otherwise the host's | The same |

## Notes

* A workspace whose [`network`](https://docs.mirage.strukto.ai/home/configuration/workspace#network) limits
  anything, or whose policies judge connections, runs nothing here: the
  program would connect around both. It answers `Permission denied`, exit
  126\.
* A timeout kills the subprocess. `kill` sends it the signal it names, then
  `KILL` a second later if it is still running. A program that handles the
  signal and exits gives `wait` its own exit status, as in Bash.


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