The Node stack
The node stack is the central registry that manages all your nodes and their relationships in PeppyOS. Think of it as a directed graph where:
- Nodes are registered configurations that can have multiple running instances
- Edges represent explicit dependencies declared via
depends_onin the node manifest
When you add a node to the stack, PeppyOS validates that all its dependencies are satisfied—ensuring that any topics, services, or actions your node relies on are provided by other nodes already in the stack. This dependency validation prevents runtime errors and helps you understand how your nodes interconnect.
The stack always contains a core node and an instance of it at its root, which coordinates the lifecycle of all other nodes. You can query the stack to see which nodes depend on each other, visualize the dependency graph, and manage node instances.
The node stack is started as a daemon on your system and the peppy binary communicates with it to execute user actions.
Adding hello_world to the stack
Section titled “Adding hello_world to the stack”Inside your node directory, add it to the PeppyOS stack by running:
peppy node add .This command registers the node with the core node by staging a snapshot of the source directory. After a successful add, the node enters the Added stage: its config is known to the daemon, but no runnable artifact exists yet — build_cmd has not been run. You’ll produce that artifact in the next section with peppy node build.
The output of this command provides some useful information:
Adding node from /private/tmp/hello_world...Log file: ~/.peppy/logs/add/hello_world_0.1.0_20260121_224824_699.logAdded node hello_world:0.1.0 to the node stackThis gives you access to the log file for debugging in case the add command fails.
When a node is added to the node stack, a copy is made in the peppy cache under ~/.peppy/built_nodes/ to “snapshot” the node based on its name and tag.
No two copies of the same node with the same name + tag can exist at the same time in the node stack.
Re-adding a node with the same name and tag overrides the one that was previously in the node stack, except if that node has dependencies—in which case the operation fails.
Building hello_world
Section titled “Building hello_world”An added node has no runnable artifact until it’s built. Building runs the node’s build_cmd (for example uv sync for Python or cargo build --release for Rust) against the snapshot that peppy node add staged:
peppy node build hello_world:0.1.0The format is <node_name>:<tag> for a node that is already part of the node stack. While the build is running the node sits in the Building stage; once it completes, it moves to Ready and can be run.
The output looks like:
Building node hello_world:0.1.0...Log file: ~/.peppy/logs/build/hello_world_0.1.0_20260121_224901_312.logBuilt node hello_world:0.1.0. Artifact: ~/.peppy/built_nodes/hello_world_0.1.0.tar.zstThe artifact is a .tar.zst archive. When you start an instance with peppy node run, the daemon extracts it into a per-instance directory and executes run_cmd there.
Starting your node
Section titled “Starting your node”Start your node:
peppy node run hello_world:0.1.0This will run the run_cmd command from the peppy.json5 process configuration.
The format is <node_name>:<tag> for a node that is already part of the node stack.
The node run command outputs the path to a log file where you can inspect the node’s output.
For example:
cat /home/ubuntu/.peppy/logs/run/elegant-solomon-5423.log[2026-02-17T10:15:23.599] Executing run_cmd: uv run hello_world (working_dir: /home/ubuntu/.peppy/instances/elegant-solomon-5423)[2026-02-17T10:15:23.837] [stdout] hello world count 1[2026-02-17T10:15:26.848] [stdout] hello world count 2[2026-02-17T10:15:29.852] [stdout] hello world count 3Chaining add, build, and run
Section titled “Chaining add, build, and run”Now that you’ve seen all three steps, peppy node add exposes flags that chain them for you:
--build(-b) runspeppy node buildimmediately after the add succeeds.--run(-r) also spawns an instance once the build finishes, and implies--build.--sync(-s) runspeppy node syncbefore the add, so the snapshot picks up any edits you made topeppy.json5. Only valid for local filesystem sources — remote git/HTTP sources are synced server-side on fetch.
peppy node add -sb . # sync, then add, then buildpeppy node add -sr . # sync, then add, then build, then run an instanceChecking node status
Section titled “Checking node status”View all added & running nodes:
peppy stack listYou should see something like:
$ peppy stack listNode stack
┌────────────────────────────────────────┬───────┬─────────┬───────────┬───────────────────────────────────────────────────────────┐│ NODE │ STAGE │ VARIANT │ INSTANCES │ PATH │├────────────────────────────────────────┼───────┼─────────┼───────────┼───────────────────────────────────────────────────────────┤│ core-node-funny-chatterjee-6386:v0.8.0 │ Root │ default │ 1 running │ /home/ubuntu/.peppy/bin ││ hello_world:0.1.0 │ Ready │ default │ 1 running │ /home/ubuntu/.peppy/built_nodes/hello_world_0.1.0.tar.zst │└────────────────────────────────────────┴───────┴─────────┴───────────┴───────────────────────────────────────────────────────────┘
Dependencies (none)The STAGE column reports each node’s stage — its artifact-level lifecycle:
Added— the node is registered and a snapshot of the source has been taken, butbuild_cmdhas not been run yet, so there is no runnable artifact.Building— a build is in progress. A second concurrentnode buildon the same entity is rejected until this one finishes.Ready— the build artifact is on disk. The node can be run; it may currently have zero, one, or several instances.Root— the synthetic core-node entity. Always present, and always reports exactly one running instance (the daemon itself).
The INSTANCES column aggregates per-instance state (starting, running) for the node, independently of its stage. To see individual instance IDs, use peppy node info.
Inspecting a node with peppy node info
Section titled “Inspecting a node with peppy node info”When you need more than the one-line view from stack list, peppy node info dumps the node’s stage, its currently-tracked instances with their individual states, and the paths to its add log and per-instance run logs. It takes a <node_name>:<node_tag> reference to a node that has already been added to the stack — it doesn’t touch the filesystem or any git/http source, so run peppy node add first if the node isn’t in the stack yet:
peppy node info hello_world:0.1.0[INFO] Getting node info for hello_world:0.1.0...
Node Information==================================================
Name: hello_worldTag: 0.1.0Language: PythonBuild cmd: uv syncRun cmd: uv run hello_world
Node Stack Status--------------------------------------------------Stage: ReadyVariant: defaultInstances: 2 tracked - suspicious-swanson-5880 [running] - flamboyant-penrose-9622 [running]
Logs--------------------------------------------------hello_world:0.1.0 Add log: /home/ubuntu/.peppy/logs/add/hello_world_0.1.0_20260416_101124_613.log Run logs: - suspicious-swanson-5880: /home/ubuntu/.peppy/logs/run/suspicious-swanson-5880.log - flamboyant-penrose-9622: /home/ubuntu/.peppy/logs/run/flamboyant-penrose-9622.log
Exposed Interfaces--------------------------------------------------Emitted Topics: - message_stream (qos: SensorData)
Integrity--------------------------------------------------Config SHA256: 67505086f8ac099d0861cb5dfa539b1c8c3c9354ad90ed7713a5147c7cb43342This is usually the fastest way to answer “is my node built yet?” and “where is the log for this specific instance?”. The Add log path is what peppy node add writes to; per-instance run logs are what peppy node run writes to. Build logs live under ~/.peppy/logs/build/ and are surfaced by peppy node build directly when it runs.
The Variant: line shows the variant that was selected when the node was added. It prints default both when no variant override was passed (auto-resolved default variant) and when the node declares no variants at all (the root’s own execution section is the default).
Exposed Interfaces summarizes the topics, services, and actions the node publishes or consumes per its peppy.json5. Config SHA256 is the fingerprint of the config that was fed through peppygen — it’s what peppy node add checks against to refuse a stale snapshot and tell you to run peppy node sync.
Stopping your node
Section titled “Stopping your node”When you’re done, you can stop your node:
peppy node stop <instance-id>This stops one instance of the hello_world:0.1.0 node, but the node itself still remains in the node stack.
Removing your node
Section titled “Removing your node”To remove the node from the node stack, run:
peppy node remove hello_world:0.1.0If you run peppy stack list again, you’ll see that only the core node remains:
$ peppy stack listNode stack
┌────────────────────────────────────────┬───────┬─────────┬───────────┬─────────────────────────┐│ NODE │ STAGE │ VARIANT │ INSTANCES │ PATH │├────────────────────────────────────────┼───────┼─────────┼───────────┼─────────────────────────┤│ core-node-funny-chatterjee-6386:v0.8.0 │ Root │ default │ 1 running │ /home/ubuntu/.peppy/bin │└────────────────────────────────────────┴───────┴─────────┴───────────┴─────────────────────────┘
Dependencies (none)Next steps
Section titled “Next steps”Now that you’ve created your first node, you can:
- Add interfaces to communicate with other nodes
- Configure parameters for your node
- Learn about the node stack and dependencies