Every time my AI agent automated a website interaction, it was burning tokens to solve the same problem it had already solved last run. Find the API. Locate the selector. Compose the steps. Re-solved, re-paid, every single time.
I built Tap to fix this. The core idea: operating an interface is a solved problem the moment you figure out how. So separate the figuring-out (AI's job, done once) from the executing (a deterministic program's job, done forever).
The Paradigm: Forging
forge_inspect → forge_verify → forge_save → tap.run
AI analyzes AI tests AI saves runs forever, zero AI
AI analyzes the live site, creates a .tap.js file, and that file runs forever — no LLM calls, no prompts, no API keys. Runs in <1s. Returns structured data. Same result every time.
Cost model: ~$0.50 in tokens to forge. Then $0.00 at runtime, forever.
The Protocol
Tap defines a minimal, complete contract for interface automation:
8 core operations (irreducible atoms):
eval · pointer · keyboard · nav · wait · screenshot · run · capabilities
17 built-in operations (composed from core):
click · type · fill · hover · scroll · pressKey · select · upload · dialog
fetch · find · cookies · download · waitFor · waitForNetwork · ssrState · storage
8 + 17 = every interaction a human can perform on any interface.
A new runtime implements 8 methods → gets 17 built-ins free. Write a tap once, run it on Chrome, Playwright, macOS native apps — same protocol.
106 Ready-to-Use Skills
# Install
curl -fsSL https://raw.githubusercontent.com/LeonTing1010/tap/master/install.sh | sh
tap update # Pulls 106 skills across 50 sites
# Use
tap github trending --limit 5
tap hackernews hot
tap xiaohongshu hot
# Compose with Unix pipes
tap github trending | tap tap/filter --field stars --gt 1000
Skills cover GitHub, Reddit, YouTube, Hacker News, X/Twitter, Medium, arXiv, Bilibili, Zhihu, Xiaohongshu, Weibo, and 40+ more sites.
What a .tap.js looks like
// API-first: fetch data directly
export default {
site: "hackernews", name: "hot",
description: "Hacker News top stories",
health: { min_rows: 10, non_empty: ["title"] },
extract: async () => {
const ids = await fetch('https://hacker-news.firebaseio.com/v0/topstories.json').then(r => r.json())
const items = await Promise.all(ids.slice(0, 30).map(id =>
fetch(`https://hacker-news.firebaseio.com/v0/item/${id}.json`).then(r => r.json())
))
return items.map(i => ({ title: i.title, score: String(i.score), url: i.url, author: i.by }))
}
}
Pure JavaScript. Zero AI at runtime. The health contract means tap doctor can self-verify this tap automatically.
MCP Native
Works with Claude Code, Cursor, Windsurf, and any MCP-compatible agent:
{
"mcpServers": {
"tap": { "command": "tap", "args": ["mcp"] }
}
}
43 tools across 6 categories — run taps, forge new ones, inspect pages, intercept network traffic.
Security
Community taps are untrusted code. Three layers:
- Sandbox — Deno Worker, zero permissions (no filesystem, network, env)
- Static analysis — 7 CI checks on every PR to tap-skills
- Data isolation — secrets and sessions never leave your machine
How It Compares
| Tap | Browser-Use / Stagehand | Playwright | |
|---|---|---|---|
| AI at runtime | No (forge once) | Yes (every step) | No (manual scripts) |
| Detection risk | Undetectable | Detectable (CDP) | Detectable (headless) |
| Cost model | ~$0.50 once, then $0 | Tokens per session | Free (manual) |
| Reusable artifacts | .tap.js (shareable) | None (ephemeral) | None |
| Skills ecosystem | 106 across 50 sites | None | None |
GitHub
https://github.com/LeonTing1010/tap
106 skills, 3 runtimes, ~2,000 lines of Deno, zero dependencies.
Top comments (0)