npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

linkedin-automation-cli

v2.0.2

Published

A CLI tool for LinkedIn automation using Playwright

Downloads

430

Readme

LinkedIn Automation CLI

A TypeScript CLI tool for LinkedIn automation using Playwright. Designed for sales representatives to manage LinkedIn messaging efficiently.

Features

  • Authentication: Secure login with 2FA/TOTP support (Microsoft Authenticator)
  • Message Management: List conversations, read threads, send replies
  • Templates: Template-based message drafting with variable substitution
  • Session Persistence: Encrypted session storage for seamless re-authentication
  • Rate Limiting: Built-in protection against LinkedIn rate limits
  • Audit Logging: Complete audit trail of all actions

Installation

# Clone the repository
git clone <repository-url>
cd linkedin-automation-cli

# Install dependencies
npm install

# Build the project
npm run build

# Link for global access (optional)
npm link

Quick Start

1. Login to LinkedIn

# Interactive login (will prompt for email, password, and 2FA if needed)
linkedin-cli auth login

# Or provide email inline
linkedin-cli auth login --email [email protected]

2. List Conversations

# List recent conversations
linkedin-cli messages list

# Show only unread
linkedin-cli messages list --unread

# Limit to 10 results
linkedin-cli messages list --limit 10

3. Read a Conversation

linkedin-cli messages show --thread 1234567890

4. Send a Reply

# Send a message inline
linkedin-cli reply send --thread 1234567890 --message "Thanks for your message!"

# Send from file
linkedin-cli reply send --thread 1234567890 --file message.txt

# Dry run (simulate without sending)
linkedin-cli reply send --thread 1234567890 --message "Test" --dry-run

5. Use Templates

# List available templates
linkedin-cli templates list

# Generate a message from template
linkedin-cli draft --thread 1234567890 --template welcome --var firstName=John --var company=Acme

# Preview without sending
linkedin-cli draft --thread 1234567890 --template welcome --var firstName=John --preview

PinchTab Backend

PinchTab is the default backend for profile, company, and messaging operations. It provides:

  • Token efficiency: Accessibility snapshots (~800 tokens vs 10,000+ DOM tokens)
  • Stability: Accessibility tree is more stable than CSS selectors
  • No AI required: Simple extractions parse accessibility tree directly
  • Session persistence: Browser profiles maintain login state

Installation

Install PinchTab server (choose one):

# npm
npm install -g pinchtab

# Homebrew
brew install pinchtab

# Docker
docker pull pinchtab/pinchtab

Usage

PinchTab is the default for profile, company, and messaging operations. Simply run:

linkedin-cli profile get https://linkedin.com/in/username
linkedin-cli company info https://linkedin.com/company/openai
linkedin-cli messages list
linkedin-cli reply send --thread 12345 --message "Hello!"
linkedin-cli connect send https://linkedin.com/in/username

Start the PinchTab server first:

pinchtab serve --port 9867

Fallback Options

If PinchTab doesn't work for a specific operation, use legacy backends:

# Use Playwright for profile extraction
linkedin-cli profile get https://linkedin.com/in/username --playwright

# Use AI for company extraction
linkedin-cli company info https://linkedin.com/company/openai --ai

# Use Playwright for messaging
linkedin-cli messages list --playwright
linkedin-cli reply send --thread 12345 --message "Hi" --playwright
linkedin-cli connect send https://linkedin.com/in/username --playwright

# Or set environment variables
export LINKEDIN_CLI_USE_PLAYWRIGHT=true  # For profile/messaging
export LINKEDIN_CLI_USE_AI=true          # For company

Configuration

Add to ~/.linkedin-cli/config.json:

{
  "pinchtab": {
    "url": "http://localhost:9867",
    "timeout": 30000,
    "profile": "default"
  }
}

| Option | Default | Description | |--------|---------|-------------| | url | http://localhost:9867 | PinchTab server URL | | timeout | 30000 | Request timeout (ms) | | profile | default | Browser profile name |

Environment Variables

| Variable | Purpose | |----------|---------| | LINKEDIN_CLI_USE_PLAYWRIGHT | Force Playwright backend for profiles and messaging | | LINKEDIN_CLI_USE_AI | Force AI backend for company extraction |

Messaging Commands

All messaging commands use PinchTab by default for token-efficient extraction.

List Conversations

linkedin-cli messages list
linkedin-cli messages list --unread
linkedin-cli messages list --limit 10

