Context manager versus method semantics:Boxliteuses a synchronouswithto enter and exit (__enter__/__exit__are synchronous), but its business methods (create/get_or_create/list_info/remove/shutdown, etc.) are allasyncand must be awaited. ABoxusesasync withto enter and exit, and its methods are likewiseasync— the only exception is the synchronousinfo().
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 needawait.
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.). Onasync withentry they lazily create and automatically start the Box, and on exit they clean up according toauto_remove, so you never have to manage the runtime handle by hand. Operate theBoxliteruntime 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 callstop() — 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.A. Wrapper layer: lazy create and automatic cleanup (recommended starting point)
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 theBoxlite 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 isJsBoxlite(there is no bareBoxlite); listing useslistInfo(); removal usesruntime.remove(idOrName, force?);SimpleBoxusesawait usingfor automatic cleanup;info()is synchronous whilegetInfo()is asynchronous.

