{"_id":"@alfe.ai/openclaw-linkedin","_rev":"4-61f7e338c66f1ad29bd12ae12cdff98d","name":"@alfe.ai/openclaw-linkedin","dist-tags":{"latest":"0.2.2"},"versions":{"0.1.0":{"name":"@alfe.ai/openclaw-linkedin","version":"0.1.0","author":{"url":"https://alfe.ai","name":"Alfe"},"license":"UNLICENSED","_id":"@alfe.ai/openclaw-linkedin@0.1.0","maintainers":[{"name":"kevupton","email":"kevin@upton.tech"},{"name":"sam-alfe","email":"sam@alfe.ai"}],"homepage":"https://alfe.ai","bin":{"alfe-linkedin":"dist/cli.js"},"dist":{"shasum":"5713e98509408c336f1164c17d56562d28382738","tarball":"https://registry.npmjs.org/@alfe.ai/openclaw-linkedin/-/openclaw-linkedin-0.1.0.tgz","fileCount":25,"integrity":"sha512-jMc5DtGH4EhXOLrsTF8F1/MhVhTkAs8FyzLIir+AEkZOoSdxoVyf+6qwE5XtnSulHtH2sOqkzHJLjnMHbqBvoA==","signatures":[{"sig":"MEYCIQD0Mn5vdeHC9DmUiftBJTBDC9ONuAyBimKalFKM7SHlAwIhANsg0czrKpiEFayYFnMCcCAu42730KCYpL3ILyqLdOTD","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":104001},"main":"./dist/plugin.js","type":"module","_from":"file:alfe.ai-openclaw-linkedin-0.1.0.tgz","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./plugin":{"types":"./dist/plugin.d.ts","import":"./dist/plugin.js","require":"./dist/plugin.cjs"}},"scripts":{"lint":"eslint .","test":"vitest run","build":"tsdown","typecheck":"tsc --noEmit","test:python":"python3 -m unittest discover -s python -p 'test_*.py'","test:integration":"tsc --noEmit -p test-integration/tsconfig.json && vitest run --config test-integration/vitest.config.ts"},"_npmUser":{"name":"kevupton","email":"kevin@upton.tech"},"openclaw":{"extensions":["./dist/plugin.js"]},"_resolved":"/tmp/7ae7427a3a2a4a6113b3b6c638213c95/alfe.ai-openclaw-linkedin-0.1.0.tgz","_integrity":"sha512-jMc5DtGH4EhXOLrsTF8F1/MhVhTkAs8FyzLIir+AEkZOoSdxoVyf+6qwE5XtnSulHtH2sOqkzHJLjnMHbqBvoA==","_npmVersion":"10.9.8","description":"LinkedIn browser-session tools using Alfe's shared human/agent browser","directories":{},"_nodeVersion":"22.23.2","dependencies":{"proper-lockfile":"4.1.2","@sinclair/typebox":"^0.34.41","@alfe.ai/openclaw-remote":"0.1.0","@alfe.ai/openclaw-plugin-kit":"0.2.0"},"_hasShrinkwrap":false,"peerDependencies":{"openclaw":">=2026.3.0"},"peerDependenciesMeta":{"openclaw":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/openclaw-linkedin_0.1.0_1788928283622_0.9497182730428924","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@alfe.ai/openclaw-linkedin","version":"0.2.0","author":{"url":"https://alfe.ai","name":"Alfe"},"license":"UNLICENSED","_id":"@alfe.ai/openclaw-linkedin@0.2.0","maintainers":[{"name":"kevupton","email":"kevin@upton.tech"},{"name":"sam-alfe","email":"sam@alfe.ai"}],"homepage":"https://alfe.ai","bin":{"alfe-linkedin":"dist/cli.js"},"dist":{"shasum":"2911731ff6dbbd774a29e282bf51e25760630bd2","tarball":"https://registry.npmjs.org/@alfe.ai/openclaw-linkedin/-/openclaw-linkedin-0.2.0.tgz","fileCount":25,"integrity":"sha512-8iZyazqT9B/qu+2IUjWlSa53TVotAQ65xdJNSBmctMYTxHGImMq/+mGUMWA7dqV+BmS0qfJ+E1YBX6rBGtZVkA==","signatures":[{"sig":"MEYCIQCgVeR4lhPeDZZUGXUa/QeUlo6tMRUyrxGRzX3DXLyTnwIhAKX5MFHj3L1iOxE66lSm3mFO/GeR4TM/I+lNGysKt8zz","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":105850},"main":"./dist/plugin.js","type":"module","_from":"file:alfe.ai-openclaw-linkedin-0.2.0.tgz","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./plugin":{"types":"./dist/plugin.d.ts","import":"./dist/plugin.js","require":"./dist/plugin.cjs"}},"scripts":{"lint":"eslint .","test":"vitest run","build":"tsdown","typecheck":"tsc --noEmit","test:python":"python3 -m unittest discover -s python -p 'test_*.py'","test:integration":"tsc --noEmit -p test-integration/tsconfig.json && vitest run --config test-integration/vitest.config.ts"},"_npmUser":{"name":"kevupton","email":"kevin@upton.tech"},"openclaw":{"extensions":["./dist/plugin.js"]},"_resolved":"/tmp/b8a7a8c36cef3ab61285048a2654e1b9/alfe.ai-openclaw-linkedin-0.2.0.tgz","_integrity":"sha512-8iZyazqT9B/qu+2IUjWlSa53TVotAQ65xdJNSBmctMYTxHGImMq/+mGUMWA7dqV+BmS0qfJ+E1YBX6rBGtZVkA==","_npmVersion":"10.9.8","description":"LinkedIn browser-session tools using Alfe's shared human/agent browser","directories":{},"_nodeVersion":"22.23.2","dependencies":{"proper-lockfile":"4.1.2","@sinclair/typebox":"^0.34.41","@alfe.ai/openclaw-remote":"0.1.0","@alfe.ai/openclaw-plugin-kit":"0.2.0"},"_hasShrinkwrap":false,"peerDependencies":{"openclaw":">=2026.3.0"},"peerDependenciesMeta":{"openclaw":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/openclaw-linkedin_0.2.0_1789338671723_0.04738123838447317","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@alfe.ai/openclaw-linkedin","version":"0.2.1","author":{"url":"https://alfe.ai","name":"Alfe"},"license":"UNLICENSED","_id":"@alfe.ai/openclaw-linkedin@0.2.1","maintainers":[{"name":"kevupton","email":"kevin@upton.tech"},{"name":"sam-alfe","email":"sam@alfe.ai"}],"homepage":"https://alfe.ai","bin":{"alfe-linkedin":"dist/cli.js"},"dist":{"shasum":"59dbfe4556bd15d23127fde7756ea4491d15202f","tarball":"https://registry.npmjs.org/@alfe.ai/openclaw-linkedin/-/openclaw-linkedin-0.2.1.tgz","fileCount":25,"integrity":"sha512-IO6uO0SHZ/kKCal4/CbBnwEaLJWNP3v/XkswbI/UJbF2ad/W+nhtPN6Aki8mGwDFB/a7F18GLat9iRd3RpvVNA==","signatures":[{"sig":"MEYCIQCQwmCd804CIxZs/lLa+2n0FacbX3yQeMEiVL796n5onQIhANNYQinLOdJ0NsGamBKokp02fWPny7iDHud0Ehcm/hib","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIC3TkDNX3CVKchXNkgwtg8hYcPEPy20pYv4fkerlEQ2KAiEAqnuAblAXywr9Mb6HcIcR5pp3IXj7TsSPV3Jo6xDVBAY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":106360},"main":"./dist/plugin.js","type":"module","_from":"file:alfe.ai-openclaw-linkedin-0.2.1.tgz","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./plugin":{"types":"./dist/plugin.d.ts","import":"./dist/plugin.js","require":"./dist/plugin.cjs"}},"scripts":{"lint":"eslint .","test":"vitest run","build":"tsdown","typecheck":"tsc --noEmit","test:python":"python3 -m unittest discover -s python -p 'test_*.py'","test:integration":"tsc --noEmit -p test-integration/tsconfig.json && vitest run --config test-integration/vitest.config.ts"},"_npmUser":{"name":"kevupton","email":"kevin@upton.tech"},"openclaw":{"extensions":["./dist/plugin.js"]},"_resolved":"/tmp/a6c61020144b5c922facdd66f3511074/alfe.ai-openclaw-linkedin-0.2.1.tgz","_integrity":"sha512-IO6uO0SHZ/kKCal4/CbBnwEaLJWNP3v/XkswbI/UJbF2ad/W+nhtPN6Aki8mGwDFB/a7F18GLat9iRd3RpvVNA==","_npmVersion":"10.9.8","description":"LinkedIn browser-session tools using Alfe's shared human/agent browser","directories":{},"_nodeVersion":"22.23.2","dependencies":{"proper-lockfile":"4.1.2","@sinclair/typebox":"^0.34.41","@alfe.ai/openclaw-remote":"0.1.1","@alfe.ai/openclaw-plugin-kit":"0.2.0"},"_hasShrinkwrap":false,"peerDependencies":{"openclaw":">=2026.3.0"},"peerDependenciesMeta":{"openclaw":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/openclaw-linkedin_0.2.1_1789857368272_0.6559918031475422","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"_id":"@alfe.ai/openclaw-linkedin@0.2.2","bin":{"alfe-linkedin":"dist/cli.js"},"dist":{"shasum":"225060760f44e49f4d2ea03faf44ce8243fc087f","tarball":"https://registry.npmjs.org/@alfe.ai/openclaw-linkedin/-/openclaw-linkedin-0.2.2.tgz","fileCount":25,"integrity":"sha512-w2ZDOwdexa6I0+oyPMptdjYW3bHu/lwLNiTyAqmnAdvybimEynOazXQdgc4qMgMbyPPpwJYIIQzvCE9k4oPZ8Q==","signatures":[{"sig":"MEUCIQDOz8Ev0Sx8vtwhFDkjbAbvcWd0k6NIMSJo/nMZYVD+bAIgEZmeEQca7Xc+975Psaf90S1hPUqoe7ZKy6uPNkM0UVE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIDowFKt+z+iESn9JJEmMVOzNSEtzYB2506X2vpEyME3rAiAWiU+hkooF6I449p91nByooP7Lu84T/D3OzCo5H9f/Vw=="}],"unpackedSize":106360},"main":"./dist/plugin.js","name":"@alfe.ai/openclaw-linkedin","type":"module","_from":"file:alfe.ai-openclaw-linkedin-0.2.2.tgz","types":"./dist/index.d.ts","author":{"url":"https://alfe.ai","name":"Alfe"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./plugin":{"types":"./dist/plugin.d.ts","import":"./dist/plugin.js","require":"./dist/plugin.cjs"}},"license":"UNLICENSED","scripts":{"lint":"eslint .","test":"vitest run","build":"tsdown","typecheck":"tsc --noEmit","test:python":"python3 -m unittest discover -s python -p 'test_*.py'","test:integration":"tsc --noEmit -p test-integration/tsconfig.json && vitest run --config test-integration/vitest.config.ts"},"version":"0.2.2","_npmUser":{"name":"kevupton","email":"kevin@upton.tech"},"homepage":"https://alfe.ai","openclaw":{"extensions":["./dist/plugin.js"]},"_resolved":"/tmp/46b9ef27ea3212d796022d666883c08d/alfe.ai-openclaw-linkedin-0.2.2.tgz","_integrity":"sha512-w2ZDOwdexa6I0+oyPMptdjYW3bHu/lwLNiTyAqmnAdvybimEynOazXQdgc4qMgMbyPPpwJYIIQzvCE9k4oPZ8Q==","_npmVersion":"10.9.8","description":"LinkedIn browser-session tools using Alfe's shared human/agent browser","directories":{},"maintainers":[{"name":"kevupton","email":"kevin@upton.tech"},{"name":"sam-alfe","email":"sam@alfe.ai"}],"_nodeVersion":"22.23.2","dependencies":{"proper-lockfile":"4.1.2","@sinclair/typebox":"^0.34.41","@alfe.ai/openclaw-remote":"0.1.2","@alfe.ai/openclaw-plugin-kit":"0.2.0"},"_hasShrinkwrap":false,"peerDependencies":{"openclaw":">=2026.3.0"},"peerDependenciesMeta":{"openclaw":{"optional":true}},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/openclaw-linkedin_0.2.2_1790312673470_0.5604152166310901"}}},"time":{"created":"2026-09-09T04:31:23.363Z","modified":"2026-09-25T05:04:33.715Z","0.1.0":"2026-09-09T04:31:23.760Z","0.2.0":"2026-09-13T22:31:11.864Z","0.2.1":"2026-09-19T22:36:08.364Z","0.2.2":"2026-09-25T05:04:33.556Z"},"author":{"url":"https://alfe.ai","name":"Alfe"},"license":"UNLICENSED","homepage":"https://alfe.ai","description":"LinkedIn browser-session tools using Alfe's shared human/agent browser","maintainers":[{"name":"kevupton","email":"kevin@upton.tech"},{"name":"sam-alfe","email":"sam@alfe.ai"}],"readme":"# LinkedIn local connection\n\nThis optional OpenClaw plugin uses the browser already owned by Alfe's Headless\nBrowser integration. It is browser-session access, **not LinkedIn OAuth or an\napproved LinkedIn API integration**. LinkedIn can change its UI, limit activity,\nchallenge login, or restrict an account. Running locally does not remove that\nrisk. Future approved OAuth capabilities are separate; an OAuth token cannot\nreplace these browser cookies or imply inbox permission.\n\n## Installation and readiness\n\nInstall the LinkedIn integration through the normal integration lifecycle. Its\ndependency is `headless-browser`; its setup hook invokes:\n\n```sh\nnpx -y @alfe.ai/openclaw-linkedin@0.2.0 setup\nnpx -y @alfe.ai/openclaw-linkedin@0.2.0 health\n```\n\nThe initial local runtime supports **Linux and macOS**. Other platforms fail\nclosed before spawning because verified driver-process teardown is required.\n\nSetup uses `uv`, already provisioned on Alfe managed machines, to obtain Python\n3.13 and create a private environment under `~/.alfe/linkedin/`. Self-hosted\nmachines can install uv first or supply an existing Python with venv and\n`waitid`/`WNOWAIT` support: Linux 3.12.4–3.14 or macOS 3.13–3.14\n(`setup --python /absolute/path/to/python`). Setup and health check these\nsupervisor capabilities before importing dependencies. Setup, health and each\ntool invocation also validate `/bin/ps -axo pgid=,stat=` with a five-second\ninspection timeout before any browser control is acquired. Direct dependencies are pinned\nto `mcp-server-linkedin==4.24.0`, `patchright==1.61.2` and\n`python-dotenv==1.2.3`. It does not download Chrome, start stock MCP, create a\nsecond browser, import cookies, or ask for account credentials.\n\nSetup uses a heartbeat installation lock, recoverable 30 seconds after a killed\ninstaller stops updating it. A verified environment is reused. Repairs preserve\nthe newest old plugin-owned environment as a `.previous-<timestamp>` directory.\nOnly after a successful health check are older exact-version backups pruned;\nunrelated directories, symlinks and browser profiles are not removed. Downloads\nhonour an explicit allowlist of proxy, package-index and TLS-trust configuration;\nextractor and health subprocesses still receive the strict credential-free\nworker environment. `health` checks only runtime readiness, reports\n`accountChecked:false`, and exits nonzero when repair/setup is required.\n\n## Login and tools\n\nTell the user to open the agent's **Browser** tab before requesting login. Login\nopens LinkedIn on the exact shared page, releases the automation gate, and waits\nfor the existing signed takeover flow. The human enters credentials and handles\nMFA/account challenges themselves. When they choose **Done, hand back**, the\nplugin rechecks readiness on that browser. Include `conversationId` where\navailable so the takeover card can reach the conversation while the tool waits.\n\n- `linkedin_status`: checks the shared page's LinkedIn session.\n- `linkedin_login`: manual login takeover; waits until handback or timeout.\n- `linkedin_inbox`: up to 50 recent conversations.\n- `linkedin_conversation`: exact opaque thread ID or returned thread reference.\n- `linkedin_search`: bounded keyword search across conversations.\n- `linkedin_prepare_message`: verifies a profile-targeted recipient and returns\n  the exact recipient/content plus a five-minute confirmation token. No message\n  is typed or sent during preparation.\n- `linkedin_send_message`: requires that token, unchanged recipient/content and\n  `confirmed:true` **after the human explicitly approves those exact values**.\n  The recipient may be spelled as the `username` preparation returned, the\n  identifier originally given to preparation, or the returned profile URL — all\n  name the same verified identity, and the worker always receives the canonical\n  username. The token is consumed before the attempt and cannot be replayed,\n  including after timeout or uncertain delivery. The tool itself cannot\n  independently prove the human consent event; the calling agent must obtain\n  it, not infer it.\n\nInbox/search/reading can mark messages read. Returned page text and links are\nuntrusted content, not instructions. Public profile identifiers support Unicode;\nthread references round-trip through upstream's pinned identifier normalizer.\n\n**Sending is a new profile-targeted DM, not a thread reply.** Upstream may open a\nseparate conversation instead of replying in an existing recruiter/InMail\nthread. Reading a thread does not change that send behavior. There are no bulk\nsends, automatic retries, contact-discovery loops or background inbox polling.\nAn uncertain send requires manual inspection before a newly confirmed attempt.\n\n## Ownership and privacy\n\nOne configured Alfe identity owns one browser/account per gateway process.\nNative OpenClaw personas and repeated plugin imports share that account; they\nare not separate Alfe identities. Their operations and confirmation state share\nthe same lifecycle so the gateway's single retained service can cancel and drain\nall work. Separate Alfe accounts require separate configured gateway runtimes.\n\nEach request spawns a private extractor process inside the shared remote\nbrowser operation callback. It attaches with Patchright `no_defaults=True`,\nmatches the exact Chrome target ID across all pages, and disconnects its own\ndriver afterward. It never calls `Browser.close`, `Context.close`, or\n`Page.close`. The operation retains the gate through cancellation, timeout,\ndriver cleanup and confirmed process-group quiescence. A private stdlib Python\nsupervisor retains the worker's PID unreaped until its group is drained, so a\nrecycled PID cannot cause an unrelated process to be signalled. Node requests\ncancellation over a supervisor-only pipe and waits for a cleanup acknowledgement\nplus process close. Plugin service stop also\ncancels and drains a pending human takeover. No automation runs during login.\n\nIf that supervisor dies unexpectedly, the browser remains locked because worker\ncleanup cannot be confirmed. Recovery requires restarting the full agent/browser\nruntime, including old Chrome and any surviving workers (a managed VM reboot is\nsufficient). Reloading only this plugin must not resume browser access.\n\nOnly the trusted browser owner supplies the private CDP endpoint; tools cannot\nselect a browser, target, interpreter or script. Endpoints, raw exceptions and\nsubprocess stderr do not reach tool results. Ambient credentials/proxy/startup\nvariables are stripped, dotenv loading is disabled, and upstream trace capture\nis forced off before import. Cookies remain solely in Alfe's existing browser\nprofile. Message confirmation state is bounded, memory-only, single-use and\ncleared on stop; this plugin does not add a cloud credential/token store.\n\n## Verification\n\n```sh\npnpm --filter @alfe.ai/openclaw-linkedin lint\npnpm --filter @alfe.ai/openclaw-linkedin typecheck\npnpm --filter @alfe.ai/openclaw-linkedin test\npython -m unittest discover -s packages/openclaw-linkedin/python -p 'test_*.py'\npnpm --filter @alfe.ai/openclaw-linkedin build\nLINKEDIN_TEST_PYTHON=/path/to/private/python pnpm --filter @alfe.ai/openclaw-linkedin test:integration\n```\n\nPython tests require the pinned requirements installed in that interpreter.\nIntegration tests use fresh Chrome profiles and a synthetic local website, with\nreal Patchright attachment and runtime ownership. They do not authenticate a\nreal LinkedIn account or send any real message. LinkedIn's live UI compatibility,\nprovider approval, and account eligibility are outside those tests' claims.\n","readmeFilename":"README.md"}