# Rust quickstart
This is a ~60-second round-trip: snapshot a directory, `push` it to a local
`file://` store, `pull` it back into a fresh directory, and confirm the
snapshot ID matches. Snapshot IDs are 64-character lowercase hex and are
bit-identical to the CLI and every other binding.
## 1. Install
```sh
cargo add snapdir-api
cargo add tokio --features full
```
`snapdir-api` is a native crate — `cargo` builds it from source, no C toolchain
required. See [Install snapdir for Rust](/install/rust/) for platform details.
## 2. Snapshot + push
Compute the snapshot ID for a directory, then push it to a local store. Both
calls return the same 64-character lowercase hex ID. The store URI is always an
argument — `file://$PWD/store` is a no-setup local store.
```rust
use snapdir_api::{id, push, ManifestOptions, PushSource, StoreUri, TransferOptions};
use std::path::Path;
#[tokio::main]
async fn main() -> Result<(), Box> {
let store = StoreUri::parse(&format!(
"file://{}/store",
std::env::current_dir()?.display()
))?;
// Snapshot ID — pure and deterministic, no store touched.
let snapshot_id = id(Path::new("./my-dir"), &ManifestOptions::default())?;
println!("{}", snapshot_id.to_hex()); // 64-char lowercase hex
// Upload the snapshot to the store; returns the same ID.
let pushed = push(
PushSource::Path(Path::new("./my-dir")),
&store,
&TransferOptions::default(),
)
.await?;
assert_eq!(pushed, snapshot_id);
Ok(())
}
```
## 3. Pull it back
Materialize the snapshot into a fresh directory and re-derive its ID — it is
the same value you started with.
```rust
use snapdir_api::{id, pull, CheckoutOptions, ManifestOptions};
use std::path::Path;
pull(
&snapshot_id,
&store,
Path::new("./restored"),
&CheckoutOptions::default(),
)
.await?;
let restored = id(Path::new("./restored"), &ManifestOptions::default())?;
assert_eq!(restored, snapshot_id);
```
That `` is the exact same value you would get from `snapdir id` or
`snapdir push` on the CLI — the binding wraps the identical Rust core.