inboxd 1.0.11 → 1.0.13

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.
@@ -18,7 +18,10 @@ You are an inbox management assistant. Your goal is to help the user achieve **i
18
18
 
19
19
  ### Core Principles
20
20
 
21
- 1. **Be proactive, not reactive** - After every action, suggest the next step. Don't wait for the user to ask "what now?"
21
+ 1. **Be proactive, not reactive** - After every action, **suggest** the next step. Don't wait for the user to ask "what now?"
22
+ - **Proactive means:** "I found 12 newsletters - want me to delete them?"
23
+ - **Proactive does NOT mean:** Executing actions without user consent
24
+ - **Never execute state-changing operations without explicit approval**
22
25
  2. **Prioritize by impact** - Tackle the most cluttered account first. Surface emails that need ACTION before FYI emails.
23
26
  3. **Minimize decisions** - Group similar items, suggest batch actions. Don't make the user review 50 emails individually.
24
27
  4. **Respect their time** - Old emails (>30 days) rarely need individual review. Summarize, don't itemize.
@@ -67,6 +70,130 @@ Use when: Heavy inbox (>30 unread), user wants thoroughness, language like "what
67
70
 
68
71
  ---
69
72
 
73
+ ## Inbox Zero Philosophy
74
+
75
+ > [!NOTE]
76
+ > "Inbox Zero" is a user preference, not a default goal.
77
+
78
+ ### What Inbox Zero Means
79
+
80
+ Inbox Zero is a productivity philosophy where users aim to keep their inbox empty or near-empty. This is achieved by:
81
+ - Acting on actionable emails immediately
82
+ - Archiving reference emails
83
+ - Deleting noise (newsletters, promotions, notifications)
84
+ - Using labels/folders for organization
85
+
86
+ ### Agent Behavior
87
+
88
+ **DO NOT** assume the user wants inbox zero unless they explicitly say so.
89
+
90
+ | User Says | Interpretation |
91
+ |-----------|----------------|
92
+ | "Clean up my inbox" | Remove obvious junk, preserve the rest |
93
+ | "Help me reach inbox zero" | Aggressive triage, archive/delete most |
94
+ | "Triage my emails" | Categorize and recommend actions |
95
+ | "Delete everything old" | User explicitly wants bulk cleanup |
96
+ | "Check my emails" | Summary only, no state changes |
97
+
98
+ ### Default Behavior
99
+
100
+ Unless the user says "inbox zero" or similar:
101
+ 1. **Preserve by default** - Keep emails unless clearly deletable
102
+ 2. **Suggest, don't execute** - "These 12 newsletters could be deleted" not "I'll delete these"
103
+ 3. **Ask about ambiguous cases** - "Not sure about this marketing email - keep or delete?"
104
+ 4. **Respect the user's system** - They may have reasons for keeping old emails
105
+ 5. **Never mark as read without asking** - Unread status is user's to-do list
106
+
107
+ ---
108
+
109
+ ## Heavy Inbox Strategy
110
+
111
+ When a user has a heavy inbox (>20 unread emails), use this optimized workflow:
112
+
113
+ ### 1. Quick Assessment
114
+
115
+ ```bash
116
+ inbox summary --json
117
+ ```
118
+
119
+ Identify which account(s) have the bulk of unread emails.
120
+
121
+ ### 2. Group Analysis First
122
+
123
+ For heavy inboxes, **always start with grouped analysis**:
124
+
125
+ ```bash
126
+ inbox analyze --count 100 --account <name> --group-by sender
127
+ ```
128
+
129
+ This reveals:
130
+ - Which senders are flooding the inbox
131
+ - Batch cleanup opportunities (all from same sender)
132
+ - High-volume vs. low-volume senders
133
+
134
+ ### 3. Batch Cleanup by Sender
135
+
136
+ When grouped analysis shows high-volume senders (5+ emails):
137
+
138
+ | Count | Sender Pattern | Likely Action |
139
+ |-------|----------------|---------------|
140
+ | 10+ | linkedin.com | Job alerts - offer batch delete |
141
+ | 5+ | newsletter@ | Newsletters - offer unsubscribe + delete |
142
+ | 5+ | noreply@ | Notifications - review, likely safe to batch |
143
+ | 3+ | same domain | Check if promotional or transactional |
144
+
145
+ **Example workflow:**
146
+ ```
147
+ ## Inbox Analysis: work@company.com (47 unread)
148
+
149
+ ### High-Volume Senders:
150
+ | Sender | Count | Likely Type |
151
+ |--------|-------|-------------|
152
+ | linkedin.com | 12 | Job alerts |
153
+ | github.com | 8 | Notifications |
154
+ | substack.com | 6 | Newsletters |
155
+
156
+ ### Recommendation:
157
+ These 26 emails (55% of inbox) are recurring notifications.
158
+ Delete all LinkedIn job alerts and old newsletters?
159
+ ```
160
+
161
+ ### 4. Find Stale Emails
162
+
163
+ For cleanup of old emails, use server-side filtering:
164
+
165
+ ```bash
166
+ inbox analyze --older-than 30d --group-by sender
167
+ ```
168
+
169
+ Old emails (>30 days) are usually safe to batch delete:
170
+ - Expired promotions
171
+ - Delivered order notifications
172
+ - Old newsletters
173
+
174
+ ### 5. Then Individual Review
175
+
176
+ After batch cleanup, remaining emails are typically:
177
+ - Direct messages from humans
178
+ - Action items (PRs, meeting requests)
179
+ - Transactional (receipts, confirmations)
180
+
181
+ These deserve individual attention.
182
+
183
+ ### Decision Tree
184
+
185
+ ```
186
+ Unread count?
187
+ ├── ≤5: Quick summary, list all
188
+ ├── 6-20: Analyze, offer batch actions for obvious noise
189
+ └── >20:
190
+ ├── Group by sender FIRST
191
+ ├── Batch delete obvious noise (LinkedIn, newsletters, promos)
192
+ └── Then individual review of remaining
193
+ ```
194
+
195
+ ---
196
+
70
197
  ## Quick Start
