ilml-plugin-linkedin 1.2.0 → 1.2.2

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/CHANGELOG.md ADDED
@@ -0,0 +1,28 @@
1
+ # Changelog
2
+
3
+ ## 1.2.2
4
+ - README polish based on real-user feedback:
5
+ - Cleaner top — removed the metadata bullet list (npm/tracker/license) that was the very first thing visitors saw on the npm page; now opens straight into "What it does"
6
+ - Removed the entire `Developer Notes` section — it was internal-only and not useful for end users (release process and architecture notes live in `CLAUDE.md` and the SDK's plugin spec)
7
+ - Clarified the `LINKEDIN_SEARCH_URL` instruction (no more raw URL parameters like `f_AL=true` — just "open LinkedIn → Jobs, set filters, copy URL")
8
+ - New **Author & contact** section with personal page, LinkedIn, and a **DigitalTwins.team** call-to-action for custom plugin development
9
+ - `CHANGELOG.md` is now shipped in the npm tarball (added to `package.json#files`), so the npm package page renders release notes next to the README
10
+ - New **Feedback & support** section in the README pointing at a dedicated **Support** node in iLiveMyLife (`0000019dde81b04f-2e534bb8ebad0000`) — users can write directly to the maintainer via the in-graph messenger or `ilml send` from the terminal
11
+
12
+ ## 1.2.1
13
+ - Documentation overhaul — `README.md` rewritten in English, split into **User Guide** (install, configure, run, update) and **Developer Notes** (release process, architecture, security checklist)
14
+ - Removed outdated `.env`-based user instructions — the plugin is now fully self-configuring via `ilml plugin install linkedin` + first-run prompts (or `ilml plugin config linkedin set KEY VALUE`)
15
+ - Added `CHANGELOG.md` (this file)
16
+ - Added `CLAUDE.md` — project-level guide for the AI assistant covering release process and key architecture pointers
17
+ - Added a `Releases` node in the iLiveMyLife graph for in-app release notifications
18
+
19
+ ## 1.2.0
20
+ - First public publish on npm as `ilml-plugin-linkedin`
21
+ - `src/config.mjs` refactored to use `getPluginConfig()` from `@ilivemylife/graph-sdk` v1.0.17
22
+ - Resolved configuration is merged into `process.env` so the rest of the codebase (16+ files reading `process.env.X`) keeps working unchanged
23
+ - The manual `LINKEDIN_NAME` bootstrap check is removed — schema validation in the SDK handles it
24
+ - Works in both **production** (`ilml linkedin <command>`) and **development** (`node run.mjs` with `.env` next to manifest), without any code changes between modes
25
+ - Bumped `@ilivemylife/graph-sdk` peer to `^1.0.17`
26
+ - `package.json` polish for npm publish — `author`, `license: UNLICENSED`, `keywords`, strict `files: ["dist", "ilml-plugin.json"]` whitelist
27
+ - `ilml-plugin.json` declares config via `config.sections[].fields[]` (richer manifest format supported by SDK 1.0.17): grouped fields with `label`, `hint`, types (`text`, `secret`, `path`, `nodeId`, `url`, `number`, `boolean`)
28
+ - All sensitive files (`.env`, `cookies.json`, raw sources, internal handoff docs, runtime data) excluded from the npm tarball via `.npmignore`
package/README.md CHANGED
@@ -1,369 +1,219 @@
1
- # LinkedIn Automation Toolkit
2
-
3
- Автоматизация LinkedIn: подача заявок на вакансии, мониторинг входящих сообщений, управление контактами и рассылка сообщений.
4
-
5
- ---
6
-
7
- ## Быстрый старт (5 минут)
8
-
9
- ### Шаг 1. Установи Node.js
10
-
11
- Зайди на https://nodejs.org/ и нажми зелёную кнопку **LTS**. Запусти скачанный файл и нажимай "Next" до конца.
12
-
13
- Проверь что установилось открой терминал и набери:
14
- ```
15
- node --version
16
- ```
17
- Должно показать версию (например `v22.x.x`).
18
-
19
- > **Как открыть терминал:**
20
- > - **Windows**: нажми `Win+R`, набери `cmd`, нажми Enter
21
- > - **Mac**: открой приложение Terminal (Cmd+Space → набери Terminal)
22
-
23
- ### Шаг 2. Распакуй проект
24
-
25
- Распакуй `linkedin-auto-apply.zip` в любую папку (например на рабочий стол).
26
-
27
- ### Шаг 3. Открой терминал в папке проекта
28
-
29
- - **Windows**: открой папку в проводнике → кликни на адресную строку вверху → набери `cmd` → Enter
30
- - **Mac**: Terminal → набери `cd ` (с пробелом) → перетащи папку в окно → Enter
31
-
32
- ### Шаг 4. Установи зависимости
33
-
34
- ```
35
- npm install
36
- ```
37
- Подожди 1-2 минуты (скачается ~200 MB для встроенного браузера).
38
-
39
- ### Шаг 5. Настрой конфигурацию
40
-
41
- Скопируй шаблон настроек:
42
- ```
43
- copy .env.example .env
44
- ```
45
- > На Mac/Linux: `cp .env.example .env`
46
-
47
- Открой файл `.env` в **Блокноте** (Windows) или **TextEdit** (Mac) и заполни:
48
-
49
- ```ini
50
- # === Обязательные ===
51
- LINKEDIN_NAME=Иван Петров # ← Твоё имя ТОЧНО как на LinkedIn
52
- LINKEDIN_LOGIN=ivan@gmail.com # ← Email для входа в LinkedIn
53
- LINKEDIN_PASS=mypassword123 # ← Пароль от LinkedIn
54
-
55
- # === iLiveMyLife (нужно для подачи заявок) ===
56
- NODE_EASY_APPLY_MAIN=id_узла # ID основного узла (см. Шаг 5б)
57
- NODE_EASY_APPLY_ERRORS=id_узла # ← ID узла для ошибок (см. Шаг 5б)
58
- ```
59
-
60
- > Токен iLiveMyLife не нужно прописывать в `.env` — он подхватывается автоматически после `ilml login` (Шаг 5б).
61
-
62
- > **LINKEDIN_NAME** — самая важная настройка. Открой свой LinkedIn профиль и скопируй имя точно как оно показано (включая язык и регистр).
63
-
64
- ### Шаг 5б. Настрой iLiveMyLife (нужно для `npm run apply`)
65
-
66
- Бот использует AI-ассистента **Lifebot** для принятия решений: подавать ли на вакансию, как заполнять анкеты. Без этого шага `npm run apply` не запустится.
67
-
68
- > **Мониторинг сообщений** (`npm run sync-all`, `npm run today`) работает без iLiveMyLife. Этот шаг нужен только для автоматической подачи заявок.
69
-
70
- #### 1. Создай аккаунт
71
-
72
- Зайди на https://app.ilivemylife.io и зарегистрируйся (бесплатно).
73
-
74
- #### 2. Установи iLiveMyLife CLI и залогинься
75
-
76
- ```
77
- npm install -g @ilivemylife/graph-sdk
78
- ilml login
79
- ```
80
-
81
- > Подробнее о CLI: https://www.npmjs.com/package/@ilivemylife/graph-sdk
82
-
83
- CLI спросит email и пароль от iLiveMyLife. После успешного входа токен сохранится автоматически в `~/.ilivemylife/config.json` бот подхватит его оттуда, ничего в `.env` прописывать не нужно.
84
-
85
- > **Бонус:** `ilml` CLI это ещё и инструмент для работы с графом из терминала. Попробуй `ilml doctor` чтобы проверить что всё настроено, или `ilml help` для списка команд.
86
-
87
- #### 3. Создай главный узел для подачи заявок
88
-
89
- 1. На главной странице нажми **+** (создать узел)
90
- 2. Назови его **"LinkedIn Easy Apply"**
91
- 3. Открой узелв правом меню включи переключатель **AI-ассистент** (Lifebot)
92
- > Это включает AI для этого узла. **Без этого бот не сможет принимать решения!**
93
- 4. Скопируй **ID узла** из адресной строки: `https://app.ilivemylife.io/item/ВОТ_ЭТОТ_ДЛИННЫЙ_КОД`
94
- 5. Вставь в `.env`: `NODE_EASY_APPLY_MAIN=скопированный_id`
95
-
96
- В **описании узла** (нажми на заголовок редактировать) напиши правила для бота:
97
-
98
- ```
99
- Правила для заполнения анкет:
100
- * Меня зовут Иван Петров
101
- * Мой город: Toronto, Ontario, Canada
102
- * Телефон: +1-416-xxx-xxxx
103
- * Email: ivan@gmail.com
104
- * Опыт программирования: 8 лет
105
- * Предпочитаю full-time, готов рассмотреть контракт
106
- * Я имею право работать в Канаде (PR)
107
- * Зарплатные ожидания: $120-150K CAD
108
- * Notice period: 14 дней
109
- ```
110
-
111
- > Lifebot читает описание узла и все дочерние узлы внутри него. Чем подробнее напишешь — тем точнее бот заполнит анкеты.
112
-
113
- #### 4. Создай дочерние узлы с информацией о себе
114
-
115
- Внутри **"LinkedIn Easy Apply"** создай несколько узлов-карточек. Lifebot будет обращаться к ним при заполнении анкет:
116
-
117
- **Узел "Резюме"** твой опыт работы:
118
- ```
119
- Senior Software Engineer, 8 лет опыта.
120
- Последний проект: ...
121
- Образование: ...
122
- Языки: английский (свободно), русский (родной)
123
- ```
124
- > Можно вставить подробно все места работы, проекты, достижения. Или вместо создания нового узла добавь ссылку на существующий узел с резюме, если он уже есть в графе.
125
-
126
- **Узел "Технологии и опыт"** — список навыков с годами:
127
- ```
128
- Java - 8 лет
129
- Python - 5 лет
130
- React - 4 года
131
- AWS - 6 лет
132
- Docker/K8s - 3 года
133
- ```
134
- > Когда анкета спросит "How many years of Python experience?"Lifebot найдёт ответ здесь.
135
-
136
- **Узел "Критерии подачи"** — на какие вакансии подавать:
137
- ```
138
- Подавать на: Software Engineer, Backend Developer, Full-stack, CTO
139
- НЕ подавать на: Sales, Marketing, Accounting, позиции не связанные с IT
140
- Локация: удалённо или Toronto
141
- ```
142
- > Бот перед каждой вакансией спрашивает Lifebot "Should I apply?". Этот узел помогает принять решение.
143
-
144
- **Узел "Error log"** сюда бот будет писать ошибки при заполнении форм:
145
- 1. Создай узел **"Error log"** внутри главного
146
- 2. AI-ассистент **не нужен** (это просто лог)
147
- 3. Скопируй ID в `.env`: `NODE_EASY_APPLY_ERRORS=скопированный_id`
148
-
149
- Итого структура будет такая:
150
- ```
151
- LinkedIn Easy Apply ← главный узел (AI включён)
152
- ├── Резюме ← опыт работы, образование
153
- ├── Технологии и опыт ← навыки с годами
154
- ├── Критерии подачи ← на что подавать / не подавать
155
- └── Error log ← сюда бот пишет ошибки
156
- ```
157
-
158
- #### 5. Настрой дешёвый AI (экономия)
159
-
160
- По умолчанию Lifebot использует дорогую модель. Для бота достаточно быстрой дешёвой — она отвечает моментально и бесплатного баланса хватит надолго.
161
-
162
- Откройте **основной узел** (LinkedIn Easy Apply) **Настройки узла** (иконка шестерёнки):
163
-
164
- | Настройка | Значение | Зачем |
165
- |-----------|----------|-------|
166
- | **AI Quality** | **Fast/Cheap** | GPT-3.5 достаточно для анкет, экономит баланс |
167
- | **Root Access** | **Off** | Боту не нужен доступ к остальному графу |
168
-
169
- > Эти настройки влияют только на этот узел. Остальные узлы будут использовать вашу обычную модель.
170
-
171
- ### Шаг 6. Залогинься в LinkedIn
172
-
173
- ```
174
- npm run login
175
- ```
176
-
177
- Откроется браузер автоматически введёт логин/пароль. Если LinkedIn попросит подтверждение (SMS код, капча) сделай это вручную. После входа браузер закроется.
178
-
179
- > Эту команду нужно запускать **один раз**. Повторнотолько если бот скажет "cookies expired".
180
-
181
- ### Готово!
182
-
183
- Теперь можешь использовать любые команды из раздела ниже.
184
-
185
- ---
186
-
187
- ## Обновление до новой версии
188
-
189
- Когда получишь новый `linkedin-auto-apply.zip`:
190
-
191
- ### Если настроен `DATA_DIR` (рекомендуется)
192
-
193
- Если в `.env` указан `DATA_DIR` данные хранятся отдельно от кода:
194
-
195
- 1. Распакуй новый zip в **новую папку**
196
- 2. Скопируй `.env` и `cookies.json` из старой папки
197
- 3. Запусти `npm install`
198
-
199
- Всё данные уже на месте, копировать ничего не нужно.
200
-
201
- ### Если `DATA_DIR` не настроен
202
-
203
- 1. Распакуй в **новую папку** (не поверх старой)
204
- 2. Скопируй из старой папки в новую:
205
- - папку `collected-profiles/` целиком (контакты, переписки, заявки)
206
- - папку `market-research/` целиком (разведка вакансий)
207
- - файл `.env` (настройки)
208
- - файл `cookies.json` (сессия LinkedIn)
209
- 3. Запусти `npm install`
210
-
211
- > **Совет:** настрой `DATA_DIR` в `.env` чтобы упростить будущие обновления (см. раздел "Путь к данным").
212
-
213
- ### После обновления
214
-
215
- Запусти любую команду — данные автоматически обновятся до нового формата:
216
- ```
217
- npm run today
218
- ```
219
-
220
- > Сообщение `Schema migration: v0 → v1` при первом запуске — это нормально. Бэкапы создаются автоматически.
221
-
222
- ---
223
-
224
- ## Основные команды
225
-
226
- ### Мониторинг входящих (рекомендую запускать каждый день)
227
-
228
- | Команда | Что делает |
229
- |---------|-----------|
230
- | `npm run sync-all` | **Главная команда.** Сканирует входящие, читает новые сообщения, обогащает данные |
231
- | `npm run sync-all:safe` | То же, но **не открывает непрочитанные** — сохраняет unread-индикатор в LinkedIn UI |
232
- | `npm run today` | Показывает план на сегодня: кому ответить, что сделать (без браузера) |
233
- | `npm run sync-all:report` | Статистика без открытия браузера |
234
- | `npm run warm-scan` | Найти 1st-degree контактов в target-компаниях (без браузера) |
235
-
236
- ### Сообщения
237
-
238
- | Команда | Что делает |
239
- |---------|-----------|
240
- | `npm run messages -- --list` | Быстрая статистика бесед (без браузера) |
241
- | `npm run messages -- --read "Имя Фамилия"` | Прочитать всю переписку с человеком |
242
- | `npm run messages -- --send "Имя" "Текст"` | Отправить сообщение |
243
- | `npm run messages -- --draft "Имя" "Текст"` | Подготовить черновик (не отправляет) |
244
- | `npm run messages:review` | Просмотреть все черновики перед отправкой |
245
- | `npm run messages:push` | Отправить все подтверждённые черновики |
246
-
247
- ### Подача заявок на вакансии
248
-
249
- | Команда | Что делает |
250
- |---------|-----------|
251
- | `npm run apply` | Автоматическая подача на Easy Apply вакансии |
252
- | `npm run funnel` | Отправить connection requests рекрутерам |
253
- | `npm run sync` | Синхронизировать список контактов |
254
-
255
- ### Поиск по заявкам
256
-
257
- Перед собеседованием — найди что ты отвечал при подаче:
258
-
259
- | Команда | Что делает |
260
- |---------|-----------|
261
- | `npm run search -- --company "Google"` | Все заявки в компанию |
262
- | `npm run search -- --job "senior engineer"` | Поиск по названию вакансии |
263
- | `npm run search -- --job-id 4387994033` | Все данные по конкретной вакансии |
264
-
265
- ---
266
-
267
- ## Ежедневный рабочий процесс
268
-
269
- ```
270
- npm run sync-all ← Утром: синхронизировать входящие
271
- npm run today ← Посмотреть что нужно сделать
272
- npm run apply ← Подать заявки на новые вакансии
273
- ```
274
-
275
- ---
276
-
277
- ## Настройки в .env
278
-
279
- ### Обязательные
280
-
281
- | Переменная | Пример | Описание |
282
- |---|---|---|
283
- | `LINKEDIN_NAME` | `John Smith` | Твоё имя как на LinkedIn (точное совпадение!) |
284
- | `LINKEDIN_LOGIN` | `john@gmail.com` | Email для входа |
285
- | `LINKEDIN_PASS` | `password123` | Пароль |
286
-
287
- ### Для подачи заявок (Easy Apply)
288
-
289
- | Переменная | Пример | Описание |
290
- |---|---|---|
291
- | `City` | `Toronto` | Город для форм |
292
- | `LINKEDIN_SEARCH_URL` | `https://www.linkedin.com/jobs/...` | URL поиска вакансий с настроенными фильтрами |
293
- | `MAX_APPLY_FOR_RUN` | `50` | Максимум заявок за один запуск |
294
- | `CV_TEXT` | `Check my CV...` | Текст для полей Cover Letter |
295
- | `RESUME_PDF_URL` | `https://...pdf` | Ссылка на PDF резюме |
296
- | `RESUME_FILENAME` | `John_Smith_Resume.pdf` | Имя файла резюме |
297
-
298
- ### Для iLiveMyLife (нужно для `npm run apply`)
299
-
300
- | Переменная | Описание |
301
- |---|---|
302
- | `NODE_EASY_APPLY_MAIN` | ID узла для решений бота (с AI-ассистентом!) |
303
- | `NODE_EASY_APPLY_ERRORS` | ID узла для логирования ошибок |
304
-
305
- > Токен подхватывается автоматически после `ilml login` (Шаг 5б). Прописывать в `.env` не нужно.
306
- >
307
- > **NODE_EASY_APPLY_MAIN обязателен** для подачи заявок (`npm run apply`). Бот использует AI для заполнения анкет.
308
- >
309
- > Мониторинг сообщений (`npm run sync-all`) работает без iLiveMyLife.
310
-
311
- ### Путь к данным (опционально)
312
-
313
- | Переменная | Описание |
314
- |---|---|
315
- | `DATA_DIR` | Папка для хранения данных. По умолчанию — рядом с кодом |
316
-
317
- Если хочешь хранить данные отдельно от кода (удобнее при обновлениях):
318
- ```ini
319
- DATA_DIR=D:\MyLinkedInData
320
- ```
321
- Бот создаст `collected-profiles/` и `market-research/` внутри этой папки.
322
-
323
- > **С `DATA_DIR` обновление проще:** распаковал новый zip → `npm install` → готово. Данные остались на месте.
324
-
325
- ---
326
-
327
- ## Где хранятся данные
328
-
329
- Все данные в папке `collected-profiles/` (создаётся автоматически):
330
-
331
- | Файл | Что внутри |
332
- |------|-----------|
333
- | `conversations.json` | Все переписки (сообщения, статусы, теги) |
334
- | `people.json` | Все контакты (имена, должности, компании) |
335
- | `jobs.json` | Поданные заявки |
336
- | `sync-state.json` | Когда последний раз синхронизировались |
337
-
338
- > **Бэкапы создаются автоматически** (`.backup` файлы). Если основной файл повредится — программа восстановит из бэкапа.
339
-
340
- ---
341
-
342
- ## Решение проблем
343
-
344
- | Ошибка | Что делать |
345
- |---|---|
346
- | `No iLiveMyLife token found` | Запусти `ilml login` (Шаг 5б) |
347
- | `NODE_EASY_APPLY_MAIN is not configured` | Создай узел с тегом `assist` и добавь ID в `.env` (Шаг 5б) |
348
- | `LINKEDIN_NAME is not set in .env` | Открой `.env` и добавь `LINKEDIN_NAME=Твоё Имя` |
349
- | `cookies.json not found` | Запусти `npm run login` |
350
- | `cookies expired` / `Redirected to login` | Запусти `npm run login` заново |
351
- | `cookies.json is corrupted` | Удали `cookies.json` и запусти `npm run login` |
352
- | `Schema migration: v0 → v1` | Нормально! При обновлении данные автоматически приводятся к новому формату |
353
- | `Lifebot timeout` | AI перегружен. Бот повторит 2 раза, потом пропустит вакансию. При 3 подряд — остановится, попробуй позже |
354
- | `npm` не найден | Установи Node.js (Шаг 1) |
355
- | Браузер не закрылся | Закрой его вручную (или нажми Ctrl+C в терминале) |
356
- | `Cannot find module` | Запусти `npm install` |
357
- | Данные пропали | Проверь папку `collected-profiles/` — там должны быть `.backup` файлы |
358
-
359
- ### Если ничего не помогает
360
-
361
- 1. Удали `cookies.json`
362
- 2. Запусти `npm run login`
363
- 3. Попробуй команду заново
364
-
365
- ---
366
-
367
- ## Дополнительные команды
368
-
369
- Полный список — в файле `COMMANDS.md`.
1
+ # ilml-plugin-linkedin
2
+
3
+ LinkedIn job-search and networking automation as a plugin for the [`ilml`](https://www.npmjs.com/package/@ilivemylife/graph-sdk) CLI.
4
+
5
+ ## What it does
6
+
7
+ A toolkit that drives LinkedIn from your machine via a real browser (Puppeteer + stealth), with results synced into your [iLiveMyLife](https://ilivemylife.io) knowledge graph:
8
+
9
+ - **Easy Apply** — auto-fills and submits LinkedIn job applications. The graph's AI assistant (**Lifebot**) reads your profile node to answer custom application questions in your voice.
10
+ - **Inbox sync** — scans LinkedIn messages, detects changes, and mirrors threads into your graph.
11
+ - **Message bot** draft review send batch messaging workflow (you approve before anything is sent).
12
+ - **Connection funnel** — process recruiter / founder / investor profiles in batches (connect, skip, message).
13
+ - **Scout**find jobs without applying; reports back which match your filters.
14
+ - **Profile activity** — track who viewed your profile, who you visited, etc.
15
+
16
+ All persistent data (job DB, profile DB, conversation history, cookies) is stored locally in a directory you choose — never in a cloud you don't control.
17
+
18
+ ---
19
+
20
+ # User Guide
21
+
22
+ ## Prerequisites
23
+
24
+ - **Node.js 18+** — [download](https://nodejs.org/) (the Long-Term Support version is fine).
25
+ - **iLiveMyLife account** free signup at [iLiveMyLife.io](https://ilivemylife.io).
26
+ - **LinkedIn account** — your personal one.
27
+
28
+ That's it. There's nothing to clone or compile.
29
+
30
+ ## Install
31
+
32
+ One-time, on your machine:
33
+
34
+ ```bash
35
+ # 1. Install the ilml CLI (skip if already installed)
36
+ npm install -g @ilivemylife/graph-sdk
37
+
38
+ # 2. Log in to your iLiveMyLife account
39
+ ilml login
40
+
41
+ # 3. Install this plugin
42
+ ilml plugin install linkedin
43
+ ```
44
+
45
+ That's the whole install. The bare-name `linkedin` resolves to `npm:ilml-plugin-linkedin` via the ilml plugin convention. The CLI downloads the latest version from npm, extracts it under `~/.ilivemylife/plugins/linkedin/`, and runs `npm install` for its runtime dependencies (mainly Puppeteer's bundled Chromium — first install takes a couple of minutes).
46
+
47
+ Verify it's installed:
48
+
49
+ ```bash
50
+ ilml plugin list
51
+ ilml linkedin
52
+ ```
53
+
54
+ ## Configure
55
+
56
+ The plugin needs a few things to know who you are and where to log activity. The first time you run any `ilml linkedin <command>`, the CLI will prompt you for the **required** fields. You can also pre-configure:
57
+
58
+ ```bash
59
+ ilml plugin config linkedin set LINKEDIN_NAME "Your Full Name"
60
+ ilml plugin config linkedin set NODE_EASY_APPLY_MAIN <node-id>
61
+ ilml plugin config linkedin set NODE_EASY_APPLY_ERRORS <node-id>
62
+ ```
63
+
64
+ To inspect (secret values are masked):
65
+
66
+ ```bash
67
+ ilml plugin config linkedin
68
+ ```
69
+
70
+ To change a value later or remove one:
71
+
72
+ ```bash
73
+ ilml plugin config linkedin set LINKEDIN_NAME "New Name"
74
+ ilml plugin config linkedin unset OPTIONAL_KEY
75
+ ilml plugin config linkedin reset # wipe all; will re-prompt next run
76
+ ```
77
+
78
+ ### Configuration fields
79
+
80
+ | Section | Field | Required | What it is |
81
+ |---|---|---|---|
82
+ | LinkedIn account | `LINKEDIN_NAME` | yes | Your full name **exactly** as it appears on LinkedIn (used to identify your own messages in threads). |
83
+ | | `LINKEDIN_LOGIN` | no | LinkedIn emailonly used for auto-fill during one-time login. |
84
+ | | `LINKEDIN_PASS` | no, secret | LinkedIn password — only used for auto-fill during one-time login. Stored locally on disk; never sent anywhere. |
85
+ | iLiveMyLife integration | `NODE_EASY_APPLY_MAIN` | yes | Node ID where job applications are tracked. See "Setting up your graph" below. |
86
+ | | `NODE_EASY_APPLY_ERRORS` | yes | Node ID where Easy Apply errors are logged. |
87
+ | | `NODE_RUN_REPORTS` | no | Node ID where end-of-session summaries are posted (enable notifications on it to get pings when long jobs finish). |
88
+ | Data storage | `DATA_DIR` | no | Absolute path to a directory for the local DB / cookies. **Recommended** — keeps data outside the plugin install folder so it survives plugin updates. |
89
+ | Apply bot | `City` | no | Default city for filters. Default: `Toronto`. |
90
+ | | `MAX_APPLY_FOR_RUN` | no | Stop after this many applications per run. Default: `50`. |
91
+ | | `LINKEDIN_SEARCH_URL` | no | Default LinkedIn jobs search URL — open LinkedIn Jobs, set your filters, then make sure **Easy Apply** is on. Copy the resulting URL from the address bar and paste it here. |
92
+ | Scouting | `LINKEDIN_SCOUT_URLS` | no | Comma-separated job search URLs to scan without applying. |
93
+ | Resume / CV | `CV_TEXT`, `RESUME_PDF_URL`, `RESUME_FILENAME` | no | CV snippet, public PDF URL, suggested filename. Used in messages to recruiters. |
94
+ | Funnel | `FUNNEL_USE_CUSTOM_MESSAGE` | no | Send a custom note with connection requests. Default: `false`. |
95
+ | | `FUNNEL_MAX_CONNECTIONS` | no | Cap connection requests per run. Default: `20`. |
96
+ | | `FUNNEL_MESSAGE` | no | Note text. Use `{name}` placeholder, e.g. `Hi {name}, I just applied for a role at your company`. |
97
+ | | `FUNNEL_EXCLUDE_LOCATIONS` | no | Comma-separated locations to skip. |
98
+
99
+ ## Setting up your graph
100
+
101
+ The Easy Apply bot uses iLiveMyLife's AI assistant (**Lifebot**) to answer custom application questions in your voice. Two graph nodes are required: a **main tracking node** with Lifebot enabled, and an **errors node** for failed applications.
102
+
103
+ 1. Open https://app.ilivemylife.io and create a node titled **"LinkedIn Easy Apply"** (or any name).
104
+ 2. Open the node's **settings** (right panel) and turn on **AI assistant**. This enables Lifebot for this node — without it, the bot can't answer questions and `ilml linkedin apply` will refuse to run.
105
+ 3. Copy the node ID from the URL: `https://app.ilivemylife.io/item/THIS-IS-THE-ID`.
106
+ 4. Set it: `ilml plugin config linkedin set NODE_EASY_APPLY_MAIN <id>`.
107
+ 5. In the node's **description**, write your answer rules — Lifebot reads this when filling forms. Example:
108
+
109
+ ```
110
+ Application question rules:
111
+ - My full name: Ivan Petrov
112
+ - City: Toronto, Ontario, Canada
113
+ - Phone: +1-416-xxx-xxxx
114
+ - Email: ivan@example.com
115
+ - Experience: Senior software engineer, 8 years
116
+ - Visa status: Permanent Resident, Canada
117
+ - Salary expectations: $120-150K CAD
118
+ - Notice period: 14 days
119
+ - Preferred work mode: hybrid or remote
120
+ ```
121
+
122
+ 6. (Optional but useful) Create child nodes inside "LinkedIn Easy Apply" with topical detail: `Resume`, `Tech stack`, `Interview availability`, etc. Lifebot reads the whole subtree and uses everything as context.
123
+
124
+ 7. Create a sibling node titled **"Easy Apply Errors"** (no AI needed). Copy its ID and set it: `ilml plugin config linkedin set NODE_EASY_APPLY_ERRORS <id>`.
125
+
126
+ ## First-time LinkedIn login
127
+
128
+ LinkedIn requires an authenticated session, so a one-time browser login is needed. Run:
129
+
130
+ ```bash
131
+ ilml linkedin login
132
+ ```
133
+
134
+ A real browser window opens. Sign in to LinkedIn (manually solve any captcha or 2FA). When you see your feed, close the window your session cookies are saved locally for future runs.
135
+
136
+ ## Daily commands
137
+
138
+ | Command | What it does |
139
+ |---|---|
140
+ | `ilml linkedin apply` | Auto-apply to LinkedIn Easy Apply jobs. Stops after `MAX_APPLY_FOR_RUN`. |
141
+ | `ilml linkedin sync` / `sync-all` | Pull the LinkedIn inbox into the local DB and the graph. |
142
+ | `ilml linkedin today` | Faster sync of just today's activity. |
143
+ | `ilml linkedin enrich` | Categorize and tag conversations. |
144
+ | `ilml linkedin report` | Summary of the latest session. |
145
+ | `ilml linkedin scout` | Scan jobs against `LINKEDIN_SCOUT_URLS` without applying. |
146
+ | `ilml linkedin messages` | Batch messaging — draft, review, then push. Nothing sends without your approval. |
147
+ | `ilml linkedin funnel` | Process a queue of recruiter / founder / investor profiles. |
148
+ | `ilml linkedin visit` | Track profile visits. |
149
+ | `ilml linkedin viewers` | List who viewed your profile. |
150
+ | `ilml linkedin daily` | Compound routine combining several commands. |
151
+ | `ilml linkedin login` | Re-save LinkedIn cookies after a session expires. |
152
+
153
+ Run `ilml linkedin` (no subcommand) to see the list anytime.
154
+
155
+ ## Updating
156
+
157
+ Updates ship via npm. The CLI checks the registry and only downloads when there's a newer version:
158
+
159
+ ```bash
160
+ ilml plugin update linkedin # check this plugin
161
+ ilml plugin update # check all installed plugins
162
+ ilml update # update the SDK and all plugins together
163
+ ```
164
+
165
+ You'll see one of:
166
+ - `linkedin: already on latest version (1.2.1)` nothing downloaded
167
+ - `linkedin: 1.2.1 1.3.0` followed by re-install newer version pulled
168
+
169
+ Your saved configuration is preserved across updates (it lives outside the install dir). If a new version requires a new field, the next run will prompt you for just the new field.
170
+
171
+ ## Where data lives
172
+
173
+ | Path | What's there | Survives plugin update? | Cleared by `ilml logout`? |
174
+ |---|---|---|---|
175
+ | `~/.ilivemylife/plugins/linkedin/` | Plugin code (re-extracted on update) | Replaced | No |
176
+ | `~/.ilivemylife/plugins-state/linkedin.json` (or per-project local) | Your configured values | Yes | Yes (with that scope) |
177
+ | Directory you set as `DATA_DIR` | Local DBs, cookies, scraped profiles | Yes | No (you manage it) |
178
+
179
+ If you didn't set `DATA_DIR`, data files default to inside the plugin's install dir meaning a plugin reinstall wipes them. Setting `DATA_DIR` to a sibling folder like `~/linkedin-plugin-data/` is strongly recommended.
180
+
181
+ ## Removing the plugin
182
+
183
+ ```bash
184
+ ilml plugin remove linkedin
185
+ ```
186
+
187
+ This wipes the install dir. To also clear your saved configuration in the active scope:
188
+
189
+ ```bash
190
+ ilml plugin config linkedin reset
191
+ ```
192
+
193
+ To clean up the data directory (cookies, DBs), delete the folder you set as `DATA_DIR` manually.
194
+
195
+ ## Feedback & support
196
+
197
+ Bug reports, feature requests, and general questions land in the plugin's **Support** node inside iLiveMyLife. Send a message there and we'll get back to you:
198
+
199
+ - In any iLiveMyLife app (web / mobile / desktop): open https://app.ilivemylife.io/item/0000019dde81b04f-2e534bb8ebad0000 and use the messenger panel
200
+ - From the terminal: `ilml send 0000019dde81b04f-2e534bb8ebad0000 "your message"`
201
+
202
+ ## Links
203
+
204
+ - This plugin on npm: https://www.npmjs.com/package/ilml-plugin-linkedin
205
+ - `ilml` CLI on npm: https://www.npmjs.com/package/@ilivemylife/graph-sdk
206
+ - iLiveMyLife: https://ilivemylife.io
207
+
208
+ ---
209
+
210
+ ## Author & contact
211
+
212
+ **[Ilya Sorokin](https://www.digitaltwins.team/team/ilya-sorokin)** — creator of [iLiveMyLife.io](https://ilivemylife.io) and this plugin.
213
+
214
+ - LinkedIn: [linkedin.com/in/ilyasorokin](https://www.linkedin.com/in/ilyasorokin/)
215
+ - Email: info@ilivemylife.io
216
+
217
+ ### Need a custom plugin or extension?
218
+
219
+ [**DigitalTwins.team**](https://www.digitaltwins.team/) — my consulting company — designs and builds custom automation, SDK extensions, and bespoke plugins for the iLiveMyLife ecosystem (and beyond). If you want to integrate your own workflow with iLiveMyLife, extend this plugin's behavior, or commission something new, get in touch.
package/ilml-plugin.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "linkedin",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "LinkedIn job automation: apply, scout, sync, funnel, messages",
5
5
  "commands": {
6
6
  "apply": { "run": "node dist/run.mjs" },
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "ilml-plugin-linkedin",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "ilml plugin: LinkedIn job automation — apply, scout, sync, funnel, messages",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist",
8
- "ilml-plugin.json"
8
+ "ilml-plugin.json",
9
+ "CHANGELOG.md"
9
10
  ],
10
11
  "scripts": {
11
12
  "build:plugin": "node scripts/build-plugin.mjs",