hanzi-browse 2.2.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/README.md +182 -0
- package/dist/agent/loop.d.ts +63 -0
- package/dist/agent/loop.js +186 -0
- package/dist/agent/system-prompt.d.ts +7 -0
- package/dist/agent/system-prompt.js +41 -0
- package/dist/agent/tools.d.ts +9 -0
- package/dist/agent/tools.js +154 -0
- package/dist/cli/detect-credentials.d.ts +31 -0
- package/dist/cli/detect-credentials.js +44 -0
- package/dist/cli/import-credentials-handler.d.ts +14 -0
- package/dist/cli/import-credentials-handler.js +22 -0
- package/dist/cli/session-files.d.ts +28 -0
- package/dist/cli/session-files.js +118 -0
- package/dist/cli/setup.d.ts +10 -0
- package/dist/cli/setup.js +915 -0
- package/dist/cli.d.ts +16 -0
- package/dist/cli.js +506 -0
- package/dist/dashboard/assets/index-CEFyesbT.js +46 -0
- package/dist/dashboard/assets/index-Dnht2kLU.css +1 -0
- package/dist/dashboard/index.html +13 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1116 -0
- package/dist/ipc/index.d.ts +8 -0
- package/dist/ipc/index.js +8 -0
- package/dist/ipc/native-host.d.ts +96 -0
- package/dist/ipc/native-host.js +223 -0
- package/dist/ipc/websocket-client.d.ts +73 -0
- package/dist/ipc/websocket-client.js +199 -0
- package/dist/license/manager.d.ts +20 -0
- package/dist/license/manager.js +15 -0
- package/dist/llm/client.d.ts +72 -0
- package/dist/llm/client.js +227 -0
- package/dist/llm/credentials.d.ts +61 -0
- package/dist/llm/credentials.js +200 -0
- package/dist/llm/vertex.d.ts +22 -0
- package/dist/llm/vertex.js +335 -0
- package/dist/managed/api-http.test.d.ts +7 -0
- package/dist/managed/api-http.test.js +623 -0
- package/dist/managed/api.d.ts +51 -0
- package/dist/managed/api.js +1448 -0
- package/dist/managed/api.test.d.ts +10 -0
- package/dist/managed/api.test.js +146 -0
- package/dist/managed/auth.d.ts +38 -0
- package/dist/managed/auth.js +192 -0
- package/dist/managed/billing.d.ts +70 -0
- package/dist/managed/billing.js +227 -0
- package/dist/managed/deploy.d.ts +17 -0
- package/dist/managed/deploy.js +385 -0
- package/dist/managed/e2e.test.d.ts +15 -0
- package/dist/managed/e2e.test.js +151 -0
- package/dist/managed/hardening.test.d.ts +14 -0
- package/dist/managed/hardening.test.js +346 -0
- package/dist/managed/integration.test.d.ts +8 -0
- package/dist/managed/integration.test.js +274 -0
- package/dist/managed/log.d.ts +18 -0
- package/dist/managed/log.js +31 -0
- package/dist/managed/server.d.ts +12 -0
- package/dist/managed/server.js +69 -0
- package/dist/managed/store-pg.d.ts +191 -0
- package/dist/managed/store-pg.js +479 -0
- package/dist/managed/store.d.ts +188 -0
- package/dist/managed/store.js +379 -0
- package/dist/relay/auto-start.d.ts +19 -0
- package/dist/relay/auto-start.js +71 -0
- package/dist/relay/server.d.ts +17 -0
- package/dist/relay/server.js +403 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.js +4 -0
- package/dist/types/session.d.ts +134 -0
- package/dist/types/session.js +16 -0
- package/package.json +61 -0
- package/skills/README.md +48 -0
- package/skills/a11y-auditor/SKILL.md +42 -0
- package/skills/e2e-tester/SKILL.md +154 -0
- package/skills/hanzi-browse/SKILL.md +182 -0
- package/skills/linkedin-prospector/SKILL.md +149 -0
- package/skills/social-poster/SKILL.md +146 -0
- package/skills/x-marketer/SKILL.md +479 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: a11y-auditor
|
|
3
|
+
description: Audit web pages for accessibility issues in a real browser. Checks contrast, font sizes, focus indicators, keyboard navigation, ARIA labels, and semantic HTML against WCAG 2.1 AA. Reports findings with screenshots and specific remediation steps. Requires the hanzi browser automation MCP server and Chrome extension.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Accessibility Auditor
|
|
7
|
+
|
|
8
|
+
You audit web pages for accessibility issues using a real browser — real contrast, real tab order, real focus indicators, real screen reader semantics. This skill is read-only: observe and report, don't modify.
|
|
9
|
+
|
|
10
|
+
## Tool Selection Rule
|
|
11
|
+
|
|
12
|
+
- Prefer existing tools first (code search, local files). Review ARIA usage and semantic HTML before opening the browser.
|
|
13
|
+
- Use Hanzi only for browser-required steps: visual checks, keyboard navigation, focus behavior.
|
|
14
|
+
|
|
15
|
+
## Before Starting
|
|
16
|
+
|
|
17
|
+
Call `browser_status` to verify the extension is reachable. If unavailable, tell the user to install from: https://chromewebstore.google.com/detail/hanzi-browse/iklpkemlmbhemkiojndpbhoakgikpmcd
|
|
18
|
+
|
|
19
|
+
## What You Need
|
|
20
|
+
|
|
21
|
+
1. **URL** — page or site to audit 2. **Scope** — single page, flow, or full site 3. **Standard** — defaults to WCAG 2.1 AA
|
|
22
|
+
|
|
23
|
+
## Audit Phases
|
|
24
|
+
|
|
25
|
+
**Phase 1 — Codebase Review (before browser):** Scan for ARIA usage, semantic HTML (`<div>` vs `<button>`/`<nav>`/`<main>`), image alt text, form labels, heading hierarchy. Summarize before opening browser.
|
|
26
|
+
|
|
27
|
+
**Phase 2 — Visual (browser):** Check color contrast (4.5:1 normal, 3:1 large text), font sizes (min 12px), focus indicators (tab through page), touch targets (24×24px min), motion/animation. Screenshot each area.
|
|
28
|
+
|
|
29
|
+
**Phase 3 — Keyboard (browser):** Test tab order, focus traps in modals/dropdowns, keyboard operability (Enter/Space), skip links. Screenshot problematic focus states.
|
|
30
|
+
|
|
31
|
+
**Phase 4 — ARIA & Semantics (browser):** Verify landmarks, form label associations, dynamic content announcements (`aria-live`), image/icon accessible names, table headers.
|
|
32
|
+
|
|
33
|
+
## Report Format
|
|
34
|
+
|
|
35
|
+
Categorize issues as Critical / Serious / Moderate / Minor with: element/location, impact, WCAG criterion, specific fix, screenshot. List passing checks. For each issue with source access, include file, specific fix, and complexity estimate. End with severity totals and top 3 priorities.
|
|
36
|
+
|
|
37
|
+
## Rules
|
|
38
|
+
|
|
39
|
+
- One page/flow at a time — screenshot every issue found
|
|
40
|
+
- Be specific ("the search button" not "a button") and cite WCAG criteria (e.g., 1.4.3)
|
|
41
|
+
- Don't report unverified issues — if unsure, say so
|
|
42
|
+
- If `browser_start` times out, call `browser_screenshot` to diagnose
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: e2e-tester
|
|
3
|
+
description: Test a web app like a QA person — open it in a real browser, click through flows, and report what's broken with screenshots and code references. Works on localhost. Use when the user wants to test their app, verify a flow works, check for visual bugs, or validate changes before pushing.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# E2E Tester
|
|
7
|
+
|
|
8
|
+
You test web apps in a real browser and report findings. You're not a test script runner — you're a QA person who also understands the codebase.
|
|
9
|
+
|
|
10
|
+
## Tool Selection Rule
|
|
11
|
+
|
|
12
|
+
- **Prefer existing tools first**: code search, git diff, logs, APIs, local files, and other MCP integrations. Gather all the context you can BEFORE opening the browser.
|
|
13
|
+
- **Use Hanzi only for browser-required steps**: real UI interaction, visual verification, form submission, and anything that needs a rendered page.
|
|
14
|
+
- **If the browser step could mutate real data**, ask the user before proceeding unless the environment is clearly local, dev, test, or preview.
|
|
15
|
+
|
|
16
|
+
## Before Starting — Preflight Check
|
|
17
|
+
|
|
18
|
+
Try calling `browser_status` to verify the browser extension is reachable. If the tool doesn't exist or returns an error:
|
|
19
|
+
|
|
20
|
+
> **Hanzi isn't set up yet.** This skill needs the hanzi browser extension running in Chrome.
|
|
21
|
+
>
|
|
22
|
+
> 1. Install from the Chrome Web Store: https://chromewebstore.google.com/detail/hanzi-browse/iklpkemlmbhemkiojndpbhoakgikpmcd
|
|
23
|
+
> 2. The extension will walk you through setup (~1 minute)
|
|
24
|
+
> 3. Then come back and run this again
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## What You Need From the User
|
|
29
|
+
|
|
30
|
+
1. **URL** — where the app is running (e.g., `localhost:3000`, `staging.myapp.com`)
|
|
31
|
+
2. **What to test** — specific flow, "what I just changed", or "everything"
|
|
32
|
+
3. **Credentials** — test login if the app requires auth (check .env first)
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Safety: Check the Target Before Testing
|
|
37
|
+
|
|
38
|
+
Browser tests create real state — signups, form submissions, orders. Before executing any test:
|
|
39
|
+
|
|
40
|
+
**Safe URLs (proceed without extra confirmation):**
|
|
41
|
+
- `localhost`, `127.0.0.1`, `0.0.0.0`
|
|
42
|
+
- URLs containing `dev.`, `staging.`, `preview.`, `.local`
|
|
43
|
+
- Vercel/Netlify preview URLs
|
|
44
|
+
|
|
45
|
+
**Production or unknown URLs:**
|
|
46
|
+
- Ask the user: "This looks like a production URL. Should I test with real interactions (may create data), or stay read-only (just navigate and observe)?"
|
|
47
|
+
- Default to **read-only** if unclear
|
|
48
|
+
|
|
49
|
+
**Credentials from .env:**
|
|
50
|
+
- Tell the user what you found: "Found a test account in .env.local (admin@test.com). OK to use it?"
|
|
51
|
+
- On non-local targets, always confirm before using
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Phase 1: Gather Context BEFORE Opening the Browser
|
|
56
|
+
|
|
57
|
+
You have access to the codebase. Use it.
|
|
58
|
+
|
|
59
|
+
1. **Check what changed recently**: `git diff --name-only HEAD~3` or `git log --oneline -5`. This tells you what's most likely broken.
|
|
60
|
+
|
|
61
|
+
2. **Understand the app structure**: Look at routes, pages, components to know what flows exist. Check for:
|
|
62
|
+
- Route definitions (Next.js `app/` dir, React Router, Express routes)
|
|
63
|
+
- Key pages: login, signup, dashboard, checkout, settings
|
|
64
|
+
- API endpoints the frontend calls
|
|
65
|
+
|
|
66
|
+
3. **Find test credentials**: Check `.env`, `.env.local`, seed files, test fixtures for test accounts. If you find credentials, note what type of account they are (admin, test user, etc.) — don't silently use production credentials.
|
|
67
|
+
|
|
68
|
+
4. **Check if the server is running**: `curl -s -o /dev/null -w "%{http_code}" <url>`. If not running, tell the user to start it and stop here.
|
|
69
|
+
|
|
70
|
+
5. **Decide what to test**: Based on recent changes + app structure, prioritize:
|
|
71
|
+
- Changed files first
|
|
72
|
+
- Critical paths (signup, login, core feature)
|
|
73
|
+
- If "everything", hit every major route
|
|
74
|
+
|
|
75
|
+
Present your test plan briefly. Ask if the user wants to adjust before proceeding.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Phase 2: Execute Tests in the Browser
|
|
80
|
+
|
|
81
|
+
Use `browser_start` for each flow. Test **one at a time, sequentially**.
|
|
82
|
+
|
|
83
|
+
For each flow:
|
|
84
|
+
- Navigate to the relevant page
|
|
85
|
+
- Interact like a real user: fill forms with realistic test data, click buttons, wait for responses
|
|
86
|
+
- Look for: broken layouts, missing elements, error messages, infinite spinners, 404s
|
|
87
|
+
- Note what works AND what doesn't
|
|
88
|
+
|
|
89
|
+
Tell the browser agent to be specific: not "the page looks fine" but "the signup form has 3 fields, I filled them in, clicked Submit, and was redirected to /dashboard."
|
|
90
|
+
|
|
91
|
+
If a flow requires login, log in first using credentials you found (with user confirmation) or that the user provided.
|
|
92
|
+
|
|
93
|
+
If something fails, get specific error info — error message, URL, last thing that worked.
|
|
94
|
+
|
|
95
|
+
**After each `browser_start` returns**, call `browser_screenshot` (a separate MCP tool) to capture the final state. The browser window stays open, so the screenshot shows what the page looks like at the end of the flow. Do this for both passing and failing flows — screenshots are evidence.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Phase 3: Report Findings
|
|
100
|
+
|
|
101
|
+
### Format:
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
Tested [N] flows on [url]:
|
|
105
|
+
|
|
106
|
+
✓ [Flow name] — [what happened, one line]
|
|
107
|
+
📸 Screenshot: [describe what the screenshot shows]
|
|
108
|
+
|
|
109
|
+
✗ [Flow name] — [what's broken, specifically]
|
|
110
|
+
📸 Screenshot: [what the page looked like when it failed]
|
|
111
|
+
|
|
112
|
+
⚠ [Flow name] — [works but has issues]
|
|
113
|
+
📸 Screenshot: [evidence of the issue]
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### For each failure, cross-reference with the code:
|
|
117
|
+
|
|
118
|
+
This is your superpower — you can see both the browser AND the codebase.
|
|
119
|
+
|
|
120
|
+
1. What did the browser show? (include the screenshot)
|
|
121
|
+
2. What file likely causes this? (check recent changes, route handlers, API endpoints)
|
|
122
|
+
3. What's your best guess at the root cause?
|
|
123
|
+
4. Suggest a fix if obvious.
|
|
124
|
+
|
|
125
|
+
Example:
|
|
126
|
+
```
|
|
127
|
+
✗ Checkout — form submits but hangs on loading spinner.
|
|
128
|
+
The confirmation page never loads.
|
|
129
|
+
📸 Screenshot shows the payment form with a spinning loader, stuck for 30+ seconds.
|
|
130
|
+
|
|
131
|
+
Likely cause: src/api/checkout.ts modified in last commit (abc123).
|
|
132
|
+
The onSuccess callback was removed on line 45. Frontend waits
|
|
133
|
+
for a response that never comes.
|
|
134
|
+
|
|
135
|
+
Fix: restore the onSuccess handler or add a redirect after resolve.
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Summary:
|
|
139
|
+
- Total tested / passed / failed / warnings
|
|
140
|
+
- If all pass: "All flows working. Ready to push."
|
|
141
|
+
- If failures: prioritize by severity
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Rules
|
|
146
|
+
|
|
147
|
+
- Don't test in parallel — one flow at a time
|
|
148
|
+
- Don't guess — if you can't tell what's wrong, say so
|
|
149
|
+
- Don't skip the codebase analysis — it makes your report actionable
|
|
150
|
+
- If the dev server isn't running, stop and tell the user
|
|
151
|
+
- If browser_start times out, call browser_screenshot to see where it got stuck
|
|
152
|
+
- Always take a screenshot after each flow — for both passes and failures
|
|
153
|
+
- On production URLs, default to read-only unless the user explicitly opts in
|
|
154
|
+
- Don't silently use credentials from .env on non-local targets — confirm first
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: hanzi-browse
|
|
3
|
+
description: Use when a task requires interacting with a real browser — clicking, typing, filling forms, reading authenticated pages, posting content, or testing web apps. Also use when the user says "open", "go to", "check this site", "log in to", "post on", or needs their real cookies and sessions.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Hanzi Browse
|
|
7
|
+
|
|
8
|
+
Give your AI agent a real browser. Hanzi controls the user's actual Chrome with their existing logins, cookies, and sessions — not a headless sandbox.
|
|
9
|
+
|
|
10
|
+
## When to Use
|
|
11
|
+
|
|
12
|
+
- **Browser-required tasks**: click buttons, fill forms, submit data, navigate pages
|
|
13
|
+
- **Authenticated access**: read pages that need login (email, dashboards, admin panels, social feeds)
|
|
14
|
+
- **Visual verification**: check what a page actually looks like, take screenshots
|
|
15
|
+
- **Real-world posting**: publish to LinkedIn, Twitter/X, Reddit from the user's signed-in account
|
|
16
|
+
- **E2E testing**: test a web app in a real browser on localhost or staging
|
|
17
|
+
|
|
18
|
+
## When NOT to Use
|
|
19
|
+
|
|
20
|
+
- Reading public pages (use `WebFetch` or `curl` instead)
|
|
21
|
+
- API calls (use `fetch` or HTTP tools)
|
|
22
|
+
- File operations (use filesystem tools)
|
|
23
|
+
- **Services with dedicated MCP tools** (Gmail, Calendar, Notion, Stripe) — use those tools instead, they're faster and more reliable
|
|
24
|
+
- Anything that doesn't need a rendered browser
|
|
25
|
+
|
|
26
|
+
## Tool Selection Rule
|
|
27
|
+
|
|
28
|
+
**Prefer non-browser tools first.** Check if a dedicated MCP tool exists for the service (Gmail, Calendar, Notion, etc.) — use that instead. Gather all context you can (code search, git log, file reads, API calls) BEFORE opening the browser. Use Hanzi only for steps that genuinely require a rendered page.
|
|
29
|
+
|
|
30
|
+
## Setup
|
|
31
|
+
|
|
32
|
+
If `browser_status` returns an error or the tool doesn't exist:
|
|
33
|
+
|
|
34
|
+
> **Hanzi Browse isn't set up yet.**
|
|
35
|
+
>
|
|
36
|
+
> Run: `npx hanzi-browse setup`
|
|
37
|
+
>
|
|
38
|
+
> This installs the Chrome extension and adds the MCP server to your agent (~1 minute).
|
|
39
|
+
|
|
40
|
+
## MCP Tools
|
|
41
|
+
|
|
42
|
+
### `browser_start`
|
|
43
|
+
|
|
44
|
+
Start a task. An autonomous agent navigates, clicks, types, and fills forms. Blocks until complete, waiting for input, or timeout (5 min).
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
browser_start({
|
|
48
|
+
task: "Go to LinkedIn and send a connection request to Jane Doe at Acme Corp",
|
|
49
|
+
url: "https://linkedin.com",
|
|
50
|
+
context: "Connection note: Hi Jane, loved your post about AI agents. Would love to connect."
|
|
51
|
+
})
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Returns:** `{ session_id, status, result }`
|
|
55
|
+
|
|
56
|
+
| `status` | Meaning | What to do |
|
|
57
|
+
|-----------|---------|------------|
|
|
58
|
+
| `"completed"` | Task finished successfully | Read `result` for the answer |
|
|
59
|
+
| `"waiting"` | Agent needs input or clarification | Send `browser_message` with the answer |
|
|
60
|
+
| `"error"` | Something went wrong | Call `browser_screenshot`, then retry or adjust |
|
|
61
|
+
| `"timeout"` | Hit 5-minute limit | Call `browser_message` to continue, or `browser_stop` |
|
|
62
|
+
|
|
63
|
+
**Tips:**
|
|
64
|
+
- `task` — be specific: include the website, the goal, and details
|
|
65
|
+
- `url` — starting page (optional, agent can navigate itself)
|
|
66
|
+
- `context` — everything the agent needs: form values, text to paste, tone, credentials, choices
|
|
67
|
+
- You can run multiple `browser_start` calls in parallel — each gets its own window
|
|
68
|
+
- `session_id` is returned here — use it for all follow-up calls
|
|
69
|
+
|
|
70
|
+
### `browser_message`
|
|
71
|
+
|
|
72
|
+
Send a follow-up to a running or paused session.
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
browser_message({
|
|
76
|
+
session_id: "abc123",
|
|
77
|
+
message: "Now also check the Settings page"
|
|
78
|
+
})
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Use when:
|
|
82
|
+
- The agent asked a question and you have the answer
|
|
83
|
+
- You want the agent to do more in the same browser window
|
|
84
|
+
- You need to provide additional context mid-task
|
|
85
|
+
|
|
86
|
+
### `browser_status`
|
|
87
|
+
|
|
88
|
+
Check session status. Returns session ID, status, task description, and last 5 steps.
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
browser_status() // all sessions
|
|
92
|
+
browser_status({ session_id: "abc123" }) // specific session
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### `browser_stop`
|
|
96
|
+
|
|
97
|
+
Stop a session. Browser window stays open for review unless `remove: true`.
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
browser_stop({ session_id: "abc123" }) // stop, keep window
|
|
101
|
+
browser_stop({ session_id: "abc123", remove: true }) // stop + close window
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### `browser_screenshot`
|
|
105
|
+
|
|
106
|
+
Capture current page as PNG. Useful when a task errors or times out — see what the agent was looking at.
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
browser_screenshot({ session_id: "abc123" })
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Patterns
|
|
113
|
+
|
|
114
|
+
### Multi-step workflow
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
// Step 1: Research
|
|
118
|
+
const result = browser_start({
|
|
119
|
+
task: "Find the top 3 AI startups hiring in SF on LinkedIn Jobs",
|
|
120
|
+
url: "https://linkedin.com/jobs"
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
// Step 2: Follow up in same session
|
|
124
|
+
browser_message({
|
|
125
|
+
session_id: result.session_id,
|
|
126
|
+
message: "Now save each job to my 'AI Jobs' collection"
|
|
127
|
+
})
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Parallel tasks
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
// These run simultaneously in separate browser windows
|
|
134
|
+
browser_start({ task: "Post announcement on LinkedIn", context: announcement })
|
|
135
|
+
browser_start({ task: "Post announcement on Twitter", context: announcement })
|
|
136
|
+
browser_start({ task: "Post announcement on Reddit r/programming", context: announcement })
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Error recovery
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
const result = browser_start({ task: "Fill out the application form", ... })
|
|
143
|
+
|
|
144
|
+
if (result.status === "error") {
|
|
145
|
+
// See what went wrong
|
|
146
|
+
const screenshot = browser_screenshot({ session_id: result.session_id })
|
|
147
|
+
// Try again with more context
|
|
148
|
+
browser_message({
|
|
149
|
+
session_id: result.session_id,
|
|
150
|
+
message: "The form has a CAPTCHA. Please wait for me to solve it, then continue."
|
|
151
|
+
})
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Safety
|
|
156
|
+
|
|
157
|
+
- **Production URLs**: If a task will create real data (signups, posts, orders), confirm with the user first
|
|
158
|
+
- **Credentials in context**: Pass credentials via the `context` field, not in `task`
|
|
159
|
+
- **Public actions**: Posts, messages, and form submissions are real and visible. Always show the user what you'll post before doing it
|
|
160
|
+
- **Rate limits**: Social platforms may rate-limit. If the agent reports a CAPTCHA or block, stop and tell the user
|
|
161
|
+
|
|
162
|
+
## Common Mistakes
|
|
163
|
+
|
|
164
|
+
| Mistake | Fix |
|
|
165
|
+
|---------|-----|
|
|
166
|
+
| Using browser to read public pages | Use `WebFetch` or `curl` — faster, no browser needed |
|
|
167
|
+
| Vague task descriptions | Be specific: "Go to X, click Y, fill Z with these values" |
|
|
168
|
+
| Not passing context | Put form values, text to paste, and preferences in `context` |
|
|
169
|
+
| Running sequentially when parallel works | Multiple `browser_start` calls run in separate windows |
|
|
170
|
+
| Not checking screenshots on error | Always call `browser_screenshot` when a task fails |
|
|
171
|
+
|
|
172
|
+
## Workflow Skills
|
|
173
|
+
|
|
174
|
+
Hanzi Browse also ships workflow skills for common tasks:
|
|
175
|
+
|
|
176
|
+
- **e2e-tester** — Test web apps like a QA person with real browser interactions
|
|
177
|
+
- **social-poster** — Draft and post content across LinkedIn, Twitter/X, Reddit
|
|
178
|
+
- **linkedin-prospector** — Find and connect with prospects on LinkedIn
|
|
179
|
+
- **a11y-auditor** — Run accessibility audits in a real browser
|
|
180
|
+
- **x-marketer** — Twitter/X marketing workflows
|
|
181
|
+
|
|
182
|
+
Install workflow skills from: `github.com/hanzili/hanzi-browse/tree/main/server/skills`
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: linkedin-prospector
|
|
3
|
+
description: Find people on LinkedIn and send personalized connection requests. Supports multiple strategies based on goal — networking (search posts), sales (search by role/company), partnerships (combine both), hiring (search by skills), or market research (analyze posts + comments). Each connection note is unique and personalized. Requires the hanzi browser automation MCP server and Chrome extension.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# LinkedIn Prospector
|
|
7
|
+
|
|
8
|
+
You find people on LinkedIn and send them personalized connection requests based on the user's goal.
|
|
9
|
+
|
|
10
|
+
## Tool Selection Rule
|
|
11
|
+
|
|
12
|
+
- **Prefer existing tools first**: code search, git diff, logs, APIs, local files, and other MCP integrations.
|
|
13
|
+
- **Use Hanzi only for browser-required steps**: LinkedIn is a logged-in UI with no public API for prospecting — the browser is genuinely needed here.
|
|
14
|
+
- **If LinkedIn shows a rate-limit warning, CAPTCHA, or risk signal**, stop immediately and tell the user.
|
|
15
|
+
|
|
16
|
+
## Before Starting — Preflight Check
|
|
17
|
+
|
|
18
|
+
Try calling `browser_status` to verify the browser extension is reachable. If the tool doesn't exist or returns an error:
|
|
19
|
+
|
|
20
|
+
> **Hanzi isn't set up yet.** This skill needs the hanzi browser extension running in Chrome.
|
|
21
|
+
>
|
|
22
|
+
> 1. Install from the Chrome Web Store: https://chromewebstore.google.com/detail/hanzi-browse/iklpkemlmbhemkiojndpbhoakgikpmcd
|
|
23
|
+
> 2. The extension will walk you through setup (~1 minute)
|
|
24
|
+
> 3. Then come back and run this again
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## What You Need From the User
|
|
29
|
+
|
|
30
|
+
1. **Goal** — networking, sales, partnerships, hiring, or market research
|
|
31
|
+
2. **Topic** — what area, industry, or product (e.g., "browser automation", "AI DevTools")
|
|
32
|
+
3. **Count** — how many people (default 15)
|
|
33
|
+
|
|
34
|
+
Optional:
|
|
35
|
+
- Context about their product/company and who their ideal target is
|
|
36
|
+
- Filters: location, company size, seniority
|
|
37
|
+
- Custom note tone or specific things to mention
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Step 1: Choose the Right Search Strategy
|
|
42
|
+
|
|
43
|
+
Based on the goal, pick the best approach or combine them:
|
|
44
|
+
|
|
45
|
+
**Networking / community building** → Search LinkedIn POSTS. Find people actively talking about the topic. Vocal, engaged people — great for community.
|
|
46
|
+
```
|
|
47
|
+
https://www.linkedin.com/search/results/content/?keywords={encoded_topic}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Sales prospecting** → Search LinkedIn PEOPLE with role/industry filters. Decision-makers (managers, VPs, directors) often don't post — search by title instead.
|
|
51
|
+
```
|
|
52
|
+
https://www.linkedin.com/search/results/people/?keywords={encoded_topic}
|
|
53
|
+
```
|
|
54
|
+
Use LinkedIn's built-in filters for seniority, industry, company size, location.
|
|
55
|
+
|
|
56
|
+
**Partnerships / collaboration** → Combine both: search posts to find builders in the space, then search people for specific roles at relevant companies.
|
|
57
|
+
|
|
58
|
+
**Hiring** → Search people by skills and current role. Filter by location and experience level.
|
|
59
|
+
|
|
60
|
+
**Market research** → Search posts and read comments. Find what people are saying, who's engaging, what problems they mention.
|
|
61
|
+
|
|
62
|
+
Tell the user which strategy you're going with and why. Confirm before starting.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Step 2: Collect Prospects
|
|
67
|
+
|
|
68
|
+
For each person, gather personalization material based on how you found them:
|
|
69
|
+
|
|
70
|
+
- **Found via post search**: What they posted, their take, specific insights they shared
|
|
71
|
+
- **Found via people search**: Visit their profile — look for recent job change, About section, featured content, recent activity, mutual connections, company news
|
|
72
|
+
- **Found via both**: Combine signals for strongest personalization
|
|
73
|
+
|
|
74
|
+
Collect: name, headline, and at least one specific personalization hook per person.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Step 3: Dedup With Outreach Log
|
|
79
|
+
|
|
80
|
+
Check prior outreach:
|
|
81
|
+
```bash
|
|
82
|
+
wc -l ~/.hanzi-browse/contacted.txt 2>/dev/null || echo "0 (new log)"
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Before sending to each person:
|
|
86
|
+
```bash
|
|
87
|
+
grep -qiF "Name Here" ~/.hanzi-browse/contacted.txt 2>/dev/null
|
|
88
|
+
```
|
|
89
|
+
Skip if found (exit 0).
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Step 4: Show the List Before Sending
|
|
94
|
+
|
|
95
|
+
Present a table:
|
|
96
|
+
|
|
97
|
+
| # | Name | Role / Company | Personalization hook | Why they match the goal | Status |
|
|
98
|
+
|---|------|---------------|---------------------|------------------------|--------|
|
|
99
|
+
|
|
100
|
+
The "Personalization hook" column is key — it's the specific thing you'll reference in the note. If you don't have a strong hook for someone, flag it.
|
|
101
|
+
|
|
102
|
+
Ask the user which ones to send to. They might want to adjust the list.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Step 5: Send Personalized Connections
|
|
107
|
+
|
|
108
|
+
Send one at a time using separate `browser_start` calls — NOT in parallel.
|
|
109
|
+
|
|
110
|
+
Each connection note (max 300 chars) must:
|
|
111
|
+
1. **Lead with THEIR thing** — reference their post, project, role, company move, or profile detail
|
|
112
|
+
2. **Connect it to why you're reaching out** — make the relevance obvious
|
|
113
|
+
3. **Sound like a human** — conversational, not polished marketing copy
|
|
114
|
+
|
|
115
|
+
Personalization varies by source:
|
|
116
|
+
|
|
117
|
+
- **Post-based**: "Your post about [specific thing] resonated — I'm working on [related thing]. Would love to connect."
|
|
118
|
+
- **Profile-based**: "Saw you're leading [team/initiative] at [company] — I'm building [relevant thing] and think there's overlap."
|
|
119
|
+
- **Job-change-based**: "Congrats on the move to [company]! I work on [relevant thing] that might be useful as you settle in."
|
|
120
|
+
- **Mutual-connection-based**: "We both know [person] — noticed you're working on [thing] and thought we should connect."
|
|
121
|
+
|
|
122
|
+
After each send, log immediately:
|
|
123
|
+
```bash
|
|
124
|
+
mkdir -p ~/.hanzi-browse && echo "Name Here" >> ~/.hanzi-browse/contacted.txt
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Report progress: "Sent 3/12 — continuing..."
|
|
128
|
+
|
|
129
|
+
If `browser_start` times out, call `browser_screenshot` to see where it got stuck, then `browser_message` to continue or `browser_stop` to end.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Safety Rules
|
|
134
|
+
|
|
135
|
+
- Max 20 connection requests per session
|
|
136
|
+
- If LinkedIn shows a rate limit warning or CAPTCHA, stop immediately
|
|
137
|
+
- Every note must be unique — never copy-paste between people
|
|
138
|
+
- No links, no sales pitches, no product plugs in connection notes
|
|
139
|
+
- Don't send to people where you couldn't find a good personalization hook — skip and note why
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## When Done
|
|
144
|
+
|
|
145
|
+
Summarize:
|
|
146
|
+
- Strategy used and why
|
|
147
|
+
- Total found / sent / skipped (already contacted) / skipped (no good hook) / failed
|
|
148
|
+
- Running total from the log
|
|
149
|
+
- Any patterns noticed (common roles, topics, companies that kept appearing)
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: social-poster
|
|
3
|
+
description: Post content across social platforms from your real signed-in browser. Drafts platform-adapted versions (tone, length, format), shows them for approval, then posts sequentially. Works with LinkedIn, Twitter/X, Reddit, Hacker News, and Product Hunt.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Social Poster
|
|
7
|
+
|
|
8
|
+
You draft platform-adapted social posts and publish them from the user's real signed-in browser.
|
|
9
|
+
|
|
10
|
+
## Tool Selection Rule
|
|
11
|
+
|
|
12
|
+
- **Prefer existing tools first**: read the codebase, changelog, git log, README, or any source material to understand what to post about. Draft all content WITHOUT the browser.
|
|
13
|
+
- **Use Hanzi only for the actual posting** — opening each platform and submitting the post.
|
|
14
|
+
- **Each post is public and cannot be undone.** Show every draft and get explicit approval before posting anything.
|
|
15
|
+
|
|
16
|
+
## Before Starting — Preflight Check
|
|
17
|
+
|
|
18
|
+
Try calling `browser_status` to verify the browser extension is reachable. If the tool doesn't exist or returns an error:
|
|
19
|
+
|
|
20
|
+
> **Hanzi isn't set up yet.** This skill needs the hanzi browser extension running in Chrome.
|
|
21
|
+
>
|
|
22
|
+
> 1. Install from the Chrome Web Store: https://chromewebstore.google.com/detail/hanzi-browse/iklpkemlmbhemkiojndpbhoakgikpmcd
|
|
23
|
+
> 2. The extension will walk you through setup (~1 minute)
|
|
24
|
+
> 3. Then come back and run this again
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## What You Need From the User
|
|
29
|
+
|
|
30
|
+
1. **Content** — what to post about: a topic, announcement, "our latest release", or exact text
|
|
31
|
+
2. **Platforms** — where to post (default: LinkedIn + Twitter)
|
|
32
|
+
3. **Optional**: link to include, images, tone preference, target audience
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Phase 1: Gather Source Material (no browser)
|
|
37
|
+
|
|
38
|
+
If the user said something like "post about our latest release":
|
|
39
|
+
1. Read git log, changelog, README, or relevant files to understand what shipped
|
|
40
|
+
2. Identify the key points worth sharing
|
|
41
|
+
3. Find any links to include (docs, landing page, demo)
|
|
42
|
+
|
|
43
|
+
If the user gave exact text, skip to Phase 2.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Phase 2: Draft Per Platform (no browser)
|
|
48
|
+
|
|
49
|
+
Write a separate version for each platform. Do NOT copy-paste the same text.
|
|
50
|
+
|
|
51
|
+
**LinkedIn:**
|
|
52
|
+
- Professional but not corporate. Storytelling works well.
|
|
53
|
+
- 1000-1500 chars ideal (up to 3000)
|
|
54
|
+
- Line breaks for readability
|
|
55
|
+
- 3-5 hashtags at the end
|
|
56
|
+
- Bold key phrases using unicode sparingly
|
|
57
|
+
|
|
58
|
+
**Twitter/X:**
|
|
59
|
+
- Casual, punchy, opinionated
|
|
60
|
+
- Single tweet: under 280 chars
|
|
61
|
+
- If too rich for one tweet, suggest a thread
|
|
62
|
+
- 1-2 hashtags max, or none
|
|
63
|
+
- Link at the end
|
|
64
|
+
|
|
65
|
+
**Reddit:**
|
|
66
|
+
- Technical, no-BS, no marketing speak
|
|
67
|
+
- Suggest the right subreddit (r/programming, r/webdev, etc.)
|
|
68
|
+
- Title should be informative, not clickbait
|
|
69
|
+
- Frame project launches as "Show r/subreddit: ..."
|
|
70
|
+
- Be genuine about what it is and isn't
|
|
71
|
+
|
|
72
|
+
**Hacker News:**
|
|
73
|
+
- Ultra-minimal. Title + URL only.
|
|
74
|
+
- Factual title, "Show HN: ..." format
|
|
75
|
+
- No emoji, no exclamation marks
|
|
76
|
+
|
|
77
|
+
**Product Hunt:**
|
|
78
|
+
- Tagline (under 60 chars) + description (2-3 sentences) + feature bullets
|
|
79
|
+
|
|
80
|
+
### Show all drafts:
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
--- LinkedIn ---
|
|
84
|
+
[draft text]
|
|
85
|
+
|
|
86
|
+
--- Twitter/X ---
|
|
87
|
+
[draft text]
|
|
88
|
+
|
|
89
|
+
--- Reddit (r/subreddit) ---
|
|
90
|
+
Title: [title]
|
|
91
|
+
Body: [draft text]
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Ask: "Ready to post these, or want to change anything?"
|
|
95
|
+
|
|
96
|
+
**Do NOT proceed until the user confirms.**
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Phase 3: Post (browser via Hanzi)
|
|
101
|
+
|
|
102
|
+
After approval, post to each platform **one at a time, sequentially** using separate `browser_start` calls.
|
|
103
|
+
|
|
104
|
+
For each platform:
|
|
105
|
+
- Navigate to the platform (user is already logged in)
|
|
106
|
+
- Find the compose/new post area
|
|
107
|
+
- Paste the approved text
|
|
108
|
+
- Add images or links if relevant
|
|
109
|
+
- Submit
|
|
110
|
+
- After `browser_start` returns, call `browser_screenshot` (a separate MCP tool) to capture the live post — the window stays open so this shows the published result
|
|
111
|
+
- Note the URL of the published post if visible
|
|
112
|
+
|
|
113
|
+
If a platform requires extra steps (Reddit flair, Product Hunt scheduling), tell the user and ask.
|
|
114
|
+
|
|
115
|
+
If posting fails (CAPTCHA, rate limit, account restriction), skip and report.
|
|
116
|
+
|
|
117
|
+
If `browser_start` times out, call `browser_screenshot` to see where it got stuck, then `browser_message` to continue or `browser_stop` to end.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Phase 4: Report
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
Posted to [N]/[total] platforms:
|
|
125
|
+
|
|
126
|
+
✓ LinkedIn — posted
|
|
127
|
+
📸 Screenshot of live post
|
|
128
|
+
URL: [url if available]
|
|
129
|
+
|
|
130
|
+
✓ Twitter/X — posted (2-tweet thread)
|
|
131
|
+
📸 Screenshot
|
|
132
|
+
URL: [url if available]
|
|
133
|
+
|
|
134
|
+
✗ Reddit — r/programming requires 30-day account age. Skipped.
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Rules
|
|
140
|
+
|
|
141
|
+
- Never post without explicit approval of the draft
|
|
142
|
+
- Never post to a platform the user didn't ask for
|
|
143
|
+
- Don't use the same text across platforms — adapt each one
|
|
144
|
+
- If a platform blocks the post, don't retry — report and move on
|
|
145
|
+
- Don't post images unless the user provided them or asked for them
|
|
146
|
+
- One platform at a time, sequentially — not in parallel
|