link-cli Rust Package
This directory contains the Rust link-cli crate, which publishes both a
reusable [lib] (link_cli) and the clink [[bin]] from the same
package. It mirrors the core query processor, named references, LiNo
import/export, and structure formatting used by the production C# tool.
The WebAssembly wrapper crate lives in rust/wasm/ and depends on this
package.
Install
# Build and install the CLI binary.
# Or pull in the public API to build your own tooling.
API documentation for every published version is hosted on
docs.rs/link-cli. A copy is also published to
GitHub Pages alongside the C# DocFX site by .github/workflows/docs.yml.
Use
Optional Transactions and Version Control
Pass --transactions (or any flag in the family — --transactions-file,
--commit-mode, --retention, --log) to record each Create/Update/Delete
as a reversible transition in a sidecar links store. Pass --vc
(or --vc-file, --branch, --branch-from, --checkout, --tag,
--list-branches, --list-tags) to add a version-control layer over the
recorded transitions log:
# Record reversible transitions into data.transitions.links
# Branch and tag on top of the transitions log
End-to-end demo scripts live in
examples/transactions/ and
examples/version-control/.
Use as a library
link_cli is usable as an embedded, doublets-backed transactional store, not
only as the code behind clink.
use ;
use DoubletsStorage;
A runnable, self-checking version of this is
examples/embedded_store.rs
(cargo run --example embedded_store).
- Any address type.
GenericTransactionsDecorator<T, S, L>is generic over the doublets address type, the wrapped store, and the transitions log.TransactionsDecoratoris theu32+NamedTypesDecoratorspecialisationclinkuses. The transitions wire format writes addresses in decimal, so it is identical across address types, and an address that does not fit the target type is reported asLinkError::AddressOutOfRangerather than truncated. - Any store.
storage::LinksStorage<T>is the trait the transactions layer is written against.storage::DoubletsStorage::opencreates a file-mappeddoublets::unit::Store;DoubletsStorage::wrapadopts a store you already own. - In-place mutation. A file-mapped store is written through its mapping, so the inode never changes and other processes that mapped the same file keep observing the same data. Nothing is replaced through a temporary file.
- Durability. Writes to a file-mapped store survive a process crash
without any
save()— the mapping is the page cache. Surviving a machine crash needs thefsyncthatLinksStorage::flushperforms (a clean drop also syncs). In-memory stores keep everything in memory untilflush/save. Recovery runs when the decorator is created: committed-but-unapplied transitions are replayed, uncommitted ones are rolled back. - Multi-process access.
storage::locklocks a<database>.locksidecar, shared for readers and exclusive for writers, throughDoubletsStorage::open_shared/open_exclusive/try_open_exclusive.LinksStorage::has_external_changesanswers "has anyone else written since I last looked?" from aStorageRevisionfingerprint. This requires Rust 1.89, the release that stabilisedstd::fs::File::lock. - Typed errors and paths. Public entry points take
AsRef<Path>and returnLinkError, notanyhow::Error.
Develop
Release automation for this package lives in rust/scripts/ and uses changelog
fragments from rust/changelog.d/.