# Python

> Author robotics controls, record observations, and replay evidence with the tinyrobot Python SDK.

Source: http://tinyro.bot/docs/reference/py

The Python SDK supplies author controls, bounded execution, recording, and replay.
External libraries still own inference, planning, and robot dynamics. This
reference tracks the repository's **main branch**, not a particular PyPI release.

## Install

```sh
uv add tinyrobot
```

Native Rerun recording requires the optional recording extra:

```sh
uv add 'tinyrobot[recording]'
```

## Author an app

```python
from tinyrobot import App, Number

app = App("example", title="Example", source="simulation")


@app.command(inputs={"steps": Number(default=10, min=1, max=100, integer=True)})
def run(recording, steps):
    for step in range(steps):
        recording.checkpoint()
```

An [App](#tinyrobotapp) declares controls and streams; a
[Run](#tinyrobotrun) is supplied to each callback by the runner. Declaring an
app does not start a web server or authorize hosted execution.

## API reference

- **Authoring:** [App](#tinyrobotapp), [Stream](#tinyrobotstream),
  [Limits](#tinyrobotlimits), and [Run](#tinyrobotrun).
- **Controls:** [Number](#tinyrobotnumber), [Choice](#tinyrobotchoice),
  [MultiChoice](#tinyrobotmultichoice), and [Toggle](#tinyrobottoggle).
- **Recorded data:** [Capture](#tinyrobotcapture),
  [replay](#tinyrobotreplay), [replay_evidence](#tinyrobotreplay_evidence),
  and [evidence_request](#tinyrobotevidence_request). Start with the
  [recorded-data guide](/docs/recorded-data) for reproduction instructions.
- **Visualization helpers:** [depth_points](#tinyrobotgeometrydepth_points)
  and [meters](#tinyrobotgeometrymeters).
- **LeRobot data:** [import_lerobot](#tinyrobotlerobotimport_lerobot) reads a
  bounded numeric subset, not a full dataset or robot-control integration. This
  requires `tinyrobot[lerobot,recording]`.

Signatures and descriptions below are extracted from SDK source
with [Griffe](https://mkdocstrings.github.io/griffe/). They are rendered by the
same TypeScript pipeline as these guides and are available through **View as
Markdown**, site search, and [/llms.txt](/llms.txt).

## tinyrobot.App

```python
from tinyrobot import App
```

```python
tinyrobot.App(id: str, *, title: str, source: str, description: str = '', limits: Limits | None = None, blueprint: Any = None)
```

A trusted Python author with typed commands, not a script-rerun web server.

Callbacks receive ``Run`` then keyword arguments matching their controls. Each
invocation must initialize its own simulator/model state. External libraries
own inference, IK, planning and dynamics. No callback or import path is sent
to clients; hosted execution needs a separately reviewed, pinned recipe.

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/app.py#L56)

### tinyrobot.App.command

```python
tinyrobot.App.command(*, inputs: Mapping[str, Control] | None = None, id: str | None = None, label: str = '', description: str = '') -> Callable[[Callable[..., None]], Callable[..., None]]
```

Register a button and its bounded controls. Missing values use defaults.

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/app.py#L128)

### tinyrobot.App.descriptor

```python
tinyrobot.App.descriptor() -> dict[str, Any]
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/app.py#L195)

### tinyrobot.App.descriptor_bytes

```python
tinyrobot.App.descriptor_bytes() -> bytes
```

Freeze declarations and return exact bytes used for descriptorSha256.

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/app.py#L174)

### tinyrobot.App.digest

```python
tinyrobot.App.digest: str
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/app.py#L201)

### tinyrobot.App.invoke

```python
tinyrobot.App.invoke(request: object, *, output: str | Path, cancel: threading.Event | None = None) -> dict[str, Any]
```

Single-flight execution; reject concurrent calls, never queue/retry.

Cancellation is cooperative inside Python. Hosts must terminate hung
processes; hosted jobs additionally require provider-confirmed cleanup.
Use requestId to ignore stale UI responses after reset/cancel/navigation.

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/app.py#L238)

### tinyrobot.App.request

```python
tinyrobot.App.request(command: str, *, request_id: str | None = None, **values: Value) -> dict[str, Any]
```

Make an invocation with validated defaults (no execution).

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/app.py#L204)

### tinyrobot.App.run

```python
tinyrobot.App.run(command: str, *, output: str | Path, **values: Value) -> dict[str, Any]
```

Run locally into a NEW directory; never upload or publish anything.

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/app.py#L225)

### tinyrobot.App.stream

```python
tinyrobot.App.stream(path: str, *, kind: Literal['scalar', 'visual'] = 'visual', role: Role = 'diagnostic', source: str | None = None, unit: str = '', timeline: str = 'step', time_kind: Literal['sequence', 'duration'] = 'sequence') -> Stream
```

Declare one output; chart-only apps need no robot, camera or geometry.

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/app.py#L97)

## tinyrobot.app.Role

```python
from tinyrobot.app import Role
```

```python
type tinyrobot.app.Role = Literal['observed', 'simulated', 'predicted', 'diagnostic', 'action']
```



[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/app.py#L16)

## tinyrobot.Capture

```python
from tinyrobot import Capture
```

```python
tinyrobot.Capture(output: str | Path, *, title: str, source: str, target: str = 'unknown', question: str = '', limits: Limits | None = None, kind: str = 'capture', source_format: str = 'native-rerun', source_version: str | None = None, adapter: str | None = None, source_files: list[dict[str, Any]] | None = None, notes: str = '', config: dict[str, Any] | None = None)
```

Local capture only. Closing stops recording, NEVER the external hardware.

Use as a context manager. Declare clocks/streams before the first log. Native
archetypes own data; metadata describes clocks/semantics, not a scene graph.
Bounds are cooperative: one native log can allocate before a checkpoint.
No App, executable author, inferred action interval, or execution attestation.

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/capture.py#L22)

### tinyrobot.Capture.__enter__

```python
tinyrobot.Capture.__enter__() -> Capture
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/capture.py#L220)

### tinyrobot.Capture.__exit__

```python
tinyrobot.Capture.__exit__(exc_type: type[BaseException] | None, exc: BaseException | None, tb: TracebackType | None) -> None
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/capture.py#L398)

### tinyrobot.Capture.checkpoint

```python
tinyrobot.Capture.checkpoint() -> None
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/capture.py#L267)

### tinyrobot.Capture.clock

```python
tinyrobot.Capture.clock(id: str, *, kind: str = 'duration', unit: str = 's', origin: str = 'unknown', source: str | None = None, derivation: str | None = None, synchronization: str = 'unknown', uncertainty_seconds: float | None = None) -> str
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/capture.py#L119)

### tinyrobot.Capture.diagnostic

```python
tinyrobot.Capture.diagnostic(code: str, message: str, *, severity: str = 'warning') -> None
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/capture.py#L198)

### tinyrobot.Capture.finish

```python
tinyrobot.Capture.finish() -> dict[str, Any]
```

Commit evidence.json last; failed captures are removed, not replayable.

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/capture.py#L323)

### tinyrobot.Capture.log

```python
tinyrobot.Capture.log(stream: str, *archetypes: Any, times: dict[str, float]) -> None
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/capture.py#L279)

### tinyrobot.Capture.metric

```python
tinyrobot.Capture.metric(id: str, value: float | None, *, unit: str | None, method: str, source: str, reason: str | None = None) -> None
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/capture.py#L175)

### tinyrobot.Capture.scalar

```python
tinyrobot.Capture.scalar(stream: str, value: float | None, *, times: dict[str, float]) -> None
```

None is a native Clear (never zero or a forward-filled measurement).

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/capture.py#L306)

### tinyrobot.Capture.stream

```python
tinyrobot.Capture.stream(path: str, *, role: str = 'unknown', meaning: str = 'unknown', unit: str | None = None, clock: str | None = None, source: str | None = None) -> str
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/capture.py#L151)

## tinyrobot.Choice

```python
from tinyrobot import Choice
```

```python
tinyrobot.Choice(*, options: tuple[str, ...], default: str, label: str = '', description: str = '')
```

One value from a fixed allowlist, never a path, model URL or code selector.

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/controls.py#L25)

### tinyrobot.Choice.default

```python
tinyrobot.Choice.default: str
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/controls.py#L30)

### tinyrobot.Choice.description

```python
tinyrobot.Choice.description: str = ''
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/controls.py#L32)

### tinyrobot.Choice.label

```python
tinyrobot.Choice.label: str = ''
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/controls.py#L31)

### tinyrobot.Choice.options

```python
tinyrobot.Choice.options: tuple[str, ...]
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/controls.py#L29)

## tinyrobot.controls.Control

```python
from tinyrobot.controls import Control
```

```python
type tinyrobot.controls.Control = Number | Choice | MultiChoice | Toggle
```



[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/controls.py#L54)

## tinyrobot.controls.Value

```python
from tinyrobot.controls import Value
```

```python
type tinyrobot.controls.Value = float | int | str | bool | list[str]
```



[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/controls.py#L55)

## tinyrobot.evidence_request

```python
from tinyrobot import evidence_request
```

```python
tinyrobot.evidence_request(directory: str | Path, namespace_id: str) -> dict[str, Any]
```

Build a bounded HTTP import body locally; never upload or claim server trust.

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/evidence.py#L193)

## tinyrobot.geometry.depth_points

```python
from tinyrobot.geometry import depth_points
```

```python
tinyrobot.geometry.depth_points(depth: npt.ArrayLike, image_from_camera: npt.ArrayLike, *, units_per_meter: float = 1000, stride: int = 1) -> tuple[npt.NDArray[np.float64], npt.NDArray[np.int64]]
```

Project calibrated depth to camera-frame meters and matching (row, col).

Uses integer pixel centers and a 3x3 pinhole intrinsic matrix. Invalid/zero
depth is omitted. Coordinates are right/down/forward (RDF); log native Rerun
ViewCoordinates/Pinhole/Transform3D when relating this to a world frame. This
does not infer calibration, undistort a lens or estimate a camera pose.
Native rr.DepthImage(meter=units_per_meter) + rr.Pinhole is preferable when
callers only need depth visualization, rather than explicit point arrays.

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/geometry.py#L12)

## tinyrobot.geometry.meters

```python
from tinyrobot.geometry import meters
```

```python
tinyrobot.geometry.meters(value: Any, *, unit: Literal['m', 'cm', 'mm']) -> Any
```

Convert scalar/array visualization positions once at the boundary.

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/geometry.py#L56)

## tinyrobot.lerobot.import_lerobot

```python
from tinyrobot.lerobot import import_lerobot
```

```python
tinyrobot.lerobot.import_lerobot(directory: str | Path, *, episode: int, output: str | Path, timestamp_policy: str = 'source', title: str = 'LeRobot numeric episode') -> dict[str, Any]
```

Import one explicit offline episode, never a new hardware trial.

``source`` preserves the source-reported display timeline; ``nominal_fps``
uses a separate derived display clock. Both retain source timestamps/indices
and nulls in native RRD. Neither proves timing, execution or policy quality.

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/lerobot.py#L169)

## tinyrobot.Limits

```python
from tinyrobot import Limits
```

```python
tinyrobot.Limits(*, seconds: float = 60, max_samples: int = 10000, max_bytes: int = 16 * 1024 * 1024)
```

Cooperative bounds; runner process/provider deadlines are the hard backstop.

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/app.py#L37)

### tinyrobot.Limits.descriptor

```python
tinyrobot.Limits.descriptor() -> dict[str, Any]
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/app.py#L45)

### tinyrobot.Limits.max_bytes

```python
tinyrobot.Limits.max_bytes: int = 16 * 1024 * 1024
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/app.py#L43)

### tinyrobot.Limits.max_samples

```python
tinyrobot.Limits.max_samples: int = 10000
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/app.py#L42)

### tinyrobot.Limits.seconds

```python
tinyrobot.Limits.seconds: float = 60
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/app.py#L41)

## tinyrobot.MultiChoice

```python
from tinyrobot import MultiChoice
```

```python
tinyrobot.MultiChoice(*, options: tuple[str, ...], default: tuple[str, ...], min: int = 1, max: int = 64, label: str = '', description: str = '')
```

A bounded subset of a fixed allowlist; selection order is meaningful.

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/controls.py#L35)

### tinyrobot.MultiChoice.default

```python
tinyrobot.MultiChoice.default: tuple[str, ...]
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/controls.py#L40)

### tinyrobot.MultiChoice.description

```python
tinyrobot.MultiChoice.description: str = ''
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/controls.py#L44)

### tinyrobot.MultiChoice.label

```python
tinyrobot.MultiChoice.label: str = ''
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/controls.py#L43)

### tinyrobot.MultiChoice.max

```python
tinyrobot.MultiChoice.max: int = 64
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/controls.py#L42)

### tinyrobot.MultiChoice.min

```python
tinyrobot.MultiChoice.min: int = 1
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/controls.py#L41)

### tinyrobot.MultiChoice.options

```python
tinyrobot.MultiChoice.options: tuple[str, ...]
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/controls.py#L39)

## tinyrobot.Number

```python
from tinyrobot import Number
```

```python
tinyrobot.Number(*, default: float, min: float, max: float, step: float = 1, integer: bool = False, unit: str = '', label: str = '', description: str = '')
```

A finite bounded slider/number input; integer=True preserves Python ints.

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/controls.py#L11)

### tinyrobot.Number.default

```python
tinyrobot.Number.default: float
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/controls.py#L15)

### tinyrobot.Number.description

```python
tinyrobot.Number.description: str = ''
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/controls.py#L22)

### tinyrobot.Number.integer

```python
tinyrobot.Number.integer: bool = False
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/controls.py#L19)

### tinyrobot.Number.label

```python
tinyrobot.Number.label: str = ''
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/controls.py#L21)

### tinyrobot.Number.max

```python
tinyrobot.Number.max: float
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/controls.py#L17)

### tinyrobot.Number.min

```python
tinyrobot.Number.min: float
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/controls.py#L16)

### tinyrobot.Number.step

```python
tinyrobot.Number.step: float = 1
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/controls.py#L18)

### tinyrobot.Number.unit

```python
tinyrobot.Number.unit: str = ''
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/controls.py#L20)

## tinyrobot.replay

```python
from tinyrobot import replay
```

```python
tinyrobot.replay(directory: str | Path) -> dict[str, Any]
```

Verify an immutable local bundle without importing the author or Rerun.

Return data only. No callbacks, compute, publication or network access. The
returned recording filename is relative to the already trusted directory.

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/recording.py#L318)

## tinyrobot.replay_evidence

```python
from tinyrobot import replay_evidence
```

```python
tinyrobot.replay_evidence(directory: str | Path) -> dict[str, Any]
```

Verify a headless bundle, without loading Rerun, an author or a reader.

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/evidence.py#L188)

## tinyrobot.Run

```python
from tinyrobot import Run
```

```python
tinyrobot.Run(app: App, request: dict[str, Any], output: Path, cancel: threading.Event)
```

One independent command/recording, owned by its callback thread.

``with run.at(step):`` synchronizes outputs without repeating clocks. Stream
declarations supply roles/units/source. Out-of-order samples are valid. Every
native log resets clocks so independent sensors/predictions never inherit time.
``checkpoint()`` should also be called inside long inference/simulation loops.

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/recording.py#L46)

### tinyrobot.Run.at

```python
tinyrobot.Run.at(step: float | None = None, **times: float) -> Iterator[None]
```

Use step by default, or named sensor clocks: ``at(elapsed=0.1)``.

Nested contexts replace rather than inherit clocks. Sequence streams
require integers; duration streams use seconds. No wall-clock inference.

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/recording.py#L99)

### tinyrobot.Run.checkpoint

```python
tinyrobot.Run.checkpoint() -> None
```

Check cancellation, timeout, sample and flushed RRD byte budgets.

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/recording.py#L85)

### tinyrobot.Run.clear

```python
tinyrobot.Run.clear(stream: Stream, *, at: float | None = None) -> None
```

Explicitly clear stale geometry at a sample time (recursive native Clear).

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/recording.py#L229)

### tinyrobot.Run.log

```python
tinyrobot.Run.log(stream: Stream, *archetypes: Any, at: float | None = None, static: bool = False, interval: tuple[float, float] | None = None) -> None
```

Log native Rerun geometry/images/transforms/plots. No scene graph DSL.

Actions require the application interval, in the stream's time units.
Predicted streams require a ``prediction`` context and target time;
geometry is never silently relabeled as observed or simulated.

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/recording.py#L147)

### tinyrobot.Run.prediction

```python
tinyrobot.Run.prediction(*, origin: float, candidate: str) -> Iterator[None]
```

Retain forecast origin and horizon separately from target/sample time.

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/recording.py#L114)

### tinyrobot.Run.scalar

```python
tinyrobot.Run.scalar(stream: Stream, value: float, *, at: float | None = None, interval: tuple[float, float] | None = None) -> None
```

Convenient finite scalar; units, role and source live on the stream.

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/recording.py#L212)

## tinyrobot.Stream

```python
from tinyrobot import Stream
```

```python
tinyrobot.Stream(path: str, kind: Literal['scalar', 'visual'], role: Role, source: str, unit: str, timeline: str, time_kind: Literal['sequence', 'duration'])
```

Semantics declared once. Native Rerun archetypes still own visual data.

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/app.py#L19)

### tinyrobot.Stream.descriptor

```python
tinyrobot.Stream.descriptor() -> dict[str, Any]
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/app.py#L31)

### tinyrobot.Stream.kind

```python
tinyrobot.Stream.kind: Literal['scalar', 'visual']
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/app.py#L24)

### tinyrobot.Stream.path

```python
tinyrobot.Stream.path: str
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/app.py#L23)

### tinyrobot.Stream.role

```python
tinyrobot.Stream.role: Role
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/app.py#L25)

### tinyrobot.Stream.source

```python
tinyrobot.Stream.source: str
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/app.py#L26)

### tinyrobot.Stream.time_kind

```python
tinyrobot.Stream.time_kind: Literal['sequence', 'duration']
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/app.py#L29)

### tinyrobot.Stream.timeline

```python
tinyrobot.Stream.timeline: str
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/app.py#L28)

### tinyrobot.Stream.unit

```python
tinyrobot.Stream.unit: str
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/app.py#L27)

## tinyrobot.Toggle

```python
from tinyrobot import Toggle
```

```python
tinyrobot.Toggle(*, default: bool = False, label: str = '', description: str = '')
```



[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/controls.py#L47)

### tinyrobot.Toggle.default

```python
tinyrobot.Toggle.default: bool = False
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/controls.py#L49)

### tinyrobot.Toggle.description

```python
tinyrobot.Toggle.description: str = ''
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/controls.py#L51)

### tinyrobot.Toggle.label

```python
tinyrobot.Toggle.label: str = ''
```

[View source](https://github.com/yujonglee/tinyrobot/blob/main/sdk/py/src/tinyrobot/controls.py#L50)

