• English
  • YAML script runner

    Midscene defines a YAML-based scripting format so you can quickly author automation scripts, then run them from the command line without extra setup. For more details on YAML scripts, see Automate with scripts in YAML.

    For example, you can write a YAML script like this:

    page:
      url: https://www.bing.com
    
    tasks:
      - name: Search for weather
        flow:
          - ai: Search for "today's weather"
          - sleep: 3000
          - aiAssert: The results show weather information

    Run it with one command:

    midscene ./bing-search.yaml

    The CLI prints execution progress and generates a visual report when it finishes, while keeping setup simple.

    Configure environment variables with .env

    The Midscene CLI uses dotenv to load a .env file from the directory where you run the tool. Create a .env file and add:

    MIDSCENE_MODEL_BASE_URL="replace with your model service URL/v1"
    MIDSCENE_MODEL_API_KEY="replace with your API Key"
    MIDSCENE_MODEL_NAME="replace with your model name"
    MIDSCENE_MODEL_FAMILY="replace with your model family"

    For supported models and complete setup examples, see Supported models and setup.

    Notes:

    • The file is optional; you can also set global environment variables instead.
    • Do not add an export prefix—this is how dotenv expects values.
    • Place .env in the directory where you run the tool, not necessarily next to the YAML file.
    • These values do not override existing global environment variables unless you enable --dotenv-override (see below).
    • Use --dotenv-debug if you need to debug how environment variables load.

    Get started

    Install the CLI

    Before installing the CLI, make sure the terminal that runs midscene uses Node.js 20.19+, 22.12+, or 24+. Some CLI execution paths use the Rstest/Rspack toolchain, which rejects older Node 20 patch versions such as 20.17.0. If you see an Unsupported Node.js version message from Rspack, upgrade Node.js and reinstall the global CLI or project dependencies.

    Install @midscene/cli globally (recommended for first-time users):

    npm i -g @midscene/cli

    Or install it per project:

    npm i @midscene/cli --save-dev

    Write your first script

    Create bing-search.yaml to drive a web browser:

    page:
      url: https://www.bing.com
    
    tasks:
      - name: Search for weather
        flow:
          - ai: Search for "today's weather"
          - sleep: 3000
          - aiAssert: The results show weather information

    Drive an Android device connected over adb:

    android:
      deviceId: s4ey59 # find the device id with `adb devices`
    
    tasks:
      - name: Maps Navigation
        flow:
          - ai: Open the Maps app
          - ai: Input 'West Lake, Hangzhou' in the search bar, and click the search button
          - ai: Click the first search result, enter the details page
          - ai: Click "Directions" button, enter the route planning page
          - ai: Click "Start" button to start navigation

    Or drive an iOS device with WebDriverAgent configured:

    ios:
      wdaPort: 8100
    
    tasks:
      - name: Change System Settings
        flow:
          - ai: Open the Settings app
          - ai: Tap "Display & Brightness"
          - ai: Turn on "Dark Mode"
          - aiAssert: Dark Mode is enabled

    Run the script

    midscene ./bing-search.yaml
    # If Midscene is installed in your project
    npx midscene ./bing-search.yaml

    The CLI prints execution progress and generates a visual report when it finishes.

    Advanced usage of the command-line tool

    Use environment variables in .yaml

    Reference environment variables in your scripts with ${variable-name}. Environment-variable interpolation is applied before YAML task execution, including task strings.

    topic=weather today
    # ...
    - ai: type ${topic} in input box
    # ...

    Run multiple scripts

    @midscene/cli supports glob patterns to batch-execute scripts, which is a shorthand for the --files argument.

    # Run a single script
    midscene ./bing-search.yaml
    
    # Use a glob pattern to run all matching scripts
    midscene './scripts/**/*.yaml'

    Analyze command-line output

    After execution, the output directory contains:

    • A JSON summary specified by --summary (defaults to index.json) with execution status and statistics for all scripts.
    • Individual execution results for each YAML file (JSON).
    • Visual reports for each script (HTML).

    Run in headed mode

    Web page scenarios only

    Headed mode opens the browser window. By default, scripts run headless.

    # Run in headed mode
    midscene /path/to/yaml --headed
    
    # Run in headed mode and keep the window after finishing
    midscene /path/to/yaml --keep-window

    Use CDP connection mode

    web scenarios only

    CDP mode lets YAML scripts connect to an existing browser instance via Chrome DevTools Protocol, without launching a new browser. This is useful for reusing an existing browser session, connecting to remote browsers, or cloud browser services.

    Set cdpEndpoint in the page section:

    page:
      url: https://www.bing.com
    + cdpEndpoint: ws://localhost:9222/devtools/browser
    Info

    CDP mode and bridge mode are mutually exclusive. In CDP mode, Midscene will only disconnect from the browser, not close it.

    Use bridge mode

    Web page scenarios only

    Bridge mode lets YAML scripts drive your existing desktop browser so you can reuse cookies, extensions, or state. Install the Chrome extension, then add:

    page:
      url: https://www.bing.com
    + bridgeMode: newTabWithUrl

    See Bridge Mode via Chrome Extension for details.

    Run YAML scripts with JavaScript

    Call the Agent's runYaml method to execute YAML from JavaScript. This runs only the tasks section of the script.

    Command-line options

    The CLI provides parameters to control how scripts run:

    • --files <file1> <file2> ...: List of script files. Executes in order, sequentially by default (--concurrent is 1), or concurrently when --concurrent is set. Supports glob patterns; when a glob pattern or directory matches multiple files, matched files are added to the execution list in lexicographic path order.
    • --setup <file>: A setup script that runs before the main --files for any supported target. If all setup attempts fail, the batch is aborted and the main scripts are reported as not executed. Puppeteer Web setup requires --share-browser-context; each retry then starts with a clean BrowserContext and Page, and the successful context is shared with the main scripts. Every YAML script still runs in its own Page, so page-scoped state such as sessionStorage is not carried between scripts. Bridge mode and non-Web targets must omit --share-browser-context; their retries create a new player and Agent but do not reset the underlying browser, device, desktop, or external interface state.
    • --concurrent <number>: Number of concurrent executions. Default 1.
    • --continue-on-error: Continue running remaining scripts even if one fails. Default off.
    • --retry <number>: Number of extra attempts for a failed script. Only failed scripts are retried, which helps with unstable networks or unstable model output. Default 0. Puppeteer Web setup retries use a clean BrowserContext and Page, while main-script retries preserve the successful setup context. Other targets create a new player and Agent for each retry without resetting their underlying environment.
    • --share-browser-context: Share one Puppeteer BrowserContext (cookies, same-origin localStorage, etc.) across scripts while giving every YAML script an independent Page. Page-scoped state such as sessionStorage, the DOM, URL, and window.name is not shared, even with --concurrent 1. Every setup and main script in the batch must use a Puppeteer Web target. Bridge mode and non-Web targets are not supported. Because the browser is created or connected only once, put browser-level options (cdpEndpoint, chromeArgs, acceptInsecureCerts, and downloadPath) in the batch config's global Web target, not in an individual setup or main script. Default off.
    • --summary <filename>: Path for the JSON summary report.
    • --headed: Run in a headed browser instead of headless.
    • --keep-window: Keep the browser window after execution; enables --headed automatically.
    • --config <filename>: Config file whose values become defaults for CLI arguments.
    • --web.userAgent <ua>: Override web.userAgent for all scripts.
    • --web.viewportWidth <width>: Override web.viewportWidth for all scripts.
    • --web.viewportHeight <height>: Override web.viewportHeight for all scripts.
    • --android.deviceId <device-id>: Override android.deviceId for all scripts.
    • --ios.wdaPort <port>: Override ios.wdaPort for all scripts.
    • --ios.wdaHost <host>: Override ios.wdaHost for all scripts.
    • --dotenv-debug: Enable dotenv debug logs. Default off.
    • --dotenv-override: Allow dotenv to override global environment variables. Default off.

    Examples:

    Use --files to specify execution order:

    midscene --files ./login.yaml ./buy/*.yaml ./checkout.yaml

    Run multiple independent search scripts with a concurrency of 4 and continue when errors occur:

    midscene --files './scripts/search-*.yaml' --concurrent 4 --continue-on-error

    Write command-line arguments in a file

    You can place arguments in a YAML config file and reference it with --config. Command-line arguments take priority over the config file.

    files:
      - './scripts/search-iphone.yaml'
      - './scripts/search-laptop.yaml'
      - './scripts/search-headphones.yaml'
      - './scripts/search-camera.yaml'
    
    concurrent: 4
    continueOnError: true
    retry: 2

    Run with:

    midscene --config ./config.yaml

    Set concurrent: 1 (the default) when scripts must run in the exact order of the files list. With a value greater than 1, execution order is unspecified; scripts must not depend on another script's start or completion order.

    Run a setup before parallel scripts

    When several independent Puppeteer Web scripts all depend on the same prerequisite (for example a login), put the prerequisite under setup. The setup script runs before the main files; once it succeeds, the main scripts run with the configured concurrency. Set shareBrowserContext: true so the successful setup attempt's browser context, including cookies and same-origin localStorage, is carried over. Every script receives an independent Page, so the setup Page's sessionStorage, DOM, URL, window.name, and other page-scoped state are not copied into main Pages. Every script in this shared batch must use a Puppeteer Web target; bridge mode is not supported.

    The shared Browser is launched or connected from the batch config once. Configure cdpEndpoint, chromeArgs, acceptInsecureCerts, and downloadPath in the batch config's global Web target. Defining any of these browser-level options in an individual setup or main script is rejected because it cannot be applied to the already-created shared Browser.

    setup: ./scripts/login.yaml
    
    files:
      - ./scripts/search.yaml
      - ./scripts/report.yaml
      - ./scripts/settings.yaml
    
    shareBrowserContext: true
    concurrent: 3
    retry: 2

    retry is the number of extra attempts, so retry: 2 allows up to three attempts. Every setup retry gets a new BrowserContext and Page, preventing cookies, local storage, navigation state, and other browser-side effects from a failed attempt from leaking into the next one. After setup succeeds, its context is shared with the main scripts. A failed main script is retried in that same context so the successful setup state is preserved. If all setup attempts fail, the batch is aborted and the main scripts are reported as not executed.

    Page-scoped state is not shared

    shareBrowserContext follows browser-native storage boundaries: it does not copy or synchronize sessionStorage between Pages. If setup establishes authentication only in sessionStorage, the main scripts will not inherit that login. Prefer cookies, same-origin localStorage, or backend state for prerequisites that must be visible to multiple scripts. When scripts run concurrently, shared-state writes can race, so coordinate them explicitly.

    setup also works with bridge mode, Android, iOS, HarmonyOS, Computer, and custom Interface targets. Omit shareBrowserContext for those targets. A retry creates a new script player and Agent, but the underlying browser profile, device, desktop session, or custom interface is not automatically reset. If a clean retry environment is required, make the setup script restore that environment explicitly.

    FAQ

    How can I export cookies from Chrome as JSON?

    Use this Chrome extension to export cookies.

    How can I view dotenv debug logs?

    Use the --dotenv-debug flag:

    midscene /path/to/yaml --dotenv-debug=true