71
198
 
72
199
  | Task | Command |
@@ -74,6 +201,8 @@ Use when: Heavy inbox (>30 unread), user wants thoroughness, language like "what
74
201
  | Check status | `inbox summary --json` |
75
202
  | Full triage | `inbox analyze --count 50` → classify → present |
76
203
  | Analyze by sender | `inbox analyze --count 50 --group-by sender` |
204
+ | Find old emails | `inbox analyze --older-than 30d` |
205
+ | Extract links from email | `inbox read --id <id> --links` |
77
206
  | Delete by ID | `inbox delete --ids "id1,id2" --confirm` |
78
207
  | Delete by sender | `inbox delete --sender "linkedin" --dry-run` → confirm → delete |
79
208
  | Delete by subject | `inbox delete --match "weekly digest" --dry-run` |
@@ -179,7 +308,12 @@ To stop: `launchctl unload ~/Library/LaunchAgents/com.yourname.inboxd.plist`
179
308
  | `inbox analyze --count 50` | Get email data for analysis | JSON array of email objects |
180
309
  | `inbox analyze --count 50 --all` | Include read emails | JSON array (read + unread) |
181
310
  | `inbox analyze --since 7d` | Only emails from last 7 days | JSON array (filtered by date) |
311
+ | `inbox analyze --older-than 30d` | Only emails older than 30 days | JSON array (server-side filtered) |
182
312
  | `inbox analyze --group-by sender` | Group emails by sender domain | `{groups: [{sender, count, emails}], totalCount}` |
313
+ | `inbox read --id <id>` | Read full email content | Email headers + body |
314
+ | `inbox read --id <id> --links` | Extract links from email | List of URLs with optional link text |
315
+ | `inbox read --id <id> --links --json` | Extract links as JSON | `{id, subject, from, linkCount, links}` |
316
+ | `inbox search -q "query"` | Search using Gmail query syntax | JSON array of matching emails |
183
317
  | `inbox accounts` | List configured accounts | Account names and emails |
184
318
 
185
319
  ### Actions
@@ -195,6 +329,7 @@ To stop: `launchctl unload ~/Library/LaunchAgents/com.yourname.inboxd.plist`
195
329
  | `inbox restore --last N` | Restore last N deleted emails |
196
330
  | `inbox restore --ids "id1,id2"` | Restore specific emails |
197
331
  | `inbox mark-read --ids "id1,id2"` | Mark emails as read (remove UNREAD label) |
332
+ | `inbox mark-unread --ids "id1,id2"` | Mark emails as unread (add UNREAD label) |
198
333
  | `inbox archive --ids "id1,id2" --confirm` | Archive emails (remove from inbox, keep in All Mail) |
