testdriver-agent
How the TestDriver agent behaves on GitHub issues, pull requests, and @mentions
Listen to SDK lifecycle events with wildcard support
$ npx -y skills add testdriverai/testdriverai --skill testdriver-events --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/testdriver-eventsContext preview
The summary Claude sees to decide when to auto-load this skill.
Listen to SDK lifecycle events with wildcard support
name: testdriver:events description: Listen to SDK lifecycle events with wildcard support
<!-- Generated from events.mdx. DO NOT EDIT. -->
TestDriver uses [EventEmitter2](https://github.com/EventEmitter2/EventEmitter2) for its event system. Events use a colon-delimited namespace pattern and support wildcard listeners.
Access the emitter through `testdriver.emitter`:
testdriver.emitter.on('command:start', (data) => {
console.log(`Running: ${data.command}`);
});The internal emitter is created with:
new EventEmitter2({
wildcard: true,
delimiter: ':',
maxListeners: 20,
verboseMemoryLeak: false,
ignoreErrors: false,
});Use `*` to match a single level or `**` to match multiple levels:
// Match all log events
testdriver.emitter.on('log:*', (message) => {
console.log(message);
});
// Match all events in any namespace
testdriver.emitter.on('**', (...args) => {
console.log('Event:', this.event, args);
});Emitted during the execution of SDK commands (`click`, `type`, `find`, etc.).
| Event | Payload | |---|---| | `command:start` | `{ command, depth, data, timestamp, sourcePosition }` | | `command:success` | `{ command, depth, data, duration, response, timestamp, sourcePosition }` | | `command:error` | `{ command, depth, data, error, duration, timestamp, sourcePosition }` | | `command:status` | `{ command, status: "executing", data, depth, timestamp }` | | `command:progress` | `{ command, status: "completed", timing, data, depth, timestamp }` |
testdriver.emitter.on('command:start', ({ command, data }) => {
console.log(`Starting ${command}`, data);
});
testdriver.emitter.on('command:error', ({ command, error, duration }) => {
console.error(`${command} failed after ${duration}ms: ${error}`);
});Emitted for each AI reasoning step within a command.
| Event | Payload | |---|---| | `step:start` | `{ stepIndex, prompt, commandCount, timestamp, sourcePosition }` | | `step:success` | `{ stepIndex, prompt, commandCount, duration, timestamp, sourcePosition }` | | `step:error` | `{ stepIndex, prompt, error, duration?, timestamp, sourcePosition? }` |
testdriver.emitter.on('step:start', ({ stepIndex, prompt }) => {
console.log(`Step ${stepIndex}: ${prompt}`);
});Emitted when a test file execution starts.
| Event | Payload | |---|---| | `test:start` | `{ filePath, timestamp }` | | `test:success` | *Emitted on test completion* | | `test:error` | *Emitted on test failure* |
Emitted for all log output from the SDK.
| Event | Payload | |---|---| | `log:log` | `(message: string)` — general log message | | `log:warn` | `(message: string)` — warning message | | `log:debug` | `(message: string)` — debug output (only when `VERBOSE`/`DEBUG`/`TD_DEBUG` env set) | | `log:info` | `(message: string)` — informational message | | `log:error` | `(message: string)` — error message | | `log:narration` | `(message: string, overwrite?: boolean)` — in-place status line | | `log:markdown` | `(markdown: string)` — full static markdown content | | `log:markdown:start` | `(streamId: string)` — begin streaming markdown | | `log:markdown:chunk` | `(streamId: string, chunk: string)` — incremental chunk | | `log:markdown:end` | `(streamId: string)` — end streaming markdown |
// Capture all logs
testdriver.emitter.on('log:*', function (message) {
console.log(`[${this.event}]`, message);
});Emitted during screenshot capture.
| Event | Payload | |---|---| | `screen-capture:start` | `{ scale, silent, display }` | | `screen-capture:end` | `{ scale, silent, display }` | | `screen-capture:error` | `{ error, scale, silent, display }` |
Emitted for sandbox WebSocket lifecycle and communication.
| Event | Payload | |---|---| | `sandbox:connected` | *No payload* — WebSocket connection established | | `sandbox:authenticated` | `{ traceId }` — authentication successful | | `sandbox:error` | `(err: Error \| string)` — connection or sandbox error | | `sandbox:sent` | `(message: object)` — WebSocket message sent | | `sandbox:received` | *No payload* — successful message reply received | | `sandbox:progress` | `{ step, message }` — sandbox setup progress |
testdriver.emitter.on('sandbox:connected', () => {
console.log('Connected to sandbox');
});
testdriver.emitter.on('sandbox:progress', ({ step, message }) => {
console.log(`Sandbox: [${step}] ${message}`);
});Emitted during screen stability detection. See [Redraw](/redraw) for more details.
| Event | Payload | |---|---| | `redraw:status` | `{ redraw: { enabled, settled, hasChangedFromInitial, consecutiveFramesStable, diffFromInitial, diffFromLast, text }, network: { enabled, settled, rxBytes, txBytes, text }, timeout: { isTimeout, elapsed, max, text } }` | | `redraw:complete` | `{ screenSettled, hasChangedFromInitial, consecutiveFramesStable, networkSettled, isTimeout, timeElapsed }` |
testdriver.emitter.on('redraw:complete', (result) => {
if (result.isTimeout) {
console.warn('Redraw timed out after', result.timeElapsed, 'ms');
}
});Emitted during file load/save operations in the agent.
| Event | Payload | |---|---| | `file:start` | `{ operation: "load" \| "save" \| "run", filePath, timestamp }` | | `file:stop` | `{ operation, filePath, duration, success, sourceMap?, reason?, timestamp }` | | `file:load` | `{ filePath, size, timestamp }` | | `file:save` | `{ filePath, size, timestamp }` | | `file:diff` | `{ filePath, diff: { patches, sourceMaps, summary: { additions, deletions, modifications } }, timestamp }` | | `file:error` | `{ operation, filePath, error, duration?, timestamp }` |
Emitted for errors at various severity levels.
| Event | P
Repo: testdriverai/testdriverai
How the TestDriver agent behaves on GitHub issues, pull requests, and @mentions
Deploy TestDriver on your AWS infrastructure using CloudFormation
How TestDriver learns your app and caches what it discovers for instant, deterministic replays