Memory layer for browser agents — zero LLM tokens on repeated tasks. Writes .vcr files compatible with Agent VCR.
Project description
████████╗███████╗██████╗ ██╗ ██╗
╚══██╔══╝██╔════╝██╔══██╗╚██╗██╔╝
██║ █████╗ ██████╔╝ ╚███╔╝
██║ ██╔══╝ ██╔══██╗ ██╔██╗
██║ ███████╗██║ ██║██╔╝ ██╗
╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝
browser agent memory. raw cdp. no playwright.
your browser agent is goldfish-brained.
it logs into the same dashboard 50 times a day. it rediscovers the login button 50 times. it burns $0.008 worth of tokens 50 times. every. single. run. if you're deploying this to production, you are NGMI.
TERX is the muscle memory layer.
Run 1: your agent figures out the path. TERX watches and records the exact Chrome DevTools Protocol (CDP) commands into a local sqlite cache. Run 2 onwards: TERX just replays the CDP commands. no LLM. no screenshot parsing. no hallucination. no generic AI BS. just sub-100ms native replay.
Run 1: agent runs normally 2.93s · 2,090 tokens · $0.0076
TERX silently records CDP commands
Run 2: TERX replays 0.078s · 0 tokens · $0.0000
Run 50: TERX replays 0.081s · 0 tokens · $0.0000
Numbers
Real measurement. Real LLM (openai/gpt-oss-120b via Groq). Token counts from API response headers.
| task | agent | terx | speedup | tokens |
|---|---|---|---|---|
| User Login | 2.93s · $0.0076 | 0.078s · $0 | 37.7x | 2,090 → 0 |
| Search + Filter | 3.99s · $0.0136 | 0.101s · $0 | 39.7x | 3,533 → 0 |
| Multi-step Signup | 1.54s · $0.0045 | 0.062s · $0 | 25x | 1,035 → 0 |
| Data Table (12 steps) | 90.84s · $0.0567 | 0.259s · $0 | 350x | 12,479 → 0 |
| average | 19.86s · $0.014 | 0.109s · $0 | 182.7x | 32,993 → 0 |
Cache hit rate: 10/10. Reproduce: GROQ_API_KEY=... python -m terx.benchmarks.real_agent
Full methodology → docs/benchmarks.md
Install
pip install terx
Use it
Option 1: MCP server — drop into Claude Desktop, Cursor, Windsurf. Zero code changes.
google-chrome --remote-debugging-port=9222 --no-first-run
terx-server
mcp.json:
{ "mcpServers": { "terx": { "command": "terx-server" } } }
Every browser task is now cached automatically. You don't write any code.
Option 2: Python library — wrap your existing agent.
from terx.cdp.session import BrowserSession
from terx.cache.cache import MemoryCache, session_for
cache = MemoryCache()
async with BrowserSession() as session:
bridge = session.bridge()
async with session_for(cache, bridge, "login to salesforce") as ctx:
if ctx.hit:
await ctx.replay() # 0 tokens, ~80ms
else:
await your_agent.run() # first time: agent runs, TERX records
Works with browser-use, LangChain, raw Claude/GPT loops, anything.
How it works
Three things, each doing one job:
CDP Bridge — raw asyncio WebSocket to Chrome. No Playwright subprocess. No Selenium. Direct wire protocol. <50ms startup, ~2MB RAM.
DOM Extractor — reads Chrome's Accessibility Tree, not raw HTML. Assigns stable numeric IDs to interactive elements. Computes a fuzzy structural hash that survives CSS refactors and A/B tests without breaking cache hits.
Muscle Memory Cache — SQLite. On task success: stores the CDP command sequence keyed by (domain, dom_hash, task). On future runs: replays directly. Uses INSERT OR IGNORE — first successful recording is canonical, never silently overwritten.
On replay, TERX re-snapshots the DOM and translates old backendNodeIds to current equivalents by matching role + label — so replays work even after Chrome restarts.
why not playwright?
playwright is a heavy test framework. TERX is a lean execution layer with memory. we're raw dogging CDP here.
| Playwright | TERX | |
|---|---|---|
| Memory across runs | ✗ | ✓ |
| Raw CDP (no subprocess) | ✗ | ✓ |
| RAM per instance | ~120MB | ~2MB |
| Works with any agent | ✗ | ✓ |
| MCP server built-in | ✗ | ✓ |
MCP tools
browser_get_state browser_navigate browser_click browser_type browser_screenshot browser_scroll browser_new_tab cache_stats cache_invalidate
Screenshots return hash refs, not base64 blobs — no context window poisoning.
Navigation validates URL schemes — blocks javascript: data: file: injections.
Roadmap
- Raw CDP bridge
- AX tree extractor + stable element IDs
- Fuzzy structural hasher
- Muscle memory cache (SQLite, INSERT OR IGNORE)
- Schema versioning + migrations
- MCP server (9 tools)
- Self-healing replay (LLM fallback on DOM drift)
- Real LLM benchmark suite (
terx-bench-real) - Parametric replay —
{{email}}variable interpolation - MutationObserver cache invalidation
-
pip install "terx[browser-use]"drop-in
Docs
ixchio.github.io/terx · Quick Start · Benchmarks · Architecture · Changelog
Dev
git clone https://github.com/ixchio/terx && cd terx
pip install -e ".[dev]"
pytest tests/ -v # 33 tests
terx-bench # modeled baseline (no API key needed)
GROQ_API_KEY=... terx-bench-real # real LLM run
MIT · built by ixchio
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file terx-0.2.0.tar.gz.
File metadata
- Download URL: terx-0.2.0.tar.gz
- Upload date:
- Size: 103.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b933fd059888c9d3fec51ffa4aea8bff5d28b0aa56fb8b1a8120f9efe50b6f84
|
|
| MD5 |
c113ce6e81c9ba1e2d03d40ba1f83596
|
|
| BLAKE2b-256 |
baa6f07dd098470f551fb17bcf3948119d11ead85a3f20bd97386ad11a8be00a
|
File details
Details for the file terx-0.2.0-py3-none-any.whl.
File metadata
- Download URL: terx-0.2.0-py3-none-any.whl
- Upload date:
- Size: 43.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c3b22e08cfc3d833080e862c2da946c42eda934aeeab7a5f0f16baee9db0eb06
|
|
| MD5 |
1282d728026d7b9cab03990da4241314
|
|
| BLAKE2b-256 |
c6ffffb8f4be58af888ec0c619454c4749d5045c37527e345aaaa590c1e6b285
|