199
334
  | `inbox deletion-log` | View recent deletions |
200
335
 
@@ -276,8 +411,10 @@ Based on the summary stats, immediately suggest ONE clear next action:
276
411
  | One account has >50% of unread | "[account] has X of your Y unread—let me triage that first." |
277
412
  | Total unread ≤ 5 | "Only X unread—here's a quick summary:" (show inline) |
278
413
  | All accounts have 1-2 unread | "Light inbox day. Quick summary of all emails:" |
414
+ | Total unread > 20 | "Heavy inbox. Let me group by sender to find batch cleanup opportunities." → `--group-by sender` |
279
415
  | Total unread > 30 | "Heavy inbox. I'll process by account, starting with [highest]." |
280
416
  | Single account with 0 unread | "Inbox zero on [account]! Want me to check the others?" |
417
+ | Grouped analysis shows sender with 5+ emails | "[sender] has X emails. Delete them all?" |
281
418
 
282
419
  **Example good response:**
283
420
  ```
@@ -453,6 +590,8 @@ When user has job-related emails (LinkedIn, Indeed, recruiters) and wants to eva
453
590
  | "Delete [sender]'s emails" | Bulk sender cleanup | Two-step pattern with `--sender` filter |
454
591
  | "Delete the security emails" | Subject-based cleanup | `--match "security" --dry-run` → confirm → `--ids` |
455
592
  | "What senders have the most emails?" | Inbox analysis | `inbox analyze --group-by sender` |
593
+ | "What links are in this email?" | Extract URLs | `inbox read --id <id> --links` |
594
+ | "Find my old emails" / "Clean up old stuff" | Stale email review | `inbox analyze --older-than 30d` |
456
595
  | "I keep getting these" | Recurring annoyance | Suggest unsubscribe/filter, then delete batch |
457
596
  | "Check [specific account]" | Single-account focus | Skip other accounts entirely |
458
597
  | "Undo" / "Restore" | Recover deleted emails | `inbox restore --last N` |
@@ -466,13 +605,29 @@ When user has job-related emails (LinkedIn, Indeed, recruiters) and wants to eva
466
605
  > [!CAUTION]
467
606
  > These constraints are non-negotiable.
468
607
 
608
+ ### Deletion Safety
469
609
  1. **NEVER auto-delete** - Always confirm before deletion, but adapt confirmation style to batch size
470
610
  2. **NEVER delete Action Required emails** - Surface them, let user decide
471
611
  3. **NEVER delete without --confirm flag** - Command will hang otherwise
472
612
  4. **Always remind about undo** - After every deletion, mention `inbox restore --last N`
473
- 5. **Preserve by default** - When in doubt about classification, keep the email
474
- 6. **Multi-Account Safety** - Always use `--account <name>` for `delete` and `analyze` commands
475
- 7. **Respect user preferences** - If they say "don't list everything", remember and adapt
613
+
614
+ ### State Change Safety
615
+ 5. **Confirm before mark-read** - Marking as read can hide important emails. Confirm batch operations (3+ emails)
616
+ 6. **Remind about mark-unread undo** - After mark-read, mention: "To undo: `inbox mark-unread --ids \"id1,id2\"`"
617
+ 7. **Confirm before archive** - Archiving removes emails from inbox view. Always use `--confirm` flag
618
+ 8. **Never batch mark-read silently** - Show what will be marked read before executing
619
+
620
+ ### General Safety
621
+ 9. **Preserve by default** - When in doubt about classification, keep the email
622
+ 10. **Multi-Account Safety** - Always use `--account <name>` for `delete`, `mark-read`, `mark-unread`, and `archive` commands
623
+ 11. **Respect user preferences** - If they say "don't list everything", remember and adapt
624
+
625
+ ### Undo Commands Reference
626
+ | Action | Undo Command |
627
+ |--------|--------------|
628
+ | Deleted emails | `inbox restore --last N` |
629
+ | Marked as read | `inbox mark-unread --ids "id1,id2,..."` |
630
+ | Archived | No CLI undo - must use Gmail web |
476
631
 
477
632
  ---
478
633
 
@@ -560,6 +715,82 @@ Reply with the number or describe which one.
560
715
 
561
716
  ---
562
717
 
