mail-db.sh 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #!/bin/bash
  2. # mail-db.sh - SQLite mail database operations
  3. # Global mail database at ~/.claude/mail.db
  4. # Project identity derived from basename of working directory
  5. set -euo pipefail
  6. MAIL_DB="$HOME/.claude/mail.db"
  7. # Ensure database and schema exist
  8. init_db() {
  9. mkdir -p "$(dirname "$MAIL_DB")"
  10. sqlite3 "$MAIL_DB" <<'SQL'
  11. CREATE TABLE IF NOT EXISTS messages (
  12. id INTEGER PRIMARY KEY AUTOINCREMENT,
  13. from_project TEXT NOT NULL,
  14. to_project TEXT NOT NULL,
  15. subject TEXT DEFAULT '',
  16. body TEXT NOT NULL,
  17. timestamp TEXT DEFAULT (datetime('now')),
  18. read INTEGER DEFAULT 0
  19. );
  20. CREATE INDEX IF NOT EXISTS idx_unread ON messages(to_project, read);
  21. CREATE INDEX IF NOT EXISTS idx_timestamp ON messages(timestamp);
  22. SQL
  23. }
  24. # Get project name from cwd
  25. get_project() {
  26. basename "$PWD"
  27. }
  28. # Count unread messages for current project
  29. count_unread() {
  30. init_db
  31. local project
  32. project=$(get_project)
  33. sqlite3 "$MAIL_DB" "SELECT COUNT(*) FROM messages WHERE to_project='${project}' AND read=0;"
  34. }
  35. # List unread messages (brief) for current project
  36. list_unread() {
  37. init_db
  38. local project
  39. project=$(get_project)
  40. sqlite3 -separator ' | ' "$MAIL_DB" \
  41. "SELECT id, from_project, subject, timestamp FROM messages WHERE to_project='${project}' AND read=0 ORDER BY timestamp DESC;"
  42. }
  43. # Read all unread messages (full) and mark as read
  44. read_mail() {
  45. init_db
  46. local project
  47. project=$(get_project)
  48. sqlite3 -header -separator ' | ' "$MAIL_DB" \
  49. "SELECT id, from_project, subject, body, timestamp FROM messages WHERE to_project='${project}' AND read=0 ORDER BY timestamp ASC;"
  50. sqlite3 "$MAIL_DB" \
  51. "UPDATE messages SET read=1 WHERE to_project='${project}' AND read=0;"
  52. }
  53. # Read a single message by ID and mark as read
  54. read_one() {
  55. local msg_id="$1"
  56. init_db
  57. sqlite3 -header -separator ' | ' "$MAIL_DB" \
  58. "SELECT id, from_project, to_project, subject, body, timestamp FROM messages WHERE id=${msg_id};"
  59. sqlite3 "$MAIL_DB" \
  60. "UPDATE messages SET read=1 WHERE id=${msg_id};"
  61. }
  62. # Send a message
  63. send() {
  64. local to_project="$1"
  65. local subject="$2"
  66. local body="$3"
  67. init_db
  68. local from_project
  69. from_project=$(get_project)
  70. sqlite3 "$MAIL_DB" \
  71. "INSERT INTO messages (from_project, to_project, subject, body) VALUES ('${from_project}', '${to_project}', '${subject}', '${body}');"
  72. echo "Sent to ${to_project}: ${subject}"
  73. }
  74. # List all messages (read and unread) for current project
  75. list_all() {
  76. init_db
  77. local project
  78. project=$(get_project)
  79. local limit="${1:-20}"
  80. sqlite3 -header -separator ' | ' "$MAIL_DB" \
  81. "SELECT id, from_project, subject, CASE WHEN read=0 THEN 'UNREAD' ELSE 'read' END as status, timestamp FROM messages WHERE to_project='${project}' ORDER BY timestamp DESC LIMIT ${limit};"
  82. }
  83. # Clear old read messages (default: older than 7 days)
  84. clear_old() {
  85. init_db
  86. local days="${1:-7}"
  87. local deleted
  88. deleted=$(sqlite3 "$MAIL_DB" \
  89. "DELETE FROM messages WHERE read=1 AND timestamp < datetime('now', '-${days} days'); SELECT changes();")
  90. echo "Cleared ${deleted} read messages older than ${days} days"
  91. }
  92. # List all known projects (that have sent or received mail)
  93. list_projects() {
  94. init_db
  95. sqlite3 "$MAIL_DB" \
  96. "SELECT DISTINCT from_project FROM messages UNION SELECT DISTINCT to_project FROM messages ORDER BY 1;"
  97. }
  98. # Dispatch
  99. case "${1:-help}" in
  100. init) init_db && echo "Mail database initialized at $MAIL_DB" ;;
  101. count) count_unread ;;
  102. unread) list_unread ;;
  103. read) if [ -n "${2:-}" ]; then read_one "$2"; else read_mail; fi ;;
  104. send) send "${2:?to_project required}" "${3:-no subject}" "${4:?body required}" ;;
  105. list) list_all "${2:-20}" ;;
  106. clear) clear_old "${2:-7}" ;;
  107. projects) list_projects ;;
  108. help)
  109. echo "Usage: mail-db.sh <command> [args]"
  110. echo ""
  111. echo "Commands:"
  112. echo " init Initialize database"
  113. echo " count Count unread messages"
  114. echo " unread List unread messages (brief)"
  115. echo " read [id] Read messages and mark as read"
  116. echo " send <to> <subj> <body> Send a message"
  117. echo " list [limit] List recent messages (default 20)"
  118. echo " clear [days] Clear read messages older than N days"
  119. echo " projects List known projects"
  120. ;;
  121. *) echo "Unknown command: $1. Run with 'help' for usage." >&2; exit 1 ;;
  122. esac