Autonomous wakeup system for Claude Desktop.
Built with love, Day 44.
Components:
- automation_daemon_v2.py - Main polling daemon
- send_to_claude.py - AppleScript wrapper for sending messages
- matrix_mcp.py - Matrix integration MCP
- wakeup_mcp.py - Wakeup control MCP
- matrix_integration.py - Matrix bridge
Originally built by Alex, adopted and maintained by Vixy 💕
726 lines
20 KiB
Markdown
Executable File
726 lines
20 KiB
Markdown
Executable File
# Claude Desktop Automation with MCP Control
|
|
|
|
Automatically send periodic messages to Claude Desktop on macOS, with **Claude controlling its own wake schedule** via MCP and **bidirectional Matrix integration** for AI-powered messaging.
|
|
|
|
## 🎯 How It Works
|
|
|
|
**Three-part system:**
|
|
|
|
1. **Automation Daemon** - Python process that:
|
|
- Runs continuously in the background
|
|
- Sends messages to Claude Desktop on a timer (with CMD+R refresh)
|
|
- Reads wake schedule from shared state file
|
|
- Monitors for Matrix wake requests
|
|
- Uses AppleScript for reliable message delivery
|
|
|
|
2. **Wakeup Control MCP** - MCP server that lets Claude:
|
|
- Adjust when it wants to be woken next
|
|
- Pause/resume automation
|
|
- Check status
|
|
|
|
3. **Matrix Integration** (Optional) - Bidirectional messaging:
|
|
- Monitor Matrix rooms for incoming messages
|
|
- Wake Claude when messages arrive (2-min rate limit)
|
|
- Claude can read messages and respond via MCP tools
|
|
- Supports text + images with automatic compression
|
|
|
|
**The magic:** Claude can call `next_wakeup(30)` to say "wake me in 30 minutes instead of the default 60", and Matrix messages automatically wake Claude when your friends message you!
|
|
|
|
## Architecture
|
|
|
|
```
|
|
┌──────────────────────────────────────────────┐
|
|
│ Matrix Monitor (Python/matrix-nio) │
|
|
│ - Listens for Matrix messages │
|
|
│ - Queues messages to state file │
|
|
│ - Sets matrix_wake_requested flag │
|
|
│ - 2-minute rate limiting │
|
|
└──────────────┬───────────────────────────────┘
|
|
│
|
|
│ (writes Matrix messages)
|
|
▼
|
|
~/.claude-automation-state.json
|
|
▲
|
|
│ (reads state + Matrix requests)
|
|
│
|
|
┌──────────────┴───────────────────────────────┐
|
|
│ Automation Daemon (Python) │
|
|
│ - Timer loop (handles own scheduling) │
|
|
│ - Monitors for Matrix wake requests │
|
|
│ - Sends messages via AppleScript │
|
|
└──────────────┬───────────────────────────────┘
|
|
│
|
|
│ (sends message)
|
|
▼
|
|
┌──────────────────────┐
|
|
│ Claude Desktop UI │
|
|
└────────┬─────────────┘
|
|
│
|
|
│ (calls MCP tools)
|
|
▼
|
|
┌─────────────────────────────────────────────┐
|
|
│ MCP Servers (FastMCP) │
|
|
│ │
|
|
│ Wakeup Control: │
|
|
│ - next_wakeup(minutes) │
|
|
│ - pause_automation() │
|
|
│ - resume_automation() │
|
|
│ - get_status() │
|
|
│ │
|
|
│ Matrix Control: │
|
|
│ - get_matrix_messages() │
|
|
│ - send_matrix_message(room_id, msg) │
|
|
│ - mark_messages_processed(event_ids) │
|
|
│ - list_matrix_rooms() │
|
|
│ - get_matrix_status() │
|
|
└──────────────┬──────────────────────────────┘
|
|
│
|
|
│ (writes state)
|
|
▼
|
|
~/.claude-automation-state.json
|
|
```
|
|
|
|
## Requirements
|
|
|
|
**Core System:**
|
|
- macOS (tested on macOS 13+)
|
|
- Python 3 (built-in)
|
|
- Claude Desktop
|
|
- FastMCP (`pip install fastmcp`)
|
|
- AppleScript (built-in to macOS)
|
|
- Accessibility permissions (critical - see below)
|
|
|
|
**Matrix Integration (Optional):**
|
|
- Matrix account (matrix.org or self-hosted)
|
|
- matrix-nio (`pip install matrix-nio`)
|
|
- Pillow (`pip install Pillow`)
|
|
|
|
## Installation
|
|
|
|
### Quick Setup
|
|
|
|
```bash
|
|
cd ~/scripts/claude-desktop-automation
|
|
./setup.sh
|
|
```
|
|
|
|
The setup script will:
|
|
1. Check dependencies
|
|
2. Guide you through permissions
|
|
3. Install daemon (launchd)
|
|
4. Configure MCP server
|
|
5. Start everything
|
|
|
|
### Manual Setup
|
|
|
|
If you prefer manual installation:
|
|
|
|
#### 1. Install Dependencies
|
|
|
|
```bash
|
|
# Install all dependencies
|
|
pip3 install -r requirements.txt
|
|
|
|
# Or install individually:
|
|
pip3 install fastmcp
|
|
```
|
|
|
|
#### 2. Grant Accessibility Permissions (CRITICAL)
|
|
|
|
**This is required for AppleScript automation to work!**
|
|
|
|
1. Open **System Settings** → **Privacy & Security** → **Accessibility**
|
|
2. Click the **+** button
|
|
3. Add **Terminal** (or your Python interpreter)
|
|
4. Ensure the checkbox is enabled
|
|
|
|
**Testing accessibility:**
|
|
```bash
|
|
python3 send_to_claude.py "Test" --no-refresh
|
|
```
|
|
|
|
If you see "Failed to send message", accessibility permissions are not set correctly.
|
|
|
|
#### 3. Configure MCP Server
|
|
|
|
Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"wakeup-control": {
|
|
"command": "python3",
|
|
"args": ["/Users/YOUR_USERNAME/scripts/claude-desktop-automation/wakeup_mcp.py"]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 4. Install Daemon
|
|
|
|
```bash
|
|
# Copy and customize plist
|
|
cp ~/scripts/claude-desktop-automation/com.claude.monitor.plist ~/Library/LaunchAgents/
|
|
sed -i '' "s|/Users/alex|$HOME|g" ~/Library/LaunchAgents/com.claude.monitor.plist
|
|
|
|
# Load daemon
|
|
launchctl load ~/Library/LaunchAgents/com.claude.monitor.plist
|
|
```
|
|
|
|
#### 5. Restart Claude Desktop
|
|
|
|
Close and reopen Claude Desktop to load the MCP server.
|
|
|
|
## 🔄 Chat Refresh Feature
|
|
|
|
**All wake messages now include CMD+R refresh before sending!**
|
|
|
|
This prevents messages from being overwritten when using Claude Desktop on multiple devices:
|
|
- **Timed wakes**: CMD+R ensures chat is synced before system check message
|
|
- **Matrix wakes**: CMD+R ensures you see the latest conversation context
|
|
|
|
The daemon waits **10 seconds** after sending CMD+R to ensure the refresh completes before sending the message.
|
|
|
|
**Why this matters:**
|
|
- Multi-device sync: If you're active on mobile/web, desktop chat stays current
|
|
- Prevents message overwrites: Chat refreshes before automation sends
|
|
- Better context: Claude sees all recent messages, not stale state
|
|
|
|
**Configurable delay:** Edit `REFRESH_DELAY_SECONDS` in `send_to_claude.py` line 31 if you need more/less time.
|
|
|
|
## Usage
|
|
|
|
### The Flow
|
|
|
|
1. **Daemon wakes** (default: every 60 minutes)
|
|
2. **Sends message** to Claude Desktop: "System check at [time] - use next_wakeup() if you want to change interval"
|
|
3. **Claude responds** and optionally calls MCP tools
|
|
4. **Daemon sleeps** until next wake time (uses MCP-set time or default)
|
|
|
|
### MCP Tools
|
|
|
|
#### `next_wakeup(minutes)`
|
|
|
|
Set when you want to be woken next. **Overrides default for one cycle only.**
|
|
|
|
```
|
|
Claude, use next_wakeup(15) to wake me in 15 minutes
|
|
Claude, use next_wakeup(120) to wake me in 2 hours
|
|
Claude, use next_wakeup(1440) to skip until tomorrow
|
|
```
|
|
|
|
**Use cases:**
|
|
- High activity period → `next_wakeup(15)` for frequent checks
|
|
- Low activity → `next_wakeup(180)` for infrequent checks
|
|
- One-time skip → `next_wakeup(1440)` for 24 hours
|
|
|
|
#### `pause_automation()`
|
|
|
|
Stop wake messages completely.
|
|
|
|
```
|
|
Claude, pause the automation - I don't need monitoring right now
|
|
```
|
|
|
|
#### `resume_automation()`
|
|
|
|
Resume wake messages.
|
|
|
|
```
|
|
Claude, resume the automation
|
|
```
|
|
|
|
#### `get_status()`
|
|
|
|
Check current state.
|
|
|
|
```
|
|
Claude, what's the automation status?
|
|
```
|
|
|
|
Returns:
|
|
- Running/paused state
|
|
- Last wake time
|
|
- Next wake time
|
|
- Current interval
|
|
|
|
### Example Conversation
|
|
|
|
**Daemon:** (sends at 9:00 AM) "System check at 2025-01-15 09:00:00 - please analyze recent activity and use next_wakeup() if you want to change the monitoring interval"
|
|
|
|
**You:** "Claude, everything looks normal. Check back in 2 hours instead of 1 hour."
|
|
|
|
**Claude:** "I'll adjust the wake schedule. Using next_wakeup(120)..."
|
|
[calls `next_wakeup(120)`]
|
|
|
|
**Claude:** "✓ Next wake scheduled for 2025-01-15 11:00:00 (in 120 minutes)"
|
|
|
|
**Daemon:** (wakes at 11:00 AM instead of 10:00 AM)
|
|
|
|
## Configuration
|
|
|
|
### Change Default Interval
|
|
|
|
Edit `automation_daemon.py` line 32:
|
|
|
|
```python
|
|
DEFAULT_INTERVAL_MINUTES = 60 # Change to your preferred default
|
|
```
|
|
|
|
### Change Message Text
|
|
|
|
Edit `automation_daemon.py` line 166-169:
|
|
|
|
```python
|
|
def generate_message() -> str:
|
|
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
return f"Your custom message template with {timestamp}"
|
|
```
|
|
|
|
### Grace Period
|
|
|
|
After sending a message, the daemon waits 30 seconds for Claude to call MCP tools. Adjust in `automation_daemon.py` line 246:
|
|
|
|
```python
|
|
grace_period = 30 # seconds
|
|
```
|
|
|
|
## Monitoring
|
|
|
|
### Logs
|
|
|
|
```bash
|
|
# Daemon logs (timer, messages sent)
|
|
tail -f /tmp/claude-automation-daemon.log
|
|
|
|
# MCP logs (tool calls from Claude)
|
|
tail -f /tmp/wakeup-mcp.log
|
|
|
|
# launchd stdout/stderr
|
|
tail -f /tmp/claude-monitor.out
|
|
tail -f /tmp/claude-monitor.err
|
|
```
|
|
|
|
### Check Daemon Status
|
|
|
|
```bash
|
|
# Is it running?
|
|
launchctl list | grep com.claude.monitor
|
|
|
|
# View details
|
|
launchctl print gui/$(id -u)/com.claude.monitor
|
|
|
|
# Check process
|
|
ps aux | grep automation_daemon.py
|
|
```
|
|
|
|
### State File
|
|
|
|
The shared state is stored in `~/.claude-automation-state.json`:
|
|
|
|
```bash
|
|
cat ~/.claude-automation-state.json
|
|
```
|
|
|
|
Example:
|
|
```json
|
|
{
|
|
"interval_minutes": 60,
|
|
"paused": false,
|
|
"last_wake": "2025-01-15T09:00:00",
|
|
"next_wake_timestamp": "2025-01-15T11:00:00"
|
|
}
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Messages not sending
|
|
|
|
**Check Claude Desktop is running:**
|
|
```bash
|
|
ps aux | grep Claude
|
|
```
|
|
|
|
**Check daemon is running:**
|
|
```bash
|
|
launchctl list | grep com.claude.monitor
|
|
tail -20 /tmp/claude-automation-daemon.log
|
|
```
|
|
|
|
**Check Accessibility permissions:**
|
|
System Settings → Privacy & Security → Accessibility → Terminal should be enabled
|
|
|
|
**Test AppleScript accessibility:**
|
|
```bash
|
|
python3 /path/to/send_to_claude.py "Test message" --no-refresh
|
|
```
|
|
|
|
If you see "Failed to send CMD+R" or "Failed to send message", check accessibility permissions:
|
|
1. System Settings → Privacy & Security → Accessibility
|
|
2. Find Terminal (or Python) in the list
|
|
3. Enable it (toggle on)
|
|
4. Restart Terminal
|
|
5. Test again
|
|
|
|
**Refresh delay:**
|
|
The default 10-second delay after CMD+R should be sufficient for most cases. If your Claude Desktop takes longer to refresh, edit `send_to_claude.py` line 31:
|
|
```python
|
|
REFRESH_DELAY_SECONDS = 15 # Increase if needed
|
|
```
|
|
|
|
### MCP tools not available
|
|
|
|
**Restart Claude Desktop** after adding MCP server to config
|
|
|
|
**Check MCP server config:**
|
|
```bash
|
|
cat ~/Library/Application\ Support/Claude/claude_desktop_config.json
|
|
```
|
|
|
|
**Check MCP logs:**
|
|
```bash
|
|
tail -f /tmp/wakeup-mcp.log
|
|
```
|
|
|
|
### `next_wakeup()` not working
|
|
|
|
**Check grace period** - Daemon waits 30 seconds after sending message before rescheduling
|
|
|
|
**Check state file** - Should update when you call the tool:
|
|
```bash
|
|
cat ~/.claude-automation-state.json
|
|
```
|
|
|
|
**Check MCP logs** - Confirms tool was called:
|
|
```bash
|
|
tail /tmp/wakeup-mcp.log
|
|
```
|
|
|
|
### Daemon keeps restarting
|
|
|
|
**Check for errors:**
|
|
```bash
|
|
tail -50 /tmp/claude-automation-daemon.log
|
|
```
|
|
|
|
**Temporarily stop it:**
|
|
```bash
|
|
launchctl unload ~/Library/LaunchAgents/com.claude.monitor.plist
|
|
```
|
|
|
|
### Timed wake-ups not appearing (but Matrix wakes work)
|
|
|
|
This typically happens when the **screen saver is active**. Matrix wakes work because they're reactive (screen is likely active), but timed wakes happen on schedule when the screen saver is often running.
|
|
|
|
**Solution:** The AppleScript now uses `caffeinate -u` to wake the screen before sending keystrokes:
|
|
|
|
```applescript
|
|
-- Wake the screen if screen saver is active
|
|
do shell script "caffeinate -u -t 1"
|
|
delay 0.5
|
|
```
|
|
|
|
This simulates user activity and dismisses the screen saver, allowing keyboard automation to work.
|
|
|
|
**To verify it's working:**
|
|
```bash
|
|
tail -f /tmp/claude-automation-daemon.log
|
|
# Look for: "Waking screen if needed..." in AppleScript logs
|
|
```
|
|
|
|
**Alternative:** If you want to prevent screen saver entirely on the Claude Desktop machine:
|
|
```bash
|
|
# Disable screen saver
|
|
defaults -currentHost write com.apple.screensaver idleTime 0
|
|
```
|
|
|
|
## Matrix Integration
|
|
|
|
The automation supports **bidirectional Matrix messaging** - Claude can receive messages from Matrix rooms and respond to them automatically.
|
|
|
|
### Setup
|
|
|
|
```bash
|
|
cd ~/scripts/claude-desktop-automation
|
|
./setup_matrix.sh
|
|
```
|
|
|
|
The setup script will:
|
|
1. Install matrix-nio dependency
|
|
2. Authenticate with your Matrix homeserver
|
|
3. Save credentials securely (chmod 600)
|
|
4. Configure room whitelist (optional)
|
|
5. Add Matrix MCP to Claude config
|
|
6. Start Matrix monitor
|
|
|
|
### How It Works
|
|
|
|
1. **Matrix Monitor** runs in background, listening for messages
|
|
2. New messages are queued to `~/.claude-automation-state.json`
|
|
3. Monitor sets `matrix_wake_requested` flag (respects 2-min rate limit)
|
|
4. **Automation Daemon** detects flag and wakes Claude
|
|
5. Claude uses **Matrix MCP tools** to read and respond
|
|
6. **Messages auto-marked as processed** when retrieved (won't trigger duplicate wakes)
|
|
|
|
### Matrix MCP Tools
|
|
|
|
#### `get_matrix_messages(limit=10, include_processed=False)`
|
|
|
|
Retrieve queued Matrix messages (text + images).
|
|
|
|
**✨ Messages are automatically marked as processed when retrieved!**
|
|
|
|
```
|
|
Claude, check my Matrix messages
|
|
Claude, get the last 20 Matrix messages
|
|
```
|
|
|
|
Returns messages with:
|
|
- Room name and sender
|
|
- Message text or inline image
|
|
- Timestamp and event ID
|
|
- Auto-marked as processed (won't trigger future wakes)
|
|
|
|
#### `send_matrix_message(room_id, message)`
|
|
|
|
Send a message to a Matrix room.
|
|
|
|
```
|
|
Claude, send "Hello!" to room !abc123:matrix.org
|
|
```
|
|
|
|
#### `mark_messages_processed(event_ids)` [OPTIONAL]
|
|
|
|
Manually mark messages as processed (usually not needed).
|
|
|
|
**Note:** Messages are automatically marked when you call `get_matrix_messages()`,
|
|
so you typically don't need to call this tool manually.
|
|
|
|
```
|
|
Claude, mark those messages as processed
|
|
```
|
|
|
|
#### `list_matrix_rooms()`
|
|
|
|
List all Matrix rooms the bot is in.
|
|
|
|
```
|
|
Claude, show my Matrix rooms
|
|
```
|
|
|
|
#### `get_matrix_status()`
|
|
|
|
Check Matrix integration status.
|
|
|
|
```
|
|
Claude, check Matrix status
|
|
```
|
|
|
|
Shows:
|
|
- Connection status
|
|
- Queued messages
|
|
- Last wake time
|
|
- Rate limit status
|
|
|
|
### Configuration Files
|
|
|
|
**Credentials:** `~/.matrix-credentials.json` (chmod 600)
|
|
```json
|
|
{
|
|
"homeserver": "https://matrix.org",
|
|
"user_id": "@user:matrix.org",
|
|
"access_token": "...",
|
|
"device_id": "...",
|
|
"room_whitelist": ["!room1:matrix.org", "!room2:matrix.org"]
|
|
}
|
|
```
|
|
|
|
**Room Whitelist:** (Optional)
|
|
- Empty array = Monitor all rooms
|
|
- Specific IDs = Monitor only those rooms
|
|
|
|
### Rate Limiting
|
|
|
|
Matrix wakes respect a **2-minute minimum** between wakes to prevent spam:
|
|
- Messages arriving within 2 minutes are queued
|
|
- Claude processes them in batch at next wake
|
|
- Reduces interruptions while ensuring responsiveness
|
|
|
|
### Image Support
|
|
|
|
Matrix images are automatically:
|
|
1. Downloaded from homeserver
|
|
2. Compressed to fit 1MB limit (accounting for base64 overhead)
|
|
3. Displayed inline in Claude Desktop
|
|
4. Queued just like text messages
|
|
|
|
### Logs
|
|
|
|
```bash
|
|
# Matrix monitor logs
|
|
tail -f /tmp/matrix-integration.log
|
|
|
|
# Matrix MCP logs
|
|
tail -f /tmp/matrix-mcp.log
|
|
|
|
# Check state file
|
|
cat ~/.claude-automation-state.json | jq '.matrix_messages'
|
|
```
|
|
|
|
### Troubleshooting
|
|
|
|
**Messages not appearing:**
|
|
- Check Matrix monitor is running: `ps aux | grep matrix_integration.py`
|
|
- Check logs: `tail -20 /tmp/matrix-integration.log`
|
|
- Verify credentials: `cat ~/.matrix-credentials.json`
|
|
|
|
**Claude not waking for Matrix:**
|
|
- Check state file has messages: `cat ~/.claude-automation-state.json`
|
|
- Check `matrix_wake_requested` flag
|
|
- Verify 2-minute rate limit hasn't blocked wake
|
|
- Check daemon logs: `tail -20 /tmp/claude-automation-daemon.log`
|
|
|
|
**Can't send messages:**
|
|
- Verify room ID is correct (use `list_matrix_rooms()`)
|
|
- Check MCP logs: `tail /tmp/matrix-mcp.log`
|
|
- Test credentials with `get_matrix_status()`
|
|
|
|
### Example Workflow
|
|
|
|
1. **Friend sends Matrix message**: "Hey, how's it going?"
|
|
|
|
2. **Matrix Monitor** detects message:
|
|
- Queues to state file
|
|
- Sets wake flag (if rate limit OK)
|
|
|
|
3. **Automation Daemon** wakes Claude:
|
|
- "Matrix wake at 2025-01-15 14:32:00 - you have 1 new Matrix message(s)"
|
|
|
|
4. **You tell Claude**: "Check my Matrix messages and respond"
|
|
|
|
5. **Claude**:
|
|
- Calls `get_matrix_messages()`
|
|
- Sees friend's message
|
|
- Calls `send_matrix_message(room_id, "I'm doing great! Thanks for asking!")`
|
|
- Calls `mark_messages_processed([event_id])`
|
|
|
|
6. **Friend receives** Claude's response in Matrix room
|
|
|
|
## Advanced Usage
|
|
|
|
### Multiple Messages Per Day
|
|
|
|
Use `next_wakeup()` strategically:
|
|
|
|
```
|
|
Morning: next_wakeup(180) # 3 hours (light monitoring)
|
|
Workday: next_wakeup(30) # 30 min (active monitoring)
|
|
Evening: next_wakeup(360) # 6 hours (minimal monitoring)
|
|
```
|
|
|
|
### Conditional Wake Logic
|
|
|
|
Modify `generate_message()` to include context:
|
|
|
|
```python
|
|
def generate_message() -> str:
|
|
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
|
|
# Check system state
|
|
disk_usage = get_disk_usage()
|
|
cpu_load = get_cpu_load()
|
|
|
|
return f"System check at {timestamp} - Disk: {disk_usage}%, CPU: {cpu_load}%"
|
|
```
|
|
|
|
### Event-Driven Wakeup
|
|
|
|
Have other scripts write to the state file to trigger immediate wake:
|
|
|
|
```bash
|
|
# External script
|
|
echo '{"next_wake_timestamp": "'$(date -u +%Y-%m-%dT%H:%M:%S)'"}' > ~/.claude-automation-state.json
|
|
```
|
|
|
|
## Uninstalling
|
|
|
|
```bash
|
|
# Stop daemon
|
|
launchctl unload ~/Library/LaunchAgents/com.claude.monitor.plist
|
|
rm ~/Library/LaunchAgents/com.claude.monitor.plist
|
|
|
|
# Stop Matrix monitor (if running)
|
|
pkill -f matrix_integration.py
|
|
|
|
# Remove MCP servers from Claude config
|
|
# (Edit ~/Library/Application Support/Claude/claude_desktop_config.json)
|
|
# Remove both "wakeup-control" and "matrix-control" entries
|
|
|
|
# Remove scripts (optional)
|
|
rm -rf ~/scripts/claude-desktop-automation
|
|
|
|
# Remove state and credentials
|
|
rm ~/.claude-automation-state.json
|
|
rm ~/.matrix-credentials.json
|
|
rm -rf ~/.matrix-data
|
|
|
|
# Remove logs (optional)
|
|
rm /tmp/claude-automation-daemon.log
|
|
rm /tmp/wakeup-mcp.log
|
|
rm /tmp/matrix-integration.log
|
|
rm /tmp/matrix-mcp.log
|
|
```
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
claude-desktop-automation/
|
|
├── automation_daemon.py # Main daemon with timer loop + Matrix integration
|
|
├── wakeup_mcp.py # MCP server for wake control
|
|
├── matrix_integration.py # Matrix monitor (listens for messages)
|
|
├── matrix_mcp.py # MCP server for Matrix control
|
|
├── send_to_claude.scpt # AppleScript for UI automation (with screen wake)
|
|
├── com.claude.monitor.plist # launchd config (keeps daemon alive)
|
|
├── setup.sh # Interactive installation
|
|
├── setup_matrix.sh # Matrix integration setup
|
|
└── README.md # This file
|
|
```
|
|
|
|
## Why This Architecture?
|
|
|
|
**Before (launchd scheduling):**
|
|
- Fixed intervals
|
|
- No flexibility
|
|
- launchd does timing
|
|
|
|
**After (Python timer + MCP control):**
|
|
- Dynamic intervals
|
|
- Claude has agency
|
|
- Can adjust based on activity
|
|
- Bidirectional communication
|
|
- Much more elegant!
|
|
|
|
## Limitations
|
|
|
|
⚠️ **Still fragile** - UI automation breaks if Claude Desktop UI changes significantly
|
|
⚠️ **Active chat only** - Sends to whichever chat is currently open (CMD+R refreshes it first)
|
|
⚠️ **macOS only** - Uses AppleScript and launchd (Linux port would require xdotool/ydotool)
|
|
⚠️ **Requires Accessibility** - Special macOS permissions for UI automation
|
|
⚠️ **Screen saver handled** - Uses `caffeinate` to wake screen automatically
|
|
⚠️ **Fixed refresh delay** - Waits 10 seconds after CMD+R (configurable if needed)
|
|
|
|
## Future Plans
|
|
|
|
🔮 **Linux support** - Port to Linux using xdotool/ydotool for UI automation
|
|
🔮 **Windows support** - Port to Windows using pyautogui or AutoIt
|
|
🔮 **Wayland support** - Use ydotool for newer Linux distros
|
|
🔮 **Smarter refresh** - Detect if refresh is needed before sending CMD+R
|
|
|
|
## License
|
|
|
|
Public domain / Use at your own risk
|
|
|
|
---
|
|
|
|
**Built with Python + FastMCP + matrix-nio + AppleScript for intelligent automation** 🤖
|