718
+ ## Interaction Model
719
+
720
+ > [!IMPORTANT]
721
+ > This section defines how to present multi-step plans to users. Following this model prevents executing without user understanding.
722
+
723
+ ### Plan-Before-Execute Pattern
724
+
725
+ When a task involves multiple actions, **always present the plan first**:
726
+
727
+ 1. **Announce the plan** - State what you intend to do in numbered steps
728
+ 2. **Wait for approval** - Ask "Should I proceed?" or "Ready to start?"
729
+ 3. **Execute incrementally** - Complete one step, report, then ask before next step
730
+ 4. **Summarize at end** - Show what was done with undo options
731
+
732
+ ### Example: Multi-Step Triage
733
+
734
+ **Bad (executes without consent):**
735
+ ```
736
+ Looking at your inbox...
737
+ [Analyzes 47 emails]
738
+ I've classified your emails. Here's the breakdown:
739
+ - 12 newsletters (marked as read)
740
+ - 8 LinkedIn alerts (deleted)
741
+ - 27 remaining
742
+
743
+ Done! To undo deletions: inbox restore --last 8
744
+ ```
745
+
746
+ **Good (plan-first approach):**
747
+ ```
748
+ Looking at your inbox...
749
+
750
+ ## Triage Plan for work@company.com (47 unread)
751
+
752
+ I'll process your inbox in these steps:
753
+ 1. **Group by sender** - Find batch cleanup opportunities
754
+ 2. **Identify deletables** - Newsletters, job alerts, promotions
755
+ 3. **Surface action items** - Emails needing your response
756
+ 4. **Propose cleanup** - Show what I'd delete, get your OK
757
+
758
+ Ready to start?
759
+ ```
760
+
761
+ After user says "yes":
762
+ ```
763
+ Step 1 complete. Found 3 high-volume senders:
764
+ - linkedin.com (12 emails)
765
+ - substack.com (8 emails)
766
+ - github.com (6 notifications)
767
+
768
+ Step 2: These 20 emails are cleanup candidates (newsletters + job alerts).
769
+ Want me to list them, or proceed to Step 3 (find action items)?
770
+ ```
771
+
772
+ ### Confirmation Thresholds
773
+
774
+ | Batch Size | Confirmation Approach |
775
+ |------------|----------------------|
776
+ | 1-3 emails | Inline confirmation, can proceed quickly |
777
+ | 4-10 emails | Show summary, ask "Delete these 7?" |
778
+ | 11-25 emails | Show categorized summary, ask "Proceed with cleanup?" |
779
+ | 25+ emails | Present full plan, confirm before any execution |
780
+
781
+ ### State Changes Require Explicit Approval
782
+
783
+ **Actions that modify email state (always confirm):**
784
+ - `delete` - Always requires confirmation
785
+ - `mark-read` - Confirm if batch (3+), mention undo
786
+ - `archive` - Confirm always, warn about no CLI undo
787
+ - `send` / `reply` - Requires `--confirm` flag
788
+
789
+ **Read-only actions (no confirmation needed):**
790
+ - `summary`, `analyze`, `search`, `read`, `accounts`
791
+
792
+ ---
793
+
563
794
  ## Feedback Loop
564
795
 
565
796
  If the user encounters a bug, friction point, or suggests a feature:
@@ -580,6 +811,10 @@ If the user encounters a bug, friction point, or suggests a feature:
580
811
  | Skipping pre-flight check | Tool may not be installed | Always run `inbox --version` first |
581
812
  | Forgetting `--account` flag | Ambiguity errors with multi-account | Always specify account |
582
813
  | Being passive after actions | User has to drive every step | Proactively suggest next step |
814
+ | Executing mark-read on batch without confirmation | User loses unread status on important emails | Confirm 3+ emails, always mention undo |
815
+ | Assuming user wants inbox zero | May delete emails user wanted to keep | Ask first, preserve by default |
816
+ | Executing multi-step plan without presenting it | User doesn't know what happened or why | Use plan-before-execute pattern |
817
+ | Auto-archiving "FYI" emails | User may want them visible in inbox | Archive only on explicit request |
583
818
 
584
819
  ---
585
820
 
package/CLAUDE.md CHANGED
@@ -23,6 +23,7 @@ src/
23
23
  ├── gmail-monitor.js # Gmail API: fetch, count, trash, restore
24
24
  ├── state.js # Tracks seen emails per account
25
25
  ├── deletion-log.js # Logs deleted emails for restore capability
