Skip to main content
@reticlehq/test is Reticle’s spec runner for CI. It turns an interactive session into a suite that runs on every pull request, without an agent and without paying model tokens to re-derive the same checks. Install it when you want unattended verification; skip it if you only ever drive Reticle interactively through MCP. Licensed under Apache-2.0. Depends on @reticlehq/core and @reticlehq/server. Optional peer dependency: vitest ^3.2.6 || ^4.0.0.

Why it exists

Driving interactively is reconnaissance. At some point you want the same checks to run unattended. This package invokes the tool layer directly, so a spec is the same evidence an agent would have gathered, minus the model.

Booting a session

BootOptions

bootSession resolves to BootedRun: { invoke: ToolInvoker; close: () => Promise<void> }.

Writing specs

reticleTest(name: string, fn: SpecFn): void registers into a module-level registry. register, getRegistered and clearRegistry are exported for anyone driving it themselves. SpecFn types its argument as SpecContext, which is TestContext, so the methods below are typed without a cast.

The test context

createTestContext(invoke: ToolInvoker, options?: TestContextOptions): TestContext, where TestContextOptions is { sessionId?: string; defaultTimeoutMs?: number } and the timeout defaults to DEFAULT_ASSERT_TIMEOUT_MS.

Running and reporting

RunnerOptions is { invoke; buildContext; now; print?; specs? }. RunSummary is { total, passed, failed, skipped, ok }.

Saved flows as specs

A recorded flow becomes a spec without being rewritten: flowToSpec, flowsAsSpecs, registerFlowSpecs, with assertSuccess, successToPredicate, and the FlowSpec, FlowSpecOptions and FlowsAsSpecsOptions types. Malformed flows raise FlowMalformedError.

Errors and control flow

ReticleSkip and isSkip for skipping, ReticleAssertionError with an AssertionDetail, ReticleQueryEmptyError when a query matched nothing. Constants: TestStatus, SpecKind, SpecOutcome, SpecMessage, PredicateKind, STATUS_GLYPH, SUMMARY_FOOTER_PREFIX, JUnit, DEFAULT_JUNIT_SUITE_NAME, SKIP_REASON_REAL_INPUT, PROBE_TESTID, FLOW_LOAD_ERROR_PREFIX, DEFAULT_ASSERT_TIMEOUT_MS. Also exported: resolveTestid, and the standalone expectInputModeReal, InputModeTracker and readInputMode.

Turning a session into a suite

Writing specs that bind to signals rather than DOM structure.
Last modified on October 29, 2026