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.
Files changed (78) hide show
  1. package/README.md +182 -0
  2. package/dist/agent/loop.d.ts +63 -0
  3. package/dist/agent/loop.js +186 -0
  4. package/dist/agent/system-prompt.d.ts +7 -0
  5. package/dist/agent/system-prompt.js +41 -0
  6. package/dist/agent/tools.d.ts +9 -0
  7. package/dist/agent/tools.js +154 -0
  8. package/dist/cli/detect-credentials.d.ts +31 -0
  9. package/dist/cli/detect-credentials.js +44 -0
  10. package/dist/cli/import-credentials-handler.d.ts +14 -0
  11. package/dist/cli/import-credentials-handler.js +22 -0
  12. package/dist/cli/session-files.d.ts +28 -0
  13. package/dist/cli/session-files.js +118 -0
  14. package/dist/cli/setup.d.ts +10 -0
  15. package/dist/cli/setup.js +915 -0
  16. package/dist/cli.d.ts +16 -0
  17. package/dist/cli.js +506 -0
  18. package/dist/dashboard/assets/index-CEFyesbT.js +46 -0
  19. package/dist/dashboard/assets/index-Dnht2kLU.css +1 -0
  20. package/dist/dashboard/index.html +13 -0
  21. package/dist/index.d.ts +2 -0
  22. package/dist/index.js +1116 -0
  23. package/dist/ipc/index.d.ts +8 -0
  24. package/dist/ipc/index.js +8 -0
  25. package/dist/ipc/native-host.d.ts +96 -0
  26. package/dist/ipc/native-host.js +223 -0
  27. package/dist/ipc/websocket-client.d.ts +73 -0
  28. package/dist/ipc/websocket-client.js +199 -0
  29. package/dist/license/manager.d.ts +20 -0
  30. package/dist/license/manager.js +15 -0
  31. package/dist/llm/client.d.ts +72 -0
  32. package/dist/llm/client.js +227 -0
  33. package/dist/llm/credentials.d.ts +61 -0
  34. package/dist/llm/credentials.js +200 -0
  35. package/dist/llm/vertex.d.ts +22 -0
  36. package/dist/llm/vertex.js +335 -0
  37. package/dist/managed/api-http.test.d.ts +7 -0
  38. package/dist/managed/api-http.test.js +623 -0
  39. package/dist/managed/api.d.ts +51 -0
  40. package/dist/managed/api.js +1448 -0
  41. package/dist/managed/api.test.d.ts +10 -0
  42. package/dist/managed/api.test.js +146 -0
  43. package/dist/managed/auth.d.ts +38 -0
  44. package/dist/managed/auth.js +192 -0
  45. package/dist/managed/billing.d.ts +70 -0
  46. package/dist/managed/billing.js +227 -0
  47. package/dist/managed/deploy.d.ts +17 -0
  48. package/dist/managed/deploy.js +385 -0
  49. package/dist/managed/e2e.test.d.ts +15 -0
  50. package/dist/managed/e2e.test.js +151 -0
  51. package/dist/managed/hardening.test.d.ts +14 -0
  52. package/dist/managed/hardening.test.js +346 -0
  53. package/dist/managed/integration.test.d.ts +8 -0
  54. package/dist/managed/integration.test.js +274 -0
  55. package/dist/managed/log.d.ts +18 -0
  56. package/dist/managed/log.js +31 -0
  57. package/dist/managed/server.d.ts +12 -0
  58. package/dist/managed/server.js +69 -0
  59. package/dist/managed/store-pg.d.ts +191 -0
  60. package/dist/managed/store-pg.js +479 -0
  61. package/dist/managed/store.d.ts +188 -0
  62. package/dist/managed/store.js +379 -0
  63. package/dist/relay/auto-start.d.ts +19 -0
  64. package/dist/relay/auto-start.js +71 -0
  65. package/dist/relay/server.d.ts +17 -0
  66. package/dist/relay/server.js +403 -0
  67. package/dist/types/index.d.ts +5 -0
  68. package/dist/types/index.js +4 -0
  69. package/dist/types/session.d.ts +134 -0
  70. package/dist/types/session.js +16 -0
  71. package/package.json +61 -0
  72. package/skills/README.md +48 -0
  73. package/skills/a11y-auditor/SKILL.md +42 -0
  74. package/skills/e2e-tester/SKILL.md +154 -0
  75. package/skills/hanzi-browse/SKILL.md +182 -0
  76. package/skills/linkedin-prospector/SKILL.md +149 -0
  77. package/skills/social-poster/SKILL.md +146 -0
  78. 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