screenci 0.0.78 → 0.0.80

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -30,20 +30,20 @@ package.json
30
30
  ## Notes
31
31
 
32
32
  - `init` can be run at any time, but it is non-destructive and will not re-initialize an existing project. If the project is already initialized (a `screenci/` directory already exists), it fails on purpose and exits with an error like `screenci/ already exists`. That is expected. Do not delete the existing project to force a re-init: continue working with the project that is already there.
33
- - On a fresh init, the command also prints a sign-in link (valid for 24 hours) and caches it in `screenci/.screenci/link-session.json`. Right after init, run `screenci login` (see below): it opens this link in the user's browser and prints it, without waiting, so sign-in can start while the video is being built. Sign-in only needs to be completed before the final recording, and a later `screenci record` reuses this same link.
34
- - Prefer `--yes` for non-interactive setup. Without it, the command prompts for setup choices and defaults the project name to the current directory name when none is provided.
33
+ - `init` accepts a one-time setup token as its first positional argument (it looks like `otp_...`, copied from the Get Started or secrets page). With a token, init exchanges it for the org's `SCREENCI_SECRET` and writes it into `screenci/.env`, so `record` uploads immediately on the free tier. The token is single-use and short-lived; a used or expired token falls back to the manual path without failing the scaffold.
34
+ - Without a token, init tells you to copy `SCREENCI_SECRET` from the secrets page into `screenci/.env` before the first record. There is no browser sign-in. A fresh token (and a ready-to-run command) is always available on the Get Started page, including for adding a second project; the org secret is shared across projects.
35
+ - Prefer `--yes` for non-interactive setup. Without it, the command prompts for setup choices and defaults the project name to the current directory name when none is provided. A positional that looks like a setup token is treated as the token, not the project name.
35
36
  - The name is used as the ScreenCI project display name. Files are always created in the current directory.
36
37
  - `--yes` accepts the defaults.
37
38
  - `--agent <name>` is passed to the selected skills install command.
38
39
  - `--verbose` shows more setup output.
39
- - `record` bootstraps `SCREENCI_SECRET` on first run if it is missing.
40
+ - `record` requires `SCREENCI_SECRET`; it does not bootstrap it.
40
41
  - `record` uses local Playwright.
41
42
 
42
43
  ## Typical Flow
43
44
 
44
45
  ```bash
45
- npm init screenci "My Project" -- --yes
46
- npx screenci login # open the sign-in link in the browser (returns immediately)
47
- npx screenci test # verify the video works while the user signs in
48
- npx screenci record # capture the final recording (waits for sign-in if pending)
46
+ npm init screenci@latest otp_your_token -- --yes # connects the project (writes SCREENCI_SECRET)
47
+ npx screenci test # verify the video works
48
+ npx screenci record # capture the final recording and upload
49
49
  ```
@@ -19,19 +19,20 @@ npx screenci record -c screenci.config.ts
19
19
  - Saves output under `.screenci/<video-name>/`
20
20
  - Produces at least `recording.mp4` and `data.json`
21
21
 
22
- ## Sign In Early
22
+ ## Connect Before Recording
23
23
 
24
- Sign-in only blocks the final recording, not authoring or testing. Get it going up front: run `npx screenci login` to open the sign-in link in the user's browser (it also prints the link and returns immediately without waiting), then surface that link to the user and ask them to sign in while you build the video. The link is valid for 24 hours. For the final recording, run `npx screenci record` (no flag): off-CI it waits and records as soon as sign-in completes. Attempting it before they finish does no harm: it reprints the link, and if the timeout elapses it exits non-zero with the link still valid, so re-prompt and run again.
24
+ `record` needs `SCREENCI_SECRET`, and there is no browser sign-in. Get it in place before the final recording (it does not block authoring or testing):
25
+
26
+ - If the user has a one-time setup token (`otp_...`), run `npm init screenci@latest <token> -- --yes`; init writes `SCREENCI_SECRET` into `screenci/.env`. A fresh token is on the user's Get Started page.
27
+ - Otherwise ask the user to copy `SCREENCI_SECRET` from their secrets page into `screenci/.env`. The org secret is shared across projects.
25
28
 
26
29
  ## Runtime Behavior
27
30
 
28
31
  - Recording runs with local Playwright.
29
- - When `SCREENCI_SECRET` is missing, `screenci record` waits for browser sign-in by default and continues once it completes. This is the default at an interactive terminal and in a plain non-interactive session (no terminal, no CI), so an agent does not need a flag. It prints the link, polls (every 2 seconds interactively, every 5 seconds otherwise) up to a timeout (15 minutes interactively, 5 minutes otherwise), then saves the secret and records. If the timeout elapses first, it exits **non-zero** with the link still valid, so re-surface the link and rerun once signed in. Override the timeout with `SCREENCI_POLL_AUTH_TIMEOUT_MS` (milliseconds).
30
- - Under CI (`CI=true`), or with `SCREENCI_NONINTERACTIVE=1` or `--no-poll-auth`, `screenci record` does not wait: it prints the sign-in link and exits cleanly with exit code 0 without recording. A clean exit here is a handoff, not a finished recording, so do not treat exit code 0 as "recording done" when the output contains a sign-in link. Set `SCREENCI_SECRET` ahead of time (the expected CI setup) to record without an interactive sign-in.
31
- - `--poll-auth` still forces waiting and is kept for backwards compatibility, but is no longer needed off-CI where waiting is already the default.
32
- - Pending auth state is cached in `.screenci/link-session.json`, so rerunning `record` reuses the same link until it expires or completes.
32
+ - `SCREENCI_SECRET` is required (from `screenci/.env` or the environment). If it is missing, `screenci record` prints guidance (pointing at the secrets page) and exits **non-zero** without recording. Get the secret in place and rerun. This is a setup step, not a code problem.
33
+ - New accounts start on the free tier; free renders include a ScreenCI watermark, and after upload `record` prints an upgrade link that removes it.
33
34
  - Playwright arguments can be passed through after the command.
34
- - When API configuration and `SCREENCI_SECRET` are available, uploads may run after recording.
35
+ - When API configuration and `SCREENCI_SECRET` are available, uploads run after recording.
35
36
 
36
37
  ## Recommended Workflow
37
38
 
