screenci 0.0.31 → 0.0.33

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.
package/README.md CHANGED
@@ -13,15 +13,15 @@ npm install screenci
13
13
  ## Init a new project
14
14
 
15
15
  ```bash
16
- npx screenci init my-project
17
- cd my-project
16
+ npx screenci init "My Project"
17
+ cd screenci
18
18
  npm install
19
19
  ```
20
20
 
21
21
  This scaffolds a ready-to-run project:
22
22
 
23
23
  ```
24
- my-project/
24
+ screenci/
25
25
  screenci.config.ts ← video settings
26
26
  videos/
27
27
  example.video.ts ← your first video script
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":";AA+BA,OAAO,KAAK,EACV,uBAAuB,EACvB,aAAa,EAEd,MAAM,iBAAiB,CAAA;AACxB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AA4D/C,KAAK,mBAAmB,GAAG;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAiBD,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,GAAG,KAAK,GAAG,OAAO,CAAC,EACtD,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,KAAK,IAAI,GACxC,MAAM,IAAI,CAiBZ;AAuED,QAAA,MAAM,mCAAmC;;;CAG/B,CAAA;AAEV,KAAK,oBAAoB,GAAG,MAAM,OAAO,mCAAmC,CAAA;AAmc5E,wBAAgB,cAAc,CAC5B,KAAK,EAAE,QAAQ,GAAG,uBAAuB,GACxC,QAAQ,GAAG,uBAAuB,CAKpC;AAED,wBAAgB,oCAAoC,CAClD,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,mBAAmB,EAAE,GAC5B,aAAa,CAqEf;AAQD,wBAAgB,+BAA+B,CAC7C,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,GACb,MAAM,CAeR;AAED,wBAAgB,8BAA8B,CAC5C,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,GACb,IAAI,CAcN;AAgRD,wBAAgB,gBAAgB,IAAI,MAAM,CAKzC;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAK1C;AA2GD,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,aAAa,GAAG,SAAS,GAClC,MAAM,GAAG,SAAS,CAepB;AA6wBD,wBAAsB,IAAI,kBA6PzB;AAyID,wBAAgB,sBAAsB,CACpC,aAAa,CAAC,EAAE,oBAAoB,GACnC,oBAAoB,CAoBtB"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":";AA+BA,OAAO,KAAK,EACV,uBAAuB,EACvB,aAAa,EAEd,MAAM,iBAAiB,CAAA;AACxB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAmE/C,KAAK,mBAAmB,GAAG;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAiBD,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,GAAG,KAAK,GAAG,OAAO,CAAC,EACtD,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,KAAK,IAAI,GACxC,MAAM,IAAI,CAiBZ;AAuED,QAAA,MAAM,mCAAmC;;;CAG/B,CAAA;AAEV,KAAK,oBAAoB,GAAG,MAAM,OAAO,mCAAmC,CAAA;AAmc5E,wBAAgB,cAAc,CAC5B,KAAK,EAAE,QAAQ,GAAG,uBAAuB,GACxC,QAAQ,GAAG,uBAAuB,CAKpC;AAED,wBAAgB,oCAAoC,CAClD,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,mBAAmB,EAAE,GAC5B,aAAa,CAqEf;AAQD,wBAAgB,+BAA+B,CAC7C,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,GACb,MAAM,CAeR;AAED,wBAAgB,8BAA8B,CAC5C,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,GACb,IAAI,CAcN;AAgRD,wBAAgB,gBAAgB,IAAI,MAAM,CAKzC;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAK1C;AA2GD,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,aAAa,GAAG,SAAS,GAClC,MAAM,GAAG,SAAS,CAepB;AA00BD,wBAAsB,IAAI,kBA2PzB;AAyID,wBAAgB,sBAAsB,CACpC,aAAa,CAAC,EAAE,oBAAoB,GACnC,oBAAoB,CAoBtB"}
package/dist/cli.js CHANGED
@@ -8,7 +8,7 @@ import { appendFile, mkdir, readdir, readFile, stat, writeFile, } from 'fs/promi
8
8
  import { dirname, relative as pathRelative, resolve } from 'path';
9
9
  import { fileURLToPath } from 'url';
10
10
  import { Command, CommanderError } from 'commander';
11
- import { input, confirm } from '@inquirer/prompts';
11
+ import { input, confirm, select } from '@inquirer/prompts';
12
12
  import ora from 'ora';
13
13
  import pc from 'picocolors';
14
14
  import { logger } from './src/logger.js';
@@ -971,19 +971,19 @@ async function updateVideoVisibility(videoId, isPublic, configPath) {
971
971
  }
972
972
  logger.info(`${isPublic ? 'Made public' : 'Made private'}: ${videoId}`);
973
973
  }
974
- function generateConfig(projectName) {
974
+ function generateConfig(projectName, initTarget) {
975
+ const baseURLBlock = initTarget
976
+ ? ` baseURL: ${JSON.stringify(initTarget.baseURL)},
977
+ `
978
+ : '';
975
979
  return `import { defineConfig } from 'screenci'
