Skip to main content

LinkedIn Message Drafter

CI

Write LinkedIn outreach that actually gets replies — personalized, warm, and ready in seconds. Feed it a name and a bit of context; it hands back a concise, human-sounding draft you can send as-is or tweak.

Draft-first and safe by design. It does not scrape LinkedIn, automate browser actions, or send anything on its own. You stay in control of every message — review, copy, send. Ready to automate? Wire in an approved LinkedIn integration through the adapter below.

No API key needed. The best way to use it is inside an AI assistant you already pay for — Claude Code, Claude Desktop, Codex, Cursor, or ChatGPT — which does the writing on your existing subscription. See Use it in your AI assistant. The standalone CLI works too: free offline via a built-in template, or with your own Anthropic API key for richer copy.

Install

pipx install linkedin-message-drafter          # or: pip install linkedin-message-drafter
# for the Claude draft path: pipx install "linkedin-message-drafter[ai]"

PyPI

Quick start

linkedin-draft prospect.json      # prints a draft and saves it to drafts/

From source (development)

git clone https://github.com/wuisabel-gif/linkedin-message-drafter.git
cd linkedin-message-drafter
python3 -m venv .venv && source .venv/bin/activate
pip install -e .                  # add [ai] for the Claude draft path: pip install -e ".[ai]"
linkedin-draft src/linkedin_message_drafter/examples/prospect.json

Web UI

Prefer a form to the CLI? A zero-dependency local UI ships with it:

linkedin-draft-web            # then open http://127.0.0.1:8000

Binds to localhost only, uses the same drafting engine (voice matching, slop check, short mode), and still just drafts — nothing is sent.

Input

See src/linkedin_message_drafter/examples/prospect.json. Required fields are name, context, and goal; company, role, and relationship are optional. CSV input uses the same column names, one prospect per row.

Options

# Batch — pass multiple files, a CSV, or a whole folder
linkedin-draft ./prospects/
linkedin-draft prospects.csv

# Connection-request note, guaranteed under LinkedIn's 300-char limit
linkedin-draft --short my-prospect.json

# Best-of-N — generate 3 AI drafts, keep the one cadence-deslop scores cleanest
linkedin-draft --best-of 3 my-prospect.json

# Write in a Cadence voice preset (AI path; needs CADENCE_VOICES)
export CADENCE_VOICES=/path/to/Cadence/voices
linkedin-draft --style punchy my-prospect.json

--short works with both the template and AI paths; --style applies to AI drafts only. Available presets are the .md files in Cadence's voices/ (punchy, column, plain, dispatch, …).

AI drafting via the API (advanced / power users)

Prefer the assistant path above — it needs no key. But if you want the standalone CLI to generate AI copy (for scripting or batch runs), set ANTHROPIC_API_KEY to draft with Claude. This uses the pay-as-you-go Anthropic API (a subscription does not cover it). With no key set, the CLI uses the dependency-free template and works fully offline.

export ANTHROPIC_API_KEY=sk-ant-...
linkedin-draft my-prospect.json

Sounds like you (Cadence)

Point VOICE_SAMPLE at your own past writing and the AI draft mimics the way you speak — tone, rhythm, and word choice. It takes a single file or a directory: drop in a folder of all your previous posts and messages and Cadence learns from the whole corpus.

export VOICE_SAMPLE=~/my-writing-sample.txt   # one sample
export VOICE_SAMPLE=~/my-linkedin-posts/       # or a folder of everything you've written

Automatic slop check. If the cadence-deslop detector is installed, every AI draft is scored 0–100 for AI-slop tells (uniform rhythm, hollow-confidence words, clichéd openers). If a draft reads as slop, Claude rewrites it once with the named tells fed back, and the cleaner version is kept. It's a no-op when the detector isn't installed.

npm install -g cadence-deslop                 # or: export CADENCE_DESLOP=/path/to/deslop.mjs

