Skip to main content
Context manager versus method semantics: Boxlite uses a synchronous with to enter and exit (__enter__/__exit__ are synchronous), but its business methods (create / get_or_create / list_info / remove / shutdown, etc.) are all async and must be awaited. A Box uses async with to enter and exit, and its methods are likewise async — the only exception is the synchronous info().

In this section


Two objects: a runtime and a Box

BoxLite separates “the runtime that manages a group of Boxes” from “operating on a single Box” into two objects. The two have different context manager semantics. Note: whether a context manager is synchronous or asynchronous is an independent question from whether its methods need await. Key point: the runtime enters with a synchronous with, but its methods must be awaited; a Box enters with async with, and its methods must also be awaited; only info() is always synchronous and must not be awaited.
In general, prefer the wrapper layer (SimpleBox / CodeBox, etc.). On async with entry they lazily create and automatically start the Box, and on exit they clean up according to auto_remove, so you never have to manage the runtime handle by hand. Operate the Boxlite runtime directly only when you need to manage several Boxes at once.

What a Box goes through

A box is created lazily, becomes running on first use, goes stopped when you call stop() — keeping its disk — and is removed either by auto_remove or by the runtime. Stop is not remove: a stopped box restarts with everything it had installed. The state diagram, the full transition table, and how to read box.info().state.status are on Lifecycle.

Making sure nothing is left running

Key point: removal is the runtime’s responsibility, not the Box’s — call await runtime.remove(id_or_name), not box.remove() (which does not exist). The same applies to listing: use await runtime.list_info(), not list(). These runtime methods are all async and must be awaited.

Quick Example

Both examples below are directly runnable. SimpleBox lazily creates and starts the Box on async with entry and, on exit, destroys it automatically according to auto_remove (default True), without touching the runtime handle directly.

B. Explicit runtime management: create a named Box, reuse it across calls, then remove it explicitly

When you need a long-lived Box or want to reuse one across processes, operate the Boxlite runtime directly. Note two things: Boxlite enters with a synchronous with, but its business methods are async and must be awaited; a single Box is still an async context manager.
Node equivalent (key differences): the package is @boxlite-ai/boxlite; the runtime class is JsBoxlite (there is no bare Boxlite); listing uses listInfo(); removal uses runtime.remove(idOrName, force?); SimpleBox uses await using for automatic cleanup; info() is synchronous while getInfo() is asynchronous.

Where to go next

This page is the mental model. Everything below has a home page that goes deeper: