Topics
Topics organize frames in the event stream. The . character creates
hierarchy, enabling wildcard queries.
Naming Rules
| Rule | Detail |
|---|---|
| Allowed characters | a-z A-Z 0-9 _ - . |
| Must start with | a-z A-Z _ |
| Cannot end with | . |
| Cannot contain | .. |
| Max length | 255 bytes |
Valid: chat, user.alice, orders.2024.pending, my_topic-v2
Invalid: .hidden, -dash, 123, trailing., foo..bar, has space
Hierarchy
The . separator creates a topic hierarchy:
user.alice.messagesuser.alice.statususer.bob.messagesThis structure enables prefix queries.
Wildcard Queries
Use .* suffix to query all direct and nested children of a prefix:
# All frames under user.alice (messages, status, etc.)xs cat ./store --topic "user.alice.*"
# All user framesxs cat ./store --topic "user.*"The wildcard user.* matches user.alice, user.alice.messages, and
user.bob, but not user itself.
Use * alone to match all topics (equivalent to omitting --topic).
Topic queries return frames in chronological order (by frame ID), not grouped by topic. Both historical reads and live follows maintain this ordering.
The xs. namespace
Topics that begin with xs. are owned by the runtime. Everything else is app
data:
xs.actor.<name>.<event> actor lifecyclexs.service.<name>.<event> service lifecyclexs.action.<name>.<event> action lifecyclexs.module.<name> module registrationxs.threshold, xs.stopping system markersA topic that starts with xs. is runtime-managed; everything else is app
data. See the lifecycle reference for the full lifecycle
vocabulary and the algorithm that consumes it.
Module Topics
Topics under xs.module.<name> register Nushell modules into the virtual
filesystem (VFS). Any actor, service, or action script can then use these
modules by their stable VFS path.
# Register a moduler#'export def greet [name: string] { $"hello ($name)" }'# | .append xs.module.mymodThe module name (after xs.module.) maps to a directory path, dots become
slashes:
| Topic | VFS Path |
|---|---|
xs.module.mymod | mymod/mod.nu |
xs.module.discord.api | discord/api/mod.nu |
Scripts reference modules by their stable VFS path. Re-appending a module topic shadows the previous version:
r#'{ run: {|frame, state| use mymod {out: {greeting: (mymod greet "world")}, next: $state} }}'# | .append xs.actor.greeter.createEach actor, service, or action sees the modules as they existed when it was created. Modules appended later are only visible to processors created after them. Re-appending a module and then re-creating a processor picks up the new version.
System Topics
| Topic | Description |
|---|---|
xs.start | System initialization complete |
xs.threshold | Stream processing threshold marker |
xs.pulse | Synthetic pulse events (configurable interval) |
xs.stopping | Server-wide shutdown signal |
Output suffix customization
Output suffixes can be changed via return_options.suffix:
.recv(services).out(actors).response(actions)
These are app-namespace data topics, not lifecycle topics; they stay outside
the xs. namespace.
{ run: {|| "Hello, World!" }, return_options: { suffix: ".message" # Changes .recv to .message }}