We live in a computing world that is full of idiots that over complicate everything. It’s a nightmare and needs to stop. Take this problem. I just wanted to sync my clipboard between machines. What do we get ? Planck as well as ClipCascade that force infuriating levels of features and confusion onto the user.

As a case in point I dropped into Gemini CLI …

I need to write a bash script (or alternative language if you think it more suitable) that checks for changes in local macos clipboard. When the clipboard changes the text is made available to companion scripts running on a couple of local network linux machines. 

As it turned out I don’t really need to run the scripts on the other machines. It’s as simple as …

The image above is from my Linux machine showing what the clipboard script is serving.

Above is my macOS machine running on the same local network.

Here is the code. Worked first time.

import http.server
import socketserver
import subprocess
import time
import threading
import sys

PORT = 8080

def get_clipboard_content():
    """Fetches the content of the macOS clipboard."""
    try:
        # pbpaste gets the clipboard content as utf-8
        return subprocess.check_output(['pbpaste']).decode('utf-8')
    except Exception as e:
        return f"Error fetching clipboard: {e}"

class ClipboardRequestHandler(http.server.SimpleHTTPRequestHandler):
    def do_GET(self):
        """Handle GET requests by serving the current clipboard content."""
        self.send_response(200)
        self.send_header('Content-type', 'text/plain; charset=utf-8')
        self.end_headers()
        
        content = get_clipboard_content()
        self.wfile.write(content.encode('utf-8'))

    def log_message(self, format, *args):
        # Silence default access logs to keep the console clean for change notifications
        pass

def monitor_clipboard():
    """Polls the clipboard and prints when changes occur."""
    last_content = get_clipboard_content()
    print(f"[*] Monitor started. Current clipboard length: {len(last_content)} chars")
    
    while True:
        try:
            current_content = get_clipboard_content()
            if current_content != last_content:
                print(f"[+] Clipboard changed! New length: {len(current_content)} chars")
                last_content = current_content
            time.sleep(1)
        except Exception as e:
            print(f"[!] Monitor error: {e}")
            time.sleep(5)

def run_server():
    """Starts the HTTP server."""
    # Allow address reuse to prevent 'Address already in use' errors on restart
    socketserver.TCPServer.allow_reuse_address = True
    with socketserver.TCPServer(("", PORT), ClipboardRequestHandler) as httpd:
        print(f"[*] Serving clipboard at http://0.0.0.0:{PORT}")
        print("[*] Press Ctrl+C to stop.")
        try:
            httpd.serve_forever()
        except KeyboardInterrupt:
            pass
        finally:
            httpd.server_close()
            print("[*] Server stopped.")

if __name__ == "__main__":
    # Start the monitor in a background thread
    monitor_thread = threading.Thread(target=monitor_clipboard, daemon=True)
    monitor_thread.start()
    
    # Run the server in the main thread
    run_server()

77 views

Leave a Reply

Your email address will not be published. Required fields are marked *