Start in 15 minutes
This page gets two devices in sync. The first part needs no Google account: two databases sync through a shared folder, which is how you develop and test. The second part switches to Google Drive.
1. Try it without Google
Section titled “1. Try it without Google”cargo install bothy-cli
# Two local databases ("a" and "b") that sync through a folder.bothy --db a init --remote path:/tmp/bothy-sharedbothy --db b join --remote path:/tmp/bothy-shared
bothy --db a put notes n1 '{"title": "Hello", "done": false}'bothy --db a syncbothy --db b syncbothy --db b get notes n1 # {"done":false,"title":"Hello"}pip install bothyimport bothy
remote = bothy.FolderRemote("/tmp/bothy-shared")a = bothy.Database.open("a.db", app_id="com.example.notes", remote=remote)b = bothy.Database.open("b.db", app_id="com.example.notes", remote=remote)a.init_or_join()b.init_or_join()
a.collection("notes").put("n1", {"title": "Hello", "done": False})a.sync()b.sync()print(b.collection("notes").get("n1")) # {'done': False, 'title': 'Hello'}# pubspec.yaml; building needs a Rust toolchain (https://rustup.rs)dependencies: bothy: ^0.4.0import 'package:bothy/bothy.dart';
await Bothy.initialize();final remote = BothyRemoteSpec.path('${dir.path}/shared');final a = await Bothy.open(path: '${dir.path}/a.db', appId: 'com.example.notes', remote: remote);final b = await Bothy.open(path: '${dir.path}/b.db', appId: 'com.example.notes', remote: remote);await a.initOrJoin();await b.initOrJoin();
await a.collection('notes').put('n1', {'title': 'Hello', 'done': false});await a.sync();await b.sync();print(await b.collection('notes').get('n1'));[dependencies]bothy = "0.4"serde_json = "1"tokio = { version = "1", features = ["macros", "rt-multi-thread"] }use std::sync::Arc;use bothy::{Config, Database, remote::FolderRemote};use serde_json::json;
#[tokio::main]async fn main() -> bothy::Result<()> { let remote = Arc::new(FolderRemote::new("/tmp/bothy-shared")?); let a = Database::open(Config::new("a.db", "com.example.notes"), remote.clone()).await?; let b = Database::open(Config::new("b.db", "com.example.notes"), remote).await?; a.init_or_join().await?; b.init_or_join().await?;
a.collection("notes")?.put("n1", json!({"title": "Hello", "done": false})).await?; a.sync().await?; b.sync().await?; println!("{:?}", b.collection("notes")?.get("n1").await?); Ok(())}Edit the same note on both sides before syncing, one field each, and both edits survive. Edit the same field and the later one wins; the other is kept in the conflict log.
2. Sync through Google Drive
Section titled “2. Sync through Google Drive”-
Create the Google Cloud project and download a Desktop app client (guide).
-
Sign in and create an encrypted database on the first computer:
Terminal window bothy auth setup --client ~/Downloads/client_secret_desktop.jsonbothy auth login # opens the browserbothy init --encrypt --remember # asks for a password twicebothy put notes n1 '{"title": "From my laptop"}'bothy sync -
On the second computer, with the same client file:
Terminal window bothy auth setup --client client_secret_desktop.jsonbothy auth loginbothy join --remember # the same passwordbothy get notes n1 -
Keep both in sync in the background, with a direct channel while both are online:
Terminal window bothy sync --watch --p2p
Next: how sync works, or a guide for Flutter, Python or robots.