tapped
A Rust wrapper library for the tap ATProto sync utility.
tapped provides an idiomatic async Rust interface for spawning and communicating with a tap subprocess, making it easy to build applications that sync data from the ATProto network.
Features
- Spawn and manage
tapsubprocesses with graceful shutdown - Strongly-typed configuration for all tap envvars
- Strongly-typed async Rust functions covering all of tap's HTTP API endpoints
- WebSocket-based event channel with automatic acknowledgment
Installation
Add to your Cargo.toml:
[]
= "0.3"
You'll also need the tap binary. Build it from the indigo repository:
&&
tapped has been most recently tested against:
tap version v0.0.0-20260120225912-12d69fa4d209-rev-12d69fa
Quick Start
use ;
async
Usage Patterns
Connect to Existing Instance
If you have a tap instance already running:
use TapClient;
let client = new?;
client.health.await?;
Spawn an Instance
use ;
let config = builder
.database_url
.full_network
.build;
// If you need a custom binary path, use spawn() instead:
// let process = TapProcess::spawn("/path/to/tap", config).await?;
let process = spawn_default.await?;
let client = process.client?;
// Use the client
client.health.await?;
let count = client.repo_count.await?;
println!;
Configuration Options
use ;
use Duration;
let config = builder
// Database
.database_url
.max_db_conns
// Network
.bind
.relay_url
.plc_url
// Filtering
.signal_collection
.collection_filter
.collection_filter
.full_network
// Performance
.firehose_parallelism
.resync_parallelism
.outbox_parallelism
.outbox_capacity
// Timeouts
.repo_fetch_timeout
.startup_timeout
.shutdown_timeout
// Logging
.log_level
.build;
Working with Events
Events are automatically acknowledged when dropped:
use ;
let mut channel = client.channel.await?;
while let Ok = channel.recv.await
Managing Repositories
// Add repos to track
client.add_repos.await?;
// Remove repos
client.remove_repos.await?;
// Get info about a specific repo
let info = client.repo_info.await?;
println!;
// Resolve a DID to its document
let doc = client.resolve_did.await?;
println!;
Checking Stats
let repos = client.repo_count.await?;
let records = client.record_count.await?;
let outbox = client.outbox_buffer.await?;
let resync = client.resync_buffer.await?;
let cursors = client.cursors.await?;
println!;
println!;
println!;
Example: Syncing standard.site Records with Schema Generation and Validation
The repository includes a complete example demonstrating how to sync and validate ATProto records using tapped together with the jacquard crates.
The jacquard ecosystem provides runtime validation of records against their lexicon constraints, and the ability to generate Rust structs from lexicon JSON files.
tapped/
├── tapped/ # The main tapped library
├── lexicons-example/ # Generated types from lexicon schemas
│ ├── lexicons/ # Source lexicon JSON files
│ │ ├── site.standard.publication.json
│ │ ├── site.standard.document.json
│ │ └── ...
│ └── src/ # Generated Rust code
└── standard-site-sync/ # Example binary using both packages
These files were generated like so:
# Install the code generator
This produces strongly-typed structs with built-in validation. For example, the site.standard.publication lexicon becomes:
use Publication;
// Deserialize from JSON
let publication: Publication = from_str?;
// Validate against lexicon constraints (max length, grapheme limits, etc.)
publication.validate?;
// Access typed fields
println!;
println!;
For more detail see process_record_event in main.rs.
License
MIT