8.7 KiB
| name | description |
|---|---|
| chrome-session | Use this skill to drive a real Chrome instance that is signed in to Oleg's accounts (LinkedIn, Gmail, GitHub, HR platforms, etc.) via the chrome-devtools MCP. The browser is launched against a forked copy of his Chrome profile, so authenticated pages, cookies, and saved sessions are available — letting you read job postings on auth-walled HR platforms, scrape logged-in LinkedIn feeds, inspect application-form fields, and pull data from any site where Oleg is already signed in. Also use this skill as the automatic fallback when WebFetch/curl/standard tools fail to retrieve a page (bot blocking, 403, JS-only render, login wall). |
Chrome Session
This skill operates a real Chrome browser, attached via the chrome-devtools MCP, using a local copy of Oleg's signed-in Chrome profile. It exists so you can fetch information from services where Oleg is logged in — without him having to copy-paste content manually.
When to use
Use this skill when any of the following apply:
- The user asks you to open / read / search something on LinkedIn (feed, profiles, jobs, messages, notifications).
- The user asks to read job descriptions or application forms on HR platforms (Greenhouse, Lever, Workable, Ashby, SmartRecruiters, Workday, LinkedIn Jobs, Wellfound, YC Work at a Startup, company career pages, etc.).
- The user asks to search for jobs by criteria, scroll a feed, or pull a list of postings.
- Any page is gated by login, and Oleg is likely already signed in (Gmail, GitHub private repos, Notion, Trello UI, Slack web, etc.).
- A standard fetch tool failed — WebFetch returned bot-blocking errors, 401/403, empty body because JS isn't executed, captcha, "please log in", or similar. In that case switch to this skill immediately, without asking for confirmation.
Do NOT use this skill for:
- Pages reachable anonymously where WebFetch works fine.
- Anything destructive (don't submit forms, don't send messages) unless the user explicitly asked.
Setup overview
- Launcher script:
scripts/launch-chrome.sh— starts Chrome with--remote-debugging-port=9222against the local profile copy at.chrome/Default. - Profile copy:
.chrome/is a fork of Oleg'sProfile 1(theusulpro@gmail.comprofile). Logged-in cookies live here. The directory is gitignored. - MCP server:
chrome-devtoolsis configured in.mcp.jsonwith--browserUrl=http://127.0.0.1:9222, i.e. it attaches to the already-running Chrome rather than launching its own.
You do not launch Chrome yourself — Oleg starts it manually via the script. Your job is to detect whether it's running and to use the MCP tools to drive it.
Standard workflow
1. Verify Chrome is running and attached
Before any browser action, confirm the debug port is live:
curl -sf http://127.0.0.1:9222/json/version >/dev/null && echo OK || echo DOWN
If DOWN, tell Oleg:
Chrome не запущен с debug-портом. Запусти
./scripts/launch-chrome.shи скажи когда готово.
Do NOT try to launch Chrome yourself — the script blocks the terminal and the user is the one who controls the browser window.
2. Open / select the right page
- Use
mcp__chrome-devtools__list_pagesto see open tabs. - Use
mcp__chrome-devtools__new_pagewith the target URL to open a new tab. If navigation times out (10s default), it's usually fine — the tab still opens; checklist_pagesto confirm the final URL. - Use
mcp__chrome-devtools__select_pageto switch context if you need to drive a tab other than the selected one.
3. Verify the page actually loaded what was expected
After navigation, always confirm you landed on the expected URL/state before extracting content. Check:
- Final URL — if LinkedIn redirected
/feed/→/loginor/checkpoint/..., Oleg is not signed in on that site. - A small
evaluate_scriptto checkdocument.title/ a known DOM marker.
If you detect a login wall, a "session expired" page, a captcha, or any other "you are not signed in" state — stop and tell Oleg immediately:
Не получается открыть
<URL>— похоже, я не залогинен (<observed state>). Залогинься в этом Chrome-инстансе вручную и скажи, когда готово.
Same rule for soft-fail cases (bot wall, "are you human?", 429, sudden empty body).
4. Extract content
Prefer evaluate_script for structured extraction. Snapshots (take_snapshot) give you the a11y tree with uids and are useful for finding clickable elements and form fields.
Scrolling — important detail for LinkedIn and similar SPAs
window.scrollTo / PageDown / End often do nothing because the real scroll container is an inner element (LinkedIn uses <main>; some apps use a div with custom overflow:auto). To trigger lazy loading:
- Find the scrollable container:
const scrollables = [...document.querySelectorAll('*')].filter(el => { const s = getComputedStyle(el); return (s.overflowY === 'auto' || s.overflowY === 'scroll') && el.scrollHeight > el.clientHeight + 50; }); - Increment its
scrollTopin steps (e.g. +1200px), dispatch awheelevent for safety, andawait~700-900ms between steps so lazy chunks can fetch. - Re-check
scrollHeightafter each step — it grows as new content streams in.
For LinkedIn feed specifically: the container is <main>, posts are marked by <h2> with text "Feed post", and the post container is the nearest ancestor whose innerText.length exceeds a few hundred characters.
Form-field inspection (job applications, etc.)
When the user asks "what fields does this application form want?", use take_snapshot to enumerate inputs by their accessibility labels — that maps cleanly to "Name / Email / Resume / Cover letter / Custom question 1 / ...". Don't fill or submit anything unless Oleg explicitly tells you to.
5. Be efficient with content
- Cap extracted text per item (e.g.
.slice(0, 2500)) — LinkedIn posts and job descriptions can be very long and you'll usually summarize anyway. - Deduplicate by container element when scanning lists.
- Return data as JSON from
evaluate_script— it's structured and easy to summarize afterwards.
Failure modes and how to react
| Symptom | Likely cause | Action |
|---|---|---|
curl http://127.0.0.1:9222/json/version fails |
Chrome not launched with debug port | Ask Oleg to run ./scripts/launch-chrome.sh |
new_page times out but the tab appears in list_pages |
Slow site / heavy SPA | Continue — check the final URL via list_pages |
Final URL is /login, /checkpoint, /signin |
Not signed in | Stop. Tell Oleg. Don't try to log in for him. |
| Feed/list shows only the first few items | Lazy loading hasn't fired | Scroll the inner container, not window |
evaluate_script returns count: 0 for known content |
Wrong selectors (sites change markup) | Dump document.body.innerText.slice(0, 500) and a structural probe before guessing more selectors |
| Captcha / "verify you're human" / 429 | Bot detection or rate limit | Stop. Tell Oleg. Don't retry in a loop. |
Don'ts
- Don't launch Chrome yourself (the launcher blocks the terminal; Oleg owns the window).
- Don't try to sign Oleg in when you hit a login wall — just report and wait.
- Don't submit forms, click "Apply", send messages, or post anything unless explicitly instructed.
- Don't loop on bot-detection pages — one detection means stop.
- Don't commit anything from
.chrome/— it's gitignored, keep it that way. - Don't write secrets, cookies, or tokens anywhere outside the running browser. If
evaluate_scriptreturns sensitive data, summarize, don't echo it back verbatim.
Example: "read first N LinkedIn posts"
curl -sf http://127.0.0.1:9222/json/version→ confirm Chrome up.list_pages— is LinkedIn already open? If not,new_page(https://www.linkedin.com/feed/).- Verify final URL contains
/feed/and not/login. evaluate_script: find<main>, stepscrollTop += 1200with 800ms waits until enough"Feed post"h2s have appeared.evaluate_script: extract{actor, text}for the first N posts (slice text to ~2500 chars).- Summarize in Russian to Oleg.
Example: "what fields does this Greenhouse form want?"
new_page(<job-application-url>).take_snapshot— read the accessibility tree, list everytextbox,combobox,radio,file upload,checkboxwith its label.- Report the fields grouped: required vs optional (snapshot exposes
requiredstate), grouped by section if the form has fieldsets. - Do not fill or submit. Wait for Oleg's instruction.