Navigation redirects
Playwright's browser_navigate causes redirects on LinkedIn edit URLs. browser-use MCP's browser_navigate handles this correctly — it's the primary navigation driver in this skill.
LinkedIn is a React SPA. input.value = is silently ignored.
Typeaheads need timed multi-step calls. This skill uses browser-use MCP for navigation and clicks,
and Playwright MCP for React form filling — so you don't have to debug the DOM every time.
$ claude "add Python to my cocode.dk LinkedIn entry"
Loading linkedin-profile-editor skill...
browser_navigate → experience edit form
browser_get_state → found Save button [idx 42]
Running add-skill.js → added: "Python"
browser_click [42] → saved
✓ Done. Profile updated.
Playwright's browser_navigate causes redirects on LinkedIn edit URLs. browser-use MCP's browser_navigate handles this correctly — it's the primary navigation driver in this skill.
.value =React maintains internal fiber state. Setting input.value directly has no effect. You need nativeInputValueSetter from the prototype chain plus dispatched synthetic events.
The company field fetches suggestions async. Type → wait → check → click. One synchronous call returns nothing. Scripts split this into 3 separate timed steps.
The skill input and title input are visually identical in the DOM. Targeting the wrong one does nothing — or silently overwrites the wrong field. Scripts use precise placeholder selectors.
| Script | Purpose | Params |
|---|---|---|
inspect-dialog.js |
Dump all fields, IDs, values, and buttons in the open dialog | none |
navigate-to-edit.js |
Open the edit dialog for an existing experience entry | USERNAME ENTRY_ID |
open-add-position.js |
Navigate to experience page and open Add Position dialog | USERNAME |
fill-position-form.js |
Fill title, employment type, checkbox, and description | TITLE TYPE working DESC |
fill-company-typeahead.js |
Type company name and select from suggestions — 3 steps | COMPANY_NAME |
fill-dates.js |
Set start and end date selects | START_M START_Y END_M END_Y |
add-skill.js |
Add one skill to an entry — run once per skill | SKILL_NAME |
save.js |
Save the dialog — tries XPath, text match, aria-label | none |
delete-entry.js |
Delete an entry via the edit form — 3 steps | USERNAME ENTRY_ID |
post-company-update.js |
Post a text update to a company page — 4 steps | COMPANY_ID POST_TEXT |
LinkedIn stores these as numeric IDs. Pass the number as a string to fill-position-form.js.
2 Contract12 Full-time11 Part-time3 Self-employed20 Freelance18 Internshipbrowser_navigate → /details/experience/browser_get_state + browser_click click + buttonbrowser_get_state + browser_click click "Add position"inspect-dialog.js verify dialog openedfill-position-form.js title, type, descriptionfill-company-typeahead.js 3 steps with waitfill-dates.js start and end datesbrowser_get_state + browser_click click Saveadd-skill.js × N — once per skillbrowser_navigate → /edit/forms/ENTRY_ID/inspect-dialog.js verify fieldsbrowser_get_state + browser_click click Savebrowser_navigate → /edit/forms/ENTRY_ID/delete-entry.js step 2 — click Deletedelete-entry.js step 3 — confirmRun this on the experience page to list all entry IDs:
(() => {
return Array.from(document.querySelectorAll('a[href*="/edit/forms/"]'))
.map(l => l.href).join('\n');
})()
Or take a screenshot — pencil buttons link to URLs that contain the ID.
Works with Claude Code, Codex, Cursor, OpenCode, GitHub Copilot, Roo, and more. Installs to all detected agents automatically:
npx add-skill cocodedk/linkedin-profile-editor
Or target a specific agent:
npx add-skill cocodedk/linkedin-profile-editor --agent claude npx add-skill cocodedk/linkedin-profile-editor --agent codex
Then just ask your agent: "add Python to my LinkedIn cocode.dk entry" — no boilerplate, no DOM debugging.
Use browser-use MCP's browser_navigate for all URLs. It handles LinkedIn redirects correctly. Playwright's browser_navigate does not.
Run browser_get_state immediately before browser_click. Element indices shift after any DOM mutation — dialog open, typeahead appearing, etc.
Never write React form logic inline. Scripts handle nativeInputValueSetter + synthetic events. Inline code will be silently ignored by React.
Built by Babak Bandpey while automating a job search workflow with Claude Code. LinkedIn breaks enough standard Playwright patterns that the fixes are worth sharing.