Skip to main content
The Mirage server serves JSON over HTTP, every route under /v1, the same in Python and TypeScript. The CLI is a client of these routes.

Run it

The server is a FastAPI app in Python and a Fastify app in TypeScript. Run it as your own service:
It answers only the Host names in allowed_hosts (MIRAGE_ALLOWED_HOSTS), 127.0.0.1, localhost and ::1 by default, so add the name your clients use. On your own machine the CLI starts the same server as a daemon, which exits 30 seconds after its last workspace is deleted. Options are on the Python and TypeScript server pages.

Auth

Every route but GET /v1/health needs Authorization: Bearer <token>. MIRAGE_AUTH_MODE decides what the server accepts: In jwt mode the server checks the signature against that public key, accepts only the pinned algorithm, requires exp, and checks iss, aud and azp when MIRAGE_JWT_ISSUER, MIRAGE_JWT_AUDIENCE and MIRAGE_JWT_AUTHORIZED_PARTIES are set. It never fetches keys, so a new key needs a restart.
The server checks that a token is valid, not what it may do: any accepted token can use every route and every workspace, including POST /v1/shutdown. Give one server to one tenant. In local mode with no token in the environment or in ~/.mirage/auth_token, the server asks for none.

Errors

A failed request answers {"detail": "<message>"}.

Server

Check health

GET /v1/health Answers {"status": "ok", "workspaces": 2, "uptime_s": 12.5}, without a token.

Shut down

POST /v1/shutdown Asks the server to stop. The daemon the CLI starts closes its workspaces and exits; a server you run yourself stops only if you gave it on_idle_exit (onIdleExit in TypeScript).

Workspaces

Create a workspace

POST /v1/workspaces
object
required
The workspace YAML as JSON.
string
The workspace id. A fresh one when absent.
Answers 201 and the workspace. The same id and config again answers 200 and that workspace; another config under a taken id answers 409.

List workspaces

GET /v1/workspaces

Get a workspace

GET /v1/workspaces/{id}
boolean
default:"false"
Add cache and job internals.

Delete a workspace

DELETE /v1/workspaces/{id} Closes the workspace and deletes its state.

Clone a workspace

POST /v1/workspaces/{id}/clone
string
The new workspace’s id.
object
A config whose mounts replace the source’s.

Snapshot a workspace

GET /v1/workspaces/{id}/snapshot Answers the tar (application/x-tar). Secrets are stored redacted. The server never writes a snapshot to its own disk. POST /v1/workspaces/{id}/snapshot
string
required
Puts the tar in the server’s snapshot store under this key, and answers {id, key, size}. 400 when the server has none.

Load a snapshot

POST /v1/workspaces/load Upload the tar as multipart/form-data: a request part holding the JSON fields below, then a snapshot part of up to 1 GiB. Or send JSON with a key to load from the snapshot store.
string
The tar’s key in the snapshot store; leave it out when uploading.
string
The new workspace’s id.
object
A config that re-supplies the redacted credentials.

Sessions

Create a session

POST /v1/workspaces/{id}/sessions
string
The session id. A fresh one when absent.
string
A profile from the workspace’s profiles.
object
Prefix to mode (read, write, exec) to narrow those mounts, such as {"/data": "read"}.

List sessions

GET /v1/workspaces/{id}/sessions

Delete a session

DELETE /v1/workspaces/{id}/sessions/{session_id}

Shell and tools

Run a shell line

POST /v1/workspaces/{id}/shell
string
required
The line.
string
The session. The default when absent.
string
A working directory for this line only.
boolean
default:"false"
Answer 202 with {job_id, workspace_id, submitted_at} at once.
Answers {kind, exit_code, stdout, stderr, refusal} when the line finishes, with the job id in X-Mirage-Job-Id. A dropped request cancels its job. To send stdin, post multipart/form-data with a request part holding the JSON body, then a stdin part. The line starts when the stdin part begins and reads it as it arrives. A body that stops before its closing boundary cancels the line and answers 400. With ?background=true, the whole upload is read before the 202.

Call a tool

POST /v1/workspaces/{id}/{tool}
string
The session. The default when absent.
The body is the tool’s input: Answers {text, is_error}. A tool that fails is still 200, with is_error set.

Jobs

Every shell line is a job: pending, running, then done, failed or canceled.

List jobs

GET /v1/jobs
string
Only this workspace’s jobs.

Get a job

GET /v1/jobs/{job_id}

Wait for a job

POST /v1/jobs/{job_id}/wait
number
Seconds to wait. A timeout answers the job as it is, without canceling it.

Cancel a job

DELETE /v1/jobs/{job_id}

Asks

List asks

GET /v1/workspaces/{id}/asks
string
Only this session’s asks.
boolean
default:"false"
Include settled ones.

Answer an ask

POST /v1/workspaces/{id}/asks/{ask_id}
string
required
allow or deny.
string
default:"once"
once, or session to allow every matching line in the session.