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

# Get started: HarmonyOS · Vitest · ChatGPT subscription {#get-started}

These are the setup steps for Midscene on **HarmonyOS** with **Vitest** and a **ChatGPT subscription**. 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`.

## Connect the HarmonyOS device
Midscene uses `hdc` on your computer to communicate with the target HarmonyOS NEXT device. If `hdc` is already installed and your device is connected, skip directly to [Verify the device connection](#verify-device-connection).

### Install HDC

HDC (HarmonyOS Device Connector) is the official command-line tool for communicating with HarmonyOS devices. Install it using either of the following methods:

- Via [DevEco Studio](https://developer.huawei.com/consumer/en/deveco-studio/) (recommended)
- Via the standalone [HarmonyOS Command Line Tools](https://developer.huawei.com/consumer/en/download/)

Run the following command to verify the installation:

```bash
hdc version
```

A version number in the terminal output confirms a working installation.

:::info Configuring the HDC path

If `hdc` is not in your system `PATH`, set the `HDC_HOME` environment variable to the directory containing the `hdc` executable:

```bash
export HDC_HOME=/path/to/hdc/directory
```

:::

### Enable debugging and connect the device

1. On your HarmonyOS device, open **Settings > System > Developer options** and enable **USB debugging**.
2. Connect the device to your computer using a USB cable that supports data transfer.
3. Keep the device unlocked and accept the debugging authorization prompt on the screen.

### Verify the device connection {#verify-device-connection}

Run the following command to check the connection status:

```bash
hdc list targets
```

A device ID in the output confirms that the device is connected and ready:

```log
0123456789ABCDEF
```

If multiple devices are connected, note the target device ID so you can select it in Playground or your project configuration. If the output is empty or `[Empty]`, check the USB cable, USB connection mode, **USB debugging** toggle, and the authorization prompt on the device.

## Sign in with your ChatGPT subscription
First, run the following command in your terminal:

```bash
pnpm dlx @midscene/cli model siwc login
```

Follow the terminal instructions to sign in to ChatGPT in your browser and authorize plan usage. You can choose a name for your Agent during authorization. Once authorized, the Agent appears on your ChatGPT usage page.

The command saves credentials to `~/.midscene/siwc.json`. Complete this sign-in manually before first use.

Then write these lines 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.

```bash
MIDSCENE_MODEL_AUTH_MODE="siwc"
MIDSCENE_MODEL_NAME="gpt-6-sol"
MIDSCENE_MODEL_FAMILY="gpt-6"
```
Available models depend on your ChatGPT account. For credentials and usage, see [Use a ChatGPT subscription](/chatgpt-subscription.md#usage-and-credentials).

## 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/harmony
```

### 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 { agentFromHdcDevice } from '@midscene/harmony';

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

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

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.launch('com.huawei.hmos.settings');
  await agent.aiWaitFor('The Settings app is visible');
  await agent.aiAct('Scroll down one screen');
  await agent.aiAssert('The Settings app is still visible');
});
```
If multiple devices are connected, pass a device ID to `agentFromHdcDevice(deviceId)`. See the [HarmonyOS SDK guide](/sdk/harmonyos.md) for 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.