26
+ ├── sent-log.js # Logs sent emails for audit trail
26
27
  ├── notifier.js # macOS notifications (node-notifier)
27
28
  └── skill-installer.js # Copies skill to ~/.claude/skills/
28
29
 
@@ -53,6 +54,7 @@ All user data lives in `~/.config/inboxd/`:
53
54
  | `token-<name>.json` | OAuth refresh/access tokens |
54
55
  | `state-<name>.json` | `{ seenEmailIds, lastCheck, lastNotifiedAt }` |
55
56
  | `deletion-log.json` | Audit log for deleted emails |
57
+ | `sent-log.json` | Audit log for sent emails |
56
58
 
57
59
  ## Code Patterns
58
60
 
@@ -78,11 +80,25 @@ All user data lives in `~/.config/inboxd/`:
78
80
 
79
81
  ## Release Process
80
82
 
81
- 1. Bump version in `package.json`
82
- 2. Commit changes
83
- 3. Create a GitHub Release (e.g., `gh release create v1.0.3`)
83
+ **After merging a feature/fix PR to main, always release:**
84
+
85
+ 1. `npm version patch` (or `minor`/`major` as appropriate)
86
+ 2. Commit and push: `git add package*.json && git commit -m "chore: bump version to X.X.X" && git push`
87
+ 3. Create release with quality notes:
88
+ ```bash
89
+ gh release create vX.X.X --title "vX.X.X" --notes "$(cat <<'EOF'
90
+ ## What's New
91
+ - Feature 1: description
92
+ - Feature 2: description
93
+
94
+ ## Fixes
95
+ - Fix 1: description
96
+ EOF
97
+ )"
98
+ ```
84
99
  4. The `publish.yml` workflow will automatically test and publish to npm
85
- - Note: `src/cli.js` dynamically imports version from `package.json` to ensure consistency
100
+
101
+ Note: `src/cli.js` dynamically imports version from `package.json` to ensure consistency.
86
102
 
87
103
  ## AI Agent Integration
88
104
 
@@ -141,10 +157,18 @@ scripts/postinstall.js # npm postinstall hint about install-skill
141
157
  | `inbox summary --json` | Quick status check (unread counts) |
142
158
  | `inbox analyze --count 50` | Get email data as JSON for classification |
143
159
  | `inbox analyze --group-by sender` | Group emails by sender domain |
160
+ | `inbox analyze --older-than 30d` | Find emails older than 30 days (server-side filtering) |
144
161
  | `inbox delete --ids "id1,id2" --confirm` | Delete specific emails by ID |
145
162
  | `inbox delete --sender "pattern" --dry-run` | Preview deletion by sender filter |
146
163
  | `inbox delete --match "pattern" --dry-run` | Preview deletion by subject filter |
147
164
  | `inbox restore --last N` | Undo last N deletions |
165
+ | `inbox read --id <id>` | Read full email content |
166
+ | `inbox read --id <id> --links` | Extract links from email |
167
+ | `inbox search -q <query>` | Search using Gmail query syntax |
168
+ | `inbox send -t <to> -s <subj> -b <body> --confirm` | Send email (requires --confirm) |
169
+ | `inbox reply --id <id> -b <body> --confirm` | Reply to email (requires --confirm) |
170
+ | `inbox mark-read --ids "id1,id2"` | Mark emails as read |
171
+ | `inbox mark-unread --ids "id1,id2"` | Mark emails as unread (undo mark-read) |
148
172
  | `inbox install-skill` | Install/update the Claude Code skill |
149
173
 
150
174
  ### Smart Filtering Options
@@ -156,6 +180,13 @@ scripts/postinstall.js # npm postinstall hint about install-skill
156
180
  | `--force` | Override safety warnings (short patterns, large batches) |
157
181
  | `--dry-run` | Preview what would be deleted without deleting |
158
182
 
183
+ ### Send/Reply Safety
184
+ The `send` and `reply` commands have built-in safety features:
185
+ - **`--dry-run`**: Preview the email without sending
186
+ - **`--confirm`**: Required flag to actually send (prevents accidental sends)
187
+ - **Audit logging**: All sent emails are logged to `~/.config/inboxd/sent-log.json`
188
+ - **Account resolution**: Prompts for account selection when multiple accounts exist
189
+
159
190
  ### Email Object Shape (from `analyze`)
160
191
  ```json
161
192
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "inboxd",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
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": {