mirror of
https://github.com/screenci/screenci.git
synced 2026-09-19 08:57:46 +08:00
4cbdbc47f3
One source model: the scripts live wherever the agent ran, ScreenCI keeps a snapshot uploaded with every preview and export (opt out with uploadSources: false). `screenci setup <code>` uses an existing workspace as is (--force replaces it with the snapshot), pulls the snapshot into an absent one, or scaffolds a new project. The repository clone under .screenci/repo is read-only context; the workspace never lives in it. Removed: `screenci merge-complete`, .screenci/pending-merge.json, the merge setup-code kind, sourceMode/sourcesUnmerged in the exchange, SCREENCI_UPLOAD_SOURCES, stripIslandProjectId, and the clone-workspace and merge-prepared outcomes. No `start` alias: breaking change on purpose. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
996 lines
38 KiB
Plaintext
996 lines
38 KiB
Plaintext
# CLI
|
|
|
|
import { Tabs, TabItem } from '@astrojs/starlight/components'
|
|
|
|
The `screenci` CLI keeps the workflow small: initialize a project, iterate
|
|
locally with `screenci test`, refine videos with `screenci preview` and the web
|
|
editor, export the finished videos with `screenci export`, and manage public
|
|
delivery when needed. Run
|
|
commands from inside your `screenci/` project directory. Most commands resolve
|
|
`screenci.config.ts` from the current directory unless you pass
|
|
`--config <path>`.
|
|
|
|
## Command overview
|
|
|
|
| Command | Purpose |
|
|
| --------------------------------- | ------------------------------------------------------------------------------ |
|
|
| `screenci setup <code>` | Set up a workspace from a setup code created in the web app |
|
|
| `screenci context` | Print the organisation's AI context for this project |
|
|
| `screenci login [url]` | Sign in to your own app once and reuse that session in every recording |
|
|
| `screenci logout` | Forget the signed-in session saved on this machine |
|
|
| `screenci init [name]` | Scaffold a ScreenCI project |
|
|
| `screenci ci-workflow` | Write the GitHub Actions workflow that records the workspace from CI |
|
|
| `screenci test [playwrightArgs]` | Run `.screenci.ts` files locally without final recording |
|
|
| `screenci preview [pattern]` | Record live previews and print their links |
|
|
| `screenci export [patterns...]` | Produce finished videos: re-record every requested video, render, and download |
|
|
| `screenci info` | Print the last record run's URLs and render status |
|
|
| `screenci make-public <videoId>` | Enable public delivery for a video |
|
|
| `screenci make-private <videoId>` | Disable public delivery for a video |
|
|
| `screenci delete <videoId>` | Permanently delete a video and its renders |
|
|
|
|
## `screenci setup <code>`
|
|
|
|
The entry point of the [web-app flow](/docs/make-videos). The
|
|
**Add project**, **Add video**, **Add screenshot**, **Edit**, **Add a
|
|
language**, **Re-record** / **Record all**, and **Add to CI** buttons in the
|
|
app produce a prompt that carries a one-time setup code and points the agent
|
|
at the brief for that button (`screenci.com/add-project.md`,
|
|
`/add-video.md`, `/add-screenshot.md`, `/edit-video.md`, `/add-language.md`,
|
|
`/record-video.md`, or `/add-to-ci.md`); the coding agent runs the command in
|
|
the repository of the app to record, or in an empty folder:
|
|
|
|
```bash
|
|
npx screenci@latest setup SC-7K3Q-M9XA
|
|
```
|
|
|
|
It runs without a config file (there may be no workspace yet) and does the
|
|
following:
|
|
|
|
1. Exchanges the code for a project-scoped `SCREENCI_SECRET` and writes it
|
|
into the workspace's env file. The secret only addresses that project. A
|
|
code belongs to the first machine that exchanges it (rerunning there
|
|
resumes it until a run lands; other machines are refused) and expires 24
|
|
hours after it was created.
|
|
2. Reads the organisation's [AI context](/docs/guides/ai-context) (with the
|
|
project's overrides) and locates the repository: the current checkout when
|
|
its `origin` is the configured repository or when it already holds a
|
|
`screenci/` workspace named after the project (a fork, or a repository
|
|
whose URL nobody told ScreenCI), else a shallow clone in `.screenci/repo`
|
|
(refreshed when it exists). The clone is read-only context for the agent
|
|
(routes, components, starting the app); the workspace never lives in it. A
|
|
failed clone is reported and the command continues when the site answers.
|
|
3. Prepares the workspace: `screenci/` inside the repository when the command
|
|
runs inside it and one exists there, else `./screenci`. The local
|
|
workspace is the source of truth; ScreenCI only holds a snapshot of it
|
|
(uploaded with every `preview` and `export`, see
|
|
[Source sync](#source-sync)).
|
|
- **Absent, new project:** scaffolds the workspace like `init --yes`
|
|
(agent skills on, no GitHub workflow) and writes `projectId` into
|
|
`screenci.config.ts`.
|
|
- **Absent, existing project with a snapshot:** pulls the project's
|
|
latest uploaded sources, installs dependencies and the Playwright
|
|
browser, and installs the agent skills at the repository root. Binary
|
|
media is not pulled; recordings reuse the project's uploaded assets.
|
|
- **Absent, existing project without a snapshot:** scaffolds a fresh
|
|
workspace for it. A code that addresses one video (Edit, Add a
|
|
language, Re-record of one video) refuses instead: its script is only
|
|
in the repository, so run the command there or pass `--dir`.
|
|
- **Present, same `projectId`, or no `projectId` and the same project
|
|
name (a workspace made by `screenci init`):** used as is. Nothing is
|
|
pulled; `--force` replaces it with the snapshot instead.
|
|
- **Present, another project:** refuses; use `--dir`.
|
|
- **Record code:** nothing is changed; the brief names the script (for
|
|
one video) and says whether a pipeline already records the project, in
|
|
which case the agent triggers it instead of recording locally.
|
|
- **CI code:** mints a CI key (no person behind it, so its uploads show as
|
|
"CI"), needs the repository (the one the command runs in, or the clone),
|
|
uses its `screenci/` workspace (pulling the snapshot into it when the
|
|
repository has none yet, for the agent to commit together with the
|
|
pipeline), lists the CI providers whose files the repository has
|
|
(`.github/workflows`, `.gitlab-ci.yml`, `.circleci/config.yml`,
|
|
`.buildkite`, `bitbucket-pipelines.yml`, `Jenkinsfile`,
|
|
`azure-pipelines.yml`), and prints a brief that stores the key in the
|
|
provider's secret store, adds the pipeline
|
|
([`ci-workflow`](#screenci-ci-workflow) for GitHub Actions, the
|
|
[CI setup templates](/docs/ci-setup#other-providers) elsewhere), and
|
|
triggers the first run. The site is not probed.
|
|
4. Looks for a signed-in session on this machine
|
|
(`.screenci/auth/default.json`, saved by [`login`](#screenci-login)) and
|
|
reports it in the brief. Nothing about your own product's credentials comes
|
|
from, or goes to, ScreenCI.
|
|
5. Probes the site (the prompt's app URL, else the context's site URL). When
|
|
nothing answers and the agent may not start the app, the brief says
|
|
**STOP** and the command exits with code 2; see
|
|
[Running the app locally](/docs/guides/ai-context#running-the-app-locally).
|
|
6. Prints a brief for the agent (the task, the repository, the site, how to
|
|
sign in, the team's notes, which script to edit, the commands to run)
|
|
followed by one machine-readable JSON line (`{"status":"ready", ...}`, or
|
|
`"stopped"` with a `stop` object).
|
|
|
|
Options:
|
|
|
|
- `--name <projectName>` names a new project. Precedence: this flag, then the
|
|
name typed in the web dialog, then the current folder name.
|
|
- `--dir <path>` uses another workspace folder than `./screenci`.
|
|
- `--force` replaces an existing workspace of this project with the snapshot
|
|
ScreenCI holds (local files that differ are overwritten and listed).
|
|
- `--package-manager <npm|pnpm|yarn>` overrides the auto-detected manager.
|
|
- `--agent <name>` targets a specific coding agent for the skills install.
|
|
- `--skip-site-check` records even when the site does not answer.
|
|
- `--no-clone` never clones the repository when running outside it.
|
|
- `-v, --verbose` prints underlying command output.
|
|
|
|
After `setup`, the usual commands run from inside the workspace: `test`,
|
|
`preview`, `export`. They upload the workspace's text sources (see
|
|
[Source sync](#source-sync)) and report the finished run, which is what makes
|
|
the originating browser tab open the result. When the workspace lives in a
|
|
repository, the agent commits its change on a branch; that is the whole of
|
|
"keeping the videos in the repository".
|
|
|
|
## `screenci context`
|
|
|
|
Prints the organisation's [AI context](/docs/guides/ai-context) as resolved
|
|
for the workspace's project (repository URL, site URL, whether the agent may
|
|
start the app, whether the site needs a sign-in, the team's notes), whether a
|
|
signed-in session is saved on this machine, the
|
|
[branding](/docs/guides/branding) new videos start from, and one
|
|
JSON line (with a `branding` key). When the branding voice is cloned from a
|
|
sample, the sample is saved as `branding/<file>` in the workspace and the JSON
|
|
line names it as `brandingSamplePath`. The
|
|
[shared branding assets](/docs/guides/branding#shared-assets) are listed with
|
|
their kind and guide, saved as `branding/<name>`, and named in the JSON line as
|
|
`brandingAssetPaths`. Runs inside a workspace; uses `SCREENCI_SECRET`
|
|
from the env file. The session line is read from disk,
|
|
not from the service.
|
|
|
|
```bash
|
|
npx screenci context
|
|
npx screenci context --json # the JSON line only
|
|
```
|
|
|
|
## `screenci login`
|
|
|
|
Captures the signed-in session of **your own app**, so recordings start signed
|
|
in and your video scripts contain no sign-in steps. It opens a real browser you
|
|
sign in to yourself, which is why two-factor, single sign-on, passkeys, and
|
|
magic links all work. See [Signing In](/docs/guides/signing-in) for the whole
|
|
picture.
|
|
|
|
Run it from the `screenci/` workspace. It needs no ScreenCI account and no
|
|
secret: an address is enough.
|
|
|
|
```bash
|
|
npx screenci login https://app.example.com # opens a browser, returns at once
|
|
npx screenci login # uses use.baseURL from the config
|
|
npx screenci login --wait # blocks until you finish signing in
|
|
npx screenci login --done # finish it now, from the terminal
|
|
npx screenci login --status # what is saved, and until when
|
|
npx screenci login --cancel # close it, save nothing
|
|
```
|
|
|
|
The command returns immediately so whoever started it can tell you to sign in.
|
|
Finish by clicking **I'm signed in** on the small ScreenCI card floating over
|
|
the page (drag it if it is in the way); closing the window finishes it too.
|
|
|
|
An agent then runs `--wait`, which blocks until you do, so your click actually
|
|
reaches it. Without that the agent has ended its turn and the click tells it
|
|
nothing. `--wait` gives up after eight minutes and says the sign-in is still
|
|
going, so it fits inside an agent's command timeout and can simply be run
|
|
again. `--done` is the other direction: it finishes the sign-in right now, for
|
|
when you say you are done rather than clicking.
|
|
|
|
Options:
|
|
|
|
- `--profile <name>` names the session, for a video that needs a second role.
|
|
Pick it for a run with `SCREENCI_AUTH_PROFILE=<name>`.
|
|
- `--timeout <minutes>` closes the browser by itself after this long
|
|
(default 30).
|
|
- `-c, --config <path>` points at another `screenci.config.ts`.
|
|
|
|
The session is written to `.screenci/auth/<profile>.json`, owner-readable only
|
|
and gitignored, and `screenci.config.ts` picks it up automatically. It never
|
|
leaves the machine: ScreenCI stores no credential and no session for your app.
|
|
Nothing prints its contents, `--status` included.
|
|
|
|
On a machine with no display (a server, a container, CI) the command refuses
|
|
and points at [CI Setup](/docs/ci-setup), which is where an unattended session
|
|
comes from.
|
|
|
|
## `screenci logout`
|
|
|
|
Forgets the saved session on this machine.
|
|
|
|
```bash
|
|
npx screenci logout
|
|
npx screenci logout --profile admin
|
|
```
|
|
|
|
## `screenci init`
|
|
|
|
Create a new ScreenCI project in the current directory:
|
|
|
|
<Tabs syncKey="package-manager">
|
|
<TabItem label="npm">
|
|
|
|
```bash
|
|
npm init screenci@latest
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem label="pnpm">
|
|
|
|
```bash
|
|
pnpm create screenci
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem label="yarn">
|
|
|
|
```bash
|
|
yarn create screenci
|
|
```
|
|
|
|
</TabItem>
|
|
</Tabs>
|
|
|
|
The project name defaults to the repository root directory name.
|
|
|
|
### Connecting to an existing account
|
|
|
|
No account or secret is needed to scaffold, record, or preview: without one,
|
|
`preview` uploads under a local, anonymous trial session and prints the web
|
|
preview link, then you sign up to keep it. Recording an anonymous trial agrees
|
|
to the [Terms](https://screenci.com/legal/tos), which the CLI prints before it
|
|
starts. Exporting requires an account with an active paid subscription.
|
|
|
|
To connect the project to an account you already have, pass your
|
|
`SCREENCI_SECRET` (from your secrets page) as `init`'s positional argument, and
|
|
it writes the secret straight into `screenci/.env`:
|
|
|
|
```bash
|
|
npm init screenci@latest PASTE_YOUR_SCREENCI_SECRET_HERE
|
|
```
|
|
|
|
You can also skip this and copy `SCREENCI_SECRET` into `screenci/.env` by hand
|
|
at any point before recording.
|
|
|
|
When using `npm init`, pass extra initializer flags after `--`:
|
|
|
|
```bash
|
|
npm init screenci@latest -- --yes --package-manager pnpm
|
|
npm init screenci@latest -- --yes --package-manager yarn
|
|
```
|
|
|
|
The package manager is auto-detected from the `npm_config_user_agent` environment
|
|
variable (set automatically when you run `pnpm create` or `yarn create`), lockfile
|
|
presence (`pnpm-lock.yaml`, `yarn.lock`), or the `packageManager` field in
|
|
`package.json`. Use `--package-manager` to override.
|
|
|
|
To keep setup fast, `init` only prompts for the choices that genuinely vary:
|
|
the project name and whether to install AI agent skills (the ScreenCI skill
|
|
plus `playwright-cli`). Everything else is applied at a sensible default and
|
|
can be steered with a flag. `init` adds no CI pipeline: recording from CI is
|
|
a separate step, **Add to CI** in the web app or
|
|
[`ci-workflow`](#screenci-ci-workflow).
|
|
|
|
Common options:
|
|
|
|
- `-y, --yes` accepts all defaults and skips every prompt
|
|
- `--package-manager <npm|pnpm|yarn>` overrides auto-detected package manager
|
|
- `--agent <name>` passes an agent name to the selected skills install command
|
|
- `-v, --verbose` prints underlying command output
|
|
|
|
Flags to override an auto-applied default without going interactive:
|
|
|
|
- `--github-workflow` also writes the GitHub Actions workflow
|
|
(`.github/workflows/screenci.yaml`), the same file `ci-workflow` writes
|
|
- `--no-skills` skips both AI agent skills (and their prompt)
|
|
- `--no-playwright-cli` keeps the ScreenCI skill but drops `playwright-cli`
|
|
(the skill and the `@playwright/cli` dev dependency)
|
|
- `--no-react` skips React overlay support (react/react-dom and JSX)
|
|
- `--no-playwright-browsers` skips installing the Chromium shell
|
|
- `--playwright-os-deps` installs Playwright operating system dependencies
|
|
(off by default because it may require sudo)
|
|
|
|
Applied defaults: install dependencies, add React overlay support, install
|
|
the Chromium shell, skip OS dependency installation, install the AI agent
|
|
skills (ScreenCI + `playwright-cli`), and write no CI workflow.
|
|
|
|
The AI skills install is best effort: if it fails (for example on an older
|
|
Node.js runtime), `init` warns, prints the command to retry it later, and
|
|
continues with the rest of the setup.
|
|
|
|
Use this command in [Manual Setup & First Video](/docs/manual-setup).
|
|
|
|
## `screenci ci-workflow`
|
|
|
|
Writes the GitHub Actions workflow that records the repository's `screenci/`
|
|
workspace from CI, at `.github/workflows/screenci.yaml` in the repository
|
|
root. Run it from the repository root (or inside the workspace, or with
|
|
`--config <path>`):
|
|
|
|
```bash
|
|
npx screenci ci-workflow
|
|
```
|
|
|
|
The workflow is keyed to the package manager the workspace uses (from its
|
|
lockfile; `--package-manager <npm|pnpm|yarn>` overrides it). An existing
|
|
file is never overwritten unless `--force` is given. The **Add to CI** brief
|
|
runs this for GitHub repositories; other providers follow the templates in
|
|
[CI Setup](/docs/ci-setup#other-providers). The secret still has to be
|
|
stored in the repository's secrets: see [Required secret](/docs/ci-setup#required-secret).
|
|
|
|
## `screenci test [playwrightArgs...]`
|
|
|
|
Run videos locally without the final recording pipeline:
|
|
|
|
<Tabs syncKey="package-manager">
|
|
<TabItem label="npm">
|
|
|
|
```bash
|
|
npx screenci test
|
|
npx screenci test recordings/onboarding.screenci.ts
|
|
npx screenci test --grep "billing"
|
|
npx screenci test --ui
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem label="pnpm">
|
|
|
|
```bash
|
|
pnpm exec screenci test
|
|
pnpm exec screenci test recordings/onboarding.screenci.ts
|
|
pnpm exec screenci test --grep "billing"
|
|
pnpm exec screenci test --ui
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem label="yarn">
|
|
|
|
```bash
|
|
yarn screenci test
|
|
yarn screenci test recordings/onboarding.screenci.ts
|
|
yarn screenci test --grep "billing"
|
|
yarn screenci test --ui
|
|
```
|
|
|
|
</TabItem>
|
|
</Tabs>
|
|
|
|
Use this during normal authoring. Most trailing arguments are forwarded to
|
|
Playwright.
|
|
|
|
Plain `screenci test` disables recording-style waits so authoring runs stay
|
|
fast. That includes ScreenCI cursor/camera pauses and
|
|
`page.waitForTimeout(...)`, which is collapsed to `0ms`. Use Playwright locator
|
|
or load-state waits for real application readiness. Use `--mock-record` when you
|
|
need to preview the same pacing that a real recording will capture.
|
|
|
|
Common Playwright examples that also work here:
|
|
|
|
<Tabs syncKey="package-manager">
|
|
<TabItem label="npm">
|
|
|
|
```bash
|
|
npx screenci test --project=chromium
|
|
npx screenci test --grep "onboarding"
|
|
npx screenci test --ui
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem label="pnpm">
|
|
|
|
```bash
|
|
pnpm exec screenci test --project=chromium
|
|
pnpm exec screenci test --grep "onboarding"
|
|
pnpm exec screenci test --ui
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem label="yarn">
|
|
|
|
```bash
|
|
yarn screenci test --project=chromium
|
|
yarn screenci test --grep "onboarding"
|
|
yarn screenci test --ui
|
|
```
|
|
|
|
</TabItem>
|
|
</Tabs>
|
|
|
|
### `--mock-record`
|
|
|
|
<Tabs syncKey="package-manager">
|
|
<TabItem label="npm">
|
|
|
|
```bash
|
|
npx screenci test --mock-record
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem label="pnpm">
|
|
|
|
```bash
|
|
pnpm exec screenci test --mock-record
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem label="yarn">
|
|
|
|
```bash
|
|
yarn screenci test --mock-record
|
|
```
|
|
|
|
</TabItem>
|
|
</Tabs>
|
|
|
|
This keeps recording-like pacing enabled without starting the real recording
|
|
capture path. Use it when `test` passes but a real recording exposes timing
|
|
differences.
|
|
|
|
If you want that behavior by default for a project, set
|
|
`test.mockRecord: true` in `screenci.config.ts`.
|
|
|
|
## `screenci export [patterns...]`
|
|
|
|
Produce finished videos and download them. `export` is the one-shot command
|
|
(also the one CI runs): it pulls any queued editor edits into the sources,
|
|
re-records every requested video (sources can carry changes a hash check would
|
|
miss, so export always captures fresh footage), waits for the renders to
|
|
finish, and downloads the outputs into `./exports/`:
|
|
|
|
<Tabs syncKey="package-manager">
|
|
<TabItem label="npm">
|
|
|
|
```bash
|
|
npx screenci export
|
|
npx screenci export "Onboarding"
|
|
npx screenci export --grep "billing"
|
|
npx screenci export --languages fi,en
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem label="pnpm">
|
|
|
|
```bash
|
|
pnpm exec screenci export
|
|
pnpm exec screenci export "Onboarding"
|
|
pnpm exec screenci export --grep "billing"
|
|
pnpm exec screenci export --languages fi,en
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem label="yarn">
|
|
|
|
```bash
|
|
yarn screenci export
|
|
yarn screenci export "Onboarding"
|
|
yarn screenci export --grep "billing"
|
|
yarn screenci export --languages fi,en
|
|
```
|
|
|
|
</TabItem>
|
|
</Tabs>
|
|
|
|
Positional arguments are title patterns (multiple are OR-combined, like
|
|
`playwright test <pattern>`); with no patterns, every video is exported in
|
|
every language. Downloads are named `<title>.<lang>.mp4` (screenshots use
|
|
`.png`). The workspace's sources are uploaded first (see
|
|
[Source sync](#source-sync)).
|
|
The command polls render status every 5 seconds for up to 30 minutes
|
|
and exits `0` only when every requested video rendered and downloaded. After a
|
|
run it prints the video's page in the app: a run with exactly one rendered
|
|
pass links that video's overview page with the run preselected
|
|
(`<app>/project/<projectId>/video/<videoId>?export=<recordId>`); several
|
|
passes (several videos, or one video exported in several languages) link the
|
|
run's page (`<app>/export/<recordId>`), which links each version.
|
|
|
|
### `--languages <langs>`
|
|
|
|
Export only specific language versions of videos declared with
|
|
`video.languages([...])`. Pass a comma-separated list:
|
|
|
|
```bash
|
|
npx screenci export --languages fi
|
|
npx screenci export --languages fi,en
|
|
```
|
|
|
|
Per-language videos record and render only the requested languages, so a run
|
|
never produces more than you asked for. Videos that do not declare those
|
|
languages are skipped. A shared-mode recording (`{ mode: 'shared' }`) is a
|
|
single capture and is not split by this filter. See
|
|
[Languages](/docs/guides/languages) for the recording API.
|
|
|
|
### `-o, --output <dir>`
|
|
|
|
Directory for the downloaded files. Defaults to `exports`:
|
|
|
|
```bash
|
|
npx screenci export -o dist/videos
|
|
```
|
|
|
|
### `--no-wait`
|
|
|
|
Start the renders and exit immediately, without waiting for them or
|
|
downloading files. Use this when the finished videos are consumed from the
|
|
web (public URLs or embeds) and the run only needs to publish fresh footage:
|
|
|
|
```bash
|
|
npx screenci export --no-wait
|
|
```
|
|
|
|
The command still records, uploads, and dispatches the renders, and prints
|
|
the results URL. It exits `0` as soon as the upload succeeds; render failures
|
|
are visible on the results page, not in the exit code. Without this flag,
|
|
`export` waits for every render and exits non-zero if any of them fails.
|
|
|
|
### `--share`
|
|
|
|
Instead of downloading files, share each finished version with a permanent,
|
|
version-pinned public URL and print the URLs:
|
|
|
|
```bash
|
|
npx screenci export --share
|
|
```
|
|
|
|
The command records, renders, and waits like a normal export, then shares the
|
|
run's finished versions and prints one public URL per video and language
|
|
(plus thumbnail and subtitle URLs when they exist). A shared version keeps
|
|
serving that exact render until it is unshared or deleted from the app: it is
|
|
exempt from version retention, and the URL works even when the video's own
|
|
public URL is switched off. See
|
|
[version-pinned URLs](/docs/reference/public-delivery-api#version-pinned-urls-shared-versions)
|
|
for the URL shape and behavior.
|
|
|
|
Shared versions count against your organization's shared-version limit
|
|
(1000 by default, shown on the billing page). When the limit is reached the
|
|
remaining versions are not shared and the command exits non-zero with the
|
|
refusal message.
|
|
|
|
`--share` needs finished renders, so combining it with `--no-wait` is an
|
|
error. It exits `0` only when every requested render finished and was shared.
|
|
|
|
### `--select`
|
|
|
|
Make each finished render the served version of its language:
|
|
|
|
```bash
|
|
npx screenci export --select
|
|
```
|
|
|
|
Without `--select`, an export never changes which version a video serves: the
|
|
public URL (and any video that embeds this one as a dependency) keeps pointing
|
|
at the version selected in the app until someone selects a newer one. With
|
|
`--select`, every render this run produces becomes the selected version of its
|
|
language as soon as it finishes, so a CI export updates the public URL on its
|
|
own. Selecting also re-renders dependent videos. Nothing is selected for
|
|
renders that fail.
|
|
|
|
The flag is never implied, in CI or elsewhere: pass it explicitly in the
|
|
workflow that should publish. The workflow `screenci init` generates shows it
|
|
on the commented export line.
|
|
|
|
### `--pr <url>`
|
|
|
|
Record for a GitHub pull request:
|
|
|
|
```bash
|
|
npx screenci export --no-wait --pr "https://github.com/acme/app/pull/42"
|
|
```
|
|
|
|
The run records and renders as usual, and the service groups the versions
|
|
under the pull request: it posts a check run and one comment with a thumbnail
|
|
and a watch link per video and language, and updates both as renders finish.
|
|
A run whose Playwright recording failed fails the check. Nothing is selected;
|
|
approving the previews in the app and merging the pull request makes exactly
|
|
those versions the served ones. `--pr` cannot combine with `--select` or
|
|
`--remote`. The generated workflow passes
|
|
`github.event.pull_request.html_url` on its pull request trigger. See
|
|
[Pull request previews](/docs/pr-previews).
|
|
|
|
### `--force`
|
|
|
|
Deprecated no-op, kept so existing scripts do not break: `export` always
|
|
re-records every requested video.
|
|
|
|
Behavior:
|
|
|
|
- enables recording timing for every requested video
|
|
- writes local output into `.screenci/`
|
|
- holds a per-project run lock at `.screenci/.record.lock` while recording and uploading. If another `screenci preview` or `screenci export` run is already active, the second run exits non-zero instead of sharing the same `.screenci` output. Stale locks are reclaimed automatically when the pid is gone or the lock is older than the maximum run TTL
|
|
- requires an account with an active paid subscription: without a `SCREENCI_SECRET`, `export` refuses before recording and prints a sign-up link (the anonymous trial is preview-only; use `screenci preview` for the free live preview, see [Anonymous Trial](/docs/guides/anonymous-trial)). Once you have signed up, re-running `export` in the same folder links your account automatically. Set `SCREENCI_SECRET` from the project `.env`, the environment, or by running `init` with it
|
|
- uploads only the recordings requested by this run (for example the videos matched by patterns, `--grep`, or `--languages`), with or without `SCREENCI_SECRET`
|
|
- exits non-zero unless every requested video rendered and downloaded. If a requested video is missing its `recording.mp4` or another failure occurs, `export` does not save `.screenci/last-record.json` and does not print a success URL for unrelated output
|
|
- prints any informational notices returned by the service in cyan after upload (occasional, non-error status messages such as maintenance or timing notes). These never affect the exit code
|
|
- new accounts choose a plan before exporting: exports need an active Starter, Pro, or Business subscription. Higher tiers raise export and active-video limits and unlock multiple languages
|
|
|
|
Relevant options:
|
|
|
|
- `-c, --config <path>`
|
|
- `-v, --verbose`
|
|
- `-g, --grep <pattern>` (same filter as Playwright's `--grep`)
|
|
|
|
Important restriction:
|
|
|
|
- `--retries` is not supported because ScreenCI forces retries to `0`
|
|
|
|
## `screenci preview [pattern]`
|
|
|
|
Records live previews and prints their links: it re-records and uploads the
|
|
live preview of every matched video (all declared videos when no pattern is
|
|
given), prints the link, and exits. A preview always records fresh footage;
|
|
there is no freshness skip. A run with exactly one
|
|
recording pass prints that video's overview page
|
|
(`<app>/project/<projectId>/video/<videoId>`); several passes (several
|
|
videos, or one video recorded in several languages) print the run listing
|
|
page (`<app>/preview/<recordId>`), which links each video and language.
|
|
|
|
```bash
|
|
screenci preview
|
|
```
|
|
|
|
Filter videos by passing a title pattern, the same way
|
|
`playwright test <pattern>` does; `--grep` does the same and takes precedence
|
|
when both are given.
|
|
|
|
```bash
|
|
screenci preview "Auto-zoom"
|
|
```
|
|
|
|
Right before recording a preview, the CLI sends a best-effort "preview
|
|
recording started" notice to the backend, so an open web preview page shows a
|
|
live "Recording preview..." indicator and refreshes automatically when the
|
|
new preview lands.
|
|
|
|
### Source sync
|
|
|
|
`preview` and `export` upload the island's text sources right before
|
|
recording (unless `screenci.config.ts` sets `uploadSources: false`), and
|
|
report the finished run afterwards. That snapshot is what the video page
|
|
shows under "Sources" and what `screenci setup` pulls onto a machine without a
|
|
workspace; the local workspace stays the source of truth.
|
|
|
|
- The bundle holds `screenci.config.ts`, `package.json`, `tsconfig.json`,
|
|
`.prettierrc`, `.gitignore`, `README.md`, the package-manager workspace
|
|
files, and every text file under `recordings/`. Env files, lockfiles,
|
|
`node_modules`, `.screenci`, `exports`, and binary media are never included.
|
|
Files over 256 KB and anything past 2 MB in total are skipped with a warning.
|
|
- The bundle is content addressed: an unchanged island is not re-uploaded.
|
|
Its canonical form is `{ "files": [{ "path", "content" }] }` sorted by path
|
|
(plain code-unit order), hashed with SHA-256 over the JSON text.
|
|
- Both steps are best effort. A failed upload warns and the recording still
|
|
runs (the next run retries); the run report never fails a command.
|
|
- Anonymous previews (no `SCREENCI_SECRET`) never sync sources.
|
|
- A project-scoped secret that pins a different project than the island's
|
|
`projectId` (an env file copied from another workspace) stops the run
|
|
before recording, with the pinned project's name in the message.
|
|
|
|
A run prints one line per phase: the record announcement, the upload results,
|
|
one line per video whose editor-uploaded media (overlays, audio, narration
|
|
audio, cloned voices) shapes the render, and the video link:
|
|
|
|
```
|
|
Recording: Search for Alfa Forni Moderno 2
|
|
...
|
|
✔ Uploaded "Search for Alfa Forni Moderno 2 [en]"
|
|
✔ Uploaded "Search for Alfa Forni Moderno 2 [et]"
|
|
Editor-uploaded media for "Search for Alfa Forni Moderno 2" applies at render time; recordings always run from code.
|
|
|
|
Open the live preview for "Search for Alfa Forni Moderno 2" at:
|
|
<app>/project/<projectId>/video/<videoId>
|
|
```
|
|
|
|
Options:
|
|
|
|
- `-c, --config <path>`: path to the ScreenCI config file.
|
|
- `-g, --grep <pattern>`: only manage videos whose title matches this pattern
|
|
(the same filter as Playwright's `--grep`, and the same as a positional
|
|
pattern above). The record pass is limited to the matching videos.
|
|
- `-v, --verbose`: verbose output.
|
|
|
|
Setup (with an account): none beyond `SCREENCI_SECRET`. That secret is the
|
|
only credential ScreenCI needs; there is nothing else to paste.
|
|
|
|
Without an account, no setup is needed either: `screenci preview` runs under a
|
|
local, anonymous trial session (see
|
|
[Anonymous Trial](/docs/guides/anonymous-trial)). Signing up claims the trial,
|
|
and the next `screenci` command picks up your new `SCREENCI_SECRET` (written
|
|
into `screenci/.env`).
|
|
|
|
## `screenci info`
|
|
|
|
<Tabs syncKey="package-manager">
|
|
<TabItem label="npm">
|
|
|
|
```bash
|
|
npx screenci info
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem label="pnpm">
|
|
|
|
```bash
|
|
pnpm exec screenci info
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem label="yarn">
|
|
|
|
```bash
|
|
yarn screenci info
|
|
```
|
|
|
|
</TabItem>
|
|
</Tabs>
|
|
|
|
Lists **every video in the project** with its public URLs as JSON, keyed by
|
|
video name and language code. It is where you get the remote `videoId` for
|
|
`make-public`, `make-private`, and `delete`.
|
|
|
|
When this machine has recorded a successful run, `info` also reports that run.
|
|
Each `screenci export` upload stores its unique record id in
|
|
`.screenci/last-record.json`; `info` then attaches, **only to the videos
|
|
produced by that run**, a per-language `latestRecord` with the run's render
|
|
status and its record-pinned URLs, plus a `latestRecordId` on the video. Videos
|
|
that were not part of the run are still listed, with `static` URLs only. This is
|
|
the command to use in CI to gate on rendering or grab links right after an
|
|
export.
|
|
|
|
```json
|
|
{
|
|
"projectName": "My Product",
|
|
"videos": {
|
|
"Onboarding": {
|
|
"videoId": "kh74…",
|
|
"latestRecordId": "5f1c…",
|
|
"isPublic": true,
|
|
"languages": {
|
|
"en": {
|
|
"static": {
|
|
"video": "https://api.screenci.com/public/kh74…/en/video",
|
|
"thumbnail": "https://api.screenci.com/public/kh74…/en/thumbnail",
|
|
"subtitle": "https://api.screenci.com/public/kh74…/en/subtitle",
|
|
"screenshot": "https://api.screenci.com/public/kh74…/en/screenshot"
|
|
},
|
|
"download": {
|
|
"video": "https://api.screenci.com/cli/download/kh74…/en/video",
|
|
"thumbnail": "https://api.screenci.com/cli/download/kh74…/en/thumbnail",
|
|
"subtitle": "https://api.screenci.com/cli/download/kh74…/en/subtitle",
|
|
"screenshot": "https://api.screenci.com/cli/download/kh74…/en/screenshot"
|
|
},
|
|
"latestRecord": {
|
|
"status": "finished",
|
|
"video": "https://api.screenci.com/public/kh74…/records/5f1c…/en/video",
|
|
"thumbnail": "https://api.screenci.com/public/kh74…/records/5f1c…/en/thumbnail",
|
|
"subtitle": "https://api.screenci.com/public/kh74…/records/5f1c…/en/subtitle",
|
|
"screenshot": "https://api.screenci.com/public/kh74…/records/5f1c…/en/screenshot",
|
|
"download": {
|
|
"video": "https://api.screenci.com/cli/download/kh74…/records/5f1c…/en/video",
|
|
"thumbnail": "https://api.screenci.com/cli/download/kh74…/records/5f1c…/en/thumbnail",
|
|
"subtitle": "https://api.screenci.com/cli/download/kh74…/records/5f1c…/en/subtitle",
|
|
"screenshot": "https://api.screenci.com/cli/download/kh74…/records/5f1c…/en/screenshot"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
Each language exposes up to three URL sets:
|
|
|
|
- `static`: stable, public URLs that always follow the currently selected
|
|
version
|
|
- `download`: authenticated download URLs for the selected version (see below)
|
|
- `latestRecord`: this run's render status plus public URLs pinned to it via a
|
|
`records/<recordId>` path segment (an immutable contract: the exact run, or
|
|
`404`, see
|
|
[resolution rules](/docs/reference/public-delivery-api#resolution-rules)). Once
|
|
finished, it also carries record-pinned `download` URLs.
|
|
|
|
Each URL set carries one entry per asset: `video`, `thumbnail`, `subtitle`, and
|
|
`screenshot`. A version is either a video or a screenshot, never both, so use the
|
|
`video` asset for video recordings and the `screenshot` asset for screenshot
|
|
recordings: the asset that does not match the version's type `404`s when fetched.
|
|
|
|
`static` is `null` for videos without public delivery enabled. `latestRecord`
|
|
carries the render status even for private videos, but its public URLs are then
|
|
`null`.
|
|
|
|
The `download` URLs are **private**: they require your `X-ScreenCI-Secret`
|
|
header, so they are not embeddable, and they work even for private videos. Use
|
|
them to archive a render permanently, before older versions are pruned (see
|
|
[Keep a render forever](/docs/reference/public-delivery-api#keep-a-render-forever)):
|
|
|
|
```bash
|
|
curl -H "X-ScreenCI-Secret: $SCREENCI_SECRET" \
|
|
"https://api.screenci.com/cli/download/kh74…/records/5f1c…/en/video" \
|
|
-o video.mp4
|
|
```
|
|
|
|
Render status (under `latestRecord.status`) is one of:
|
|
|
|
- `finished`: a render finished and is servable
|
|
- `rendering`: a render is still in progress (or has not started)
|
|
- `failed`: a render failed and none for that language is still in progress
|
|
|
|
Because rendering happens after upload, poll `info` until each `latestRecord`
|
|
reaches `finished` (or gate your pipeline on `failed`).
|
|
|
|
**Not recorded on this machine?** If there is no `.screenci/last-record.json`
|
|
(for example a fresh checkout that has never run `screenci export`), `info` does
|
|
not fail. It simply omits `latestRecordId` and the `latestRecord` fields and
|
|
prints the project-wide listing with `static` URLs only.
|
|
|
|
## `screenci make-public <videoId>`
|
|
|
|
<Tabs syncKey="package-manager">
|
|
<TabItem label="npm">
|
|
|
|
```bash
|
|
npx screenci make-public kh74…
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem label="pnpm">
|
|
|
|
```bash
|
|
pnpm exec screenci make-public kh74…
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem label="yarn">
|
|
|
|
```bash
|
|
yarn screenci make-public kh74…
|
|
```
|
|
|
|
</TabItem>
|
|
</Tabs>
|
|
|
|
Enables public delivery for a video. Get the ID from `screenci info`.
|
|
|
|
When you make a video public, ScreenCI starts it in the same mode as the app:
|
|
|
|
- public delivery is enabled for the video
|
|
- the latest finished render for each language becomes the active public output
|
|
(later exports change it only with `export --select` or a selection in the app)
|
|
|
|
That means `make-public` is the CLI equivalent of turning on **Enable public
|
|
URL** in the dashboard.
|
|
|
|
## `screenci make-private <videoId>`
|
|
|
|
<Tabs syncKey="package-manager">
|
|
<TabItem label="npm">
|
|
|
|
```bash
|
|
npx screenci make-private kh74…
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem label="pnpm">
|
|
|
|
```bash
|
|
pnpm exec screenci make-private kh74…
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem label="yarn">
|
|
|
|
```bash
|
|
yarn screenci make-private kh74…
|
|
```
|
|
|
|
</TabItem>
|
|
</Tabs>
|
|
|
|
Disables public delivery for a video.
|
|
|
|
This is the CLI equivalent of turning off **Enable public URL** in the
|
|
dashboard.
|
|
|
|
## `screenci delete <videoId>`
|
|
|
|
<Tabs syncKey="package-manager">
|
|
<TabItem label="npm">
|
|
|
|
```bash
|
|
npx screenci delete kh74…
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem label="pnpm">
|
|
|
|
```bash
|
|
pnpm exec screenci delete kh74…
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem label="yarn">
|
|
|
|
```bash
|
|
yarn screenci delete kh74…
|
|
```
|
|
|
|
</TabItem>
|
|
</Tabs>
|
|
|
|
Permanently deletes a video and all of its renders. Use the same `videoId` that
|
|
`make-public` and `make-private` accept (copy it from `screenci info`).
|
|
|
|
This is irreversible, so the command prints the video's name and asks you to
|
|
confirm before deleting. Pass `-y` (or `--yes`) to skip the prompt in CI or
|
|
scripts:
|
|
|
|
```bash
|
|
npx screenci delete kh74… --yes
|
|
```
|
|
|
|
You can only delete videos that belong to your own project's organization.
|
|
|
|
## What the CLI does not do
|
|
|
|
The CLI currently covers:
|
|
|
|
- workspace setup from a web-app setup code with `setup`
|
|
- reading the organisation's AI context with `context`
|
|
- signing in to your own app with `login` and `logout`
|
|
- project scaffolding with `init`
|
|
- project auth setup (handled automatically on first `export`)
|
|
- local iteration with `test`
|
|
- live previews and editing sessions with `preview`
|
|
- finished videos with `export`
|
|
- per-run URLs and render status with `info`
|
|
- public visibility changes with `make-public` and `make-private`
|
|
- permanent video deletion with `delete`
|
|
|
|
Version selection happens in two places:
|
|
|
|
- `screenci export --select` selects each render this run produces as it
|
|
finishes
|
|
- in the app, open a language section and choose the version to mark as
|
|
**Selected**
|
|
|
|
A selected version that is served at a public URL cannot be deleted until
|
|
another version is selected or the public URL is switched off.
|
|
|
|
## Shared environment and config behavior
|
|
|
|
These commands support `--config <path>`:
|
|
|
|
- `context`
|
|
- `login`
|
|
- `logout`
|
|
- `test`
|
|
- `preview`
|
|
- `export`
|
|
- `info`
|
|
- `make-public`
|
|
- `make-private`
|
|
- `delete`
|
|
|
|
`SCREENCI_SECRET` is used for:
|
|
|
|
- auth bootstrap and persistence
|
|
- uploads
|
|
- per-run URLs and render status (`info`)
|
|
- public delivery changes
|
|
- video deletion (`delete`)
|
|
|
|
If `envFile` is configured in `screenci.config.ts`, the CLI loads it
|
|
automatically. Otherwise it falls back to the project `.env`. The CLI resolves
|
|
`envFile` by evaluating the config the same way Playwright does, so a dynamic
|
|
value like `envFile: isLocal ? '.env.local' : '.env'` picks the right file at
|
|
run time.
|
|
|
|
That env file is the recommended place to keep `SCREENCI_SECRET` and other
|
|
runtime variables your setup needs. Your ElevenLabs key is not kept here: add it
|
|
on the Branding page in the app instead (see
|
|
[Narration](/docs/guides/narration#elevenlabs-voices)).
|
|
|
|
## Related pages
|
|
|
|
- [Configuration](/docs/reference/configuration) for `screenci.config.ts`.
|