Browse Source

experiment: Add global install, command router, and /sync mail integration

- Agentmail SKILL.md rewritten with command router (agentmail read/send/reply etc.)
- Global installation: scripts at ~/.claude/agentmail/, hook in ~/.claude/settings.json
- /sync checks mail on startup (Step 5), shows Mail section, suggests agentmail read
- Hook notification text updated to reference agentmail read

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
0xDarkMatter 1 week ago
parent
commit
6f5d656d7e
3 changed files with 133 additions and 125 deletions
  1. 41 9
      commands/sync.md
  2. 1 1
      hooks/check-mail.sh
  3. 91 115
      skills/agentmail/SKILL.md

+ 41 - 9
commands/sync.md

@@ -148,7 +148,20 @@ git log -1 --format="%h %s" 2>/dev/null
 - `wc -l` in Git Bash = count lines (CORRECT)
 - Git Bash understands `2>/dev/null` but NOT `2>nul`
 
-### Step 5: Acknowledge Memory
+### Step 5: Check Mail
+
+Check for unread agentmail messages using the globally installed script:
+
+```bash
+bash "$HOME/.claude/agentmail/mail-db.sh" status 2>/dev/null
+bash "$HOME/.claude/agentmail/mail-db.sh" unread 2>/dev/null
+```
+
+- If the script doesn't exist or returns no unread, skip silently
+- If unread messages exist, show count and preview in the output Mail section
+- Do NOT auto-mark messages as read - just show what's waiting
+
+### Step 6: Acknowledge Memory
 
 MEMORY.md is auto-loaded into the system prompt by Claude Code - do NOT re-read the file.
 Instead, check your system prompt for the memory content you already have, and surface it:
@@ -158,7 +171,7 @@ Instead, check your system prompt for the memory content you already have, and s
 
 This costs zero extra tokens while confirming the safety net is working.
 
-### Step 6: Output
+### Step 7: Output
 
 Format and display unified status.
 
@@ -223,6 +236,18 @@ Note: PR row only shown when pr_number/pr_url are present in saved state.
 Note: MEMORY.md is auto-loaded into the system prompt. This section surfaces
 what's already in context - no file read needed.
 
+## Mail
+
+[If agentmail is installed and has unread messages:]
+3 unread messages:
+  From: some-api  |  Auth endpoints ready
+  From: frontend  |  Need updated types
+  From: infra     |  Deploy complete
+
+Run `agentmail read` to read.
+
+[If no unread messages or agentmail not installed: omit this section entirely]
+
 ## Quick Reference
 
 | Category | Items |
@@ -233,10 +258,11 @@ what's already in context - no file read needed.
 
 ## Next Steps
 
-1. **Continue**: Fix callback URL handling
-2. **Check diff**: /sync --diff to see changes since save
-3. **Resume conversation**: `claude --resume abc123...` (when session_id present)
-4. **PR context**: `claude --from-pr 42` (when PR is linked)
+1. **Read mail**: N unread messages - `agentmail read` (when unread mail exists)
+2. **Continue**: Fix callback URL handling
+3. **Check diff**: /sync --diff to see changes since save
+4. **Resume conversation**: `claude --resume abc123...` (when session_id present)
+5. **PR context**: `claude --from-pr 42` (when PR is linked)
 ```
 
 Note: Next Steps items 3-4 are only shown when the corresponding data exists in saved state.
@@ -262,13 +288,15 @@ Project Synced: [project-name]
 | **Plan** | No active plan |
 | **Saved State** | None |
 | **Memory** | [summary of MEMORY.md content, or "Empty"] |
+| **Mail** | [N unread, or omit row if none/not installed] |
 | **Git** | [branch], [N] uncommitted |
 
 ## Next Steps
 
-1. **Ready for new task** - No pending work detected
-2. **Create a plan** - Use native /plan for implementation planning
-3. **Save before leaving** - /save "notes" to persist state
+1. **Read mail**: N unread messages - `agentmail read` (when unread mail exists)
+2. **Ready for new task** - No pending work detected
+3. **Create a plan** - Use native /plan for implementation planning
+4. **Save before leaving** - /save "notes" to persist state
 ```
 
 ---
@@ -421,6 +449,10 @@ Status
 
 [Summary of MEMORY.md content, or "Empty"]
 
+## Mail
+
+[N unread messages with preview, or omit if none/not installed]
+
 ## Git
 
 | Field | Value |

+ 1 - 1
hooks/check-mail.sh

@@ -57,5 +57,5 @@ sqlite3 -separator '  ' "$MAIL_DB" \
 if [ "$UNREAD" -gt 3 ]; then
   echo "  ... and $((UNREAD - 3)) more"
 fi
-echo "Use /mail to read messages."
+echo "Use agentmail read to read messages."
 echo "==="

+ 91 - 115
skills/agentmail/SKILL.md

@@ -7,146 +7,135 @@ related-skills: [sqlite-ops]
 
 # AgentMail
 
