aboutsummaryrefslogtreecommitdiffstats
path: root/crates/atuin-client/src/database.rs
diff options
context:
space:
mode:
authorEllie Huxtable <ellie@atuin.sh>2026-02-25 19:10:58 -0800
committerGitHub <noreply@github.com>2026-02-25 19:10:58 -0800
commit9fe7d10fcf73570767ba7b4eabaa95f65958821b (patch)
treeed9705225db8e5bbe2f3c689ba5d1c9908b75eb1 /crates/atuin-client/src/database.rs
parentfeat: Generate commands or ask questions with `atuin ai` (#3199) (diff)
downloadatuin-9fe7d10fcf73570767ba7b4eabaa95f65958821b.zip
feat: Add history author/intent metadata and v1 record version (#3205)
<!-- Thank you for making a PR! Bug fixes are always welcome, but if you're adding a new feature or changing an existing one, we'd really appreciate if you open an issue, post on the forum, or drop in on Discord --> ## Checks - [x] I am happy for maintainers to push small adjustments to this PR, to speed up the review cycle - [x] I have checked that there are no existing pull requests for the same thing Adds `author` and `intent` to client history records and DB persistence, including migration/backfill and CLI/daemon propagation. Introduces V2 record-store history version `v1` while retaining read compatibility for legacy `v0` records. Adds `--author` and `--intent` flags to `atuin history start`, plus `{author}` and `{intent}` format keys for listing/history output. Updates shell-integration docs for `ATUIN_HISTORY_AUTHOR` and `ATUIN_HISTORY_INTENT`, and updates related tests/fixtures. Validated with `cargo test -p atuin-client --lib`, `cargo test -p atuin-daemon --tests`, `cargo test -p atuin search::inspector`, and `cargo fmt --check`.
Diffstat (limited to 'crates/atuin-client/src/database.rs')
-rw-r--r--crates/atuin-client/src/database.rs23
1 files changed, 19 insertions, 4 deletions
diff --git a/crates/atuin-client/src/database.rs b/crates/atuin-client/src/database.rs
index 7aa095f7..5f292bec 100644
--- a/crates/atuin-client/src/database.rs
+++ b/crates/atuin-client/src/database.rs
@@ -200,8 +200,8 @@ impl Sqlite {
async fn save_raw(tx: &mut sqlx::Transaction<'_, sqlx::Sqlite>, h: &History) -> Result<()> {
sqlx::query(
- "insert or ignore into history(id, timestamp, duration, exit, command, cwd, session, hostname, deleted_at)
- values(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9)",
+ "insert or ignore into history(id, timestamp, duration, exit, command, cwd, session, hostname, author, intent, deleted_at)
+ values(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11)",
)
.bind(h.id.0.as_str())
.bind(h.timestamp.unix_timestamp_nanos() as i64)
@@ -211,6 +211,8 @@ impl Sqlite {
.bind(h.cwd.as_str())
.bind(h.session.as_str())
.bind(h.hostname.as_str())
+ .bind(h.author.as_str())
+ .bind(h.intent.as_deref())
.bind(h.deleted_at.map(|t|t.unix_timestamp_nanos() as i64))
.execute(&mut **tx)
.await?;
@@ -232,6 +234,13 @@ impl Sqlite {
fn query_history(row: SqliteRow) -> History {
let deleted_at: Option<i64> = row.get("deleted_at");
+ let hostname: String = row.get("hostname");
+ let author: Option<String> = row.try_get("author").ok().flatten();
+ let author = author
+ .filter(|author| !author.trim().is_empty())
+ .unwrap_or_else(|| History::author_from_hostname(hostname.as_str()));
+ let intent: Option<String> = row.try_get("intent").ok().flatten();
+ let intent = intent.filter(|intent| !intent.trim().is_empty());
History::from_db()
.id(row.get("id"))
@@ -244,7 +253,9 @@ impl Sqlite {
.command(row.get("command"))
.cwd(row.get("cwd"))
.session(row.get("session"))
- .hostname(row.get("hostname"))
+ .hostname(hostname)
+ .author(author)
+ .intent(intent)
.deleted_at(
deleted_at.and_then(|t| OffsetDateTime::from_unix_timestamp_nanos(t as i128).ok()),
)
@@ -295,7 +306,7 @@ impl Database for Sqlite {
sqlx::query(
"update history
- set timestamp = ?2, duration = ?3, exit = ?4, command = ?5, cwd = ?6, session = ?7, hostname = ?8, deleted_at = ?9
+ set timestamp = ?2, duration = ?3, exit = ?4, command = ?5, cwd = ?6, session = ?7, hostname = ?8, author = ?9, intent = ?10, deleted_at = ?11
where id = ?1",
)
.bind(h.id.0.as_str())
@@ -306,6 +317,8 @@ impl Database for Sqlite {
.bind(h.cwd.as_str())
.bind(h.session.as_str())
.bind(h.hostname.as_str())
+ .bind(h.author.as_str())
+ .bind(h.intent.as_deref())
.bind(h.deleted_at.map(|t|t.unix_timestamp_nanos() as i64))
.execute(&self.pool)
.await?;
@@ -612,6 +625,8 @@ impl Database for Sqlite {
"exit",
"command",
"deleted_at",
+ "null as author",
+ "null as intent",
"group_concat(cwd, ':') as cwd",
"group_concat(session) as session",
"group_concat(hostname, ',') as hostname",