Skip to content

Hooks

Hooks receive the same CommandInvocation as the selected command, so they can read retained input handles through invocation.valueOf. Context is passed to hook methods as a separate argument; it is not part of CommandInvocation and is not available to Command.run.

Mix HookRunner into a command to run behavior immediately before and after its run method:

final class DeployCommand extends Command with HookRunner {
@override
FutureOr<void> preRun(
CommandInvocation invocation,
MambaReadContext context,
ProcessedStandardInput? input,
) {}
@override
FutureOr<void> postRun(
CommandInvocation invocation,
MambaReadContext context,
) {}
}

Ordinary command hooks receive a read-only MambaReadContext. preRun also receives piped standard input when available. postRun runs only when the matching pre-hook completed. Eligible cleanup hooks still run after command failure.

Mix PersistentHookRunner into a GroupCommand to wrap descendant command execution:

final class WorkspaceCommand extends GroupCommand
with PersistentHookRunner {
WorkspaceCommand(super.commands) : super();
@override
FutureOr<void> prePersistentRun(
CommandInvocation invocation,
MambaContext context,
) {}
@override
FutureOr<void> postPersistentRun(
CommandInvocation invocation,
MambaContext context,
) {}
}

Persistent hooks receive the mutable MambaContext. Persistent pre-hooks run from the outermost group inward. Their matching post-hooks run in reverse order, so nested groups behave like wrappers.

MambaContext is an executor-scoped, identity-keyed scalar hook-state bag. Use one MambaContextKey<T> instance wherever a value is written or read. The key’s primitive type determines which sealed wrapper can be stored, while get returns that primitive directly:

final workspaceKey = MambaContextKey<String>();
final verboseKey = MambaContextKey<bool>();
final retryKey = MambaContextKey<int>();
context.set(workspaceKey, const MambaContextString('/workspace'));
context.set(verboseKey, const MambaContextBool(true));
context.set(retryKey, const MambaContextInt(3));
final String? workspace = context.get(workspaceKey);
final bool? verbose = context.get(verboseKey);
final int? retries = context.get(retryKey);

MambaContextDouble stores a double in the same way. Only the four built-in variants (String, bool, int, and double) are supported; applications cannot define additional variants. An unset key returns null, but null cannot be stored. Collections and domain objects are not supported, because context is not a dependency container. A reused executor retains its context between executions. Create a separate executor when state must be isolated. Applications remain responsible for reading environment variables or configuration files.

Mamba records hook failures as MambaExecutionError values tagged with their execution phase and command path. One failing cleanup hook does not prevent remaining eligible cleanup hooks from running. The first failure determines the execution result’s exit code.