> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nvidia.com/nemo/relay/llms.txt.
> For full documentation content, see https://docs.nvidia.com/nemo/relay/llms-full.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nvidia.com/nemo/relay/_mcp/server.

# Rust Quick Start

This quick start shows the smallest Rust workflow that emits scope and mark events.

## Choose an Install Path

Pick the installation path that matches whether you are using a published package or a
local checkout.

### Install from a Package Manager

Use the published crates when you are consuming a release:

```bash
cargo add nemo-relay@0.4.0
cargo add nemo-relay-adaptive@0.4.0
cargo add serde_json
```

Install the published NeMo Relay CLI separately when you need coding-agent hook
and LLM gateway observability:

```bash
cargo install nemo-relay-cli@0.4.0
```

### Install from the Repository

Use a path dependency when your application is consuming a local checkout:

```toml
[dependencies]
nemo-relay = { path = "../NeMo-Relay/crates/core" }
nemo-relay-adaptive = { path = "../NeMo-Relay/crates/adaptive" }
serde_json = "1"
```

* `nemo-relay` is the core Rust runtime surface.
* `nemo-relay-adaptive` is the companion crate for adaptive runtime primitives and Redis-backed learning components.
* `nemo-relay-cli` is a binary crate. Use `cargo install nemo-relay-cli@0.4.0` when
  you need the NeMo Relay CLI.

## Push a Scope and Emit a Mark

The example below creates a scope and records a mark event from Rust.

```rust
use nemo_relay::api::scope::{
    self, EmitMarkEventParams, PopScopeParams, PushScopeParams, ScopeAttributes, ScopeType,
};
use nemo_relay::api::subscriber::{deregister_subscriber, flush_subscribers, register_subscriber};
use serde_json::json;
use std::sync::Arc;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    register_subscriber(
        "quickstart-printer",
        Arc::new(|event| {
            println!("{} {}", event.kind(), event.name());
        }),
    )?;

    let handle = scope::push_scope(
        PushScopeParams::builder()
            .name("demo-agent")
            .scope_type(ScopeType::Agent)
            .attributes(ScopeAttributes::empty())
            .data(json!({"binding": "rust"}))
            .build(),
    )?;

    scope::event(
        EmitMarkEventParams::builder()
            .name("initialized")
            .parent(&handle)
            .data(json!({"ok": true}))
            .build(),
    )?;
    scope::pop_scope(PopScopeParams::builder().handle_uuid(&handle.uuid).build())?;
    flush_subscribers()?;
    let _ = deregister_subscriber("quickstart-printer")?;
    Ok(())
}
```

## What Success Looks Like

The script should exit cleanly and print lifecycle lines from the subscriber.
Native subscriber delivery is asynchronous, so examples flush before checking
subscriber output.
You should see one line for the scope start event, one for the `initialized`
mark, and one for the scope end event.

That tells you two things:

* The scope API ran successfully.
* Emitted events were observable through the subscriber system.

## What to Learn Next

Use these links to continue from the quick start into the core runtime concepts.

* Use [Scopes](/about-nemo-relay/concepts/scopes), [Middleware](/about-nemo-relay/concepts/middleware), [Subscribers](/about-nemo-relay/concepts/subscribers), and [Plugins](/about-nemo-relay/concepts/plugins) for the runtime model.