View Thread

linkedin-cli messages show --thread <thread-id>

Send Reply

linkedin-cli reply send --thread <thread-id> --message "Hello!"
linkedin-cli reply send --thread <thread-id> --file message.txt
linkedin-cli reply send --thread <thread-id> --message "Test" --dry-run

Send Connection

linkedin-cli connect send https://linkedin.com/in/username/
linkedin-cli connect send https://linkedin.com/in/username/ --note "Hi, I'd like to connect"

Configuration

Configuration is stored in ~/.linkedin-cli/config.json:

# View current config
linkedin-cli config --get

# Set values
linkedin-cli config --set headless=false
linkedin-cli config --set rateLimit=10000

Available Options

| Option | Default | Description | |--------|---------|-------------| | headless | true | Run browser in headless mode | | rateLimit | 5000 | Delay between actions (ms) | | sessionTimeout | 86400000 | Session validity (24 hours) | | dryRun | false | Default dry-run mode |

Templates

Templates use Handlebars-style variable substitution:

Hi {{firstName}},

Thanks for connecting! I noticed you're working at {{company}}.

Best regards,
{{senderName}}

Creating Custom Templates

  1. Create a file in ~/.linkedin-cli/templates/custom/:
mkdir -p ~/.linkedin-cli/templates/custom
cat > ~/.linkedin-cli/templates/custom/intro.txt << 'EOF'
---
name: Introduction
description: Brief introduction template
category: welcome
---

Hi {{firstName}},

I'm {{senderName}} from {{company}}. I came across your profile and was impressed by your experience in {{industry}}.

I'd love to connect and learn more about your work.

Best regards,
{{senderName}}
EOF
  1. Use the template:
linkedin-cli draft --thread 1234567890 --template intro --var firstName=John --var industry=Tech

Security

  • Encrypted Storage: Sessions and credentials are encrypted using AES-256-GCM
  • Machine-Bound: Encryption keys are derived from machine-specific data
  • No Credential Storage: Passwords are never stored; only session cookies
  • Audit Logging: All actions are logged to ~/.linkedin-cli/audit.log

Troubleshooting

Login Issues

# Check auth status
linkedin-cli auth status

# Re-login if needed
linkedin-cli auth logout
linkedin-cli auth login

Rate Limiting

If you encounter rate limiting:

# Increase rate limit delay
linkedin-cli config --set rateLimit=10000

# Use non-headless mode to see what's happening
linkedin-cli messages list --headless false

Selector Failures

If LinkedIn UI changes cause failures:

  1. Check the audit log: cat ~/.linkedin-cli/audit.log
  2. Run with non-headless mode to see the current state
  3. The multi-layer selector system will attempt fallbacks automatically

Development

Setup

# Install dependencies
npm install

# Build
npm run build

# Watch mode
npm run watch

# Run locally
node dist/index.js --help

Quality Checks

# Type check
npm run typecheck

# Lint
npm run lint
npm run lint:fix  # Auto-fix issues

# Format
npm run format:check
npm run format    # Auto-format code

# Run tests
npm run test           # Run tests
npm run test:watch     # Watch mode
npm run test:coverage  # With coverage report

Pre-commit Hooks

Husky runs automatically before each commit:

  • ESLint validation
  • Prettier format check

If the hook fails, fix the issues and re-commit.

Testing

Tests are written with Vitest and located alongside source files:

src/
├── core/
│   ├── storage.ts
│   └── storage.test.ts
├── templates/
│   ├── engine.ts
│   └── engine.test.ts

Coverage threshold: 80% minimum across all files.

Publishing

See NPM_PUBLISHING.md for detailed publishing instructions.

Quick Publish

# Run all checks
npm run test:coverage
npm run build

# Bump version (choose: patch, minor, major)
npm version patch

# Push (triggers auto-publish via GitHub Actions)
git push && git push --tags

Manual Publish

npm login              # One-time setup
npm publish --dry-run  # Preview
npm publish --access public

License

MIT

Contributing

Contributions welcome! Please ensure:

  • TypeScript compiles without errors
  • Follow existing code style
  • Add tests for new features
  • Update documentation

Disclaimer: This tool is for legitimate sales and business development purposes. Users are responsible for complying with LinkedIn's Terms of Service and applicable laws. Use responsibly and respect rate limits to avoid account restrictions.