Lifecycle
How the current runtime boots and stops a stack.
defineDevstack(...) is synchronous. It builds a static stack handle and performs composition-time
checks. The runtime path starts when a surface consumes that handle.
Runtime surfaces:
devstack upstarts a supervisor and stays attached.devstack applypublishesapply.requestedto the live supervisor when this stack is already attached; otherwise it starts the same supervisor path in one-shot mode.runStack(stack, opts)embeds the supervisor in another TypeScript program.
import { Effect } from 'effect';
import { account, defineDevstack, runStack, sui } from '@mysten-incubation/devstack';
const stack = defineDevstack({ members: [sui(), account('alice')], stackName: 'embedded' });
const handle = runStack(stack, {
runtimeRoot: '.devstack',
identity: { app: 'demo', stack: 'embedded' },
});
await Effect.runPromise(handle.start);
await Effect.runPromise(handle.stop);
await Effect.runPromise(handle.awaitShutdown);Boot order is derived from dependsOn edges. Members that need Sui depend on the shared sui
resource, so the stack includes one concrete sui(...) provider. wallet({ accounts: 'all' }) is
expanded after the full member list is known, so it depends on every account member in the final
stack.
The supervisor claims roster.json while attached, publishes typed events, maintains a live
projection, writes the manifest, emits generated files, and serves commands from the attached TUI
and filesystem command channel. Shutdown is attached to the running process: quit the TUI or
interrupt devstack up, then scope finalizers run and the roster claim is released.