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.
Files changed (314) hide show
  1. package/.env.example +12 -0
  2. package/.github/workflows/ci.yml +66 -0
  3. package/.github/workflows/publish.yml +48 -0
  4. package/.husky/pre-commit +6 -0
  5. package/.prettierignore +4 -0
  6. package/.prettierrc +10 -0
  7. package/AGENTS.md +294 -0
  8. package/CHANGELOG.md +40 -0
  9. package/GIT_RELEASE.md +167 -0
  10. package/LICENSE +21 -0
  11. package/Makefile +30 -0
  12. package/NPM_PUBLISHING.md +230 -0
  13. package/PYEOF +0 -0
  14. package/README.md +295 -0
  15. package/TESTING-GUIDE.md +151 -0
  16. package/cmd/linkedin/main.go +9 -0
  17. package/dist/agent/action-executor.d.ts +81 -0
  18. package/dist/agent/action-executor.d.ts.map +1 -0
  19. package/dist/agent/action-executor.js +170 -0
  20. package/dist/agent/action-executor.js.map +1 -0
  21. package/dist/agent/action-executor.test.d.ts +2 -0
  22. package/dist/agent/action-executor.test.d.ts.map +1 -0
  23. package/dist/agent/action-executor.test.js +366 -0
  24. package/dist/agent/action-executor.test.js.map +1 -0
  25. package/dist/agent/claude-client.d.ts +74 -0
  26. package/dist/agent/claude-client.d.ts.map +1 -0
  27. package/dist/agent/claude-client.js +314 -0
  28. package/dist/agent/claude-client.js.map +1 -0
  29. package/dist/agent/claude-client.test.d.ts +2 -0
  30. package/dist/agent/claude-client.test.d.ts.map +1 -0
  31. package/dist/agent/claude-client.test.js +590 -0
  32. package/dist/agent/claude-client.test.js.map +1 -0
  33. package/dist/agent/dom-extractor.d.ts +50 -0
  34. package/dist/agent/dom-extractor.d.ts.map +1 -0
  35. package/dist/agent/dom-extractor.js +374 -0
  36. package/dist/agent/dom-extractor.js.map +1 -0
  37. package/dist/agent/dom-extractor.test.d.ts +7 -0
  38. package/dist/agent/dom-extractor.test.d.ts.map +1 -0
  39. package/dist/agent/dom-extractor.test.js +504 -0
  40. package/dist/agent/dom-extractor.test.js.map +1 -0
  41. package/dist/agent/extension-client.d.ts +75 -0
  42. package/dist/agent/extension-client.d.ts.map +1 -0
  43. package/dist/agent/extension-client.js +245 -0
  44. package/dist/agent/extension-client.js.map +1 -0
  45. package/dist/agent/index.d.ts +8 -0
  46. package/dist/agent/index.d.ts.map +1 -0
  47. package/dist/agent/index.js +16 -0
  48. package/dist/agent/index.js.map +1 -0
  49. package/dist/agent/page-agent.d.ts +76 -0
  50. package/dist/agent/page-agent.d.ts.map +1 -0
  51. package/dist/agent/page-agent.js +236 -0
  52. package/dist/agent/page-agent.js.map +1 -0
  53. package/dist/agent/types.d.ts +236 -0
  54. package/dist/agent/types.d.ts.map +1 -0
  55. package/dist/agent/types.js +37 -0
  56. package/dist/agent/types.js.map +1 -0
  57. package/dist/cli/agent-commands.d.ts +3 -0
  58. package/dist/cli/agent-commands.d.ts.map +1 -0
  59. package/dist/cli/agent-commands.js +250 -0
  60. package/dist/cli/agent-commands.js.map +1 -0
  61. package/dist/cli/auth.d.ts +3 -0
  62. package/dist/cli/auth.d.ts.map +1 -0
  63. package/dist/cli/auth.js +288 -0
  64. package/dist/cli/auth.js.map +1 -0
  65. package/dist/cli/company.d.ts +3 -0
  66. package/dist/cli/company.d.ts.map +1 -0
  67. package/dist/cli/company.js +55 -0
  68. package/dist/cli/company.js.map +1 -0
  69. package/dist/cli/connection.d.ts +3 -0
  70. package/dist/cli/connection.d.ts.map +1 -0
  71. package/dist/cli/connection.js +79 -0
  72. package/dist/cli/connection.js.map +1 -0
  73. package/dist/cli/index.d.ts +7 -0
  74. package/dist/cli/index.d.ts.map +1 -0
  75. package/dist/cli/index.js +17 -0
  76. package/dist/cli/index.js.map +1 -0
  77. package/dist/cli/messages.d.ts +3 -0
  78. package/dist/cli/messages.d.ts.map +1 -0
  79. package/dist/cli/messages.js +268 -0
  80. package/dist/cli/messages.js.map +1 -0
  81. package/dist/cli/profile.d.ts +3 -0
  82. package/dist/cli/profile.d.ts.map +1 -0
  83. package/dist/cli/profile.js +81 -0
  84. package/dist/cli/profile.js.map +1 -0
  85. package/dist/cli/profile.test.d.ts +2 -0
  86. package/dist/cli/profile.test.d.ts.map +1 -0
  87. package/dist/cli/profile.test.js +15 -0
  88. package/dist/cli/profile.test.js.map +1 -0
  89. package/dist/cli/reply.d.ts +3 -0
  90. package/dist/cli/reply.d.ts.map +1 -0
  91. package/dist/cli/reply.js +129 -0
  92. package/dist/cli/reply.js.map +1 -0
  93. package/dist/core/audit.d.ts +17 -0
  94. package/dist/core/audit.d.ts.map +1 -0
  95. package/dist/core/audit.js +121 -0
  96. package/dist/core/audit.js.map +1 -0
  97. package/dist/core/audit.test.d.ts +2 -0
  98. package/dist/core/audit.test.d.ts.map +1 -0
  99. package/dist/core/audit.test.js +142 -0
  100. package/dist/core/audit.test.js.map +1 -0
  101. package/dist/core/browser-cookies.d.ts +19 -0
  102. package/dist/core/browser-cookies.d.ts.map +1 -0
  103. package/dist/core/browser-cookies.js +181 -0
  104. package/dist/core/browser-cookies.js.map +1 -0
  105. package/dist/core/browser.d.ts +50 -0
  106. package/dist/core/browser.d.ts.map +1 -0
  107. package/dist/core/browser.js +318 -0
  108. package/dist/core/browser.js.map +1 -0
  109. package/dist/core/config.d.ts +20 -0
  110. package/dist/core/config.d.ts.map +1 -0
  111. package/dist/core/config.js +103 -0
  112. package/dist/core/config.js.map +1 -0
  113. package/dist/core/config.test.d.ts +2 -0
  114. package/dist/core/config.test.d.ts.map +1 -0
  115. package/dist/core/config.test.js +111 -0
  116. package/dist/core/config.test.js.map +1 -0
  117. package/dist/core/storage.d.ts +19 -0
  118. package/dist/core/storage.d.ts.map +1 -0
  119. package/dist/core/storage.js +124 -0
  120. package/dist/core/storage.js.map +1 -0
  121. package/dist/core/storage.test.d.ts +2 -0
  122. package/dist/core/storage.test.d.ts.map +1 -0
  123. package/dist/core/storage.test.js +142 -0
  124. package/dist/core/storage.test.js.map +1 -0
  125. package/dist/index.d.ts +3 -0
  126. package/dist/index.d.ts.map +1 -0
  127. package/dist/index.js +63 -0
  128. package/dist/index.js.map +1 -0
  129. package/dist/linkedin/auth.d.ts +22 -0
  130. package/dist/linkedin/auth.d.ts.map +1 -0
  131. package/dist/linkedin/auth.js +167 -0
  132. package/dist/linkedin/auth.js.map +1 -0
  133. package/dist/linkedin/company-extractor.d.ts +36 -0
  134. package/dist/linkedin/company-extractor.d.ts.map +1 -0
  135. package/dist/linkedin/company-extractor.js +211 -0
  136. package/dist/linkedin/company-extractor.js.map +1 -0
  137. package/dist/linkedin/company-extractor.test.d.ts +2 -0
  138. package/dist/linkedin/company-extractor.test.d.ts.map +1 -0
  139. package/dist/linkedin/company-extractor.test.js +52 -0
  140. package/dist/linkedin/company-extractor.test.js.map +1 -0
  141. package/dist/linkedin/connector.d.ts +45 -0
  142. package/dist/linkedin/connector.d.ts.map +1 -0
  143. package/dist/linkedin/connector.js +245 -0
  144. package/dist/linkedin/connector.js.map +1 -0
  145. package/dist/linkedin/message-sender.d.ts +32 -0
  146. package/dist/linkedin/message-sender.d.ts.map +1 -0
  147. package/dist/linkedin/message-sender.js +112 -0
  148. package/dist/linkedin/message-sender.js.map +1 -0
  149. package/dist/linkedin/messages.d.ts +78 -0
  150. package/dist/linkedin/messages.d.ts.map +1 -0
  151. package/dist/linkedin/messages.js +745 -0
  152. package/dist/linkedin/messages.js.map +1 -0
  153. package/dist/linkedin/profile.d.ts +37 -0
  154. package/dist/linkedin/profile.d.ts.map +1 -0
  155. package/dist/linkedin/profile.js +268 -0
  156. package/dist/linkedin/profile.js.map +1 -0
  157. package/dist/linkedin/profile.test.d.ts +2 -0
  158. package/dist/linkedin/profile.test.d.ts.map +1 -0
  159. package/dist/linkedin/profile.test.js +68 -0
  160. package/dist/linkedin/profile.test.js.map +1 -0
  161. package/dist/linkedin/reply.d.ts +21 -0
  162. package/dist/linkedin/reply.d.ts.map +1 -0
  163. package/dist/linkedin/reply.js +76 -0
  164. package/dist/linkedin/reply.js.map +1 -0
  165. package/dist/linkedin/selector-engine.d.ts +69 -0
  166. package/dist/linkedin/selector-engine.d.ts.map +1 -0
  167. package/dist/linkedin/selector-engine.js +339 -0
  168. package/dist/linkedin/selector-engine.js.map +1 -0
  169. package/dist/linkedin/selector-engine.test.d.ts +2 -0
  170. package/dist/linkedin/selector-engine.test.d.ts.map +1 -0
  171. package/dist/linkedin/selector-engine.test.js +135 -0
  172. package/dist/linkedin/selector-engine.test.js.map +1 -0
  173. package/dist/linkedin/selectors.d.ts +65 -0
  174. package/dist/linkedin/selectors.d.ts.map +1 -0
  175. package/dist/linkedin/selectors.js +261 -0
  176. package/dist/linkedin/selectors.js.map +1 -0
  177. package/dist/templates/engine.d.ts +37 -0
  178. package/dist/templates/engine.d.ts.map +1 -0
  179. package/dist/templates/engine.js +215 -0
  180. package/dist/templates/engine.js.map +1 -0
  181. package/dist/templates/engine.test.d.ts +2 -0
  182. package/dist/templates/engine.test.d.ts.map +1 -0
  183. package/dist/templates/engine.test.js +212 -0
  184. package/dist/templates/engine.test.js.map +1 -0
  185. package/dist/templates/index.d.ts +2 -0
  186. package/dist/templates/index.d.ts.map +1 -0
  187. package/dist/templates/index.js +7 -0
  188. package/dist/templates/index.js.map +1 -0
  189. package/dist/types/index.d.ts +113 -0
  190. package/dist/types/index.d.ts.map +1 -0
  191. package/dist/types/index.js +3 -0
  192. package/dist/types/index.js.map +1 -0
  193. package/dist/types/index.test.d.ts +2 -0
  194. package/dist/types/index.test.d.ts.map +1 -0
  195. package/dist/types/index.test.js +90 -0
  196. package/dist/types/index.test.js.map +1 -0
  197. package/dist/utils/paths.d.ts +8 -0
  198. package/dist/utils/paths.d.ts.map +1 -0
  199. package/dist/utils/paths.js +68 -0
  200. package/dist/utils/paths.js.map +1 -0
  201. package/dist/utils/rate-limiter.d.ts +22 -0
  202. package/dist/utils/rate-limiter.d.ts.map +1 -0
  203. package/dist/utils/rate-limiter.js +57 -0
  204. package/dist/utils/rate-limiter.js.map +1 -0
  205. package/dist/utils/retry.d.ts +18 -0
  206. package/dist/utils/retry.d.ts.map +1 -0
  207. package/dist/utils/retry.js +49 -0
  208. package/dist/utils/retry.js.map +1 -0
  209. package/docs/connection-command.md +52 -0
  210. package/docs/plans/2025-03-03-linkedin-cli-design.md +280 -0
  211. package/docs/plans/2025-03-03-linkedin-cli-implementation-plan.md +2087 -0
  212. package/docs/plans/2025-03-03-linkedin-cli-implementation.md +2420 -0
  213. package/docs/plans/2026-02-19-linkedin-connection-feature.md +596 -0
  214. package/docs/plans/2026-02-28-messages-send-feature.md +480 -0
  215. package/docs/plans/2026-02-28-messages-show-design.md +243 -0
  216. package/docs/plans/2026-03-03-linkedin-cli-oss-publishing-design.md +394 -0
  217. package/docs/plans/2026-03-03-linkedin-cli-oss-publishing-plan.md +1592 -0
  218. package/docs/superpowers/plans/2026-03-13-linkedin-automation-resilience-migration.md +425 -0
  219. package/docs/superpowers/plans/2026-03-13-playwright-fara-migration.md +1112 -0
  220. package/docs/superpowers/plans/2026-03-14-page-agent-plan.md +1598 -0
  221. package/docs/superpowers/plans/2026-03-15-company-profile-extraction.md +591 -0
  222. package/docs/superpowers/plans/2026-03-15-profile-extraction-plan.md +943 -0
  223. package/docs/superpowers/specs/2026-03-14-company-profile-extraction-design.md +371 -0
  224. package/docs/superpowers/specs/2026-03-14-page-agent-design.md +385 -0
  225. package/docs/superpowers/specs/2026-03-15-profile-extraction-design.md +409 -0
  226. package/eslint.config.mjs +58 -0
  227. package/go.mod +9 -0
  228. package/go.sum +10 -0
  229. package/import-cookies.js +376 -0
  230. package/internal/cmd/actions.go +123 -0
  231. package/internal/cmd/auth.go +108 -0
  232. package/internal/cmd/connect.go +42 -0
  233. package/internal/cmd/message.go +44 -0
  234. package/internal/cmd/people.go +454 -0
  235. package/internal/cmd/profiles.go +121 -0
  236. package/internal/cmd/root.go +89 -0
  237. package/internal/cmd/sequence.go +192 -0
  238. package/internal/config/config.go +187 -0
  239. package/internal/config/config_test.go +121 -0
  240. package/internal/config/profile.go +65 -0
  241. package/internal/linkedin/navigator.go +195 -0
  242. package/internal/linkedin/selectors.go +39 -0
  243. package/internal/linkedin/validator.go +69 -0
  244. package/internal/pinchtab/client.go +183 -0
  245. package/internal/pinchtab/client_test.go +67 -0
  246. package/internal/pinchtab/types.go +50 -0
  247. package/internal/ratelimit/limiter.go +115 -0
  248. package/internal/ratelimit/limits.go +32 -0
  249. package/package.json +67 -0
  250. package/release.sh +66 -0
  251. package/scripts/debug-linkedin.js +156 -0
  252. package/scripts/debug-login.js +193 -0
  253. package/scripts/extract-from-edge.js +96 -0
  254. package/scripts/import-cookies.js +101 -0
  255. package/scripts/poc-show-data.js +205 -0
  256. package/scripts/proof-of-access.js +87 -0
  257. package/scripts/prove-connection.js +110 -0
  258. package/scripts/show-linkedin-data.js +173 -0
  259. package/src/agent/action-executor.test.ts +464 -0
  260. package/src/agent/action-executor.ts +203 -0
  261. package/src/agent/claude-client.test.ts +707 -0
  262. package/src/agent/claude-client.ts +422 -0
  263. package/src/agent/dom-extractor.test.ts +574 -0
  264. package/src/agent/dom-extractor.ts +437 -0
  265. package/src/agent/extension-client.ts +306 -0
  266. package/src/agent/index.ts +28 -0
  267. package/src/agent/page-agent.ts +292 -0
  268. package/src/agent/types.ts +288 -0
  269. package/src/cli/agent-commands.ts +274 -0
  270. package/src/cli/auth.ts +343 -0
  271. package/src/cli/company.ts +66 -0
  272. package/src/cli/connection.ts +89 -0
  273. package/src/cli/index.ts +7 -0
  274. package/src/cli/messages.ts +338 -0
  275. package/src/cli/profile.test.ts +14 -0
  276. package/src/cli/profile.ts +95 -0
  277. package/src/cli/reply.ts +110 -0
  278. package/src/core/audit.test.ts +134 -0
  279. package/src/core/audit.ts +98 -0
  280. package/src/core/browser-cookies.ts +203 -0
  281. package/src/core/browser.ts +304 -0
  282. package/src/core/config.test.ts +90 -0
  283. package/src/core/config.ts +81 -0
  284. package/src/core/storage.test.ts +129 -0
  285. package/src/core/storage.ts +100 -0
  286. package/src/index.ts +70 -0
  287. package/src/linkedin/auth.ts +218 -0
  288. package/src/linkedin/company-extractor.test.ts +58 -0
  289. package/src/linkedin/company-extractor.ts +222 -0
  290. package/src/linkedin/connector.ts +336 -0
  291. package/src/linkedin/message-sender.ts +141 -0
  292. package/src/linkedin/messages.ts +894 -0
  293. package/src/linkedin/profile.test.ts +79 -0
  294. package/src/linkedin/profile.ts +314 -0
  295. package/src/linkedin/reply.ts +96 -0
  296. package/src/linkedin/selector-engine.test.ts +167 -0
  297. package/src/linkedin/selector-engine.ts +393 -0
  298. package/src/linkedin/selectors.ts +268 -0
  299. package/src/templates/defaults/followup.txt +14 -0
  300. package/src/templates/defaults/meeting.txt +16 -0
  301. package/src/templates/defaults/welcome.txt +14 -0
  302. package/src/templates/engine.test.ts +228 -0
  303. package/src/templates/engine.ts +208 -0
  304. package/src/templates/index.ts +1 -0
  305. package/src/types/index.test.ts +94 -0
  306. package/src/types/index.ts +143 -0
  307. package/src/types/sql.js.d.ts +23 -0
  308. package/src/utils/paths.ts +33 -0
  309. package/src/utils/rate-limiter.ts +75 -0
  310. package/src/utils/retry.ts +78 -0
  311. package/test-cli.sh +85 -0
  312. package/test-real-data.sh +97 -0
  313. package/tsconfig.json +23 -0
  314. 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.
@@ -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
+ ```
@@ -0,0 +1,9 @@
1
+ package main
2
+
3
+ import (
4
+ "github.com/thaddeus-git/linkedin-cli/internal/cmd"
5
+ )
6
+
7
+ func main() {
8
+ cmd.Execute()
9
+ }