Drive a machine from the CLI
The CLI can call any API method a machine serves, with JSON in and JSON out. That makes it a complete way to operate a machine from a shell, for a person or for an AI agent, without writing SDK code. This page shows the commands in the order you need them. For the concepts behind them, see Use Viam from an AI agent.
Find the machine
viam organizations list
viam locations list --organization=<org-id>
viam machines list --location=<location-id>
viam machines part list --machine=<machine-id>
viam machines part status --part=<part-id>
A machine has one or more parts; the main part is the one running viam-server.
Every command below takes --part=<part-id>.
status shows when the part was last reachable.
Call any API method
viam machines part run --part=<part-id> --method=<method> --data='<json>'
run invokes any gRPC method the machine serves, using the machine’s own reflection, so it works for every component, service, and module.
Name the method one of two ways:
- Full name, for machine-level calls:
--method=viam.robot.v1.RobotService.ResourceNames. - Short name with a component:
--component=my-arm --method=GetJointPositions. The CLI looks up the component’s API, expands the name, and fills in thenamefield of the request.
--data is the request message as JSON, with field names as they appear in the proto (camera_name, not cameraName).
Omit it when the request needs nothing beyond the resource name.
Discover what the machine has
Run these first, before any motion.
viam machines part run --part=<part-id> --method=viam.robot.v1.RobotService.ResourceNames
Every resource on the machine, with its API.
viam machines part run --part=<part-id> --method=viam.robot.v1.RobotService.GetMachineStatus
Every resource’s state (configuring, ready, or unhealthy, with the error), the config revision the machine has applied, and module health.
viam machines part run --part=<part-id> --method=viam.robot.v1.RobotService.ResourceRPCSubtypes
The gRPC service descriptors for every API the machine serves: method names and request fields.
viam machines part run --part=<part-id> --method=viam.robot.v1.RobotService.FrameSystemConfig
The kinematic frame tree: which frames exist, their parents, and their geometry.
Per resource, ask for the detail you need:
viam machines part run --part=<part-id> --component=my-arm --method=GetKinematics
viam machines part run --part=<part-id> --component=my-arm --method=GetGeometries
viam machines part run --part=<part-id> --component=my-cam --method=GetProperties
The motion service prints a readable frame table with current poses:
viam machines part motion print-config --part=<part-id>
viam machines part motion print-status --part=<part-id>
Note
The CLI has no command that prints a machine’s saved configuration (models and attributes).
The SDKs can read it with get_robot_part.
The calls above are the runtime truth and are usually what you want.
Observe
viam machines part run --part=<part-id> --component=my-cam --method=GetImages
viam machines part run --part=<part-id> --component=my-cam --method=GetPointCloud
viam machines part run --part=<part-id> --component=my-sensor --method=GetReadings
viam machines part run --part=<part-id> --component=my-arm --method=GetJointPositions
viam machines part run --part=<part-id> --component=my-arm --method=GetEndPosition
Images and point clouds come back inline, base64-encoded in the JSON.
A vision service returns an image, detections, and object point clouds in one call:
viam machines part run --part=<part-id> --component=my-vision --method=CaptureAllFromCamera \
--data='{"camera_name":"my-cam","return_image":true,"return_detections":true,"return_object_point_clouds":true}'
Detections only:
viam machines part run --part=<part-id> --component=my-vision --method=GetDetectionsFromCamera \
--data='{"camera_name":"my-cam"}'
--stream=1s repeats a call on an interval and prints each result.
It is polling, not a video stream; live video is on the machine’s page in the Viam app.
Act
Prefer planned motion.
The motion service takes a goal pose and returns collision-checked motion against the frame system’s geometry and any obstacles you declare.
An arm’s own MoveToPosition is unplanned and will drive straight through things.
viam machines part motion get-pose --part=<part-id> --component=my-gripper
viam machines part motion set-pose --part=<part-id> --component=my-gripper \
--x=300 --y=250 --z=900 --ox=0 --oy=0 --oz=-1 --theta=0
set-pose moves a component’s frame to a pose in the world frame: millimeters, and an orientation vector with theta in degrees.
The same call through the raw API, with a declared obstacle and a straight-line constraint:
viam machines part run --part=<part-id> --component=builtin --method=Move --data='{
"component_name": "my-gripper",
"destination": {"reference_frame": "world",
"pose": {"x": 300, "y": 250, "z": 900, "o_x": 0, "o_y": 0, "o_z": -1, "theta": 0}},
"world_state": {"obstacles": [{"reference_frame": "world", "geometries": [
{"center": {"x": 450, "y": -50, "z": 780, "o_z": 1},
"box": {"dims_mm": {"x": 60, "y": 60, "z": 60}}, "label": "blue-block"}]}]},
"constraints": {"linear_constraint": [{"line_tolerance_mm": 5, "orientation_tolerance_degs": 5}]}
}'
Typed verbs on components:
viam machines part run --part=<part-id> --component=my-gripper --method=Open
viam machines part run --part=<part-id> --component=my-gripper --method=Grab
viam machines part run --part=<part-id> --component=my-gripper --method=IsHoldingSomething
viam machines part run --part=<part-id> --component=my-arm --method=MoveToJointPositions \
--data='{"positions": {"values": [0, -90, 0, -90, 90, 0]}}'
viam machines part run --part=<part-id> --component=my-base --method=SetVelocity \
--data='{"linear": {"y": 100}, "angular": {"z": 0}}'
viam machines part run --part=<part-id> --component=my-motor --method=SetPower --data='{"power_pct": 0.5}'
Anything a resource offers beyond its typed API goes through DoCommand.
The request wraps your command in a command object:
viam machines part run --part=<part-id> --component=my-service --method=DoCommand \
--data='{"command": {"command": "status"}}'
Stop, and what stops for you
viam machines part run --part=<part-id> --method=viam.robot.v1.RobotService.StopAll
viam machines part run --part=<part-id> --method=viam.robot.v1.RobotService.GetOperations
viam machines part run --part=<part-id> --method=viam.robot.v1.RobotService.CancelOperation --data='{"id": "<op-id>"}'
StopAll stops every operation and every actuator in one call.
Each client connection to the machine carries a heartbeat.
When it lapses because the client exits or crashes, viam-server stops the actuators that client commanded, within about two seconds.
For CLI users that means:
- Every
part runis its own connection, so a command that starts a motion and exits has that motion stopped when the connection ends. Long moves belong in the motion service, whoseMovereturns when the motion finishes. - On some gripper models the same stop releases the drive, dropping what the gripper holds.
A sequence that must hold an object across steps belongs in one process with one connection, which means an SDK script rather than separate CLI commands.
Check
IsHoldingSomethingafter a lift; do not trustGrab’s return value alone.
Motion-service moves are not covered by the heartbeat: a Move in progress continues after the client that started it disappears.
Use StopAll if it must end.
Change the machine
viam machines part add-resource --part=<part-id> --name=my-cam --resource-subtype=camera --model-name=viam:camera:realsense
viam machines part remove-resource --part=<part-id> --name=my-cam
viam machines api-key create --machine-id=<machine-id> --name=agent-key
viam machines create --name=my-robot --location=<location-id>
viam machines part logs --part=<part-id> --count=50
viam machines part logs --part=<part-id> --tail
After a configuration change the machine converges within about ten seconds.
Confirm with GetMachineStatus, which reports the config revision and each resource’s state, rather than by waiting.
Reading errors
| Error | Meaning |
|---|---|
resource rdk:component:arm/my-arm not found | Wrong name or not configured; check ResourceNames. |
Unimplemented | This model does not implement that method. No further detail is given. |
all IK solutions failed constraints. Failures: { obstacle constraint: 62.00% } | The planner could not reach the goal; the percentages say which constraint blocked most candidates. |
arm stalled at waypoint 2/2 (stuck joints: j3: at 110.0 want 118.8) | The arm hit something during execution. |
modular resource config validation error: context deadline exceeded | The module did not answer in time, usually because it is still starting. |
Method names by API
| API | Read | Act |
|---|---|---|
Machine (full names under viam.robot.v1.RobotService) | ResourceNames, GetMachineStatus, ResourceRPCSubtypes, FrameSystemConfig, TransformPose, GetOperations | StopAll, CancelOperation, RestartModule |
| Arm | GetJointPositions, GetEndPosition, GetKinematics, GetGeometries, IsMoving | MoveToPosition, MoveToJointPositions, MoveThroughJointPositions, Stop |
| Gripper | IsHoldingSomething, GetGeometries, GetKinematics, IsMoving | Open, Grab, Stop |
| Camera | GetImages, GetPointCloud, GetProperties, GetGeometries | |
| Sensor | GetReadings | |
| Base | GetProperties, IsMoving | MoveStraight, Spin, SetVelocity, SetPower, Stop |
| Motor | GetPosition, GetProperties, IsPowered, IsMoving | SetPower, GoFor, GoTo, SetRPM, Stop |
| Vision service | GetDetectionsFromCamera, GetClassificationsFromCamera, GetObjectPointClouds, CaptureAllFromCamera, GetProperties | |
| Motion service | GetPose, GetPlan, ListPlanStatuses | Move, StopPlan |
| Any resource | DoCommand |
The full, current list always comes from the machine itself through ResourceRPCSubtypes.
When in doubt, ask the machine.
Was this page helpful?
Glad to hear it! If you have any other feedback please let us know:
We're sorry about that. To help us improve, please tell us what we can do better:
Thank you!