Give your agent access.
Relay runs locally. Your agent uses its normal shell tools.
You complete LinkedIn sign-in in your own browser session.
Paste this into your agent.
Use Codex, Claude, Pi, or another agent with local shell access. Each runtime keeps its own tools and permissions.
The CLI creates and reads a private key itself. You do not paste a key into chat. Sign in only in the browser opened by Relay.
What the instructions ask your agent to do
Check an existing installation, preserve its settings, start the local API if needed, wait for your sign-in, and discover supported operations. For a new installation, download and verify the pinned release, install managed Chromium, and approve this computer through your account. It does not send a test message. Open the instructions as text above to read them in full.
The local API has been tested through its CLI and HTTP interface. These are setup instructions, not a claim that every agent runtime has passed its own integration test.
Install Relay 0.3.0.
Node.js 22 or later on macOS, Windows or Linux. Managed Chromium does not require Chrome.
Download the local app · SHA-256 checksum · Release manifest
Compare the downloaded archive's SHA-256 with the checksum before installing. Use a directory you own; keep browser profiles and private data outside it.
npm install --prefix "$HOME/.local/share/relay-runtime" /path/to/verified-release.tgz
"$HOME/.local/share/relay-runtime/node_modules/.bin/relay" --help
On Windows, use PowerShell Get-FileHash for the checksum and node_modules/.bin/relay.cmd as the executable. Use the installed executable's full path if relay is not on PATH. For a fresh installation:
relay browser install
relay init
relay pair --url https://relay-access.onrender.com --site https://relaycli.dev
relay billing status
Keep the pair command running. Open its approval URL, sign in and click Connect computer. The page creates a key if you have none, selects your key if you have one, or lets you choose between several. You stay on the same page and never copy a key. The CLI must report paired before you start product work.
Start the service with --browser chromium --headless, dedicated private data/profile outside the package directory, and an unused port. If the session needs sign-in, stop that service and restart with the same options without --headless. After sign-in reports ready, restart headless and check ready again. Wait for active work before restarting; release retained cursors first. Each completed LinkedIn request costs $0.01; the $5 welcome credit covers 500 requests. Setup checks are free. relay billing sync retries accounting only. Never unpair or create another installation to avoid an access denial.
Upgrade an existing installation
An installation of 0.1.3 or earlier uses the rea-l command and REA_L_ settings. It keeps working; you do not have to upgrade. To upgrade, keep its verified archive for rollback, stop only its owned service and wait for it to exit. Then install the verified 0.3.0 archive into the same prefix, remove only the old package and relink the commands:
npm install --prefix "$HOME/.local/share/relay-runtime" /path/to/verified-release.tgz
npm uninstall --prefix "$HOME/.local/share/relay-runtime" rea-l
npm rebuild --prefix "$HOME/.local/share/relay-runtime" relay
Afterwards relay and rea-l both run the new version. Run relay browser install, then restart with the same browser, profile, data directory, port and settings. The upgrade does not change the data directory, browser profile or pairing.
To roll back, stop the service, reinstall the kept 0.1.3 archive, remove only the new package and relink rea-l. Then check that rea-l --help works. The data directory is not changed. 0.1.3 reads only REA_L_ settings, so if you set RELAY_DATA_DIR or RELAY_URL, set the matching REA_L_DATA_DIR or REA_L_URL again:
npm install --prefix "$HOME/.local/share/relay-runtime" /path/to/your-kept-0.1.3-archive.tgz
npm uninstall --prefix "$HOME/.local/share/relay-runtime" relay
npm rebuild --prefix "$HOME/.local/share/relay-runtime" rea-l
If Relay is already installed, keep its service, browser profile and data directory. Relay's command is relay. Installations of 0.1.3 and earlier use rea-l, which keeps working; keep your existing launch command if it differs.
relay --help
relay session
If the service is stopped, restart it with its existing browser, profile, data directory and port. Complete normal LinkedIn sign-in in that browser, then run session again. Continue only when it reports ready for your account.
Managed Chromium does not require Google Chrome. Use the browser setup instructions included with your installed version. Linux may also need system libraries and a display for visible sign-in.
Run without a visible window
After a successful visible sign-in, stop your service with Ctrl-C and wait for it to exit. Restart with the same browser, profile, data directory and port, adding --headless. For an existing managed Chromium profile:
relay serve --browser chromium --profile /path/to/your-existing-profile --headlessIf the session needs login or a challenge, stop it and return to the same visible setup. Headless mode does not bypass a challenge. Restart cancels active work and invalidates cursors.
Credentials and local logs
The default data directory is ~/Library/Application Support/Relay on macOS and ~/.local/share/relay elsewhere. If only the earlier rea-L directory exists there, it is reused unchanged. If both exist, the CLI stops until RELAY_DATA_DIR selects one. It contains your private token, saved account, drafts and browser profile. Keep it outside Git.
init prints the token path, never its value. The CLI reads the private file internally. Set RELAY_DATA_DIR and RELAY_URL to select an existing installation; the earlier REA_L_ names still work, and 0.1.3 reads only those. Do not read or print its secrets.
For local tests, add --log to the service command. Startup prints the log directory and file. Private logs include API inputs/results and browser/network metadata. They can contain message and profile content. They do not record network headers, cookies or bodies. Keep logs private.
Plain HTTP. Plain JSON.
The default address is http://127.0.0.1:3447. Every protected request uses the private token that init created. The CLI reads it and adds it for you. A dashboard API key does not work here.
POST /v1/operations/connections.list
Authorization: Bearer <local-token>
Content-Type: application/json
{"query":"Alex"}
Same request, through the CLI:
relay connections --query Alex
Discover what this installation supports before making a request:
relay capabilities
relay schema
These call GET /v1/capabilities and GET /v1/openapi.json. Start with a native search query; query results have no cursor. For a full listing, follow a cursor only when the task needs another page. Release a retained window with relay release <cursor>.
Send a message
Save the final text and one confirmed profile in a JSON file:
{
"text": "Hi Alex — good to meet you.",
"target": {
"profileUrl": "https://www.linkedin.com/in/example-person/"
}
}
relay message send message.json
message.send sends right away to the named profile. The route is POST /v1/operations/message.send.
Every operation.
One page per LinkedIn operation, generated from the release schema. Each costs $0.01 per completed request.
- Get a LinkedIn profile
profile.get - Get a LinkedIn company
company.get - List people at a LinkedIn company
company.people - Search LinkedIn people
people.search - Search LinkedIn companies
companies.search - List your LinkedIn connections
connections.list - List LinkedIn invitations
invitations.list - List LinkedIn conversations
conversations.list - Read a LinkedIn conversation
conversation.get - Send a LinkedIn message
message.send - List LinkedIn posts by a member or company
posts.list - Get a LinkedIn post
post.get - List comments on a LinkedIn post
comments.list - List reactions on a LinkedIn post
reactions.list - Read your LinkedIn feed
feed.list - List LinkedIn notifications
notifications.list
Know what happened.
LinkedIn reads and message.send return the operation, verified account, data, source and completeness. Unavailable data fields are null. Collections can be partial.
{
"operation": "…",
"account": { "…": "verified account" },
"data": { "…": "operation result" },
"source": {
"url": "…",
"observedAt": "…",
"method": "…"
},
"completeness": {
"status": "partial",
"missingFields": ["…"],
"hasMore": null,
"nextCursor": null
}
}
LinkedIn result outline only. Local draft operations return operation, account and data, using the saved account binding. They omit source and completeness. See the schema for each exact result type.
A message receipt with status: "accepted" includes the verified recipient, exact text, conversation and message identifiers. It means LinkedIn accepted the message. It does not mean the recipient has read it.
SEND_OUTCOME_UNKNOWN means a send may have occurred. Read the supplied conversation and compare the known receipt before any repeat. A lost HTTP connection is also uncertain. Never retry a send blindly.
auth_required and challenge require human browser action. An account mismatch must be resolved before further work.
For the exact contracts supported by your installation, run relay schema. Use relay --help for CLI commands. Download the OpenAPI schema for release 0.3.0.
Use with MCP clients.
Relay is a CLI and local API. relay mcp is an optional adapter that serves its operations as MCP tools over stdio, for Claude Desktop, Claude Code, Cursor and Codex. It is available from release 0.3.0.
Start relay serve first. relay mcp reads the tools and input schemas from it, so they match your installation. Each tool call is one request to the local API, with the same token, credits and errors as the CLI. Calls are never retried. message_send sends a real LinkedIn message. If the client's tool timeout cancels it, the result is SEND_OUTCOME_UNKNOWN: check the conversation first. An exact retry after SEND_OUTCOME_UNKNOWN or OPERATION_RECOVERY_REQUIRED needs the CLI with RELAY_OPERATION_ID set to the returned operation_id.
Use the full path of the installed command. Replace /Users/you with your home directory. Add "env": {"RELAY_DATA_DIR": "…"} only if your installation uses a custom data directory or port (RELAY_URL).
Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json on macOS, %APPDATA%\Claude\claude_desktop_config.json on Windows) and Cursor (~/.cursor/mcp.json, or .cursor/mcp.json in one project):
{
"mcpServers": {
"relay": {
"command": "/Users/you/.local/share/relay-runtime/node_modules/.bin/relay",
"args": ["mcp"]
}
}
}
Claude Code (--scope user adds it for every project):
claude mcp add --scope user relay -- "$HOME/.local/share/relay-runtime/node_modules/.bin/relay" mcp
Codex (~/.codex/config.toml):
[mcp_servers.relay]
command = "/Users/you/.local/share/relay-runtime/node_modules/.bin/relay"
args = ["mcp"]
If the client cannot find Node.js, set command to the full path of node and put the installed relay path before mcp in args. Restart the MCP client after you upgrade Relay.
What it does.
Profile and company reads, people and network search, inbox search, selected conversations, posts, feed, comments, reactions, notifications, and text messages to one profile, as a reply or a new chat. Relay runs on your computer and binds one installation to one LinkedIn account.
The account dashboard provides API keys and a one-time $5 credit. Each completed LinkedIn request costs $0.01, including reads, searches, sends and cursor continuations; Relay reserves the price before work and settles it afterward. Browser subrequests and setup checks are free.
relay billing status shows your available and held credit in cents. When purchases are on, it also shows a billing_url to buy more. When less than $1.00 is available, it adds a low_credit hint.
Relay receives only account and billing metadata, never task inputs, results, browser state or local logs.