---
title: Unitree G1
description: Install wendy-agent on the Unitree G1's onboard computer to deploy and manage apps with Wendy
---

<img
  src={`${(process.env.NEXT_PUBLIC_BASE_PATH || '').replace(/\/$/, '')}/media/unitree-g1-card.jpg`}
  alt="Unitree G1 humanoid robot"
  className="not-prose aspect-video w-full bg-fd-muted object-cover object-center"
/>

## Overview

The Unitree G1 EDU includes an NVIDIA Jetson development computer known as PC2.
Install Wendy Agent on PC2 to deploy apps, stream logs, inspect hardware, and
connect to the G1's DDS and `unitree_sdk2` interfaces.

The Wendy CLI runs on your development machine. Wendy Agent runs on PC2.

<Callout type="info">
  This guide supports G1 PC2 images based on Ubuntu 20.04 or Ubuntu 22.04 on
  arm64.
</Callout>

## What You Need

- A Unitree G1 EDU with the onboard development computer
- The [Wendy CLI](../../#1-install-the-wendy-cli) on your
  development machine
- An Ethernet cable and, if needed, a USB-to-Ethernet adapter
- Internet access from PC2
- Administrator access on your development machine and `sudo` access on PC2

PC2 uses this factory network configuration:

```text
Address:  192.168.123.164
Username: unitree
Password: 123
```

Change the factory password before connecting PC2 to Wi-Fi or another shared
network.

## Installation Steps

<Steps>
  <Step>
    ### Connect Your Development Machine

    Power on the G1 and wait for PC2 to boot. Connect your development machine
    to the G1 Ethernet port that reaches PC2.

    <Tabs items={['macOS', 'Linux']} groupId="g1-developer-os" persist>
      <Tab value="macOS">
        Find the Ethernet network service:

        ```bash
        networksetup -listallhardwareports
        networksetup -listnetworkserviceorder
        ```

        Assign an address on the G1 network. Replace
        `<robot-link-service>` with the network service from the previous
        command:

        ```bash
        sudo networksetup -setmanual "<robot-link-service>" \
          192.168.123.99 255.255.255.0 ""
        ```
      </Tab>

      <Tab value="Linux">
        Find the Ethernet interface:

        ```bash
        ip -br link
        ```

        Assign an address on the G1 network. Replace
        `<robot-link-interface>` with the interface from the previous command:

        ```bash
        sudo ip addr replace 192.168.123.99/24 dev <robot-link-interface>
        sudo ip link set <robot-link-interface> up
        ```
      </Tab>
    </Tabs>

    Verify the connection:

    ```bash
    ping 192.168.123.164
    ```
  </Step>

  <Step>
    ### Connect to PC2

    Connect to the G1's development computer over SSH:

    ```bash
    ssh unitree@192.168.123.164
    ```

    Sign in with the factory password, then change it:

    ```bash
    passwd
    ```

    Commands in the next two steps run on PC2.
  </Step>

  <Step>
    ### Check Internet Access

    Check whether PC2 can reach the Wendy Agent installer:

    ```bash
    wget --spider https://install.wendy.dev/agent.sh
    ```

    Continue when the command reports `200 OK` and `Remote file exists`. If it
    fails, connect PC2 to Wi-Fi using Unitree's networking instructions. On
    macOS, you can also [temporarily share your development machine's internet
    connection](#temporary-macos-internet-sharing).
  </Step>

  <Step>
    ### Install Wendy Agent

    Download and run the installer on PC2:

    ```bash
    wget -O /tmp/wendy-agent.sh https://install.wendy.dev/agent.sh
    less /tmp/wendy-agent.sh
    bash /tmp/wendy-agent.sh
    ```

    <Callout type="warning">
      Stop if APT says it will remove Docker or replace Docker's
      `containerd.io` package. Resolve the package conflict before continuing.
    </Callout>

    Verify the installation:

    ```bash
    sudo systemctl is-active wendy-agent
    ```

    The command should report `active`.
  </Step>

  <Step>
    ### Discover the G1

    Return to your development machine and run:

    ```bash
    wendy discover
    ```

    PC2 may appear under its Ubuntu hostname or as **Unitree G1 Nx**. Use the
    address shown by `wendy discover` when deploying an app:

    ```bash
    cd <your-wendy-project>
    wendy run --device <address-from-wendy-discover>
    ```

    PC2 is now ready for Wendy app development. You can use the app, device,
    debugging, and robotics guides throughout these docs. WendyOS installation
    guides do not apply because PC2 continues to run Unitree's Ubuntu image.
  </Step>
</Steps>

## Wendy Cloud Enrollment

Cloud enrollment is optional. On your development machine, run `wendy install`
and select **Linux Desktop** to generate an enrollment command for PC2. The
enrollment token expires after about an hour.

Run the generated command on PC2. The G1 will then appear in Wendy Cloud when
it is online.

## Drive the G1 from your browser

The `g1-rc` template gives you a live camera view, a touch joystick, posture
and arm controls, and a latching software E-stop.

Before you start:

- Put the G1 on its gantry and clear the area around it.
- Keep the Unitree remote with the operator. The physical E-stop is the primary
  stop.
- Make sure no other app is controlling the robot. Check the running apps with:

  ```bash
  wendy device apps list --device <address-from-wendy-discover>
  ```

  Stop any other motion app before continuing:

  ```bash
  wendy device apps stop <app-name> \
    --device <address-from-wendy-discover>
  ```

Create and deploy the remote control:

```bash
wendy init --app-id my-g1-rc --template g1-rc --language python
cd my-g1-rc
wendy run --device <address-from-wendy-discover>
```

The first build takes a few minutes. When it is ready, Wendy opens the remote
control in your browser. If it does not open, use the G1 hostname or Wi-Fi
address on port 3500, for example:

```text
http://unitree-g1-nx.local:3500
```

Check the four status badges before touching the controls:

- **motion: ok** means the app can reach Unitree's motion service.
- **cam: live** means the page is receiving the front camera at `/dev/video4`.
- **battery** shows the percentage reported by the G1 battery controller.
- **fsm** shows the G1 locomotion state. The page does not send velocity
  commands until it has a recent `801 (walk-ready)` readback.

Use the FSM badge to choose the next step:

| FSM | Meaning | What to do |
|---|---|---|
| `1` | DAMP; joints are compliant | Press **stand**, then wait for FSM `4`. |
| `4` | LOCK STAND; standing but not walking | Press **ready-to-walk**. |
| `801` | RUNNING; ready to walk | You can use the joystick or WASD controls. |
| another value or `—` | Not ready or no fresh readback | Do not drive. Check the motion app and make sure no other app owns motion. |

For the first motion test, set **Speed** to 20% and press forward briefly. Let
go to stop. Use the red **STOP** button if the robot does not stop as expected,
and use the Unitree remote's physical E-stop if needed.

<Callout type="warning">
  **stand** may move the G1 through DAMP before LOCK STAND. From an unexpected
  FSM, the page asks you to confirm that the robot is supported. Do not confirm
  unless the G1 is secured on its gantry. **damp** makes the joints compliant
  and can make an unsupported robot fall.
</Callout>

If the camera badge stays red, list the G1 camera devices:

```bash
wendy device camera list --device <address-from-wendy-discover>
```

The tested G1 uses `/dev/video4` for the 640×480 color stream. If your G1 uses
a different color node, create the project again with that camera number:

```bash
wendy init --app-id my-g1-rc --template g1-rc --language python \
  --var CAMERA_SOURCE=<number>
```

## Work with the G1 from an app

Containers that communicate with Unitree DDS need host networking. A minimal
service declaration looks like this:

```json
{
  "$schema": "https://wendy.dev/schemas/wendy.json",
  "appId": "com.example.g1-app",
  "version": "0.1.0",
  "platform": "linux",
  "services": {
    "app": {
      "context": ".",
      "entitlements": [
        { "type": "network", "mode": "host" }
      ]
    }
  }
}
```

Host networking lets the container bind DDS to PC2's internal Ethernet
interface. Identify it with `ip -br address` instead of assuming a fixed name.
Host networking also removes container network isolation and grants access to
the robot's internal network. Unitree DDS traffic on that network is generally
unauthenticated and unencrypted, so grant this entitlement only to trusted apps.

The G1 uses the `unitree_hg` message package for low-level communication. The
SDK topic names are `rt/lowstate` and `rt/lowcmd`. `unitree_go` is used by the
Go2 and B2; using that package on a G1 can connect while receiving no useful
messages.

If you're using ROS 2, see the [Robotics integration](../../integrations/ros2/)
guide. Wendy can introspect the live ROS 2 graph without a separate SSH
session.

<Callout type="warning">
  Installing the agent does not move the robot, but a deployed app can. A
  software Stop button is not a safety-rated E-stop. For every first motion
  test, support the G1 on its gantry, keep the Unitree physical remote and
  E-stop with the operator, require an explicit actuation gate, use short
  command leases and live FSM readback, and ensure only one app owns motion.
</Callout>

## Troubleshooting

### Temporary macOS Internet Sharing

Use these steps if PC2 cannot connect to Wi-Fi. They share your Mac's internet
connection with PC2 over the Ethernet cable.

<Accordions>
  <Accordion title="Share your Mac's internet connection">
    On your Mac, open a terminal and run:

    ```bash
    UPLINK=$(route -n get default | awk '/interface:/{print $2}')
    ORIGINAL_FORWARDING=$(sysctl -n net.inet.ip.forwarding)
    PF_TOKEN=$(sudo pfctl -E 2>&1 | awk '/Token :/ {print $3}')

    printf 'nat on %s from 192.168.123.0/24 to any -> (%s)\n' \
      "$UPLINK" "$UPLINK" | \
      sudo pfctl -a com.apple/wendy-g1 -f -
    sudo sysctl -w net.inet.ip.forwarding=1
    ```

    Keep this terminal open. You will use the saved values to restore the Mac
    after installing Wendy Agent.

    On PC2, run:

    ```bash
    PC2_ETHERNET=$(ip -br address | \
      awk '$3 ~ /^192\.168\.123\.164\// {print $1; exit}')
    test -n "$PC2_ETHERNET"
    sudo ip route replace default via 192.168.123.99 \
      dev "$PC2_ETHERNET" metric 100
    sudo resolvectl dns "$PC2_ETHERNET" 1.1.1.1
    wget --spider https://install.wendy.dev/agent.sh
    ```

    After installing Wendy Agent, remove the temporary settings from PC2:

    ```bash
    sudo ip route del default via 192.168.123.99 dev "$PC2_ETHERNET"
    sudo resolvectl revert "$PC2_ETHERNET"
    ```

    Return to the same terminal on your Mac and run:

    ```bash
    sudo pfctl -a com.apple/wendy-g1 -F all
    if [ -n "${PF_TOKEN:-}" ]; then sudo pfctl -X "$PF_TOKEN"; fi
    sudo sysctl -w net.inet.ip.forwarding="$ORIGINAL_FORWARDING"
    ```
  </Accordion>
</Accordions>

- **`wendy discover` shows nothing on macOS:** Check System Settings → Privacy
  & Security → Local Network and make sure the terminal has access. Verify the
  advertisement with `dns-sd -B _wendyos._udp`.
- **Agent unreachable:** Read the address and port from `wendy discover`, then
  test that exact pair with `nc -zv <address> <advertised-port>`. Do not assume
  every agent uses `50051` or `50052`.
- **Installer reports `/dev/tty: No such device or address`:** Use the
  downloaded script with `bash /tmp/wendy-agent.sh -y`.
- **The service is enabled but inactive after an upgrade:** Run
  `sudo systemctl start wendy-agent`, inspect the journal, and record the agent
  package version with `dpkg-query -W wendy-agent` when contacting support.
- **`wendy run` reports `wendy.json not found`:** Change into a Wendy project
  or create one with `wendy init` before deploying.
- **Installer download fails:** Re-run the `wget --spider` internet check in
  Step 3. Inspect both PC2's default route and the developer machine's default
  route before changing either system.
- **SSH warns that the remote host identification changed:** This is expected
  after reflashing PC2, but it can also indicate the wrong device or a
  man-in-the-middle attack. Verify the new ED25519 fingerprint from a local PC2
  terminal with `ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub`. Only after
  it matches, remove the single stale developer-machine entry with
  `ssh-keygen -R 192.168.123.164` and reconnect. Do not bypass host-key checking.
- **PC2 does not answer ping:** Recheck the physical G1 port, Ethernet link,
  interface name, `192.168.123.99/24` address, and absence of a gateway on the
  developer machine's robot-link service.

## Remove the agent

To remove Wendy from PC2 without removing the shared container runtime:

```bash
sudo apt-get purge -y wendy-agent
sudo rm -f /etc/apt/sources.list.d/wendy.list
sudo rm -f /usr/share/keyrings/wendy-archive-keyring.gpg
sudo apt-get update
```

This intentionally leaves `/var/lib/wendy-agent` and deployed app data in
place. Review and remove those directories separately only when their data is
no longer needed. Do not remove `containerd` automatically because Docker,
Unitree software, or other workloads may use it.

## Reflash PC2

Reflashing PC2 is a separate recovery procedure and is not required to install
Wendy Agent. See [Reflash Unitree G1 PC2](../../installation/unitree-g1-reflash/)
to replace the PC2 operating system and module firmware.

## Next steps

Start with a non-motion app instead:

- [Hello World in Python](../../guides/tutorials/python/hello-world/)
- [ROS 2 on Wendy devices](../../integrations/ros2/)
- [App entitlements](../../device/entitlements/)
