client: actually write incoming messages to the OS clipboard

The MVP only printed to stdout. Now the listener calls
clipboard.WriteAll on every received message, except when the message
originated from itself (to avoid clobbering local edits with our own
prior send).

Adds:
- github.com/atotto/clipboard (cross-platform: Win/macOS/Linux)
- -no-clipboard flag for stdout-only mode
- "→ clipboard updated" trace line so the user can confirm the write

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Claude Opus 4.7
2026-05-21 00:19:35 -05:00
parent b8f168df54
commit fa52bf2693
3 changed files with 28 additions and 2 deletions

View File

@@ -1,5 +1,5 @@
// tether-client: connects to a tether-server, prints messages to stdout.
// MVP — does not yet touch the OS clipboard.
// tether-client: connects to a tether-server, writes incoming messages
// to the OS clipboard and prints them to stdout.
package main
import (
@@ -14,6 +14,13 @@ import (
"os"
"strings"
"time"
"github.com/atotto/clipboard"
)
var (
noClipboard bool
myLabel string
)
type Message struct {
@@ -26,13 +33,20 @@ func main() {
server := flag.String("server", "http://localhost:8765", "tether-server base URL")
label := flag.String("label", "linux-client", "X-Tether-Client label")
sendText := flag.String("send", "", "send this text and exit (otherwise listen)")
flag.BoolVar(&noClipboard, "no-clipboard", false, "don't write incoming messages to the OS clipboard")
flag.Parse()
myLabel = *label
if *sendText != "" {
send(*server, *label, *sendText)
return
}
if !noClipboard && clipboard.Unsupported {
fmt.Fprintln(os.Stderr, "tether-client: OS clipboard unsupported on this platform; falling back to stdout-only")
noClipboard = true
}
for {
if err := listen(*server, *label); err != nil {
log.Printf("stream error: %v — reconnecting in 3s", err)
@@ -85,6 +99,14 @@ func listen(server, label string) error {
if err := json.Unmarshal([]byte(data), &m); err == nil {
ts := time.UnixMilli(m.TS).Format("15:04:05")
fmt.Printf("\n────── %s from %s ──────\n%s\n", ts, m.Source, m.Text)
// Don't echo our own message back into our own clipboard
if !noClipboard && m.Source != myLabel {
if err := clipboard.WriteAll(m.Text); err != nil {
fmt.Fprintf(os.Stderr, " ! clipboard write error: %v\n", err)
} else {
fmt.Fprintln(os.Stderr, " → clipboard updated")
}
}
}
}
ev, data = "", ""

2
go.mod
View File

@@ -1,3 +1,5 @@
module github.com/pecord/tether
go 1.22
require github.com/atotto/clipboard v0.1.4

2
go.sum Normal file
View File

@@ -0,0 +1,2 @@
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=