# Projects CLI commands

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

Create, select, rename, move and export projects, sign in and out, invite people, read plan limits and advertising amounts, and run doctor. 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.

## Project and organization lifecycle

The current project is the last one used. Every JSON envelope includes organization and project context; human output names both. Identity credentials are limited by the selected project's membership. Retry state stays separate per project.

```console
project list
project token --projects IDS
project use ID
project create NAME [--organization-id ID | --organization NAME]
project moves
project move --organization-id ID
project transfer-owner --user-id ID
project deletion-preview
project delete --name NAME --revision N --yes
organization list
organization rename ID NAME
project export DIR [--no-media] [--since YYYY-MM-DD]
agent disconnect --yes [--allow-lockout]
agent revoke-identity --yes
```

`project list` verifies accessible memberships. `project token --projects IDS` replaces the projects this sign-in's token covers with 1 to 64 consented project IDs separated by commas or spaces. `project use` selects one. Create requires a name unique in its organization and defaults to the current project's organization, then to the organization you administer; when none is named, the organization holding the owner's verified email domain comes first. The responsible person becomes owner. Each plan caps how many projects an organization holds; each person has one free Standard organization, and a second needs Plus, Premium or Enterprise. With no current project and no organization named, the server places the project the same way. `--organization NAME` starts a new organization only for a person who holds no free one; otherwise creation is refused with `free_organization_limit`, whose detail names the organization to use. Enrollment is governed by rate limits.

The owner can move into a destination returned by `project moves`, or transfer ownership to an existing verified member. A move carries screens, and a destination organization that already holds as many projects as its plan allows refuses it with `project_limit_reached`. Deletion uses the exact current name and positive revision from its preview. It requires zero non-archived screens, no plan of its own and no live advertising. Only the project's owner or an administrator of its organization may delete it; an agent deletes for its responsible person, or alone only the project it enrolled while no person has accepted that enrollment. It emails members and retains a tombstone.

Organization names can repeat; use explicit IDs when renaming an organization you administer. An organization has designated admins and home members; admins invite other admins and members by email from the dashboard. `organization list` marks `free` and `plan_required` organizations, reports `new_organization_allowed`, and names an organization's Library project in `library_project_id` when it has one. Its project list does not grant access to project content. The organization pays: its plan, storage and agent request cap are shared by its projects.

