linkedin-automation-cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +12 -0
- package/.github/workflows/ci.yml +66 -0
- package/.github/workflows/publish.yml +48 -0
- package/.husky/pre-commit +6 -0
- package/.prettierignore +4 -0
- package/.prettierrc +10 -0
- package/AGENTS.md +294 -0
- package/CHANGELOG.md +40 -0
- package/GIT_RELEASE.md +167 -0
- package/LICENSE +21 -0
- package/Makefile +30 -0
- package/NPM_PUBLISHING.md +230 -0
- package/PYEOF +0 -0
- package/README.md +295 -0
- package/TESTING-GUIDE.md +151 -0
- package/cmd/linkedin/main.go +9 -0
- package/dist/agent/action-executor.d.ts +81 -0
- package/dist/agent/action-executor.d.ts.map +1 -0
- package/dist/agent/action-executor.js +170 -0
- package/dist/agent/action-executor.js.map +1 -0
- package/dist/agent/action-executor.test.d.ts +2 -0
- package/dist/agent/action-executor.test.d.ts.map +1 -0
- package/dist/agent/action-executor.test.js +366 -0
- package/dist/agent/action-executor.test.js.map +1 -0
- package/dist/agent/claude-client.d.ts +74 -0
- package/dist/agent/claude-client.d.ts.map +1 -0
- package/dist/agent/claude-client.js +314 -0
- package/dist/agent/claude-client.js.map +1 -0
- package/dist/agent/claude-client.test.d.ts +2 -0
- package/dist/agent/claude-client.test.d.ts.map +1 -0
- package/dist/agent/claude-client.test.js +590 -0
- package/dist/agent/claude-client.test.js.map +1 -0
- package/dist/agent/dom-extractor.d.ts +50 -0
- package/dist/agent/dom-extractor.d.ts.map +1 -0
- package/dist/agent/dom-extractor.js +374 -0
- package/dist/agent/dom-extractor.js.map +1 -0
- package/dist/agent/dom-extractor.test.d.ts +7 -0
- package/dist/agent/dom-extractor.test.d.ts.map +1 -0
- package/dist/agent/dom-extractor.test.js +504 -0
- package/dist/agent/dom-extractor.test.js.map +1 -0
- package/dist/agent/extension-client.d.ts +75 -0
- package/dist/agent/extension-client.d.ts.map +1 -0
- package/dist/agent/extension-client.js +245 -0
- package/dist/agent/extension-client.js.map +1 -0
- package/dist/agent/index.d.ts +8 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +16 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/page-agent.d.ts +76 -0
- package/dist/agent/page-agent.d.ts.map +1 -0
- package/dist/agent/page-agent.js +236 -0
- package/dist/agent/page-agent.js.map +1 -0
- package/dist/agent/types.d.ts +236 -0
- package/dist/agent/types.d.ts.map +1 -0
- package/dist/agent/types.js +37 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/cli/agent-commands.d.ts +3 -0
- package/dist/cli/agent-commands.d.ts.map +1 -0
- package/dist/cli/agent-commands.js +250 -0
- package/dist/cli/agent-commands.js.map +1 -0
- package/dist/cli/auth.d.ts +3 -0
- package/dist/cli/auth.d.ts.map +1 -0
- package/dist/cli/auth.js +288 -0
- package/dist/cli/auth.js.map +1 -0
- package/dist/cli/company.d.ts +3 -0
- package/dist/cli/company.d.ts.map +1 -0
- package/dist/cli/company.js +55 -0
- package/dist/cli/company.js.map +1 -0
- package/dist/cli/connection.d.ts +3 -0
- package/dist/cli/connection.d.ts.map +1 -0
- package/dist/cli/connection.js +79 -0
- package/dist/cli/connection.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +17 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/messages.d.ts +3 -0
- package/dist/cli/messages.d.ts.map +1 -0
- package/dist/cli/messages.js +268 -0
- package/dist/cli/messages.js.map +1 -0
- package/dist/cli/profile.d.ts +3 -0
- package/dist/cli/profile.d.ts.map +1 -0
- package/dist/cli/profile.js +81 -0
- package/dist/cli/profile.js.map +1 -0
- package/dist/cli/profile.test.d.ts +2 -0
- package/dist/cli/profile.test.d.ts.map +1 -0
- package/dist/cli/profile.test.js +15 -0
- package/dist/cli/profile.test.js.map +1 -0
- package/dist/cli/reply.d.ts +3 -0
- package/dist/cli/reply.d.ts.map +1 -0
- package/dist/cli/reply.js +129 -0
- package/dist/cli/reply.js.map +1 -0
- package/dist/core/audit.d.ts +17 -0
- package/dist/core/audit.d.ts.map +1 -0
- package/dist/core/audit.js +121 -0
- package/dist/core/audit.js.map +1 -0
- package/dist/core/audit.test.d.ts +2 -0
- package/dist/core/audit.test.d.ts.map +1 -0
- package/dist/core/audit.test.js +142 -0
- package/dist/core/audit.test.js.map +1 -0
- package/dist/core/browser-cookies.d.ts +19 -0
- package/dist/core/browser-cookies.d.ts.map +1 -0
- package/dist/core/browser-cookies.js +181 -0
- package/dist/core/browser-cookies.js.map +1 -0
- package/dist/core/browser.d.ts +50 -0
- package/dist/core/browser.d.ts.map +1 -0
- package/dist/core/browser.js +318 -0
- package/dist/core/browser.js.map +1 -0
- package/dist/core/config.d.ts +20 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +103 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/config.test.d.ts +2 -0
- package/dist/core/config.test.d.ts.map +1 -0
- package/dist/core/config.test.js +111 -0
- package/dist/core/config.test.js.map +1 -0
- package/dist/core/storage.d.ts +19 -0
- package/dist/core/storage.d.ts.map +1 -0
- package/dist/core/storage.js +124 -0
- package/dist/core/storage.js.map +1 -0
- package/dist/core/storage.test.d.ts +2 -0
- package/dist/core/storage.test.d.ts.map +1 -0
- package/dist/core/storage.test.js +142 -0
- package/dist/core/storage.test.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +63 -0
- package/dist/index.js.map +1 -0
- package/dist/linkedin/auth.d.ts +22 -0
- package/dist/linkedin/auth.d.ts.map +1 -0
- package/dist/linkedin/auth.js +167 -0
- package/dist/linkedin/auth.js.map +1 -0
- package/dist/linkedin/company-extractor.d.ts +36 -0
- package/dist/linkedin/company-extractor.d.ts.map +1 -0
- package/dist/linkedin/company-extractor.js +211 -0
- package/dist/linkedin/company-extractor.js.map +1 -0
- package/dist/linkedin/company-extractor.test.d.ts +2 -0
- package/dist/linkedin/company-extractor.test.d.ts.map +1 -0
- package/dist/linkedin/company-extractor.test.js +52 -0
- package/dist/linkedin/company-extractor.test.js.map +1 -0
- package/dist/linkedin/connector.d.ts +45 -0
- package/dist/linkedin/connector.d.ts.map +1 -0
- package/dist/linkedin/connector.js +245 -0
- package/dist/linkedin/connector.js.map +1 -0
- package/dist/linkedin/message-sender.d.ts +32 -0
- package/dist/linkedin/message-sender.d.ts.map +1 -0
- package/dist/linkedin/message-sender.js +112 -0
- package/dist/linkedin/message-sender.js.map +1 -0
- package/dist/linkedin/messages.d.ts +78 -0
- package/dist/linkedin/messages.d.ts.map +1 -0
- package/dist/linkedin/messages.js +745 -0
- package/dist/linkedin/messages.js.map +1 -0
- package/dist/linkedin/profile.d.ts +37 -0
- package/dist/linkedin/profile.d.ts.map +1 -0
- package/dist/linkedin/profile.js +268 -0
- package/dist/linkedin/profile.js.map +1 -0
- package/dist/linkedin/profile.test.d.ts +2 -0
- package/dist/linkedin/profile.test.d.ts.map +1 -0
- package/dist/linkedin/profile.test.js +68 -0
- package/dist/linkedin/profile.test.js.map +1 -0
- package/dist/linkedin/reply.d.ts +21 -0
- package/dist/linkedin/reply.d.ts.map +1 -0
- package/dist/linkedin/reply.js +76 -0
- package/dist/linkedin/reply.js.map +1 -0
- package/dist/linkedin/selector-engine.d.ts +69 -0
- package/dist/linkedin/selector-engine.d.ts.map +1 -0
- package/dist/linkedin/selector-engine.js +339 -0
- package/dist/linkedin/selector-engine.js.map +1 -0
- package/dist/linkedin/selector-engine.test.d.ts +2 -0
- package/dist/linkedin/selector-engine.test.d.ts.map +1 -0
- package/dist/linkedin/selector-engine.test.js +135 -0
- package/dist/linkedin/selector-engine.test.js.map +1 -0
- package/dist/linkedin/selectors.d.ts +65 -0
- package/dist/linkedin/selectors.d.ts.map +1 -0
- package/dist/linkedin/selectors.js +261 -0
- package/dist/linkedin/selectors.js.map +1 -0
- package/dist/templates/engine.d.ts +37 -0
- package/dist/templates/engine.d.ts.map +1 -0
- package/dist/templates/engine.js +215 -0
- package/dist/templates/engine.js.map +1 -0
- package/dist/templates/engine.test.d.ts +2 -0
- package/dist/templates/engine.test.d.ts.map +1 -0
- package/dist/templates/engine.test.js +212 -0
- package/dist/templates/engine.test.js.map +1 -0
- package/dist/templates/index.d.ts +2 -0
- package/dist/templates/index.d.ts.map +1 -0
- package/dist/templates/index.js +7 -0
- package/dist/templates/index.js.map +1 -0
- package/dist/types/index.d.ts +113 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/index.test.d.ts +2 -0
- package/dist/types/index.test.d.ts.map +1 -0
- package/dist/types/index.test.js +90 -0
- package/dist/types/index.test.js.map +1 -0
- package/dist/utils/paths.d.ts +8 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +68 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/rate-limiter.d.ts +22 -0
- package/dist/utils/rate-limiter.d.ts.map +1 -0
- package/dist/utils/rate-limiter.js +57 -0
- package/dist/utils/rate-limiter.js.map +1 -0
- package/dist/utils/retry.d.ts +18 -0
- package/dist/utils/retry.d.ts.map +1 -0
- package/dist/utils/retry.js +49 -0
- package/dist/utils/retry.js.map +1 -0
- package/docs/connection-command.md +52 -0
- package/docs/plans/2025-03-03-linkedin-cli-design.md +280 -0
- package/docs/plans/2025-03-03-linkedin-cli-implementation-plan.md +2087 -0
- package/docs/plans/2025-03-03-linkedin-cli-implementation.md +2420 -0
- package/docs/plans/2026-02-19-linkedin-connection-feature.md +596 -0
- package/docs/plans/2026-02-28-messages-send-feature.md +480 -0
- package/docs/plans/2026-02-28-messages-show-design.md +243 -0
- package/docs/plans/2026-03-03-linkedin-cli-oss-publishing-design.md +394 -0
- package/docs/plans/2026-03-03-linkedin-cli-oss-publishing-plan.md +1592 -0
- package/docs/superpowers/plans/2026-03-13-linkedin-automation-resilience-migration.md +425 -0
- package/docs/superpowers/plans/2026-03-13-playwright-fara-migration.md +1112 -0
- package/docs/superpowers/plans/2026-03-14-page-agent-plan.md +1598 -0
- package/docs/superpowers/plans/2026-03-15-company-profile-extraction.md +591 -0
- package/docs/superpowers/plans/2026-03-15-profile-extraction-plan.md +943 -0
- package/docs/superpowers/specs/2026-03-14-company-profile-extraction-design.md +371 -0
- package/docs/superpowers/specs/2026-03-14-page-agent-design.md +385 -0
- package/docs/superpowers/specs/2026-03-15-profile-extraction-design.md +409 -0
- package/eslint.config.mjs +58 -0
- package/go.mod +9 -0
- package/go.sum +10 -0
- package/import-cookies.js +376 -0
- package/internal/cmd/actions.go +123 -0
- package/internal/cmd/auth.go +108 -0
- package/internal/cmd/connect.go +42 -0
- package/internal/cmd/message.go +44 -0
- package/internal/cmd/people.go +454 -0
- package/internal/cmd/profiles.go +121 -0
- package/internal/cmd/root.go +89 -0
- package/internal/cmd/sequence.go +192 -0
- package/internal/config/config.go +187 -0
- package/internal/config/config_test.go +121 -0
- package/internal/config/profile.go +65 -0
- package/internal/linkedin/navigator.go +195 -0
- package/internal/linkedin/selectors.go +39 -0
- package/internal/linkedin/validator.go +69 -0
- package/internal/pinchtab/client.go +183 -0
- package/internal/pinchtab/client_test.go +67 -0
- package/internal/pinchtab/types.go +50 -0
- package/internal/ratelimit/limiter.go +115 -0
- package/internal/ratelimit/limits.go +32 -0
- package/package.json +67 -0
- package/release.sh +66 -0
- package/scripts/debug-linkedin.js +156 -0
- package/scripts/debug-login.js +193 -0
- package/scripts/extract-from-edge.js +96 -0
- package/scripts/import-cookies.js +101 -0
- package/scripts/poc-show-data.js +205 -0
- package/scripts/proof-of-access.js +87 -0
- package/scripts/prove-connection.js +110 -0
- package/scripts/show-linkedin-data.js +173 -0
- package/src/agent/action-executor.test.ts +464 -0
- package/src/agent/action-executor.ts +203 -0
- package/src/agent/claude-client.test.ts +707 -0
- package/src/agent/claude-client.ts +422 -0
- package/src/agent/dom-extractor.test.ts +574 -0
- package/src/agent/dom-extractor.ts +437 -0
- package/src/agent/extension-client.ts +306 -0
- package/src/agent/index.ts +28 -0
- package/src/agent/page-agent.ts +292 -0
- package/src/agent/types.ts +288 -0
- package/src/cli/agent-commands.ts +274 -0
- package/src/cli/auth.ts +343 -0
- package/src/cli/company.ts +66 -0
- package/src/cli/connection.ts +89 -0
- package/src/cli/index.ts +7 -0
- package/src/cli/messages.ts +338 -0
- package/src/cli/profile.test.ts +14 -0
- package/src/cli/profile.ts +95 -0
- package/src/cli/reply.ts +110 -0
- package/src/core/audit.test.ts +134 -0
- package/src/core/audit.ts +98 -0
- package/src/core/browser-cookies.ts +203 -0
- package/src/core/browser.ts +304 -0
- package/src/core/config.test.ts +90 -0
- package/src/core/config.ts +81 -0
- package/src/core/storage.test.ts +129 -0
- package/src/core/storage.ts +100 -0
- package/src/index.ts +70 -0
- package/src/linkedin/auth.ts +218 -0
- package/src/linkedin/company-extractor.test.ts +58 -0
- package/src/linkedin/company-extractor.ts +222 -0
- package/src/linkedin/connector.ts +336 -0
- package/src/linkedin/message-sender.ts +141 -0
- package/src/linkedin/messages.ts +894 -0
- package/src/linkedin/profile.test.ts +79 -0
- package/src/linkedin/profile.ts +314 -0
- package/src/linkedin/reply.ts +96 -0
- package/src/linkedin/selector-engine.test.ts +167 -0
- package/src/linkedin/selector-engine.ts +393 -0
- package/src/linkedin/selectors.ts +268 -0
- package/src/templates/defaults/followup.txt +14 -0
- package/src/templates/defaults/meeting.txt +16 -0
- package/src/templates/defaults/welcome.txt +14 -0
- package/src/templates/engine.test.ts +228 -0
- package/src/templates/engine.ts +208 -0
- package/src/templates/index.ts +1 -0
- package/src/types/index.test.ts +94 -0
- package/src/types/index.ts +143 -0
- package/src/types/sql.js.d.ts +23 -0
- package/src/utils/paths.ts +33 -0
- package/src/utils/rate-limiter.ts +75 -0
- package/src/utils/retry.ts +78 -0
- package/test-cli.sh +85 -0
- package/test-real-data.sh +97 -0
- package/tsconfig.json +23 -0
- package/vitest.config.ts +35 -0
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
# npm Publishing Guide
|
|
2
|
+
|
|
3
|
+
This guide walks you through publishing the LinkedIn Automation CLI to npm.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
1. **npm account**: You mentioned you have one - great!
|
|
8
|
+
2. **Logged in to npm**: Run `npm login` if you haven't already
|
|
9
|
+
|
|
10
|
+
## Initial Setup (One-Time)
|
|
11
|
+
|
|
12
|
+
### 1. Login to npm
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm login
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
You'll be prompted for:
|
|
19
|
+
- Username
|
|
20
|
+
- Password
|
|
21
|
+
- Email
|
|
22
|
+
- OTP (if you have 2FA enabled)
|
|
23
|
+
|
|
24
|
+
### 2. Verify Login
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm whoami
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Should return your npm username.
|
|
31
|
+
|
|
32
|
+
## Publishing a New Version
|
|
33
|
+
|
|
34
|
+
### Step 1: Run Full Test Suite
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# Run all quality checks
|
|
38
|
+
npm run typecheck # TypeScript compilation check
|
|
39
|
+
npm run lint # ESLint
|
|
40
|
+
npm run format:check # Prettier format check
|
|
41
|
+
npm run test:coverage # Tests with coverage (requires 80%+)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**All must pass** before publishing.
|
|
45
|
+
|
|
46
|
+
### Step 2: Build the Project
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm run build
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Verify the output:
|
|
53
|
+
```bash
|
|
54
|
+
ls -la dist/
|
|
55
|
+
node dist/index.js --help
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Step 3: Bump Version
|
|
59
|
+
|
|
60
|
+
npm uses [Semantic Versioning](https://semver.org/):
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# Choose one based on your changes:
|
|
64
|
+
npm version patch # Bug fix: 0.1.0 → 0.1.1
|
|
65
|
+
npm version minor # New feature: 0.1.0 → 0.2.0
|
|
66
|
+
npm version major # Breaking change: 0.1.0 → 1.0.0
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
This will:
|
|
70
|
+
- Update version in package.json
|
|
71
|
+
- Create a git commit
|
|
72
|
+
- Create a git tag (e.g., v0.1.0)
|
|
73
|
+
|
|
74
|
+
### Step 4: Push to GitHub
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
git push origin main
|
|
78
|
+
git push origin v0.1.0 # Replace with your version tag
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Pushing the tag triggers the GitHub Actions publish workflow automatically!
|
|
82
|
+
|
|
83
|
+
### Step 5: Manual Publish (Alternative)
|
|
84
|
+
|
|
85
|
+
If you want to publish manually instead of using GitHub Actions:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# Dry run first (see what will be published)
|
|
89
|
+
npm publish --dry-run
|
|
90
|
+
|
|
91
|
+
# Actual publish
|
|
92
|
+
npm publish --access public
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Step 6: Verify Publication
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# Check on npm registry
|
|
99
|
+
npm view linkedin-automation-cli
|
|
100
|
+
|
|
101
|
+
# Or visit in browser
|
|
102
|
+
# https://www.npmjs.com/package/linkedin-automation-cli
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Installation Test
|
|
106
|
+
|
|
107
|
+
After publishing, test installation:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# In a fresh directory
|
|
111
|
+
npm install -g linkedin-automation-cli
|
|
112
|
+
linkedin-automation --help
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## CI/CD Automatic Publishing
|
|
116
|
+
|
|
117
|
+
The project includes a GitHub Actions workflow (`.github/workflows/publish.yml`) that automatically publishes when you push a version tag.
|
|
118
|
+
|
|
119
|
+
### Required GitHub Secret
|
|
120
|
+
|
|
121
|
+
You need to add your npm token to GitHub:
|
|
122
|
+
|
|
123
|
+
1. Get your npm token:
|
|
124
|
+
```bash
|
|
125
|
+
npm token create --read-only
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
2. In GitHub, go to your repo → Settings → Secrets and variables → Actions
|
|
129
|
+
|
|
130
|
+
3. Add a new secret:
|
|
131
|
+
- Name: `NPM_TOKEN`
|
|
132
|
+
- Value: Your npm token from step 1
|
|
133
|
+
|
|
134
|
+
### Automatic Release Flow
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
# Just bump version and push tag
|
|
138
|
+
npm version minor
|
|
139
|
+
git push && git push --tags
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
GitHub Actions will:
|
|
143
|
+
1. Run full CI (typecheck, lint, test, coverage)
|
|
144
|
+
2. Build the project
|
|
145
|
+
3. Publish to npm
|
|
146
|
+
4. Create a GitHub Release
|
|
147
|
+
|
|
148
|
+
## Troubleshooting
|
|
149
|
+
|
|
150
|
+
### "EPUBLISHCONFLICT: Cannot publish"
|
|
151
|
+
|
|
152
|
+
You're trying to publish a version that already exists. Bump the version:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
npm version patch
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### "E404: Not found"
|
|
159
|
+
|
|
160
|
+
Package name might be taken. Check:
|
|
161
|
+
```bash
|
|
162
|
+
npm view linkedin-automation-cli
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### 2FA Issues
|
|
166
|
+
|
|
167
|
+
If npm requires 2FA for publishing:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
# Publish with OTP
|
|
171
|
+
npm publish --otp=123456
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Or configure npm to require 2FA only for login:
|
|
175
|
+
```bash
|
|
176
|
+
npm profile set-lifecycle-script 2fa
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Coverage Below 80%
|
|
180
|
+
|
|
181
|
+
If tests don't meet the 80% threshold:
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
# See detailed coverage report
|
|
185
|
+
npm run test:coverage
|
|
186
|
+
|
|
187
|
+
# Open HTML report
|
|
188
|
+
open coverage/index.html
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Add more tests for uncovered code.
|
|
192
|
+
|
|
193
|
+
## Version Naming Examples
|
|
194
|
+
|
|
195
|
+
| Scenario | Command | Result |
|
|
196
|
+
|----------|---------|--------|
|
|
197
|
+
| Bug fix | `npm version patch` | 0.1.0 → 0.1.1 |
|
|
198
|
+
| New feature | `npm version minor` | 0.1.0 → 0.2.0 |
|
|
199
|
+
| Breaking change | `npm version major` | 0.1.0 → 1.0.0 |
|
|
200
|
+
| Pre-release | `npm version prerelease` | 0.1.0 → 0.1.1-0 |
|
|
201
|
+
|
|
202
|
+
## Best Practices
|
|
203
|
+
|
|
204
|
+
1. **Never skip tests** - Always run full CI before publishing
|
|
205
|
+
2. **Use semantic versioning** - Communicates breaking changes to users
|
|
206
|
+
3. **Write changelog** - Document what changed in each version
|
|
207
|
+
4. **Test installation** - Verify published package works
|
|
208
|
+
5. **Tag releases** - GitHub releases help track versions
|
|
209
|
+
|
|
210
|
+
## Unpublishing (Emergency Only)
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
# Only within 72 hours of publishing
|
|
214
|
+
npm unpublish linkedin-automation-cli@0.1.0
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
npm has strict unpublish policies. Use only for mistakes or security issues.
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
**Quick Reference:**
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
# Full publish workflow
|
|
225
|
+
npm run test:coverage && \
|
|
226
|
+
npm run build && \
|
|
227
|
+
npm version minor && \
|
|
228
|
+
git push && git push --tags
|
|
229
|
+
# GitHub Actions handles the rest!
|
|
230
|
+
```
|
package/PYEOF
ADDED
|
File without changes
|
package/README.md
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
# LinkedIn Automation CLI
|
|
2
|
+
|
|
3
|
+
A TypeScript CLI tool for LinkedIn automation using Playwright. Designed for sales representatives to manage LinkedIn messaging efficiently.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Authentication**: Secure login with 2FA/TOTP support (Microsoft Authenticator)
|
|
8
|
+
- **Message Management**: List conversations, read threads, send replies
|
|
9
|
+
- **Templates**: Template-based message drafting with variable substitution
|
|
10
|
+
- **Session Persistence**: Encrypted session storage for seamless re-authentication
|
|
11
|
+
- **Rate Limiting**: Built-in protection against LinkedIn rate limits
|
|
12
|
+
- **Audit Logging**: Complete audit trail of all actions
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# Clone the repository
|
|
18
|
+
git clone <repository-url>
|
|
19
|
+
cd linkedin-automation-cli
|
|
20
|
+
|
|
21
|
+
# Install dependencies
|
|
22
|
+
npm install
|
|
23
|
+
|
|
24
|
+
# Build the project
|
|
25
|
+
npm run build
|
|
26
|
+
|
|
27
|
+
# Link for global access (optional)
|
|
28
|
+
npm link
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
### 1. Login to LinkedIn
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Interactive login (will prompt for email, password, and 2FA if needed)
|
|
37
|
+
linkedin-cli auth login
|
|
38
|
+
|
|
39
|
+
# Or provide email inline
|
|
40
|
+
linkedin-cli auth login --email your@email.com
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### 2. List Conversations
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# List recent conversations
|
|
47
|
+
linkedin-cli messages list
|
|
48
|
+
|
|
49
|
+
# Show only unread
|
|
50
|
+
linkedin-cli messages list --unread
|
|
51
|
+
|
|
52
|
+
# Limit to 10 results
|
|
53
|
+
linkedin-cli messages list --limit 10
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 3. Read a Conversation
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
linkedin-cli messages show --thread 1234567890
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 4. Send a Reply
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
# Send a message inline
|
|
66
|
+
linkedin-cli reply send --thread 1234567890 --message "Thanks for your message!"
|
|
67
|
+
|
|
68
|
+
# Send from file
|
|
69
|
+
linkedin-cli reply send --thread 1234567890 --file message.txt
|
|
70
|
+
|
|
71
|
+
# Dry run (simulate without sending)
|
|
72
|
+
linkedin-cli reply send --thread 1234567890 --message "Test" --dry-run
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 5. Use Templates
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# List available templates
|
|
79
|
+
linkedin-cli templates list
|
|
80
|
+
|
|
81
|
+
# Generate a message from template
|
|
82
|
+
linkedin-cli draft --thread 1234567890 --template welcome --var firstName=John --var company=Acme
|
|
83
|
+
|
|
84
|
+
# Preview without sending
|
|
85
|
+
linkedin-cli draft --thread 1234567890 --template welcome --var firstName=John --preview
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Configuration
|
|
89
|
+
|
|
90
|
+
Configuration is stored in `~/.linkedin-cli/config.json`:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# View current config
|
|
94
|
+
linkedin-cli config --get
|
|
95
|
+
|
|
96
|
+
# Set values
|
|
97
|
+
linkedin-cli config --set headless=false
|
|
98
|
+
linkedin-cli config --set rateLimit=10000
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Available Options
|
|
102
|
+
|
|
103
|
+
| Option | Default | Description |
|
|
104
|
+
|--------|---------|-------------|
|
|
105
|
+
| `headless` | `true` | Run browser in headless mode |
|
|
106
|
+
| `rateLimit` | `5000` | Delay between actions (ms) |
|
|
107
|
+
| `sessionTimeout` | `86400000` | Session validity (24 hours) |
|
|
108
|
+
| `dryRun` | `false` | Default dry-run mode |
|
|
109
|
+
|
|
110
|
+
## Templates
|
|
111
|
+
|
|
112
|
+
Templates use Handlebars-style variable substitution:
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
Hi {{firstName}},
|
|
116
|
+
|
|
117
|
+
Thanks for connecting! I noticed you're working at {{company}}.
|
|
118
|
+
|
|
119
|
+
Best regards,
|
|
120
|
+
{{senderName}}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Creating Custom Templates
|
|
124
|
+
|
|
125
|
+
1. Create a file in `~/.linkedin-cli/templates/custom/`:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
mkdir -p ~/.linkedin-cli/templates/custom
|
|
129
|
+
cat > ~/.linkedin-cli/templates/custom/intro.txt << 'EOF'
|
|
130
|
+
---
|
|
131
|
+
name: Introduction
|
|
132
|
+
description: Brief introduction template
|
|
133
|
+
category: welcome
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
Hi {{firstName}},
|
|
137
|
+
|
|
138
|
+
I'm {{senderName}} from {{company}}. I came across your profile and was impressed by your experience in {{industry}}.
|
|
139
|
+
|
|
140
|
+
I'd love to connect and learn more about your work.
|
|
141
|
+
|
|
142
|
+
Best regards,
|
|
143
|
+
{{senderName}}
|
|
144
|
+
EOF
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
2. Use the template:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
linkedin-cli draft --thread 1234567890 --template intro --var firstName=John --var industry=Tech
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Security
|
|
154
|
+
|
|
155
|
+
- **Encrypted Storage**: Sessions and credentials are encrypted using AES-256-GCM
|
|
156
|
+
- **Machine-Bound**: Encryption keys are derived from machine-specific data
|
|
157
|
+
- **No Credential Storage**: Passwords are never stored; only session cookies
|
|
158
|
+
- **Audit Logging**: All actions are logged to `~/.linkedin-cli/audit.log`
|
|
159
|
+
|
|
160
|
+
## Troubleshooting
|
|
161
|
+
|
|
162
|
+
### Login Issues
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
# Check auth status
|
|
166
|
+
linkedin-cli auth status
|
|
167
|
+
|
|
168
|
+
# Re-login if needed
|
|
169
|
+
linkedin-cli auth logout
|
|
170
|
+
linkedin-cli auth login
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Rate Limiting
|
|
174
|
+
|
|
175
|
+
If you encounter rate limiting:
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
# Increase rate limit delay
|
|
179
|
+
linkedin-cli config --set rateLimit=10000
|
|
180
|
+
|
|
181
|
+
# Use non-headless mode to see what's happening
|
|
182
|
+
linkedin-cli messages list --headless false
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Selector Failures
|
|
186
|
+
|
|
187
|
+
If LinkedIn UI changes cause failures:
|
|
188
|
+
|
|
189
|
+
1. Check the audit log: `cat ~/.linkedin-cli/audit.log`
|
|
190
|
+
2. Run with non-headless mode to see the current state
|
|
191
|
+
3. The multi-layer selector system will attempt fallbacks automatically
|
|
192
|
+
|
|
193
|
+
## Development
|
|
194
|
+
|
|
195
|
+
### Setup
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
# Install dependencies
|
|
199
|
+
npm install
|
|
200
|
+
|
|
201
|
+
# Build
|
|
202
|
+
npm run build
|
|
203
|
+
|
|
204
|
+
# Watch mode
|
|
205
|
+
npm run watch
|
|
206
|
+
|
|
207
|
+
# Run locally
|
|
208
|
+
node dist/index.js --help
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Quality Checks
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
# Type check
|
|
215
|
+
npm run typecheck
|
|
216
|
+
|
|
217
|
+
# Lint
|
|
218
|
+
npm run lint
|
|
219
|
+
npm run lint:fix # Auto-fix issues
|
|
220
|
+
|
|
221
|
+
# Format
|
|
222
|
+
npm run format:check
|
|
223
|
+
npm run format # Auto-format code
|
|
224
|
+
|
|
225
|
+
# Run tests
|
|
226
|
+
npm run test # Run tests
|
|
227
|
+
npm run test:watch # Watch mode
|
|
228
|
+
npm run test:coverage # With coverage report
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Pre-commit Hooks
|
|
232
|
+
|
|
233
|
+
Husky runs automatically before each commit:
|
|
234
|
+
- ESLint validation
|
|
235
|
+
- Prettier format check
|
|
236
|
+
|
|
237
|
+
If the hook fails, fix the issues and re-commit.
|
|
238
|
+
|
|
239
|
+
### Testing
|
|
240
|
+
|
|
241
|
+
Tests are written with Vitest and located alongside source files:
|
|
242
|
+
|
|
243
|
+
```
|
|
244
|
+
src/
|
|
245
|
+
├── core/
|
|
246
|
+
│ ├── storage.ts
|
|
247
|
+
│ └── storage.test.ts
|
|
248
|
+
├── templates/
|
|
249
|
+
│ ├── engine.ts
|
|
250
|
+
│ └── engine.test.ts
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Coverage threshold: 80% minimum across all files.
|
|
254
|
+
|
|
255
|
+
## Publishing
|
|
256
|
+
|
|
257
|
+
See [NPM_PUBLISHING.md](./NPM_PUBLISHING.md) for detailed publishing instructions.
|
|
258
|
+
|
|
259
|
+
### Quick Publish
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
# Run all checks
|
|
263
|
+
npm run test:coverage
|
|
264
|
+
npm run build
|
|
265
|
+
|
|
266
|
+
# Bump version (choose: patch, minor, major)
|
|
267
|
+
npm version patch
|
|
268
|
+
|
|
269
|
+
# Push (triggers auto-publish via GitHub Actions)
|
|
270
|
+
git push && git push --tags
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Manual Publish
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
npm login # One-time setup
|
|
277
|
+
npm publish --dry-run # Preview
|
|
278
|
+
npm publish --access public
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## License
|
|
282
|
+
|
|
283
|
+
MIT
|
|
284
|
+
|
|
285
|
+
## Contributing
|
|
286
|
+
|
|
287
|
+
Contributions welcome! Please ensure:
|
|
288
|
+
- TypeScript compiles without errors
|
|
289
|
+
- Follow existing code style
|
|
290
|
+
- Add tests for new features
|
|
291
|
+
- Update documentation
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
**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.
|
package/TESTING-GUIDE.md
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# LinkedIn CLI Testing Guide
|
|
2
|
+
|
|
3
|
+
## 🧪 Safe Testing Protocol
|
|
4
|
+
|
|
5
|
+
### Step 1: Dry Run Mode (Safe)
|
|
6
|
+
Test all commands without actually connecting to LinkedIn:
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
# Test help commands
|
|
10
|
+
node ./dist/index.js --help
|
|
11
|
+
node ./dist/index.js auth --help
|
|
12
|
+
node ./dist/index.js messages --help
|
|
13
|
+
node ./dist/index.js connect --help
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### Step 2: Configuration Test
|
|
17
|
+
```bash
|
|
18
|
+
# View default config
|
|
19
|
+
node ./dist/index.js config --get
|
|
20
|
+
|
|
21
|
+
# Set dry-run mode for safety
|
|
22
|
+
node ./dist/index.js config --set dryRun=true
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Step 3: Authentication Test (Requires Credentials)
|
|
26
|
+
|
|
27
|
+
**Option A: Interactive Login (Recommended)**
|
|
28
|
+
```bash
|
|
29
|
+
# Run in non-headless mode so you can see what's happening
|
|
30
|
+
node ./dist/index.js auth login --headless false
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Option B: With Email Provided**
|
|
34
|
+
```bash
|
|
35
|
+
node ./dist/index.js auth login --email your@email.com --headless false
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**What you'll see:**
|
|
39
|
+
1. Browser opens
|
|
40
|
+
2. LinkedIn login page loads
|
|
41
|
+
3. You'll enter password manually (secure)
|
|
42
|
+
4. If 2FA is enabled, you'll enter the TOTP code
|
|
43
|
+
5. Session is saved securely
|
|
44
|
+
|
|
45
|
+
### Step 4: Verify Authentication
|
|
46
|
+
```bash
|
|
47
|
+
node ./dist/index.js auth status
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Step 5: Test Messages (Read-Only)
|
|
51
|
+
```bash
|
|
52
|
+
# List recent conversations
|
|
53
|
+
node ./dist/index.js messages list --limit 5
|
|
54
|
+
|
|
55
|
+
# Read a specific thread
|
|
56
|
+
node ./dist/index.js messages show --thread <THREAD_ID>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Step 6: Test Reply (With Dry Run)
|
|
60
|
+
```bash
|
|
61
|
+
# Dry run - simulates sending without actually sending
|
|
62
|
+
node ./dist/index.js reply send --thread <THREAD_ID> --message "Test message" --dry-run
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Step 7: Test Connection Request (With Dry Run)
|
|
66
|
+
```bash
|
|
67
|
+
# Dry run connection request
|
|
68
|
+
node ./dist/index.js connect send https://www.linkedin.com/in/some-profile/ --note "Hi, I'd like to connect" --dry-run
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## 🔐 Security Notes
|
|
74
|
+
|
|
75
|
+
1. **Passwords are NEVER stored** - Only session cookies are saved
|
|
76
|
+
2. **Encrypted storage** - Sessions use AES-256-GCM encryption
|
|
77
|
+
3. **Machine-bound** - Sessions can't be copied to other machines
|
|
78
|
+
4. **Audit logging** - All actions are logged to `~/.linkedin-cli/audit.log`
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## 🚨 Safety Checklist
|
|
83
|
+
|
|
84
|
+
Before running any command that modifies data:
|
|
85
|
+
- [ ] Use `--dry-run` flag first
|
|
86
|
+
- [ ] Review the action in the output
|
|
87
|
+
- [ ] Check audit log: `cat ~/.linkedin-cli/audit.log`
|
|
88
|
+
- [ ] Start with `--limit 1` for list commands
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## 📊 Test Checklist
|
|
93
|
+
|
|
94
|
+
Let's test together:
|
|
95
|
+
|
|
96
|
+
### Phase 1: Basic Tests (No Credentials Needed)
|
|
97
|
+
- [ ] CLI help works
|
|
98
|
+
- [ ] Config can be read
|
|
99
|
+
- [ ] All command groups show help
|
|
100
|
+
|
|
101
|
+
### Phase 2: Authentication (Requires Your Input)
|
|
102
|
+
- [ ] Browser opens
|
|
103
|
+
- [ ] Can login to LinkedIn
|
|
104
|
+
- [ ] Session is saved
|
|
105
|
+
- [ ] Status shows logged in
|
|
106
|
+
|
|
107
|
+
### Phase 3: Read Operations (Safe)
|
|
108
|
+
- [ ] Can list messages
|
|
109
|
+
- [ ] Can read conversation threads
|
|
110
|
+
- [ ] Data displays correctly
|
|
111
|
+
|
|
112
|
+
### Phase 4: Write Operations (Use Dry-Run First!)
|
|
113
|
+
- [ ] Dry-run reply works
|
|
114
|
+
- [ ] Dry-run connection works
|
|
115
|
+
- [ ] Audit log captures actions
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## 🔍 Troubleshooting
|
|
120
|
+
|
|
121
|
+
### Issue: "Not logged in"
|
|
122
|
+
**Solution:** Run `node ./dist/index.js auth login` first
|
|
123
|
+
|
|
124
|
+
### Issue: Browser doesn't open
|
|
125
|
+
**Solution:** Check Playwright installation:
|
|
126
|
+
```bash
|
|
127
|
+
npx playwright install chromium
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Issue: Session expires quickly
|
|
131
|
+
**Solution:** LinkedIn sessions expire after ~24 hours. Just run auth login again.
|
|
132
|
+
|
|
133
|
+
### Issue: Rate limiting
|
|
134
|
+
**Solution:** Increase rate limit delay:
|
|
135
|
+
```bash
|
|
136
|
+
node ./dist/index.js config --set rateLimit=10000
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## 📞 Next Steps
|
|
142
|
+
|
|
143
|
+
Ready to test? Let's start with **Phase 1** (no credentials needed), then move to **Phase 2** when you're ready to login!
|
|
144
|
+
|
|
145
|
+
**Commands to run now:**
|
|
146
|
+
```bash
|
|
147
|
+
cd /Users/thaddeus/projects/linkedin-automation/.worktrees/linkedin-automation-cli
|
|
148
|
+
node ./dist/index.js --help
|
|
149
|
+
node ./dist/index.js auth --help
|
|
150
|
+
node ./dist/index.js config --get
|
|
151
|
+
```
|