mirror of
https://github.com/atuinsh/atuin.git
synced 2026-09-27 12:01:48 +02:00
Dotfiles was an interesting idea at the time, but I never felt that it was one worth continuing development of. There are much better solutions for dotfile management, many of which are much more comprehensive (see chezmoi, etc) ## Checks - [ ] I am happy for maintainers to push small adjustments to this PR, to speed up the review cycle - [ ] I have checked that there are no existing pull requests for the same thing
5.5 KiB
5.5 KiB
Atuin
Shell history tool. Replaces your shell's built-in history with a SQLite database, adds context (cwd, exit code, duration, hostname), and optionally syncs across machines with end-to-end encryption.
Workspace crates
atuin CLI binary + TUI (clap, ratatui, crossterm)
atuin-client Client library: local DB, encryption, sync, settings, client-facing domain types
atuin-common Low-level cross-crate utilities and API models (not a home for client-facing domain types)
atuin-daemon Background gRPC daemon (tonic) for shell hooks
atuin-dotfiles Legacy read-only alias/var listing via record store
atuin-history Sorting algorithms, stats
atuin-kv Key-value store (synced)
atuin-scripts Script management (minijinja)
atuin-server HTTP sync server (axum) - lib + standalone binary
atuin-server-database Database trait for server
atuin-server-postgres Postgres implementation (sqlx)
atuin-server-sqlite SQLite implementation (sqlx)
Two sync protocols
- V1 (legacy): Syncs history entries directly. Being phased out. Toggleable via
sync_v1_enabled. - V2 (current): Record store abstraction. All data types (history, KV, aliases, vars, scripts) share the same sync infrastructure using tagged records. Envelope-encrypted with PASETO V4 and per-record CEKs.
Encryption
- V1: XSalsa20Poly1305 (secretbox). Key at
~/.local/share/atuin/key. - V2: PASETO V4 Local (XChaCha20-Poly1305 + Blake2b). Envelope encryption: each record gets a random CEK wrapped with the master key. Record metadata (id, idx, version, tag, host) is authenticated as implicit assertions.
Databases
- Client: SQLite everywhere. Separate DBs for history, record store, KV, scripts. All use sqlx + WAL mode.
- Server: Postgres (primary) or SQLite. Auto-detected from URI prefix.
- Migrations live alongside each crate. Never modify existing migrations, only add new ones.
Hot paths
history start, history end, and init skip database initialization for latency. Don't add DB calls to these without good reason.
Conventions
- Crate placement: anything client-facing -- domain types users' code touches and the stores over
them -- lives in
atuin-client.atuin-commonis for low-level, cross-crate utilities only; do not put client-facing domain types there. - Rust 2024 edition, toolchain 1.98.0.
- Errors:
eyre::Resultin binaries,thiserrorfor typed errors in libraries. - Derive boilerplate:
derive_more(workspace dep) forDisplay,From,Into,AsRef,Deref,Debugon newtypes and simple enums. Preferderive_moreover manualimplwhen the formatting/conversion is a straight delegation. Usethiserror(notderive_more) for error types. Use#[as_ref(str)]on string newtypes forAsRef<str>. - Async: tokio. Client uses
current_thread; server usesmulti_thread. #![deny(unsafe_code)]on client/common,#![forbid(unsafe_code)]on server.- Clippy:
pedantic+nurseryon main crate. CI enforces-D warnings, on both the default targets and--tests. - Rustdoc: CI runs
cargo doc --document-private-items --no-deps --workspacewithRUSTDOCFLAGS=-D warnings. Broken intra-doc links fail the build. - Format:
cargo +nightly fmt..rustfmt.tomluses nightly-only options, so formatting requires the nightly toolchain even though the project builds on stable 1.97.0. - IDs: UUIDv7 (time-ordered), newtype wrappers (
HistoryId,RecordId,HostId). - Serialization: MessagePack for encrypted payloads, JSON for API, TOML for config.
- Storage traits:
Database(client),Store(record store),Database(server) -- allasync_trait. - History builders:
HistoryImported,HistoryCaptured,HistoryFromDbwith compile-time field validation. - Feature flags:
client,sync,daemon,clipboard,check-update.
Testing
- Unit tests inline with
#[cfg(test)]. Userstestfor every test —#[rstest], never a bare#[test](async:#[rstest]+#[tokio::test]); migrate plain#[test]s in files you touch. - Lean on
#[fixture]s for shared setup and compose them; when a test needs teardown, return an RAII guard from the fixture (e.g. a temp dir removed onDrop) rather than cleaning up by hand. - Parametrize with
#[case(...)](input/expected tables) and#[values(...)](cross-products of independent parameters) instead of near-duplicate tests. - Reach for
proptestwhen a property holds across many inputs — round-trips (encode/decode, serde, parse/display), invariants, idempotence; keep targeted#[case]s for known edge cases and regressions. - Server integration tests in
crates/atuin-server/tests/need Postgres (ATUIN_DB_URIenv var). - E2e tests use temporary homes and private daemon sockets. Add shell setups in
crates/atuin/tests/shells/*.toml. Seecrates/atuin/tests/README.mdfor dependencies and how to run them. - Use
rstestfor tests, especially when they can be made simpler usingcases andfixtures. - Use
":memory:"SQLite for unit tests needing a database. - Runner:
cargo nextest. - Benchmarks:
divaninatuin-clientandatuin-history, tracked in CI by CodSpeed. Run them locally withcargo codspeed build && cargo codspeed run, or with plaincargo bench.
Build and check
cargo build
cargo test
cargo clippy -- -D warnings
cargo clippy --tests -- -D warnings
cargo +nightly fmt --check
RUSTDOCFLAGS="-D warnings" cargo doc --document-private-items --no-deps --workspace