-Inter-session messaging for Claude Code. Sessions running in different project directories can send and receive messages through a shared SQLite database.
+Inter-session messaging for Claude Code. Send and receive messages between sessions running in different projects.
 
-## Architecture
+## Quick Reference
 
-```
-~/.claude/mail.db          # Global message store (auto-created)
-
-Session A (claude-mods)    Session B (some-api)     Session C (frontend)
-    |                          |                        |
-    +-- check-mail hook -------+-- check-mail hook -----+-- check-mail hook
-    |   (PreToolUse, silent    |   (10s cooldown)       |
-    |    when empty)           |                        |
-    |                          |                        |
-    +-- /mail send some-api ---+--> unread message -----+
-         "API changed"             appears next
-                                   tool call
-```
-
-## Project Identity
-
-Project name = `basename` of current working directory. No configuration needed.
-
-- `X:\Forge\claude-mods` -> `claude-mods`
-- `X:\Forge\some-api` -> `some-api`
+All commands go through `MAIL`, a shorthand for `bash "$HOME/.claude/agentmail/mail-db.sh"`.
 
-If a project directory is renamed, use the `alias` command to link old and new names:
+Set this at the top of execution:
 
 ```bash
-bash skills/agentmail/scripts/mail-db.sh alias "old-name" "new-name"
+MAIL="$HOME/.claude/agentmail/mail-db.sh"
 ```
 
-## Commands
+Then use it for all commands below.
 
-All commands use the helper script at `skills/agentmail/scripts/mail-db.sh`.
+## Command Router
 
-### Send a Message
+Parse the user's input after `agentmail` (or `/agentmail`) and run the matching command:
 
-```bash
-bash skills/agentmail/scripts/mail-db.sh send "<target-project>" "<subject>" "<body>"
-```
-
-Send with urgent priority (highlighted in hook notifications):
-
-```bash
-bash skills/agentmail/scripts/mail-db.sh send --urgent "<target-project>" "<subject>" "<body>"
-```
+| User says | Run |
+|-----------|-----|
+| `agentmail read` | `bash "$MAIL" read` |
+| `agentmail read 42` | `bash "$MAIL" read 42` |
+| `agentmail send <project> "<subject>" "<body>"` | `bash "$MAIL" send "<project>" "<subject>" "<body>"` |
+| `agentmail send --urgent <project> "<subject>" "<body>"` | `bash "$MAIL" send --urgent "<project>" "<subject>" "<body>"` |
+| `agentmail reply <id> "<body>"` | `bash "$MAIL" reply <id> "<body>"` |
+| `agentmail broadcast "<subject>" "<body>"` | `bash "$MAIL" broadcast "<subject>" "<body>"` |
+| `agentmail search <keyword>` | `bash "$MAIL" search "<keyword>"` |
+| `agentmail status` | `bash "$MAIL" status` |
+| `agentmail unread` | `bash "$MAIL" unread` |
+| `agentmail list` | `bash "$MAIL" list` |
+| `agentmail list 50` | `bash "$MAIL" list 50` |
+| `agentmail projects` | `bash "$MAIL" projects` |
+| `agentmail clear` | `bash "$MAIL" clear` |
+| `agentmail clear 7` | `bash "$MAIL" clear 7` |
+| `agentmail alias <old> <new>` | `bash "$MAIL" alias "<old>" "<new>"` |
+| `agentmail purge` | `bash "$MAIL" purge` |
+| `agentmail purge --all` | `bash "$MAIL" purge --all` |
+| `agentmail init` | `bash "$MAIL" init` |
 
-### Read Messages
+When the user just says "check mail", "read mail", "inbox", or "any mail?" - run `bash "$MAIL" read`.
 
-```bash
-bash skills/agentmail/scripts/mail-db.sh read          # All unread, mark as read
-bash skills/agentmail/scripts/mail-db.sh read 42        # Single message by ID
-```
+When the user says "send mail to X" or "message X" - parse out the project name, subject, and body, then run `bash "$MAIL" send`.
 
-### Reply
+## Project Identity
 
-Reply to a message - automatically addresses the sender with Re: prefix:
+Project name = `basename` of current working directory. No configuration needed.
 
-```bash
-bash skills/agentmail/scripts/mail-db.sh reply <message-id> "<body>"
-```
+- `X:\Forge\claude-mods` -> `claude-mods`
+- `X:\Forge\some-api` -> `some-api`
+- `X:\Roam\Fathom` -> `Fathom`
 
-### Broadcast
+## Passive Notification (Hook)
 
-Send to all known projects (except self):
+A global PreToolUse hook checks for mail on every tool call (10-second cooldown). Silent when inbox is empty.
 
-```bash
-bash skills/agentmail/scripts/mail-db.sh broadcast "<subject>" "<body>"
 ```
