Initial commit: claude-automation 🦊
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 💕
This commit is contained in:
725
README.md
Executable file
725
README.md
Executable file
@@ -0,0 +1,725 @@
|
||||
# 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** 🤖
|
||||
Reference in New Issue
Block a user