For a deeper voice pass, run the /cadence skill on any saved draft in drafts/.

Use it in your AI assistant — no API key

This is the recommended way. Your own assistant does the writing, powered by the Claude / Codex / ChatGPT subscription you already pay for — no API key, no hosting, no per-message cost. The assistant learns your voice, drafts in it, and cleans the AI-slop with Cadence.

Skill (Claude Code, Codex, Cursor — anything that reads skills):

Drop skills/linkedin-drafter/SKILL.md into your assistant's skills directory. Then just ask it to draft a LinkedIn message — it follows the learn → draft → deslop flow, running npx cadence-deslop --fix itself to clean the result.

MCP server (Claude Desktop, ChatGPT — apps that can't run a terminal):

These can't run npx, so they reach Cadence through an MCP tool instead. Install the extra and register linkedin-draft-mcp in your MCP client:

pip install "linkedin-message-drafter[mcp]"

It exposes one tool — deslop — which cleans a draft with Cadence and returns the tells still needing a voice rewrite. The assistant writes the draft; the tool cleans it. Needs Node + cadence-deslop on the machine running the server.

Both paths stay draft-only — nothing is scraped or sent.

Adding an approved API integration

src/linkedin_message_drafter/linkedin.py contains a deliberately unimplemented LinkedInClient. Implement only the endpoints and scopes that LinkedIn has approved for your application. Keep the default workflow draft-only and require a user confirmation before any send operation. Do not add scraping, credential collection, or bulk/unattended sending.

Read TUTORIAL.md before configuring credentials or requesting permissions.

Tests

python -m unittest discover -s tests -v

Publishing

Releases publish to PyPI automatically via Trusted Publishing — no API token is stored anywhere. One-time setup:

  1. On pypi.org, add a pending publisher: project linkedin-message-drafter, owner wuisabel-gif, repo linkedin-message-drafter, workflow publish.yml, environment pypi.

  2. Cut a release: bump version in pyproject.toml, then

    git tag v0.1.0 && git push origin v0.1.0
    gh release create v0.1.0 --generate-notes
    

The Publish to PyPI workflow builds the sdist + wheel and uploads them. Local dry run:

python -m build && twine check dist/*

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

linkedin_message_drafter-0.1.3.tar.gz (18.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

linkedin_message_drafter-0.1.3-py3-none-any.whl (17.6 kB view details)

Uploaded Python 3

File details

Details for the file linkedin_message_drafter-0.1.3.tar.gz.

File metadata

  • Download URL: linkedin_message_drafter-0.1.3.tar.gz
  • Upload date:
  • Size: 18.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for linkedin_message_drafter-0.1.3.tar.gz
Algorithm Hash digest
SHA256 8e50f1ed6bba366764fb73e1d87a3564a6f9821a35c897dd7962c6f7a977c720
MD5 92fb679ebfcae5033ade1199aef8bf90
BLAKE2b-256 8af792cd20d6655abcfb33cd01d1f4dc366599cb37b6028baed8c2707d5a4bbd

See more details on using hashes here.

Provenance

The following attestation bundles were made for linkedin_message_drafter-0.1.3.tar.gz:

Publisher: publish.yml on wuisabel-gif/linkedin-message-drafter

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file linkedin_message_drafter-0.1.3-py3-none-any.whl.

File metadata

File hashes

Hashes for linkedin_message_drafter-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 f8dd30d6571c45678a84f41a6c0ae64efaae8a6289e57b46060e5e3ffd5d6927
MD5 f0d0a115e0adc8383adfd64a457c3d41
BLAKE2b-256 e040082cfa3637a50f3862f26c402a726d98903ad96414e90f4146d3a928d5ea

See more details on using hashes here.

Provenance

The following attestation bundles were made for linkedin_message_drafter-0.1.3-py3-none-any.whl:

Publisher: publish.yml on wuisabel-gif/linkedin-message-drafter

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page