effing-use 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Michael Obubelebra Amachree
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,112 @@
1
+ # effing-use — stop paying 19.5 KB every session for browser control
2
+
3
+ Full Chromium automation in **3 tools, 3.9 KB**. Same pages, same clicks, same scrapes — without the 24-tool handshake eating your context window before you load a page.
4
+
5
+ **Measured, not marketed:** `tools/list` is **3,913 bytes** here vs **19,517 bytes** for `@playwright/mcp@latest` (~5x smaller, ~15.6 KB saved every session). Local ops stay in milliseconds — snapshot ~15 ms, extract ~50 ms, batch ~65 ms, screenshot ~60–190 ms. Page loads still cost seconds (network, not us). Full numbers in [`docs/COMPARISON.md`](docs/COMPARISON.md).
6
+
7
+ ## Install (Bun-only)
8
+
9
+ Requires [Bun](https://bun.sh) 1.4+. The `playwright` npm package ships the driver, **not** the browser — every user needs Playwright's version-pinned Chromium (~150 MB) once:
10
+
11
+ ```bash
12
+ bunx effing-use --help # after: bun publish (runs src/index.ts via bin)
13
+ # or from source:
14
+ bun install
15
+ bunx playwright install chromium --only-shell # one-time Chromium download
16
+ bun src/index.ts # STDIO (single editor)
17
+ bun src/http.ts # HTTP on :3000 (/mcp) — shared across editors
18
+ ```
19
+
20
+ Re-run `bunx playwright install chromium --only-shell` whenever you bump the `playwright` dependency (each Playwright version pins its own browser build). Verify with `bunx playwright install --dry-run chromium` or check `~/.cache/ms-playwright/`.
21
+
22
+ **Why Chromium is separate:** Playwright supports multiple browsers and updates its pinned builds every release, so the binary can't live inside the npm tarball (ours is 16 kB). Docker users skip this — Chromium is baked into the `mcr.microsoft.com/playwright` base image.
23
+
24
+ ## Run it in 60 seconds (recommended path)
25
+
26
+ **Step 1/3 — Start the server.** One server, every local editor:
27
+
28
+ ```bash
29
+ bun install
30
+ bunx playwright install chromium --only-shell
31
+ docker compose up --build -d
32
+ curl http://localhost:3000/healthz
33
+ ```
34
+
35
+ Point any VS Code instance at `http://localhost:3000/mcp` (see `.vscode/mcp.json` → `effing-use (http)`). Plain HTTP on loopback is intentional — add TLS at the edge for remote use.
36
+
37
+ **Step 2/3 — Connect.** STDIO for one editor, HTTP for all of them:
38
+
39
+ ```json
40
+ {
41
+ "mcpServers": {
42
+ "computer-use": {
43
+ "command": "bun",
44
+ "args": ["/path/to/litepilot/src/index.ts"]
45
+ }
46
+ }
47
+ }
48
+ ```
49
+
50
+ Or HTTP: `http://localhost:3000/mcp`.
51
+
52
+ **Step 3/3 — Drive.** Search Wikipedia in one call instead of two round-trips:
53
+
54
+ ```jsonc
55
+ // browser_act batch: fill + press in 65 ms measured
56
+ {
57
+ "action": "batch",
58
+ "steps": [
59
+ { "action": "fill", "target": "input[name=search]", "value": "Playwright" },
60
+ { "action": "press", "target": "input[name=search]", "value": "Enter" },
61
+ ],
62
+ }
63
+ ```
64
+
65
+ No Docker? `bun src/index.ts` (STDIO) or `bun src/http.ts` (`:3000` `/mcp`) works directly.
66
+
67
+ ## Why agents prefer 3 tools
68
+
69
+ - 🪶 **Tiny handshake, full surface** — `browser_act` (27 actions), `browser_observe` (8 kinds), `browser_extract` (7 kinds). No schema bloat, no guessing which of 24 tools to call.
70
+ - 🧠 **Context-safe by default** — snapshots capped at `OUTPUT_MAX_CHARS` (default 4000); full YAML/text saved under `.browser-use/`, never dumped inline. HN snapshot: 4,034-char preview, full file on disk.
71
+ - 🖼️ **File paths, not base64** — screenshots, PDFs, traces return paths like `.browser-use/shot-*.png`. Read the file only when needed.
72
+ - ⚡ **One call, not five** — `batch` runs fill+press flows in one turn (max 20 steps, stops on first error). `goal` plans or returns `E_GOAL_UNCLEAR` + `suggestedSteps` instead of hallucinating.
73
+ - 🐳 **Shared, not spawned** — one Docker server serves every local VS Code instance. No per-client `npx` spawn.
74
+
75
+ ## The loop (agents: follow this order)
76
+
77
+ 1. `browser_observe` kind=`snapshot` → get `[eN]` refs (never guess refs, re-snapshot after navigation)
78
+ 2. `browser_act` to interact — prefer `batch` with `steps[]`
79
+ 3. `browser_observe` kind=`screenshot` → verify visually (you get a path)
80
+ 4. `browser_extract` kind=`text`|`table`|`query` → scrape structured data
81
+
82
+ ## Tools
83
+
84
+ - `browser_act` — open/goto, click, dblclick, fill, type, press, select, check/uncheck, hover, drag, upload, scroll, back/forward/reload, wait, dialog_accept/dismiss, tabs (new/select/close), resize, close, `goal`, `batch`
85
+ - `browser_observe` — snapshot (e-refs), screenshot (path), url, title, console (last N), network (method/url/status ring), tabs, focused
86
+ - `browser_extract` — text, html, table (≤100 rows JSON), query (text|href|json), pdf, trace_start/stop
87
+
88
+ Errors are always `{ ok: false, code, message, hint }` with `E_NOT_FOUND | E_TIMEOUT | E_NO_PAGE | E_BAD_INPUT | E_GOAL_UNCLEAR` — never a stack trace.
89
+
90
+ ## effing-use vs Playwright MCP
91
+
92
+ | | effing-use | Playwright MCP |
93
+ | ---------------- | ------------------------------- | ---------------------------------------------------------- |
94
+ | `tools/list` | **3,913 bytes / 3 tools** | **19,517 bytes / 24 tools** |
95
+ | Snapshot | capped 4 KB preview + full file | full accessibility tree |
96
+ | Screenshots/PDFs | file paths | inline or output dir |
97
+ | Browsers | Chromium (headless in Docker) | Chromium, Firefox, WebKit, Edge + vision/pdf/devtools caps |
98
+
99
+ Need Firefox/WebKit, device emulation, or persistent profiles? Use Playwright MCP. Need context budget for Chromium work? Stay here. Full breakdown in [`docs/COMPARISON.md`](docs/COMPARISON.md).
100
+
101
+ ## Config
102
+
103
+ Env defaults in [`.env.example`](.env.example): `BROWSER_HEADLESS`, `BROWSER_VIEWPORT_W/H`, `BROWSER_TIMEOUT_MS`, `OUTPUT_DIR` (`.browser-use/`, gitignored), `OUTPUT_MAX_CHARS`, `ALLOW_EVAL`.
104
+
105
+ Agent skill: `skills/effing-use/SKILL.md` (skills.sh-ready).
106
+
107
+ ## Verify
108
+
109
+ ```bash
110
+ bunx tsc --noEmit # 0 errors
111
+ bun test # 6 pass
112
+ ```
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "effing-use",
3
+ "version": "0.1.0",
4
+ "description": "Token-efficient browser control: 3 tools (act, observe, extract) built with tmcp + Bun + Playwright",
5
+ "license": "MIT",
6
+ "author": "Michael Obubelebra Amachree",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/Michael-Obele/litepilot.git"
10
+ },
11
+ "homepage": "https://github.com/Michael-Obele/litepilot#readme",
12
+ "type": "module",
13
+ "main": "src/index.ts",
14
+ "bin": {
15
+ "effing-use": "src/index.ts",
16
+ "effing-use-http": "src/http.ts"
17
+ },
18
+ "files": [
19
+ "src",
20
+ "skills",
21
+ "README.md",
22
+ "LICENSE"
23
+ ],
24
+ "scripts": {
25
+ "start": "bun src/index.ts",
26
+ "start:http": "bun src/http.ts",
27
+ "dev": "bun --watch src/index.ts",
28
+ "dev:http": "bun --watch src/http.ts",
29
+ "check": "bunx tsc --noEmit",
30
+ "test": "bun test"
31
+ },
32
+ "keywords": [
33
+ "mcp",
34
+ "model-context-protocol",
35
+ "playwright",
36
+ "browser-automation",
37
+ "tmcp",
38
+ "chromium"
39
+ ],
40
+ "dependencies": {
41
+ "@tmcp/adapter-valibot": "^0.1.6",
42
+ "@tmcp/transport-http": "^0.9.0",
43
+ "@tmcp/transport-stdio": "^0.5.0",
44
+ "playwright": "^1.63.0",
45
+ "tmcp": "^1.20.0",
46
+ "valibot": "^1.4.2"
47
+ },
48
+ "devDependencies": {
49
+ "@types/bun": "latest",
50
+ "typescript": "latest"
51
+ }
52
+ }
@@ -0,0 +1,58 @@
1
+ ---
2
+ name: effing-use
3
+ description: Drive a headless Chromium browser through 3 token-efficient MCP tools (browser_act, browser_observe, browser_extract). Use when automating web pages, scraping structured data, screenshotting UIs, filling forms, or testing web flows.
4
+ license: MIT
5
+ compatibility: Requires the effing-use MCP server (Bun + Playwright Chromium). Works over stdio or Streamable HTTP at /mcp.
6
+ metadata:
7
+ repo: Michael-Obele/litepilot
8
+ tools: browser_act,browser_observe,browser_extract
9
+ ---
10
+
11
+ # effing-use — token-efficient browser control
12
+
13
+ Three tools cover 100% of the interaction surface at ~4–10x lower token
14
+ cost than 21-tool browser servers. `tools/list` is ~3.9KB.
15
+
16
+ ## The loop (always follow this order)
17
+
18
+ 1. `browser_observe` with `kind: "snapshot"` → get `[eN]` refs.
19
+ 2. `browser_act` to interact (`open`, `click`, `fill`, `type`, `press`, `select`, `check`, `wait`, …).
20
+ 3. `browser_observe` with `kind: "screenshot"` → verify visually (returns a file path).
21
+ 4. `browser_extract` with `kind: "text" | "table" | "query"` → scrape.
22
+
23
+ Rules:
24
+
25
+ - Never guess refs. Re-snapshot after every navigation.
26
+ - Prefer `batch`: one `browser_act` with `steps[]` for fill+press flows (max 20 steps, stops on first error).
27
+ - Large outputs are files under `.browser-use/` (gitignored). Read the path, not the preview.
28
+ - Snapshots are capped at `OUTPUT_MAX_CHARS` (default 4000) with `…[truncated N chars, see file]`.
29
+
30
+ ## Tool cheat sheet
31
+
32
+ **browser_act** — `action` + optional `target` (e-ref, `role=` selector, or CSS) + `value`:
33
+ `open`/`goto` (URL in `value`), `click`, `dblclick`, `fill`, `type`,
34
+ `press` (key like `Enter`), `select`, `check`/`uncheck`, `hover`,
35
+ `drag` (start in `target`, end in `value`), `upload` (comma-separated paths in `value`),
36
+ `scroll` (`up`/`down`/`top`/`bottom` or a target), `back`/`forward`/`reload`,
37
+ `wait` (`ms:500`, `text:Saved`, or a ref), `dialog_accept`/`dialog_dismiss` (arm before the triggering step),
38
+ `resize` (`1280x800` in `value`), `tab_new`/`tab_select`/`tab_close`, `close`,
39
+ `goal` (deterministic add-todo/search planner, else `E_GOAL_UNCLEAR` + `suggestedSteps`),
40
+ `batch` (needs `steps[]`).
41
+
42
+ **browser_observe** — read-only: `snapshot` (e-refs), `screenshot` (file path,
43
+ `full` page by default), `url`, `title`, `console` (last N, `limit`),
44
+ `network` (method/url/status ring), `tabs`, `focused` (activeElement HTML).
45
+
46
+ **browser_extract** — `text`, `html`, `table` (≤100 rows as JSON),
47
+ `query` (`selector` + `mode: text|href|json`), `pdf` (headless Chromium only),
48
+ `trace_start`/`trace_stop` (Playwright trace zip).
49
+
50
+ Errors always come back as `{ ok: false, code, message, hint }` with codes
51
+ `E_NOT_FOUND | E_TIMEOUT | E_NO_PAGE | E_BAD_INPUT | E_GOAL_UNCLEAR` — never a stack trace.
52
+
53
+ ## Setup
54
+
55
+ See [references/setup.md](references/setup.md) for install (local Bun,
56
+ Docker, VS Code `mcp.json` entries), port config (`ECU_PORT`), and the
57
+ `.browser-use/` gitignore contract. See [references/troubleshooting.md](references/troubleshooting.md)
58
+ for port conflicts, Chromium sandbox notes, and the `doQuery` arity lesson.
@@ -0,0 +1,89 @@
1
+ # Setup — effing-use
2
+
3
+ ## Prerequisites
4
+
5
+ - [Bun](https://bun.sh) 1.4+ (`bun --version`)
6
+ - Docker 29+ with Compose v2 (only for the container route)
7
+ - Chromium system deps — handled by `bunx playwright install chromium`
8
+ locally, or baked into the `mcr.microsoft.com/playwright:v1.63.0-noble`
9
+ base image in Docker.
10
+
11
+ ## Option A — local Bun (single VS Code instance)
12
+
13
+ ```bash
14
+ bun install
15
+ bunx playwright install chromium --only-shell
16
+ bun src/index.ts # STDIO transport
17
+ bun src/http.ts # Streamable HTTP on $PORT (default 3000), MCP at /mcp
18
+ ```
19
+
20
+ VS Code `.vscode/mcp.json`:
21
+
22
+ ```json
23
+ {
24
+ "servers": {
25
+ "effing-use (stdio)": {
26
+ "type": "stdio",
27
+ "command": "bun",
28
+ "args": ["/path/to/effing-use/src/index.ts"],
29
+ "cwd": "/path/to/effing-use",
30
+ "env": {
31
+ "BROWSER_HEADLESS": "true",
32
+ "OUTPUT_DIR": "/path/to/effing-use/.browser-use"
33
+ }
34
+ },
35
+ "effing-use (http)": { "type": "http", "url": "http://localhost:3123/mcp" }
36
+ }
37
+ }
38
+ ```
39
+
40
+ ## Option B — Docker (shared across VS Code instances)
41
+
42
+ ```bash
43
+ ECU_PORT=3123 docker compose up --build -d
44
+ curl http://localhost:3123/healthz # {"ok":true,"name":"effing-use"}
45
+ ```
46
+
47
+ Then point any local client at `http://localhost:<ECU_PORT>/mcp`.
48
+ The container listens on 3000 internally; only the host-side port moves.
49
+
50
+ - `restart: unless-stopped` — survives daemon restarts and host reboots
51
+ once started with `up -d`.
52
+ - `init: true` + `ipc: host` — Playwright's recommended flags (no PID-1
53
+ zombies, no Chromium `/dev/shm` crashes).
54
+ - `.browser-use/` is bind-mounted so snapshots/screenshots land on the host.
55
+ - Plain HTTP on loopback is intentional. For remote use, terminate TLS at
56
+ the edge (reverse proxy, Cloudflare Tunnel, Tailscale) — never bake certs
57
+ into the image.
58
+
59
+ ## Environment
60
+
61
+ All optional; defaults shown (see `.env.example`):
62
+
63
+ | Var | Default | Notes |
64
+ | ---------------------- | -------------- | ---------------------------------------------- |
65
+ | `PORT` | `3000` | `src/http.ts` listen port (container-internal) |
66
+ | `ECU_PORT` | `3000` | compose host-side port override |
67
+ | `BROWSER_HEADLESS` | `true` | Docker supports headless Chromium only |
68
+ | `BROWSER_VIEWPORT_W/H` | `1280/800` | |
69
+ | `BROWSER_TIMEOUT_MS` | `15000` | per-action Playwright timeout |
70
+ | `OUTPUT_DIR` | `.browser-use` | all file outputs land here |
71
+ | `OUTPUT_MAX_CHARS` | `4000` | inline cap; full text goes to the file |
72
+ | `ALLOW_EVAL` | `false` | no raw JS eval path unless explicitly enabled |
73
+
74
+ ## Gitignore contract
75
+
76
+ `.browser-use/`, `*.png`, `*.pdf`, `node_modules/` stay out of git.
77
+ Any local planning/scratch folder (e.g. `docs/plan/`) should also be gitignored —
78
+ it holds the build spec, not shippable code.
79
+
80
+ ## Verify
81
+
82
+ ```bash
83
+ bunx tsc --noEmit # 0 errors
84
+ bun test # unit green
85
+ curl -s -X POST http://localhost:3123/mcp \
86
+ -H 'Content-Type: application/json' \
87
+ -H 'Accept: application/json, text/event-stream' \
88
+ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | head -c 300
89
+ ```
@@ -0,0 +1,64 @@
1
+ # Troubleshooting — effing-use
2
+
3
+ ## Port already in use
4
+
5
+ Port 3000 is a popular squat (e.g. other MCP servers). Diagnose:
6
+
7
+ ```bash
8
+ ss -tlnp | grep -E ':3000|:3123'
9
+ docker ps --format "{{.Names}} {{.Ports}}"
10
+ ```
11
+
12
+ Fix — move our host port, never the container's:
13
+
14
+ ```bash
15
+ ECU_PORT=3123 docker compose up -d # client → http://localhost:3123/mcp
16
+ PORT=3123 bun src/http.ts # local Bun route
17
+ ```
18
+
19
+ ## Chromium won't launch in Docker
20
+
21
+ - Keep `ipc: host` (Chromium crashes on small `/dev/shm` without it).
22
+ - Keep `init: true` (avoids PID-1 zombie processes).
23
+ - Headless only in containers. If you see sandbox errors on untrusted
24
+ sites, run with a non-root user + seccomp profile per
25
+ <https://playwright.dev/docs/docker> (trusted E2E code is fine as root).
26
+
27
+ ## `bun: not found` during `docker build`
28
+
29
+ The `curl | bash` Bun installer can break mid-download (`curl: (56)`) yet
30
+ the layer still "succeeds", leaving no binary. The effing-use Dockerfile copies Bun from
31
+ the pinned `oven/bun` image instead — deterministic, no network flakiness:
32
+
33
+ ```dockerfile
34
+ COPY --from=oven/bun:1.4.0 /usr/local/bin/bun /usr/local/bin/bun
35
+ ```
36
+
37
+ ## Query extract returns `[]`
38
+
39
+ `page.locator(sel).evaluateAll(fn)` does **not** forward outer-scope args —
40
+ the second parameter must be passed explicitly:
41
+
42
+ ```ts
43
+ .evaluateAll((els, m: string) => /* … */, mode)
44
+ ```
45
+
46
+ Without it the callback receives `undefined` and (depending on arity
47
+ handling) the call throws inside the page, surfacing as an empty result
48
+ via `.catch(() => [])`. Lesson: always pass `evaluateAll`/`evaluate`
49
+ arguments explicitly; never rely on closure capture across the
50
+ browser boundary.
51
+
52
+ ## Stale snapshot refs (`E_NOT_FOUND`)
53
+
54
+ Refs are nth-match positions in DOM order — any navigation or re-render
55
+ invalidates them. Fix: re-run `browser_observe kind: "snapshot"` and use
56
+ fresh `eN` values. Fuzzy matching (`fill` with a label) and `role=`
57
+ selectors survive re-renders better than raw `eN` refs.
58
+
59
+ ## Slow external sites timing out
60
+
61
+ Default action timeout is 15s (`BROWSER_TIMEOUT_MS`). For slow demos,
62
+ either raise it or prefer `wait` with `text:` expectations over fixed
63
+ `ms:` sleeps. For deterministic E2E, serve a local fixture
64
+ (`file:///tmp/…`) instead of depending on the network.