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

# Develop with the Python SDK

> Install the SDK, authenticate, and control your first robot in under 5 minutes

<div
  style={{
background: '#f8fafa',
border: '1px solid #d0e8ed',
color: '#333',
padding: '1rem 1.25rem',
borderRadius: '0.5rem',
fontSize: '0.95rem',
lineHeight: '1.6'
}}
>
  <p style={{ margin: '0 0 0.25rem 0', fontWeight: 'bold' }}>Cyberwave is in Private Beta.</p>
  <p style={{ margin: 0 }}><a href="https://cyberwave.com/request-early-access" target="_blank" style={{ color: '#00b5dd', fontWeight: 'bold' }}>Request early access</a> to get access to the Cyberwave dashboard.</p>
</div>

The Cyberwave Python SDK (`cyberwave`) lets you control robots, manage digital twins, and stream sensor data with a few lines of Python. This guide takes you from an empty terminal to a moving robot in simulation, no hardware required.

<Note>
  Already comfortable with the basics? The [full Python SDK reference](/overview/tools/python-sdk) covers joint control, video streaming, workflows, datasets, ML models, and more.
</Note>

## Prerequisites

* **Python 3.10 or higher** installed on your machine
* A **Cyberwave account** ([signup now](https://cyberwave.com/signup) if you don't have one)
* A **Cyberwave API key** (we'll generate one in Step 2)

## Step 1: Install the SDK

Install `cyberwave` from PyPI:

```bash theme={null}
pip install cyberwave
```

Verify the install:

```bash theme={null}
cyberwave --help
```

## Step 2: Get your API key

<Steps>
  <Step title="Open your profile">
    Go to the [Cyberwave dashboard](https://cyberwave.com/profile) and open the **API Tokens** section of your Profile page.
  </Step>

  <Step title="Create a new key">
    Click **Create Token**, give it a name (e.g. "Quickstart"), and copy the key. You won't be able to see it again, so store it somewhere safe.
  </Step>
</Steps>

## Step 3: Authenticate

The SDK reads your API key from the `CYBERWAVE_API_KEY` environment variable. This is the recommended approach — it keeps secrets out of your code.

```bash theme={null}
export CYBERWAVE_API_KEY="your_api_key_here"
```

Then initialize the client with no arguments:

```python theme={null}
from cyberwave import Cyberwave

cw = Cyberwave()  # picks up CYBERWAVE_API_KEY automatically
```

<Tip>
  Prefer to pass the key explicitly? Use `Cyberwave(api_key="your_api_key_here")`. Avoid this in code you commit or share.
</Tip>

## Step 4: Control your first robot

The snippet below creates a digital twin of an [SO101 robot arm](https://cyberwave.com/catalog), runs it **in simulation**, and moves one of its joints. Nothing here touches physical hardware, so it's safe to run as-is.

```python theme={null}
import math
from cyberwave import Cyberwave

# 1. Connect (reads CYBERWAVE_API_KEY from your environment)
cw = Cyberwave()

# 2. Run against the simulation, not a physical robot
cw.affect("simulation")

# 3. Create (or fetch) a digital twin from the asset catalog
robot = cw.twin("the-robot-studio/so101")

# 4. Move a joint — 45 degrees on the shoulder
robot.joints.set("shoulder_pan", 45, degrees=True)

# 5. Read it back
print("Joints:", robot.joints.list())
robot.joints.print_joint_states()
```

Run it:

```bash theme={null}
python quickstart.py
```

<Check>
  If you see a table of joint states printed to your terminal, it worked. Open the twin's environment in the [dashboard](https://cyberwave.com) to watch the arm move in the 3D viewport.
</Check>

## What just happened

<AccordionGroup>
  <Accordion title="cw = Cyberwave()">
    Creates the SDK client and authenticates using your API key. It establishes connections to both the REST API (for twins, catalog, workflows) and the MQTT API (for real-time control).
  </Accordion>

  <Accordion title="cw.affect(&#x22;simulation&#x22;)">
    Tells the SDK that your commands should drive the **digital twin in simulation** rather than a physical robot. Switch to `cw.affect("live")` later to run the exact same code against real hardware.
  </Accordion>

  <Accordion title="cw.twin(&#x22;the-robot-studio/so101&#x22;)">
    Resolves the `vendor/model` asset from the catalog and returns a twin. If you don't have an environment yet, the SDK auto-creates a "Quickstart Environment" and places the twin there.
  </Accordion>

  <Accordion title="robot.joints.set(&#x22;shoulder_pan&#x22;, 45, degrees=True)">
    Sends a real-time joint command. Positions default to **radians** — pass `degrees=True` to use degrees instead.
  </Accordion>
</AccordionGroup>

## Try a few more things

Once the quickstart runs, swap in these snippets to explore other capabilities:

<Tabs>
  <Tab title="Position the twin">
    ```python theme={null}
    robot.edit_position(x=1.0, y=0.0, z=0.5)
    robot.edit_rotation(yaw=90)
    ```
  </Tab>

  <Tab title="Capture a frame">
    ```python theme={null}
    # Grab the latest camera frame — no streaming setup needed
    path = robot.capture_frame()          # saves a JPEG, returns the path
    frame = robot.capture_frame("numpy")  # numpy BGR array
    ```
  </Tab>

  <Tab title="Search the catalog">
    ```python theme={null}
    for asset in cw.assets.search("unitree"):
        print(asset.registry_id, asset.name)
    ```
  </Tab>

  <Tab title="Drive a different robot">
    ```python theme={null}
    dog = cw.twin("unitree/go2")
    dog.move_forward(distance=1.0)
    ```
  </Tab>
</Tabs>

## Go live on real hardware

The same code that drives the simulation drives a physical robot — you only change the affect mode:

```python theme={null}
cw.affect("live")   # commands now go to the real robot
robot.joints.set("shoulder_pan", 45, degrees=True)
```

To connect real hardware, pair a device running the Cyberwave Edge Core. See [Connecting to hardware](/overview/connecting-hardware/index) for the full walkthrough.

## Troubleshooting

<AccordionGroup>
  <Accordion title="Authentication error / no API key found">
    Make sure `CYBERWAVE_API_KEY` is exported in the **same terminal session** where you run your script. Verify with `echo $CYBERWAVE_API_KEY`. If you opened a new terminal, re-export it or add it to your shell profile / a `.env` file.
  </Accordion>

  <Accordion title="Asset not found">
    Confirm the `vendor/model` identifier exists in the [catalog](https://cyberwave.com/catalog). You can also search programmatically with `cw.assets.search("so101")`.
  </Accordion>

  <Accordion title="Python version errors">
    The SDK requires Python 3.10+. Check with `python --version`. Consider using a virtual environment: `python -m venv .venv && source .venv/bin/activate`.
  </Accordion>
</AccordionGroup>

## Next steps

<CardGroup cols={2}>
  <Card title="Full Python SDK reference" icon="python" href="/overview/tools/python-sdk">
    Joint control, video streaming, workflows, alerts, datasets, and ML models
  </Card>

  <Card title="Develop in simulation" icon="hand-wave" href="/overview/hello-robot">
    Control a robot from the browser with no code
  </Card>

  <Card title="Connect hardware" icon="plug" href="/overview/connecting-hardware/index">
    Pair a real robot with your digital twin
  </Card>

  <Card title="Browse the catalog" icon="book-open" href="https://cyberwave.com/catalog">
    Explore 90+ supported robots, cameras, and sensors
  </Card>
</CardGroup>