`login --project ID` asks for that project on the same identity. Only explicit approval of this request grants a membership. `agent disconnect --yes` revokes one membership (`--allow-lockout` also allows revoking the project's last agent); `agent revoke-identity --yes` separately revokes the identity and all memberships. An ambiguous response retains local credentials and retry state for reconciliation.

Advertising reports retain settlement facts beyond event retention. Read their coverage metadata: missing historical plays or unknown approved duration are unknown, never zero. A report can have complete financial totals and incomplete outcome history.

## Projects, invitations, and diagnostics

Project commands list memberships, select a project, create projects, and manage their names, owners, moves and deletion.
Invitations bring people into projects or advertising networks.

### `project show`

Read the project record.

```console
project show
```

No parameters.

```console
screenrig project show
```


### `project rename`

Set the name people see in the dashboard project switcher.

```console
project rename NAME
```

### `project token`

Replace the projects this sign-in's token covers.

```console
project token --projects IDS
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `--projects IDS` | string | yes | none | 1 to 64 distinct `prj_` project ids separated by commas or spaces, each one this identity has consented to. |

```console
screenrig project token --projects prj_01EXAMPLEPROJECT0000,prj_01EXAMPLEOTHER000000
```

Replaces the whole subset; `project list` alone grants no access. A lost answer keeps the rotation request id for an identical retry.

### `project capabilities`

Read the project's plan, independent `screens` and `advertiser` feature flags,
and effective capability set. A route denial wins over a stale capability read.

```console
project capabilities
```

### `project uptime`

Read the project's daily screen availability over UTC days.

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

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `--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. At most 366 days after `--day-from`. |
| `--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 | `./project-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 project uptime
screenrig project uptime --day-from 2026-09-01 --day-to 2026-09-30
```

Range and defaults are those of `screen uptime`. `data.items` lists one row per UTC day, oldest first: `online_s` and `offline_s` summed over the screens with a recorded state that day, `availability`, `coverage` (the share of those screens' day with a recorded state), and `screens` (how many had a recorded state). Today's row covers intervals that ended so far; `screen list` shows who is online now.

### `project health-trend`

Read the fleet's health by UTC hour: screens reporting, hot, display disconnected, crashing.

```console
project health-trend [--from TIME] [--to TIME] [--format json|csv|xlsx|pdf] [--output FILE]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `--from TIME` | string | no | 24 hours before `--to` | Inclusive start of the hour: 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 93 days after `--from`. |
| `--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 | `./health-trend.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 project health-trend
screenrig project health-trend --from 7d
```

`data.items` lists the fleet's health by UTC hour: `hour`, `screens_reporting`, `hot` (peak temperature at or above 80 °C), `display_disconnected`, and `crashing` (3 or more crashes in 24 hours). The CLI follows `next_cursor` to the end and answers every hour with `next_cursor` `null`. Hours follow reports by up to about 5 minutes.

### `project export`

Write this project's data to a directory in open formats.

```console
project export <DIR> [--no-media] [--since YYYY-MM-DD]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `<DIR>` | path | yes | none | The directory to write. It is created if needed, and a rerun continues and refreshes it. |
| `--no-media` | boolean | no | off | Skip the original media files; the manifest still lists them with their hashes. |
| `--since YYYY-MM-DD` | string | no | as far back as the plan keeps the data | First UTC day of the plays, uptime and playback CSV and of the event log. |

```console
screenrig project export ./export
screenrig project export ./export --no-media --since 2026-01-01
```

`DIR` gets JSON for the project, screens, screen folders, tags, per-screen schedules, playlists with every revision, campaigns, direct campaigns, cards and their data, sources (never their credentials), notifications, webhooks (no signing secrets or receiver URLs), mutes, application metadata, triggers and report subscriptions; the original media files in `media/files` with `media/manifest.json` holding each file's SHA-256; CSV for plays, playback, uptime and alerts in `data/`; and the event log in `log/events.jsonl`. `export.json` is written last and lists every file with its size and SHA-256 and each section's outcome (`ok`, `skipped` or `failed`). A rerun keeps complete media files and continues partial ones. A section the credential cannot read is `skipped`; the warning `export_section_failed` means the copy is incomplete, so run the same command again. Application files are reported as omitted with `complete: false` and the warning `export_application_content_omitted`, including with `--no-media`: keep the original application archives for recovery. Each request is a billed API request, and media downloads are egress.

### `invitations`

Create, list, or revoke project-member, uploader and ad-buyer invitations.

```console
invitations create (--email ADDRESS[,ADDRESS] | --link) [--kind member|uploader|ad-buyer]
    [--screen-id IDS] [--screen-folder-id IDS] [--slot-id IDS] [--policy trusted|review_required]
    [--folder-id IDS] [--playlist-id IDS] [--access propose|manage]
invitations list [--kind member|ad-buyer] [--status STATUS]
invitations revoke ID
```

`--kind` defaults to `member`. Email delivery is the default and expires after
seven days. `--email` accepts comma-separated recipients, up to fifty per request.
`--link` is member-only, names no recipient, and returns a
twenty-four-hour invitation URL once for direct handoff to the intended person. Never put that URL in
logs, notes, or a shared transcript. Lists never return it. At most 50 invitations
may be outstanding per organization.

Ad buyers use email only and need an owned screen or slot scope (or both).
`--screen-id` and `--slot-id` accept comma-separated IDs; `--policy` selects
`trusted` or `review_required`. Status filters are `queued`, `sent`, `issued`,
`accepted`, `revoked`, `expired`, and `failed`.

`--kind uploader` invites a person who works only in the media folders given with `--folder-id` (at least one) and the playlists given with `--playlist-id`: they upload into those folders and add, replace and remove pages of those playlists, and nothing else. Their changes wait for review unless `--access manage`, which only someone who can approve reviews may grant. A `--kind member` invitation with `--screen-folder-id` (each folder includes every folder inside it) or `--screen-id` limits the person who accepts to those screens. `--folder-id`, `--playlist-id` and `--access` need `--kind uploader`, and `--slot-id` and `--policy` need `--kind ad-buyer`. See [Authentication](https://screenrig.ai/docs/authentication.md).

```console
screenrig invitations create --email teammate@example.com
screenrig invitations create --kind ad-buyer --email buyer@example.com --screen-id scr_LOBBY --policy review_required
```

Agents do not accept invitations. The invited person opens the email, signs in
or creates a passkey, and accepts in the dashboard. Link signup
verifies their email first. Revoking an accepted invitation does not undo a
membership; use the buyer membership controls to revoke advertising access.

### `agent status`

Report whether this installation holds a usable credential.

```console
agent status
```

No parameters.

```console
screenrig agent status
```

Read-only. It never changes local or server state, and it costs nothing.
The result carries the session's `access`, its `effective_access` and, when
the project's review setting or a member who cannot approve holds it lower,
`access_limited_by` (`project` or `person`). When the project limits this agent to screen folders and screens, `screen_scope` lists them (`folder_ids`, each with every folder inside it, and `screen_ids`) and `person_screen_scope` is the scope of the person responsible for the agent; the agent acts only on the screens both allow, and both are absent for an agent of the whole project. Outside the scope a command answers `outside_screen_scope` (exit `3`). New project notes, or notes due for review, add the warning `notes_waiting`.

### `agent disconnect`

Revoke this agent's membership in the current project.

```console
agent disconnect --yes [--allow-lockout]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `--yes` | boolean | yes | off | Confirm the revocation. Nothing is sent without it. |
| `--allow-lockout` | boolean | no | off | Allow disconnecting the last agent of the project. Without it the server refuses with `agent_lockout_risk`. |

```console
screenrig agent disconnect --yes
```

Revokes only the current project's membership: the identity, the other memberships, the project and its screens remain. Local credentials and retry state stay when the answer is ambiguous, so rerunning is safe.

### `agent revoke-identity`

Revoke this identity and all its project memberships.

```console
agent revoke-identity --yes
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `--yes` | boolean | yes | off | Confirm the revocation across every project. |

```console
screenrig agent revoke-identity --yes
```

Confirmed revocation clears the local credentials and pending work for every cached project. An ambiguous failure keeps them.

### `login`

Sign this installation in to an existing account, with a person's approval in the dashboard, or as a service client.

```console
login [--project ID] [--access read|propose|manage] [--name NAME] [--no-wait] [--resume ID]
login --client-id ID (--client-key-file PATH | --client-secret-file PATH)
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `--project ID` | string | no | none | Suggest the `prj_` project the person approves. |
| `--access LEVEL` | string | no | manage | `read`, `propose` or `manage`. The person makes the final choice. |
| `--name NAME` | string | no | none | Name this installation, at most 80 characters. |
| `--no-wait` | boolean | no | off | Return `status: pending` with the address, the code and a `login_` handle. |
| `--resume ID` | string | no | none | Wait for the pending sign-in that `--no-wait` started. |
| `--client-id ID` | string | no | none | Sign this configuration in as a [service client](https://screenrig.ai/docs/service-clients.md) (`scl_…`) instead of a person, with no approval. Not with `--no-wait`, `--project`, `--access` or `--name`. |
| `--client-key-file PATH` | path | with `--client-id` | none | The client's private key, a JWK or PEM. Exactly one of the key file and the secret file. |
| `--client-secret-file PATH` | path | with `--client-id` | none | A file holding the client's secret. |

```console
screenrig login --access read
screenrig --config ci.json login --client-id scl_01EXAMPLECLIENT0000 --client-key-file ci-key.pem
```

Prints the dashboard address and an eight-letter code to stderr, then waits up to 24 hours. The person checks that the code matches and presses Connect once, with no second passkey prompt after a dashboard sign-in from the last hour. The envelope reports `status: signed_in`, the project, the organization and `access`. Running it again on a signed-in installation adds a project or raises a Read only or Propose project to Manage. Denial is `login_denied` and expiry is `login_expired`.

A service client's configuration must be its own file: every later command with that `--config` signs in as the client, reading the key or secret file each time and keeping the token in memory.

### `logout`

End this installation's sign-in and remove its tokens.

```console
logout
```

No parameters.

```console
screenrig logout
```

Revokes the sign-in on the server, then removes the stored tokens and reports `status: signed_out`. In a service client's configuration it removes the saved client and leaves its key or secret file. A failure that might not have reached the server keeps them, so rerunning is safe. Run `screenrig login` to sign in again.

### `dashboard`

Open the ordinary dashboard URL. This command does not mint a sign-in link,
create a session, or need an agent credential.

```console
dashboard [open]
```

```console
screenrig dashboard
```

The dashboard shows the person's projects after sign-in. Browser project
selection does not change the project bound to an agent.

### `dashboard reset-sign-in`

Request a sign-in reset email without an agent credential.

```console
dashboard reset-sign-in --email ADDRESS
```

The acknowledgment does not reveal whether the email has a login. The emailed
reset expires after one hour; the person creates a new passkey.
Completion replaces their sign-in credentials and revokes other sessions. While the project's ownership is still pending from enrollment, `--email` with the original enrollment address also emails a fresh seven-day enrollment invitation; the person opens it and accepts with their sign-in to claim ownership.

### `doctor`

Check this installation and report every check by name.

```console
doctor [--repair-config]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `--repair-config` | boolean | no | off | Tighten the permissions on an existing configuration file that is readable by group or others. |

```console
screenrig doctor
```

`data.checks` names each check and its status (`pass`, `warn` or `fail`): the Node runtime, the resolved configuration path and its permissions, the stored credential and the sign-in's end, the control-plane origin and its service routes, the advertised `feedback` capability, and the optional media toolchain (`ffmpeg`, `ffprobe`, `encoder_libx264`, `encoder_libx265`, `encoder_libwebp`, `cwebp`, `filter_hdr_tonemap`).

Any failed check makes `doctor` exit non-zero, and a `warn` does not, so read the individual names before calling the installation unhealthy. A missing media toolchain affects only the commands that convert media: `media upload`, `media upload-batch`, `media replace` and `playlist init`.

### `version`

Print the bundled CLI version and its protocol adapter.

```console
version
```

No parameters.

```console
screenrig version
```

Run this first in a session. A successful envelope proves the launcher resolved the bundled CLI. `--version` and `-V` do the same thing from anywhere on the command line.

<a id="service-clients"></a>

## Billing

Plan limits and advertising amounts for the project. Requests, storage, playback and everything else a project does are never charged; the amounts here are advertising only. All three commands are free, and reads of `/api/billing` do not count toward the hourly agent request cap.

### `billing usage`

Read the plan's storage and agent request limits.

```console
billing usage
```

No parameters.

```console
screenrig billing usage
```

`data.stored_bytes` is the storage used and `data.allowance.storage_bytes` the plan's storage limit; an upload past it is refused with `quota_exceeded`. `data.allowance.requests_per_hour` is the hourly agent request cap (`agent_requests_per_hour` in the human output). The requests remaining this hour are in the `RateLimit` header of each counted response.

### `billing balance`

Read advertising amounts in US dollars: remaining, reserved, available and payable earnings.

```console
billing balance
```

No parameters.

```console
screenrig billing balance
```

Advertisers pay by card or x402 machine payment, prices and earnings are US dollars, and payouts start 1 January 2027. The human output shows dollars; the JSON keeps the decimal mcr members, where 10,000,000 mcr is US$1.

### `billing statement`

Read the posted ledger entries.

```console
billing statement [--cursor CURSOR] [--limit COUNT]
```

| Parameter | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `--cursor CURSOR` | string | no | first page | The `next_cursor` of a previous statement. |
| `--limit COUNT` | integer | no | server default | The most entries to return. |

```console
screenrig billing statement --limit 20
```

Entries are posted ledger rows in US dollars, in a stable order. Reservations show as holds, not posted earnings or spend, and a correction links to the original entry instead of rewriting it. An advertising charge is visible to the buyer; a seller sees its gross, serving fee and net.

## Other command groups

- [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)
- [Device health](https://screenrig.ai/docs/cli/device.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)
