// clip-sync — bidirectional LAN clipboard synchronization daemon. // // Usage: // // clip-sync [--config path] // // clip-sync polls the local clipboard every 500 ms and broadcasts any new // text content to all configured peers via HTTP POST /clip. It also runs an // HTTP server on :9137 (configurable) to receive clips from peers and write // them to the local clipboard. // // Configuration is read from ~/.config/clip-sync/peers.toml (TOML format). // Environment variables CLIP_SYNC_PORT and CLIP_SYNC_POLL_MS override // the corresponding config values. package main import ( "context" "flag" "fmt" "log" "os" "os/signal" "syscall" "git.dracodev.net/Projets/clip-sync/internal/config" "git.dracodev.net/Projets/clip-sync/internal/daemon" ) var version = "dev" func main() { showVersion := flag.Bool("version", false, "print version and exit") flag.Parse() if *showVersion { fmt.Printf("clip-sync %s\n", version) return } log.SetFlags(log.LstdFlags | log.Lshortfile) log.SetPrefix("") cfg, err := config.Load() if err != nil { log.Fatalf("clip-sync: config: %v", err) } d, err := daemon.New(cfg) if err != nil { log.Fatalf("clip-sync: init: %v", err) } ctx, cancel := context.WithCancel(context.Background()) defer cancel() // Handle graceful shutdown on SIGINT / SIGTERM. sigCh := make(chan os.Signal, 1) signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) go func() { sig := <-sigCh log.Printf("clip-sync: received %v, shutting down...", sig) cancel() }() if err := d.Run(ctx); err != nil && err != context.Canceled { log.Fatalf("clip-sync: %v", err) } log.Println("clip-sync: stopped") }