TanCat logo
TanCat tancat-0.1.0
BYO-LLM · BOUNDED EGRESS · RUNS OFFLINE

The AI test generator that keeps your data on your own machines.

Paste a user story → generate executable Playwright pytest tests from your own LLM, on your own machines. Point it at a local or self-hosted model and nothing leaves your network; cloud OpenAI and OpenRouter work too. It even learns from your reference docs — point it at a local model and those stay in-house.

TanCat — Product UI
Real TanCat Streamlit UI: the Run & Fix view with the generated Playwright pytest code, the Final Code / Skeleton / Scrape Summary tabs, and the sidebar settings.
Streamlit Web UIReal product capture - launch_ui.sh output
No telemetry · 100% private
$git clone https://github.com/tancat-ai/tancat && cd tancat && uv sync && bash launch_ui.sh
How It Works

Story → Generate → Run → Evidence → Export

One seamless loop that completes end-to-end, with locators taken from the real rendered DOM — not guessed.

1

Paste a User Story

Plain language Jira ticket, user acceptance criteria, or markdown spec. That's the only input — no syntax to learn or test framework to master. Or upload a spec doc — the LLM learns from it, and it stays in-house.

“As an admin, clicking 'Revoke Token' opens confirm modal.”
2

Generate against the live DOM

TanCat launches headless Chromium, inspects real DOM nodes, builds a page skeleton, and feeds exact attributes to your own LLM. Resolution is score-gated: an unresolved criterion is reported as a skip, never as a guess.

Resolved: button[data-testid="revoke-access-confirm"]
3

Run, Evidence, Export

TanCat executes the generated test, records screenshots, and writes out evidence in the shape each role needs: a suite heatmap for the product owner, a Gantt timeline for the test manager, and JUnit/HTML/CSV for the rest.

PASSED 1/1 (0.84s)test_report.html
Live DOM Resolution Engine

See how plain English becomes ground-truth Pytest.

Locators aren't guessed. TanCat scrapes the live DOM and resolves against real attributes — with score-gated confidence — before it prompts, so every selector traces back to the rendered page.

Session: #TAN-8921
DOM Synthesized[Example BYO model: Llama-3-70B-Q4 / Ollama / llama.cpp]
1. Input User StoryJira Acceptance

# Feature: High-Value Wire Confirmation

1. Navigate to /transfers/wire
2. Input amount: “50000”
3. Select beneficiary: “Escrow Alpha”
4. Click “Submit Wire”
5. Verify 2FA modal with ID #two-factor-dialog

Auto-Extracted Intent:
✓ form_fill(amount, beneficiary)
✓ action_click(submit_button)
✓ assert_visible(modal_overlay)
2. Live Scraped DOM TreeChromium v126
<form id="wire-transfer-form" data-state="ready">
<input name=“transfer_amt” data-testid=“wire-amount-input” />
↳ Resolved: [data-testid="wire-amount-input"] (Score: 0.99)
<button type=“button” id=“submit-wire-btn” > Submit Wire </button>
↳ Resolved: #submit-wire-btn (Unique XPath, Safe)
</form>
<dialog id="two-factor-dialog" class="modal-open">...</dialog>
Ground-truth resolution:Score-gated (a criterion that will not resolve is a skip)
3. Playwright PytestPASSED
test_wire.pyjunit.xmlreport.html
import pytest
from playwright.sync_api import Page, expect

@pytest.mark.egress_gated
def test_wire_confirmation_modal(page: Page):
    page.goto("/transfers/wire")
    page.locator('[data-testid="wire-amount-input"]').fill("50000")
    page.locator('select[name="beneficiary"]').select_option("escrow_alpha")
    page.locator('#submit-wire-btn').click()
    modal = page.locator('dialog#two-factor-dialog')
    expect(modal).to_be_visible()
    expect(modal).to_contain_text("Confirm Authorization")
Execution completed in 0.62sEvidence saved: ./evidence/wire_01.tar.gz
UI, CLI and CI

One engine. Run it your way.

The Streamlit UI, the tancat CLI, and the CI Action all run the same generation pipeline against your own LLM. There is no second implementation to trust.

CLI — tancat run

real run
TanCat CLI: a real tancat run generates five pytest tests from a short story; the pipeline stages and the final summary are shown.

Generate, run, or gate an existing suite from the terminal or your own scripts. Same story, same LLM, same evidence as the UI.

CI — GitHub Action & GitLab template

CI: passing
TanCat CI: a real Action self-test run on main, showing the job steps - generate and run, assert, cache, upload artifacts.

The GitHub Action and the GitLab include template run the same headless pipeline on a pull or merge request: generate (or restore from cache), run pytest as the referee, attach JUnit evidence, and comment the result. The exit code is pytest's, so a red run is your change, not the tool's opinion.

It runs on your runner against your own LLM endpoint - nothing is sent to a vendor cloud. CI reference.

Security & Architecture

Built for teams that cannot send their data to a vendor cloud.

Your LLM, your machines, no vendor cloud. TanCat runs on your machines, pointed at your own LLM, so your customer data stays where you put it.

🦒

BYO-LLM Architecture

