No description
  • Go 80.2%
  • JavaScript 12.1%
  • HTML 5.8%
  • Makefile 1.1%
  • Dockerfile 0.8%
Find a file
John McCardle 195ada4fd7
Some checks failed
ci / test (push) Has been cancelled
Track cmd/; .gitignore was hiding both binaries' source
The previous commit pushed a tree that cannot build. `go build ./cmd/...`
matched nothing and `make dist` produced no binaries.

.gitignore listed the built binaries as bare names:

    gobbomesh-node
    gobbomesh-relay

An unanchored pattern matches at any depth, so alongside the intended
build output at the repo root git also ignored the source directories
cmd/gobbomesh-node/ and cmd/gobbomesh-relay/. Ignored paths are not
reported as untracked, so `git status` was clean and the omission was
invisible right up to the point where someone tried to build a clone.

Both patterns are now anchored to the repository root, which is what they
always meant, with a comment saying why the slash is load-bearing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P7NRCiFRzCV1QVVsMyNjNg
2026-09-07 20:26:42 -04:00
.github/workflows Add relay, probe, report, web and the deployment path 2026-09-07 17:59:11 -04:00
cmd Track cmd/; .gitignore was hiding both binaries' source 2026-09-07 20:26:42 -04:00
deploy Add relay, probe, report, web and the deployment path 2026-09-07 17:59:11 -04:00
docs Add relay, probe, report, web and the deployment path 2026-09-07 17:59:11 -04:00
probe Add relay, probe, report, web and the deployment path 2026-09-07 17:59:11 -04:00
relay Add relay, probe, report, web and the deployment path 2026-09-07 17:59:11 -04:00
rendezvous Add relay, probe, report, web and the deployment path 2026-09-07 17:59:11 -04:00
report Add relay, probe, report, web and the deployment path 2026-09-07 17:59:11 -04:00
web Add relay, probe, report, web and the deployment path 2026-09-07 17:59:11 -04:00
.gitignore Track cmd/; .gitignore was hiding both binaries' source 2026-09-07 20:26:42 -04:00
ARCHITECTURE.md Add relay, probe, report, web and the deployment path 2026-09-07 17:59:11 -04:00
Containerfile Add relay, probe, report, web and the deployment path 2026-09-07 17:59:11 -04:00
go.mod Add relay, probe, report, web and the deployment path 2026-09-07 17:59:11 -04:00
go.sum Add relay, probe, report, web and the deployment path 2026-09-07 17:59:11 -04:00
LICENSE initial commit 2026-09-06 18:00:42 -04:00
Makefile Add relay, probe, report, web and the deployment path 2026-09-07 17:59:11 -04:00
README.md Add relay, probe, report, web and the deployment path 2026-09-07 17:59:11 -04:00

gobbomesh

Explain why your phone can't reach your PC, then connect them anyway.

A Go library, a pair of binaries, and a browser client that work out — step by step, on both screens at once — why a device on your LAN can't reach a server on your LAN. Then they establish the best connection that is actually available.

Status: the diagnosis works; transport is not built. Ladder tiers 0 and 1, the address comparison and the correlation loop are implemented and tested — which is every cause listed below, with no WebRTC. See docs/status.md, ARCHITECTURE.md and docs/adr/.


The problem

You run a server on your desktop. You want to open it from your phone. Both devices are ten feet apart on the same Wi-Fi. The browser says:

This site can't be reached

That message is true and useless. It is the same message for:

  • Windows Firewall silently dropping the packet
  • the server bound to 127.0.0.1 instead of 0.0.0.0
  • the router isolating wireless clients from each other
  • the phone on a VPN that swallows LAN traffic
  • the phone on cellular, not Wi-Fi at all
  • the phone on the guest SSID
  • a typo in the port

Six of those seven are fixable in under a minute if you know which one it is. gobbomesh's job is to tell you which one it is.

How

Two devices that cannot talk to each other directly can still both talk to a third party on the internet. gobbomesh uses that third party as a whiteboard, not a pipe: each side announces what it is about to try, the other side watches for it and reports what it saw. Comparing "what I sent" against "what you received" distinguishes failures that look identical from either side alone.

The whiteboard is cheap — a few hundred bytes per diagnosis — and it carries only ciphertext. The key never reaches it.

Once the diagnosis is done, the same machinery establishes a connection over whichever tier turned out to work.

Try it

make build

# Everything the node can work out on its own: no phone, no relay, no network.
./dist/gobbomesh-node -self-check

That alone catches a server bound to 127.0.0.1 and a closed port — two of the seven causes above — because the node connects to each of its own addresses and compares what happens.

For the rest you need a phone and, for the fallback path, a relay:

# On a $5 VPS, or anywhere with a public address.
./dist/gobbomesh-relay -listen :8080 \
  -reflect-v4-url https://v4.example.net/v1/reflect \
  -reflect-v6-url https://v6.example.net/v1/reflect

# On the machine that is meant to be reachable.
./dist/gobbomesh-node -relay https://relay.example.net

The node prints a QR code. Scan it from the phone. If nothing loads, press Enter — that keypress is the first packet this program sends to any third party — and scan the second code it prints.

There is no default relay address. Without -relay the fallback path is unavailable and says so; nothing is contacted that you did not name.

The three pieces

what it is who runs it
library Report (the diagnosis) and Listen/Dial (the transport) anyone embedding gobbomesh
node a demo local server + the browser client, exercising the whole flow the user, on their own machine
relay STUN reflection + an encrypted rendezvous mailbox us, free — or you, on a $5 VPS

The library half is report (the rules, no I/O), probe (observation), rendezvous (the encrypted mailbox) and relay. Both binaries are thin wrappers over them, and the node exposes the same state over REST that its terminal UI and its /console page render — so the CLI, the web console and anything else are interchangeable surfaces on one API.

Design commitments

  • Third-party servers are a last resort. A user whose LAN works never sends us a packet. First contact with the relay happens at the moment the user clicks "it isn't working", and that click is the consent step.
  • The relay cannot read your traffic. Key material travels in the QR code and in the URL fragment, neither of which the relay ever receives. See ADR-0004 for the one case where this requires trusting us, and how self-hosting removes it.
  • The free relay does not carry your bytes. It signals; it does not tunnel. Relay transport is a self-host tier. See ADR-0002.
  • We learn nothing about your problem. Classification happens on your two devices. The relay sees ciphertext, two public addresses, and a byte count.
  • Self-hosting is a first-class deployment, not a grudging option. The relay is a single small Go binary with no database. See docs/deploying-a-relay.md.

Relationship to gobbonet

gobbonet is the project this came out of, and its first consumer. gobbomesh knows nothing about LLMs and never will. gobbonet is AGPL-3.0; gobbomesh is MIT so it can be imported by anything, including gobbonet. See ADR-0008.

License

MIT. See LICENSE.