976
980
 
977
981
  export default defineConfig({
978
982
  projectName: ${JSON.stringify(projectName)},
979
983
  envFile: '.env',
980
984
  videoDir: './videos',
981
- forbidOnly: !!process.env.CI,
982
- reporter: 'html',
983
985
  use: {
984
- trace: 'retain-on-failure',
985
- sendTraces: true,
986
- recordOptions: {
986
+ ${baseURLBlock} recordOptions: {
987
987
  aspectRatio: '16:9',
988
988
  quality: '1080p',
989
989
  fps: 30,
@@ -997,18 +997,13 @@ export default defineConfig({
997
997
  })
998
998
  `;
999
999
  }
1000
- function generatePackageJson(projectName, includePlaywrightCli = false, screenciDependency = 'latest') {
1001
- const npmName = projectName.toLowerCase().replace(/[^a-z0-9-]/g, '-');
1002
- const devDependencies = {
1003
- '@types/node': '^25.0.0',
1004
- };
1000
+ function generatePackageJson(packageName, includePlaywrightCli = false, screenciDependency = 'latest') {
1001
+ const devDependencies = {};
1005
1002
  if (includePlaywrightCli) {
1006
1003
  devDependencies['@playwright/cli'] = 'latest';
1007
1004
  }
1008
1005
  return (JSON.stringify({
1009
- name: npmName,
1010
- version: '1.0.0',
1011
- description: '',
1006
+ name: packageName,
1012
1007
  type: 'module',
1013
1008
  scripts: {
1014
1009
  record: 'screenci record',
@@ -1021,6 +1016,25 @@ function generatePackageJson(projectName, includePlaywrightCli = false, screenci
1021
1016
  devDependencies,
1022
1017
  }, null, 2) + '\n');
1023
1018
  }
1019
+ async function readCurrentScreenciVersion() {
1020
+ const currentFileDir = dirname(fileURLToPath(import.meta.url));
1021
+ const packageJsonPaths = [
1022
+ resolve(currentFileDir, 'package.json'),
1023
+ resolve(currentFileDir, '../package.json'),
1024
+ ];
1025
+ for (const packageJsonPath of packageJsonPaths) {
1026
+ try {
1027
+ const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf-8'));
1028
+ if (typeof packageJson.version === 'string') {
1029
+ return packageJson.version;
1030
+ }
1031
+ }
1032
+ catch {
1033
+ // Try the next candidate path.
1034
+ }
1035
+ }
1036
+ return 'latest';
1037
+ }
1024
1038
  function generateTsconfig() {
1025
1039
  return `${JSON.stringify({
1026
1040
  compilerOptions: {
@@ -1065,6 +1079,7 @@ function generateDockerfile() {
1065
1079
  return `FROM ghcr.io/screenci/record:latest
1066
1080
 
1067
1081
  COPY package.json ./
1082
+ RUN npm install
1068
1083
  COPY screenci.config.ts ./
1069
1084
  COPY videos ./videos
1070
1085
  `;
@@ -1108,10 +1123,16 @@ jobs:
1108
1123
  node-version: latest
1109
1124
 
1110
1125
  - name: Install dependencies
1111
- run: npm install
1126
+ working-directory: screenci
1127
+ run: npm install --include=dev
1128
+
1129
+ - name: Install Chromium
1130
+ working-directory: screenci
1131
+ run: npx playwright install chromium --with-deps
1112
1132
 
1113
1133
  - id: record
1114
1134
  name: Record
1135
+ working-directory: screenci
1115
1136
  env:
1116
1137
  SCREENCI_SECRET: \${{ secrets.SCREENCI_SECRET }}
1117
1138
  run: npm run record
@@ -1168,7 +1189,7 @@ async function performBrowserLogin(appUrl) {
1168
1189
  });
1169
1190
  }
1170
1191
  function generateExampleVideo() {
1171
- return `import { createNarration, hide, video, voices } from 'screenci'
1192
+ return `import { autoZoom, createNarration, hide, video, voices } from 'screenci'
1172
1193
 
1173
1194
  const narration = createNarration({
1174
1195
  voice: { name: voices.Sophie, style: 'Clear, friendly product walkthrough' },
@@ -1176,45 +1197,53 @@ const narration = createNarration({
1176
1197
  en: {
1177
1198
  cues: {
1178
1199
  intro:
1179
- 'Here is how to find instructions for starting to create your own ScreenCI [pronounce: screen see eye] videos. [short pause] Start on the homepage, then open the documentation from the hero section.',
1180
- docs: 'The documentation opens with the guide sidebar on the left. In the Guides group, choose AI-Supported Editing.',
1200
+ 'This example opens your app at the configured base URL first, then uses ScreenCI [pronounce: screen see eye] to show the next steps for creating your first videos.',
1201
+ docs: 'Use the guide sidebar to open the AI-Supported Editing guide and review the next steps for writing your own videos.',
1181
1202
  },
1182
1203
  },
1183
1204
  es: {
1184
1205
  cues: {
1185
1206
  intro:
1186
- 'Aqui se muestra como encontrar instrucciones para empezar a crear tus propios videos de ScreenCI [pronounce: screen see eye]. [short pause] Comienza en la pagina principal y abre la documentacion desde la seccion principal.',
1187
- docs: 'La documentacion se abre con la barra lateral de guias a la izquierda. En el grupo Guias, elige Edicion asistida por IA.',
1207
+ 'Este ejemplo abre primero tu aplicacion en la URL base configurada y despues usa ScreenCI [pronounce: screen see eye] para mostrar los siguientes pasos para crear tus primeros videos.',
1208
+ docs: 'Usa la barra lateral de guias para abrir la guia de edicion asistida por IA y revisar los siguientes pasos para escribir tus propios videos.',
1188
1209
  },
1189
1210
  },
1190
1211
  },
1191
1212
  })
1192
1213
 
1193
- video('Navigate to AI editing documentation', async ({ page }) => {
1214
+ video('See the next steps in ScreenCI docs', async ({ page }) => {
1215
+ await hide(async () => {
1216
+ await page.goto('/')
1217
+ await page.waitForLoadState('domcontentloaded')
1218
+ })
1219
+
1220
+ await narration.intro
1221
+ await page.waitForTimeout(1000)
1222
+
1194
1223
  await hide(async () => {
1195
1224
  await page.goto('https://screenci.com/')
1196
1225
  await page.getByText('ScreenCI', { exact: true }).first().waitFor()
1197
1226
  })
1198
1227
 
1199
- await narration.intro
1200
- await page.getByRole('link', { name: 'View Documentation' }).click()
1228
+ await autoZoom(
1229
+ async () => {
1230
+ await page.getByRole('link', { name: 'View Documentation' }).click()
1231
+ await page
1232
+ .getByRole('link', { name: 'AI-Supported Editing', exact: true })
1233
+ .click()
1234
+ await page.waitForTimeout(1000)
1235
+ },
1236
+ { duration: 400, easing: 'ease-in-out', amount: 0.4 }
1237
+ )
1201
1238
 
1202
1239
  await narration.docs
1203
- await page
1204
- .getByRole('link', { name: 'AI-Supported Editing', exact: true })
1205
- .click()
1240
+ await narration.wait()
1206
1241
  })
1207
1242
  `;
1208
1243
  }
1209
1244
  async function promptProjectName() {
1210
1245
  return input({ message: 'Project name:' });
1211
1246
  }
1212
- async function promptInitGitRepository() {
1213
- return confirm({
1214
- message: 'Initialize a git repository? (Y/n)',
1215
- default: true,
1216
- });
1217
- }
1218
1247
  async function promptInitDependencies() {
1219
1248
  return confirm({
1220
1249
  message: 'Install dependencies now, including Chromium for Playwright? (Y/n)',
@@ -1233,8 +1262,30 @@ async function promptInitGithubActionCi() {
1233
1262
  default: true,
1234
1263
  });
1235
1264
  }
1236
- function getProjectDirName(name) {
1237
- return name.toLowerCase().replace(/\s+/g, '-');
1265
+ async function promptInitTargetMode() {
1266
+ return select({
1267
+ message: 'Should videos run against a local development server or a public URL?',
1268
+ choices: [
1269
+ { name: 'Local development server', value: 'local' },
1270
+ { name: 'Public URL', value: 'public' },
1271
+ ],
1272
+ default: 'local',
1273
+ });
1274
+ }
1275
+ async function promptInitTargetUrl(mode) {
1276
+ return input({
1277
+ message: mode === 'local' ? 'Local development server URL:' : 'Public app URL:',
1278
+ default: mode === 'local' ? 'http://localhost:3000' : 'https://screenci.com',
1279
+ });
1280
+ }
1281
+ function normalizeInitUrl(url) {
1282
+ try {
1283
+ return new URL(url.trim()).toString();
1284
+ }
1285
+ catch {
1286
+ logger.error(`Error: Invalid URL "${url}"`);
1287
+ process.exit(1);
1288
+ }
1238
1289
  }
1239
1290
  function getInitProjectRoot() {
1240
1291
  return process.env['SCREENCI_INIT_CWD'] ?? process.cwd();
@@ -1344,7 +1395,7 @@ function checkNodeVersion() {
1344
1395
  }
1345
1396
  }
1346
1397
  async function runInit(projectNameArg, options) {
1347
- const { verbose, git, install, yes, skill, ci } = options;
1398
+ const { verbose, install, yes, skill, ci } = options;
1348
1399
  checkNodeVersion();
1349
1400
  checkContainerRuntimeForInit();
1350
1401
  const initCwd = getInitProjectRoot();
@@ -1356,17 +1407,25 @@ async function runInit(projectNameArg, options) {
1356
1407
  logger.error('Error: Project name is required');
1357
1408
  process.exit(1);
1358
1409
  }
1359
- const dirName = getProjectDirName(projectName);
1410
+ const dirName = 'screenci';
1360
1411
  const projectDir = resolve(initCwd, dirName);
1412
+ const githubDir = resolve(initCwd, '.github');
1413
+ const githubWorkflowsDir = resolve(githubDir, 'workflows');
1414
+ const githubActionPath = resolve(githubWorkflowsDir, 'screenci.yaml');
1361
1415
  if (existsSync(projectDir)) {
1362
1416
  logger.error(`Error: Directory "${dirName}" already exists`);
1363
1417
  process.exit(1);
1364
1418
  }
1365
- const shouldInitializeGitRepository = yes
1366
- ? true
1367
- : git
1368
- ? true
1369
- : await promptInitGitRepository();
1419
+ const initTarget = yes
1420
+ ? undefined
1421
+ : await (async () => {
1422
+ const mode = await promptInitTargetMode();
1423
+ const baseURL = normalizeInitUrl(await promptInitTargetUrl(mode));
1424
+ return {
1425
+ mode,
1426
+ baseURL,
1427
+ };
1428
+ })();
1370
1429
  const shouldInstallDependencies = yes
1371
1430
  ? true
1372
1431
  : install
@@ -1382,6 +1441,10 @@ async function runInit(projectNameArg, options) {
1382
1441
  : ci
1383
1442
  ? true
1384
1443
  : await promptInitGithubActionCi();
1444
+ if (shouldAddGithubActionCi && existsSync(githubActionPath)) {
1445
+ logger.error('Error: GitHub Actions workflow ".github/workflows/screenci.yaml" already exists');
1446
+ process.exit(1);
1447
+ }
1385
1448
  const skillsArgs = [
1386
1449
  '--yes',
1387
1450
  'skills',
@@ -1396,17 +1459,20 @@ async function runInit(projectNameArg, options) {
1396
1459
  const devScreenciPackageRoot = getDevScreenciPackageRoot();
1397
1460
  const screenciDependency = devScreenciPackageRoot
1398
1461
  ? getLocalScreenciDependency(devScreenciPackageRoot, projectDir)
1399
- : 'latest';
1462
+ : await readCurrentScreenciVersion();
1400
1463
  if (devScreenciPackageRoot) {
1401
1464
  await buildLocalScreenciPackage(devScreenciPackageRoot);
1402
1465
  }
1403
1466
  await mkdir(resolve(projectDir, 'videos'), { recursive: true });
1404
1467
  if (shouldAddGithubActionCi) {
1405
- await mkdir(resolve(projectDir, '.github', 'workflows'), {
1406
- recursive: true,
1407
- });
1468
+ if (!existsSync(githubDir)) {
1469
+ await mkdir(githubDir);
1470
+ }
1471
+ if (!existsSync(githubWorkflowsDir)) {
1472
+ await mkdir(githubWorkflowsDir);
1473
+ }
1408
1474
  }
1409
- await writeFile(resolve(projectDir, 'screenci.config.ts'), generateConfig(projectName));
1475
+ await writeFile(resolve(projectDir, 'screenci.config.ts'), generateConfig(projectName, initTarget));
1410
1476
  await writeFile(resolve(projectDir, 'package.json'), generatePackageJson(dirName, shouldAddPlaywrightCli, screenciDependency));
1411
1477
  await writeFile(resolve(projectDir, 'tsconfig.json'), generateTsconfig());
1412
1478
  await writeFile(resolve(projectDir, 'README.md'), generateReadme(projectName));
@@ -1414,7 +1480,7 @@ async function runInit(projectNameArg, options) {
1414
1480
  await writeFile(resolve(projectDir, '.gitignore'), generateGitignore());
1415
1481
  await writeFile(resolve(projectDir, 'videos', 'example.video.ts'), generateExampleVideo());
1416
1482
  if (shouldAddGithubActionCi) {
1417
- await writeFile(resolve(projectDir, '.github', 'workflows', 'record.yml'), generateGithubAction());
1483
+ await writeFile(githubActionPath, generateGithubAction());
1418
1484
  }
1419
1485
  await writeFile(resolve(projectDir, '.env'), '');
1420
1486
  logger.info(`Initialized screenci project "${projectName}" in ${projectDir}/`);
@@ -1427,27 +1493,10 @@ async function runInit(projectNameArg, options) {
1427
1493
  logger.info(' .gitignore');
1428
1494
  logger.info(' videos/example.video.ts');
1429
1495
  if (shouldAddGithubActionCi) {
1430
- logger.info(' .github/workflows/record.yml');
1496
+ logger.info(' .github/workflows/screenci.yaml');
1431
1497
  }
1432
1498
  logger.info(' .env (empty placeholder)');
1433
1499
  logger.info('');
1434
- if (shouldInitializeGitRepository) {
1435
- if (verbose) {
1436
- logger.info("Running 'git init'...");
1437
- await spawnInherited('git', ['init'], projectDir, 'screenci init');
1438
- }
1439
- else {
1440
- const spinner = ora('Initializing git repository...').start();
1441
- try {
1442
- await spawnSilent('git', ['init'], projectDir);
1443
- spinner.succeed('Git repository initialized');
1444
- }
1445
- catch (err) {
1446
- spinner.fail('git init failed');
1447
- throw err;
1448
- }
1449
- }
1450
- }
1451
1500
  if (shouldInstallDependencies) {
1452
1501
  if (verbose) {
1453
1502
  logger.info(`Running '${skillsCommand}'...`);
@@ -1613,7 +1662,7 @@ export async function main() {
1613
1662
  await run('test', parsed.otherArgs, parsed.configPath);
1614
1663
  if (process.env.SCREENCI_IN_CONTAINER === 'true')
1615
1664
  return;
1616
- logger.info('Tests passed. Run `npx screenci record` to render the videos.');
1665
+ logger.info(`Tests passed. Run ${pc.cyan('npx screenci record')} to render the videos.`);
1617
1666
  });
1618
1667
  program
1619
1668
  .command('info')
@@ -1649,7 +1698,6 @@ export async function main() {
1649
1698
  program
1650
1699
  .command('init [name]')
1651
1700
  .description('Initialize a new screenci project')
1652
- .option('--git', 'initialize a git repository without prompting')
1653
1701
  .option('--install', 'install skills, dependencies, and Chromium without prompting')
1654
1702
  .option('--ci', 'add GitHub Action CI without prompting')
1655
1703
  .option('--skill', 'enable playwright-cli without prompting')
@@ -1662,7 +1710,6 @@ export async function main() {
1662
1710
  else {
1663
1711
  await runInit(name, {
1664
1712
  verbose: options['verbose'] ?? false,
1665
- git: options['git'] ?? false,
1666
1713
  install: options['install'] ?? false,
1667
1714
  yes: options['yes'] ?? false,
1668
1715
  skill: options['skill'] ?? false,
@@ -1897,13 +1944,21 @@ async function runWithContainer(additionalArgs, customConfigPath, verbose = fals
1897
1944
  process.exit(1);
1898
1945
  }
1899
1946
  logger.info('Starting ScreenCI recording container...');
1947
+ const containerBaseHost = containerRuntime === 'docker'
1948
+ ? 'host.docker.internal'
1949
+ : 'host.containers.internal';
1900
1950
  await spawnContainerRecording(containerRuntime, [
1901
1951
  'run',
1902
1952
  '--rm',
1953
+ ...(containerRuntime === 'docker'
1954
+ ? ['--add-host', 'host.docker.internal:host-gateway']
1955
+ : []),
1903
1956
  ...(process.env.CI !== undefined ? ['-e', `CI=${process.env.CI}`] : []),
1904
1957
  '-e',
1905
1958
  'SCREENCI_IN_CONTAINER=true',
1906
1959
  '-e',
1960
+ `SCREENCI_CONTAINER_BASE_HOST=${containerBaseHost}`,
1961
+ '-e',
1907
1962
  'SCREENCI_RECORD=true',
1908
1963
  '-e',
1909
1964
  `SCREENCI_SECRET=${secret}`,