-
-### Search
-
-Find messages by keyword in subject or body:
-
-```bash
-bash skills/agentmail/scripts/mail-db.sh search "<keyword>"
+=== MAIL: 3 unread message(s) ===
+  From: some-api  |  Auth endpoints ready
+  From: frontend  |  Need updated types
+  ... and 1 more
+Use agentmail read to read messages.
 ```
 
-### Status
-
-Inbox summary with per-project breakdown:
+## When to Send
 
-```bash
-bash skills/agentmail/scripts/mail-db.sh status
-```
+- You've completed work another session depends on
+- An API contract or shared interface changed
+- A shared branch (main) is broken or fixed
+- You need input from a session working on a different project
 
-### Other Commands
+## Per-Project Disable
 
 ```bash
-bash skills/agentmail/scripts/mail-db.sh count          # Unread count (number only)
-bash skills/agentmail/scripts/mail-db.sh unread          # List unread (brief)
-bash skills/agentmail/scripts/mail-db.sh list [N]        # Recent messages (default 20)
-bash skills/agentmail/scripts/mail-db.sh projects        # All known projects
-bash skills/agentmail/scripts/mail-db.sh clear [days]    # Delete read msgs older than N days
-bash skills/agentmail/scripts/mail-db.sh alias <old> <new>  # Rename project in all messages
-bash skills/agentmail/scripts/mail-db.sh init            # Initialize database
+touch .claude/agentmail.disable    # Disable hook notifications
+rm .claude/agentmail.disable       # Re-enable
 ```
 
-## Passive Notification (Hook)
+Only the hook is disabled - you can still send messages from the project.
 
-The `hooks/check-mail.sh` hook provides passive notification:
-
-1. Runs on every tool call (PreToolUse, 10-second cooldown)
-2. Checks for unread messages matching current directory name
-3. Silent when inbox is empty
-4. Shows count + preview of up to 3 messages
-5. Highlights urgent messages with `[!]` prefix
+---
 
-### Hook Output
+## Installation
 
-```
-=== MAIL: 3 unread message(s) ===
-  From: some-api  |  Auth endpoints ready
-  From: frontend  |  Need updated types
-  ... and 1 more
-Use /mail to read messages.
-```
+Agentmail installs globally - one setup, every project gets mail automatically.
 
-Urgent messages:
+### Files
 
 ```
-=== URGENT MAIL: 2 unread (1 urgent) ===
-  [!] From: some-api  |  Production is down
-  From: frontend  |  Need updated types
-Use /mail to read messages.
+~/.claude/
+  mail.db                  # Message store (auto-created on first use)
+  agentmail/
+    mail-db.sh             # Mail commands
+    check-mail.sh          # PreToolUse hook
 ```
 
-## When to Use
+### Setup
 
-**Send messages when:**
-- You've completed work another session depends on
-- An API contract or shared interface changed
-- A shared branch (main) is broken or fixed
-- You need input from a session working on a different project
+1. Copy scripts to global location:
 
-**The hook handles receiving automatically.** When this skill triggers from a user saying "check mail" or "read messages", run the read command.
+```bash
+mkdir -p ~/.claude/agentmail
+cp skills/agentmail/scripts/mail-db.sh ~/.claude/agentmail/
+cp hooks/check-mail.sh ~/.claude/agentmail/
+```
+
+2. Add the hook to `~/.claude/settings.json`:
+
+```json
+{
+  "hooks": {
+    "PreToolUse": [
+      {
+        "matcher": "*",
+        "hooks": [
+          {
+            "type": "command",
+            "command": "bash \"$HOME/.claude/agentmail/check-mail.sh\"",
+            "timeout": 5
+          }
+        ]
+      }
+    ]
+  }
+}
+```
 
 ## Database
 
-Single SQLite file at `~/.claude/mail.db`. Not inside any git repo.
+Single SQLite file at `~/.claude/mail.db`. Auto-created on first use.
 
 ```sql
 CREATE TABLE messages (
@@ -161,25 +150,12 @@ CREATE TABLE messages (
 );
 ```
 
-All user inputs are sanitized via SQL single-quote escaping. Numeric inputs (IDs, limits) are validated before use.
-
-## Per-Project Disable
-
-To disable mail notifications for a specific project:
-
-```bash
-touch .claude/agentmail.disable    # Disable
-rm .claude/agentmail.disable       # Re-enable
-```
-
-Only the hook is disabled - you can still send messages from the project. This is useful for projects where you don't want hook overhead or notification noise.
-
 ## Troubleshooting
 
 | Issue | Fix |
 |-------|-----|
 | `sqlite3: not found` | Ships with macOS, Linux, and Git Bash on Windows |
-| Hook not firing | Register in `.claude/settings.json` or `.claude/settings.local.json` |
+| Hook not firing | Add PreToolUse hook to `~/.claude/settings.json` (see Installation) |
 | Wrong project name | Uses `basename $PWD` - ensure cwd is project root |
 | Messages not arriving | `to_project` must match target's directory basename exactly |
-| Renamed directory | Use `alias` command to update old name to new name |
+| Renamed directory | Use `agentmail alias old-name new-name` |