# Device health CLI commands

> Canonical HTML: https://screenrig.ai/docs/cli/device

Reboot, restart and update a device, schedule its display and reboots, set brightness, the output mode and TV input switching, lock the kiosk and read uptime, health and storage. Every command here runs as described in the [CLI reference](https://screenrig.ai/docs/cli.md): global flags, JSON output, exit codes, revisions and retries.

## Device health and power

Every paired Player reports device health on session start, every fifteen minutes, and at once when its display connection or power changes. It also declares the host capabilities it supports: `reboot`, `volume`, `clear_cache`, `restart_app` and `update` where each works on that device, and the display power methods it can use (`display_power.serial`, the display's RS-232 control port; `display_power.cec`, `display_power.ddc`, `display_power.backlight`, or `display_power.scrim`, an on-screen blackout), plus `display_power.idle`, `brightness.auto` and `kiosk_lock` for the settings below. `screen show` returns both.

`screen show` returns health as `data.health` with the server's `reported_at`; `stale` turns true after 35 minutes without a report, and the last report stays visible. With `--human` it prints a `Health` block: report time, device and Player uptime, memory in use, CPU load and cores, temperature, display connection and power, network kind and Wi-Fi signal, battery level, charging and power source on a device with a battery, and crashes and renderer restarts in the last 24 hours. `screen list --human` adds a `HEALTH` column when any listed screen needs attention: `display disconnected`, `hot` (80 °C or more), `on battery`, `crashing` (3 or more crashes in 24 hours), or `stale`; a screen that has reported and has no problem reads `ok`.

A Player also reports the storage it may use. `screen show` returns it as `storage`, with `storage_shortfall` while the playlist does not fit, and [`screen storage-forecast`](https://screenrig.ai/docs/cli/device.md#cmd-screen-storage-forecast) checks a playlist against it before you assign the playlist.

Transitions arrive as `screen.health_changed` events, printed by `events list` and `events follow` with a compact `changes=` value such as `display_disconnected,temperature_high temperature_c=82`. `screen reboot` appends `screen.reboot_requested` (`reboot_id`, `expires_at`, `state`, `source`), and `screen clear-cache`, `screen restart-app` and `screen update-software` append `screen.command_requested` (`command_id`, `command`, `expires_at`, `state`); the Player's report appends `screen.command_result` (`command_id`, `command`, `state` `done` or `failed`, and its `cause` and `detail`). A display override or schedule appends `screen.display_changed`. A volume change appends `screen.volume_requested` (`volume_id`, `level`, `muted`). A reboot schedule appends `screen.reboot_schedule_changed` when it is set or cleared and `screen.reboot_skipped` when a window passes without a reboot, with a `reason` of `reboot_pending` (a reboot a person asked for still waits), `reboot_unsupported` (the Player does not declare `reboot`), `window_missed` (the window had ended, or a daylight-saving gap swallowed it) or `not_permitted` (the project does not permit screens). `screen.reboot_requested` carries `source` `schedule` when the schedule issued it and `manual` otherwise. Like every `screen.*` event, they are free on the listen stream and as [webhook](https://screenrig.ai/docs/cli/notifications.md#webhooks) deliveries. A [notification](https://screenrig.ai/docs/cli/notifications.md#notifications) emails you, or POSTs a signed webhook, when a display disconnects, a device runs hot or on its battery, or a Player keeps crashing.

`screen uptime`, `screen presence` and `screen health-history` read what one screen did over time: daily availability, online and offline transitions, and the health it reported. `project uptime` and `project health-trend` read the fleet. Offline is recorded after a screen has been unreachable for 60 seconds, and history is kept for the plan's event retention.

| Problem code | Exit | Meaning |
| --- | --- | --- |
| `reboot_unsupported` | `5` | The screen's Player does not declare `reboot`. Nothing was sent or stored; `screen reload` refreshes content without a device reboot. |
| `command_unsupported` | `5` | The screen's Player does not declare `clear_cache`, `restart_app` or `update`, the capability the command needs. Nothing was sent; `screen show` lists the host capabilities and `screen reload` refreshes content. |
| `volume_unsupported` | `5` | The screen's Player does not declare `volume`. Nothing was sent or stored; update the Player, or set the volume in its settings menu. |
| `resource_conflict` | `5` | The screen is still waiting to pair and has no Player to switch yet. A display schedule can still be set. |
| `invalid_request` | `8` | A display or reboot schedule file is malformed. |
| `protected_target` | `5` | The screen is in a [protected folder](https://screenrig.ai/docs/permissions.md#protected-folders) and the change has no review form: display power and its schedule, `display-idle`, `brightness` and `volume`. Reboots and the maintenance commands stay open. |
| `rate_limited` | `7` | Reboots: 2 per screen per 10 minutes. Clear-cache, restart-app and update-software together: 2 per screen per 10 minutes. Both also 600 per organization and 60 per IP a minute. Display, reboot-schedule and volume writes: 10 per screen, 600 per organization and 60 per IP a minute. Wait for `retry_after_seconds`. |

Where a command takes several ids, `--tag TAG` or `--folder ID`, they run as one [fleet request](https://screenrig.ai/docs/cli/screens.md#fleet-results) with the fleet envelope and exit rules. `--tag` and `--folder` select active screens only, and `--folder` reaches the screen folder and every folder inside it. `--expect-rev` takes one screen id only.

### `screen reboot`

Reboot a screen's device, or a fleet's devices.

```console
screen reboot (<id>... | --tag TAG | --folder ID) [--yes] [--expires-in DURATION] [--expect-rev REVISION]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `<id>...` | string | one of `<id>`, `--tag` or `--folder` | none | One or more `scr_` screen ids. Several ids run as one fleet request. |
| `--tag TAG` | string | one of `<id>`, `--tag` or `--folder` | none | Every active screen carrying this tag. |
| `--folder ID` | string | one of `<id>`, `--tag` or `--folder` | none | Every active screen in this `sfd_` screen folder and the folders inside it. |
| `--yes` | boolean | for several ids, `--tag` or `--folder` | off | Confirms a fleet reboot. The CLI never prompts. |
| `--expires-in DURATION` | string | no | `24h`, applied by the server | How long the request waits for an offline screen to come online: `90s`, `30m`, `2h`, or `1d`, from `60s` to `24h`. |
| `--expect-rev REVISION` | string | no | none | One screen id only. Optional revision precondition. |

```console
screenrig screen reboot scr_LOBBY
screenrig screen reboot scr_LOBBY --expires-in 2h
screenrig screen reboot --tag Lobby --yes
screenrig screen reboot --folder sfd_01EXAMPLEFOLDER000000000 --yes
```

The Player reboots the device, not just itself. A screen that is online is sent the reboot at once (`state` `sent`); an offline screen holds it `queued` and is sent it when it comes online before `expires_at`, 24 hours after the request unless `--expires-in` says otherwise. The answer carries `reboot_id`, `state` and `expires_at`. A newer reboot supersedes one still queued. `screen show` lists the screen's `commands`: a sent reboot becomes `done` once the device reports it booted, and `screen command cancel` cancels one still queued. In a fleet, each result's `reboot` carries the same `state`. A refused or failed request, and an exact replay of the same request, do not count toward the per-screen limit. From the moment a reboot is sent until the device reports it booted or ten minutes pass, the screen opens no `screen_offline` or `display_disconnected` alert; a notice for either that falls due then waits until that period ends plus its hold, and a `crashing` notice is skipped as `planned_reboot`. A condition that still holds afterwards opens normally.

### `screen clear-cache`

Clear the caches of a screen's Player, or of a fleet's Players.

```console
screen clear-cache (<id>... | --tag TAG | --folder ID) [--yes] [--expires-in DURATION] [--expect-rev REVISION]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `<id>...` | string | one of `<id>`, `--tag` or `--folder` | none | One or more `scr_` screen ids. Several ids run as one fleet request. |
| `--tag TAG` | string | one of `<id>`, `--tag` or `--folder` | none | Every active screen carrying this tag. |
| `--folder ID` | string | one of `<id>`, `--tag` or `--folder` | none | Every active screen in this `sfd_` screen folder and the folders inside it. |
| `--yes` | boolean | for several ids, `--tag` or `--folder` | off | Confirms a fleet request. The CLI never prompts. |
| `--expires-in DURATION` | string | no | `24h`, applied by the server | How long the request waits for an offline screen to come online: `90s`, `30m`, `2h`, or `1d`, from `60s` to `24h`. |
| `--expect-rev REVISION` | string | no | none | One screen id only. Optional revision precondition. |

```console
screenrig screen clear-cache scr_LOBBY
screenrig screen clear-cache scr_LOBBY --expires-in 2h
screenrig screen clear-cache --tag Lobby --yes
```

The Player deletes its downloaded media, application packages and data caches, keeps its pairing, identity and settings, then fetches the manifest and content again; the screen can show its loading state while content refills. It reaches only a Player that declares `clear_cache`. A screen that is online is sent the request at once (`state` `sent`); an offline screen holds it `queued` and is sent it when it comes online before `expires_at`, 24 hours after the request unless `--expires-in` says otherwise. The answer carries `command_id`, `command`, `state` and `expires_at`. A Player that does not declare the capability answers 409 `command_unsupported` and nothing is sent; in a fleet that screen fails alone. `screen show` lists the command under `commands` and, once the Player reports, marks it `done` or `failed` with a `cause` and a short `detail`: `cleared` when the caches are cleared and the refetch has started, or `clear_failed` when a cache cannot be cleared. A sent command with no report stays `sent`. A newer command of the same kind supersedes one still queued, and `screen command cancel` cancels one still queued. In a fleet, each result's `command` carries the same `state`. A fleet (several ids, `--tag` or `--folder`) needs `--yes`. A refused or failed request, and an exact replay of the same request, do not count toward the per-screen limit of 2 clear-cache, restart-app and update-software requests together per 10 minutes.


### `screen restart-app`

Restart the application of a screen's Player, or of a fleet's Players.

```console
screen restart-app (<id>... | --tag TAG | --folder ID) [--yes] [--expires-in DURATION] [--expect-rev REVISION]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `<id>...` | string | one of `<id>`, `--tag` or `--folder` | none | One or more `scr_` screen ids. Several ids run as one fleet request. |
| `--tag TAG` | string | one of `<id>`, `--tag` or `--folder` | none | Every active screen carrying this tag. |
| `--folder ID` | string | one of `<id>`, `--tag` or `--folder` | none | Every active screen in this `sfd_` screen folder and the folders inside it. |
| `--yes` | boolean | for several ids, `--tag` or `--folder` | off | Confirms a fleet request. The CLI never prompts. |
| `--expires-in DURATION` | string | no | `24h`, applied by the server | How long the request waits for an offline screen to come online: `90s`, `30m`, `2h`, or `1d`, from `60s` to `24h`. |
| `--expect-rev REVISION` | string | no | none | One screen id only. Optional revision precondition. |

```console
screenrig screen restart-app scr_LOBBY
screenrig screen restart-app scr_LOBBY --expires-in 2h
screenrig screen restart-app --tag Lobby --yes
```

The Player restarts its application, not the device (a web Player reloads its page) and reports from the restarted process. It reaches only a Player that declares `restart_app`; `screen reboot` restarts the device. A screen that is online is sent the request at once (`state` `sent`); an offline screen holds it `queued` and is sent it when it comes online before `expires_at`, 24 hours after the request unless `--expires-in` says otherwise. The answer carries `command_id`, `command`, `state` and `expires_at`. A Player that does not declare the capability answers 409 `command_unsupported` and nothing is sent; in a fleet that screen fails alone. `screen show` lists the command under `commands` and, once the Player reports, marks it `done` or `failed` with a `cause` and a short `detail`: `restarted`, or `restart_failed` when the restart cannot start. A sent command with no report stays `sent`. A newer command of the same kind supersedes one still queued, and `screen command cancel` cancels one still queued. In a fleet, each result's `command` carries the same `state`. A fleet (several ids, `--tag` or `--folder`) needs `--yes`. A refused or failed request, and an exact replay of the same request, do not count toward the per-screen limit of 2 clear-cache, restart-app and update-software requests together per 10 minutes.


### `screen update-software`

Update a screen's Player to the newest release, or a fleet's Players.

```console
screen update-software (<id>... | --tag TAG | --folder ID) [--yes] [--expires-in DURATION] [--expect-rev REVISION]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `<id>...` | string | one of `<id>`, `--tag` or `--folder` | none | One or more `scr_` screen ids. Several ids run as one fleet request. |
| `--tag TAG` | string | one of `<id>`, `--tag` or `--folder` | none | Every active screen carrying this tag. |
| `--folder ID` | string | one of `<id>`, `--tag` or `--folder` | none | Every active screen in this `sfd_` screen folder and the folders inside it. |
| `--yes` | boolean | for several ids, `--tag` or `--folder` | off | Confirms a fleet request. The CLI never prompts. |
| `--expires-in DURATION` | string | no | `24h`, applied by the server | How long the request waits for an offline screen to come online: `90s`, `30m`, `2h`, or `1d`, from `60s` to `24h`. |
| `--expect-rev REVISION` | string | no | none | One screen id only. Optional revision precondition. |

```console
screenrig screen update-software scr_LOBBY
screenrig screen update-software scr_LOBBY --expires-in 2h
screenrig screen update-software --tag Lobby --yes
```

The Player checks for the newest Player release now and installs it where its platform lets the Player update itself; a web Player updates its service worker, then reloads. It reaches only a Player that declares `update`: a Player installed from a store or managed by a device manager updates through that channel. A screen that is online is sent the request at once (`state` `sent`); an offline screen holds it `queued` and is sent it when it comes online before `expires_at`, 24 hours after the request unless `--expires-in` says otherwise. The answer carries `command_id`, `command`, `state` and `expires_at`. A Player that does not declare the capability answers 409 `command_unsupported` and nothing is sent; in a fleet that screen fails alone. `screen show` lists the command under `commands` and, once the Player reports, marks it `done` or `failed` with a `cause` and a short `detail`: `up_to_date` when the newest release already runs, `updated` once the new version has started, or, when it failed, `update_check_failed`, `download_failed`, `install_failed` or `no_update_channel`. A sent command with no report stays `sent`. A newer command of the same kind supersedes one still queued, and `screen command cancel` cancels one still queued. In a fleet, each result's `command` carries the same `state`. A fleet (several ids, `--tag` or `--folder`) needs `--yes`. A refused or failed request, and an exact replay of the same request, do not count toward the per-screen limit of 2 clear-cache, restart-app and update-software requests together per 10 minutes.


### `screen command cancel`

Cancel a command that is still queued for an offline screen.

```console
screen command cancel <id> <command_id> [--expect-rev REVISION]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `<id>` | string | yes | none | The `scr_` screen id. |
| `<command_id>` | string | yes | none | An id from `commands` in `screen show`, or the `reboot_id`, `reload_id` or `command_id` the request answered with. |
| `--expect-rev REVISION` | string | no | none | Optional revision precondition. Omit to write the current resource. A supplied stale value is `revision_conflict`: refetch, reapply, retry. |

```console
screenrig screen command cancel scr_01EXAMPLESCREEN00000000 rbt_01EXAMPLEREBOOT00000000
```

It cancels a `reboot`, `reload`, `clear_cache`, `restart_app` or `update` that waits for an offline screen, so it is never sent. Only a queued command can be cancelled. One that was already sent (`sent` or `done`) answers 409 `resource_conflict` with "The command was already sent.", one that is no longer queued (`expired`, `cancelled`, or `superseded`) answers 409 `resource_conflict` with "The command is no longer queued.", and an id the screen does not list answers 404 `not_found`. The answer is the screen with the command `cancelled`, and the screen revision does not change.

### `screen display`

Turn a screen's display, or a fleet's displays, on or off now, or clear that override.

```console
screen display [set] (<id>... | --tag TAG | --folder ID) --power on|off [--until TIME | --for DURATION] [--expect-rev REVISION]
screen display clear (<id>... | --tag TAG | --folder ID) [--expect-rev REVISION]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `<id>...` | string | one of `<id>`, `--tag` or `--folder` | none | One or more `scr_` screen ids. Several ids run as one fleet request. A trailing `on` or `off` after the ids is the same as `--power`. |
| `--tag TAG` | string | one of `<id>`, `--tag` or `--folder` | none | Every active screen carrying this tag. |
| `--folder ID` | string | one of `<id>`, `--tag` or `--folder` | none | Every active screen in this `sfd_` screen folder and the folders inside it. |
| `--power on\|off` | string | yes, for `set` | none | The power to apply now. |
| `--until TIME` | string | no | the display schedule's next boundary | A strict RFC 3339 instant with seconds and an offset, sent normalized to UTC; strictly in the future and at most 7 days ahead. Not with `--for`. |
| `--for DURATION` | string | no | the display schedule's next boundary | `30m`, `2h`, or `3d`, up to `6d23h59m`. Not with `--until`. |
| `--expect-rev REVISION` | string | no | none | One screen id only. Optional revision precondition. |

```console
screenrig screen display scr_LOBBY --power off --for 2h
screenrig screen display --tag Lobby --power on
screenrig screen display scr_A scr_B --power off --for 8h
screenrig screen display clear --tag Lobby
```

`screen display ID` is short for `screen display set ID`; `clear` takes no `--power`, `--until` or `--for`. `screen display` is a manual override of the display schedule. Without `--until` or `--for` it ends at the schedule's next boundary; a later display-schedule or timezone change moves that end to the new boundary. With no boundary in the next eight days, for example with no enabled schedule, it holds until `screen display clear` or a replacement. `screen display clear` ends the override, so the display schedule applies again; without one, the display is on.

Saving an override does not wait for the Player. `display.override_status` compares a newer display report with it: `matches`, `mismatch`, `pending`, `stale` or `unknown`; `matches` describes the report, not that the command ran. The warning `display_power_mismatch` names a fresh report that differs and `display_power_unconfirmed` says a newer usable report is needed, so check `screen show` before taking a screenshot. `display_scrim_only` means the Player controls only a black overlay: `on` removes it and sends no hardware wake. A screen in a [protected folder](https://screenrig.ai/docs/permissions.md#protected-folders) refuses a display change (`protected_target`).

### `screen display-schedule`

Show, set, or clear when a screen's display is on.

```console
screen display-schedule show <id>
screen display-schedule set (<id>... | --tag TAG | --folder ID) --file FILE [--expect-rev REVISION]
screen display-schedule clear (<id>... | --tag TAG | --folder ID) [--expect-rev REVISION]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `<id>...` | string | one of `<id>`, `--tag` or `--folder` | none | One or more `scr_` screen ids; `show` takes one. Several ids run as one fleet request. |
| `--tag TAG` | string | one of `<id>`, `--tag` or `--folder` | none | Every active screen carrying this tag. |
| `--folder ID` | string | one of `<id>`, `--tag` or `--folder` | none | Every active screen in this `sfd_` screen folder and the folders inside it. |
| `--file FILE` | path | yes, for `set` | none | The display schedule, or `-` for stdin. |
| `--expect-rev REVISION` | string | no | none | One screen id only. Optional revision precondition. |

```console
screenrig screen display-schedule set scr_LOBBY --file hours.json
screenrig screen display-schedule set --tag Cafe --file hours.json
```

A display schedule is `{enabled, windows}`, both required, and `windows` lists 1 to 16 windows when the display is on, in the screen timezone; outside every window the display goes to standby. The Player evaluates it on the device, so it keeps working offline. A window whose `end` is at or before its `start` crosses midnight, and a window without `start` and `end` covers the whole day. `enabled: false` keeps the windows and leaves the display on. `display-schedule show` answers `display_schedule` (`null` when there is none) and the screen's `display` state. Its saved output can be edited and sent back with `set --file`. A screen in a [protected folder](https://screenrig.ai/docs/permissions.md#protected-folders) refuses a change to its display schedule (`protected_target`).

```json
{"enabled": true, "windows": [{"days": ["mon", "tue", "wed", "thu", "fri"], "start": "07:00", "end": "19:00"}, {"days": ["sat"]}]}
```

`screen show --human` prints `Display:` with the requested power, its source (manual override, display schedule, or default) and until when in the screen timezone, the schedule windows, and the power the Player reported, marked stale after 35 minutes without a report.

### `screen volume`

Set a screen's volume, or mute it, on one screen or a fleet.

```console
screen volume (<id>... | --tag TAG) [--level 0-100] [--mute | --unmute] [--expect-rev REVISION]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `<id>...` | string | one of `<id>` or `--tag` | none | One or more `scr_` screen ids. Several ids run as one fleet request. |
| `--tag TAG` | string | one of `<id>` or `--tag` | none | Every active screen carrying this tag. |
| `--level 0-100` | integer | at least one of `--level`, `--mute` or `--unmute` | none | The volume, from 0 to 100. Omitted, the Player keeps its level. |
| `--mute` | boolean | at least one of `--level`, `--mute` or `--unmute` | off | Silences the screen and keeps its level. Not with `--unmute`. |
| `--unmute` | boolean | at least one of `--level`, `--mute` or `--unmute` | off | Plays at the level again. Not with `--mute`. |
| `--expect-rev REVISION` | string | no | none | One screen id only. Optional revision precondition. |

```console
screenrig screen volume scr_LOBBY --level 40
screenrig screen volume scr_LOBBY --mute
screenrig screen volume scr_LOBBY --unmute
screenrig screen volume --tag Lobby --level 25 --unmute
```

A screen has one volume: a level from 0 to 100 and a mute. Muting keeps the level, so unmuting restores it. A screen that is online applies the change at once; an offline screen applies the latest request when it comes back, and a newer request replaces an earlier one. A change made later in the Player's own settings menu wins until the next `screen volume`, and changing the level there clears the mute. `screen show` reports `volume` with the latest `requested` change and, as `reported`, the `level` and `muted` the Player reached and `hardware`: true when the level reaches the device or panel output, false when it is the Player's own gain; `stale` turns true after 35 minutes without a report. Only a Player that declares the `volume` capability applies it: any other screen answers 409 `volume_unsupported` (exit code 5) and nothing is recorded. An archived screen answers `screen_archived` and a screen still waiting to pair answers `resource_conflict`. A screen in a [protected folder](https://screenrig.ai/docs/permissions.md#protected-folders) refuses the change (`protected_target`), and in a fleet one protected screen refuses the whole request. The dashboard's screen page has the same Volume control.

### `screen display-idle`

Darken a screen's glass after a time without use, or turn that off.

```console
screen display-idle <id> --after SECONDS --wake WAKE [--expect-rev REVISION]
screen display-idle <id> --off [--expect-rev REVISION]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `<id>` | string | yes | none | The `scr_` screen id. |
| `--after SECONDS` | integer | one of `--after` or `--off` | none | Go dark after this many seconds without use, 30 to 86400. Needs `--wake`. |
| `--wake WAKE` | string | with `--after` | none | What lights the glass again: `touch`, `presence` or `touch,presence`. Presence reads the device's camera on the device; no image leaves it. |
| `--off` | boolean | one of `--after` or `--off` | off | Turn idle dark off. |
| `--expect-rev REVISION` | string | no | none | Optional revision precondition. Omit to write the current resource. A supplied stale value is `revision_conflict`: refetch, reapply, retry. |

```console
screenrig screen display-idle scr_LOBBY --after 300 --wake touch
screenrig screen display-idle scr_LOBBY --after 600 --wake touch,presence --expect-rev 4
screenrig screen display-idle scr_LOBBY --off
```

The glass goes dark after `--after` seconds without a touch or key or, when `--wake` lists `presence`, anybody in front of the screen. While it is dark the Player parks playback, with no plays and no ads, and reports display power off; a wake event lights the glass at once and playback resumes, and the touch that wakes a dark glass is not passed to the page. A display schedule or override that holds the panel off wins, and so does an application that holds `device.display` while its page is on glass. Only `display.idle` changes. A Player applies it when `screen show` lists `display_power.idle` in its host capabilities; the setting is stored either way, and `screen show` lists it as `Display idle`. Propose access cannot change it (`insufficient_access`), and a screen in a protected folder refuses it (`protected_target`).

### `screen brightness`

Set whether a screen's brightness follows the device's light sensor.

```console
screen brightness <id> --mode auto|fixed [--expect-rev REVISION]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `<id>` | string | yes | none | The `scr_` screen id. |
| `--mode auto\|fixed` | string | yes | none | `auto` sets the brightness from the device's light sensor; `fixed` keeps the operator's brightness, the default. |
| `--expect-rev REVISION` | string | no | none | Optional revision precondition. Omit to write the current resource. A supplied stale value is `revision_conflict`: refetch, reapply, retry. |

```console
screenrig screen brightness scr_LOBBY --mode auto
screenrig screen brightness scr_LOBBY --mode fixed --expect-rev 4
```

Only `display.brightness` changes. A Player applies `auto` when `screen show` lists `brightness.auto` in its host capabilities, which a device declares only with a light sensor; an application that sets the display's brightness wins while its page shows. The setting is stored either way, and `screen show` lists it as `Display brightness`. The access rules of `screen display-idle` apply.

### `screen display-output`

Set the video mode a screen's Player puts on its output, or clear it.

```console
screen display-output <id> (--mode MODE | --clear) [--expect-rev REVISION]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `<id>` | string | yes | none | The `scr_` screen id. |
| `--mode MODE` | string | one of `--mode` or `--clear` | none | `auto` leaves the mode to the display's own preferred mode. Otherwise `WIDTHxHEIGHTxFPS` with an optional `p` or `i`, as BrightSign names a mode, such as `3840x2160x60p`. |
| `--clear` | boolean | one of `--mode` or `--clear` | off | Remove the setting. |
| `--expect-rev REVISION` | string | no | none | Optional revision precondition. Omit to write the current resource. A supplied stale value is `revision_conflict`: refetch, reapply, retry. |

```console
screenrig screen display-output scr_LOBBY --mode 3840x2160x60p
screenrig screen display-output scr_LOBBY --mode auto --expect-rev 4
screenrig screen display-output scr_LOBBY --clear
```

`screen show` lists the modes the Player can set now, under `Output modes the Player can set`, and the mode in force. Once the Player has reported them, a mode outside that list is `invalid_request`, so pick one it lists. Only `display.output` changes. A Player applies it when `screen show` lists `display_output.mode` in its host capabilities, which a BrightSign player declares; any other mode than `auto` on another Player answers `display_output_unsupported`, and clearing always works. The Player applies a mode once, may restart to do it, and reports the mode it reached. The access rules of `screen display-idle` apply.

### `screen display-cec`

Have a screen's Player take the TV's HDMI input over CEC, or stop.

```console
screen display-cec <id> (--on | --off | --clear) [--expect-rev REVISION]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `<id>` | string | yes | none | The `scr_` screen id. |
| `--on`, `--off`, `--clear` | boolean | one of the three | none | `--on` has the Player assert HDMI-CEC active source at start and whenever display power turns on, so the TV switches to the Player's input. `--off` keeps the setting without taking the input. `--clear` removes it. |
| `--expect-rev REVISION` | string | no | none | Optional revision precondition. Omit to write the current resource. A supplied stale value is `revision_conflict`: refetch, reapply, retry. |

```console
screenrig screen display-cec scr_LOBBY --on
screenrig screen display-cec scr_LOBBY --off --expect-rev 4
screenrig screen display-cec scr_LOBBY --clear
```

Only `display.cec` changes. A Player applies it when `screen show` lists `display_power.cec_active_source` in its host capabilities, which a BrightSign player declares; `--on` on another Player answers `display_cec_unsupported`, while `--off` and `--clear` always work. The Player sends nothing while a display schedule or override holds the display off, and a CEC failure never affects playback. `screen show` lists the setting as `Display CEC`. The access rules of `screen display-idle` apply.

### `screen kiosk-lock`

Pin a screen's Player to the screen, or release it.

```console
screen kiosk-lock <id> (--on | --off) [--expect-rev REVISION]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `<id>` | string | yes | none | The `scr_` screen id. |
| `--on`, `--off` | boolean | one of the two | none | `--on` pins the Player to the screen; `--off` releases it. |
| `--expect-rev REVISION` | string | no | none | Optional revision precondition. Omit to write the current resource. A supplied stale value is `revision_conflict`: refetch, reapply, retry. |

```console
screenrig screen kiosk-lock scr_LOBBY --on
screenrig screen kiosk-lock scr_LOBBY --off --expect-rev 4
```

`--on` uses Android screen pinning: the person at the screen confirms the first time, and the status bar, home and recents are blocked while the Player is pinned. The operator settings panel can leave the lock until the next manifest or restart applies it again. A Player applies it when `screen show` lists `kiosk_lock` in its host capabilities; the setting is stored either way, and `screen show` lists `Kiosk lock` while it is on. Propose access cannot change it (`insufficient_access`).

### `screen reboot-schedule`

Show, set, or clear when the backend reboots a screen's device.

```console
screen reboot-schedule show <id>
screen reboot-schedule set (<id>... | --tag TAG | --folder ID) (--window SPEC... | --file FILE) [--disabled] [--expect-rev REVISION]
screen reboot-schedule clear (<id>... | --tag TAG | --folder ID) [--expect-rev REVISION]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `<id>...` | string | one of `<id>`, `--tag` or `--folder` | none | One or more `scr_` screen ids; `show` takes one. Several ids run as one fleet request. |
| `--tag TAG` | string | one of `<id>`, `--tag` or `--folder` | none | Every active screen carrying this tag. |
| `--folder ID` | string | one of `<id>`, `--tag` or `--folder` | none | Every active screen in this `sfd_` screen folder and the folders inside it. |
| `--window SPEC` | string | one of `--window` or `--file`, for `set` | none | Reboot at the start of this weekly window, `DAYS HH:MM-HH:MM` in the screen timezone, such as `"Mon-Sun 04:00-04:30"` (`DAYS@HH:MM-HH:MM` also works). `DAYS` is `daily`, a day, a range such as `Mon-Fri` or a list such as `Sat,Sun`. Repeat up to 16 times; each window lasts 5 minutes to 24 hours. |
| `--file FILE` | path | one of `--window` or `--file`, for `set` | none | The reboot schedule as JSON, or `-` for stdin, instead of `--window`. |
| `--disabled` | boolean | no | off | Keep the windows and reboot nothing. Not with `--file`; put `"enabled": false` in the file instead. |
| `--expect-rev REVISION` | string | no | none | One screen id only. Optional revision precondition. |

```console
screenrig screen reboot-schedule set scr_LOBBY --window "Mon-Sun 04:00-04:30"
screenrig screen reboot-schedule set --tag Cafe --window "Mon-Fri 04:00-04:30" --window "Sat,Sun 05:00-06:00"
screenrig screen reboot-schedule set scr_LOBBY --file reboots.json --expect-rev 4
screenrig screen reboot-schedule set --folder sfd_01EXAMPLEFOLDER000000000 --window "Mon-Sun 04:00-04:30"
```

At the start of each window, in the screen timezone, screenRIG issues the same reboot as `screen reboot`, so `"Mon-Sun 04:00-04:30"` reboots the screen at 04:00 local time every day. `commands` in `screen show` lists it with `source` `schedule`, and `screen show` and `reboot-schedule show` print `next_reboot_at`. A window whose end is at or before its start crosses midnight, and a window without times covers the whole day. The saved output of `reboot-schedule show` can be edited and sent back with `set --file`:

```json
{"enabled": true, "windows": [{"days": ["mon", "tue", "wed", "thu", "fri", "sat", "sun"], "start": "04:00", "end": "04:30"}]}
```

An online screen is sent the reboot at once. An offline screen keeps it queued only until its window ends, so a reboot never lands outside the window: a screen that comes back after it gets none. A start inside a spring-forward gap fires at the first valid minute of the window, and a fall-back repeat fires once per window per local date. A scheduled reboot never replaces one a person asked for that still waits for the screen; the occurrence is skipped with `screen.reboot_skipped` (`reboot_pending`). The screen needs a Player that declares `reboot`; a screen that loses `reboot` later skips each window and keeps its schedule. Changing the timezone cancels the scheduled reboots still waiting and moves `next_reboot_at` to the new zone. A reboot a schedule sent raises no offline alert, as under [`screen reboot`](https://screenrig.ai/docs/cli/device.md#cmd-screen-reboot). `screen.reboot_schedule_changed` records each set or clear. A file is `{enabled, windows}`, both required. Reboot schedules are in every plan. In a fleet, each result is that screen's own: `reboot_unsupported` for a screen whose Player cannot reboot.

### `screen uptime`

Read a screen's daily availability over UTC days.

```console
screen uptime <id> [--day-from YYYY-MM-DD] [--day-to YYYY-MM-DD] [--format json|csv|xlsx|pdf] [--output FILE]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `<id>` | string | yes | none | The `scr_` screen id. |
| `--day-from YYYY-MM-DD` | string | no | 29 days before `--day-to` | First UTC day, inclusive. |
| `--day-to YYYY-MM-DD` | string | no | today | Last UTC day, inclusive. With `--day-from`, the range counts both days and spans at most 366. |
| `--format FORMAT` | string | no | `json` | `json` is the command answer. `csv`, `xlsx` or `pdf` writes every row to `--output` and answers its `path`, `bytes`, `sha256`, `content_type` and `format`. |
| `--output FILE` | path | no | `./screen-uptime.FORMAT` | The file for `csv`, `xlsx` or `pdf`: a file path, not a directory, and not `-`. An existing file is replaced. Not with `json`. |

```console
screenrig screen uptime scr_01EXAMPLESCREEN00000000
screenrig screen uptime scr_01EXAMPLESCREEN00000000 --day-from 2026-09-01 --day-to 2026-09-30
screenrig screen uptime scr_01EXAMPLESCREEN00000000 --format xlsx --output uptime.xlsx
```

`data.items` lists one row per UTC day with a recorded state, oldest first: `online_s`, `offline_s`, `availability` (online over recorded time; `null` when nothing was recorded), `coverage` (the share of the day with a recorded state), `intervals`, and `live` for a day that includes the open interval up to now. Time with no recorded state lowers `coverage` and is never downtime. Days with nothing recorded have no row.

### `screen presence`

List a screen's online and offline transitions, newest first.

```console
screen presence <id> [--since TIME] [--until TIME]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `<id>` | string | yes | none | The `scr_` screen id. |
| `--since TIME` | string | no | 30 days before `--until` | Inclusive start of the transition time: an RFC 3339 instant with seconds and an offset (normalized to UTC), `now`, or an age such as `7d`, `12h`, or `30m`. |
| `--until TIME` | string | no | now | Exclusive end, in the same forms. At most 366 days after `--since`. |

```console
screenrig screen presence scr_01EXAMPLESCREEN00000000 --since 7d
screenrig screen presence scr_01EXAMPLESCREEN00000000 --since 2026-09-01T00:00:00Z --until 2026-09-08T00:00:00Z
```

`data.items` carries `at`, `state`, and `detected_on_reconnect` on an offline the server noticed only when the screen reconnected (`at` is then when its presence lease ended). The CLI follows `next_cursor` to the end and answers every transition with `next_cursor` `null`, so narrow a long range with `--since`.

### `screen health-history`

List the health a screen reported over time, each report or one summary per hour.

```console
screen health-history <id> [--from TIME] [--to TIME] [--resolution raw|hour] [--format json|csv|xlsx|pdf] [--output FILE]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `<id>` | string | yes | none | The `scr_` screen id. |
| `--from TIME` | string | no | 24 hours before `--to` | Inclusive start of the report time: an RFC 3339 instant with seconds and an offset (normalized to UTC), `now`, or an age such as `7d`, `12h`, or `30m`. |
| `--to TIME` | string | no | now | Exclusive end, in the same forms. At most 31 days after `--from`, 93 with `--resolution hour`. |
| `--resolution raw\|hour` | string | no | `raw` | `raw` lists each accepted report; `hour` summarizes each UTC hour. |
| `--format FORMAT` | string | no | `json` | `json` is the command answer. `csv`, `xlsx` or `pdf` writes every row to `--output` and answers its `path`, `bytes`, `sha256`, `content_type` and `format`. |
| `--output FILE` | path | no | `./screen-health-history.FORMAT` | The file for `csv`, `xlsx` or `pdf`: a file path, not a directory, and not `-`. An existing file is replaced. Not with `json`. |

```console
screenrig screen health-history scr_01EXAMPLESCREEN00000000 --from 6h
screenrig screen health-history scr_01EXAMPLESCREEN00000000 --from 30d --resolution hour
screenrig screen health-history scr_01EXAMPLESCREEN00000000 --from 30d --resolution hour --format csv --output health.csv
```

`raw` answers `data.samples`, each accepted report shaped like the `health` of `screen show` without `stale`. `hour` answers `data.hours`, one summary per UTC hour: reports, peak and average temperature, peak load and memory ratio, weakest Wi-Fi signal, `display_disconnected`, and peak crash and renderer-restart counts. The CLI follows `next_cursor` to the end, so narrow a long raw range or use `--resolution hour`. Raw reports arrive within seconds and hourly summaries within about 5 minutes.

### `screen storage-forecast`

Check whether a playlist fits the storage a screen's Player last reported, before the playlist is assigned.

```console
screen storage-forecast <id> --playlist-id ID [--playlist-rev REVISION]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `<id>` | string | yes | none | The `scr_` screen id. |
| `--playlist-id ID` | string | yes | none | The `pl_` playlist to check. |
| `--playlist-rev REVISION` | integer | no | none | Refuse the check (`revision_conflict`, exit `6`) when the playlist is not at this revision. |

```console
screenrig screen storage-forecast scr_01EXAMPLESCREEN00000000 --playlist-id pl_01EXAMPLEPLAYLIST000000
screenrig screen storage-forecast scr_01EXAMPLESCREEN00000000 --playlist-id pl_01EXAMPLEPLAYLIST000000 --playlist-rev 7
```

It writes nothing: no assignment, no screen revision, no event. Read only access is enough, and a screen takes at most 30 checks a minute. `data.fit` is `fits`, `partial` (some pages are left out), `none_fit` (nothing loads) or `unknown` (the screen has never reported storage, or the playlist's content is not ready). `data.excluded_page_count` counts the pages left out, `data.required_bytes` is what the whole playlist needs, `data.capacity_bytes` what the Player reported it may use, `data.basis` is `reported_capacity` and `data.received_at` is when the Player reported. With `fit` `unknown` the byte counts and `received_at` are `null`. A report older than 24 hours is marked stale but still used. When the playlist does not fit, the answer carries a `storage_full` warning: free storage on the device that runs the Player, then check again. [Cache and storage](https://screenrig.ai/docs/troubleshooting.md#cache-and-storage) explains the plan. A saved assignment does not confirm playback.

## Other command groups

- [Projects](https://screenrig.ai/docs/cli/projects.md)
- [Service clients](https://screenrig.ai/docs/cli/service-clients.md)
- [Help and support](https://screenrig.ai/docs/cli/help.md)
- [Media](https://screenrig.ai/docs/cli/media.md)
- [Media sync](https://screenrig.ai/docs/cli/media-sync.md)
- [Playlists](https://screenrig.ai/docs/cli/playlists.md)
- [Cards](https://screenrig.ai/docs/cli/cards.md)
- [Applications](https://screenrig.ai/docs/cli/applications.md)
- [Screens](https://screenrig.ai/docs/cli/screens.md)
- [Schedules](https://screenrig.ai/docs/cli/schedules.md)
- [Campaigns](https://screenrig.ai/docs/cli/campaigns.md)
- [Reviews and notes](https://screenrig.ai/docs/cli/reviews.md)
- [Notifications](https://screenrig.ai/docs/cli/notifications.md)
- [Reports](https://screenrig.ai/docs/cli/reports.md)
- [Data sources](https://screenrig.ai/docs/cli/data-sources.md)
- [BI dashboards](https://screenrig.ai/docs/cli/bi.md)
- [Triggers](https://screenrig.ai/docs/cli/triggers.md)
- [Fleet links](https://screenrig.ai/docs/cli/fleet-links.md)
- [Advertising](https://screenrig.ai/docs/cli/ads.md)