Native compatibility with llama.cpp, Ollama, LM Studio, or an in-cluster private vLLM endpoint. Swap models anytime with zero vendor lock-in.

LLM_PROVIDER=openai-local · OPENAI_BASE_URL=http://127.0.0.1:8080/v1
🛡

Bounded Egress (Verified in CI)

Runtime outbound calls are strictly limited to your configured LLM endpoint and your target application. Point it at a local or self-hosted LLM and nothing leaves your network; cloud OpenAI and OpenRouter are supported too. A scan in CI fails the build on any new outbound call site - see the published egress audit.

Audit gate: run in CI
🪁

Self-Healing Locators

When markup or CSS class names drift, TanCat re-resolves the locator against the live DOM, patches the test, and re-runs it - after a failure, so the fix is proven by the re-run.

Re-resolves a drifted locator against the live DOM and re-runs the test.
📊

Evidence and Reports

Real evidence, not just a vague checkmark: HTML reports, CSV logs, JUnit XML, and NDJSON (newline-delimited JSON, one record per line).

HTML ReportsCSV LogsNDJSONJUnit XML
⚙

Native CI/CD Action & POM Mode

Organizes test code into maintainable Page-Object-Model (POM) python classes automatically. POM mode and the CI/CD Action are Pro features, and the CI runner must be able to reach your LLM endpoint. Drop the reusable GitHub Action or GitLab CI template into your existing pipelines.

GitHub ActionsGitLab CIPOM Pattern
Egress Audit Verified (Automated CI Gate)

The runtime makes outbound calls only to your LLM endpoint and your own target site.

No background calls to PyPI. No tracking beacons. Two components fetch model weights from Hugging Face on first use, and both can be pre-seeded: the RAG embedder, and the optional GPU OCR backend (off by default; OCR_BACKEND=power turns it on). The default OCR path is the CPU one (RapidOCR, offline, and the path that runs today); the GPU OCR path needs CUDA or ROCm, and its live path is untested. A scan in CI fails the build on any new outbound call site. LLM traffic is constrained to your trusted endpoint, and target traffic is strictly SSRF-guarded.

BOUNDED EGRESS TOPOLOGYISOLATED
TanCat Engine (Your Host)
↕ Egress-audited / localhost / private IP
IN-PERIMETERLocal LLM
IN-PERIMETERTarget App DOM
✕ Product runtime egress: LLM + target only
Predictable Model

Per deployment, not per seat.

Deploy it once per company, per infra. You should never be penalized when your entire QA and dev squad writes reliable tests.

Developer / OSS

Free Community

For solo developers, or for local debugging.

$0 / forever
  • ✓25 test runs per 30 days
  • ✓10 evidence exports per 30 days
  • ✓Self-healing locators, remembers your site’s DOM
  • ✓Your own LLM, bounded egress
  • ✓Playwright Pytest test generator
Most Popular
Engineering Team

Pro Deployment

No run caps, and the Jira export, for teams that bill test work to a project.

Perpetual licence / deployment
Pricing announced at launch - request a licence.
  • ✓Unlimited test runs & evidence exports
  • ✓Jira evidence export
  • ✓Email support and setup help - direct from the developer
  • ✓Perpetual licence · 12 months of updates included

install & activate guide

* Per-deployment pricing. Prices exclude taxes. A deployment is one installation serving one organisation.
Update policy: a licence is perpetual for the version you buy and includes 12 months of updates. Updates after that are paid. Security fixes and bug fixes in your version line stay free. Updates arrive as files on Lemon Squeezy and on the releases page - TanCat makes no runtime update check.
Need a custom arrangement? Talk to us — enterprise arrangement, priced case by case, not a published tier.
Fast Setup

Clone + uv sync + run

TanCat uses uv for fast, reproducible dependencies.

# Terminal (macOS / Linux / WSL2)bash
# 1. Prerequisites: Python 3.14+, uv, local LLM server
# (llama.cpp @ localhost:8080, Ollama, or LM Studio)
# 2. Clone and prepare dependencies
$ git clone https://github.com/tancat-ai/tancat
$ cd tancat
$ uv sync
$ playwright install chromium
# 3. Launch the visual mission control
$ bash launch_ui.sh
# (or headless CLI: bash launch_cli.sh)

What you need

  • •Python 3.14+ runtime with uv
  • •Local OpenAI-compatible API endpoint (llama.cpp, Ollama, or LM Studio)
  • •Chromium browser binary (installed by playwright)
  • •Target staging URL or localhost dev server
Get Started

Contact us

Tell us about your deployment — your stack, your LLM, whether it runs online or fully offline. We’ll set you up with a licence and point you to the right arrangement.

Email us
hello@tancat.dev

Support is provided by email at hello@tancat.dev, by the developer who builds TanCat. You get help with installation, licensing, and defects in TanCat. We aim to reply within two working days, Monday to Friday, UK business hours. Support does not include custom development, third-party systems, or on-site work, and we do not offer telephone or out-of-hours support. A contractual service level is available on request. Per-deployment pricing · no per-seat charges.

Your message is used only to answer you — see Privacy.