> For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt.

# Get started: Desktop · Vitest · Model API Key {#get-started}

These are the setup steps for Midscene on **Desktop** with **Vitest** and a **Model API Key**. To choose another combination, see [all setup paths](/get-started.md#all-setup-paths).

## Install Node.js
Install Node.js `^20.19.0 || ^22.12.0 || >=24.0.0`, then check that `node -v` works in your terminal.
The commands below use pnpm. If it is not installed yet, run `npm install -g pnpm`.

## Grant desktop permissions
- **macOS**: Grant two separate system permissions to the terminal or IDE that launches Playground or runs your scripts (such as Terminal, iTerm2, VS Code, Cursor, or WebStorm):
  1. **Accessibility** (for mouse and keyboard control): Enable your terminal or IDE in **System Settings > Privacy & Security > Accessibility** (see [nut.js macOS setup](https://github.com/nut-tree/nut.js#macos)).
  2. **Screen Recording** (for desktop screenshots): Enable your terminal or IDE in **System Settings > Privacy & Security > Screen Recording**. **After granting access, completely quit and relaunch the terminal or IDE** before starting Playground.
- **Windows**: No extra setup is required for standard applications. However, Windows User Interface Privilege Isolation (UIPI) blocks non-elevated processes from injecting mouse clicks or keystrokes into windows running **as Administrator** (the cursor still moves to the target coordinates, but clicks and key presses are silently dropped). Prefer running the target app without Administrator privileges; if it must run elevated, launch the terminal or Node.js process running Midscene **as Administrator** as well (see [Windows: clicks have no effect on some apps](/platforms/desktop.md#windows-clicks-have-no-effect-on-some-apps)).
- **Linux (desktop GUI)**: Install [ImageMagick](https://imagemagick.org/script/download.php) for screen capture support.
- **Linux (headless server / CI)**: To run desktop automation on a headless Linux host (such as GitHub Actions), install Xvfb and ImageMagick, then enable headless mode to start a virtual display automatically:

```bash
# Install dependencies
sudo apt-get install -y xvfb x11-xserver-utils imagemagick
```

When using Xvfb, make sure the target application is started inside the same virtual display environment (not needed on machines with a physical display).
To control a remote Windows desktop over RDP, see [Desktop environment setup](/platforms/desktop.md#connect-device).

## Configure a model
Choose a model below. Its configuration has four values. Open **Get API key** to create a key with the provider, then replace `......` in `MIDSCENE_MODEL_API_KEY` with it.

The configuration below is for Doubao-Seed-2.1 Turbo. Other recommended models:

- [Qwen3.7 Plus](/model-api-setup.md#qwen) (Alibaba)
- [DeepSeek V4.1 Flash](/model-api-setup.md#deepseek) (DeepSeek)
- [Gemini 3.5 Flash](/model-api-setup.md#gemini) (Google)
- [GPT-6 Sol](/model-api-setup.md#gpt) (OpenAI)
- [Kimi K3](/model-api-setup.md#kimi) (Moonshot AI)
- [MiMo V2.6 Pro](/model-api-setup.md#xiaomi-mimo) (Xiaomi)
- [GLM-5V-Turbo](/model-api-setup.md#glm-v) (Zhipu AI)
- [Ling-3.0-flash-VL](/model-api-setup.md#ant-ling) (Ant Group)

**Volcano Engine** ([Get API key](https://console.volcengine.com/ark))

```bash
MIDSCENE_MODEL_BASE_URL="https://ark.cn-beijing.volces.com/api/v3"
MIDSCENE_MODEL_API_KEY="......"
MIDSCENE_MODEL_NAME="doubao-seed-2-1-turbo-260628"
MIDSCENE_MODEL_FAMILY="doubao-seed"
```

**OpenRouter** ([Get API key](https://openrouter.ai/settings/keys))

```bash
MIDSCENE_MODEL_BASE_URL="https://openrouter.ai/api/v1"
MIDSCENE_MODEL_API_KEY="......"
MIDSCENE_MODEL_NAME="bytedance-seed/seed-2-1-turbo"
MIDSCENE_MODEL_FAMILY="doubao-seed"
```

For other versions and usage notes, see [Doubao Seed series](/model-api-setup.md#doubao-seed-model).

To compare models, see the [Model selection guide](/model-selection.md). For compatible models such as UI-TARS, see [Use a model API key](/model-api-setup.md#supported-models).

Write the four values to a `.env` file in your project directory. If you are starting without a project, create a directory and run `pnpm init` in it first.

## Set up the project
In the project directory that contains `.env`, verify the model configuration:
```bash
pnpm dlx @midscene/test@latest model verify
```
If the check fails, see [Verify model connectivity](/model-config.md#verify-model-connectivity).

### Install dependencies

```bash
pnpm add -D vitest dotenv @midscene/computer
```
### Configure Vitest
Create `vitest.config.ts`. If your project already uses Vitest for unit tests, you can save this configuration separately as `vitest.device.config.ts` and pass `--config vitest.device.config.ts` when running device tests, leaving your existing test configuration untouched.

```typescript title="vitest.config.ts"
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    include: ['e2e/**/*.test.ts'],
    environment: 'node',
    testTimeout: 90_000,
    hookTimeout: 90_000,
    fileParallelism: false,
    sequence: { concurrent: false },
  },
});
```

Because model calls and device connections take longer than standard unit tests, adjust `testTimeout` and `hookTimeout` to fit your test cases. When running against a single shared device, disable file parallelism (`fileParallelism: false`) and run tests sequentially (`sequence.concurrent: false`), and avoid `test.concurrent` or `describe.concurrent`. For details, see the Vitest documentation on [fileParallelism](https://vitest.dev/config/fileparallelism), [testTimeout](https://vitest.dev/config/testtimeout), and [hookTimeout](https://vitest.dev/config/hooktimeout).

## Write a test

Create `e2e/settings.test.ts`, initializing a new Agent for each test in `beforeEach` and destroying it in `afterEach`:

```typescript title="e2e/settings.test.ts"
import 'dotenv/config';
import { afterEach, beforeEach, test } from 'vitest';
import { agentForComputer } from '@midscene/computer';

let agent: Awaited<ReturnType<typeof agentForComputer>> | undefined;

beforeEach(async () => {
  agent = await agentForComputer();
});

afterEach(async () => {
  const currentAgent = agent;
  agent = undefined;
  await currentAgent?.destroy();
});

test('scroll through settings', async () => {
  if (!agent) throw new Error('Agent was not initialized');

  await agent.aiWaitFor('The Settings app is visible');
  await agent.aiAct('Scroll down one screen');
  await agent.aiAssert('The Settings app is still visible');
});
```
Before running the test, open your system Settings app and bring a scrollable settings page to the foreground. Keep it visible during the test. See the [desktop SDK guide](/sdk/desktop.md) for permissions and connection options.

`dotenv/config` loads model settings from the project's `.env` file (settings in the Playground are not automatically shared with test runs).

When an `aiAssert` check fails, it throws an error, causing Vitest to mark the test as failed before running `afterEach` to clean up the Agent. You can also extract data from the screen with methods like `aiQuery` and pass the result to Vitest's `expect`. For more interaction and extraction methods, see the [Agent API reference](/reference/index.md#interaction-methods).

## Run the test and inspect the report

```bash
pnpm exec vitest run e2e/settings.test.ts
```

Vitest prints the pass or fail status of each test in the terminal, while the Midscene SDK generates an execution report for each Agent under `midscene_run/report/` by default and prints the report path. Open the generated HTML file in a browser to inspect step-by-step screenshots, AI execution details, and assertion results.

Unlike Playwright Test, Vitest integration uses the SDK's built-in report generation directly and does not require a custom reporter. Vitest test results and Midscene Agent reports are generated separately; to merge or further process report files, see [Process report files](/consume-report-file.md).

When the test passes and the report shows each step with screenshots, your model, environment, and project are all working.

## Next steps
- **Explore more examples**: [Showcases](/showcases.md) includes demo videos and full execution reports across platforms.

- **Look up APIs**: [API reference](/reference.md) lists every Agent method and its options.
- **Combine AI calls with code**: [Key APIs](/basics.md#javascript-orchestration) explains when to use `aiAct`, instant actions, and insight APIs.

- **Share a device across tests**: [Lifecycle and exclusive device access](/sdk/vitest.md#lifecycle-and-exclusive-device-access) explains how to create and destroy Agents when tests share one device.
