> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cerulion.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Network a graph and reach remote robots

> How cross-machine visibility works by default, how to restrict it with the network block, and how to find, pair with, and pull topics from a robot.

A live Cerulion run is **network-viewable by default**. A robot on your LAN announces the topics it produces and forwards one the moment a remote subscriber asks for it, with no configuration. You restrict that with a `network:` block, or turn it off for a run.

Local transport is unaffected by any of this: nodes on the same machine always talk through zero-copy shared memory.

## What a run resolves to

Evaluated in this order:

| Condition                                 | Result                                                                   |
| ----------------------------------------- | ------------------------------------------------------------------------ |
| `--network off` or `CERULION_NETWORK=off` | Local-only. Nothing crosses the machine boundary, with a loud notice.    |
| `--time-source virtual` or `external`     | Network inert — a live network session would break replay byte-identity. |
| A `network:` block                        | Strict: exactly the declared allow-lists and locators.                   |
| No block (including under `--record`)     | Permissive: every produced topic is network-viewable.                    |

Recording keeps the network on, so a robot stays viewable while it records.

```bash theme={null}
# Local-only for this run:
cerulion graph run perception --network off
```

## Restrict what leaves the machine

The `network:` block is a **tightening**, not an on-switch. Declaring one puts the run in strict mode.

```yaml theme={null}
network:
  mode: peer
  listen:
    - tcp/0.0.0.0:7683
  egress:
    - /robot1/lidar/cloud
  ingress:
    - /operator/cmd_vel
```

| Field                | Meaning                                                                                                                                                                     |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `mode`               | `peer` joins the mesh, `client` connects to a router without routing traffic, `disabled` leaves the block parsed but inert. Omitted means `disabled`, so set it explicitly. |
| `listen` / `connect` | Locators, used **verbatim** — a declared block does no scouting, so one side must `listen` and the other must `connect`.                                                    |
| `egress`             | A true allow-list: only these topics ever leave. Each must be produced by a node in this graph.                                                                             |
| `ingress`            | Topics imported from the network. Each must have no in-graph producer and must be consumed by one, and every frame is schema-checked before injection.                      |

Validation refuses each mistake by name — a topic in both lists, an `egress` topic nobody produces, an `ingress` topic this graph already produces, a relative topic name, or a non-empty list under `mode: disabled`. Empty lists under `peer` are valid: that is an export-restricted robot.

<Note>
  `--record` together with a block that declares `ingress:` is refused, because recorded ingress re-injection is not yet replay-faithful. Record without the ingress bridge, or run without `--record`.
</Note>

The full key reference is in [Graph and schema files](/cerulion/reference/graph-and-schema-files).

## Find robots on the network

`cerulion topic list` prints local topics instantly, then discovers robots and their topics over the LAN.

```bash theme={null}
cerulion topic list
```

The local `TOPIC` section prints first and instantly, so a slow network never delays it. A `ROBOTS` section then lists each robot found, its visible-topic count, and its locator, followed by `REMOTE TOPICS` — every topic a networked robot is advertising or asking for:

```text theme={null}
REMOTE TOPICS
/go2/utlidar/cloud
```

With nothing discovered, both remote sections are simply absent.

| Flag                      | Use it for                                                                                                                                                         |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--no-network`            | Scripts, CI, and offline work — skips the remote query entirely.                                                                                                   |
| `--connect tcp/HOST:7683` | A robot that discovery cannot see. Repeatable; `--listen` mirrors it.                                                                                              |
| `--scan`                  | Sweeping the local `/24` for a robot that both multicast and mDNS hide. Opt-in only — a horizontal sweep reads as port-scan recon to corporate network monitoring. |

The remote half is best-effort and bounded to a few seconds. A discovery failure is a loud note and still exits 0, since the local list already printed.

<Tip>
  A robot that should be findable needs a listen endpoint. Set `CERULION_NETD_LISTEN=tcp/0.0.0.0:7683` in the robot's service environment and restart its `cerulion-netd`; the shared network plane then binds the port and advertises it over mDNS. Without it, the robot is reachable only where LAN multicast is allowed, which is why an intermittent robot is usually a discovery problem rather than a Cerulion one.
</Tip>

## Pull a robot's topics to your desk

`cerulion connect` demands topics from a robot and re-injects them into your machine's shared memory, so every local tool sees them as ordinary topics.

<Steps>
  <Step title="Pair with the robot once" icon="key">
    ```bash theme={null}
    cerulion pair lab-go2
    ```

    The robot's owner starts code pairing on the robot and reads you a short code; type it at the prompt. Pairing puts this desk on the robot's access list, then pins `name → endpoint` locally so `cerulion connect lab-go2` works with no flags afterwards. Your desk key is created once and never overwritten.

    Exit codes are stable for scripting: `0` paired, `2` the robot refused, `3` unreachable, `4` wrong code.

    <Warning>
      `--code` exists for a driver piping the code in, but prefer the prompt: a code on the command line is visible in process listings for the length of the ceremony, and it authorizes durable enrollment.
    </Warning>
  </Step>

  <Step title="See the catalog" icon="list">
    ```bash theme={null}
    cerulion connect lab-go2
    ```

    With no `--topic` and no `--all`, `connect` prints the robot's catalog and demands nothing.
  </Step>

  <Step title="Demand the topics you want" icon="download">
    ```bash theme={null}
    cerulion connect lab-go2 --topic /go2/utlidar/cloud
    ```

    Then, in another shell, the topic behaves like a local one:

    ```bash theme={null}
    cerulion topic hz /go2/utlidar/cloud
    cerulion topic echo /go2/utlidar/cloud
    ```

    `--all` demands the whole catalog. Demand only what you need: every demanded topic is real traffic over the link.
  </Step>
</Steps>

To watch a robot without demanding topics by hand, connect to it in Cerulion Studio and check the topics you want — see [Visualize a running graph](/cerulion/guides/visualize-in-studio).

## Manage the machines on your account

```bash theme={null}
cerulion login                       # device-code sign-in for this machine
cerulion account devices list        # every machine registered to your account
cerulion account devices revoke <device_id>
```

`login` prints a short code and a verification URL and waits while you authorize it in a browser. Any command that needs an identity triggers it for you. Robot access management itself lives in the web account page, not the CLI — `account devices` is for your own desks.

## Next steps

<CardGroup cols={2}>
  <Card title="Visualize a running graph" icon="chart-line" href="/cerulion/guides/visualize-in-studio" color="#0080FF">
    Watch local or remote topics on the Studio stage.
  </Card>

  <Card title="Bridge a ROS 2 system" icon="robot" href="/cerulion/guides/bridge-ros2" color="#0080FF">
    Attach to an existing DDS graph.
  </Card>
</CardGroup>