@@ -1,34 +0,0 @@
1
- import { spawn } from 'child_process';
2
- export type BrowserOpenSpec = {
3
- command: string;
4
- args: string[];
5
- };
6
- export type OpenBrowserResult = {
7
- opened: true;
8
- } | {
9
- opened: false;
10
- reason: string;
11
- };
12
- /**
13
- * Resolve the platform-specific command that opens a URL in the default
14
- * browser: `open` on macOS, `cmd /c start` on Windows, and `xdg-open`
15
- * everywhere else (Linux, BSD). The empty `""` on Windows is `start`'s window
16
- * title argument, so a quoted URL is not consumed as the title.
17
- */
18
- export declare function resolveBrowserOpenSpec(url: string, platform?: NodeJS.Platform): BrowserOpenSpec;
19
- /**
20
- * Try to open `url` in the user's default browser. Best-effort: a synchronous
21
- * spawn failure or an asynchronous launch error (e.g. `xdg-open` missing on a
22
- * minimal Linux box) resolves to `{ opened: false, reason }` instead of
23
- * throwing. A resolved `{ opened: true }` only means the launch was dispatched,
24
- * not that a browser window actually appeared, so callers still surface the
25
- * link as a fallback.
26
- *
27
- * Dependency-injected (`platform`, `spawnFn`) so tests can drive both outcomes
28
- * without a real terminal or browser.
29
- */
30
- export declare function openUrlInBrowser(url: string, options?: {
31
- platform?: NodeJS.Platform;
32
- spawnFn?: typeof spawn;
33
- }): Promise<OpenBrowserResult>;
34
- //# sourceMappingURL=openBrowser.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"openBrowser.d.ts","sourceRoot":"","sources":["../../src/openBrowser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAQrC,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,EAAE,CAAA;CACf,CAAA;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,MAAM,EAAE,IAAI,CAAA;CAAE,GAChB;IAAE,MAAM,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAErC;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,eAAe,CAQjB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE;IACP,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAA;IAC1B,OAAO,CAAC,EAAE,OAAO,KAAK,CAAA;CAClB,GACL,OAAO,CAAC,iBAAiB,CAAC,CAqC5B"}
@@ -1,62 +0,0 @@
1
- import { spawn } from 'child_process';
2
- /**
3
- * Resolve the platform-specific command that opens a URL in the default
4
- * browser: `open` on macOS, `cmd /c start` on Windows, and `xdg-open`
5
- * everywhere else (Linux, BSD). The empty `""` on Windows is `start`'s window
6
- * title argument, so a quoted URL is not consumed as the title.
7
- */
8
- export function resolveBrowserOpenSpec(url, platform = process.platform) {
9
- if (platform === 'darwin') {
10
- return { command: 'open', args: [url] };
11
- }
12
- if (platform === 'win32') {
13
- return { command: 'cmd', args: ['/c', 'start', '', url] };
14
- }
15
- return { command: 'xdg-open', args: [url] };
16
- }
17
- /**
18
- * Try to open `url` in the user's default browser. Best-effort: a synchronous
19
- * spawn failure or an asynchronous launch error (e.g. `xdg-open` missing on a
20
- * minimal Linux box) resolves to `{ opened: false, reason }` instead of
21
- * throwing. A resolved `{ opened: true }` only means the launch was dispatched,
22
- * not that a browser window actually appeared, so callers still surface the
23
- * link as a fallback.
24
- *
25
- * Dependency-injected (`platform`, `spawnFn`) so tests can drive both outcomes
26
- * without a real terminal or browser.
27
- */
28
- export async function openUrlInBrowser(url, options = {}) {
29
- const platform = options.platform ?? process.platform;
30
- const spawnFn = options.spawnFn ?? spawn;
31
- const spec = resolveBrowserOpenSpec(url, platform);
32
- let child;
33
- try {
34
- child = spawnFn(spec.command, spec.args, {
35
- stdio: 'ignore',
36
- detached: true,
37
- });
38
- }
39
- catch (err) {
40
- return {
41
- opened: false,
42
- reason: err instanceof Error ? err.message : String(err),
43
- };
44
- }
45
- // Keep an error listener attached for the child's lifetime so a late launch
46
- // error (e.g. ENOENT) is handled rather than thrown as an unhandled event.
47
- const launchError = new Promise((resolveError) => {
48
- child.on('error', resolveError);
49
- });
50
- // Detach so the parent (login) can exit without waiting on the browser.
51
- child.unref();
52
- // ENOENT and friends surface on the next tick, ahead of this setImmediate, so
53
- // a failed launch wins the race; otherwise we treat the dispatch as success.
54
- const settled = new Promise((resolveTick) => {
55
- setImmediate(() => resolveTick(null));
56
- });
57
- const result = await Promise.race([launchError, settled]);
58
- return result === null
59
- ? { opened: true }
60
- : { opened: false, reason: result.message };
61
- }
62
- //# sourceMappingURL=openBrowser.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"openBrowser.js","sourceRoot":"","sources":["../../src/openBrowser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAiBrC;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CACpC,GAAW,EACX,WAA4B,OAAO,CAAC,QAAQ;IAE5C,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAA;IACzC,CAAC;IACD,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,CAAA;IAC3D,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAA;AAC7C,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,GAAW,EACX,UAGI,EAAE;IAEN,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAA;IACrD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,KAAK,CAAA;IACxC,MAAM,IAAI,GAAG,sBAAsB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;IAElD,IAAI,KAA+B,CAAA;IACnC,IAAI,CAAC;QACH,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE;YACvC,KAAK,EAAE,QAAQ;YACf,QAAQ,EAAE,IAAI;SACC,CAAC,CAAA;IACpB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,MAAM,EAAE,KAAK;YACb,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SACzD,CAAA;IACH,CAAC;IAED,4EAA4E;IAC5E,2EAA2E;IAC3E,MAAM,WAAW,GAAG,IAAI,OAAO,CAAQ,CAAC,YAAY,EAAE,EAAE;QACtD,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,CAAC,CAAA;IACjC,CAAC,CAAC,CAAA;IAEF,wEAAwE;IACxE,KAAK,CAAC,KAAK,EAAE,CAAA;IAEb,8EAA8E;IAC9E,6EAA6E;IAC7E,MAAM,OAAO,GAAG,IAAI,OAAO,CAAO,CAAC,WAAW,EAAE,EAAE;QAChD,YAAY,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAA;IACvC,CAAC,CAAC,CAAA;IAEF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAA;IACzD,OAAO,MAAM,KAAK,IAAI;QACpB,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE;QAClB,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,CAAA;AAC/C,CAAC"}