# Use Retest from code

> Run test files from your program, receive events and add checks your host controls.

Source: https://rehearsal.dev/retest/docs/scaling-up/from-code

Use `runFiles` when a script, worker or service needs to run Retest directly. Your program is the host. It supplies the configuration and run folder, then receives events and the final result.

## Run a test file

The authoring helpers come from the root package; host functions come from `@rehearsal-labs/retest/runner`. Build a config in memory, validate it and resolve its secrets before calling the runner.

```ts filename="host.ts"
import type { Reporter } from '@rehearsal-labs/retest/runner'
import { randomUUID } from 'node:crypto'
import { resolve } from 'node:path'
import { chrome, defineConfig } from '@rehearsal-labs/retest'
import {
  defaultTimeouts,
  resolveSecrets,
  runFiles,
  validateConfig,
} from '@rehearsal-labs/retest/runner'

const rootDir = process.cwd()
const loaded = validateConfig(
  defineConfig({
    apps: { web: chrome({ baseUrl: 'http://127.0.0.1:4173' }) },
  }),
  resolve(rootDir, 'host.config.ts'),
)
if (!loaded.ok) throw new Error(loaded.failure.message)

const secrets = resolveSecrets(loaded.config, process.env)
if (!secrets.ok) throw new Error(secrets.failure.message)

const reporter: Reporter = {
  name: 'host',
  onEvent(event) {
    process.stdout.write(`${JSON.stringify(event)}\n`)
  },
  onRunEnd() {},
}

const stop = new AbortController()
process.once('SIGINT', () => stop.abort('SIGINT'))
process.once('SIGTERM', () => stop.abort('SIGTERM'))

const result = await runFiles({
  files: ['tests/task.retest.ts'],
  rootDir,
  apps: { kind: 'config', config: loaded.config, secrets: secrets.secrets },
  timeouts: defaultTimeouts,
  outputDir: resolve(rootDir, '.retest/runs', randomUUID()),
  lastRunFile: false,
  headless: true,
  signal: stop.signal,
  testEnvironment: {},
}, [reporter])

process.exitCode = result.exitCode
```

Run this script with `node host.ts` from a project containing the task test and an app already serving that address. The random id gives each call a new output folder because Retest refuses one that already holds files. Your reporter receives events in sequence while the run proceeds.

The path passed to `validateConfig` labels the config and anchors relative paths; no config file needs to exist there. `lastRunFile: false` leaves history management to your host. An empty `testEnvironment` gives the test process none of your application environment; pass only variables the test actually needs.

## Supply secrets

A host can use `env` sources or functions that read a vault. `resolveSecrets` reads environment sources once and keeps function sources for later use. To use your vault client, replace the config passed to `validateConfig` with this fragment:

```ts
defineConfig({
  apps: { web: chrome({ baseUrl: 'http://127.0.0.1:4173' }) },
  secrets: {
    password: ({ signal }) => vault.read('task-app-password', { signal }),
  },
})
```

Here `vault` is your own credential service, and the function stays in the host process. Test code uses `secret('password')` without receiving the value. A config with only function sources can use an empty environment map when resolving secrets.

## Add host checks

Host checks let your program require facts about the final page independently of assertions in the test body. Add this option to `runFiles` to check both the address and visible saved title:

```ts
hostChecks: {
  'tests/task.retest.ts': [
    { kind: 'address', origin: 'http://127.0.0.1:4173', path: '/' },
    { kind: 'text', text: 'Release checklist' },
  ],
},
```

A file key applies to every test collected from that file, including setups. To require a check on only one test, use its full test id as the key. After a passing body and its cleanup hooks, Retest runs the checks before closing pages; a failed host check fails the test.

Address checks compare the origin and optional path, leaving queries and fragments out. Text checks read the top-level body's visible text, excluding frames, shadow roots and hidden elements. They prove the final state, not the steps used to reach it. A check targeting no selected test or file is refused before a browser starts.

## Stop and read a run

Abort the signal to stop a run. The example forwards SIGINT and SIGTERM, which produce interrupted results and exit codes 130 and 143. A host can also abort with a structured interruption reason, which Retest records and reports with exit code 130.

```ts
stop.abort({
  class: 'interrupted',
  message: 'The host is shutting down, so it stopped the run.',
})
```

To inspect evidence later, read the run folder through the runner subpath. This validates the files and returns the result, events and any warnings.

```ts
import { readRunFolder } from '@rehearsal-labs/retest/runner'

const folder = readRunFolder('/path/to/run')
process.stdout.write(`${folder.result.status}\n`)
for (const warning of folder.warnings) process.stderr.write(`${warning}\n`)
```

If `result.json` was never written, the reader reconstructs the run from events and marks it incomplete. For concurrent calls, give every run a separate output folder and share a [session budget](https://rehearsal.dev/retest/docs/scaling-up/parallel-runs.md) when you need a common limit.

## Host boundaries

Take the authoritative result from `runFiles` and events from your reporter. The run folder contains copies that the test process can write, so a host evaluating untrusted tests should not treat those copies as independent proof.

> [!WARNING]
> **Test execution**
>
> The test process is not a sandbox. It runs as the same user and can access that user's files and network. A host running code it did not write must isolate the whole Retest run, for example in a container it controls.

For an agent that needs to drive a session interactively instead of running test files, use `@rehearsal-labs/retest/agent`. [Coding agents](https://rehearsal.dev/retest/docs/coding-agents.md) explains where those sessions fit.

## Next steps

- [Parallel runs](https://rehearsal.dev/retest/docs/scaling-up/parallel-runs.md): Share a session limit across runs in your host.
- [Run folder and events](https://rehearsal.dev/retest/docs/reference/run-folder.md): Read saved evidence and the event format.
- [Coding agents](https://rehearsal.dev/retest/docs/coding-agents.md): Use interactive sessions when building an agent.
