Skip to content

tailtest

You build. We cover.

tailtest watches every file Claude writes and automatically generates tests for it -- no prompting, no configuration, no test runner setup (beyond what you already have).

When tests pass, you get one line of confirmation. When something fails, you get one line with "want me to fix this?" That is the entire interaction.


Choose your platform

tailtest works with three AI coding tools. Pick the one you use:

Platform Install time How it works
Claude Code 30 seconds Claude Code plugin -- hooks fire automatically inside the Claude CLI
Cursor 2 minutes Cursor hooks -- fires after every file save, triggers a test turn
Codex 2 minutes Codex hooks -- mtime sweep at turn end, blocks to run tests before continuing

What tailtest does

After any Claude-written file lands in your project:

  1. Tailtest generates scenarios that describe real business behavior -- not function signatures
  2. It runs them using your existing test runner (pytest, vitest, jest, go test, and more)
  3. If all pass: tailtest: 6 scenarios -- all passed.
  4. If something fails: one line surfaced, "want me to fix this?"

Example: Claude builds a billing service. Tailtest generates: "Create invoice at $800 against a $1,000 credit limit -- verify it succeeds. Create invoice at $1,200 -- verify it is rejected." Runs them. If the credit-limit check has a bug, you see it before you move on.


Supported languages

Language Runner Test location
Python pytest (with pytest-asyncio auto-detected) tests/test_{name}.py
TypeScript vitest / jest / bun test / deno test __tests__/{name}.test.ts (or colocated for Deno)
JavaScript vitest / jest / bun test __tests__/{name}.test.js
Go go test colocated {name}_test.go
Ruby rspec / minitest spec/{name}_spec.rb or test/{name}_test.rb
PHP (Laravel) phpunit tests/Feature/ or tests/Unit/
Java Maven / Gradle src/test/java/{Name}Test.java
Kotlin Maven / Gradle (with Kotlin plugin) src/test/kotlin/{Name}Test.kt
C# / .NET dotnet test *.Tests/{SourceName}Tests.cs (sibling test project by convention)
Rust cargo test inline #[cfg(test)] module

Supported frameworks

When a framework is detected, tailtest layers framework-keyed baseline scenarios on top of the language baselines. The framework is written to session.json so every test generated during the session knows to include these scenarios.

Framework Detection signal Baseline scenarios always included
Django (Python) manage.py present Auth required / rejected, model field validation, URL routing
FastAPI (Python) fastapi in pyproject deps Valid body / missing field (422) / wrong type (422), app.dependency_overrides
Flask (Python) flask in pyproject deps Valid route (200) / unknown (404), blueprint registration, test_client + app context, validation rejection
Next.js (JS/TS) next in package.json deps Component renders with required props, missing optional props, loading / loaded / error states
NestJS (JS/TS) @nestjs/core in package.json deps DTO validation pass / fail, guard rejects unauthenticated, Test.createTestingModule provider override, controller or microservice harness
Nuxt (JS/TS) nuxt in deps or nuxt.config.{ts,js} mountSuspended render, required props, async setup
Rails (Ruby) rails in Gemfile Valid record saves, invalid record fails validation, unauthorized request rejected
Laravel (PHP) laravel/framework in composer.json + artisan Valid input, validation failure (422), unauthenticated rejection
Spring Boot (Java) spring-boot in pom.xml or build.gradle Valid request (200), missing field (400), unauthenticated (401), @WebMvcTest slice, @MockBean service override

Precedence when multiple signals are present: manage.py wins for Django. For other Python frameworks, when both flask and fastapi are declared (rare, e.g. mid-migration), tailtest inspects entry-point files (app.py, main.py, wsgi.py, asgi.py) for Flask(__name__) or FastAPI() to pick the right one. For Node, @nestjs/core is checked before next. Monorepos with different frameworks per workspace are detected per-package.


Initial coverage scan

The first time tailtest starts on an existing project, it scans your codebase and queues the most important files for an initial coverage pass. Files are ranked by git activity, path (services and models score higher), and size. The top 7 are queued by default.

Before running them, you see: tailtest: initial coverage scan -- first session detected. 7 file(s) queued for coverage.

This runs once. A sentinel file prevents it from re-firing on restart. You can control how many files are scanned with the ramp_up_limit config option.


Escape hatch

Add a .tailtest-ignore file at your project root (gitignore syntax) to silence specific paths:

scripts/
generated/*.py
fixtures/

Session state

Tailtest writes .tailtest/session.json during each session. Add .tailtest/ to your .gitignore to keep it out of version control.