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

# Your first skill

> Write and run Python against your live robot, all from the GRID CLI

A **skill** is plain Python that drives your robot through GRID's APIs. You
develop it against a *live* robot in a generated notebook — no environment
setup, because the CLI provisions the Python environment for you.

## 1. Open a dev session

```text theme={null}
GRID # session start robot
```

Pick your robot, then choose **Create a new skill**. The CLI opens a VS Code
workspace with a generated notebook whose first cell already holds the live
connection:

```python theme={null}
from grid_nexus_client import connect

robot = connect("my-go2")
print(f"Connected: {robot}")
```

## 2. Find out what your robot can do

`connect()` returns a [`RemoteRobot`](/v2.0/python-api/grid-nexus-client/remoterobot).
Its attributes are the robot's own methods, discovered live when you connect —
so the fastest way to see the surface is to ask it:

```python theme={null}
for name in robot.session.methods_info():
    print(f"  {name}")
```

Those methods come from the [Robot interface](/v2.0/python-api/robot-interface/overview),
which is the same whether the robot is physical or simulated. A quadruped gets
[`Quadruped`](/v2.0/python-api/robot-interface/quadruped), an arm gets
[`Arm`](/v2.0/python-api/robot-interface/arm), and every robot gets the shared
[`Robot`](/v2.0/python-api/robot-interface/robot) methods like `getState()` and
`getImage()`.

## 3. Drive it

State, motion, and camera all work directly from notebook cells:

```python theme={null}
robot.getState()
robot.standUp()
robot.moveByVelocity((0.1, 0.0, 0.0), (0.0, 0.0, 0.0))
```

<Warning>
  Motion cells move the robot physically. Make sure it has clearance, and run
  `robot.shutdown()` when you're done — it releases the session cleanly.
</Warning>

Sensors, arms, and end effectors nest as attributes, so you can reach into a
subcomponent the same way:

```python theme={null}
image = robot.getImage("front")
wrist = robot.left_arm.wrist_cam.getImage()
```

## 4. Add perception

Anything you capture can go straight to a hosted Cortex model. This finds a
water bottle in the robot's camera frame:

```python theme={null}
from grid_cortex_client import CortexClient

cortex = CortexClient()  # reads GRID_CORTEX_API_KEY from the environment
image = robot.getImage("front")
detections = cortex.run("owlv2", image_input=image, prompt="water bottle")
print(detections["scores"])
```

From there it's ordinary Python — loop over frames, check a score threshold,
and command the robot when you see what you're looking for:

```python theme={null}
import time

robot.standUp()
while True:
    image = robot.getImage("front")
    detections = cortex.run("owlv2", image_input=image, prompt="water bottle")
    scores = detections.get("scores", [])
    if len(scores) > 0 and max(scores) > 0.3:
        robot.stop()
        break
    robot.moveByVelocity((0.0, 0.0, 0.0), (0.0, 0.0, 0.4))
    time.sleep(0.5)
```

## Where next

* Every method your robot exposes: [Robot interface](/v2.0/python-api/robot-interface/overview)
* The full Cortex model catalog for perception in your skills:
  [AI models](/v2.0/models/overview)
* Calling models from Python: [grid-cortex-client](/v2.0/python-api/grid-cortex-client/overview)
* Every shell command: [CLI reference](/v2.0/cli/reference)


## Related topics

- [Your first skill](/get-started/first-skill.md)
- [Your first session](/get-started/first-session.md)
- [Sensors](/simulation/isaac/sensors.md)
- [CLI reference](/cli/reference.md)
- [ROS2 Communication](/simulation/isaac/comms.md)
