Sync Socket

A desktop daemon can keep your other computers' clones current by listening for pushes instead of polling. Connect a Phoenix Channels client (protocol 2.0.0) to wss://git.vianet.us/socket/sync/websocket?vsn=2.0.0 with a personal access token that has the read_api or api scope.

Authenticating

Send the token as the websocket subprotocol base64url.bearer.phx.<token>, the token Base64-encoded without padding, which is what Phoenix's JavaScript client sends for its authToken option. Prefer it: query strings end up in proxy logs. A client that can't set a subprotocol may add &token=<token> to the URL instead.

An IP address may connect 30 times a minute, and an account may have 10 joined channels at once; the next join is refused with too many connections. A join is refused with unauthorized once the token is revoked or expired, or the account is banned, deleted or must set up two-factor authentication. Open connections are dropped when any of that happens, when the token expires and when an admin loses admin rights.

Push events

Join the sync:pushes topic; the reply carries the server's server_time. Every push, merge or new branch in a repository you can read then arrives as a push event:

{"project_id": 42, "path_with_namespace": "alice/app",
 "ssh_url_to_repo": "git@host:alice/app.git", "http_url_to_repo": "https://host/alice/app.git",
 "ref": "refs/heads/main", "before": "<old sha, 40 zeros for a new branch>", "after": "<new sha>",
 "pusher": "alice", "pushed_at": "2026-10-16T12:00:00Z",
 "mirror_sources": [{"provider": "github", "remote_repo_name": "alice/app"}]}

mirror_sources lists the repository's pull mirrors for its maintainers; everyone else gets an empty list.

Catching up

After a reconnect, send catch_up with the last server_time you saw as since (ISO 8601). The reply's pushes holds the newest push per repository and branch at or after since, looking back 30 days at most, to the second (so you may see one push again), newest first, at most 500; truncated is true when more matched, so fetch everything instead. A channel answers one catch_up every 10 seconds (too many requests otherwise); an unreadable since is refused with invalid since and any other event with unknown event.