inboxd 1.1.0 → 1.2.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/.claude/skills/inbox-assistant/SKILL.md +85 -85
- package/CLAUDE.md +41 -41
- package/README.md +32 -32
- package/package.json +3 -3
- package/scripts/postinstall.js +5 -5
- package/src/cli.js +29 -30
- package/src/gmail-auth.js +1 -1
- package/tests/filter.test.js +1 -1
- package/tests/json-output.test.js +4 -4
- package/tests/older-than.test.js +1 -1
- package/tests/setup.test.js +1 -1
|
@@ -113,7 +113,7 @@ When a user has a heavy inbox (>20 unread emails), use this optimized workflow:
|
|
|
113
113
|
### 1. Quick Assessment
|
|
114
114
|
|
|
115
115
|
```bash
|
|
116
|
-
|
|
116
|
+
inboxd summary --json
|
|
117
117
|
```
|
|
118
118
|
|
|
119
119
|
Identify which account(s) have the bulk of unread emails.
|
|
@@ -123,7 +123,7 @@ Identify which account(s) have the bulk of unread emails.
|
|
|
123
123
|
For heavy inboxes, **always start with grouped analysis**:
|
|
124
124
|
|
|
125
125
|
```bash
|
|
126
|
-
|
|
126
|
+
inboxd analyze --count 100 --account <name> --group-by sender
|
|
127
127
|
```
|
|
128
128
|
|
|
129
129
|
This reveals:
|
|
@@ -163,7 +163,7 @@ Delete all LinkedIn job alerts and old newsletters?
|
|
|
163
163
|
For cleanup of old emails, use server-side filtering:
|
|
164
164
|
|
|
165
165
|
```bash
|
|
166
|
-
|
|
166
|
+
inboxd analyze --older-than 30d --group-by sender
|
|
167
167
|
```
|
|
168
168
|
|
|
169
169
|
Old emails (>30 days) are usually safe to batch delete:
|
|
@@ -198,15 +198,15 @@ Unread count?
|
|
|
198
198
|
|
|
199
199
|
| Task | Command |
|
|
200
200
|
|------|---------|
|
|
201
|
-
| Check status | `
|
|
202
|
-
| Full triage | `
|
|
203
|
-
| Analyze by sender | `
|
|
204
|
-
| Find old emails | `
|
|
205
|
-
| Extract links from email | `
|
|
206
|
-
| Delete by ID | `
|
|
207
|
-
| Delete by sender | `
|
|
208
|
-
| Delete by subject | `
|
|
209
|
-
| Undo deletion | `
|
|
201
|
+
| Check status | `inboxd summary --json` |
|
|
202
|
+
| Full triage | `inboxd analyze --count 50` → classify → present |
|
|
203
|
+
| Analyze by sender | `inboxd analyze --count 50 --group-by sender` |
|
|
204
|
+
| Find old emails | `inboxd analyze --older-than 30d` |
|
|
205
|
+
| Extract links from email | `inboxd read --id <id> --links` |
|
|
206
|
+
| Delete by ID | `inboxd delete --ids "id1,id2" --confirm` |
|
|
207
|
+
| Delete by sender | `inboxd delete --sender "linkedin" --dry-run` → confirm → delete |
|
|
208
|
+
| Delete by subject | `inboxd delete --match "weekly digest" --dry-run` |
|
|
209
|
+
| Undo deletion | `inboxd restore --last N` |
|
|
210
210
|
|
|
211
211
|
## Package Information
|
|
212
212
|
|
|
@@ -214,7 +214,7 @@ Unread count?
|
|
|
214
214
|
|---|---|
|
|
215
215
|
| **Package** | `inboxd` |
|
|
216
216
|
| **Install** | `npm install -g inboxd` |
|
|
217
|
-
| **Setup** | `
|
|
217
|
+
| **Setup** | `inboxd setup` (interactive wizard) |
|
|
218
218
|
| **Documentation** | https://github.com/dparedesi/inboxd |
|
|
219
219
|
| **npm** | https://www.npmjs.com/package/inboxd |
|
|
220
220
|
|
|
@@ -224,10 +224,10 @@ Before any inbox operation, always verify the setup:
|
|
|
224
224
|
|
|
225
225
|
```bash
|
|
226
226
|
# 1. Check if inboxd is installed
|
|
227
|
-
|
|
227
|
+
inboxd --version
|
|
228
228
|
|
|
229
229
|
# 2. Check if accounts are configured
|
|
230
|
-
|
|
230
|
+
inboxd accounts
|
|
231
231
|
```
|
|
232
232
|
|
|
233
233
|
## Account Management
|
|
@@ -235,24 +235,24 @@ inbox accounts
|
|
|
235
235
|
### Adding New Accounts
|
|
236
236
|
If the user wants to add an account (e.g. "add my work email"):
|
|
237
237
|
```bash
|
|
238
|
-
|
|
239
|
-
# Example:
|
|
238
|
+
inboxd auth -a <name>
|
|
239
|
+
# Example: inboxd auth -a work
|
|
240
240
|
```
|
|
241
241
|
|
|
242
242
|
### Listing Accounts
|
|
243
243
|
```bash
|
|
244
|
-
|
|
244
|
+
inboxd accounts
|
|
245
245
|
```
|
|
246
246
|
|
|
247
247
|
### Removing Accounts
|
|
248
248
|
```bash
|
|
249
|
-
|
|
250
|
-
|
|
249
|
+
inboxd logout -a <name> # Remove specific account
|
|
250
|
+
inboxd logout --all # Remove all accounts
|
|
251
251
|
```
|
|
252
252
|
|
|
253
253
|
### Re-authenticating (Token Expired)
|
|
254
254
|
```bash
|
|
255
|
-
rm ~/.config/inboxd/token-<account>.json &&
|
|
255
|
+
rm ~/.config/inboxd/token-<account>.json && inboxd auth -a <account>
|
|
256
256
|
```
|
|
257
257
|
|
|
258
258
|
### If Not Installed
|
|
@@ -264,7 +264,7 @@ rm ~/.config/inboxd/token-<account>.json && inbox auth -a <account>
|
|
|
264
264
|
inboxd is not installed. To install:
|
|
265
265
|
|
|
266
266
|
1. Run: npm install -g inboxd
|
|
267
|
-
2. Run:
|
|
267
|
+
2. Run: inboxd setup
|
|
268
268
|
3. Follow the wizard to configure your Gmail account
|
|
269
269
|
|
|
270
270
|
The setup requires creating OAuth credentials in Google Cloud Console.
|
|
@@ -272,7 +272,7 @@ The setup requires creating OAuth credentials in Google Cloud Console.
|
|
|
272
272
|
|
|
273
273
|
### If No Accounts Configured
|
|
274
274
|
```
|
|
275
|
-
No Gmail accounts configured. Run:
|
|
275
|
+
No Gmail accounts configured. Run: inboxd setup
|
|
276
276
|
|
|
277
277
|
This will guide you through:
|
|
278
278
|
1. Creating OAuth credentials in Google Cloud Console
|
|
@@ -284,9 +284,9 @@ This will guide you through:
|
|
|
284
284
|
Users can enable automatic inbox checking with notifications:
|
|
285
285
|
|
|
286
286
|
```bash
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
287
|
+
inboxd install-service # Check every 5 minutes
|
|
288
|
+
inboxd install-service --interval 10 # Check every 10 minutes
|
|
289
|
+
inboxd install-service --uninstall # Remove service
|
|
290
290
|
```
|
|
291
291
|
|
|
292
292
|
This installs and starts a background service that:
|
|
@@ -304,43 +304,43 @@ This installs and starts a background service that:
|
|
|
304
304
|
|
|
305
305
|
| Command | Description | Output |
|
|
306
306
|
|---------|-------------|--------|
|
|
307
|
-
| `
|
|
308
|
-
| `
|
|
309
|
-
| `
|
|
310
|
-
| `
|
|
311
|
-
| `
|
|
312
|
-
| `
|
|
313
|
-
| `
|
|
314
|
-
| `
|
|
315
|
-
| `
|
|
316
|
-
| `
|
|
317
|
-
| `
|
|
307
|
+
| `inboxd summary --json` | Quick inbox overview | `{accounts: [{name, email, unreadCount}], totalUnread}` |
|
|
308
|
+
| `inboxd analyze --count 50` | Get email data for analysis | JSON array of email objects |
|
|
309
|
+
| `inboxd analyze --count 50 --all` | Include read emails | JSON array (read + unread) |
|
|
310
|
+
| `inboxd analyze --since 7d` | Only emails from last 7 days | JSON array (filtered by date) |
|
|
311
|
+
| `inboxd analyze --older-than 30d` | Only emails older than 30 days | JSON array (server-side filtered) |
|
|
312
|
+
| `inboxd analyze --group-by sender` | Group emails by sender domain | `{groups: [{sender, count, emails}], totalCount}` |
|
|
313
|
+
| `inboxd read --id <id>` | Read full email content | Email headers + body |
|
|
314
|
+
| `inboxd read --id <id> --links` | Extract links from email | List of URLs with optional link text |
|
|
315
|
+
| `inboxd read --id <id> --links --json` | Extract links as JSON | `{id, subject, from, linkCount, links}` |
|
|
316
|
+
| `inboxd search -q "query"` | Search using Gmail query syntax | JSON array of matching emails |
|
|
317
|
+
| `inboxd accounts` | List configured accounts | Account names and emails |
|
|
318
318
|
|
|
319
319
|
### Actions
|
|
320
320
|
|
|
321
321
|
| Command | Description |
|
|
322
322
|
|---------|-------------|
|
|
323
|
-
| `
|
|
324
|
-
| `
|
|
325
|
-
| `
|
|
326
|
-
| `
|
|
327
|
-
| `
|
|
328
|
-
| `
|
|
329
|
-
| `
|
|
330
|
-
| `
|
|
331
|
-
| `
|
|
332
|
-
| `
|
|
333
|
-
| `
|
|
334
|
-
| `
|
|
335
|
-
| `
|
|
336
|
-
| `
|
|
337
|
-
| `
|
|
338
|
-
| `
|
|
339
|
-
| `
|
|
340
|
-
| `
|
|
341
|
-
| `
|
|
342
|
-
| `
|
|
343
|
-
| `
|
|
323
|
+
| `inboxd delete --ids "id1,id2,id3" --confirm` | Move emails to trash by ID |
|
|
324
|
+
| `inboxd delete --sender "pattern" --dry-run` | Preview deletion by sender filter |
|
|
325
|
+
| `inboxd delete --match "pattern" --dry-run` | Preview deletion by subject filter |
|
|
326
|
+
| `inboxd delete --sender "X" --match "Y" --confirm` | Delete by combined filters (AND) |
|
|
327
|
+
| `inboxd delete --sender "X" --limit 100 --confirm` | Override 50-email safety limit |
|
|
328
|
+
| `inboxd delete --sender "ab" --force --confirm` | Override short-pattern warning |
|
|
329
|
+
| `inboxd restore --last N` | Restore last N deleted emails |
|
|
330
|
+
| `inboxd restore --ids "id1,id2"` | Restore specific emails |
|
|
331
|
+
| `inboxd mark-read --ids "id1,id2"` | Mark emails as read (remove UNREAD label) |
|
|
332
|
+
| `inboxd mark-unread --ids "id1,id2"` | Mark emails as unread (add UNREAD label) |
|
|
333
|
+
| `inboxd archive --ids "id1,id2" --confirm` | Archive emails (remove from inbox, keep in All Mail) |
|
|
334
|
+
| `inboxd unarchive --last N` | Undo last N archived emails |
|
|
335
|
+
| `inboxd unarchive --ids "id1,id2"` | Unarchive specific emails |
|
|
336
|
+
| `inboxd stats` | Show email activity dashboard (deletions, sent counts) |
|
|
337
|
+
| `inboxd stats --days 7 --json` | Get stats as JSON for custom period |
|
|
338
|
+
| `inboxd cleanup-suggest` | Get smart cleanup suggestions based on deletion patterns |
|
|
339
|
+
| `inboxd deletion-log` | View recent deletions |
|
|
340
|
+
| `inboxd deletion-log --json` | Get deletion log as JSON |
|
|
341
|
+
| `inboxd accounts --json` | List accounts as JSON |
|
|
342
|
+
| `inboxd delete --dry-run --json` | Preview deletion as structured JSON |
|
|
343
|
+
| `inboxd restore --json` | Get restore results as JSON |
|
|
344
344
|
|
|
345
345
|
### Smart Filtering Options
|
|
346
346
|
|
|
@@ -405,7 +405,7 @@ You have 5 emails from LinkedIn. Delete them all?
|
|
|
405
405
|
|
|
406
406
|
### 1. Check Inbox Status
|
|
407
407
|
```bash
|
|
408
|
-
|
|
408
|
+
inboxd summary --json
|
|
409
409
|
```
|
|
410
410
|
Report the total unread count and per-account breakdown.
|
|
411
411
|
|
|
@@ -443,7 +443,7 @@ Want me to triage that first?
|
|
|
443
443
|
|
|
444
444
|
### 3. Fetch Emails for Analysis
|
|
445
445
|
```bash
|
|
446
|
-
|
|
446
|
+
inboxd analyze --count 50 --account <name>
|
|
447
447
|
```
|
|
448
448
|
Parse the JSON output and classify each email.
|
|
449
449
|
|
|
@@ -545,7 +545,7 @@ Confirm deletion? (y/n)
|
|
|
545
545
|
|
|
546
546
|
Only after explicit user confirmation:
|
|
547
547
|
```bash
|
|
548
|
-
|
|
548
|
+
inboxd delete --ids "id1,id2,id3,..." --account <name> --confirm
|
|
549
549
|
```
|
|
550
550
|
|
|
551
551
|
### 8. Confirm & Remind About Undo
|
|
@@ -554,7 +554,7 @@ After deletion:
|
|
|
554
554
|
```
|
|
555
555
|
Deleted 8 emails.
|
|
556
556
|
|
|
557
|
-
To undo: `
|
|
557
|
+
To undo: `inboxd restore --last 8`
|
|
558
558
|
```
|
|
559
559
|
|
|
560
560
|
---
|
|
@@ -598,14 +598,14 @@ When user has job-related emails (LinkedIn, Indeed, recruiters) and wants to eva
|
|
|
598
598
|
| "Delete all from [sender]" | Bulk sender cleanup | `--sender "X" --dry-run` → confirm → `--ids` |
|
|
599
599
|
| "Delete [sender]'s emails" | Bulk sender cleanup | Two-step pattern with `--sender` filter |
|
|
600
600
|
| "Delete the security emails" | Subject-based cleanup | `--match "security" --dry-run` → confirm → `--ids` |
|
|
601
|
-
| "What senders have the most emails?" | Inbox analysis | `
|
|
602
|
-
| "Show my email stats" | Activity summary | `
|
|
603
|
-
| "What should I clean up?" | Pattern analysis | `
|
|
604
|
-
| "What links are in this email?" | Extract URLs | `
|
|
605
|
-
| "Find my old emails" / "Clean up old stuff" | Stale email review | `
|
|
601
|
+
| "What senders have the most emails?" | Inbox analysis | `inboxd analyze --group-by sender` |
|
|
602
|
+
| "Show my email stats" | Activity summary | `inboxd stats` |
|
|
603
|
+
| "What should I clean up?" | Pattern analysis | `inboxd cleanup-suggest` |
|
|
604
|
+
| "What links are in this email?" | Extract URLs | `inboxd read --id <id> --links` |
|
|
605
|
+
| "Find my old emails" / "Clean up old stuff" | Stale email review | `inboxd analyze --older-than 30d` |
|
|
606
606
|
| "I keep getting these" | Recurring annoyance | Suggest unsubscribe/filter, then delete batch |
|
|
607
607
|
| "Check [specific account]" | Single-account focus | Skip other accounts entirely |
|
|
608
|
-
| "Undo" / "Restore" | Recover deleted emails | `
|
|
608
|
+
| "Undo" / "Restore" | Recover deleted emails | `inboxd restore --last N` |
|
|
609
609
|
| "What are these companies?" | Research job/opportunity emails | Fetch websites, assess legitimacy |
|
|
610
610
|
| "Research these job opportunities" | Job alert evaluation | Job Research workflow (see below) |
|
|
611
611
|
|
|
@@ -620,11 +620,11 @@ When user has job-related emails (LinkedIn, Indeed, recruiters) and wants to eva
|
|
|
620
620
|
1. **NEVER auto-delete** - Always confirm before deletion, but adapt confirmation style to batch size
|
|
621
621
|
2. **NEVER delete Action Required emails** - Surface them, let user decide
|
|
622
622
|
3. **NEVER delete without --confirm flag** - Command will hang otherwise
|
|
623
|
-
4. **Always remind about undo** - After every deletion, mention `
|
|
623
|
+
4. **Always remind about undo** - After every deletion, mention `inboxd restore --last N`
|
|
624
624
|
|
|
625
625
|
### State Change Safety
|
|
626
626
|
5. **Confirm before mark-read** - Marking as read can hide important emails. Confirm batch operations (3+ emails)
|
|
627
|
-
6. **Remind about mark-unread undo** - After mark-read, mention: "To undo: `
|
|
627
|
+
6. **Remind about mark-unread undo** - After mark-read, mention: "To undo: `inboxd mark-unread --ids \"id1,id2\"`"
|
|
628
628
|
7. **Confirm before archive** - Archiving removes emails from inbox view. Always use `--confirm` flag
|
|
629
629
|
8. **Never batch mark-read silently** - Show what will be marked read before executing
|
|
630
630
|
|
|
@@ -636,9 +636,9 @@ When user has job-related emails (LinkedIn, Indeed, recruiters) and wants to eva
|
|
|
636
636
|
### Undo Commands Reference
|
|
637
637
|
| Action | Undo Command |
|
|
638
638
|
|--------|--------------|
|
|
639
|
-
| Deleted emails | `
|
|
640
|
-
| Marked as read | `
|
|
641
|
-
| Archived | `
|
|
639
|
+
| Deleted emails | `inboxd restore --last N` |
|
|
640
|
+
| Marked as read | `inboxd mark-unread --ids "id1,id2,..."` |
|
|
641
|
+
| Archived | `inboxd unarchive --last N` |
|
|
642
642
|
|
|
643
643
|
---
|
|
644
644
|
|
|
@@ -647,13 +647,13 @@ When user has job-related emails (LinkedIn, Indeed, recruiters) and wants to eva
|
|
|
647
647
|
> [!IMPORTANT]
|
|
648
648
|
> **ALWAYS use this pattern for filter-based deletions.** Filters are for DISCOVERY. IDs are for EXECUTION.
|
|
649
649
|
|
|
650
|
-
This pattern prevents accidental mass deletion. When user says "delete LinkedIn emails", never run `
|
|
650
|
+
This pattern prevents accidental mass deletion. When user says "delete LinkedIn emails", never run `inboxd delete --sender "linkedin" --confirm` directly—it could delete hundreds of emails.
|
|
651
651
|
|
|
652
652
|
### The Pattern
|
|
653
653
|
|
|
654
654
|
1. **Discover** - Find what matches the filter
|
|
655
655
|
```bash
|
|
656
|
-
|
|
656
|
+
inboxd delete --sender "linkedin" --dry-run
|
|
657
657
|
```
|
|
658
658
|
Output shows emails that would be deleted, plus IDs for programmatic use.
|
|
659
659
|
|
|
@@ -670,7 +670,7 @@ This pattern prevents accidental mass deletion. When user says "delete LinkedIn
|
|
|
670
670
|
|
|
671
671
|
3. **Execute** - Delete with explicit IDs (from dry-run output)
|
|
672
672
|
```bash
|
|
673
|
-
|
|
673
|
+
inboxd delete --ids "id1,id2,id3,id4,id5" --confirm
|
|
674
674
|
```
|
|
675
675
|
|
|
676
676
|
### When to Use Each Approach
|
|
@@ -694,20 +694,20 @@ This pattern prevents accidental mass deletion. When user says "delete LinkedIn
|
|
|
694
694
|
|
|
695
695
|
❌ **Bad agent behavior:**
|
|
696
696
|
```bash
|
|
697
|
-
|
|
697
|
+
inboxd delete --sender "linkedin" --confirm # Deletes ALL LinkedIn emails!
|
|
698
698
|
```
|
|
699
699
|
|
|
700
700
|
✅ **Good agent behavior:**
|
|
701
701
|
```bash
|
|
702
702
|
# Step 1: Find LinkedIn emails
|
|
703
|
-
|
|
703
|
+
inboxd analyze --count 20
|
|
704
704
|
# Sees: 3 LinkedIn emails - job alert, connection request, message
|
|
705
705
|
|
|
706
706
|
# Step 2: Identify the specific one by subject
|
|
707
707
|
# (job alert has subject containing "jobs for you")
|
|
708
708
|
|
|
709
709
|
# Step 3: Delete precisely
|
|
710
|
-
|
|
710
|
+
inboxd delete --ids "18e9abc" --confirm # Just the job alert
|
|
711
711
|
```
|
|
712
712
|
|
|
713
713
|
### Ambiguity Handling
|
|
@@ -751,7 +751,7 @@ I've classified your emails. Here's the breakdown:
|
|
|
751
751
|
- 8 LinkedIn alerts (deleted)
|
|
752
752
|
- 27 remaining
|
|
753
753
|
|
|
754
|
-
Done! To undo deletions:
|
|
754
|
+
Done! To undo deletions: inboxd restore --last 8
|
|
755
755
|
```
|
|
756
756
|
|
|
757
757
|
**Good (plan-first approach):**
|
|
@@ -819,7 +819,7 @@ If the user encounters a bug, friction point, or suggests a feature:
|
|
|
819
819
|
| Listing 50 emails individually | Overwhelming, wastes time | Summarize by category for large batches |
|
|
820
820
|
| Suggesting deletion of "Re:" emails | Often important replies | Classify as Action Required |
|
|
821
821
|
| Batching >20 emails without summary | Hard to verify what's being deleted | Show category breakdown |
|
|
822
|
-
| Skipping pre-flight check | Tool may not be installed | Always run `
|
|
822
|
+
| Skipping pre-flight check | Tool may not be installed | Always run `inboxd --version` first |
|
|
823
823
|
| Forgetting `--account` flag | Ambiguity errors with multi-account | Always specify account |
|
|
824
824
|
| Being passive after actions | User has to drive every step | Proactively suggest next step |
|
|
825
825
|
| Executing mark-read on batch without confirmation | User loses unread status on important emails | Confirm 3+ emails, always mention undo |
|
|
@@ -845,10 +845,10 @@ If the user encounters a bug, friction point, or suggests a feature:
|
|
|
845
845
|
|
|
846
846
|
| Problem | Solution |
|
|
847
847
|
|---------|----------|
|
|
848
|
-
| `command not found:
|
|
849
|
-
| "No accounts configured" | Run: `
|
|
850
|
-
| Token expired / auth errors | Delete token and re-auth: `rm ~/.config/inboxd/token-<account>.json &&
|
|
851
|
-
| Permission errors on delete | Re-authenticate: `
|
|
848
|
+
| `command not found: inboxd` | Run: `npm install -g inboxd` |
|
|
849
|
+
| "No accounts configured" | Run: `inboxd setup` |
|
|
850
|
+
| Token expired / auth errors | Delete token and re-auth: `rm ~/.config/inboxd/token-<account>.json && inboxd auth -a <account>` |
|
|
851
|
+
| Permission errors on delete | Re-authenticate: `inboxd logout -a <account> && inboxd auth -a <account>` |
|
|
852
852
|
|
|
853
853
|
---
|
|
854
854
|
|
package/CLAUDE.md
CHANGED
|
@@ -7,11 +7,11 @@ CLI tool for Gmail monitoring with multi-account support and macOS notifications
|
|
|
7
7
|
```bash
|
|
8
8
|
npm test # Run tests
|
|
9
9
|
npm run test:watch # Watch mode
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
inboxd setup # First-time setup wizard
|
|
11
|
+
inboxd auth -a <name> # Add account
|
|
12
|
+
inboxd summary # Check all inboxes
|
|
13
|
+
inboxd check -q # Background check
|
|
14
|
+
inboxd install-service # Install background service (macOS/Linux)
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
## Architecture
|
|
@@ -68,13 +68,13 @@ All user data lives in `~/.config/inboxd/`:
|
|
|
68
68
|
|
|
69
69
|
## Key Behaviors
|
|
70
70
|
|
|
71
|
-
- `
|
|
72
|
-
- `
|
|
73
|
-
- `
|
|
74
|
-
- `
|
|
75
|
-
- `
|
|
76
|
-
- `
|
|
77
|
-
- `
|
|
71
|
+
- `inboxd setup` guides first-time users through credentials and auth
|
|
72
|
+
- `inboxd check` marks emails as seen after notifying
|
|
73
|
+
- `inboxd delete` logs to `deletion-log.json` before trashing
|
|
74
|
+
- `inboxd restore` moves from Trash to Inbox, removes log entry
|
|
75
|
+
- `inboxd archive` logs to `archive-log.json` before archiving
|
|
76
|
+
- `inboxd unarchive` moves archived emails back to Inbox, removes log entry
|
|
77
|
+
- `inboxd send/reply` prompts for interactive confirmation (or use `--confirm` to skip)
|
|
78
78
|
- `install-service` creates and enables launchd (macOS) or systemd (Linux) service
|
|
79
79
|
|
|
80
80
|
## OAuth Notes
|
|
@@ -121,11 +121,11 @@ Traditional CLIs are for humans. Agent-ready CLIs add:
|
|
|
121
121
|
The skill can be installed globally for all Claude Code sessions:
|
|
122
122
|
|
|
123
123
|
```bash
|
|
124
|
-
|
|
125
|
-
|
|
124
|
+
inboxd install-skill # Install to ~/.claude/skills/
|
|
125
|
+
inboxd install-skill --uninstall # Remove
|
|
126
126
|
```
|
|
127
127
|
|
|
128
|
-
The `
|
|
128
|
+
The `inboxd setup` wizard also offers to install the skill automatically.
|
|
129
129
|
|
|
130
130
|
### Skill Location & Update Detection
|
|
131
131
|
|
|
@@ -136,7 +136,7 @@ The `inbox setup` wizard also offers to install the skill automatically.
|
|
|
136
136
|
|
|
137
137
|
The skill uses content-hash detection (no version field). Updates are detected automatically:
|
|
138
138
|
- On `npm install`: Auto-updates if skill already installed
|
|
139
|
-
- Manual: Run `
|
|
139
|
+
- Manual: Run `inboxd install-skill` to update
|
|
140
140
|
|
|
141
141
|
Safety features:
|
|
142
142
|
- `source: inboxd` marker identifies ownership (won't overwrite user's own skills)
|
|
@@ -159,31 +159,31 @@ scripts/postinstall.js # npm postinstall hint about install-skill
|
|
|
159
159
|
### Key Commands for AI Use
|
|
160
160
|
| Command | Purpose |
|
|
161
161
|
|---------|---------|
|
|
162
|
-
| `
|
|
163
|
-
| `
|
|
164
|
-
| `
|
|
165
|
-
| `
|
|
166
|
-
| `
|
|
167
|
-
| `
|
|
168
|
-
| `
|
|
169
|
-
| `
|
|
170
|
-
| `
|
|
171
|
-
| `
|
|
172
|
-
| `
|
|
173
|
-
| `
|
|
174
|
-
| `
|
|
175
|
-
| `
|
|
176
|
-
| `
|
|
177
|
-
| `
|
|
178
|
-
| `
|
|
179
|
-
| `
|
|
180
|
-
| `
|
|
181
|
-
| `
|
|
182
|
-
| `
|
|
183
|
-
| `
|
|
184
|
-
| `
|
|
185
|
-
| `
|
|
186
|
-
| `
|
|
162
|
+
| `inboxd summary --json` | Quick status check (unread counts) |
|
|
163
|
+
| `inboxd analyze --count 50` | Get email data as JSON for classification |
|
|
164
|
+
| `inboxd analyze --group-by sender` | Group emails by sender domain |
|
|
165
|
+
| `inboxd analyze --older-than 30d` | Find emails older than 30 days (server-side filtering) |
|
|
166
|
+
| `inboxd delete --ids "id1,id2" --confirm` | Delete specific emails by ID |
|
|
167
|
+
| `inboxd delete --sender "pattern" --dry-run` | Preview deletion by sender filter |
|
|
168
|
+
| `inboxd delete --match "pattern" --dry-run` | Preview deletion by subject filter |
|
|
169
|
+
| `inboxd restore --last N` | Undo last N deletions |
|
|
170
|
+
| `inboxd read --id <id>` | Read full email content |
|
|
171
|
+
| `inboxd read --id <id> --links` | Extract links from email |
|
|
172
|
+
| `inboxd search -q <query>` | Search using Gmail query syntax |
|
|
173
|
+
| `inboxd send -t <to> -s <subj> -b <body> --confirm` | Send email (requires --confirm) |
|
|
174
|
+
| `inboxd reply --id <id> -b <body> --confirm` | Reply to email (requires --confirm) |
|
|
175
|
+
| `inboxd mark-read --ids "id1,id2"` | Mark emails as read |
|
|
176
|
+
| `inboxd mark-unread --ids "id1,id2"` | Mark emails as unread (undo mark-read) |
|
|
177
|
+
| `inboxd archive --ids "id1,id2" --confirm` | Archive emails (remove from inbox) |
|
|
178
|
+
| `inboxd unarchive --last N` | Undo last N archives |
|
|
179
|
+
| `inboxd stats` | Show email activity dashboard (deletions, sent) |
|
|
180
|
+
| `inboxd stats --json` | Get stats as JSON |
|
|
181
|
+
| `inboxd cleanup-suggest` | Get smart cleanup suggestions based on patterns |
|
|
182
|
+
| `inboxd accounts --json` | List accounts as JSON |
|
|
183
|
+
| `inboxd deletion-log --json` | Get deletion log as JSON |
|
|
184
|
+
| `inboxd delete --dry-run --json` | Preview deletion as JSON |
|
|
185
|
+
| `inboxd install-skill` | Install/update the Claude Code skill |
|
|
186
|
+
| `inboxd install-service --uninstall` | Remove background service |
|
|
187
187
|
|
|
188
188
|
### Smart Filtering Options
|
|
189
189
|
| Option | Description |
|
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@ npm install -g inboxd
|
|
|
30
30
|
Run the interactive setup wizard:
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
|
-
|
|
33
|
+
inboxd setup
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
The wizard will guide you through:
|
|
@@ -60,33 +60,33 @@ mv ~/Downloads/client_secret_*.json ~/.config/inboxd/credentials.json
|
|
|
60
60
|
### 2. Authenticate
|
|
61
61
|
|
|
62
62
|
```bash
|
|
63
|
-
|
|
63
|
+
inboxd auth --account personal
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
### 3. Check Your Inbox
|
|
67
67
|
|
|
68
68
|
```bash
|
|
69
|
-
|
|
69
|
+
inboxd summary
|
|
70
70
|
```
|
|
71
71
|
|
|
72
72
|
## Commands
|
|
73
73
|
|
|
74
74
|
| Command | Description |
|
|
75
75
|
|---------|-------------|
|
|
76
|
-
| `
|
|
77
|
-
| `
|
|
78
|
-
| `
|
|
79
|
-
| `
|
|
80
|
-
| `
|
|
81
|
-
| `
|
|
82
|
-
| `
|
|
83
|
-
| `
|
|
84
|
-
| `
|
|
85
|
-
| `
|
|
86
|
-
| `
|
|
87
|
-
| `
|
|
88
|
-
| `
|
|
89
|
-
| `
|
|
76
|
+
| `inboxd setup` | Interactive setup wizard |
|
|
77
|
+
| `inboxd auth -a <name>` | Authenticate a Gmail account |
|
|
78
|
+
| `inboxd accounts` | List configured accounts |
|
|
79
|
+
| `inboxd summary` | Show inboxd summary for all accounts |
|
|
80
|
+
| `inboxd check` | Check for new emails + send notifications |
|
|
81
|
+
| `inboxd check -q` | Silent check (for background use) |
|
|
82
|
+
| `inboxd delete --ids <ids>` | Move emails to trash |
|
|
83
|
+
| `inboxd delete --sender <pattern>` | Delete by sender (with confirmation) |
|
|
84
|
+
| `inboxd delete --match <pattern>` | Delete by subject (with confirmation) |
|
|
85
|
+
| `inboxd restore --last 1` | Restore last deleted email |
|
|
86
|
+
| `inboxd deletion-log` | View deletion history |
|
|
87
|
+
| `inboxd logout --all` | Remove all accounts |
|
|
88
|
+
| `inboxd install-service` | Install background monitoring (macOS) |
|
|
89
|
+
| `inboxd install-skill` | Install Claude Code skill for AI agents |
|
|
90
90
|
|
|
91
91
|
## Configuration
|
|
92
92
|
|
|
@@ -106,10 +106,10 @@ Install as a macOS launchd service to check for new emails periodically:
|
|
|
106
106
|
|
|
107
107
|
```bash
|
|
108
108
|
# Install and start with default 5-minute interval
|
|
109
|
-
|
|
109
|
+
inboxd install-service
|
|
110
110
|
|
|
111
111
|
# Or customize the interval
|
|
112
|
-
|
|
112
|
+
inboxd install-service --interval 10
|
|
113
113
|
```
|
|
114
114
|
|
|
115
115
|
The service starts automatically after installation. Manage it with:
|
|
@@ -127,7 +127,7 @@ launchctl unload ~/Library/LaunchAgents/com.danielparedes.inboxd.plist
|
|
|
127
127
|
|
|
128
128
|
**Note:** `install-service` is macOS-only. For Linux, use cron:
|
|
129
129
|
```bash
|
|
130
|
-
*/5 * * * * /path/to/node /path/to/
|
|
130
|
+
*/5 * * * * /path/to/node /path/to/inboxd check --quiet
|
|
131
131
|
```
|
|
132
132
|
|
|
133
133
|
## JSON Output
|
|
@@ -135,13 +135,13 @@ launchctl unload ~/Library/LaunchAgents/com.danielparedes.inboxd.plist
|
|
|
135
135
|
For AI agent integration, use the `--json` flag:
|
|
136
136
|
|
|
137
137
|
```bash
|
|
138
|
-
|
|
138
|
+
inboxd summary --json
|
|
139
139
|
```
|
|
140
140
|
|
|
141
141
|
Or use the `analyze` command for structured output:
|
|
142
142
|
|
|
143
143
|
```bash
|
|
144
|
-
|
|
144
|
+
inboxd analyze --count 20
|
|
145
145
|
```
|
|
146
146
|
|
|
147
147
|
## AI Agent Integration
|
|
@@ -163,12 +163,12 @@ This package includes a **skill** that can be installed globally, enabling any C
|
|
|
163
163
|
After installing inboxd, run:
|
|
164
164
|
|
|
165
165
|
```bash
|
|
166
|
-
|
|
166
|
+
inboxd install-skill
|
|
167
167
|
```
|
|
168
168
|
|
|
169
169
|
This copies the inbox-assistant skill to `~/.claude/skills/`, making it available in all your Claude Code sessions.
|
|
170
170
|
|
|
171
|
-
The setup wizard (`
|
|
171
|
+
The setup wizard (`inboxd setup`) also offers to install the skill automatically.
|
|
172
172
|
|
|
173
173
|
### What the Skill Enables
|
|
174
174
|
|
|
@@ -194,13 +194,13 @@ The skill auto-updates when you update inboxd (if already installed). You can al
|
|
|
194
194
|
|
|
195
195
|
```bash
|
|
196
196
|
npm update -g inboxd
|
|
197
|
-
|
|
197
|
+
inboxd install-skill
|
|
198
198
|
```
|
|
199
199
|
|
|
200
200
|
Safety features:
|
|
201
201
|
- Won't overwrite skills not created by inboxd (uses `source: inboxd` marker)
|
|
202
202
|
- Creates `SKILL.md.backup` before replacing if you've modified the skill
|
|
203
|
-
- Use `
|
|
203
|
+
- Use `inboxd install-skill --force` to override ownership check
|
|
204
204
|
|
|
205
205
|
### CLI vs MCP
|
|
206
206
|
|
|
@@ -208,9 +208,9 @@ Unlike an MCP server that exposes raw Gmail API primitives, `inboxd` provides **
|
|
|
208
208
|
|
|
209
209
|
| inboxd CLI | Raw Gmail MCP |
|
|
210
210
|
|------------|---------------|
|
|
211
|
-
| `
|
|
212
|
-
| `
|
|
213
|
-
| `
|
|
211
|
+
| `inboxd delete` logs before trashing | Just trashes |
|
|
212
|
+
| `inboxd restore` removes from log | Just untrashes |
|
|
213
|
+
| `inboxd analyze` formats for AI consumption | Raw API response |
|
|
214
214
|
|
|
215
215
|
The skill layer adds expert workflow guidance on top of these commands.
|
|
216
216
|
|
|
@@ -225,7 +225,7 @@ npm uninstall -g inboxd
|
|
|
225
225
|
To also remove all account data and tokens:
|
|
226
226
|
|
|
227
227
|
```bash
|
|
228
|
-
|
|
228
|
+
inboxd logout --all
|
|
229
229
|
```
|
|
230
230
|
|
|
231
231
|
To completely remove all data including credentials:
|
|
@@ -239,13 +239,13 @@ rm -rf ~/.config/inboxd
|
|
|
239
239
|
## Troubleshooting
|
|
240
240
|
|
|
241
241
|
**"credentials.json not found"**
|
|
242
|
-
Run `
|
|
242
|
+
Run `inboxd setup` or manually download OAuth credentials from Google Cloud Console and save to `~/.config/inboxd/credentials.json`.
|
|
243
243
|
|
|
244
244
|
**"Token expired"**
|
|
245
245
|
Delete the token file and re-authenticate:
|
|
246
246
|
```bash
|
|
247
247
|
rm ~/.config/inboxd/token-<account>.json
|
|
248
|
-
|
|
248
|
+
inboxd auth -a <account>
|
|
249
249
|
```
|
|
250
250
|
|
|
251
251
|
**No notifications appearing**
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "inboxd",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "CLI assistant for Gmail monitoring with multi-account support and AI-ready JSON output",
|
|
5
5
|
"main": "src/cli.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"
|
|
7
|
+
"inboxd": "src/cli.js"
|
|
8
8
|
},
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"test": "vitest run",
|
|
22
22
|
"test:watch": "vitest",
|
|
23
23
|
"lint": "eslint src tests",
|
|
24
|
-
"
|
|
24
|
+
"inboxd": "node src/cli.js",
|
|
25
25
|
"postinstall": "node scripts/postinstall.js || true"
|
|
26
26
|
},
|
|
27
27
|
"keywords": [
|
package/scripts/postinstall.js
CHANGED
|
@@ -21,10 +21,10 @@ function showInstallHint() {
|
|
|
21
21
|
│ inboxd installed successfully! │
|
|
22
22
|
│ │
|
|
23
23
|
│ Quick start: │
|
|
24
|
-
│
|
|
24
|
+
│ inboxd setup # First-time configuration │
|
|
25
25
|
│ │
|
|
26
26
|
│ AI Agent Integration: │
|
|
27
|
-
│
|
|
27
|
+
│ inboxd install-skill # Enable Claude Code skill │
|
|
28
28
|
│ │
|
|
29
29
|
│ This lets AI agents manage your inbox with expert triage. │
|
|
30
30
|
│ │
|
|
@@ -50,7 +50,7 @@ function handleSkillUpdate() {
|
|
|
50
50
|
// Someone else's skill with same name → don't touch, warn
|
|
51
51
|
console.log(`\n⚠️ ~/.claude/skills/inbox-assistant exists but isn't from inboxd`);
|
|
52
52
|
console.log(` The existing skill has source: "${status.source || 'none'}"`);
|
|
53
|
-
console.log(` Run '
|
|
53
|
+
console.log(` Run 'inboxd install-skill --force' to replace it\n`);
|
|
54
54
|
return;
|
|
55
55
|
}
|
|
56
56
|
|
|
@@ -69,13 +69,13 @@ function handleSkillUpdate() {
|
|
|
69
69
|
}
|
|
70
70
|
} else if (result.reason === 'backup_failed') {
|
|
71
71
|
console.log(`\n⚠️ Could not backup existing skill - update skipped`);
|
|
72
|
-
console.log(` Run '
|
|
72
|
+
console.log(` Run 'inboxd install-skill' manually to update\n`);
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
// Up-to-date → silent (no message)
|
|
76
76
|
} catch (err) {
|
|
77
77
|
// Fail silently - postinstall should not break npm install
|
|
78
|
-
// User can always run '
|
|
78
|
+
// User can always run 'inboxd install-skill' manually
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
|
package/src/cli.js
CHANGED
|
@@ -128,7 +128,7 @@ async function main() {
|
|
|
128
128
|
updateNotifier({ pkg }).notify();
|
|
129
129
|
|
|
130
130
|
program
|
|
131
|
-
.name('
|
|
131
|
+
.name('inboxd')
|
|
132
132
|
.description('Gmail monitoring CLI with multi-account support')
|
|
133
133
|
.version(pkg.version);
|
|
134
134
|
|
|
@@ -167,7 +167,7 @@ async function main() {
|
|
|
167
167
|
console.log('');
|
|
168
168
|
const answer = await prompt(rl, chalk.white('Do you want to add another account? (y/N): '));
|
|
169
169
|
if (answer.toLowerCase() !== 'y' && answer.toLowerCase() !== 'yes') {
|
|
170
|
-
console.log(chalk.gray('\nSetup cancelled. Run "
|
|
170
|
+
console.log(chalk.gray('\nSetup cancelled. Run "inboxd summary" to check your inbox.\n'));
|
|
171
171
|
rl.close();
|
|
172
172
|
return;
|
|
173
173
|
}
|
|
@@ -192,7 +192,7 @@ async function main() {
|
|
|
192
192
|
addAccount(accountName, email);
|
|
193
193
|
console.log(chalk.green(`\n ✓ Authenticated as ${email}\n`));
|
|
194
194
|
}
|
|
195
|
-
console.log(chalk.bold.green('🎉 Setup complete! Try:
|
|
195
|
+
console.log(chalk.bold.green('🎉 Setup complete! Try: inboxd summary\n'));
|
|
196
196
|
return;
|
|
197
197
|
}
|
|
198
198
|
}
|
|
@@ -291,10 +291,10 @@ async function main() {
|
|
|
291
291
|
// Success
|
|
292
292
|
console.log(chalk.bold.green('🎉 You\'re all set!\n'));
|
|
293
293
|
console.log(chalk.white(' Try these commands:'));
|
|
294
|
-
console.log(chalk.cyan('
|
|
295
|
-
console.log(chalk.cyan('
|
|
296
|
-
console.log(chalk.cyan('
|
|
297
|
-
console.log(chalk.cyan('
|
|
294
|
+
console.log(chalk.cyan(' inboxd summary') + chalk.gray(' - View your inbox'));
|
|
295
|
+
console.log(chalk.cyan(' inboxd check') + chalk.gray(' - Check for new emails'));
|
|
296
|
+
console.log(chalk.cyan(' inboxd auth -a work') + chalk.gray(' - Add another account'));
|
|
297
|
+
console.log(chalk.cyan(' inboxd install-service') + chalk.gray(' - Enable background monitoring'));
|
|
298
298
|
console.log('');
|
|
299
299
|
|
|
300
300
|
// Offer to install Claude Code skill
|
|
@@ -314,10 +314,10 @@ async function main() {
|
|
|
314
314
|
console.log(chalk.gray(' In Claude Code, ask: "check my emails" or "clean up my inbox"\n'));
|
|
315
315
|
} catch (skillError) {
|
|
316
316
|
console.log(chalk.yellow(`\n Could not install skill: ${skillError.message}`));
|
|
317
|
-
console.log(chalk.gray(' You can install it later with:
|
|
317
|
+
console.log(chalk.gray(' You can install it later with: inboxd install-skill\n'));
|
|
318
318
|
}
|
|
319
319
|
} else {
|
|
320
|
-
console.log(chalk.gray('\n Skipped. Install later with:
|
|
320
|
+
console.log(chalk.gray('\n Skipped. Install later with: inboxd install-skill\n'));
|
|
321
321
|
}
|
|
322
322
|
|
|
323
323
|
} catch (error) {
|
|
@@ -389,7 +389,7 @@ async function main() {
|
|
|
389
389
|
}
|
|
390
390
|
|
|
391
391
|
if (accounts.length === 0) {
|
|
392
|
-
console.log(chalk.gray('No accounts configured. Run:
|
|
392
|
+
console.log(chalk.gray('No accounts configured. Run: inboxd setup'));
|
|
393
393
|
return;
|
|
394
394
|
}
|
|
395
395
|
|
|
@@ -398,7 +398,7 @@ async function main() {
|
|
|
398
398
|
console.log(` ${chalk.cyan(acc.name)} - ${acc.email || 'unknown email'}`);
|
|
399
399
|
}
|
|
400
400
|
console.log('');
|
|
401
|
-
console.log(chalk.gray('To add another account:
|
|
401
|
+
console.log(chalk.gray('To add another account: inboxd auth -a <name>'));
|
|
402
402
|
console.log('');
|
|
403
403
|
});
|
|
404
404
|
|
|
@@ -426,7 +426,7 @@ async function main() {
|
|
|
426
426
|
removeAccount(options.account);
|
|
427
427
|
console.log(chalk.green(`Removed account "${options.account}"`));
|
|
428
428
|
} else {
|
|
429
|
-
console.log(chalk.gray('Usage:
|
|
429
|
+
console.log(chalk.gray('Usage: inboxd logout --account <name> or inboxd logout --all'));
|
|
430
430
|
}
|
|
431
431
|
});
|
|
432
432
|
|
|
@@ -1055,9 +1055,9 @@ async function main() {
|
|
|
1055
1055
|
else {
|
|
1056
1056
|
console.log(chalk.red('Error: Must specify --ids or filter flags (--sender, --match)'));
|
|
1057
1057
|
console.log(chalk.gray('Examples:'));
|
|
1058
|
-
console.log(chalk.gray('
|
|
1059
|
-
console.log(chalk.gray('
|
|
1060
|
-
console.log(chalk.gray('
|
|
1058
|
+
console.log(chalk.gray(' inboxd delete --ids "id1,id2" --confirm'));
|
|
1059
|
+
console.log(chalk.gray(' inboxd delete --sender "linkedin" --dry-run'));
|
|
1060
|
+
console.log(chalk.gray(' inboxd delete --sender "newsletter" --match "weekly" --confirm'));
|
|
1061
1061
|
return;
|
|
1062
1062
|
}
|
|
1063
1063
|
|
|
@@ -1160,7 +1160,7 @@ async function main() {
|
|
|
1160
1160
|
|
|
1161
1161
|
if (totalSucceeded > 0) {
|
|
1162
1162
|
console.log(chalk.green(`\nMoved ${totalSucceeded} email(s) to trash.`));
|
|
1163
|
-
console.log(chalk.gray(`Tip: Use '
|
|
1163
|
+
console.log(chalk.gray(`Tip: Use 'inboxd restore --last ${totalSucceeded}' to undo.`));
|
|
1164
1164
|
}
|
|
1165
1165
|
if (totalFailed > 0) {
|
|
1166
1166
|
console.log(chalk.red(`Failed to delete ${totalFailed} email(s).`));
|
|
@@ -1341,8 +1341,8 @@ async function main() {
|
|
|
1341
1341
|
|
|
1342
1342
|
// Helpful tip
|
|
1343
1343
|
console.log(chalk.gray('Tip: Use these commands to act on suggestions:'));
|
|
1344
|
-
console.log(chalk.gray('
|
|
1345
|
-
console.log(chalk.gray('
|
|
1344
|
+
console.log(chalk.gray(' inboxd delete --sender "domain.com" --dry-run'));
|
|
1345
|
+
console.log(chalk.gray(' inboxd search -q "from:sender@domain.com"\n'));
|
|
1346
1346
|
});
|
|
1347
1347
|
|
|
1348
1348
|
program
|
|
@@ -1382,8 +1382,8 @@ async function main() {
|
|
|
1382
1382
|
} else {
|
|
1383
1383
|
console.log(chalk.red('Error: Must specify either --ids or --last'));
|
|
1384
1384
|
console.log(chalk.gray('Examples:'));
|
|
1385
|
-
console.log(chalk.gray('
|
|
1386
|
-
console.log(chalk.gray('
|
|
1385
|
+
console.log(chalk.gray(' inboxd restore --last 1'));
|
|
1386
|
+
console.log(chalk.gray(' inboxd restore --ids 12345,67890'));
|
|
1387
1387
|
return;
|
|
1388
1388
|
}
|
|
1389
1389
|
|
|
@@ -1518,7 +1518,7 @@ async function main() {
|
|
|
1518
1518
|
} catch (error) {
|
|
1519
1519
|
if (error.message.includes('403') || error.code === 403) {
|
|
1520
1520
|
console.error(chalk.red('Permission denied. You may need to re-authenticate with updated scopes.'));
|
|
1521
|
-
console.error(chalk.yellow('Run:
|
|
1521
|
+
console.error(chalk.yellow('Run: inboxd auth -a <account>'));
|
|
1522
1522
|
} else {
|
|
1523
1523
|
console.error(chalk.red('Error marking emails as read:'), error.message);
|
|
1524
1524
|
}
|
|
@@ -1576,7 +1576,7 @@ async function main() {
|
|
|
1576
1576
|
} catch (error) {
|
|
1577
1577
|
if (error.message.includes('403') || error.code === 403) {
|
|
1578
1578
|
console.error(chalk.red('Permission denied. You may need to re-authenticate with updated scopes.'));
|
|
1579
|
-
console.error(chalk.yellow('Run:
|
|
1579
|
+
console.error(chalk.yellow('Run: inboxd auth -a <account>'));
|
|
1580
1580
|
} else {
|
|
1581
1581
|
console.error(chalk.red('Error marking emails as unread:'), error.message);
|
|
1582
1582
|
}
|
|
@@ -1659,7 +1659,7 @@ async function main() {
|
|
|
1659
1659
|
|
|
1660
1660
|
if (succeeded > 0) {
|
|
1661
1661
|
console.log(chalk.green(`\nArchived ${succeeded} email(s).`));
|
|
1662
|
-
console.log(chalk.gray(`Tip: Use '
|
|
1662
|
+
console.log(chalk.gray(`Tip: Use 'inboxd unarchive --last ${succeeded}' to undo.`));
|
|
1663
1663
|
}
|
|
1664
1664
|
if (failed > 0) {
|
|
1665
1665
|
console.log(chalk.red(`Failed to archive ${failed} email(s).`));
|
|
@@ -1671,7 +1671,7 @@ async function main() {
|
|
|
1671
1671
|
} catch (error) {
|
|
1672
1672
|
if (error.message.includes('403') || error.code === 403) {
|
|
1673
1673
|
console.error(chalk.red('Permission denied. You may need to re-authenticate with updated scopes.'));
|
|
1674
|
-
console.error(chalk.yellow('Run:
|
|
1674
|
+
console.error(chalk.yellow('Run: inboxd auth -a <account>'));
|
|
1675
1675
|
} else {
|
|
1676
1676
|
console.error(chalk.red('Error archiving emails:'), error.message);
|
|
1677
1677
|
}
|
|
@@ -1721,8 +1721,8 @@ async function main() {
|
|
|
1721
1721
|
} else {
|
|
1722
1722
|
console.log(chalk.red('Error: Must specify either --ids or --last'));
|
|
1723
1723
|
console.log(chalk.gray('Examples:'));
|
|
1724
|
-
console.log(chalk.gray('
|
|
1725
|
-
console.log(chalk.gray('
|
|
1724
|
+
console.log(chalk.gray(' inboxd unarchive --last 1'));
|
|
1725
|
+
console.log(chalk.gray(' inboxd unarchive --ids 12345,67890'));
|
|
1726
1726
|
}
|
|
1727
1727
|
return;
|
|
1728
1728
|
}
|
|
@@ -1923,7 +1923,7 @@ WantedBy=timers.target
|
|
|
1923
1923
|
console.log(chalk.white('Useful commands:'));
|
|
1924
1924
|
console.log(chalk.cyan(' systemctl --user status inboxd.timer') + chalk.gray(' # Check status'));
|
|
1925
1925
|
console.log(chalk.cyan(' journalctl --user -u inboxd') + chalk.gray(' # View logs'));
|
|
1926
|
-
console.log(chalk.cyan('
|
|
1926
|
+
console.log(chalk.cyan(' inboxd install-service --uninstall') + chalk.gray(' # Remove service\n'));
|
|
1927
1927
|
} catch (error) {
|
|
1928
1928
|
console.error(chalk.red('Error installing service:'), error.message);
|
|
1929
1929
|
console.log(chalk.yellow('\nThe config files may have been created but could not be enabled.'));
|
|
@@ -1951,7 +1951,6 @@ WantedBy=timers.target
|
|
|
1951
1951
|
const scriptPath = path.resolve(__dirname, 'cli.js');
|
|
1952
1952
|
const workingDir = path.resolve(__dirname, '..');
|
|
1953
1953
|
const plistName = 'com.danielparedes.inboxd.plist';
|
|
1954
|
-
const homeDir = os.homedir();
|
|
1955
1954
|
const launchAgentsDir = path.join(homeDir, 'Library/LaunchAgents');
|
|
1956
1955
|
const plistPath = path.join(launchAgentsDir, plistName);
|
|
1957
1956
|
|
|
@@ -2061,7 +2060,7 @@ WantedBy=timers.target
|
|
|
2061
2060
|
console.log(chalk.yellow(`\n⚠️ A skill with the same name already exists but isn't from ${SOURCE_MARKER}.`));
|
|
2062
2061
|
console.log(chalk.gray(` Current source: "${status.source || 'none'}"`));
|
|
2063
2062
|
console.log(chalk.gray(` Location: ${SKILL_DEST_DIR}\n`));
|
|
2064
|
-
console.log(chalk.white(`To replace it, run:
|
|
2063
|
+
console.log(chalk.white(`To replace it, run: inboxd install-skill --force\n`));
|
|
2065
2064
|
return;
|
|
2066
2065
|
}
|
|
2067
2066
|
|
|
@@ -2121,7 +2120,7 @@ WantedBy=timers.target
|
|
|
2121
2120
|
if (process.argv.length === 2) {
|
|
2122
2121
|
if (!isConfigured()) {
|
|
2123
2122
|
console.log(chalk.cyan('\nWelcome to inboxd!'));
|
|
2124
|
-
console.log(chalk.white('Run ') + chalk.bold('
|
|
2123
|
+
console.log(chalk.white('Run ') + chalk.bold('inboxd setup') + chalk.white(' to get started.\n'));
|
|
2125
2124
|
return;
|
|
2126
2125
|
}
|
|
2127
2126
|
}
|
package/src/gmail-auth.js
CHANGED
|
@@ -226,7 +226,7 @@ async function authorize(account = 'default') {
|
|
|
226
226
|
} catch (_err) {
|
|
227
227
|
throw new Error(
|
|
228
228
|
`credentials.json not found at ${credentialsPath}\n\n` +
|
|
229
|
-
`Run '
|
|
229
|
+
`Run 'inboxd setup' to configure Gmail API access, or manually:\n` +
|
|
230
230
|
`1. Go to https://console.cloud.google.com/\n` +
|
|
231
231
|
`2. Create a project and enable the Gmail API\n` +
|
|
232
232
|
`3. Configure OAuth consent screen (add yourself as test user)\n` +
|
package/tests/filter.test.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest';
|
|
2
2
|
|
|
3
|
-
// Test the email filtering logic used in
|
|
3
|
+
// Test the email filtering logic used in inboxd delete command
|
|
4
4
|
// We test the logic patterns without importing the actual module
|
|
5
5
|
|
|
6
6
|
describe('Email Filtering Logic', () => {
|
|
@@ -4,7 +4,7 @@ import { describe, it, expect } from 'vitest';
|
|
|
4
4
|
// Validates the output format for AI agent consumption
|
|
5
5
|
|
|
6
6
|
describe('JSON Output Formats', () => {
|
|
7
|
-
describe('
|
|
7
|
+
describe('inboxd accounts --json', () => {
|
|
8
8
|
it('should output account list structure', () => {
|
|
9
9
|
const jsonOutput = {
|
|
10
10
|
accounts: [
|
|
@@ -28,7 +28,7 @@ describe('JSON Output Formats', () => {
|
|
|
28
28
|
});
|
|
29
29
|
});
|
|
30
30
|
|
|
31
|
-
describe('
|
|
31
|
+
describe('inboxd deletion-log --json', () => {
|
|
32
32
|
it('should output deletion log structure', () => {
|
|
33
33
|
const jsonOutput = {
|
|
34
34
|
days: 30,
|
|
@@ -75,7 +75,7 @@ describe('JSON Output Formats', () => {
|
|
|
75
75
|
});
|
|
76
76
|
});
|
|
77
77
|
|
|
78
|
-
describe('
|
|
78
|
+
describe('inboxd delete --dry-run --json', () => {
|
|
79
79
|
it('should output preview structure', () => {
|
|
80
80
|
const jsonOutput = {
|
|
81
81
|
dryRun: true,
|
|
@@ -126,7 +126,7 @@ describe('JSON Output Formats', () => {
|
|
|
126
126
|
});
|
|
127
127
|
});
|
|
128
128
|
|
|
129
|
-
describe('
|
|
129
|
+
describe('inboxd restore --json', () => {
|
|
130
130
|
it('should output restore results structure', () => {
|
|
131
131
|
const jsonOutput = {
|
|
132
132
|
restored: 3,
|
package/tests/older-than.test.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest';
|
|
2
2
|
|
|
3
|
-
// Test the older-than parsing logic used in
|
|
3
|
+
// Test the older-than parsing logic used in inboxd analyze command
|
|
4
4
|
// We test the logic patterns directly since the function is not exported
|
|
5
5
|
|
|
6
6
|
describe('Older Than Duration Parsing', () => {
|
package/tests/setup.test.js
CHANGED
|
@@ -206,7 +206,7 @@ describe('Platform Detection', () => {
|
|
|
206
206
|
|
|
207
207
|
if (!isMacOS) {
|
|
208
208
|
// Should suggest cron as alternative
|
|
209
|
-
const cronExample = '*/5 * * * * /path/to/node /path/to/
|
|
209
|
+
const cronExample = '*/5 * * * * /path/to/node /path/to/inboxd check --quiet';
|
|
210
210
|
expect(cronExample).toContain('* * *');
|
|
211
211
|
expect(cronExample).toContain('check --quiet');
|
|
212
212
|
}
|