Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Launch browsers, desktop apps, and extensions in your sandbox
.claude/skills/testdriverai-testdriver-provision/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-16 | ✗→✓ | ▲ Improved | 98% | 0% |
| case-01 | ✗→✓ | ▲ Improved | 142% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 101% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 76% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 60% | 0% |
<!-- Generated from provision.mdx. DO NOT EDIT. -->
The Provision API sets up applications in your sandbox before tests run. It handles downloading, installing, and launching browsers, desktop apps, VS Code, Chrome extensions, and more.
Access provision methods via testdriver.provision.*:
javascriptawait testdriver.provision.chrome({ url: 'https://example.com' });
<Note> When reconnect: true is set on the client, all provision methods are skipped since the application is assumed to already be running. </Note>
Launch Google Chrome with an optional URL.
javascriptawait testdriver.provision.chrome(options?)
<ParamField path="options" type="ProvisionChromeOptions"> <Expandable title="properties"> <ParamField path="url" type="string" default="http://testdriver-sandbox.vercel.app/"> URL to navigate to after launch. </ParamField>
<ParamField path="maximized" type="boolean" default={true}> Launch Chrome in maximized window mode. </ParamField>
<ParamField path="guest" type="boolean" default={false}> Launch Chrome in guest profile mode. </ParamField> </Expandable> </ParamField>
javascript// Basic await testdriver.provision.chrome({ url: 'https://example.com' }); // With guest mode await testdriver.provision.chrome({ url: 'https://example.com', guest: true, maximized: true, });
Install and launch a Chrome extension. You can install from a local unpacked directory or from the Chrome Web Store by extension ID.
javascriptawait testdriver.provision.chromeExtension(options)
<ParamField path="options" type="ProvisionChromeExtensionOptions" required> One of extensionPath or extensionId is required.
<Expandable title="properties"> <ParamField path="extensionPath" type="string"> Local path to an unpacked extension directory. The extension files are uploaded to the sandbox. </ParamField>
<ParamField path="extensionId" type="string"> Chrome Web Store extension ID to install. </ParamField>
<ParamField path="maximized" type="boolean" default={true}> Launch Chrome in maximized window mode. </ParamField> </Expandable> </ParamField>
javascript// From local directory await testdriver.provision.chromeExtension({ extensionPath: './my-extension', }); // From Chrome Web Store await testdriver.provision.chromeExtension({ extensionId: 'abcdefghijklmnop', });
Launch Visual Studio Code with an optional workspace and extensions.
javascriptawait testdriver.provision.vscode(options?)
<ParamField path="options" type="ProvisionVSCodeOptions"> <Expandable title="properties"> <ParamField path="workspace" type="string"> Path to a workspace folder or .code-workspace file to open. </ParamField>
<ParamField path="extensions" type="string]" default={]}> Array of VS Code extension IDs to install before launching. </ParamField> </Expandable> </ParamField>
javascriptawait testdriver.provision.vscode({ workspace: '/home/testdriver/project', extensions: ['ms-python.python', 'esbenp.prettier-vscode'], });
Download and run an application installer. Supports .msi, .exe, .deb, .rpm, .appimage, .sh, .dmg, and .pkg formats.
javascriptawait testdriver.provision.installer(options)
<ParamField path="options" type="ProvisionInstallerOptions" required> <Expandable title="properties"> <ParamField path="url" type="string" required> Download URL for the installer. </ParamField>
<ParamField path="filename" type="string"> Override the auto-detected filename from the URL. </ParamField>
<ParamField path="appName" type="string"> Application name to focus after installation completes. </ParamField>
<ParamField path="launch" type="boolean" default={true}> Whether to focus/launch the app after installation. </ParamField> </Expandable> </ParamField>
Behavior:
msiexec for .msi, dpkg for .deb)javascript// Windows MSI installer await testdriver.provision.installer({ url: 'https://example.com/app-setup.msi', appName: 'MyApp', }); // Linux DEB package await testdriver.provision.installer({ url: 'https://example.com/app.deb', appName: 'MyApp', launch: true, });
Launch an Electron application.
javascriptawait testdriver.provision.electron(options)
<ParamField path="options" type="ProvisionElectronOptions" required> <Expandable title="properties"> <ParamField path="appPath" type="string" required> Path to the Electron application directory or executable. </ParamField>
<ParamField path="args" type="string]" default={]}> Additional command-line arguments to pass to the Electron app. </ParamField> </Expandable> </ParamField>
javascriptawait testdriver.provision.electron({ appPath: '/home/testdriver/my-electron-app', args: ['--no-sandbox'], });
Start Dashcam recording with custom options. Usually called automatically by other provision methods, but can be called directly for custom configurations.
javascriptawait testdriver.provision.dashcam(options?)
<ParamField path="options" type="ProvisionDashcamOptions"> <Expandable title="properties"> <ParamField path="logPath" type="string"> Path to the TestDriver log file. Defaults to /tmp/testdriver.log (Linux) or C:\Users\testdriver\testdriver.log (Windows). </ParamField>
<ParamField path="logName" type="string" default="TestDriver Log"> Display name for the log file in the Dashcam replay. </ParamField>
<ParamField path="webLogs" type="boolean" default={true}> Enable web traffic log capture. </ParamField>
<ParamField path="title" type="string"> Recording title for the Dashcam session. </ParamField> </Expandable> </ParamField>
javascriptawait testdriver.provision.dashcam({ title: 'Login Flow Test', logPath: '/tmp/my-app.log', logName: 'Application Log', webLogs: true, });
When reconnect: true is set on the client, all provision methods are wrapped in a Proxy that intercepts calls and skips them silently. This is because when reconnecting to an existing sandbox, the applications are already running.
javascriptconst testdriver = new TestDriver({ reconnect: true, }); await testdriver.ready(); // These calls are silently skipped: await testdriver.provision.chrome({ url: 'https://example.com' }); await testdriver.provision.dashcam();
typescriptinterface ProvisionChromeOptions { url?: string; // Default: "http://testdriver-sandbox.vercel.app/" maximized?: boolean; // Default: true guest?: boolean; // Default: false } interface ProvisionChromeExtensionOptions { extensionPath?: string; // Local unpacked extension path extensionId?: string; // Chrome Web Store ID maximized?: boolean; // Default: true } interface ProvisionVSCodeOptions { workspace?: string; // Workspace path extensions?: string[]; // Extension IDs to install } interface ProvisionInstallerOptions { url: string; // Download URL (required) filename?: string; // Override filename appName?: string; // App name to focus launch?: boolean; // Default: true } interface ProvisionElectronOptions { appPath: string; // Path to Electron app (required) args?: string[]; // Additional args } interface ProvisionDashcamOptions { logPath?: string; // Log file path logName?: string; // Default: "TestDriver Log" webLogs?: boolean; // Default: true title?: string; // Recording title }
javascriptimport { describe, it, beforeAll, afterAll } from 'vitest'; import TestDriver from 'testdriverai'; describe('Chrome Extension Test', () => { let testdriver; beforeAll(async () => { testdriver = new TestDriver({ os: 'linux', resolution: '1920x1080', }); await testdriver.ready(); // Install extension and open Chrome await testdriver.provision.chromeExtension({ extensionPath: './my-extension', }); // Start Dashcam with custom logs await testdriver.provision.dashcam({ title: 'Extension Test', webLogs: true, }); }); afterAll(async () => { await testdriver.disconnect(); }); it('tests the extension popup', async () => { await testdriver.find('extension icon').click(); await testdriver.find('popup content').click(); }); });
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-21 | pass→pass | 6,047 | 1,930 | -68% | 1 | 1 | 0% | 1,163 | 2,685 | +131% | 0 | 0 | — |
case-16 | fail→pass | 7,579 | 2,285 | -70% | 1 | 1 | 0% | 1,391 | 2,754 | +98% | 0 | 0 | — |
case-01 | fail→pass | 6,762 | 17,614 | +160% | 1 | 1 | 0% | 1,270 | 3,072 | +142% | 0 | 0 | — |
case-02 | fail→pass | 9,310 | 4,543 | -51% | 1 | 1 | 0% | 1,660 | 3,343 | +101% | 0 | 0 | — |
case-03 | fail→pass | 12,590 | 8,239 | -35% | 1 | 1 | 0% | 2,284 | 4,020 | +76% | 0 | 0 | — |
case-04 | fail→pass | 9,814 | 2,035 | -79% | 1 | 1 | 0% | 1,652 | 2,643 | +60% | 0 | 0 | — |
case-05 | fail→pass | 12,684 | 3,041 | -76% | 1 | 1 | 0% | 2,302 | 2,912 | +26% | 0 | 0 | — |
case-06 | fail→pass | 6,957 | 1,389 | -80% | 1 | 1 | 0% | 1,054 | 2,511 | +138% | 0 | 0 | — |
case-07 | fail→pass | 8,802 | 1,525 | -83% | 1 | 1 | 0% | 1,418 | 2,529 | +78% | 0 | 0 | — |
case-08 | fail→pass | 5,752 | 3,005 | -48% | 1 | 1 | 0% | 1,045 | 2,872 | +175% | 0 | 0 | — |
case-09 | pass→pass | 10,348 | 2,204 | -79% | 1 | 1 | 0% | 1,582 | 2,685 | +70% | 0 | 0 | — |
case-10 | fail→pass | 7,746 | 2,489 | -68% | 1 | 1 | 0% | 1,273 | 2,786 | +119% | 0 | 0 | — |
case-11 | fail→pass | 13,294 | 1,834 | -86% | 1 | 1 | 0% | 2,184 | 2,581 | +18% | 0 | 0 | — |
case-12 | fail→pass | 12,207 | 4,000 | -67% | 1 | 1 | 0% | 2,003 | 3,062 | +53% | 0 | 0 | — |
case-13 | pass→pass | 11,379 | 2,368 | -79% | 1 | 1 | 0% | 1,916 | 2,640 | +38% | 0 | 0 | — |
case-14 | pass→pass | 4,538 | 1,546 | -66% | 1 | 1 | 0% | 681 | 2,550 | +274% | 0 | 0 | — |
case-15 | pass→pass | 6,700 | 1,886 | -72% | 1 | 1 | 0% | 956 | 2,628 | +175% | 0 | 0 | — |
case-17 | fail→pass | 11,391 | 3,583 | -69% | 1 | 1 | 0% | 1,665 | 3,093 | +86% | 0 | 0 | — |
case-18 | fail→pass | 7,325 | 2,156 | -71% | 1 | 1 | 0% | 1,112 | 2,566 | +131% | 0 | 0 | — |
case-19 | fail→pass | 4,411 | 2,005 | -55% | 1 | 1 | 0% | 716 | 2,643 | +269% | 0 | 0 | — |
case-20 | pass→pass | 7,531 | 4,727 | -37% | 1 | 1 | 0% | 1,372 | 3,287 | +140% | 0 | 0 | — |
case-22 | pass→pass | 9,276 | 1,125 | -88% | 1 | 1 | 0% | 1,563 | 2,505 | +60% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +68 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.