memex-mvp 0.7.0 → 0.9.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/HELP.md +52 -4
- package/README.md +26 -2
- package/README.ru.md +25 -2
- package/ingest.js +112 -2
- package/lib/cli/index.js +489 -2
- package/lib/hook/install.js +268 -0
- package/lib/parse-telegram-html.js +358 -0
- package/package.json +2 -2
- package/server.js +109 -4
- package/skills/install-memex/SKILL.md +46 -9
- package/skills/install-memex/examples.md +13 -13
package/HELP.md
CHANGED
|
@@ -301,6 +301,10 @@ Memex по дефолту сортирует по **релевантности**
|
|
|
301
301
|
memex search "Postgres миграция" # FTS5 поиск
|
|
302
302
|
memex search "Q2 deck" --chat "Memex Bot" # фильтр по title чата
|
|
303
303
|
memex search "auth" --source claude-code --limit 5 --sort date_desc
|
|
304
|
+
memex search "JWT" --as-of 2026-05-01 # time-travel (v0.8.1+) — только до даты
|
|
305
|
+
|
|
306
|
+
memex when "Brian Chesky" # «когда мы об этом говорили»
|
|
307
|
+
memex when "JWT decision" --limit 5 # → chronological list of chats, без snippets
|
|
304
308
|
|
|
305
309
|
memex recent --limit 5 # последние сообщения
|
|
306
310
|
memex recent --source telegram
|
|
@@ -310,7 +314,7 @@ memex list --source web # только сохранё
|
|
|
310
314
|
|
|
311
315
|
memex get web-1582ab51a7b7 # полный контент conversation
|
|
312
316
|
|
|
313
|
-
memex overview # snapshot корпуса
|
|
317
|
+
memex overview # snapshot корпуса (+ capture streak v0.8.1+)
|
|
314
318
|
memex projects # уникальные project_paths
|
|
315
319
|
memex help # эта инструкция в терминале
|
|
316
320
|
memex --help # справка по командам
|
|
@@ -338,6 +342,35 @@ memex get web-1582ab51a7b7 --json > backup.json
|
|
|
338
342
|
|
|
339
343
|
---
|
|
340
344
|
|
|
345
|
+
## 🪄 Auto-context (v0.8+) — Brian Chesky moment
|
|
346
|
+
|
|
347
|
+
Magic-фича. Когда ты открываешь Claude Code в проекте, Claude **сам** инжектит 500-1500 токенов контекста про этот проект — что ты делал недавно, какие conversations касались темы. Ты ещё ничего не спросил, а AI **уже знает**.
|
|
348
|
+
|
|
349
|
+
**Технически:** SessionStart hook в `~/.claude/settings.json`. При старте каждой Claude Code сессии хук вызывает `memex context` → memex выдаёт markdown summary → Claude получает его как system message _до_ твоего первого вопроса.
|
|
350
|
+
|
|
351
|
+
**Установка:** во время `memex-sync install` будет промпт `[Y/n]` — соглашайся (Y по default'у). Или установи позже:
|
|
352
|
+
|
|
353
|
+
```bash
|
|
354
|
+
memex hook install # добавить хук
|
|
355
|
+
memex hook uninstall # удалить (только memex-запись, другие хуки сохраняются)
|
|
356
|
+
memex hook status # узнать текущее состояние
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
**Посмотреть что будет инжектиться** (dry-run в текущей директории):
|
|
360
|
+
|
|
361
|
+
```bash
|
|
362
|
+
memex context # markdown как для хука
|
|
363
|
+
memex context --json # структурированный
|
|
364
|
+
memex context --no-source telegram # исключить telegram (privacy)
|
|
365
|
+
memex context --freshness-days 30 # только последние 30 дней
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
**Privacy:** хук ничего не отправляет наружу — это локальная инъекция в локальную Claude-сессию. Но в context могут попасть фрагменты из любых indexed sources (включая Telegram). Чтобы исключить — добавь `--no-source telegram` в команду хука (правится в `~/.claude/settings.json`).
|
|
369
|
+
|
|
370
|
+
**Где это пока не работает:** Cursor, Cline, Continue, Zed — у них нет native SessionStart hook'а. Fallback через MCP-tool — в roadmap v0.9.0. Сейчас auto-context работает только в **Claude Code и OpenClaw**.
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
341
374
|
## Если что-то не работает
|
|
342
375
|
|
|
343
376
|
### Поиск пустой
|
|
@@ -357,9 +390,24 @@ npx memex-sync scan
|
|
|
357
390
|
|
|
358
391
|
### Telegram-чаты не появляются
|
|
359
392
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
393
|
+
В Telegram **Desktop** (не mobile!): чат → меню (⋮ или ☰) → **Export chat history**.
|
|
394
|
+
|
|
395
|
+
**memex поддерживает оба формата экспорта (v0.9+):**
|
|
396
|
+
|
|
397
|
+
- **«Machine-readable JSON»** ← рекомендуется. Один файл `result.json`, чисто ингестится.
|
|
398
|
+
- **«HTML»** ← тоже работает (с v0.9+). Получишь директорию `ChatExport_<chat>_<date>/` — кинь её **целиком** в inbox, memex авто-парсит.
|
|
399
|
+
|
|
400
|
+
Шаги:
|
|
401
|
+
1. Выбери формат (JSON — короче путь, HTML — если уже экспортировано).
|
|
402
|
+
2. Сохрани в **`~/.memex/inbox/`** — для JSON это `result.json`, для HTML — вся директория `ChatExport_…`.
|
|
403
|
+
3. Memex подхватит автоматически за ~1.5 секунды. Файл/директория уедет в `~/.memex/data/conversations/telegram/` (или `…/telegram-html/`) после ingest'a.
|
|
404
|
+
|
|
405
|
+
Если ингест не произошёл — проверь `~/.memex/data/memex.log`. Для HTML-export'а парсер пишет actionable error если что-то не так (формат изменился у Telegram, директория повреждена, и т.д.).
|
|
406
|
+
|
|
407
|
+
**Что НЕ работает:**
|
|
408
|
+
- ❌ Мобильный экспорт (Telegram mobile не экспортирует структурированно)
|
|
409
|
+
- ❌ Скриншоты чатов
|
|
410
|
+
- ❌ Только-медиа чаты (без текста парсятся как `[photo]`/`[voice]` placeholders, но без content)
|
|
363
411
|
|
|
364
412
|
### Хочу подключить новый Obsidian-vault
|
|
365
413
|
|
package/README.md
CHANGED
|
@@ -107,10 +107,12 @@ The same `memex` binary that runs as an MCP server also has a terminal mode for
|
|
|
107
107
|
```sh
|
|
108
108
|
memex search "Postgres migration" # full-text search
|
|
109
109
|
memex search "Q2 deck" --chat "Memex Bot" # scope to one conversation by title
|
|
110
|
+
memex search "JWT" --as-of 2026-05-01 # v0.8.1: time-travel — only msgs before date
|
|
111
|
+
memex when "Brian Chesky" # v0.8.1: "when did we talk about X" — dates + chats
|
|
110
112
|
memex recent --limit 5 # last 5 messages across all sources
|
|
111
113
|
memex list --source web # all saved URLs
|
|
112
114
|
memex get web-1582ab51a7b7 # full content of one conversation
|
|
113
|
-
memex overview # snapshot of corpus
|
|
115
|
+
memex overview # snapshot of corpus + v0.8.1: capture streak
|
|
114
116
|
memex projects # distinct project_paths captured
|
|
115
117
|
memex help # full user guide (HELP.md)
|
|
116
118
|
memex --help # command reference
|
|
@@ -122,6 +124,28 @@ When called **without arguments** (`memex`), the binary still runs as an MCP std
|
|
|
122
124
|
|
|
123
125
|
---
|
|
124
126
|
|
|
127
|
+
## Auto-context (v0.8+) — Claude already knows what you were doing
|
|
128
|
+
|
|
129
|
+
After `memex-sync install`, you're prompted to enable **auto-context**. When yes, memex adds a SessionStart hook to `~/.claude/settings.json` so that **every time you open Claude Code in a project**, Claude gets injected with ~500-1500 tokens of relevant context — what you did recently in this project, which conversations touched it, which related topics came up. No prompts. No tool calls. Just memory.
|
|
130
|
+
|
|
131
|
+
```sh
|
|
132
|
+
# Adding/removing the hook outside the install flow:
|
|
133
|
+
memex hook install # add SessionStart hook (idempotent)
|
|
134
|
+
memex hook uninstall # remove only the memex entry, preserves other hooks
|
|
135
|
+
memex hook status # show current state
|
|
136
|
+
|
|
137
|
+
# Inspecting what gets injected:
|
|
138
|
+
memex context # dry-run the hook output for the current dir
|
|
139
|
+
memex context --pwd /path # for a different project
|
|
140
|
+
memex context --no-source telegram # exclude a source
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
The hook respects existing hooks (e.g. `gstack`, custom user hooks) — they're preserved untouched.
|
|
144
|
+
|
|
145
|
+
**Currently only Claude Code has native SessionStart hooks.** For Cursor / Cline / Continue / Zed, MCP-tool-based fallback is on the v0.9.0 roadmap.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
125
149
|
## Save URLs into memex (v0.6+)
|
|
126
150
|
|
|
127
151
|
Once memex is installed, any MCP-aware agent can also save **web pages, AI chat shares, and pasted text** into your memex memory — searchable from any other AI chat later. In Claude Code, Cursor, Cline, …:
|
|
@@ -148,7 +172,7 @@ Perplexity threads need to be made **Public** in the Share dialog first — meme
|
|
|
148
172
|
| Cursor IDE chats | Auto: reads Cursor's local SQLite session store |
|
|
149
173
|
| Continue / Zed | Auto: filesystem watchers per platform |
|
|
150
174
|
| Obsidian notes | Auto: per-vault markdown watcher |
|
|
151
|
-
| Telegram exports | Manual: drop `result.json` (Telegram Desktop) into `~/.memex/inbox
|
|
175
|
+
| Telegram exports | Manual: drop `result.json` (Telegram Desktop → Export → JSON) into `~/.memex/inbox/`. v0.9+: also accepts the **HTML** export directory (`ChatExport_*/`) — drop the whole folder, memex parses it. |
|
|
152
176
|
| Telegram (live) | Run [`memex-bot`](bot/README.md) — captures messages you send/forward to your private bot |
|
|
153
177
|
| **Web pages, AI chat shares, pasted text** | From any MCP agent: *"save https://... to memex"*. Agent fetches; memex stores verbatim. Cloudflare-protected pages (Perplexity, npm.com, Twitter, Medium, …) handled via the agent's r.jina.ai fallback. See [HELP.md §8](HELP.md) |
|
|
154
178
|
|
package/README.ru.md
CHANGED
|
@@ -143,10 +143,12 @@ curl -fsSL https://raw.githubusercontent.com/parallelclaw/memex-mvp/main/skills/
|
|
|
143
143
|
```bash
|
|
144
144
|
memex search "Postgres миграция" # полнотекстовый поиск
|
|
145
145
|
memex search "Q2 deck" --chat "Memex Bot" # сузить до конкретного чата по title
|
|
146
|
+
memex search "JWT" --as-of 2026-05-01 # v0.8.1: time-travel — только до даты
|
|
147
|
+
memex when "Brian Chesky" # v0.8.1: «когда мы это обсуждали» — даты + чаты
|
|
146
148
|
memex recent --limit 5 # последние 5 сообщений из всех источников
|
|
147
149
|
memex list --source web # все сохранённые URL'ы
|
|
148
150
|
memex get web-1582ab51a7b7 # полный контент одной conversation
|
|
149
|
-
memex overview # snapshot корпуса
|
|
151
|
+
memex overview # snapshot корпуса + v0.8.1: capture streak
|
|
150
152
|
memex projects # уникальные project_paths
|
|
151
153
|
memex help # полное руководство (HELP.md)
|
|
152
154
|
memex --help # справка по командам
|
|
@@ -162,6 +164,26 @@ memex --help # справка по команд
|
|
|
162
164
|
- Хочешь пайпить результаты: `memex search foo --json | jq ...`
|
|
163
165
|
- Хочешь сдампить полный transcript в stdout для context'a
|
|
164
166
|
|
|
167
|
+
### Auto-context (v0.8+) — Claude уже знает что ты делал
|
|
168
|
+
|
|
169
|
+
После `memex-sync install` появляется промпт про **auto-context**. Если согласишься — memex добавит SessionStart хук в `~/.claude/settings.json`. Когда ты потом открываешь Claude Code в каком-то проекте, Claude **сам подгружает 500-1500 токенов контекста** про этот проект — что ты делал недавно, какие conversations его касались, какие связанные темы всплывали. Никаких вопросов, никаких tool-call'ов, просто Claude **знает**.
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
# Добавить/удалить хук вне install-flow:
|
|
173
|
+
memex hook install # добавить SessionStart хук (idempotent)
|
|
174
|
+
memex hook uninstall # удалить только memex-запись, остальные хуки не трогает
|
|
175
|
+
memex hook status # показать текущее состояние
|
|
176
|
+
|
|
177
|
+
# Посмотреть что будет инжектиться:
|
|
178
|
+
memex context # dry-run для текущей директории
|
|
179
|
+
memex context --pwd /path # для другого проекта
|
|
180
|
+
memex context --no-source telegram # исключить источник
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Хук **сохраняет существующие хуки** (gstack, твои кастомные) — добавляет только свою запись.
|
|
184
|
+
|
|
185
|
+
**Сейчас native SessionStart есть только в Claude Code.** Для Cursor / Cline / Continue / Zed fallback через MCP-tool — в roadmap v0.9.0.
|
|
186
|
+
|
|
165
187
|
### Подключение к Claude Code
|
|
166
188
|
|
|
167
189
|
Сначала возьми **два абсолютных пути** в терминале:
|
|
@@ -202,7 +224,8 @@ which node # → путь до бинарника node (например /Users
|
|
|
202
224
|
| **Claude Cowork** | `cowork-*.jsonl` (через filename prefix), включая subagents | ✅ работает |
|
|
203
225
|
| **Cursor IDE** (Composer + Chat) | SQLite `state.vscdb` в `~/Library/Application Support/Cursor/` | ✅ работает (poll каждые 5 мин) |
|
|
204
226
|
| **Obsidian** vault notes | `.md` файлы + YAML frontmatter | ✅ работает (FSEvents, hash-based dedupe) |
|
|
205
|
-
| **Telegram** | `result.json` из Desktop export | ✅ работает |
|
|
227
|
+
| **Telegram (JSON export)** | `result.json` из Desktop export | ✅ работает |
|
|
228
|
+
| **Telegram (HTML export)** | директория `ChatExport_*` из Desktop (v0.9+) | ✅ работает — кидай всю папку в inbox |
|
|
206
229
|
| **Telegram (live)** | бот `memex-bot` ловит твои сообщения / форварды | ✅ работает |
|
|
207
230
|
| **Web-страницы, AI-share'ы, paste'ы** | `memex_store_document` — агент fetch'ит, memex хранит verbatim (v0.6+) | ✅ работает |
|
|
208
231
|
| Claude.ai web export | будет в v0.7 | — |
|
package/ingest.js
CHANGED
|
@@ -61,6 +61,8 @@ import {
|
|
|
61
61
|
vaultSlug,
|
|
62
62
|
shouldSkipPath,
|
|
63
63
|
} from './lib/parse-obsidian.js';
|
|
64
|
+
import { installHook as installSessionStartHook } from './lib/hook/install.js';
|
|
65
|
+
import { createInterface } from 'node:readline';
|
|
64
66
|
import {
|
|
65
67
|
CONFIG_PATH,
|
|
66
68
|
KNOWN_SOURCES,
|
|
@@ -137,7 +139,12 @@ if (subcommand && subcommand !== '--help' && subcommand.startsWith('-') === fals
|
|
|
137
139
|
console.error(`usage: memex-sync [install|uninstall|status|logs|serve]`);
|
|
138
140
|
process.exit(2);
|
|
139
141
|
}
|
|
140
|
-
|
|
142
|
+
// Handlers may be sync (most) or async (cmdInstall after v0.8 — needs readline
|
|
143
|
+
// for the auto-context prompt). Promise.resolve() normalises both.
|
|
144
|
+
Promise.resolve(handler()).catch((e) => {
|
|
145
|
+
console.error(`error in ${subcommand}: ${e.stack || e.message}`);
|
|
146
|
+
process.exit(1);
|
|
147
|
+
});
|
|
141
148
|
// CLI handlers either exit themselves or fall through to daemon mode (cmdServe)
|
|
142
149
|
} else if (subcommand === '--help' || subcommand === '-h') {
|
|
143
150
|
console.log(`memex-sync — auto-capture daemon for memex memory
|
|
@@ -185,7 +192,7 @@ paths:
|
|
|
185
192
|
|
|
186
193
|
// -------------------- CLI command handlers --------------------
|
|
187
194
|
|
|
188
|
-
function cmdInstall() {
|
|
195
|
+
async function cmdInstall() {
|
|
189
196
|
if (platform() !== 'darwin') {
|
|
190
197
|
console.error('install: macOS-only for now (LaunchAgent). Linux systemd-user support pending.');
|
|
191
198
|
console.error('on Linux you can run: nohup memex-sync &');
|
|
@@ -243,6 +250,18 @@ function cmdInstall() {
|
|
|
243
250
|
console.log(` log: ${LOG_PATH}`);
|
|
244
251
|
console.log('');
|
|
245
252
|
|
|
253
|
+
// ── Auto-context prompt (v0.8+) ─────────────────────────────────────
|
|
254
|
+
// Bundle Claude Code SessionStart hook install into the same flow
|
|
255
|
+
// the user is already running. Single [Y/n] beats a separate command
|
|
256
|
+
// they'd never remember.
|
|
257
|
+
//
|
|
258
|
+
// Honor non-interactive flags / env for CI:
|
|
259
|
+
// --auto-context yes explicit opt-in
|
|
260
|
+
// --auto-context no explicit opt-out
|
|
261
|
+
// --yes / -y accept all defaults (yes)
|
|
262
|
+
// $MEMEX_AUTO_CONTEXT=yes|no env override
|
|
263
|
+
await maybeInstallAutoContextHook();
|
|
264
|
+
|
|
246
265
|
// Show what daemon will actually capture, based on current config.
|
|
247
266
|
const cfg = loadConfig();
|
|
248
267
|
console.log('memex-sync will capture from these sources:');
|
|
@@ -277,6 +296,97 @@ function cmdInstall() {
|
|
|
277
296
|
process.exit(0);
|
|
278
297
|
}
|
|
279
298
|
|
|
299
|
+
// ──────────────────────────────────────────────────────────────────
|
|
300
|
+
// Auto-context hook prompt — bundled into `memex-sync install` so the
|
|
301
|
+
// user doesn't need to remember an extra `memex hook install` step.
|
|
302
|
+
//
|
|
303
|
+
// Decision priority:
|
|
304
|
+
// 1. CLI flag --auto-context=yes|no (explicit)
|
|
305
|
+
// 2. CLI flag --yes / -y (accept all defaults: yes)
|
|
306
|
+
// 3. env MEMEX_AUTO_CONTEXT=yes|no (for CI / scripts)
|
|
307
|
+
// 4. Interactive [Y/n] prompt (TTY only)
|
|
308
|
+
// 5. Default: SKIP if no TTY (don't hang on stdin in non-TTY contexts)
|
|
309
|
+
async function maybeInstallAutoContextHook() {
|
|
310
|
+
const argv = process.argv.slice(3); // drop ["node", "ingest.js", "install"]
|
|
311
|
+
|
|
312
|
+
// Parse flags
|
|
313
|
+
let explicit = null; // 'yes' | 'no' | null
|
|
314
|
+
for (let i = 0; i < argv.length; i++) {
|
|
315
|
+
const a = argv[i];
|
|
316
|
+
if (a === '--auto-context') {
|
|
317
|
+
const v = (argv[++i] || '').toLowerCase();
|
|
318
|
+
if (v === 'yes' || v === 'y' || v === 'true') explicit = 'yes';
|
|
319
|
+
else if (v === 'no' || v === 'n' || v === 'false') explicit = 'no';
|
|
320
|
+
} else if (a === '--auto-context=yes') explicit = 'yes';
|
|
321
|
+
else if (a === '--auto-context=no') explicit = 'no';
|
|
322
|
+
else if (a === '--yes' || a === '-y') explicit = 'yes';
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Env fallback
|
|
326
|
+
if (explicit === null) {
|
|
327
|
+
const env = (process.env.MEMEX_AUTO_CONTEXT || '').toLowerCase();
|
|
328
|
+
if (env === 'yes' || env === 'y' || env === 'true' || env === '1') explicit = 'yes';
|
|
329
|
+
else if (env === 'no' || env === 'n' || env === 'false' || env === '0') explicit = 'no';
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Interactive prompt as last resort
|
|
333
|
+
if (explicit === null) {
|
|
334
|
+
if (!process.stdin.isTTY) {
|
|
335
|
+
// Non-interactive (CI, scripts, install-skill flows that don't pipe stdin):
|
|
336
|
+
// skip silently. User can run `memex hook install` later.
|
|
337
|
+
console.log('Auto-context hook: skipped (non-interactive). Enable with: memex hook install');
|
|
338
|
+
console.log('');
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
explicit = await promptYesNo(
|
|
342
|
+
`Auto-context (Brian Chesky mode):\n` +
|
|
343
|
+
` When you open Claude Code in a project, memex can inject 500-1500 tokens\n` +
|
|
344
|
+
` of relevant context so Claude knows what you were doing — without you\n` +
|
|
345
|
+
` having to ask. Adds a SessionStart hook to ~/.claude/settings.json.\n` +
|
|
346
|
+
` Other hooks (e.g. gstack) are preserved.\n\n` +
|
|
347
|
+
` Enable?`,
|
|
348
|
+
'yes' // default Y
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
if (explicit !== 'yes') {
|
|
353
|
+
console.log('Auto-context hook: skipped. Enable later with: memex hook install');
|
|
354
|
+
console.log('');
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const r = installSessionStartHook();
|
|
359
|
+
if (r.error) {
|
|
360
|
+
console.log(`Auto-context hook: ✗ ${r.error}`);
|
|
361
|
+
console.log(' (memex-sync daemon still works — only the auto-context hook failed)');
|
|
362
|
+
console.log('');
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
if (r.alreadyPresent) {
|
|
366
|
+
console.log('Auto-context hook: already installed (no-op).');
|
|
367
|
+
} else {
|
|
368
|
+
console.log('Auto-context hook: ✓ installed.');
|
|
369
|
+
console.log(` settings: ${r.settingsPath}`);
|
|
370
|
+
console.log(` command: ${r.command}`);
|
|
371
|
+
console.log(' Restart Claude Code (Cmd+Q + reopen) to activate.');
|
|
372
|
+
}
|
|
373
|
+
console.log('');
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function promptYesNo(question, defaultAnswer) {
|
|
377
|
+
return new Promise((resolve) => {
|
|
378
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
379
|
+
const suffix = defaultAnswer === 'yes' ? ' [Y/n] ' : ' [y/N] ';
|
|
380
|
+
rl.question(question + suffix, (answer) => {
|
|
381
|
+
rl.close();
|
|
382
|
+
const v = (answer || '').trim().toLowerCase();
|
|
383
|
+
if (v === 'y' || v === 'yes') resolve('yes');
|
|
384
|
+
else if (v === 'n' || v === 'no') resolve('no');
|
|
385
|
+
else resolve(defaultAnswer); // empty enter → default
|
|
386
|
+
});
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
|
|
280
390
|
function cmdUninstall() {
|
|
281
391
|
if (platform() !== 'darwin') {
|
|
282
392
|
console.error('uninstall: macOS-only for now.');
|