Learn R Programming

autosync

R sync server and client for Automerge CRDT documents. Implements the automerge-repo WebSocket protocol, enabling R to serve as a synchronization hub for Automerge clients in R, JavaScript, Rust, and other languages, and to act as a client that fetches, edits, and synchronizes documents hosted on remote servers.

Features

  • Full automerge-repo protocol compatibility (interoperates with sync.automerge.org)
  • Secure connections via TLS (wss://)
  • Persistent document storage
  • Ephemeral message broadcasting
  • Client functions for fetching documents from remote servers

Installation

Install the released version from CRAN:

install.packages("autosync")

Or the development version from GitHub:

pak::pak("posit-dev/autosync")

Server

Create a WebSocket sync server:

library(autosync)

server <- sync_server()
server$start()
server

# Server runs non-blocking in the background

server$close()

With TLS for secure connections:

cert <- nanonext::write_cert()
tls <- nanonext::tls_config(server = cert$server)

server <- sync_server(tls = tls)
server$start()
server$url

Authentication

Enable OIDC authentication to restrict access. The defaults point to Google, but any OIDC-compliant provider (Microsoft Entra, Okta, Auth0, etc.) can be used by setting the issuer argument.

Register your OAuth client as a "Desktop app" and set the OIDC_CLIENT_ID and OIDC_CLIENT_SECRET environment variables (e.g. in .Renviron):

# .Renviron
OIDC_CLIENT_ID=YOUR_CLIENT_ID
OIDC_CLIENT_SECRET=YOUR_CLIENT_SECRET

Google issues a client secret for Desktop app clients and requires it in the token exchange, but — unlike a "Web application" secret — it is not treated as confidential: it is designed to be distributed with installed apps, so it is safe to keep in .Renviron. Google states that for installed apps "the client secret is obviously not treated as a secret" (Google OAuth 2.0 docs), consistent with the OAuth 2.0 for Native Apps standard (RFC 8252 §8.5). The interactive flow also uses PKCE, so the secret alone does not grant access.

Other providers (Microsoft Entra, Okta, Auth0, etc.) can register the client as a native / public client, which authenticates via PKCE alone — for those, set only OIDC_CLIENT_ID and leave OIDC_CLIENT_SECRET unset.

cert <- nanonext::write_cert()
tls <- nanonext::tls_config(server = cert$server)

server <- sync_server(
  tls = tls,  # TLS required when auth is enabled
  auth = auth_config(allowed_domains = "posit.co")
)
server$start()

Clients obtain a token interactively, then pass it when fetching:

token <- sync_token()

tlsclient <- nanonext::tls_config(client = cert$client)
doc <- sync_fetch(
  server$url,
  "35ei6ouA7nLhtjmf3d9xk1KKvtKv",
  token = token,
  tls = tlsclient
)

Sharing policy

The share parameter controls which documents are announced to clients and which requests are allowed. It accepts TRUE, FALSE, NA, or a function returning one of these per client and document:

ValueAnnounceAllow requests
NA (default)NoYes
TRUEYesYes
FALSENoNo

Announce all documents to every client that connects:

server <- sync_server(share = TRUE)

Combine with authentication and use a share function for fine-grained access control. The function receives the client_id and doc_id, and can look up the authenticated email on the connection to decide:

# Allow list of emails that can access documents
allowed <- c("[email protected]", "[email protected]")

server <- sync_server(
  tls = tls,
  auth = auth_config(),
  share = function(client_id, doc_id) {
    state <- attr(server, "sync")
    conn <- state$connections[[client_id]]
    if (conn$authenticated_email %in% allowed) NA else FALSE
  }
)

Document management

# Create a new document
doc_id <- create_document(server)

# List all documents
list_documents(server)

# Get a document
doc <- get_document(server, doc_id)

Connecting from JavaScript

import { Repo } from "@automerge/automerge-repo"
import { BrowserWebSocketClientAdapter } from "@automerge/automerge-repo-network-websocket"

const repo = new Repo({
  network: [new BrowserWebSocketClientAdapter("ws://localhost:8080")]
})

Client

Fetch a document from any automerge-repo sync server in a single, one-off retrieval over a throwaway connection:

# Fetch from public sync server
doc <- sync_fetch("wss://sync.automerge.org", "your-document-id")

# Inspect document structure
str(doc)

# Or verbose fetch for debugging sync issues
doc <- sync_fetch("wss://sync.automerge.org", "your-document-id", verbose = TRUE)

Live connections

For a persistent connection that keeps documents in sync — receiving real-time updates from other peers and flushing local changes — use sync_client(). Several documents can share a single connection, each opened with $open_doc():

conn <- sync_client("wss://sync.automerge.org")

# Open a live document over the connection
doc <- conn$open_doc("your-document-id")
automerge::am_keys(doc$doc)

# Make local changes and push them to the server
automerge::am_put(doc$doc, automerge::AM_ROOT, "key", "value")
doc$push()

# Open another document over the same connection
other <- conn$open_doc("another-document-id")

# Disconnect (closes every document on the connection)
conn$close()

Utilities

Generate document IDs compatible with automerge-repo:

doc_id <- generate_document_id()

Links

Copy Link

Version

Install

install.packages('autosync')

Monthly Downloads

423

Version

0.2.0

License

MIT + file LICENSE

Issues

Pull Requests

Stars

Forks

Maintainer

Charlie Gao

Last Published

September 23rd, 2026

Functions in autosync (0.2.0)

autosync-package

autosync: 'Automerge' Sync Server and Client
create_document

Create a new document on the server
validate_token

Validate a JWT token
sync_token

Obtain an OIDC token interactively
sync_client

Open a persistent sync connection
sync_app

Launch the autosync browser app
sync_fetch

Fetch a document from a sync server
sync_server

Create an Automerge sync server
oidc_issuer

Default OIDC issuer URL
get_document

Get a document from the server
sync_project

Open files from a project document
print.autosync_server

Print method for autosync_server
generate_document_id

Generate a new document ID
list_documents

List all document IDs
get_signing_key

Get a signing key for JWT verification
auth_config

Create an authentication configuration
authenticate_header

Authenticate a client from HTTP request headers
fetch_jwks

Fetch and parse a JWKS endpoint
discover_jwks_uri

Discover the JWKS URI for an OIDC issuer