diff options
| author | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2026-06-10 22:34:34 +0200 |
|---|---|---|
| committer | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2026-06-10 22:34:34 +0200 |
| commit | edc27740c0fec4e8daaabbabe0479c1efc191316 (patch) | |
| tree | 29f458b39f62ab722df33488f40ad1b03086b868 | |
| parent | chore: Turn all `allow`s into into `expect`s (diff) | |
| download | atuin-edc27740c0fec4e8daaabbabe0479c1efc191316.zip | |
chore: Remove more (kinda) useless stuff
67 files changed, 0 insertions, 6835 deletions
diff --git a/.cargo/audit.toml b/.cargo/audit.toml deleted file mode 100644 index 342aa88d..00000000 --- a/.cargo/audit.toml +++ /dev/null @@ -1,9 +0,0 @@ -[advisories] -ignore = [ - # This is a vuln on RSA. RSA is in our lockfile, but not in cargo-tree. - # It is a issue with sqlx/cargo, and does not affect Atuin. - # See: - # - https://github.com/launchbadge/sqlx/issues/3211 - # - https://github.com/rust-lang/cargo/issues/10801 - "RUSTSEC-2023-0071" -] @@ -194,7 +194,6 @@ dependencies = [ "atuin-common", "atuin-daemon", "atuin-history", - "atuin-kv", "atuin-nucleo-matcher", "atuin-pty-proxy", "atuin-server", @@ -361,22 +360,6 @@ dependencies = [ ] [[package]] -name = "atuin-kv" -version = "18.16.1" -dependencies = [ - "atuin-client", - "atuin-common", - "eyre", - "pretty_assertions", - "rmp", - "sqlx", - "tokio", - "tracing", - "tracing-subscriber", - "typed-builder", -] - -[[package]] name = "atuin-nucleo" version = "0.6.0" dependencies = [ @@ -22,10 +22,7 @@ async-trait = "0.1.58" atuin-client = { path = "crates/atuin-client", version = "18.16.1" } atuin-common = { path = "crates/atuin-common", version = "18.16.1" } atuin-daemon = { path = "crates/atuin-daemon", version = "18.16.1" } -atuin-dotfiles = { path = "crates/atuin-dotfiles", version = "18.16.1" } atuin-history = { path = "crates/atuin-history", version = "18.16.1" } -atuin-kv = { path = "crates/atuin-kv", version = "18.16.1" } -atuin-scripts = { path = "crates/atuin-scripts", version = "18.16.1" } atuin-server = { path = "crates/atuin-server", version = "18.16.1" } atuin-server-database = { path = "crates/atuin-server-database", version = "18.16.1" } atuin-server-postgres = { path = "crates/atuin-server-postgres", version = "18.16.1" } diff --git a/crates/atuin-kv/Cargo.toml b/crates/atuin-kv/Cargo.toml deleted file mode 100644 index c92b2ed2..00000000 --- a/crates/atuin-kv/Cargo.toml +++ /dev/null @@ -1,27 +0,0 @@ -[package] -name = "atuin-kv" -edition = "2024" -version = { workspace = true } -description = "The kv crate for Atuin" - -authors.workspace = true -rust-version.workspace = true -license.workspace = true -homepage.workspace = true -repository.workspace = true -readme.workspace = true - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -atuin-client = { path = "../atuin-client", version = "18.16.1" } -atuin-common = { path = "../atuin-common", version = "18.16.1" } - -tracing = { workspace = true } -tracing-subscriber = { workspace = true } -rmp = { version = "0.8.14" } -eyre = { workspace = true } -tokio = { workspace = true } -typed-builder = { workspace = true } -pretty_assertions = { workspace = true } -sqlx = { workspace = true } diff --git a/crates/atuin-kv/migrations/20250501160746_create_kv_db.down.sql b/crates/atuin-kv/migrations/20250501160746_create_kv_db.down.sql deleted file mode 100644 index bce8dfd3..00000000 --- a/crates/atuin-kv/migrations/20250501160746_create_kv_db.down.sql +++ /dev/null @@ -1,2 +0,0 @@ --- Add down migration script here -DROP TABLE kv; diff --git a/crates/atuin-kv/migrations/20250501160746_create_kv_db.up.sql b/crates/atuin-kv/migrations/20250501160746_create_kv_db.up.sql deleted file mode 100644 index 77384044..00000000 --- a/crates/atuin-kv/migrations/20250501160746_create_kv_db.up.sql +++ /dev/null @@ -1,12 +0,0 @@ --- Add up migration script here -CREATE TABLE - kv ( - namespace TEXT NOT NULL, - key TEXT NOT NULL, - value TEXT NOT NULL, - inserted_at INTEGER NOT NULL DEFAULT (strftime ('%s', 'now')) - ); - -CREATE INDEX idx_kv_namespace ON kv (namespace); - -CREATE UNIQUE INDEX idx_kv ON kv (namespace, key); diff --git a/crates/atuin-kv/src/database.rs b/crates/atuin-kv/src/database.rs deleted file mode 100644 index 446aa7af..00000000 --- a/crates/atuin-kv/src/database.rs +++ /dev/null @@ -1,229 +0,0 @@ -use std::{path::Path, str::FromStr, time::Duration}; - -use atuin_common::utils; -use sqlx::{ - Result, Row, - sqlite::{ - SqliteConnectOptions, SqliteJournalMode, SqlitePool, SqlitePoolOptions, SqliteRow, - SqliteSynchronous, - }, -}; -use tokio::fs; -use tracing::debug; - -use crate::store::entry::KvEntry; - -#[derive(Debug, Clone)] -pub struct Database { - pub pool: SqlitePool, -} - -impl Database { - pub async fn new(path: impl AsRef<Path>, timeout: f64) -> Result<Self> { - let path = path.as_ref(); - debug!("opening KV sqlite database at {:?}", path); - - if utils::broken_symlink(path) { - eprintln!( - "Atuin: KV sqlite db path ({path:?}) is a broken symlink. Unable to read or create replacement." - ); - std::process::exit(1); - } - - if !path.exists() - && let Some(dir) = path.parent() - { - fs::create_dir_all(dir).await?; - } - - let opts = SqliteConnectOptions::from_str(path.as_os_str().to_str().unwrap())? - .journal_mode(SqliteJournalMode::Wal) - .optimize_on_close(true, None) - .synchronous(SqliteSynchronous::Normal) - .with_regexp() - .foreign_keys(true) - .create_if_missing(true); - - let pool = SqlitePoolOptions::new() - .acquire_timeout(Duration::from_secs_f64(timeout)) - .connect_with(opts) - .await?; - - Self::setup_db(&pool).await?; - Ok(Self { pool }) - } - - pub async fn sqlite_version(&self) -> Result<String> { - sqlx::query_scalar("SELECT sqlite_version()") - .fetch_one(&self.pool) - .await - } - - async fn setup_db(pool: &SqlitePool) -> Result<()> { - debug!("running sqlite database setup"); - - sqlx::migrate!("./migrations").run(pool).await?; - - Ok(()) - } - - async fn save_raw(tx: &mut sqlx::Transaction<'_, sqlx::Sqlite>, e: &KvEntry) -> Result<()> { - sqlx::query( - "insert into kv(namespace, key, value) - values(?1, ?2, ?3) - on conflict(namespace, key) do update set - namespace = excluded.namespace, - key = excluded.key, - value = excluded.value", - ) - .bind(e.namespace.as_str()) - .bind(e.key.as_str()) - .bind(e.value.as_str()) - .execute(&mut **tx) - .await?; - - Ok(()) - } - - async fn delete_raw( - tx: &mut sqlx::Transaction<'_, sqlx::Sqlite>, - namespace: &str, - key: &str, - ) -> Result<()> { - sqlx::query("delete from kv where namespace = ?1 and key = ?2") - .bind(namespace) - .bind(key) - .execute(&mut **tx) - .await?; - Ok(()) - } - - pub async fn save(&self, e: &KvEntry) -> Result<()> { - debug!("saving kv entry to sqlite"); - let mut tx = self.pool.begin().await?; - Self::save_raw(&mut tx, e).await?; - tx.commit().await?; - - Ok(()) - } - - pub async fn delete(&self, namespace: &str, key: &str) -> Result<()> { - debug!("deleting kv entry {namespace}/{key}"); - - let mut tx = self.pool.begin().await?; - Self::delete_raw(&mut tx, namespace, key).await?; - tx.commit().await?; - - Ok(()) - } - - fn query_kv_entry(row: SqliteRow) -> KvEntry { - let namespace = row.get("namespace"); - let key = row.get("key"); - let value = row.get("value"); - - KvEntry::builder() - .namespace(namespace) - .key(key) - .value(value) - .build() - } - - pub async fn load(&self, namespace: &str, key: &str) -> Result<Option<KvEntry>> { - debug!("loading kv entry {namespace}.{key}"); - - let res = sqlx::query("select * from kv where namespace = ?1 and key = ?2") - .bind(namespace) - .bind(key) - .map(Self::query_kv_entry) - .fetch_optional(&self.pool) - .await?; - - Ok(res) - } - - pub async fn list(&self, namespace: Option<&str>) -> Result<Vec<KvEntry>> { - debug!("listing kv entries"); - - let res = if let Some(namespace) = namespace { - sqlx::query("select * from kv where namespace = ?1 order by key asc") - .bind(namespace) - .map(Self::query_kv_entry) - .fetch_all(&self.pool) - .await? - } else { - sqlx::query("select * from kv order by namespace, key asc") - .map(Self::query_kv_entry) - .fetch_all(&self.pool) - .await? - }; - - Ok(res) - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[tokio::test] - async fn test_list() { - let db = Database::new("sqlite::memory:", 1.0).await.unwrap(); - let scripts = db.list(None).await.unwrap(); - assert_eq!(scripts.len(), 0); - - let entry = KvEntry::builder() - .namespace("test".to_string()) - .key("test".to_string()) - .value("test".to_string()) - .build(); - - db.save(&entry).await.unwrap(); - - let entries = db.list(None).await.unwrap(); - assert_eq!(entries.len(), 1); - assert_eq!(entries[0].namespace, "test"); - assert_eq!(entries[0].key, "test"); - assert_eq!(entries[0].value, "test"); - } - - #[tokio::test] - async fn test_save_load() { - let db = Database::new("sqlite::memory:", 1.0).await.unwrap(); - - let entry = KvEntry::builder() - .namespace("test".to_string()) - .key("test".to_string()) - .value("test".to_string()) - .build(); - - db.save(&entry).await.unwrap(); - - let loaded = db - .load(&entry.namespace, &entry.key) - .await - .unwrap() - .unwrap(); - - assert_eq!(loaded, entry); - } - - #[tokio::test] - async fn test_delete() { - let db = Database::new("sqlite::memory:", 1.0).await.unwrap(); - - let entry = KvEntry::builder() - .namespace("test".to_string()) - .key("test".to_string()) - .value("test".to_string()) - .build(); - - db.save(&entry).await.unwrap(); - - assert_eq!(db.list(None).await.unwrap().len(), 1); - db.delete(&entry.namespace, &entry.key).await.unwrap(); - - let loaded = db.list(None).await.unwrap(); - assert_eq!(loaded.len(), 0); - } -} diff --git a/crates/atuin-kv/src/lib.rs b/crates/atuin-kv/src/lib.rs deleted file mode 100644 index ad57b6ac..00000000 --- a/crates/atuin-kv/src/lib.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod database; -pub mod store; diff --git a/crates/atuin-kv/src/store.rs b/crates/atuin-kv/src/store.rs deleted file mode 100644 index 23fd7934..00000000 --- a/crates/atuin-kv/src/store.rs +++ /dev/null @@ -1,211 +0,0 @@ -use std::collections::HashSet; - -use eyre::{Result, bail}; - -use atuin_client::record::sqlite_store::SqliteStore; -use atuin_client::record::{encryption::PASETO_V4, store::Store}; -use atuin_common::record::{Host, HostId, Record, RecordId, RecordIdx}; -use entry::KvEntry; -use record::{KV_TAG, KV_VERSION, KvRecord}; - -use crate::database::Database; - -pub mod entry; -pub mod record; - -#[derive(Debug, Clone)] -pub struct KvStore { - pub record_store: SqliteStore, - pub kv_db: Database, - pub host_id: HostId, - pub encryption_key: [u8; 32], -} - -impl KvStore { - pub fn new( - record_store: SqliteStore, - kv_db: Database, - host_id: HostId, - encryption_key: [u8; 32], - ) -> Self { - KvStore { - record_store, - kv_db, - host_id, - encryption_key, - } - } - - pub async fn set(&self, namespace: &str, key: &str, value: &str) -> Result<()> { - let kv_record = KvRecord::builder() - .namespace(namespace.to_string()) - .key(key.to_string()) - .value(Some(value.to_string())) - .build(); - - self.push_record(kv_record).await?; - - let kv = KvEntry::builder() - .namespace(namespace.to_string()) - .key(key.to_string()) - .value(value.to_string()) - .build(); - - self.kv_db.save(&kv).await?; - - Ok(()) - } - - pub async fn get(&self, namespace: &str, key: &str) -> Result<Option<String>> { - let kv = self.kv_db.load(namespace, key).await?; - Ok(kv.map(|kv| kv.value)) - } - - pub async fn delete(&self, namespace: &str, keys: &[String]) -> Result<()> { - for key in keys { - let record = KvRecord::builder() - .namespace(namespace.to_string()) - .key(key.to_string()) - .value(None) - .build(); - - self.push_record(record).await?; - self.kv_db.delete(namespace, key).await?; - } - - Ok(()) - } - - pub async fn list(&self, namespace: Option<&str>) -> Result<Vec<KvEntry>> { - let entries = self.kv_db.list(namespace).await?; - - Ok(entries) - } - - async fn push_record(&self, record: KvRecord) -> Result<(RecordId, RecordIdx)> { - let bytes = record.serialize()?; - let idx = self - .record_store - .last(self.host_id, KV_TAG) - .await? - .map_or(0, |p| p.idx + 1); - - let record = Record::builder() - .host(Host::new(self.host_id)) - .version(KV_VERSION.to_string()) - .tag(KV_TAG.to_string()) - .idx(idx) - .data(bytes) - .build(); - - let id = record.id; - - self.record_store - .push(&record.encrypt::<PASETO_V4>(&self.encryption_key)) - .await?; - - Ok((id, idx)) - } - - pub async fn build(&self) -> Result<()> { - let mut tagged = self.record_store.all_tagged(KV_TAG).await?; - tagged.reverse(); - - let cached = self.kv_db.list(None).await?; - - let mut visited = HashSet::new(); - - // Iterate through all KV records from newest to oldest; - // only visit each KV once, inserting or deleting based on the first time we see it - for record in tagged { - let decrypted = match record.version.as_str() { - "v0" | KV_VERSION => record.decrypt::<PASETO_V4>(&self.encryption_key)?, - version => bail!("unknown version {version:?}"), - }; - - let kv = KvRecord::deserialize(&decrypted.data, &decrypted.version)?; - let uniq_id = format!("{}.{}", kv.namespace, kv.key); - - if visited.insert(uniq_id) { - match kv.value { - Some(value) => { - self.kv_db - .save( - &KvEntry::builder() - .namespace(kv.namespace.clone()) - .key(kv.key.clone()) - .value(value) - .build(), - ) - .await?; - } - None => { - self.kv_db - .delete(kv.namespace.as_str(), kv.key.as_str()) - .await?; - } - } - } - } - - // Any KVs that were in the cache but not in the tagged list should be deleted; - // this should never happen in practice since the cache is always built from the tagged list, - // but just in case because ** S O F T W A R E ** - for kv in cached { - if !visited.contains(&format!("{}.{}", kv.namespace, kv.key)) { - self.kv_db - .delete(kv.namespace.as_str(), kv.key.as_str()) - .await?; - } - } - - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - async fn setup() -> Result<KvStore> { - let record_store = SqliteStore::new("sqlite::memory:", 1.0).await.unwrap(); - let kv_db = Database::new("sqlite::memory:", 1.0).await.unwrap(); - let host_id = atuin_common::record::HostId(atuin_common::utils::uuid_v7()); - let encryption_key = [0; 32]; - Ok(KvStore::new(record_store, kv_db, host_id, encryption_key)) - } - - #[tokio::test] - async fn test_kv_store() -> Result<()> { - let store = setup().await?; - - store.set("test", "key", "value").await.unwrap(); - let value = store.get("test", "key").await.unwrap(); - assert_eq!(value, Some("value".to_string())); - - let records = store.record_store.all_tagged(KV_TAG).await?; - assert_eq!(records.len(), 1); - - let list = store.list(Some("test")).await.unwrap(); - let expected = vec![ - KvEntry::builder() - .namespace("test".to_string()) - .key("key".to_string()) - .value("value".to_string()) - .build(), - ]; - assert_eq!(list, expected); - - let ns_list = store.list(None).await.unwrap(); - assert_eq!(ns_list, expected); - - store.delete("test", &["key".to_string()]).await.unwrap(); - let value = store.get("test", "key").await.unwrap(); - assert_eq!(value, None); - - let records = store.record_store.all_tagged(KV_TAG).await?; - assert_eq!(records.len(), 2); - - Ok(()) - } -} diff --git a/crates/atuin-kv/src/store/entry.rs b/crates/atuin-kv/src/store/entry.rs deleted file mode 100644 index 1d6a1ef8..00000000 --- a/crates/atuin-kv/src/store/entry.rs +++ /dev/null @@ -1,8 +0,0 @@ -use typed_builder::TypedBuilder; - -#[derive(Debug, Clone, PartialEq, Eq, TypedBuilder)] -pub struct KvEntry { - pub namespace: String, - pub key: String, - pub value: String, -} diff --git a/crates/atuin-kv/src/store/record.rs b/crates/atuin-kv/src/store/record.rs deleted file mode 100644 index 37254176..00000000 --- a/crates/atuin-kv/src/store/record.rs +++ /dev/null @@ -1,159 +0,0 @@ -use atuin_common::record::DecryptedData; -use eyre::{Result, bail, ensure, eyre}; -use typed_builder::TypedBuilder; - -pub const KV_VERSION: &str = "v1"; -pub const KV_TAG: &str = "kv"; -pub const KV_VAL_MAX_LEN: usize = 100 * 1024; - -#[derive(Debug, Clone, PartialEq, Eq, TypedBuilder)] -pub struct KvRecord { - pub namespace: String, - pub key: String, - pub value: Option<String>, -} - -impl KvRecord { - pub fn serialize(&self) -> Result<DecryptedData> { - use rmp::encode; - - let mut output = vec![]; - - // INFO: ensure this is updated when adding new fields - encode::write_array_len(&mut output, 4)?; - - encode::write_str(&mut output, &self.namespace)?; - encode::write_str(&mut output, &self.key)?; - encode::write_bool(&mut output, self.value.is_some())?; - - if let Some(value) = &self.value { - encode::write_str(&mut output, value)?; - } - - Ok(DecryptedData(output)) - } - - pub fn deserialize(data: &DecryptedData, version: &str) -> Result<Self> { - use rmp::decode; - - fn error_report<E: std::fmt::Debug>(err: E) -> eyre::Report { - eyre!("{err:?}") - } - - match version { - "v0" => { - let mut bytes = decode::Bytes::new(&data.0); - - let nfields = decode::read_array_len(&mut bytes).map_err(error_report)?; - ensure!(nfields == 3, "too many entries in v0 kv record"); - - let bytes = bytes.remaining_slice(); - - let (namespace, bytes) = - decode::read_str_from_slice(bytes).map_err(error_report)?; - let (key, bytes) = decode::read_str_from_slice(bytes).map_err(error_report)?; - let (value, bytes) = decode::read_str_from_slice(bytes).map_err(error_report)?; - - if !bytes.is_empty() { - bail!("trailing bytes in encoded kvrecord. malformed") - } - - Ok(KvRecord { - namespace: namespace.to_owned(), - key: key.to_owned(), - value: Some(value.to_owned()), - }) - } - KV_VERSION => { - let mut bytes = decode::Bytes::new(&data.0); - - let nfields = decode::read_array_len(&mut bytes).map_err(error_report)?; - ensure!(nfields == 4, "too many entries in v1 kv record"); - - let bytes = bytes.remaining_slice(); - - let (namespace, bytes) = - decode::read_str_from_slice(bytes).map_err(error_report)?; - let (key, mut bytes) = decode::read_str_from_slice(bytes).map_err(error_report)?; - let has_value = decode::read_bool(&mut bytes).map_err(error_report)?; - - let (value, bytes) = if has_value { - let (value, bytes) = - decode::read_str_from_slice(bytes).map_err(error_report)?; - (Some(value.to_owned()), bytes) - } else { - (None, bytes) - }; - - if !bytes.is_empty() { - bail!("trailing bytes in encoded kvrecord. malformed") - } - - Ok(KvRecord { - namespace: namespace.to_owned(), - key: key.to_owned(), - value, - }) - } - _ => { - bail!("unknown version {version:?}") - } - } - } -} - -#[cfg(test)] -mod tests { - use super::{DecryptedData, KV_VERSION, KvRecord}; - - #[test] - fn encode_decode_some() { - let kv = KvRecord { - namespace: "foo".to_owned(), - key: "bar".to_owned(), - value: Some("baz".to_owned()), - }; - let snapshot = [ - 0x94, 0xa3, b'f', b'o', b'o', 0xa3, b'b', b'a', b'r', 0xc3, 0xa3, b'b', b'a', b'z', - ]; - - let encoded = kv.serialize().unwrap(); - let decoded = KvRecord::deserialize(&encoded, KV_VERSION).unwrap(); - - assert_eq!(encoded.0, &snapshot); - assert_eq!(decoded, kv); - } - - #[test] - fn encode_decode_none() { - let kv = KvRecord { - namespace: "foo".to_owned(), - key: "bar".to_owned(), - value: None, - }; - let snapshot = [0x94, 0xa3, b'f', b'o', b'o', 0xa3, b'b', b'a', b'r', 0xc2]; - - let encoded = kv.serialize().unwrap(); - let decoded = KvRecord::deserialize(&encoded, KV_VERSION).unwrap(); - - assert_eq!(encoded.0, &snapshot); - assert_eq!(decoded, kv); - } - - #[test] - fn decode_v0() { - let kv = KvRecord { - namespace: "foo".to_owned(), - key: "bar".to_owned(), - value: Some("baz".to_owned()), - }; - - let snapshot = vec![ - 0x93, 0xa3, b'f', b'o', b'o', 0xa3, b'b', b'a', b'r', 0xa3, b'b', b'a', b'z', - ]; - - let decoded = KvRecord::deserialize(&DecryptedData(snapshot), "v0").unwrap(); - - assert_eq!(decoded, kv); - } -} diff --git a/crates/atuin/Cargo.toml b/crates/atuin/Cargo.toml index 198db48b..1ec6f754 100644 --- a/crates/atuin/Cargo.toml +++ b/crates/atuin/Cargo.toml @@ -28,7 +28,6 @@ atuin-common = { workspace = true } atuin-history = { workspace = true } atuin-daemon = { path = "../atuin-daemon", version = "18.16.1", optional = true, default-features = false } atuin-pty-proxy = { path = "../atuin-pty-proxy", version = "18.16.1", optional = true, default-features = false } -atuin-kv = { workspace = true } log = { workspace = true } time = { workspace = true } diff --git a/docs/.gitignore b/docs/.gitignore deleted file mode 100644 index 45ddf0ae..00000000 --- a/docs/.gitignore +++ /dev/null @@ -1 +0,0 @@ -site/ diff --git a/docs/docs/ai/images/basic-followup-questions.png b/docs/docs/ai/images/basic-followup-questions.png Binary files differdeleted file mode 100644 index d0c1d12d..00000000 --- a/docs/docs/ai/images/basic-followup-questions.png +++ /dev/null diff --git a/docs/docs/ai/images/basic-refine.png b/docs/docs/ai/images/basic-refine.png Binary files differdeleted file mode 100644 index e2404bc5..00000000 --- a/docs/docs/ai/images/basic-refine.png +++ /dev/null diff --git a/docs/docs/ai/images/basic.png b/docs/docs/ai/images/basic.png Binary files differdeleted file mode 100644 index a58e510a..00000000 --- a/docs/docs/ai/images/basic.png +++ /dev/null diff --git a/docs/docs/ai/images/danger.png b/docs/docs/ai/images/danger.png Binary files differdeleted file mode 100644 index 9c762f19..00000000 --- a/docs/docs/ai/images/danger.png +++ /dev/null diff --git a/docs/docs/ai/images/question.png b/docs/docs/ai/images/question.png Binary files differdeleted file mode 100644 index a1dc5690..00000000 --- a/docs/docs/ai/images/question.png +++ /dev/null diff --git a/docs/docs/ai/images/tool_atuin_history.png b/docs/docs/ai/images/tool_atuin_history.png Binary files differdeleted file mode 100644 index c71d37bd..00000000 --- a/docs/docs/ai/images/tool_atuin_history.png +++ /dev/null diff --git a/docs/docs/ai/images/tool_fs.png b/docs/docs/ai/images/tool_fs.png Binary files differdeleted file mode 100644 index 33b6033a..00000000 --- a/docs/docs/ai/images/tool_fs.png +++ /dev/null diff --git a/docs/docs/ai/images/tool_shell.png b/docs/docs/ai/images/tool_shell.png Binary files differdeleted file mode 100644 index 1ccb962f..00000000 --- a/docs/docs/ai/images/tool_shell.png +++ /dev/null diff --git a/docs/docs/ai/introduction.md b/docs/docs/ai/introduction.md deleted file mode 100644 index 1fda185e..00000000 --- a/docs/docs/ai/introduction.md +++ /dev/null @@ -1,53 +0,0 @@ -# Atuin AI - -Atuin AI is a subcommand that enables shell command generation and other information lookup via an LLM directly from your terminal. - -Atuin AI requires an account on [Atuin Hub](https://hub.atuin.sh/), and you'll be prompted to login upon first use of the binary. - -Usage of Atuin AI is currently free. - -## Getting Started - -Atuin AI currently supports zsh, bash, and fish shells. Your shell's usual `atuin init` call will automatically bind the question mark key to the Atuin AI UI (only when the prompt is empty). - -!!! note "Disabling Atuin AI" - - You can disable the default question mark key binding by passing `--disable-ai` to your shell's `atuin init` call, or by setting `ai.enabled` to `false` in your Atuin config. - -## Settings - -For a list of settings that control the behavior of Atuin AI, see [its dedicated settings documentation](./settings.md). - -## Features - -### Command generation - -Prompt the LLM to create a command, and get one back, no fuss. Press `enter` to run, or `tab` to insert. - -[](./images/basic.png) - -### Follow-up - -You can follow-up with another prompt to update the command that will be inserted. - -[](./images/basic-refine.png) - -You can also follow-up with questions to get responses in natural language. - -[](./images/basic-followup-questions.png) - -You can still use `enter` or `tab` to run or insert the last suggested command, even if it was suggested in a previous turn. - -### Conversational and search usage - -If you prompt the LLM with a question that doesn't imply you want to generate a command, it can respond in natural language, and use web search if necessary to fetch the data it needs. - -[](./images/question.png) - -### Dangerous or low-confidence command detection - -The LLM scores its confidence in the command, as well as how dangerous the command is. This information is shown if a threshold is exceeded, and requires an extra confirmation step before running automatically with `enter`. - -The Atuin Hub server also monitors suggested commands for dangerous patterns the LLM didn't catch, and appends its own assessment at the end of the LLM's own assessment. - -[](./images/danger.png) diff --git a/docs/docs/ai/settings.md b/docs/docs/ai/settings.md deleted file mode 100644 index edc54aaf..00000000 --- a/docs/docs/ai/settings.md +++ /dev/null @@ -1,98 +0,0 @@ -# AI Settings - -All the settings that control the behavior of [Atuin AI](./introduction.md) are specified in an `[ai]` section in your `config.toml`. See [the configuration documentation](../configuration/config.md) for more detailed information about Atuin's configuration system. - -### enabled - -Default: `false` - -Whether or not the AI feature are enabled. When set to `false`, the question mark keybinding will output a message with instructions to run `atuin setup` to enable the feature. - -### db_path - -Default: `ai_sessions.db` in the Atuin data directory. - -The path to the SQLite database where Atuin AI sessions are stored. - -### session_continue_minutes - -Default: `60` (minutes) - -The amount of time after the last interaction with Atuin AI that a session is considered "recent" and can be automatically continued. If you interact with Atuin AI and then invoke it again within this time window, the second interaction will be part of the same session. If you wait longer than this time window, a new session will be started. You can always start a new session manually by using the `/new` slash command in the Atuin AI interface. - -### endpoint - -Default: `null` - -The address of the Atuin AI endpoint. Used for AI features like command generation. Most users will not need this setting; it is only necessary for custom AI endpoints. - -### api_token - -Default: `null` - -The API token for the Atuin AI endpoint. Used for AI features like command generation. Most users will not need this setting; it is only necessary for custom AI endpoints. - -## Capabilities - -Settings that control what capabilities are sent to the LLM, which the LLM uses to understand what features the client has available. These are specified under `[ai.capabilities]`. - -### enable_history_search - -Default: `true` - -Whether or not to include the "history search" capability in the context sent to the LLM. This allows the AI to request to search your Atuin history for relevant commands when generating suggestions or answering questions. - -### enable_history_output - -Default: `true` - -Whether or not to include the "history output" capability in the context sent to the LLM. This allows the AI to request to view the output of previous commands. This requires the [pty-proxy](../reference/pty-proxy.md) and [daemon](../reference/daemon.md) to be enabled and running in order for Atuin to capture commands' outputs. - -### enable_file_tools - -Default: `true` - -Whether or not to include the "file tools" capability in the context sent to the LLM. This allows the AI to request to read and update files on your system. - -### enable_command_execution - -Default: `true` - -Whether or not to include the "command execution" capability in the context sent to the LLM. This allows the AI to request to execute commands on your system. - -**Example config** - -```toml -[ai.capabilities] -enable_history_search = false -``` - -## Opening context - -Settings that control what context is sent in the opening AI request. These are specified under `[ai.opening]`. - -### send_cwd - -Default: `false` - -Whether or not to include your current working directory in the context sent to the LLM. By default, only your OS and current shell are sent. - -**Example config** - -```toml -[ai.opening] -send_cwd = true -``` - -### send_last_command - -Default: `false` - -Whether or not to send your previous command as context in the initial request, allowing the AI to provide more relevant suggestions. - -**Example config** - -```toml -[ai.opening] -send_last_command = true -``` diff --git a/docs/docs/ai/skills.md b/docs/docs/ai/skills.md deleted file mode 100644 index 70afadb6..00000000 --- a/docs/docs/ai/skills.md +++ /dev/null @@ -1,97 +0,0 @@ -# Skills - -Skills are reusable instruction sets for Atuin AI: playbooks, conventions, workflows, or any structured guidance you want the LLM to follow for specific tasks. - -## How Skills Work - -Skills are lazily loaded: Atuin sends only skill names and descriptions to the server. The LLM decides which skills are relevant and loads their full content on demand. You can also invoke skills directly with `/skill-name` in the TUI. - -## Creating a Skill - -A skill is a directory containing a `SKILL.md` file with optional YAML frontmatter: - -``` -.atuin/skills/code-review/SKILL.md -``` - -```markdown ---- -name: code-review -description: Conducts a structured code review. Use when the user asks to review code, a PR, or a diff. ---- - -When reviewing code: - -1. **Correctness** — Does the code do what it claims? -2. **Edge cases** — What inputs could break it? -3. **Style** — Does it match the project's conventions? - -Current branch: !`git branch --show-current` -``` - -## Skill Locations - -| Scope | Path | -| ------- | ---------------------------------------- | -| Project | `.atuin/skills/<name>/SKILL.md` | -| Global | `~/.config/atuin/skills/<name>/SKILL.md` | - -Project skills override global skills when names collide. Nested directories are supported for organization (e.g. `.atuin/skills/ops/deploy/SKILL.md`). - -## Frontmatter - -All frontmatter fields are optional. YAML frontmatter goes between `---` markers at the top of `SKILL.md`. - -| Field | Default | Description | -| -------------------------- | ----------------------- | -------------------------------------------------------------------------------------------- | -| `name` | directory name | Display name. Lowercase letters, numbers, hyphens. | -| `description` | first paragraph of body | What the skill does. Sent to the server so the LLM knows when to load it. | -| `disable-model-invocation` | `false` | If `true`, the LLM cannot discover or load the skill. Only reachable via `/name` in the TUI. | - -Multiline descriptions using YAML's `>` (folded) or `|` (literal) syntax are supported. - -## Invoking Skills - -### From the TUI - -Type `/skill-name` to invoke a skill directly. Tab-completion is available. Arguments are supported: - -``` -/deploy patch -``` - -The LLM will see the skill content with `[Loaded skill: deploy]` and `[Arguments: patch]` headers. - -### By the LLM - -When the LLM determines a skill is relevant to your request, it calls `load_skill` automatically to fetch the full content. Skills with `disable-model-invocation: true` are excluded from this — the LLM won't see them. - -## Dynamic Content - -Skills support the same shell substitution as [user context files](user-context.md): - -- **Inline:** `!`command`` — replaced with command stdout -- **Block:** ` ```! ` code block — entire block replaced with script stdout - -Commands run at skill load time (when invoked), not at discovery time. - -## Arguments - -When invoking a skill with arguments (e.g. `/deploy patch`), the `$ARGUMENTS` placeholder in the skill body is replaced with the argument string before shell substitution runs: - -```yaml ---- -name: deploy -description: Deploy the application -disable-model-invocation: true ---- - -Deploy $ARGUMENTS to production. -Current status: !`kubectl get deployment $ARGUMENTS` -``` - -If the body doesn't contain `$ARGUMENTS` and arguments were provided, they're appended as `ARGUMENTS: <value>`. - -## Description Budget - -Skill descriptions are packed into the request to the server under a total character budget. Each description is truncated at 512 characters, then skills are included until the budget is exhausted. If skills are omitted, the server is told which ones were left out. diff --git a/docs/docs/ai/tools-permissions.md b/docs/docs/ai/tools-permissions.md deleted file mode 100644 index b9620b8e..00000000 --- a/docs/docs/ai/tools-permissions.md +++ /dev/null @@ -1,161 +0,0 @@ -# Atuin AI Tools & Permissions - -Atuin AI has a number of tools that it can use to interact with your system, given your permission. The AI can use these tools to help answer questions and perform actions on your behalf. - -## Permission System - -By default, Atuin AI asks your permission before using any client-side tool. You can change these defaults using a _permission file_. - -### Permission Files - -Permission files live at `.atuin/permissions.ai.toml` in any project. When the AI wants to run a tool, Atuin AI will check its working directory for a `.atuin/permissions.ai.toml` file, and will also check every permission file in parent directories, up to the root of the filesystem. Finally, Atuin AI checks for a `permissions.ai.toml` file in the Atuin config directory (`~/.config/atuin/permissions.ai.toml` by default). - -A permission file is a TOML file with the following format: - -```toml -[permissions] - -allow = [ - # rules for automatically allowed tools -] - -deny = [ - # rules for automatically denied tools -] - -ask = [ - # rules for tools that require asking for permission -] -``` - -If Atuin AI doesn't find a matching rule, it defaults to asking for permission before running the tool. - -Permission files found deeper in the filesystem take priority over permission files found higher up. For example, if Atuin AI finds a permission file in the current working directory that allows a tool, it will allow that tool, even if a parent directory has a permission file that denies it. - -Within a permissions file, `ask` rules take priority over `deny` rules, which take priority over `allow` rules. For example, if a permission file has a rule that allows a tool, but also has a rule that asks for permission for that tool, Atuin AI will ask for permission before running the tool. - -### Permission Scopes - -Most rules can be scoped to a particular path or other context. For example, you can allow Atuin AI to read files in a particular directory, but not in others. For rules pertaining to file operations, the scope is a glob pattern that matches file paths. - -### Example Config - -Here's an example of a permission file that allows Atuin AI to read and write any markdown files in the current project (because Write implies Read — see below), but denies it access to any `.env` files. Attempts to read or write any _other_ files will result in Atuin AI requesting permission before proceeding. - -```toml -[permissions] - -allow = [ - "Write(**/*.md)" -] - -deny = [ - "Read(.env)" -] -``` - -## Tools - -### Atuin History - -The `AtuinHistory` tool allows Atuin AI to search your Atuin history for relevant commands. This tool is read-only. Atuin AI might ask to use this tool when you ask it to recall a command or information about a command you ran in the past, or when you ask for help with a failing command (e.g. "why did my last command fail?"). - - - -**Permission rule and scope:** `AtuinHistory` - -**Config value:** `ai.capabilities.enable_history_search` (see [settings documentation](./settings.md#capabilities)) - -**Example permissions file:** - -```toml -[permissions] - -allow = ["AtuinHistory"] -``` - -### Read - -The `Read` tool allows Atuin AI to read files on your system. Atuin AI might ask to use this tool when you ask it to analyze the contents of a file, when you ask for edits to the contents of a file, or when you ask a question that is most easily answered by consulting the contents of a file. - - - -**Permission rule and scope:** `Read(<glob_pattern>)` (e.g. `Read(**/\*.md)`to allow reading all markdown files in the current directory and subdirectories). A missing glob pattern (e.g.`Read`) matches all files. - -**Config value:** `ai.capabilities.enable_fs_tools` (see [settings documentation](./settings.md#capabilities)) — this setting enables both the `Read` and `Write` tools. - -**Example permissions file:** - -```toml -[permissions] -allow = ["Read(**/*.md)"] -deny = ["Read(.secret/**)"] -``` - -!!! warning "Write Implies Read" - - To prevent accidental data loss, Atuin AI is required to read the contents of a file before writing to it. This means that any permission rule that allows the `Write` tool for a particular file or set of files will also automatically allow the `Read` tool for those same files. For example, if you have a rule that allows `Write(**/*.md)`, Atuin AI will also be able to read any markdown files in the current directory and subdirectories, even if you don't have an explicit rule allowing `Read(**/*.md)`. - -### Write - -The `Write` tool allows Atuin AI to create and edit files on your system. Atuin AI might ask to use this tool when you ask it to update configuration for a tool or help debug a problem. - - - -**Permission rule and scope:** `Write(<glob_pattern>)` (e.g. `Write(**/\*.md)`to allow reading all markdown files in the current directory and subdirectories). A missing glob pattern (e.g.`Write`) matches all files. - -**Config value:** `ai.capabilities.enable_fs_tools` (see [settings documentation](./settings.md#capabilities)) — this setting enables both the `Read` and `Write` tools. - -**Example permissions file:** - -```toml -[permissions] -allow = ["Write(**/*.md)"] -deny = ["Write(.secret/**)"] -``` - -!!! note "File Backups" - - The first time Atuin AI writes to a file in a session, it creates a backup of the original file and stores it in Atuin's data directory, under `ai/sessions/<session_id>`. A manifest file in that directory maps the original file paths to the backup file paths. In the future, we'll be providing easier ways to recover from accidental data loss. - -### Shell Command Execution - -The `Shell` tool allows Atuin AI to execute shell commands on your system. Atuin AI might ask to use this tool when you ask it to perform an action that is most easily accomplished by running a shell command itself, or when you ask for help debugging a failing command, or during a multi-step workflow. - - - -**Permission rule and scope:** `Shell(<command pattern>)` (e.g. `Shell(git *)` to allow any command that starts with `git`). A missing command pattern (e.g. `Shell`) matches all commands. - -**Config value:** `ai.capabilities.enable_command_execution` (see [settings documentation](./settings.md#capabilities)) - -**Example permissions file:** - -```toml -[permissions] -allow = [ - "Shell(git add *)", - "Shell(git commit *)" -] -``` - -!!! note "Command Execution Scope" - - The command pattern in a `Shell` permission rule is matched against the words in the command. The `*` wildcard has different behavior depending on where it appears: - - | Pattern | Matches | Does Not Match | - |---------|---------|----------------| - | `*` | Any command | — | - | `git commit *` | `git commit`, `git commit -m "msg"` | `git`, `git push` | - | `ls*` | `ls`, `ls -a`, `lsof` | `cat` | - | `git * --amend` | `git commit --amend`, `git rebase --amend` | `git commit` | - | `git commit` | `git commit` | `git`, `git push`, `git commit -m "msg"` | - - Note the difference between `ls *` (with a space) and `ls*` (without). The space-separated form uses **word-boundary** matching — `ls *` matches `ls` and `ls -a` but _not_ `lsof`. The attached form uses **prefix** matching — `ls*` matches all of those, including `lsof`. - - For `allow` and `ask` rules, a pattern without any wildcard (e.g. `git commit`) is an **exact match** — it only matches when the command words are identical. Use `git commit *` if you want to allow `git commit` with any arguments. - - For `deny` rules, a pattern without any wildcard (e.g. `rm`) is a **prefix match** — it matches any command that starts with that prefix. This means that a `deny` rule of `rm` would deny `rm`, `rm -rf /`, and `rm ./README.md` so be careful when writing `deny` rules without explicit wildcards. - -!!! warning "Compound Commands" - - When the AI runs a compound command (e.g. `git add . && npm test`), Atuin parses it into individual subcommands. For a command to be automatically allowed, all subcommands must be allowed. This means that `git add . && npm test` must be enabled by both `Shell(git add *)` and `Shell(npm test)` for it to be allowed, else it would fall through and ask for permission. However, our parsing is not perfect, and there may be edge cases where it fails to correctly identify the subcommands, and some shells where command parsing is sub-par. For this reason, we recommend being cautious when allowing compound commands with broad patterns. diff --git a/docs/docs/ai/user-context.md b/docs/docs/ai/user-context.md deleted file mode 100644 index bbec4745..00000000 --- a/docs/docs/ai/user-context.md +++ /dev/null @@ -1,44 +0,0 @@ -# Sending Additional Context in Atuin AI - -Atuin AI allows you to send additional context to the LLM beyond just your prompt, similar to `CLAUDE.md` or `AGENTS.md`. - -## Additional Context Search Paths - -Atuin AI looks for additional context in `TERMINAL.md` and `.atuin/TERMINAL.md` files in the current directory and its parent directories. It also checks `TERMINAL.md` in your Atuin config directory (`~/.config/atuin/TERMINAL.md` by default). If it finds any of these files, it sends their contents as additional context to the LLM. - -- `.atuin/TERMINAL.md` — scoped inside the `.atuin` dotdir -- `TERMINAL.md` — at the directory root (e.g. project root) - -It also checks `TERMINAL.md` in your Atuin config directory (`~/.config/atuin/TERMINAL.md` by default). - -If it finds any of these files, it sends their contents as additional context to the LLM. Atuin AI will send at maximum 10 additional context files, prioritizing files found globally first and then other files in order of filesystem depth, shallowest to deepest, and each file is limited to 10,000 characters. - -## Dynamic Content - -You can send dynamic content by using shell substitution in your `TERMINAL.md` file: - -```markdown -My username: !`whoami` -``` - -When Atuin AI reads this file, it will execute the `whoami` command and include its output in the context sent to the LLM. So if your username is `binarymuse`, the context sent to the LLM would include: - -```markdown -My username: binarymuse -``` - -Atuin AI can also run substitutions for code blocks, to run multi-line commands. For example: - -````markdown -```! -node --version -npm --version -git status --short -``` -```` - -## Why not `AGENTS.md`? - -Most agent files are optimized for _coding_ agents: patterns, tools, coding style, and so on. This is great for coding agents, but not as useful for general-purpose agents. By using `TERMINAL.md` instead, we can provide a more flexible way to send additional context that is not tied to coding-specific patterns. This allows users to provide any kind of context they want, without being constrained by the structure of an agent file. - -If your agent file has relevant information, you can instruct the LLM in `TERMINAL.md` to read from it. diff --git a/docs/docs/configuration/advanced-key-binding.md b/docs/docs/configuration/advanced-key-binding.md deleted file mode 100644 index c2edc6c3..00000000 --- a/docs/docs/configuration/advanced-key-binding.md +++ /dev/null @@ -1,445 +0,0 @@ -# Advanced Atuin UI Keybinding - -Atuin includes a powerful keybinding system that can be used to fully customize the TUI keyboard shortcuts. Many of the configuration options, like `enter_accept`, `exit_past_line_start`, and `accept_past_line_end`, can be explicitly expressed with this new configuration. - -The `[keymap]` section in your config replaces the older `[keys]` section. If any `[keymap]` settings are present, the `[keys]` section is ignored entirely. - -!!! warning - Modifier keys, F1-F24 keys, and some special characters work best - or _only_ work - with a terminal that implements the kitty keyboard protocol. Notably, the default macOS Terminal app does _not_ include this feature. For more information and a list of terminals that are known to support this protocol, see [https://sw.kovidgoyal.net/kitty/keyboard-protocol/](https://sw.kovidgoyal.net/kitty/keyboard-protocol/). - -## Keymaps - -The Atuin TUI has multiple modes, each with its own keymap. You configure each one under a separate TOML table: - -| Config section | When it is active | -|----------------------|-------------------| -| `[keymap.emacs]` | Search tab, `keymap_mode = "emacs"` | -| `[keymap.vim-normal]`| Search tab, `keymap_mode = "vim"`, normal mode | -| `[keymap.vim-insert]`| Search tab, `keymap_mode = "vim"`, insert mode | -| `[keymap.inspector]` | Inspector tab (opened with `ctrl-o`) | -| `[keymap.prefix]` | After pressing the prefix key (`ctrl-a` by default) | - -Vim-insert mode inherits all emacs bindings by default, then overrides `esc` and `ctrl-[` to enter normal mode instead of exiting. - -You only need to specify the keys you want to change. Unmentioned keys keep their default bindings. - -!!! warning - If you specify a key in your keymap that would normally be changed by an option, like the `enter` key with the `enter_accept` setting, the setting will not take any affect. Those options modify the default keymap based on their setting, but if you override the key in the keymap, you're responsible for managing correct behavior. - -## Key format - -Keys are specified as TOML string keys using a human-readable format. - -### Basic keys - -Lowercase letters, digits, and named keys: - -``` -"a", "z", "1", "9" -"enter", "esc", "tab", "space", "backspace", "delete" -"up", "down", "left", "right" -"home", "end", "pageup", "pagedown" -"f1", "f2", ... "f12", ... "f24" -``` - -`return` is an alias for `enter`. `escape` is an alias for `esc`. `del` is an alias for `delete`. - -!!! warning "macOS delete key" - The key labeled "delete" on Mac keyboards sends `backspace` (it deletes the character *before* the cursor). The `delete` key in Atuin refers to forward-delete, which is `fn+delete` on a Mac keyboard. - -### Modifiers - -Modifiers are prefixed with a dash separator. Multiple modifiers can be combined: - -``` -"ctrl-c", "alt-f", "ctrl-alt-x" -``` - -Available modifiers: `ctrl`, `alt`, `shift`, `super` (also accepted as `cmd` or `win`). - -!!! warning - The `super` modifier (Cmd on macOS, Win on Windows) **requires** the kitty keyboard protocol. Only terminals that implement this protocol will report the Super modifier to applications. Even in supported terminals, some Super+key combinations may be intercepted by the terminal or OS (e.g. Cmd+C for copy, Cmd+V for paste, or Cmd+T for opening a new tab). - -### Uppercase letters - -An uppercase letter represents itself without needing a `shift` modifier. For example, `"G"` matches the `shift+g` key press. - -### Special characters - -Some special characters are written out directly: - -``` -"?", "/", "[", "]", "$" -``` - -### Shifted and punctuation keys - -When you press a key like `Shift+1`, your terminal sends the resulting character (`!`) rather than "shift-1". To bind shifted punctuation keys, use the character directly: - -```toml -[keymap.emacs] -"!" = "some-action" # Binds to Shift+1 -"@" = "some-action" # Binds to Shift+2 -"#" = "some-action" # Binds to Shift+3 -"$" = "cursor-end" # Binds to Shift+4 (vim $ motion) -``` - -Any single character can be used as a key binding. - -!!! note - The `shift` modifier is still valid for non-character keys like `"shift-tab"` or `"shift-up"`. - -### Media keys - -Media keys are supported on terminals that implement the kitty keyboard protocol with `DISAMBIGUATE_ESCAPE_CODES` enabled: - -``` -"play", "pause", "playpause", "stop" -"fastforward", "rewind", "tracknext", "trackprevious" -"record", "lowervolume", "raisevolume", "mutevolume", "mute" -``` - -### Multi-key sequences - -Separate keys with a space to define a sequence. The first key is buffered until the second key arrives: - -``` -"g g" -``` - -If the second key does not complete a known sequence, both keys are handled individually. - -## Keymap format - -Each entry in a keymap section maps a key to either a simple action or a conditional rule list. - -### Simple binding - -Maps a key directly to a single action, with no conditions: - -```toml -[keymap.emacs] -"ctrl-c" = "return-original" -"enter" = "accept" -``` - -### Conditional binding - -Maps a key to an ordered list of rules. Each rule has an `action` and an optional `when` condition. Rules are evaluated top-to-bottom; the first rule whose condition matches (or that has no condition) wins. - -```toml -[keymap.emacs] -"left" = [ - { when = "cursor-at-start", action = "exit" }, - { action = "cursor-left" }, -] -``` - -In this example, pressing left when the cursor is at position 0 exits the TUI. Otherwise, it moves the cursor left. - -A rule without a `when` field is unconditional and always matches. It is typically placed last as a fallback. - -!!! warning "Override semantics" - When you specify a key in `[keymap]`, it **replaces** the **entire** default binding for that key. Other keys you don't mention keep their defaults. - -## Actions - -Actions are specified as kebab-case strings. - -### Cursor movement - -| Action | Description | -|--------|-------------| -| `cursor-left` | Move cursor one character left | -| `cursor-right` | Move cursor one character right | -| `cursor-word-left` | Move cursor one word left | -| `cursor-word-right` | Move cursor one word right | -| `cursor-word-end` | Move cursor to end of current/next word (vim `e` motion) | -| `cursor-start` | Move cursor to start of line | -| `cursor-end` | Move cursor to end of line | - -### Editing - -| Action | Description | -|--------|-------------| -| `delete-char-before` | Delete the character before the cursor (backspace) | -| `delete-char-after` | Delete the character after the cursor (delete) | -| `delete-word-before` | Delete the word before the cursor | -| `delete-word-after` | Delete the word after the cursor | -| `delete-to-word-boundary` | Delete to the next word boundary (like `ctrl-w`) | -| `clear-line` | Clear the entire input line | -| `clear-to-start` | Clear the start of input line | -| `clear-to-end` | Clear the end of input line | - -### List navigation - -| Action | Description | -|--------|-------------| -| `select-next` | Move selection to the next item in the results list | -| `select-previous` | Move selection to the previous item in the results list | -| `scroll-half-page-up` | Scroll half a page up | -| `scroll-half-page-down` | Scroll half a page down | -| `scroll-page-up` | Scroll a full page up | -| `scroll-page-down` | Scroll a full page down | -| `scroll-to-top` | Jump to the top of the list | -| `scroll-to-bottom` | Jump to the bottom of the list | -| `scroll-to-screen-top` | Jump to the top of the visible screen | -| `scroll-to-screen-middle` | Jump to the middle of the visible screen | -| `scroll-to-screen-bottom` | Jump to the bottom of the visible screen | - -Note: `select-next` and `select-previous` respect the `invert` setting. When `invert` is true, the visual direction is flipped. - -### Commands - -| Action | Description | -|--------|-------------| -| `accept` | Accept the selected entry and **execute it immediately** | -| `accept-N` | Accept the Nth entry below the selection and execute it (e.g. `accept-1` through `accept-9`) | -| `return-selection` | Return the selected entry to the command line **without executing** | -| `return-selection-N` | Return the Nth entry below the selection without executing (e.g. `return-selection-1` through `return-selection-9`) | -| `return-original` | Close the TUI and return the original command line text | -| `return-query` | Close the TUI and return the current search query | -| `copy` | Copy the selected entry to the clipboard | -| `delete` | Delete the selected entry from history | -| `delete-all` | Delete **all** history entries matching the selected command text | -| `exit` | Exit the TUI (behavior depends on the `exit_mode` setting) | -| `redraw` | Redraw the screen | -| `cycle-filter-mode` | Cycle through filter modes (global, host, session, directory) | -| `cycle-search-mode` | Cycle through search modes (fuzzy, prefix, fulltext, skim) | -| `toggle-tab` | Toggle between the search tab and inspector tab | -| `switch-context` | Switch to the [context](../guide/advanced-usage.md#context-switch) of the currently selected command | -| `clear-context` | Return to the initial [context](../guide/advanced-usage.md#context-switch) | - -The difference between `accept` and `return-selection`: `accept` runs the command immediately when the TUI closes, while `return-selection` places it on your command line for further editing before you press enter. The `enter_accept` setting controls which of these the default `enter` key uses. - -### Mode changes - -| Action | Description | -|--------|-------------| -| `vim-enter-normal` | Switch to vim normal mode | -| `vim-enter-insert` | Switch to vim insert mode (cursor stays in place) | -| `vim-enter-insert-after` | Switch to vim insert mode (cursor moves right, like vim `a`) | -| `vim-enter-insert-at-start` | Move to start of line and enter vim insert mode (like vim `I`) | -| `vim-enter-insert-at-end` | Move to end of line and enter vim insert mode (like vim `A`) | -| `vim-search-insert` | Clear the search input and enter vim insert mode (like vim `?` or `/`) | -| `vim-change-to-end` | Delete to end of line and enter vim insert mode (like vim `C`) | -| `enter-prefix-mode` | Enter prefix mode (waits for one more key, e.g. `d` for delete) | - -### Inspector - -| Action | Description | -|--------|-------------| -| `inspect-previous` | Inspect the previous entry (in the inspector tab) | -| `inspect-next` | Inspect the next entry (in the inspector tab) | - -### Special - -| Action | Description | -|--------|-------------| -| `noop` | Do nothing (useful for disabling a default binding) | - -## Conditions - -Conditions let a single key do different things depending on the current state. They are specified as strings in the `when` field of a rule. - -### Condition atoms - -| Condition | True when | -|-----------|-----------| -| `cursor-at-start` | The cursor is at position 0 | -| `cursor-at-end` | The cursor is at the end of the input | -| `input-empty` | The input line is empty (no text entered) | -| `original-input-empty` | The original query passed to the TUI was empty | -| `list-at-start` | The selection is at the first entry (index 0) | -| `list-at-end` | The selection is at the last entry | -| `no-results` | The search returned zero results | -| `has-results` | The search returned at least one result | -| `has-context` | The context comes from a previously selected command (`switch-context`) | - -### Boolean expressions - -Conditions support boolean operators with standard precedence (`!` binds tightest, then `&&`, then `||`). Parentheses can override precedence. - -```toml -# Negation -{ when = "!no-results", action = "select-next" } - -# Conjunction (AND) -{ when = "cursor-at-start && input-empty", action = "exit" } - -# Disjunction (OR) -{ when = "list-at-start || no-results", action = "exit" } - -# Grouping with parentheses -{ when = "(cursor-at-start && !input-empty) || no-results", action = "return-original" } -``` - -## Examples - -### Reproducing the default `[keys]` behaviors - -The default keymaps already encode the standard `[keys]` behaviors. Here is what they look like as explicit `[keymap]` entries for reference. - -**`scroll_exits = true`** (default) -- exit when scrolling past the first entry: - -```toml -[keymap.emacs] -"down" = [ - { when = "list-at-start", action = "exit" }, - { action = "select-next" }, -] -``` - -**`exit_past_line_start = true`** (default) -- exit when pressing left at position 0: - -```toml -[keymap.emacs] -"left" = [ - { when = "cursor-at-start", action = "exit" }, - { action = "cursor-left" }, -] -``` - -**`accept_past_line_end = true`** (default) -- accept when pressing right at the end: - -```toml -[keymap.emacs] -"right" = [ - { when = "cursor-at-end", action = "accept" }, - { action = "cursor-right" }, -] -``` - -**`accept_past_line_start = true`** -- accept when pressing left at position 0 (off by default): - -```toml -[keymap.emacs] -"left" = [ - { when = "cursor-at-start", action = "accept" }, - { action = "cursor-left" }, -] -``` - -**`accept_with_backspace = true`** -- accept when pressing backspace with empty input (off by default): - -```toml -[keymap.emacs] -"backspace" = [ - { when = "cursor-at-start", action = "accept" }, - { action = "delete-char-before" }, -] -``` - -### Disabling scroll-exit - -To make `down` always scroll without ever exiting: - -```toml -[keymap.emacs] -"down" = "select-next" -``` - -### Disabling a key entirely - -Use `noop` to make a key do nothing: - -```toml -[keymap.emacs] -"ctrl-d" = "noop" -``` - -### ctrl-d to exit only when input is empty - -```toml -[keymap.emacs] -"ctrl-d" = [ - { when = "input-empty", action = "exit" }, - { action = "delete-char-after" }, -] -``` - -### Making enter return the selection without executing - -```toml -[keymap.emacs] -"enter" = "return-selection" -``` - -This is equivalent to setting `enter_accept = false`, but expressed directly as a keybinding. - -### Custom vim-normal bindings - -```toml -[keymap.vim-normal] -# Use 'q' to quit -"q" = "exit" - -# Use 'x' to delete the selected entry -"x" = "delete" - -# Use 'y' to copy -"y" = "copy" -``` - -### Custom inspector bindings - -```toml -[keymap.inspector] -# Use 'delete' key in inspector to remove entries -"delete" = "delete" -``` - -### Custom prefix bindings - -Prefix mode is a two-step shortcut: press the prefix key (++ctrl+a++ by default), then a second key. This is useful for actions you don't need on a single key. The default prefix bindings are: - -| Key | Action | -|-----|--------| -| `d` | Delete the selected entry | -| `D` | Delete all entries matching the selected command | -| `a` | Move cursor to start of line | -| `c` | Clear context (if in a switched context), otherwise switch context | - -You can customize these with `[keymap.prefix]`: - -```toml -[keymap.prefix] -# Add a binding to copy the selected entry -"y" = "copy" - -# Make 'x' delete instead of 'd' -"x" = "delete" -"d" = "noop" -``` - -To change which key enters prefix mode, set `prefix` under `[keys]`: - -```toml -[keys] -prefix = "x" # ctrl-x instead of ctrl-a -``` - -Or bind `enter-prefix-mode` directly in your keymap: - -```toml -[keymap.emacs] -"ctrl-x" = "enter-prefix-mode" -``` - -## Relationship with `[keys]` - -The `[keymap]` section is a more powerful replacement for the `[keys]` section. The two are **mutually exclusive**: - -- If you have any `[keymap]` settings, the entire `[keys]` section is ignored. Defaults are built from the standard `[keys]` values, and then your `[keymap]` overrides are applied on top. -- If you have no `[keymap]` settings, the `[keys]` section works as before for backward compatibility. - -If you are migrating from `[keys]` to `[keymap]`, here is how the old flags map: - -| `[keys]` setting | Equivalent `[keymap]` | -|------------------|-----------------------| -| `scroll_exits = false` | `"down" = "select-next"` and `"up" = "select-previous"` in the relevant keymap | -| `exit_past_line_start = false` | `"left" = "cursor-left"` | -| `accept_past_line_end = false` | `"right" = "cursor-right"` | -| `accept_past_line_start = true` | `"left" = [{ when = "cursor-at-start", action = "accept" }, { action = "cursor-left" }]` | -| `accept_with_backspace = true` | `"backspace" = [{ when = "cursor-at-start", action = "accept" }, { action = "delete-char-before" }]` | -| `prefix = "x"` | Prefix key becomes `ctrl-x` (set in the emacs/vim keymaps) | diff --git a/docs/docs/configuration/config.md b/docs/docs/configuration/config.md deleted file mode 100644 index 0e82f19a..00000000 --- a/docs/docs/configuration/config.md +++ /dev/null @@ -1,1052 +0,0 @@ -# Config - -Atuin maintains two configuration files, stored in `~/.config/atuin/`. We store -data in `~/.local/share/atuin` (unless overridden by XDG\_\*). - -The full path to the config file would be `~/.config/atuin/config.toml` - -The config location can be overridden with ATUIN_CONFIG_DIR - -### `db_path` - -Default: `~/.local/share/atuin/history.db` - -The path to the Atuin SQLite database. - -```toml -db_path = "~/.history.db" -``` - -### `key_path` - -Default: `~/.local/share/atuin/key` - -The path to the Atuin encryption key. - -```toml -key_path = "~/.atuin-key" -``` - -### `session_path` - -Default: `~/.local/share/atuin/session` - -The path to the Atuin server session file. -This is essentially just an API token - -```toml -session_path = "~/.atuin-session" -``` - -### `dialect` - -Default: `us` - -This configures how the [stats](../reference/stats.md) command parses dates. It has two -possible values - -```toml -dialect = "uk" -``` - -or - -```toml -dialect = "us" -``` - -### `auto_sync` - -Default: `true` - -Configures whether or not to automatically sync, when logged in. - -```toml -auto_sync = true/false -``` - -### `update_check` - -Default: `true` - -Configures whether or not to automatically check for updates. - -```toml -update_check = true/false -``` - -### `sync_address` - -Default: `https://api.atuin.sh` - -The address of the server to sync with! - -```toml -sync_address = "https://api.atuin.sh" -``` - -### `sync_frequency` - -Default: `1h` - -How often to automatically sync with the server. This can be given in a -"human-readable" format. For example, `10s`, `20m`, `1h`, etc. - -If set to `0`, Atuin will sync after every command. Some servers may potentially -rate limit, which won't cause any issues. - -```toml -sync_frequency = "1h" -``` - -### `search_mode` - -Default: `fuzzy` - -Which search mode to use. Atuin supports "prefix", "fulltext", "fuzzy", "daemon-fuzzy", and -"skim" search modes. - -Prefix mode searches for "query\*"; fulltext mode searches for "\*query\*"; -"fuzzy" applies the [fuzzy search syntax](#fuzzy-search-syntax); -"skim" applies the [skim search syntax](https://github.com/lotabout/skim#search-syntax). - -!!! note "daemon-fuzzy search mode" - - The "daemon-fuzzy" mode is new as of Atuin 18.13. This search mode uses an in-memory index, stored in the daemon, to perform fast and customizable searches. - - To use the new `"daemon-fuzzy"` mode, enable the daemon, set autostart to true (unless you manage its lifecycle yourself), and set the search mode: - - ```toml - search_mode = "daemon-fuzzy" - - [daemon] - enabled = true - autostart = true - ``` - - You can customize the priority given to frequency, recency, and frecency scores in this mode. See [the score multipliers section](#score-multipliers) for more information. - -#### `fuzzy` search syntax - -The "fuzzy" and "daemon-fuzzy" search syntax is based on the -[fzf search syntax](https://github.com/junegunn/fzf#search-syntax). - -| Token | Match type | Description | -| --------- | -------------------------- | ------------------------------------ | -| `sbtrkt` | fuzzy-match | Items that match `sbtrkt` | -| `'wild` | exact-match (quoted) | Items that include `wild` | -| `^music` | prefix-exact-match | Items that start with `music` | -| `.mp3$` | suffix-exact-match | Items that end with `.mp3` | -| `!fire` | inverse-exact-match | Items that do not include `fire` | -| `!^music` | inverse-prefix-exact-match | Items that do not start with `music` | -| `!.mp3$` | inverse-suffix-exact-match | Items that do not end with `.mp3` | - -A single bar character term acts as an OR operator. For example, the following -query matches entries that start with `core` and end with either `go`, `rb`, -or `py`. - -``` -^core go$ | rb$ | py$ -``` - -!!! warning "Bar not supported in daemon-fuzzy" - The "daemon-fuzzy" search mode does not currently support the bar character operator. - -### `filter_mode` - -Default: `global` - -The default filter to use when searching - -| Mode | Description | -|------------------|--------------------------------------------------------------------------------------| -| global (default) | Search from the full history | -| host | Search history from this host | -| session | Search history from the current session | -| directory | Search history from the current directory | -| workspace | Search history from the current git repository | -| session-preload | Search from the current session and the global history from before the session start | - -Filter modes can still be toggled via ctrl-r - -```toml -filter_mode = "host" -``` - -### `search_mode_shell_up_key_binding` - -Atuin version: >= 17.0 - -Default: `fuzzy` - -The default searchmode to use when searching and being invoked from a shell up-key binding. - -Accepts exactly the same options as `search_mode` above - -```toml -search_mode_shell_up_key_binding = "fuzzy" -``` - -Defaults to the value specified for `search_mode`. - -### `filter_mode_shell_up_key_binding` - -Default: `global` - -The default filter to use when searching and being invoked from a shell up-key binding. - -Accepts exactly the same options as `filter_mode` above - -```toml -filter_mode_shell_up_key_binding = "session" -``` - -Defaults to the value specified for `filter_mode`. - -### `inline_height_shell_up_key_binding` - -The maximum number of lines the interface should take up when atuin is invoked from a shell up-key binding. - -The accepted values are identical to those of `inline_height`. - -When unset, the value from `inline_height` is used. - -### `workspaces` - -Atuin version: >= 17.0 - -Default: `false` - -This flag enables a pseudo filter-mode named "workspace": the filter is automatically -activated when you are in a git repository. - -With workspace filtering enabled, Atuin will filter for commands executed in any directory -within a git repository tree. - -Filter modes can still be toggled via ctrl-r. - -### `style` - -Default: `compact` - -Which style to use. Possible values: `auto`, `full` and `compact`. - -- `compact`: - - - -- `full`: - - - -This means that Atuin will automatically switch to `compact` mode when the terminal window is too short for `full` to display properly. - -### `invert` - -Atuin version: >= 17.0 - -Default: `false` - -Invert the UI - put the search bar at the top. - -```toml -invert = true/false -``` - -### `inline_height` - -Default: `40` - -Set the maximum number of lines Atuin's interface should take up. - -If set to `0`, Atuin will always take up as many lines as available (full screen). - -### `show_preview` - -Default: `true` - -Configure whether or not to show a preview of the selected command. - -Useful when the command is longer than the terminal width and is cut off. - -### `max_preview_height` - -Atuin version: >= 17.0 - -Default: `4` - -Configure the maximum height of the preview to show. - -Useful when you have long scripts in your history that you want to distinguish by more than the first few lines. - -### `show_help` - -Atuin version: >= 17.0 - -Default: `true` - -Configure whether or not to show the help row, which includes the current Atuin version (and whether an update is available), a keymap hint, and the total amount of commands in your history. - -### `show_tabs` - -Atuin version: >= 18.0 - -Default: `true` - -Configure whether or not to show tabs for search and inspect. - -### `auto_hide_height` - -Atuin version: >= 18.4 - -Default: `8` - -Set Atuin to hide lines when a minimum number of rows is subceeded. This has no effect except -when `compact` style is being used (see `style` above), and currently applies to only the -interactive search and inspector. It can be turned off entirely by setting to `0`. - -### `exit_mode` - -Default: `return-original` - -What to do when the escape key is pressed when searching - -| Value | Behaviour | -| ------------------------- | ---------------------------------------------------------------- | -| return-original (default) | Set the command-line to the value it had before starting search | -| return-query | Set the command-line to the search query you have entered so far | - -Pressing ctrl+c or ctrl+d will always return the original command-line value. - -```toml -exit_mode = "return-query" -``` - -### `history_format` - -Default to `history list` - -The history format allows you to configure the default `history list` format - which can also be specified with the --format arg. - -The specified --format arg will prioritize the config when both are present - -More on [history list](../reference/list.md) - -### `history_filter` - -The history filter allows you to exclude commands from history tracking - maybe you want to keep ALL of your `curl` commands totally out of your shell history, or maybe just some matching a pattern. - -This supports regular expressions, so you can hide pretty much whatever you want! - -```toml -## Note that these regular expressions are unanchored, i.e. if they don't start -## with ^ or end with $, they'll match anywhere in the command. -history_filter = [ - "^secret-cmd", - "^innocuous-cmd .*--secret=.+" -] -``` - -### `cwd_filter` - -The cwd filter allows you to exclude directories from history tracking. - -This supports regular expressions, so you can hide pretty much whatever you want! - -```toml -## Note that these regular expressions are unanchored, i.e. if they don't start -## with ^ or end with $, they'll match anywhere in the path. -# cwd_filter = [ -# "^/very/secret/directory", -# ] -``` - -After updating that parameter, you can run [the prune command](../reference/prune.md) to remove old history entries that match the new filters. - -### `store_failed` - -Atuin version: >= 18.3.0 - -Default: `true` - -```toml -store_failed = true -``` - -Configures whether to store commands that failed (those with non-zero exit status) or not. - -### `secrets_filter` - -Atuin version: >= 17.0 - -Default: `true` - -```toml -secrets_filter = true -``` - -This matches history against a set of default regex, and will not save it if we get a match. Defaults include - -1. AWS key id -2. Github pat (old and new) -3. Slack oauth tokens (bot, user) -4. Slack webhooks -5. Stripe live/test keys -6. Atuin login command -7. Cloud environment variable patterns (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AZURE_STORAGE_CLASS_KEY`, `GOOGLE_SERVICE_ACCOUNT_KEY`) -8. Netlify authentication tokens -9. Npm pat -10. Pulumi pat - -### macOS Ctrl-n key shortcuts - -Default: `true` - -macOS does not have an ++alt++ key, although terminal emulators can often be configured to map the ++option++ key to be used as ++alt++. _However_, remapping ++option++ this way may prevent typing some characters, such as using ++option+3++ to type `#` on the British English layout. For such a scenario, set the `ctrl_n_shortcuts` option to `true` in your config file to replace ++alt+0++ to ++alt+9++ shortcuts with ++ctrl+0++ to ++ctrl+9++ instead: - -```toml -# Use Ctrl-0 .. Ctrl-9 instead of Alt-0 .. Alt-9 UI shortcuts -ctrl_n_shortcuts = true -``` - -### show_numeric_shortcuts - -Atuin version: >= 18.9 - -Default: `true` - -Whether to show numeric shortcuts (1..9) beside list items in the TUI. Set this to `false` to hide the moving numbers if you find them distracting. - -### `network_timeout` - -Atuin version: >= 18.0 - -Default: `30` - -The max amount of time (in seconds) to wait for a network request. If any -operations with a sync server take longer than this, the code will fail - -rather than wait indefinitely. - -### `network_connect_timeout` - -Atuin version: >= 18.0 - -Default: `5` - -The max time (in seconds) we wait for a connection to become established with a -remote sync server. Any longer than this and the request will fail. - -### `local_timeout` - -Atuin version: >= 18.0 - -Default: `5` - -Timeout (in seconds) for acquiring a local database connection (sqlite). - -### `command_chaining` - -Atuin version: >= 18.8 - -Default: `false` - -Allows building a command chain with the `&&` or `||` operator. When enabled, opening atuin will search for the next command in the chain, and append to the current buffer. - -### `enter_accept` - -Atuin version: >= 17.0 - -Default: `false` - -When set to true, Atuin will default to immediately executing a command rather -than the user having to press enter twice. Pressing tab will return to the -shell and give the user a chance to edit. - -This technically defaults to true for new users, but false for existing. We -have set `enter_accept = true` in the default config file. This is likely to -change to be the default for everyone in a later release. - -### `keymap_mode` - -Atuin version: >= 18.0 - -Default: `emacs` - -The initial keymap mode of the interactive Atuin search (e.g. started by the -keybindings in the shells). There are four supported values: `"emacs"`, -`"vim-normal"`, `"vim-insert"`, and `"auto"`. The keymap mode `"emacs"` is the -most basic one. In the keymap mode `"vim-normal"`, you may use ++k++ -and ++j++ to navigate the history list as in Vim, whilst pressing - -++i++ changes the keymap mode to `"vim-insert"`. In the keymap mode `"vim-insert"`, -you can search for a string as in the keymap mode `"emacs"`, while pressing ++esc++ -switches the keymap mode to `"vim-normal"`. When set to `"auto"`, the initial -keymap mode is automatically determined based on the shell's keymap that triggered -the Atuin search. `"auto"` is not supported by NuShell at present, where it will -always trigger the Atuin search with the keymap mode `"emacs"`. - -### `keymap_cursor` - -Atuin version: >= 18.0 - -Default: `(empty dictionary)` - -The terminal's cursor style associated with each keymap mode in the Atuin -search. This is specified by a dictionary whose keys and values being the -keymap names and the cursor styles, respectively. A key specifies one of the -keymaps from `emacs`, `vim_insert`, and `vim_normal`. A value is one of the -cursor styles, `default` or `{blink,steady}-{block,underline,bar}`. The -following is an example. - -```toml -keymap_cursor = { emacs = "blink-block", vim_insert = "blink-block", vim_normal = "steady-block" } -``` - -If the cursor style is specified, the terminal's cursor style is changed to the -specified one when the Atuin search starts with or switches to the -corresponding keymap mode. Also, the terminal's cursor style is reset to the -one associated with the keymap mode corresponding to the shell's keymap on the -termination of the Atuin search. - -### `prefers_reduced_motion` - -Atuin version: >= 18.0 - -Default: `false` - -Enable this, and Atuin will reduce motion in the TUI as much as possible. Users -with motion sensitivity can find the live-updating timestamps distracting. - -Alternatively, set env var NO_MOTION - -## search - -### `filters` - -Atuin version: >= 18.4 - -The list of filter modes available in interactive search, in the order they cycle through when you press ctrl-r. By default, all modes are enabled. Removing a mode from this list disables it entirely. The `workspace` mode is skipped when not in a git repository or when `workspaces = false`. See [`filter_mode`](#filter_mode) for a description of each mode. - -The `filter_mode` setting selects the initial mode from this list. If `filter_mode` is set to a mode not in the list, the first available mode is used instead. - -```toml -[search] -filters = ["global", "host", "session", "directory"] -``` - -### Score multipliers - -For the [`"daemon-fuzzy"` search mode](#search_mode), you can control the scoring of matched items. The system scores matches based on three numbers: frequency, recency, and frecency: - -* Frequency — how often this exact match has been run, with diminishing returns -* Recency — how recently this exact match was last run -* Frecency — a combination of frequency and recency - -The frecency calculation is `Recency Score * Recency Multiplier + Frequency Score * Frequency Multiplier`. By changing the options below, you can customize the relative importance of each part of the score calculation. - -For each setting, a value of `1.0` (the default) means the score is used as-is. Values less than `1.0` decrease that score's influence, and values greater than `1.0` increase that score's influence. - -So, for example, if you cared a lot about how frequently you run a command but not as much how recently, you could set `frequency_score_multiplier` to `10.0` and `recency_score_multiplier` to `0.1`. - -!!! warning "daemon-fuzzy mode only" - The score multiplier settings shown here only work with the `"daemon-fuzzy"` search mode. - -#### `frequency_score_multiplier` - -Default: `1.0` - -The multiplier to apply to the frequency score in the frecency calculation. Setting this to `0` disables the frequency portion of the frecency scoring altogether. - -#### `recency_score_multiplier` - -Default: `1.0` - -The multiplier to apply to the recency score in the frecency calculation. Setting this to `0` disables the recency portion of the frecency scoring altogether. - -#### `frecency_score_multiplier` - -Default: `1.0` - -The multiplier used for the final frecency score. Setting this to `0` disables frecency scoring altogether, relying solely on the fuzzy matcher's score. - -Example: - -```toml -search_mode = "daemon-fuzzy" - -[daemon] -enabled = true -autostart = true - -[search] -recency_score_multiplier = 10.0 -frequency_score_multiplier = 0.8 -frecency_score_multiplier = 2.0 -``` - -#### `authors` - -Default: `["$all-user"]` - -Filter search results by command author. This controls which commands appear in interactive search based on who (or what) ran them. Useful when AI coding agents are recording commands via [agent hooks](../guide/agent-hooks.md). - -Special values: - -| Value | Meaning | -|-------|---------| -| `$all-user` | Commands from any author that is **not** a known AI agent | -| `$all-agent` | Commands from any known AI agent | - -You can also use literal author names like `"claude-code"`, `"codex"`, or `"pi"`. - -```toml -[search] -# Default: only show human-authored commands -authors = ["$all-user"] - -# Show everything (no author filtering) -# authors = [] - -# Show commands from you and Claude Code -# authors = ["$all-user", "claude-code"] -``` - -## Stats - -This section of client config is specifically for configuring Atuin stats calculations - -``` -[stats] -common_subcommands = [...] -common_prefix = [...] -``` - -### `common_subcommands` - -Default: - -```toml -common_subcommands = [ - "apt", - "cargo", - "composer", - "dnf", - "docker", - "git", - "go", - "ip", - "jj", - "kubectl", - "nix", - "nmcli", - "npm", - "pecl", - "pnpm", - "podman", - "port", - "systemctl", - "tmux", - "yarn", -] -``` - -Configures commands where we should consider the subcommand as part of the statistics. For example, consider `kubectl get` rather than just `kubectl`. - -### `common_prefix` - -Atuin version: >= 17.1 - -Default: - -```toml -common_prefix = [ - "sudo", -] -``` - -Configures commands that should be totally stripped from stats calculations. For example, 'sudo' should be ignored. - -## sync - -We have developed a new version of sync, that is both faster and more efficient than the original version. - -Presently, it is the default for fresh installs but not for existing users. This will change in a later release. - -To enable sync v2, add the following to your config - -```toml -[sync] -records = true -``` - -## `dotfiles` - -Atuin version: >= 18.1 - -Default: `false` - -To enable sync of shell aliases between hosts. Requires `sync` enabled. - -Add the new section to the bottom of your config file, for every machine you use Atuin with - -```toml -[dotfiles] -enabled = true -``` - -Note: you will need to have sync v2 enabled. See the above section. - -Manage aliases using the command line options - -``` -# Alias 'k' to 'kubectl' -atuin dotfiles alias set k kubectl - -# List all aliases -atuin dotfiles alias list - -# Delete an alias -atuin dotfiles alias delete k -``` - -After setting an alias, you will either need to restart your shell or source the init file for the change to take affect - -## keys - -This section of the client config is specifically for configuring key-related settings. - -``` -[keys] -scroll_exits = [...] -prefix = 'a' -``` - -### `scroll_exits` - -Atuin version: >= 18.1 - -Default: `true` - -Configures whether the TUI exits, when scrolled past the last or first entry. - -### `prefix` - -Atuin version: > 18.3 - -Default: `a` - -Which key to use as the prefix. Prefix mode is a two-step shortcut system: you press ++ctrl++ and the prefix key to enter prefix mode, then press a second key to trigger an action. For example, with the default prefix `a`, pressing ++ctrl+a++ then ++d++ deletes the selected entry. - -See the [key binding page](key-binding.md#prefix-mode) for the full list of default prefix shortcuts, or the [advanced key binding page](advanced-key-binding.md#custom-prefix-bindings) to customize them. - -### `exit_past_line_start` - -Atuin version: >= 18.5 - -Default: `true` - -Exits the TUI when scrolling left while the cursor is at the start of the line. - -### `accept_past_line_end` - -Atuin version: >= 18.5 - -Default: `true` - -The right arrow key performs the same functionality as Tab and copies the selected line to the command line to be -modified. - -### `accept_past_line_start` - -Atuin version: >= 18.9 - -Default: `false` - -The left arrow key performs the same functionality as Tab and copies the selected line to the command line to be -modified. - -### `accept_with_backspace` - -Atuin version: >= 18.9 - -Default: `false` - -The backspace key performs the same functionality as Tab and copies the selected line to the command line to be -modified. - -## preview - -This section of the client config is specifically for configuring preview-related settings. -(In the future the other 2 preview settings will be moved here.) - -``` -[preview] -strategy = [...] -``` - -### `strategy` - -Atuin version: >= 18.3 - -Default: `auto` - -Which preview strategy is used to calculate the preview height. It respects `max_preview_height`. - -| Value | Preview height is calculated from the length of the | -| -------------- | --------------------------------------------------- | -| auto (default) | selected command | -| static | longest command in the current result set | -| fixed | use `max_preview_height` as fixed value | - -By using `auto` a preview is shown, if the command is longer than the width of the terminal. - -## Daemon - -Atuin version: >= 18.3 - -### enabled - -Default: `false` - -Enable the background daemon - -Add the new section to the bottom of your config file - -```toml -[daemon] -enabled = true -``` - -### autostart - -Default: `false` - -Automatically start and manage the daemon when needed. -This is not compatible with `systemd_socket = true`. -If a legacy experimental daemon is already running, restart it manually once before using autostart. - -```toml -autostart = false -``` - -### sync_frequency - -Default: `300` - -How often the daemon should sync, in seconds - -```toml -sync_frequency = 300 -``` - -### socket_path - -Default: - -```toml -socket_path = "~/.local/share/atuin/atuin.sock" -``` - -Where to bind a unix socket for client -> daemon communication - -If XDG_RUNTIME_DIR is available, then we use this directory instead. - -### pidfile_path - -Default: - -```toml -pidfile_path = "~/.local/share/atuin/atuin-daemon.pid" -``` - -Path to the daemon pidfile used for process coordination. - -### systemd_socket - -Default `false` - -Use a socket passed via systemd socket activation protocol instead of the path - -```toml -systemd_socket = false -``` - -### tcp_port - -Default: `8889` - -The port to use for client -> daemon communication. Only used on non-unix systems. - -```toml -tcp_port = 8889 -``` - -## logs - -Atuin version: >= 18.13 - -Behavior of log files. - -### enabled - -Default: `true` - -Whether or not to enable file-based logging. - -### dir - -Default: `"~/.atuin/logs"` - -The directory in which to store log files. - -### level - -Default: `"info"` - -The logging level to use. Valid values are `"trace"`, `"debug"`, `"info"`, `"warn"`, and `"error"`, in order of highest-to-lowest verbosity. - -### retention - -Default: `4` - -How many days of log files to keep (per file type). Files older than this will be removed. - -### ai - -A sub-object with specific options for AI logging: - -* `enabled` - whether to output AI logs; defaults to `logs.enabled` -* `file` - the filename to use for the AI logs; defaults to `"ai.log"`. Always relative to `logs.dir`. -* `level` - override the log level for the AI logs; defaults to `logs.level` -* `retention` - how many days to store AI logs; defaults to `logs.retention` - -### daemon - -A sub-object with specific options for daemon logging: - -* `enabled` - whether to output daemon logs; defaults to `logs.enabled` -* `file` - the filename to use for the daemon logs; defaults to `"daemon.log"`. Always relative to `logs.dir`. -* `level` - override the log level for the daemon logs; defaults to `logs.level` -* `retention` - how many days to store daemon logs; defaults to `logs.retention` - -### search - -A sub-object with specific options for search logging: - -* `enabled` - whether to output search logs; defaults to `logs.enabled` -* `file` - the filename to use for the search logs; defaults to `"search.log"`. Always relative to `logs.dir`. -* `level` - override the log level for the search logs; defaults to `logs.level` -* `retention` - how many days to store search logs; defaults to `logs.retention` - -## theme - -Atuin version: >= 18.4 - -The theme to use for showing the terminal interface. - -```toml -[theme] -name = "default" -debug = false -max_depth = 10 -``` - -### `name` - -Default: `"default"` - -A theme name that must be present as a built-in (unset or `default` for the default, -else `autumn` or `marine`), or found in the themes directory, with the suffix `.toml`. -By default this is `~/.config/atuin/themes/` but can be overridden with the -`ATUIN_THEME_DIR` environment variable. - -```toml -name = "my-theme" -``` - -### `debug` - -Default: `false` - -Output information about why a theme will not load. Independent from other log -levels as it can cause data from the theme file to be printed unfiltered to the -terminal. - -```toml -debug = false -``` - -### `max_depth` - -Default: 10 - -Number of levels of "parenthood" that will be traversed for a theme. This should not -need to be added in or changed in normal usage. - -```toml -max_depth = 10 -``` - -## ui - -Atuin version: >= 18.5 - -Configure the interactive search UI appearance. - -```toml -[ui] -columns = ["duration", "time", "command"] -``` - -### `columns` - -Default: `["duration", "time", "command"]` - -Columns to display in the interactive search, from left to right. The selection -indicator (`" > "`) is always shown first implicitly. - -Each column can be specified as: -- A simple string (uses default width): `"duration"` -- An object with type and optional width/expand: `{ type = "directory", width = 30 }` - -#### Available column types - -| Column | Default Width | Description | -| --------- | ------------- | ----------------------------------------------- | -| duration | 5 | Command execution duration (e.g., "123ms") | -| time | 8 | Relative time since execution (e.g., "59m ago") | -| datetime | 16 | Absolute timestamp (e.g., "2025-01-22 14:35") | -| directory | 20 | Working directory (truncated if too long) | -| host | 15 | Hostname where command was run | -| user | 10 | Username | -| exit | 3 | Exit code (colored by success/failure) | -| command | * | The command itself (expands by default) | - -#### Column options - -- **type**: The column type (required when using object format) -- **width**: Custom width in characters (optional, uses default if not specified) -- **expand**: If `true`, the column fills remaining space. Default is `true` for `command`, `false` for others. Only one column should have `expand = true`. - -#### Examples - -```toml -# Minimal - more space for commands -columns = ["duration", "command"] - -# With custom directory width -columns = ["duration", { type = "directory", width = 30 }, "command"] - -# Show host for multi-machine sync users -columns = ["duration", "time", "host", "command"] - -# Show exit codes prominently -columns = ["exit", "duration", "command"] - -# Make directory expand instead of command -columns = ["duration", "time", { type = "directory", expand = true }, { type = "command", expand = false }] -``` - -## ai - -The settings for Atuin AI are listed in [a separate section](../../ai/settings/). diff --git a/docs/docs/configuration/key-binding.md b/docs/docs/configuration/key-binding.md deleted file mode 100644 index c8dc91bc..00000000 --- a/docs/docs/configuration/key-binding.md +++ /dev/null @@ -1,292 +0,0 @@ -# Key Binding - -## Custom up arrow filter mode - -It can be useful to use a different filter or search mode on the up arrow. For example, you could use ctrl-r for searching globally, but the up arrow for searching history from the current directory only. - -Set your config like this: - -``` -filter_mode_shell_up_key_binding = "directory" # or global, host, directory, etc -``` - -## Disable up arrow - -Our default up-arrow binding can be a bit contentious. Some people love it, some people hate it. Many people who found it a bit jarring at first have since come to love it, so give it a try! - -It becomes much more powerful if you consider binding a different filter mode to the up arrow. For example, on "up" Atuin can default to searching all history for the current directory only, while ctrl-r searches history globally. See the [config](config.md#filter_mode_shell_up_key_binding) for more. - -Otherwise, if you don't like it, it's easy to disable. - -You can also disable either the up-arrow or ++ctrl+r++ bindings individually, by passing -`--disable-up-arrow` or `--disable-ctrl-r` to the call to `atuin init` in your shell config file: - -An example for zsh: -``` -# Bind ctrl-r but not up arrow -eval "$(atuin init zsh --disable-up-arrow)" - -# Bind up-arrow but not ctrl-r -eval "$(atuin init zsh --disable-ctrl-r)" -``` - -If you do not want either key to be bound, either pass both `--disable` arguments, or set the -environment variable `ATUIN_NOBIND` to any value before the call to `atuin init`: - -``` -## Do not bind any keys -# Either: -eval "$(atuin init zsh --disable-up-arrow --disable-ctrl-r)" - -# Or: -export ATUIN_NOBIND="true" -eval "$(atuin init zsh)" -``` - -You can then choose to bind Atuin if needed, do this after the call to init. - -## Enter key behavior - -By default, the `enter` key will directly execute the selected command instead of letting you edit it like the `tab` key. If you want to change this behavior, set `enter_accept = false` in your config. For more details: [enter_accept](config.md#enter_accept). - -## Ctrl-n key shortcuts - -macOS does not have an ++alt++ key, although terminal emulators can often be configured to map the ++option++ key to be used as ++alt++. *However*, remapping ++option++ this way may prevent typing some characters, such as using ++option+3++ to type `#` on the British English layout. For such a scenario, set the `ctrl_n_shortcuts` option to `true` in your config file to replace ++alt+0++ to ++alt+9++ shortcuts with ++ctrl+0++ to ++ctrl+9++ instead: - -``` -# Use Ctrl-0 .. Ctrl-9 instead of Alt-0 .. Alt-9 UI shortcuts -ctrl_n_shortcuts = true -``` - -Ghostty on Linux maps ++alt+1++ .. ++alt+9++ for switching between tabs by number. To disable this behavior either add the following to ~/.config/ghostty/config: -``` -keybind=alt+one=unbind -keybind=alt+two=unbind -keybind=alt+three=unbind -keybind=alt+four=unbind -keybind=alt+five=unbind -keybind=alt+six=unbind -keybind=alt+seven=unbind -keybind=alt+eight=unbind -keybind=alt+nine=unbind -``` -(this will disable tab switching by ++alt+n++) -or use the `ctrl_n_shortcuts` as outlined above. - -## zsh - -If you'd like to customize your bindings further, it's possible to do so with custom shell config: - -Atuin defines the ZLE widgets "atuin-search" and "atuin-up-search". The latter -can be used for the keybindings to the ++up++ key and similar keys. - -Note: instead use the widget names "\_atuin\_search\_widget" and "\_atuin\_up\_search\_widget", respectively, in `atuin < 18.0` - -``` -export ATUIN_NOBIND="true" -eval "$(atuin init zsh)" - -bindkey '^r' atuin-search - -# bind to the up key, which depends on terminal mode -bindkey '^[[A' atuin-up-search -bindkey '^[OA' atuin-up-search -``` - -For the keybindings in vi mode, "atuin-search-viins", "atuin-search-vicmd", -"atuin-up-search-viins", and "atuin-up-search-vicmd" (`atuin >= 18.0`) can be -used in combination with the config -["keymap\_mode"](config.md#keymap_mode) -(`atuin >= 18.0`) to start the Atuin search in respective keymap modes. - -## bash - -Atuin (`>= 18.10.0`) provides a shell function `atuin-bind` to set up -keybindings easily: - -``` -atuin-bind [-m KEYMAP] KEYSEQ COMMAND -``` - -`KEYMAP` is one of `emacs`, `vi-insert`, and `vi-command` and specifies the -target keymap where the keybinding is defined. `KEYSEQ` specifies a key -sequence in the format used in `bind '"KEYSEQ": ...'`. `COMMAND` specifies a -shell command to run with the keybindings. The following special commands can -be used as well as an arbitrary shell command: - -| Command | Description | -| ----------------------- | ----------------------------------------------------------------------------------- | -| `atuin-search` | Standard search | -| `atuin-search-emacs` | Standard search with the `emacs` keymap mode | -| `atuin-search-viins` | Standard search with the `vim-insert` keymap mode | -| `atuin-search-vicmd` | Standard search with the `vim-normal` keymap mode | -| `atuin-up-search` | Search command for <kbd>up</kbd> or similar keys | -| `atuin-up-search-emacs` | Search command for <kbd>up</kbd> or similar keys, with the `emacs` keymap mode | -| `atuin-up-search-viins` | Search command for <kbd>up</kbd> or similar keys, with the `vim-insert` keymap mode | -| `atuin-up-search-vicmd` | Search command for <kbd>up</kbd> or similar keys, with the `vim-nomarl` keymap mode | - -The keymap mode controls the initial keymap in the Atuin search and is -determined in combination with the config -["keymap\_mode"](config.md#keymap_mode) -(`atuin >= 18.0`). - - -``` -export ATUIN_NOBIND="true" -eval "$(atuin init bash)" - -# bind to ctrl-r, add any other bindings you want here too -atuin-bind '\C-r' atuin-search -# example of CTRL-upkey -# atuin-bind '\e[1;5A' atuin-search - -# bind to the up key, which depends on terminal mode -atuin-bind '\e[A' atuin-up-search -atuin-bind '\eOA' atuin-up-search -``` - -With older versions of Atuin, the user needs to bind a bindable shell function -"`__atuin_history`" directly using Bash's `bind`. The flag -`--shell-up-key-binding` can be optionally specified to the first argument for -keybindings to the <kbd>up</kbd> key or similar keys. For the keybindings in -the `vi` editing mode, the options `--keymap-mode=vim-insert` and the keymap -mode `--keymap-mode=vim-normal` (`atuin >= 18.0`) can be additionally specified -to the shell function `__atuin_history`. - -## fish -Edit key bindings in FISH shell by adding the following to ~/.config/fish/config.fish - -``` -set -gx ATUIN_NOBIND "true" -atuin init fish | source - -# bind to ctrl-r in normal and insert mode, add any other bindings you want here too -bind \cr _atuin_search -bind -M insert \cr _atuin_search -``` - -For the ++up++ keybinding, `_atuin_bind_up` can be used instead of `_atuin_search`. - -Adding the useful alternative key binding of ++ctrl+up++ is tricky and determined by the terminals adherence to terminfo(5). - -Conveniently FISH uses a command to capture keystrokes and advises you of the exact command to add for your specific terminal. -In your terminal, run `fish_key_reader` then punch the desired keystroke/s. - -For example, in Gnome Terminal the output to ++ctrl+up++ is `bind \e\[1\;5A 'do something'` - -So, adding this to the above sample, `bind \e\[1\;5A _atuin_search` will provide the additional search keybinding. - -## nu - -``` -$env.ATUIN_NOBIND = true -atuin init nu | save -f ~/.local/share/atuin/init.nu #make sure you created the directory beforehand with `mkdir ~/.local/share/atuin/init.nu` -source ~/.local/share/atuin/init.nu - -#bind to ctrl-r in emacs, vi_normal and vi_insert modes, add any other bindings you want here too -$env.config = ( - $env.config | upsert keybindings ( - $env.config.keybindings - | append { - name: atuin - modifier: control - keycode: char_r - mode: [emacs, vi_normal, vi_insert] - event: { send: executehostcommand cmd: (_atuin_search_cmd) } - } - ) -) -``` - - -## Atuin UI shortcuts - -| Shortcut | Action | -|-------------------------------------------|-------------------------------------------------------------------------------| -| enter | Execute selected item | -| tab | Select item and edit | -| ctrl + r | Cycle through filter modes | -| ctrl + s | Cycle through search modes | -| alt + 1 to alt + 9 | Select item by the number located near it | -| ctrl + c / ctrl + d / ctrl + g / esc | Return original | -| ctrl + y | Copy selected item to clipboard | -| ctrl + ← / alt + b | Move the cursor to the previous word | -| ctrl + → / alt + f | Move the cursor to the next word | -| ctrl + b / ← | Move the cursor to the left | -| ctrl + f / → | Move the cursor to the right | -| ctrl + a / home | Move the cursor to the start of the line | -| ctrl + e / end | Move the cursor to the end of the line | -| ctrl + backspace / ctrl + alt + backspace | Remove the previous word / remove the word just before the cursor | -| ctrl + delete / ctrl + alt + delete | Remove the next word or the word just after the cursor | -| ctrl + w | Remove the word before the cursor even if it spans across the word boundaries | -| ctrl + u | Clear the current line | -| ctrl + n / ctrl + j / ↑ | Select the next item on the list | -| ctrl + p / ctrl + k / ↓ | Select the previous item on the list | -| ctrl + o | Open the [inspector](#inspector) | -| page down | Scroll search results one page down | -| page up | Scroll search results one page up | -| ↓ (with no entry selected) | Return original or return query depending on [settings](config.md#exit_mode) | -| ↓ | Select the next item on the list | -| ctrl + a, d | Delete the selected history entry | -| ctrl + a, D | Delete **all** history entries matching the selected command | -| ctrl + a, a | Move cursor to the start of the line | -| ctrl + a, c | Switch to the context of the currently selected command / return to default | - -### Prefix mode - -The shortcuts above that start with ++ctrl+a++ use **prefix mode** — a two-step key combination. Pressing the prefix key (++ctrl+a++ by default) enters prefix mode, then the next key you press triggers the action. Prefix mode exits automatically after the action runs. - -This is useful for less-frequent actions that don't need a dedicated shortcut. The prefix key can be changed with the [`prefix`](config.md#prefix) setting, and the bindings themselves can be customized with [`[keymap.prefix]`](advanced-key-binding.md#custom-prefix-bindings). - -### Vim mode -If [vim is enabled in the config](config.md#keymap_mode), the following keybindings are enabled: - -| Shortcut | Mode | Action | -| -------- | ------ | ------------------------------------------ | -| k | Normal | Selects the next item on the list | -| j | Normal | Selects the previous item on the list | -| h | Normal | Move cursor left | -| l | Normal | Move cursor right | -| 0 | Normal | Move cursor to start of line | -| $ | Normal | Move cursor to end of line | -| w | Normal | Move cursor to next word | -| b | Normal | Move cursor to previous word | -| e | Normal | Move cursor to end of current/next word | -| x | Normal | Delete character under cursor | -| dd | Normal | Clear the entire line | -| D | Normal | Delete to end of line | -| C | Normal | Delete to end of line and enter insert | -| i | Normal | Enters insert mode | -| I | Normal | Move to start of line and enter insert | -| a | Normal | Move right and enter insert mode | -| A | Normal | Move to end of line and enter insert | -| Ctrl+u | Normal | Half-page up (toward visual top) | -| Ctrl+d | Normal | Half-page down (toward visual bottom) | -| Ctrl+b | Normal | Full-page up (toward visual top) | -| Ctrl+f | Normal | Full-page down (toward visual bottom) | -| G | Normal | Jump to visual bottom of history | -| gg | Normal | Jump to visual top of history | -| H | Normal | Jump to top of visible screen | -| M | Normal | Jump to middle of visible screen | -| L | Normal | Jump to bottom of visible screen | -| ? or / | Normal | Clear input and enter insert mode | -| 1-9 | Normal | Select item by number | -| enter | Normal | Execute selected item (respects enter_accept) | -| Esc | Insert | Enters normal mode | - - -### Inspector -Open the inspector with ctrl + o - -| Shortcut | Action | -| --------- | --------------------------------------------- | -| Esc | Close the inspector, returning to the shell | -| ctrl + o | Close the inspector, returning to search view | -| ctrl + d | Delete the inspected item from the history | -| ↑ | Inspect the previous item in the history | -| ↓ | Inspect the next item in the history | -| page up | Inspect the previous item in the history | -| page down | Inspect the next item in the history | -| j / k | Navigate items (when vim mode is enabled) | -| enter | Execute selected item (respects enter_accept) | -| tab | Select current item and edit | diff --git a/docs/docs/faq.md b/docs/docs/faq.md deleted file mode 100644 index c247a982..00000000 --- a/docs/docs/faq.md +++ /dev/null @@ -1,90 +0,0 @@ -# FAQ - -## Why isn't Atuin recording commands in my IDE's terminal? - -IDEs like PyCharm, VS Code, and others often start non-interactive shells that don't source your shell configuration. This means Atuin's hooks never get installed. - -To fix this, configure your IDE to start an interactive shell (e.g., `/bin/bash -i` instead of `/bin/bash`). - -See [Shell Integration and Interoperability](guide/shell-integration.md) for detailed instructions. - -## How do I exclude certain commands from my history? - -Use the `history_filter` option in `~/.config/atuin/config.toml`: - -```toml -history_filter = [ - "^secret-cmd", - "^ls$", -] -``` - -You can also exclude commands by directory with `cwd_filter`, or prefix individual commands with a space. - -See [Shell Integration and Interoperability](guide/shell-integration.md#excluding-commands-from-history) for more options. - -## How do I remove the default up arrow binding? - -Open your shell config file, find the line containing `atuin init`. - -Add `--disable-up-arrow` - -EG: - -``` -eval "$(atuin init zsh --disable-up-arrow)" -``` - -See [key binding](../configuration/key-binding.md) for more - -## How do I remove the default question mark binding for Atuin AI? - -Open your shell config file, find the line containing `atuin init`. - -Add `--disable-ai` - -EG: - -``` -eval "$(atuin init zsh --disable-ai)" -``` - -## How do I edit a command instead of running it immediately? - -Press tab! By default, enter will execute a command, and tab will insert it ready for editing. - -You can make `enter` edit a command by putting `enter_accept = false` into your config file (~/.config/atuin/config.toml) - -## How do I delete my account? - -**Attention:** This command does not prompt for confirmation. - -``` -atuin account delete -``` - -This will delete your account, and all history from the remote server. It will not delete your local data. - -## I've forgotten my password! How can I reset it? - -We don't currently have a password reset system. So long as you're still logged -in on at least one machine, it's safe to delete and re-create your account. - -## I did not set up sync, and now I have to reinstall my system! - -If you have a backup of `~/.local/share/atuin`, you can import it by: -1. disabling atuin by commenting out the shell integration, e.g. for bash it's `eval "$(atuin init bash)"` -2. copying the backup to `~/.local/share/atuin` -3. reenabling atuin -4. setting up sync! - -## Alternative projects - -If you don't like atuin, perhaps one of these works better for you: - -- https://github.com/ddworken/hishtory - - written in go - - also provides sync'ed history -- https://github.com/cantino/mcfly - - uses a small local neural network for search - - only local history diff --git a/docs/docs/guide/advanced-usage.md b/docs/docs/guide/advanced-usage.md deleted file mode 100644 index 0d5a1359..00000000 --- a/docs/docs/guide/advanced-usage.md +++ /dev/null @@ -1,49 +0,0 @@ -# Advanced Usage - -Atuin offers you several options to help navigate through the results. - -## Filter mode - -The command history can be filtered in different ways, letting you narrow the search scope. - -You can cycle through the different modes by pressing **ctrl-r**. - -The available modes are: - -| Mode | Description | -|------------------|--------------------------------------------------------------------------------------| -| global (default) | Search from the full history | -| host | Search history from this host | -| session | Search history from the current session | -| directory | Search history from the current directory | -| workspace | Search history from the current git repository | -| session-preload | Search from the current session and the global history from before the session start | - -See the [`filter_mode` config reference](../configuration/config.md#filter_mode) for more details. - -## Search mode - -Atuin offers different modes to interpret your search query. - -You can cycle through the different modes by pressing **ctrl-s**. - -The available modes are: - -| Mode | Description | -|-----------------|----------------------------------------------------------------------------------------------------------------| -| fuzzy (default) | Search for commands in a fuzzy way, similar to the [fzf syntax](https://github.com/junegunn/fzf#search-syntax) | -| prefix | Commands that start with your query | -| fulltext | Commands that contain your query as a substring | -| skim | Search for commands using the [skim syntax](https://github.com/lotabout/skim#search-syntax) | - -See the [`search_mode` config reference](../configuration/config.md#search_mode) for more details. - -## Context switch - -Atuin uses the current context (host, session, directory) to filter the history when you use a filter mode other than *global*. - -You can switch this context to the one of the currently selected command by pressing **ctrl-a** then **c**. - -This will set the filter mode to *session* and clear the search query, which will show you all the commands executed in the same shell session. - -Pressing this key combination again will return to the initial context. You can customize this behavior by setting [custom key bindings](../configuration/advanced-key-binding.md) to the `switch-context` and `clear-context` commands. `switch-context` can be called several times to navigate through multiple command contexts, while `clear-context` will always return to the initial context. diff --git a/docs/docs/guide/agent-hooks.md b/docs/docs/guide/agent-hooks.md deleted file mode 100644 index 0801e819..00000000 --- a/docs/docs/guide/agent-hooks.md +++ /dev/null @@ -1,138 +0,0 @@ -# AI Agent Hooks - -Atuin can capture commands run by AI coding agents (like Claude Code, Codex, and pi) alongside your regular shell history. Each command is tagged with the agent that ran it, so you can filter your history by author. - -## Quick Start - -Install hooks for your agent, then restart or reload the agent: - -```shell -# Claude Code -atuin hook install claude-code - -# Codex -atuin hook install codex - -# pi -atuin hook install pi -``` - -That's it. Commands the agent runs will now appear in your Atuin history, tagged with the agent's name. - -## How It Works - -AI coding agents support hook systems that notify external tools when they're about to run a shell command and when the command finishes. Atuin uses these hooks to record each command as a history entry, just like commands you type yourself. - -When `atuin hook install` runs, it writes the agent's config file or extension to register Atuin as a hook handler: - -| Agent | Config file / extension | -|-------|-------------------------| -| Claude Code | `~/.claude/settings.json` | -| Codex | `~/.codex/hooks.json` | -| pi | `~/.pi/agent/extensions/atuin.ts` | - -The hook lifecycle: - -1. **PreToolUse** -- the agent is about to run a Bash command. Atuin records the command, working directory, and timestamp (same as `history start`). -2. **PostToolUse / PostToolUseFailure** -- the command finished. Atuin records the exit code and duration (same as `history end`). - -Only `Bash` tool invocations are captured. Other tool types (file writes, web fetches, etc.) are ignored. - -## Filtering by Author - -By default, Atuin's interactive search shows only your own commands. Agent-run commands are hidden so they don't clutter your history. - -Today this default is built into the search UI rather than configurable via `config.toml`. Interactive search uses the equivalent of: - -- `$all-user` — any author that is **not** a known AI agent - -For explicit author filtering, use the CLI `atuin search --author ...` flag. Special values: - -| Value | Meaning | -|-------|---------| -| `$all-user` | Any author that is **not** a known AI agent | -| `$all-agent` | Any known AI agent author | - -You can also use literal author names: - -```shell -# Show only your own commands and Claude Code commands -atuin search --author '$all-user' --author 'claude-code' -- '' -``` - -```shell -# Show everything (no filtering) -atuin search -- '' -``` - -```shell -# Show only agent commands -atuin search --author '$all-agent' -- '' -``` - -Currently recognized agent names are: `claude-code`, `codex`, `copilot`, and `pi`. - -## Supported Agents - -### Claude Code - -```shell -atuin hook install claude-code -``` - -This adds hook entries to `~/.claude/settings.json`. Claude Code calls `atuin hook claude-code` on each `Bash` tool use, passing the event as JSON on stdin. - -### Codex - -```shell -atuin hook install codex -``` - -This adds hook entries to `~/.codex/hooks.json`. Codex calls `atuin hook codex` on each Bash tool use matching `^Bash$`. - -### pi - -```shell -atuin hook install pi -``` - -This writes Atuin's extension to `~/.pi/agent/extensions/atuin.ts`. - -Then restart pi or run `/reload`. The extension wraps pi's built-in `bash` tool and records every bash command with author `pi` by calling `atuin history start` before execution and `atuin history end` afterwards. - -## Verifying Installation - -After installing hooks and restarting your agent, run a command through the agent and then check your history: - -```shell -# Show all history including agent commands -atuin search --authors '' -- '' - -# Show only agent commands -atuin search --authors '$all-agent' -- '' -``` - -You can also check the agent's config file directly to confirm the hooks are registered: - -```shell -# Claude Code -cat ~/.claude/settings.json | grep atuin - -# Codex -cat ~/.codex/hooks.json | grep atuin - -# pi -ls ~/.pi/agent/extensions/atuin.ts -``` - -## Re-installing - -Running `atuin hook install` again is safe. If hooks are already installed, the command will skip them and print a message: - -``` -hooks.PreToolUse: already installed, skipping -hooks.PostToolUse: already installed, skipping -hooks.PostToolUseFailure: already installed, skipping -``` - -For pi, reinstalling will also skip if the managed extension already matches the bundled version. diff --git a/docs/docs/guide/basic-usage.md b/docs/docs/guide/basic-usage.md deleted file mode 100644 index 09cf67e0..00000000 --- a/docs/docs/guide/basic-usage.md +++ /dev/null @@ -1,65 +0,0 @@ -# Basic Usage - -Now that you're all set up and running, here's a quick walkthrough of how you can use Atuin best. - -## What does Atuin record? - -While you work, Atuin records: - -1. The command you run -2. The directory you ran it in -3. The time you ran it, and how long it took to run -4. The exit code of the command -5. The hostname + user of the machine -6. The shell session you ran it in - -## Opening and using the TUI - -At any time, you can open the TUI with the default keybindings of the up arrow, or `ctrl-r`. - -Once in the TUI, press enter to immediately execute a command, or press tab to insert it into your shell for editing. - -While searching in the TUI, you can adjust the "filter mode" by repeatedly pressing `ctrl-r`. Atuin can filter by: - -1. All hosts -2. Just your local machine -3. The current directory only -4. The current shell session only - -See the [advanced usage](advanced-usage.md) page for more options. - -## Common config adjustment - -For a full set of config values, please see the [config reference page](../configuration/config.md). - -The default configuration file is located at `~/.config/atuin/config.toml`. - -### Keybindings - -We have a [full page dedicated to keybinding adjustments](../configuration/key-binding.md). -There are a whole bunch of options there, including disabling the up arrow behavior if you don't like it. - -### Enter to run - -You may prefer that Atuin always inserts the selected command for editing. To configure this, set - -``` -enter_accept = false -``` - -in your config file. - -### Inline window - -If you find the full screen TUI overwhelming or too large, you can adjust it like so: - -``` -# height of the search window -inline_height = 40 -``` - -You may also prefer the compact UI mode: - -``` -style = "compact" -``` diff --git a/docs/docs/guide/delete-history.md b/docs/docs/guide/delete-history.md deleted file mode 100644 index 6d0022e1..00000000 --- a/docs/docs/guide/delete-history.md +++ /dev/null @@ -1,146 +0,0 @@ -# Deleting History - -Atuin provides several ways to delete history, whether you want to remove a single entry, bulk delete by query, clean up duplicates, or wipe everything. - -All deletion methods are local-first. If you have sync enabled, deletions are propagated to other machines automatically. - -## Deleting a single entry - -The quickest way to delete a single entry is via the interactive TUI. - -### Using the inspector - -1. Open the TUI with ++ctrl+r++ or the up arrow -2. Search for the entry you want to delete -3. Press ++ctrl+o++ to open the inspector on the selected entry -4. Verify this is the correct entry -5. Press ++ctrl+d++ to delete it - -### Using the prefix shortcut - -1. Open the TUI with ++ctrl+r++ or the up arrow -2. Navigate to the entry you want to delete -3. Press ++ctrl+a++ then ++d++ to delete the selected entry - -Both methods remove the entry immediately with no further confirmation. - -## Deleting entries matching a query - -Use `atuin search --delete` to delete all entries matching a search query. This uses the same query syntax as regular search, so you can preview what will be deleted before committing. - -### Preview first, then delete - -Always run your query without `--delete` first to verify the results: - -``` -# Step 1: preview - see what matches -atuin search "^curl https://internal" - -# Step 2: delete - once you're satisfied the results are correct -atuin search --delete "^curl https://internal" -``` - -### Combining filters - -You can combine `--delete` with any search filter: - -``` -# Delete all failed commands run from a specific directory -atuin search --delete --exit 1 --cwd /home/user/experiments - -# Delete commands matching a pattern that ran before a certain date -atuin search --delete --before "2024-01-01" "^tmp-script" - -# Delete successful cargo commands run after yesterday at 3pm -atuin search --delete --exit 0 --after "yesterday 3pm" cargo -``` - -!!! warning - `--delete` requires a query or filter. It will not run without one. This is intentional to prevent accidental bulk deletion. - -## Deleting all history - -If you want to wipe your entire local history: - -``` -atuin search --delete-it-all -``` - -!!! danger - This deletes every entry in your local history database. It cannot be combined with a query or filters. This action is irreversible. - -### Starting fresh with sync - -If you use sync and want to start completely fresh, `--delete-it-all` alone is not enough. Atuin sync works by recording every action (including deletions) as encrypted records. Deleting 100,000 entries locally creates 100,000 delete records that still need to sync. When your other machines pull those records, they process every single one, and your database still contains the overhead of all that history. - -The cleaner approach is to delete your sync account and start over: - -``` -# Delete your sync account and all server-side data -atuin account delete - -# Register a new account -atuin register - -# Import your shell history fresh (optional) -atuin import auto -``` - -This gives you a clean slate on the server with no leftover records. Your other machines can then register with the new account and start fresh too. - -!!! tip - If you only want to delete specific entries and keep the rest, `atuin search --delete` is the right tool. The account reset approach is only better when you want to wipe everything and start over. - -## Pruning filtered commands - -If you've updated your [`history_filter`](../configuration/config.md#history_filter) config and want to retroactively remove entries that match the new filters: - -``` -# Preview what will be removed -atuin history prune --dry-run - -# Perform the deletion -atuin history prune -``` - -This is useful when you add a new pattern to `history_filter` - future commands matching the filter are never recorded, but old entries that were recorded before the filter was set up remain. `prune` cleans those up. - -## Deduplicating history - -Remove duplicate entries (same command, working directory, and hostname): - -``` -# Preview duplicates that would be removed -atuin history dedup --dry-run --before "2025-01-01" --dupkeep 1 - -# Delete them -atuin history dedup --before "2025-01-01" --dupkeep 1 -``` - -| Flag | Description | -|------|-------------| -| `--dry-run`/`-n` | List duplicates without deleting | -| `--before`/`-b` | Only consider entries added before this date (required) | -| `--dupkeep` | Number of recent duplicates to keep | - -## Deleting your sync account - -To delete your remote sync account and all server-side history: - -``` -atuin account delete -``` - -This removes your account and all synchronized history from the server. **Local history is not affected.** See the [sync reference](../reference/sync.md) for more details. - -## Summary - -| Goal | Command | -|------|---------| -| Delete one entry (TUI) | ++ctrl+o++ then ++ctrl+d++, or ++ctrl+a++ then ++d++ | -| Delete entries by query | `atuin search --delete <query>` | -| Delete all history | `atuin search --delete-it-all` | -| Start fresh (with sync) | `atuin account delete` then re-register | -| Remove filtered entries | `atuin history prune` | -| Remove duplicates | `atuin history dedup --before <date> --dupkeep <n>` | -| Delete sync account | `atuin account delete` | diff --git a/docs/docs/guide/dotfiles.md b/docs/docs/guide/dotfiles.md deleted file mode 100644 index d4157cb7..00000000 --- a/docs/docs/guide/dotfiles.md +++ /dev/null @@ -1,141 +0,0 @@ -# Syncing dotfiles - -While Atuin started as a tool for syncing and searching shell history, we are -building tooling for syncing dotfiles across machines, and making them easier -to work with. - -At the moment, we support managing and syncing of shell aliases and environment variables - with more -coming soon. - -The following shells are supported: - -- zsh -- bash -- fish -- xonsh -- powershell - -Note: Atuin handles your configuration internally, so once it is installed you -no longer need to edit your config files manually. - -## Required config - -Once Atuin is set up and installed, the following is required in your config file (`~/.config/atuin/config.toml`) - -``` -[dotfiles] -enabled = true -``` - -In a later release, this will be enabled by default. - -Note: If you have not yet set up sync v2, please also add - -``` -[sync] -records = true -``` - -to the same config file. - -## Usage - -### Aliases - -After creating or deleting an alias, remember to restart your shell! - -#### Creating an alias - -``` -atuin dotfiles alias set NAME 'COMMAND' -``` - -For example, to alias `k` to be `kubectl` - - -``` -atuin dotfiles alias set k 'kubectl' -``` - -or to alias `ll` to be `ls -lah` - -``` -atuin dotfiles alias set ll 'ls -lah' -``` - -#### Deleting an alias - -Deleting an alias is as simple as: - -``` -atuin dotfiles alias delete NAME -``` - -For example, to delete the above alias `k`: - -``` -atuin dotfiles alias delete k -``` - -#### Listing aliases - -You can list all aliases with: - -``` -atuin dotfiles alias list -``` - -### Env vars - -After creating or deleting an env var, remember to restart your shell! - -#### Creating a var - -``` -atuin dotfiles var set NAME 'value' -``` - -For example, to set `FOO` to be `bar` - - -``` -atuin dotfiles var set FOO 'bar' -``` - -Vars are exported by default, but you can create a shell var like so - -``` -atuin dotfiles var set -n foo 'bar' -``` - - -#### Deleting a var - -Deleting a var is as simple as: - -``` -atuin dotfiles var delete NAME -``` - -For example, to delete the above var `FOO`: - -``` -atuin dotfiles var delete FOO -``` - -#### Listing vars - -You can list all vars with: - -``` -atuin dotfiles var list -``` - -### Syncing and backing up dotfiles -If you have [set up sync](sync.md), then running - -``` -atuin sync -``` - -will back up your config to the server and sync it across machines. diff --git a/docs/docs/guide/getting-started.md b/docs/docs/guide/getting-started.md deleted file mode 100644 index 85140b25..00000000 --- a/docs/docs/guide/getting-started.md +++ /dev/null @@ -1,54 +0,0 @@ -# Getting Started - -Atuin replaces your existing shell history with a SQLite database, and records -additional context for your commands. With this context, Atuin gives you faster -and better search of your shell history. - -Additionally, Atuin (optionally) syncs your shell history between all of your -machines. Fully end-to-end encrypted, of course. - -You may use either the server I host, or host your own! Or just don't use sync -at all. As all history sync is encrypted, I couldn't access your data even if I -wanted to. And I **really** don't want to. - -If you have any problems, please open an [issue](https://github.com/ellie/atuin/issues) or get in touch on our [Discord](https://discord.gg/Fq8bJSKPHh)! - -## Supported Shells - -- zsh -- bash -- fish -- nushell -- xonsh -- powershell (tier 2 support) - -## Quickstart - -Please do try and read this guide, but if you're in a hurry and want to get -started quickly: - -``` -bash <(curl --proto '=https' --tlsv1.2 -sSf https://setup.atuin.sh) - -atuin register -u <USERNAME> -e <EMAIL> -atuin import auto -atuin sync -``` - -Now restart your shell! - -Anytime you press ctrl-r or up, you will see the Atuin search UI. Type your -query, enter to execute. If you'd like to select a command without executing -it, press tab. - -You might like to configure an [inline window](../configuration/config.md#inline_height), or [disable up arrow bindings](../configuration/key-binding.md#disable-up-arrow) - -Note: The above sync and registration is fully optional. If you'd like to use Atuin offline, you can run - -``` -bash <(curl --proto '=https' --tlsv1.2 -sSf https://setup.atuin.sh) - -atuin import auto -``` - -Your shell history will be local only, not backed up, and not synchronized across devices. diff --git a/docs/docs/guide/import.md b/docs/docs/guide/import.md deleted file mode 100644 index 3e19b26c..00000000 --- a/docs/docs/guide/import.md +++ /dev/null @@ -1,18 +0,0 @@ -# Import existing history - -Atuin uses a shell plugin to ensure that we capture new shell history. But for -older history, you will need to import it - -This will import the history for your current shell: -``` -atuin import auto -``` - -Alternatively, you can specify the shell like so: - -``` -atuin import bash -atuin import zsh # etc -``` - -Your old shell history file will continue to be updated, regardless of Atuin usage. diff --git a/docs/docs/guide/installation.md b/docs/docs/guide/installation.md deleted file mode 100644 index 7fe69130..00000000 --- a/docs/docs/guide/installation.md +++ /dev/null @@ -1,308 +0,0 @@ -# Installation - -## Recommended installation approach - -### On Unix - -Let's get started! First up, you will want to install Atuin. The recommended -approach is to use the installation script, which automatically handles the -installation of Atuin including the requirements for your environment. - - -It will install a binary to `~/.atuin/bin`, and if you'd rather do something else -then the manual steps below offer much more flexibility. - -```shell -curl --proto '=https' --tlsv1.2 -LsSf https://setup.atuin.sh | sh -``` - -The install script will walk you through importing your shell history and setting -up a sync account. To skip these interactive prompts (e.g. in CI or -Dockerfiles), pass `--non-interactive`: - -```shell -curl --proto '=https' --tlsv1.2 -LsSf https://setup.atuin.sh | sh -s -- --non-interactive -``` - -The script also automatically detects non-interactive environments (piped input, -no TTY) and skips the prompts in those cases. - -[**Set up sync** - Move on to the next step, or read on to manually install Atuin instead.](sync.md) - -### On Windows - -The recommended approach on Windows is to use WinGet to install Atuin. Then, if you use PowerShell, -add the initialization command to your PowerShell profile, and restart your shell. - -```shell -winget install -e Atuinsh.Atuin -if (-not (Test-Path -Path $PROFILE)) { New-Item -ItemType File -Path $PROFILE -Force | Out-Null } -Write-Output 'atuin init powershell | Out-String | Invoke-Expression' >> $PROFILE -``` - -Note that the `$PROFILE` path may depend on your PowerShell version. - -[**Set up sync** - Move on to the next step.](sync.md) - -## Manual installation - -### Installing the binary - -If you don't wish to use the installer, the manual installation steps are as follows. - -=== "Cargo" - - It's best to use [rustup](https://rustup.rs/) to set up a Rust - toolchain, then you can run: - - ```shell - cargo install atuin - ``` - -=== "Homebrew" - - ```shell - brew install atuin - ``` - -=== "MacPorts" - - Atuin is also available in [MacPorts](https://ports.macports.org/port/atuin/) - - ```shell - sudo port install atuin - ``` - -=== "mise" - - Atuin is also installable using [mise](https://github.com/jdx/mise) - - ```shell - mise use -g atuin@latest - ``` - -=== "Nix" - - This repository is a flake, and can be installed using `nix profile`: - - ```shell - nix profile install "github:atuinsh/atuin" - ``` - - Atuin is also available in [nixpkgs](https://github.com/NixOS/nixpkgs): - - ```shell - nix-env -f '<nixpkgs>' -iA atuin - ``` - -=== "Pacman" - - Atuin is available in the Arch Linux [extra repository](https://archlinux.org/packages/extra/x86_64/atuin/): - - ```shell - pacman -S atuin - ``` - -=== "XBPS" - - Atuin is available in the Void Linux [repository](https://github.com/void-linux/void-packages/tree/master/srcpkgs/atuin): - - ```shell - sudo xbps-install atuin - ``` - -=== "Termux" - - Atuin is available in the Termux package repository: - - ```shell - pkg install atuin - ``` - -=== "zinit" - - Atuin is installable from github-releases directly: - - ```shell - # line 1: `atuin` binary as command, from github release, only look at .tar.gz files, use the `atuin` file from the extracted archive - # line 2: setup at clone(create init.zsh, completion) - # line 3: pull behavior same as clone, source init.zsh - zinit ice as"command" from"gh-r" bpick"atuin-*.tar.gz" mv"atuin*/atuin -> atuin" \ - atclone"./atuin init zsh > init.zsh; ./atuin gen-completions --shell zsh > _atuin" \ - atpull"%atclone" src"init.zsh" - zinit light atuinsh/atuin - ``` - -=== "WinGet" - - Atuin is available on WinGet: - - ```shell - winget install -e Atuinsh.Atuin - ``` - -=== "Source" - - Atuin builds on the latest stable version of Rust, and we make no - promises regarding older versions. We recommend using [rustup](https://rustup.rs/). - - ```shell - git clone https://github.com/atuinsh/atuin.git - cd atuin/crates/atuin - cargo install --path . - ``` - -!!! warning "Please be advised" - - If you choose to manually install Atuin rather than using the recommended installation script, - merely installing the binary is not sufficient, you should also set up the shell plugin. - ---- - -### Installing the shell plugin - -Once the binary is installed, the shell plugin requires installing. -If you use the install script, this should all be done for you! -After installing, remember to restart your shell. - -=== "zsh" - - ```shell - echo 'eval "$(atuin init zsh)"' >> ~/.zshrc - ``` - - === "zinit" - - ```shell - # if you _only_ want to install the shell-plugin, do this; otherwise look above for a "everything via zinit" solution - zinit load atuinsh/atuin - ``` - - === "Antigen" - - ```shell - antigen bundle atuinsh/atuin@main - ``` - - === "Antidote" - - ```shell - antidote install atuinsh/atuin - ``` - -=== "bash" - - === "ble.sh" - - Atuin works best in bash when using [ble.sh](https://github.com/akinomyoga/ble.sh) >= 0.4. - - With ble.sh (>= 0.4) installed and loaded in `~/.bashrc`, just add atuin to your `~/.bashrc` - - ```shell - echo 'eval "$(atuin init bash)"' >> ~/.bashrc - ``` - - === "bash-preexec" - - [Bash-preexec](https://github.com/rcaloras/bash-preexec) can also be used, but you may experience - some minor problems with the recorded duration and exit status of some commands. - - !!! warning "Please note" - - bash-preexec currently has an issue where it will stop honoring `ignorespace`. - While Atuin will ignore commands prefixed with whitespace, they may still end up in your bash history. - Please check your configuration! All other shells do not have this issue. - - To use `atuin < 18.10.0` in `bash < 4` with bash-preexec, the option - `enter_accept` needs to be turned on (which is so by default). There is no - restriction in the latest version of Atuin (>= 18.10.0). - - bash-preexec cannot properly invoke the `preexec` hook for subshell commands - `(...)`, function definitions `func() { ...; }`, empty for-in-statements `for - i in; do ...; done`, etc., so those commands and duration may not be recorded - in the Atuin's history correctly. - - To use bash-preexec, download and initialize it - - ```shell - curl https://raw.githubusercontent.com/rcaloras/bash-preexec/master/bash-preexec.sh -o ~/.bash-preexec.sh - echo '[[ -f ~/.bash-preexec.sh ]] && source ~/.bash-preexec.sh' >> ~/.bashrc - ``` - - Then set up Atuin - - ```shell - echo 'eval "$(atuin init bash)"' >> ~/.bashrc - ``` - -=== "fish" - - Add - - ```shell - atuin init fish | source - ``` - - to your `is-interactive` block in your `~/.config/fish/config.fish` file - -=== "Nushell" - - Run in *Nushell*: - - ```shell - mkdir ~/.local/share/atuin/ - atuin init nu | save ~/.local/share/atuin/init.nu - ``` - - Add to `config.nu`: - - ```shell - source ~/.local/share/atuin/init.nu - ``` - - ??? tip "Optional: Atuin pty-proxy" - pty-proxy is a lightweight pty proxy that renders the Atuin popup over - your previous output, restoring it when closed — no clearing, no - fullscreen. To use pty-proxy with Nushell, generate the init script: - - ```shell - mkdir ~/.local/share/atuin/ - atuin pty-proxy init nu | save -f ~/.local/share/atuin/pty-proxy-init.nu - ``` - - Then source it as early as possible in your `config.nu`, *before* - the regular atuin init: - - ```shell - source ~/.local/share/atuin/pty-proxy-init.nu - source ~/.local/share/atuin/init.nu - ``` - - Nushell's `source` command requires a static file path, so you must - pre-generate both files. - -=== "xonsh" - - Add - ```shell - execx($(atuin init xonsh)) - ``` - to the end of your `~/.xonshrc` - -=== "PowerShell" - - Add the following to the end of your `$PROFILE` file: - - ```shell - atuin init powershell | Out-String | Invoke-Expression - ``` - -## Upgrade - -Run `atuin update`, and if that command is not available, run the install script again. - -If you used a package manager to install Atuin, then you should also use your package manager to update Atuin. - -## Uninstall - -If you'd like to uninstall Atuin, please check out [the uninstall page](../uninstall.md). diff --git a/docs/docs/guide/shell-integration.md b/docs/docs/guide/shell-integration.md deleted file mode 100644 index cc0d2530..00000000 --- a/docs/docs/guide/shell-integration.md +++ /dev/null @@ -1,263 +0,0 @@ -# Shell Integration and Interoperability - -Atuin uses shell hooks to capture your command history. This page explains how the integration works, why Atuin might not record commands in certain environments, and how to control what gets recorded. - -## How Atuin's Shell Integration Works - -When you add `eval "$(atuin init <shell>)"` to your shell configuration, Atuin installs hooks that run at specific points in your shell's command lifecycle: - -1. **Preexec hook**: Runs *before* each command executes. Atuin records the command text, timestamp, and working directory. -2. **Precmd hook**: Runs *after* each command completes. Atuin records the exit code and duration. - -These hooks only activate under specific conditions: - -- The shell must be **interactive** (started with `-i` or inherently interactive) -- Your shell configuration file must be **sourced** (`.bashrc`, `.zshrc`, etc.) -- The `atuin init` command must run during shell startup - -If any of these conditions aren't met, Atuin's hooks won't be installed, and commands won't be recorded. - -### Environment Variables - -When Atuin initializes, it sets several environment variables: - -| Variable | Purpose | -|----------|---------| -| `ATUIN_SESSION` | Unique identifier for this shell session | -| `ATUIN_SHLVL` | Tracks shell nesting level | -| `ATUIN_HISTORY_ID` | Temporary ID for the currently executing command | -| `ATUIN_HISTORY_AUTHOR` | Optional command author identity (for example `ellie`, `claude`, `copilot`) | -| `ATUIN_HISTORY_INTENT` | Optional command intent/rationale text | - -These variables are used internally to track command execution and associate commands with sessions. -If `ATUIN_HISTORY_AUTHOR` is not set, Atuin defaults to the local shell username. - -## Embedded Terminals and IDE Integrations - -Many development tools include embedded terminals: - -- **IDEs**: PyCharm, IntelliJ, VS Code, Cursor, Zed -- **AI coding assistants**: Claude Code, GitHub Copilot CLI, Aider -- **Container environments**: Docker, Podman, devcontainers - -These tools often spawn shells differently than your regular terminal, which can prevent Atuin from working. - -### Why Atuin Might Not Work - -Embedded terminals commonly: - -1. **Start non-interactive shells**: Many tools run commands via `bash -c "command"` or similar, which doesn't trigger shell configuration -2. **Skip shell configuration**: Some tools explicitly avoid sourcing `.bashrc`/`.zshrc` for performance or isolation -3. **Use different shell paths**: The embedded terminal might use a different shell than your default - -You can verify whether Atuin is active by running: - -```shell -atuin doctor -``` - -Look for the `shell.preexec` field in the output. If it shows `none`, Atuin's hooks aren't installed in that shell session. - -### Enabling Atuin in Embedded Terminals - -If you want Atuin to record commands from an embedded terminal, you'll need to ensure it starts an interactive shell that sources your configuration. - -#### IDE Terminal Settings - -Most IDEs let you customize the shell command used for their integrated terminal: - -**PyCharm / IntelliJ:** - -1. Go to Settings → Tools → Terminal -2. Change "Shell path" to include the `-i` flag: - - Linux/macOS: `/bin/bash -i` or `/bin/zsh -i` - - Or create a wrapper script (see below) - -**VS Code:** - -Add to your `settings.json` (substitute the shells for whatever you use): - -```json -{ - "terminal.integrated.profiles.linux": { - "bash": { - "path": "/bin/bash", - "args": ["-i"] - } - }, - "terminal.integrated.profiles.osx": { - "zsh": { - "path": "/bin/zsh", - "args": ["-i"] - } - } -} -``` - -#### Wrapper Script Approach - -For tools that don't easily support shell arguments, create a wrapper script: - -```shell -#!/bin/bash -# Save as ~/bin/interactive-bash.sh and chmod +x -exec /bin/bash -i "$@" -``` - -Then configure your IDE to use `~/bin/interactive-bash.sh` as the shell path. - -#### Verifying the Fix - -After configuring, open a new terminal in your IDE and run: - -```shell -atuin doctor | grep preexec -``` - -You should see `built-in`, `bash-preexec`, `blesh`, or similar—not `none`. - -## Excluding Commands from History - -Sometimes you *don't* want certain commands in your history. This is common when: - -- AI coding tools run many automated commands (git status, file listings, etc.) -- You're running sensitive commands you don't want synced -- Build tools or scripts generate repetitive command noise - -### Using history_filter - -The `history_filter` option in `~/.config/atuin/config.toml` lets you exclude commands matching specific patterns: - -```toml -history_filter = [ - "^ls$", # Exclude bare 'ls' commands - "^cd ", # Exclude cd commands - "^cat ", # Exclude cat commands -] -``` - -Patterns are regular expressions. They're unanchored by default, so `secret` matches anywhere in a command. Use `^` and `$` for exact matching. - -### Using cwd_filter - -To exclude all commands run from specific directories: - -```toml -cwd_filter = [ - "^/tmp", # Exclude commands run from /tmp - "/node_modules/", # Exclude commands from any node_modules - "^/home/user/scratch", # Exclude a scratch directory -] -``` - -### Prefix with Space (ignorespace) - -Most shells support "ignorespace"—commands prefixed with a space aren't saved to history. Atuin honors this convention: - -```shell - echo "this won't be saved" # Note the leading space -``` - -!!! warning "Bash with bash-preexec" - When using bash-preexec (not ble.sh), there's a known issue where ignorespace isn't fully honored. The command won't appear in Atuin, but may still appear in your bash history. See [installation](installation.md) for details. - -### Disabling Atuin for Specific Tools - -If a tool spawns interactive shells but you don't want its commands recorded, you have several options: - -#### Option 1: Environment Variable Check - -Modify your shell configuration to skip Atuin initialization based on an environment variable: - -```shell -# In .bashrc or .zshrc -if [[ -z "${MY_TOOL_SESSION}" ]]; then - eval "$(atuin init bash)" -fi -``` - -Then configure your tool to set `MY_TOOL_SESSION=1` when spawning shells. - -#### Option 2: Use history_filter for Tool-Specific Patterns - -If the tool runs predictable commands, filter them: - -```toml -history_filter = [ - "^git status$", - "^git diff", - "^ls -la$", -] -``` - -#### Option 3: Filter by Directory - -If the tool operates in specific directories: - -```toml -cwd_filter = [ - "^/path/to/tool/workspace", -] -``` - -### Cleaning Up Existing History - -After adding filters, you can remove matching entries from your existing history: - -```shell -atuin history prune -``` - -This removes entries that match your current `history_filter` or `cwd_filter` patterns. - -## Shell-Specific Notes - -### Bash - -Atuin supports two preexec backends for Bash: - -- **ble.sh** (recommended): Full-featured line editor with accurate timing and proper ignorespace support -- **bash-preexec**: Simpler but has some limitations with subshells and ignorespace - -The shell integration explicitly checks for interactive mode: - -```bash -if [[ $- != *i* ]]; then - # Not interactive, skip initialization - return -fi -``` - -### Zsh - -Zsh has native hook support via `add-zsh-hook`. The integration is straightforward and works reliably in interactive sessions. - -### Fish - -Fish uses its event system (`fish_preexec` and `fish_postexec` events). It also respects Fish's private mode—commands run with `fish --private` aren't recorded. - -## Troubleshooting - -### Commands aren't being recorded - -1. Run `atuin doctor` and check the output -2. Verify `shell.preexec` is not `none` -3. Ensure your shell is interactive (`echo $-` should contain `i`) -4. Check that `atuin init` is in your shell config and being sourced - -### Commands from a specific tool aren't recorded - -1. Check if the tool starts an interactive shell -2. Try configuring the tool to use `bash -i` or `zsh -i` -3. Use a wrapper script if the tool doesn't support shell arguments - -### Too many commands are being recorded - -1. Add patterns to `history_filter` in your config -2. Use `cwd_filter` for directory-based exclusion -3. Prefix sensitive commands with a space -4. Run `atuin history prune` to clean existing entries - -### Atuin works in terminal but not in IDE - -This is the most common issue. The IDE's embedded terminal likely isn't starting an interactive shell. See [Enabling Atuin in Embedded Terminals](#enabling-atuin-in-embedded-terminals) above. diff --git a/docs/docs/guide/sync.md b/docs/docs/guide/sync.md deleted file mode 100644 index 070d8178..00000000 --- a/docs/docs/guide/sync.md +++ /dev/null @@ -1,78 +0,0 @@ -# Setting up Sync - -At this point, you have Atuin storing and searching your shell history! But it -isn't syncing it just yet. To do so, you'll need to register with the sync -server. All of your history is fully end-to-end encrypted, so there are no -risks of the server snooping on you. - -If you don't have an account, please [register](#register). If you have already registered, -proceed to [login](#login). - -**Note:** You first have to set up your `sync_address` if you want to use a [self hosted server](../self-hosting/server-setup.md). - -## Register - -``` -atuin register -u <YOUR_USERNAME> -e <YOUR EMAIL> -``` - -After registration, Atuin will generate an encryption key for you and store it -locally. This is needed for logging in to other machines, and can be seen with - -``` -atuin key -``` - -Please **never** share this key with anyone! The Atuin developers will never -ask you for your key, your password, or the contents of your Atuin directory. - -If you lose your key, we can do nothing to help you. We recommend you store -this somewhere safe, such as in a password manager. - -## First sync -By default, Atuin will sync your history once per hour. This can be -[configured](../configuration/config.md#sync_frequency). - -To run a sync manually, please run - -``` -atuin sync -``` - -Atuin tries to be smart with a sync, and not waste data transfer. However, if -you are seeing some missing data, please try running - -``` -atuin sync -f -``` - -This triggers a full sync, which may take longer as it works through historical data. - -## Login - -When only signed in on one machine, Atuin sync operates as a backup. This is -pretty useful by itself, but syncing multiple machines is where the magic -happens. - -First, ensure you are [registered with the sync server](#register) and make a -note of your key. You can see this with `atuin key`. - -Then, install Atuin on a new machine. Once installed, login with - -``` -atuin login -u <USERNAME> -``` - -You will be prompted for your password, and for your key. - -Syncing will happen automatically in the background, but you may wish to run it manually with - -``` -atuin sync -``` - -Or, if you see missing data, force a full sync with: - -``` -atuin sync -f -``` diff --git a/docs/docs/guide/theming.md b/docs/docs/guide/theming.md deleted file mode 100644 index 2d71d41d..00000000 --- a/docs/docs/guide/theming.md +++ /dev/null @@ -1,138 +0,0 @@ -# Theming - -Available in Atuin >= 18.4 - -For terminal interface customization, Atuin supports user and built-in color themes. - -Atuin ships with only a couple of built-in alternative themes, but more can be added via TOML files. - -## Required config - -The following is required in your config file (`~/.config/atuin/config.toml`) - -``` -[theme] -name = "THEMENAME" -``` - -Where `THEMENAME` is a known theme. The following themes are available out-of-the-box: - -* `default` theme -* `autumn` theme -* `marine` theme -* `(none)` theme (removes all styling) - -These are present to ensure users and developers can try out theming, but in general, you -will need to download themes or make your own. - -If you are writing your own themes, you can add the following line to get additional output: - -``` -debug = true -``` - -to the same config block. This will print out any color names that cannot be parsed from -the requested theme. - -A final optional setting is available: - -``` -max_depth: 10 -``` - -which sets the maximum levels of theme parents to traverse. This should not need to be -explicitly added in normal use. - -## Usage - -### Theme structure - -Themes are maps from *Meanings*, describing the developer's intentions, -to (at present) colors. In future, this may be expanded to allow richer style support. - -*Meanings* are from an enum with the following values: - -* `AlertInfo`: alerting the user at an INFO level -* `AlertWarn`: alerting the user at a WARN level -* `AlertError`: alerting the user at an ERROR level -* `Annotation`: less-critical, supporting text -* `Base`: default foreground color -* `Guidance`: instructing the user as help or context -* `Important`: drawing the user's attention to information -* `Title`: titling a section or view -* `Muted`: anodyne, usually grey, foreground for contrast with other colors. Normally equivalent to the base color, but allows themes to change the base color, with less risk of breaking intentional color contrasts (e.g. stacked bar charts) - -These may expand over time as they are added to Atuin's codebase, but Atuin -should have fallbacks added for any new *Meanings* so that, whether themes limit to -the present list or take advantage of new *Meanings* in future, they should -keep working sensibly. - -**Note for Atuin contributors**: please do identify and, where appropriate during your own -PRs, extend the Meanings enum if needed (along with a fallback Meaning!). - -### Theme creation - -When a theme name is read but not yet loaded, Atuin will look for it in the folder -`~/.config/atuin/themes/` unless overridden by the `ATUIN_THEME_DIR` environment -variable. It will attempt to open a file of name `THEMENAME.toml` and read it as a -map from *Meanings* to foreground colors. - -Note that, at present, it is not possible to specify the default terminal color explicitly -in a theme file. However, the default theme Base color will always be unset and therefore -will be the user's default terminal color. Hence, you should only override the Base color -in your theme, or derive from a theme that does so, if your theme would not make sense -otherwise (e.g. the `marine` theme is intended to make everything green/blue, so it does, -but the `autumn` theme only seeks to make the custom colors warmer, so it does not). - -Colors may be specified either as names from the [palette](https://ogeon.github.io/docs/palette/master/palette/named/index.html) -crate in lowercase, or as six-character hex codes, prefixed with `#`. To explicitly select ANSI colors by integer, or for greater flexibility in general, you can prefix with `@` and the rest of the string will be handled by crossterm's color parsing. For examples, see [crossterm's color deserialization tests](https://github.com/crossterm-rs/crossterm/blob/5d50d8da62c5e034ef8b2787a771a2c0f9b3b2f9/src/style/types/color.rs#L389), remembering the need to add a `@` prefix for atuin. - -For example, the following are valid color names: - -* `#ff0088` -* `teal` -* `powderblue` -* `@ansi_(255)` -* `@rgb_(255, 128, 0)` - -You can also express colors through Crossterm-supported strings, prefixed by `@`. -For example, - -* `@ansi_(123)` -* `@dark_yellow` - -While there is not currently an official reference, you can see examples in the -[crossterm tests](https://docs.rs/crossterm/latest/src/crossterm/style/types/color.rs.html#376). -As this is passed straight to Crossterm, using [ANSI codes](https://www.ditig.com/256-colors-cheat-sheet) -can be helpful for ensuring your theme is compatible with 256-color terminals. - -A theme file, say `my-theme.toml` can then be built up, such as: - -```toml -[theme] -name = "my-theme" -parent = "autumn" - -[colors] -AlertInfo = "green" -Guidance = "#888844" - -``` - -where not all of the *Meanings* need to be explicitly defined. If they are absent, -then the color will be chosen from the parent theme, if one is defined, or if that -key is missing in the `theme` block, from the `default` theme. - -If the entire named theme is missing, which is inherently an error, then the theme -will drop to `(none)` and leave Atuin unstyled, rather than trying to fallback to -the any default, or other, theme. - -This theme file should be moved to `~/.config/atuin/themes/my-theme.toml` and the -following added to `~/.config/atuin/config.toml`: - -``` -[theme] -name = "my-theme" -``` - -When you next run Atuin, your theme should be applied. diff --git a/docs/docs/index.md b/docs/docs/index.md deleted file mode 100644 index 43ef2f9c..00000000 --- a/docs/docs/index.md +++ /dev/null @@ -1,48 +0,0 @@ -# Getting started - -Atuin replaces your existing shell history with a SQLite database, and records -additional context for your commands. With this context, Atuin gives you faster -and better search of your shell history. - -Additionally, Atuin (optionally) syncs your shell history between all of your -machines. Fully end-to-end encrypted, of course. - -You may use either the server I host, or host your own! Or just don't use sync -at all. As all history sync is encrypted, I couldn't access your data even if I -wanted to. And I **really** don't want to. - -If you have any problems, please open a topic on the [forum](https://forum.atuin.sh) - -Alternatively, get in touch on our [Discord](https://discord.gg/Fq8bJSKPHh) or open an [issue](https://github.com/atuinsh/atuin/issues) - -#### Supported Shells - -- zsh -- bash -- fish -- nushell -- xonsh -- powershell (tier 2 support) - -## Quickstart - -Please do try and read this guide, but if you're in a hurry and want to get -started quickly: - -```bash -bash <(curl --proto '=https' --tlsv1.2 -sSf https://setup.atuin.sh) - -atuin register -u <USERNAME> -e <EMAIL> -atuin import auto -atuin sync -``` - -Now restart your shell! - -Anytime you press ctrl-r or up, you will see the Atuin search UI. Type your -query, enter to execute. If you'd like to select a command without executing -it, press tab. - -You might like to configure an [inline window](configuration/config.md#inline_height), or [disable up arrow bindings](configuration/key-binding.md#disable-up-arrow) - -[**Installation** - Install and setup Atuin](guide/installation.md) diff --git a/docs/docs/integrations.md b/docs/docs/integrations.md deleted file mode 100644 index 6a78b52d..00000000 --- a/docs/docs/integrations.md +++ /dev/null @@ -1,41 +0,0 @@ -# Integrations - -This page covers integrations with shell plugins and tools. For information about how Atuin's shell hooks work and troubleshooting embedded terminals (IDEs, AI coding assistants, etc.), see [Shell Integration and Interoperability](guide/shell-integration.md). - -## zsh-autosuggestions - -Atuin automatically adds itself as an [autosuggest strategy](https://github.com/zsh-users/zsh-autosuggestions#suggestion-strategy). - -If you'd like to override this, add your own config after `"$(atuin init zsh)"` in your `.zshrc`. - -## zsh-vi-mode - -If you are using [Zsh Vi Mode](https://github.com/jeffreytse/zsh-vi-mode), you may want to add the following to your `.zshrc` to prevent overriding the default atuin binds: - -```shell -# Append a command directly (after sourcing zvm) -zvm_after_init_commands+=( - 'eval "$(atuin init zsh)"' -) -``` - -## ble.sh auto-complete (Bash) - -If ble.sh is available when Atuin's integration is loaded in Bash, Atuin automatically defines and registers an auto-complete source for the autosuggestion feature of ble.sh. - -If you'd like to change the behavior, please overwrite the shell function `ble/complete/auto-complete/source:atuin-history` after `eval "$(atuin init bash)"` in your `.bashrc`. - -If you would not like Atuin's auto-complete source, please add the following setting after `eval "$(atuin init bash)"` in your `.bashrc`: - -```shell -# bashrc (after eval "$(atuin init bash)") - -ble/util/import/eval-after-load core-complete ' - ble/array#remove _ble_complete_auto_source atuin-history' -``` - -## Embedded Terminals and IDEs - -Atuin may not work out of the box in embedded terminals found in IDEs (PyCharm, VS Code, etc.) or AI coding assistants (Claude Code, etc.). This is because these tools often start non-interactive shells that don't source your shell configuration. - -For solutions and workarounds, see [Shell Integration and Interoperability](guide/shell-integration.md). diff --git a/docs/docs/known-issues.md b/docs/docs/known-issues.md deleted file mode 100644 index 21179fa9..00000000 --- a/docs/docs/known-issues.md +++ /dev/null @@ -1,4 +0,0 @@ -# Known Issues - -- SQLite has some issues with ZFS in certain configurations. As Atuin uses SQLite, this may cause your shell to become slow! We have an [issue](https://github.com/atuinsh/atuin/issues/952) to track, with some workarounds -- SQLite also does not tend to like network filesystems (eg, NFS) diff --git a/docs/docs/reference/config.md b/docs/docs/reference/config.md deleted file mode 100644 index 3e3465d9..00000000 --- a/docs/docs/reference/config.md +++ /dev/null @@ -1,127 +0,0 @@ -# config - -## `atuin config` - -Read, write, and inspect Atuin configuration values. Atuin resolves -configuration from multiple sources (defaults, config file, environment -variables). The `config` command lets you see what is set where, and change -values in your `config.toml` without opening an editor. - -## Subcommands - -### `atuin config get <key>` - -Print the value of a key as it appears in your config file. - -``` -$ atuin config get search_mode -fuzzy - -$ atuin config get daemon -[daemon] -enabled = true -socket_path = "/tmp/atuin_daemon.sock" -``` - -If the key is not present in the config file, you'll see: - -``` -$ atuin config get enter_accept -(not set in config file) -``` - -#### `--resolved` / `-r` - -Print the effective value after merging defaults, the config file, and -environment variable overrides: - -``` -$ atuin config get enter_accept --resolved -false -``` - -This also works for table keys, showing all resolved children as flat -dotted key=value pairs: - -``` -$ atuin config get logs --resolved -logs.ai.file = ai.log -logs.daemon.file = daemon.log -logs.dir = /home/user/.local/share/atuin/logs -logs.enabled = true -logs.level = info -logs.search.file = search.log -``` - -#### `--verbose` / `-v` - -Show both the config file value and the resolved value side by side: - -``` -$ atuin config get enter_accept --verbose -Config file: - (not set in config file) - -Resolved: - false -``` - -### `atuin config set <key> <value>` - -Set a configuration value in your `config.toml`. The file's existing -formatting and comments are preserved. - -``` -$ atuin config set search_mode fuzzy -$ atuin config set daemon.enabled true -``` - -#### Type detection - -By default, `set` matches the TOML type of the existing value when the key -is already in the config file. This prevents accidentally changing a string -like `"300"` into an integer `300`. - -For new keys (not already in the file), `set` auto-detects the type: - -| Value | Detected type | -|---------------|---------------| -| `true`/`false`| boolean | -| `42`, `-1` | integer | -| `3.14` | float | -| anything else | string | - -!!! warning "Scalar values only" - `atuin config set` can only set config entries with scalar values; for tables or arrays, edit the config file manually. - -#### `--type` / `-t` - -Override type detection with an explicit type: - -``` -$ atuin config set sync_frequency 600 --type string -``` - -Possible values: `auto`, `string`, `boolean`, `integer`, `float`. - -Setting a key that is currently a table will produce an error directing you -to use a dotted key instead: - -``` -$ atuin config set logs true -Error: 'logs' is a table; use a dotted key like 'logs.key' to set a value within it -``` - -### `atuin config print [key]` - -Print configuration values from your config file in TOML format. Without a -key, prints the entire file. With a key, prints that section: - -``` -$ atuin config print daemon -[daemon] -enabled = true -socket_path = "/tmp/atuin_daemon.sock" -pidfile_path = "/tmp/atuin_daemon.pid" -autostart = false -``` diff --git a/docs/docs/reference/daemon.md b/docs/docs/reference/daemon.md deleted file mode 100644 index 540404bb..00000000 --- a/docs/docs/reference/daemon.md +++ /dev/null @@ -1,32 +0,0 @@ -# daemon - -## `atuin daemon` - -The Atuin daemon is a background daemon designed to - -1. Speed up database writes -2. Allow machines to sync when not in use, so they're ready to go right away -3. Provides a hot in-memory fuzzy searcher -4. Perform background maintenance - -It may also work around issues with ZFS/SQLite performance. - -## To enable - -Add the following to the bottom of your Atuin config file - -```toml -[daemon] -enabled = true -autostart = true -``` - -With `autostart = true`, the CLI will automatically start and manage a local daemon for history hook calls. -If you use systemd socket activation, keep `autostart = false`. -If a legacy experimental daemon is already running, autostart cannot upgrade it in-place. Restart the daemon manually once. - -If you prefer running the daemon yourself (for example via systemd/tmux), keep `autostart = false` and run `atuin daemon`. - -## Extra config - -See the [config section](../configuration/config.md#daemon) diff --git a/docs/docs/reference/doctor.md b/docs/docs/reference/doctor.md deleted file mode 100644 index bd091aeb..00000000 --- a/docs/docs/reference/doctor.md +++ /dev/null @@ -1,38 +0,0 @@ -# doctor - -## `atuin doctor` - -This command will attempt to diagnose common problems. It will also dump information about your system - -Please include its output with issues and support requests. - -Example output: - -``` -Atuin Doctor -Checking for diagnostics - - -Please include the output below with any bug reports or issues - -atuin: - version: 18.1.0 - sync: - cloud: true - records: true - auto_sync: true - last_sync: 2024-03-05 14:54:48.447677 +00:00:00 -shell: - name: zsh - plugins: - - atuin -system: - os: Darwin - arch: arm64 - version: 14.4 - disks: - - name: Macintosh HD - filesystem: apfs - - name: Macintosh HD - filesystem: apfs -``` diff --git a/docs/docs/reference/gen-completions.md b/docs/docs/reference/gen-completions.md deleted file mode 100644 index 3027d8a9..00000000 --- a/docs/docs/reference/gen-completions.md +++ /dev/null @@ -1,20 +0,0 @@ -# gen-completions - -[Shell completions](https://en.wikipedia.org/wiki/Command-line_completion) for Atuin can be generated by specifying the output directory and desired shell via `gen-completions` subcommand. - -``` -$ atuin gen-completions --shell bash --out-dir $HOME - -Shell completion for BASH is generated in "/home/user" -``` - -Possible values for the `--shell` argument are the following: - -- `bash` -- `fish` -- `zsh` -- `nushell` -- `powershell` -- `elvish` - -Also, see the [supported shells](https://github.com/atuinsh/atuin#supported-shells). diff --git a/docs/docs/reference/hex.md b/docs/docs/reference/hex.md deleted file mode 100644 index 8bffed68..00000000 --- a/docs/docs/reference/hex.md +++ /dev/null @@ -1 +0,0 @@ -`atuin hex` has been renamed `atuin pty-proxy` as of Atuin v18.17.0. diff --git a/docs/docs/reference/import.md b/docs/docs/reference/import.md deleted file mode 100644 index 05a4e466..00000000 --- a/docs/docs/reference/import.md +++ /dev/null @@ -1,109 +0,0 @@ -# import - -## `atuin import` - -Atuin can import your history from your "old" history file - -`atuin import auto` will attempt to figure out your shell (via \$SHELL) and run -the correct importer - -Unfortunately these older files do not store as much information as Atuin does, -so not all features are available with imported data. - -Except as noted otherwise, you can set the `HISTFILE` environment variable to -control which file is read, otherwise each importer will try some default filenames. - -``` -HISTFILE=/path/to/history/file atuin import zsh -``` - -Note that for shells such as Xonsh that store history in many files rather than a -single file, `$HISTFILE` should be set to the directory in which those files reside. - -For formats that don't store timestamps, timestamps will be generated starting at -the current time plus 1ms for each additional command in the history. - -Most importers will discard commands found that have invalid UTF-8. - -## bash - -This will read the history from `$HISTFILE` or `$HOME/.bash_history`. - -Warnings will be issued if timestamps are found to be out of order, which could also -happen when a history file starts without timestamps but later entries include them. - -## fish - -fish supports multiple history sessions, so the importer will default to the `fish` -session unless the `fish_history` environment variable is set. The file to be read -will be `{session}_history` in `$XDG_DATA_HOME/fish/` (or `$HOME/.local/share/fish`). - -Not all of the data in the fish history is preserved, some data about filenames used -for each command are not used by Atuin, so it is discarded. - -## nu - -This importer reads from Nushell's text history format, which is stored in -`$XDG_CONFIG_HOME/nushell/history.txt` or `$HOME/.config/nushell/history.txt`. -There is no way to set the filename otherwise. - -## nu-hist-db - -This importer reads from Nushell's SQLite history database, which is stored in -`$XDG_CONFIG_HOME/nushell/history.sqlite3` or `$HOME/.config/nushell/history.sqlite3`. -There is no way to set the filename otherwise. - -## powershell - -This importer reads from -[PowerShell's history file](https://learn.microsoft.com/en-us/powershell/module/psreadline/about/about_psreadline#command-history). -On Windows, the file is located at -`$APPDATA\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt`. -On other systems, it is located at -`$XDG_DATA_HOME/powershell/PSReadLine/ConsoleHost_history.txt` -or `$HOME/.local/share/powershell/PSReadLine/ConsoleHost_history.txt`. - -## replxx - -The [replxx](https://github.com/AmokHuginnsson/replxx) importer will read from -`$HISTFILE` or `$HOME/.histfile`. - -## resh - -The [RESH](https://github.com/curusarn/resh) importer will read from `$HISTFILE` -or `$HOME/.resh_history.json`. - -## xonsh - -The Xonsh importer will read from all JSON files it finds in the Xonsh history -directory. The location of the directory is determined as follows: -* If `$HISTFILE` is set, its value is used as the history directory. -* If `$XONSH_DATA_DIR` is set (as it typically will be if the importer is invoked -from within Xonsh), `$XONSH_DATA_DIR/history_json` is used. -* If `$XDG_DATA_HOME` is set, `$XDG_DATA_HOME/xonsh/history_json` is used. -* Otherwise, `$HOME/.local/share/xonsh/history_json` is used. - -Not all data present in Xonsh history JSON files is used by Atuin. Xonsh stores the -environment variables present when each session was initiated, but this data is -discarded by Atuin. Xonsh optionally stores the output of each command; if present -this data is also ignored by Atuin. - -## xonsh-sqlite - -The Xonsh SQLite importer will read from the Xonsh SQLite history file. The history -file's location is determined by the same process as the regular Xonsh importer, -but with `history_json` replaced by `xonsh-history.sqlite`. - -The Xonsh SQLite backend does not store environment variables, but like the JSON -backend it can optionally store the output of each command. As with the JSON backend, -if present this data will be ignored by Atuin. - -## zsh - -This will read the Zsh history from `$HISTFILE` or `$HOME/.zhistory` -or `$HOME/.zsh_history` in either the simple or extended format. - -## zsh-hist-db - -This will read the Zsh histdb SQLite file from `$HISTDB_FILE` or -`$HOME/.histdb/zsh-history.db`. diff --git a/docs/docs/reference/info.md b/docs/docs/reference/info.md deleted file mode 100644 index a19d0b42..00000000 --- a/docs/docs/reference/info.md +++ /dev/null @@ -1,22 +0,0 @@ -# info - -## `atuin info` - -This command shows the location of config files on your system - -Example output: - -``` -Config files: -client config: "/Users/ellie/.config/atuin/config.toml" -server config: "/Users/ellie/.config/atuin/server.toml" -client db path: "/Users/ellie/.local/share/atuin/history.db" -key path: "/Users/ellie/.local/share/atuin/key" -session path: "/Users/ellie/.local/share/atuin/session" - -Env Vars: -ATUIN_CONFIG_DIR = "None" - -Version info: -version: 18.1.0 -``` diff --git a/docs/docs/reference/list.md b/docs/docs/reference/list.md deleted file mode 100644 index a9920718..00000000 --- a/docs/docs/reference/list.md +++ /dev/null @@ -1,31 +0,0 @@ -# history list - -## `atuin history list` - - -| Arg | Description | -|------------------|-------------------------------------------------------------------------------| -| `--cwd`/`-c` | List history for the current directory only (default: all dirs) | -| `--session`/`-s` | List history for the current session only (default: false) | -| `--human` | Use human-readable formatting for the timestamp and duration (default: false) | -| `--cmd-only` | Show only the text of the command (default: false) | -| `--reverse` | Reverse the order of the output (default: false) | -| `--format` | Specify the formatting of a command (see below) | -| `--print0` | Terminate the output with a null, for better multiline support | - - -## Format - -Customize the output of `history list` - -Example - -``` -atuin history list --format "{time} - {duration} - {command}" -``` - -Supported variables - -``` -{command}, {directory}, {duration}, {user}, {host} and {time} -``` diff --git a/docs/docs/reference/prune.md b/docs/docs/reference/prune.md deleted file mode 100644 index 40a75d5c..00000000 --- a/docs/docs/reference/prune.md +++ /dev/null @@ -1,15 +0,0 @@ -# history prune - -## `atuin history prune` - -This command deletes history entries matching the [history_filter](../configuration/config.md#history_filter) configuration parameter. - -These may be commands that match the current `history_filter` configuration, but were saved to history before the filter was set up, and therefore were not excluded from history at the time of execution. - -It may be useful to run the prune command after updating `history_filter` to remove old history entries that match the new filters. - -It can be run with `--dry-run` first to list history entries that will be removed. - -| Argument | Description | -|------------------|--------------------------------------------------------------------| -| `--dry-run`/`-n` | List matching history lines without performing the actual deletion | diff --git a/docs/docs/reference/pty-proxy.md b/docs/docs/reference/pty-proxy.md deleted file mode 100644 index ce4a881f..00000000 --- a/docs/docs/reference/pty-proxy.md +++ /dev/null @@ -1,69 +0,0 @@ -# pty-proxy - -Atuin pty-proxy is an experimental lightweight PTY proxy, providing new features without needing to replace your existing terminal or shell. It currently supports bash, zsh, fish, and nu. - -!!! Note "Previously `atuin hex`" - - `atuin pty-proxy` is a replacement for the old `atuin hex` command. `atuin hex` still works for backward compatibility reasons, but will eventually be removed. - -## TUI Rendering - -The search TUI exposes a tradeoff: the UI is either in fullscreen alt-screen mode that takes over your terminal, or inline mode that clears your previous output. Neither is great. - -With pty-proxy, the Atuin popup renders over the top of your previous output, but when it's closed we can restore the output successfully. - -## Initialization - -Atuin pty-proxy needs to be initialized separately from your existing Atuin config. Place the init line shown below in your shell's init script, as high in the document as possible, _before_ your normal `atuin init` call. - -=== "zsh" - - ```shell - eval "$(atuin pty-proxy init zsh)" - ``` - -=== "bash" - - ```shell - eval "$(atuin pty-proxy init bash)" - ``` - -=== "fish" - - Add - - ```shell - atuin pty-proxy init fish | source - ``` - - to your `is-interactive` block in your `~/.config/fish/config.fish` file - -=== "Nushell" - - Run in *Nushell*: - - ```shell - mkdir ~/.local/share/atuin/ - atuin pty-proxy init nu | save -f ~/.local/share/atuin/pty-proxy-init.nu - ``` - - Add to `config.nu`, **before** the regular `atuin init`: - - ```shell - source ~/.local/share/atuin/pty-proxy-init.nu - ``` - Nushell's `source` command requires a static file path, so you must - pre-generate the file. - ---- - -If the `atuin` binary is not in your `PATH` by default, you should initialize pty-proxy as soon as it is set. For example, for a bash user with Atuin installed in `~/.atuin/bin/atuin`, a config file might look like this: - -```bash -export PATH=$HOME/.atuin/bin:$PATH -eval "$(atuin pty-proxy init bash)" - -# ... other shell configuration ... - -eval "$(atuin init bash)" -``` diff --git a/docs/docs/reference/search.md b/docs/docs/reference/search.md deleted file mode 100644 index 7bce816b..00000000 --- a/docs/docs/reference/search.md +++ /dev/null @@ -1,65 +0,0 @@ -# search - -Atuin search supports wildcards, with either the `*` or `%` character. By -default, a prefix search is performed (ie, all queries are automatically -appended with a wildcard). - -| Arg | Description | -| -------------------- | ----------------------------------------------------------------------------- | -| `--cwd`/`-c` | The directory to list history for (default: all dirs) | -| `--exclude-cwd` | Do not include commands that ran in this directory (default: none) | -| `--exit`/`-e` | Filter by exit code (default: none) | -| `--exclude-exit` | Do not include commands that exited with this value (default: none) | -| `--before` | Only include commands ran before this time(default: none) | -| `--after` | Only include commands ran after this time(default: none) | -| `--interactive`/`-i` | Open the interactive search UI (default: false) | -| `--human` | Use human-readable formatting for the timestamp and duration (default: false) | -| `--limit` | Limit the number of results (default: none) | -| `--offset` | Offset from the start of the results (default: none) | -| `--delete` | Delete history matching this query | -| `--delete-it-all` | Delete all shell history | -| `--reverse` | Reverse order of search results, oldest first | -| `--format`/`-f` | Available variables: {command}, {directory}, {duration}, {user}, {host}, {time}, {exit} and {relativetime}. Example: --format "{time} - [{duration}] - {directory}$\t{command}" | -| `--inline-height` | Set the maximum number of lines Atuin's interface should take up | -| `--help`/`-h` | Print help | - -## `atuin search -i` - -Atuin's interactive search TUI allows you to fuzzy search through your history. - - - -You can replay the `nth` command with `alt + #` where `#` is the line number of the command you would like to replay. - -Note: This is not yet supported on macOS. - -## Examples - -``` -# Open the interactive search TUI -atuin search -i - -# Open the interactive search TUI preloaded with a query -atuin search -i atuin - -# Search for all commands, beginning with cargo, that exited successfully -atuin search --exit 0 cargo - -# Search for all commands, that failed, from the current dir, and were ran before April 1st 2021 -atuin search --exclude-exit 0 --before 01/04/2021 --cwd . - -# Search for all commands, beginning with cargo, that exited successfully, and were ran after yesterday at 3pm -atuin search --exit 0 --after "yesterday 3pm" cargo - -# Delete all commands, beginning with cargo, that exited successfully, and were ran after yesterday at 3pm -atuin search --delete --exit 0 --after "yesterday 3pm" cargo - -# Search for a command beginning with cargo, return exactly one result. -atuin search --limit 1 cargo - -# Search for a single result for a command beginning with cargo, skipping (offsetting) one result -atuin search --offset 1 --limit 1 cargo - -# Find the oldest cargo command -atuin search --limit 1 --reverse cargo -``` diff --git a/docs/docs/reference/stats.md b/docs/docs/reference/stats.md deleted file mode 100644 index b1e4f0f9..00000000 --- a/docs/docs/reference/stats.md +++ /dev/null @@ -1,50 +0,0 @@ -# stats - -Atuin can also calculate stats based on your history - this is currently a -little basic, but more features to come. - -## 1-day stats - -You provide the starting point, and Atuin computes the stats for 24h from that point. -Date parsing is provided by `interim`, which supports different formats -for full or relative dates. Certain formats rely on the dialect option in your -[configuration](../configuration/config.md#dialect) to differentiate day from month. -Refer to [the module's documentation](https://docs.rs/interim/0.1.0/interim/#supported-formats) for more details on the supported date formats. - -``` -$ atuin stats last friday - -+---------------------+------------+ -| Statistic | Value | -+---------------------+------------+ -| Most used command | git status | -+---------------------+------------+ -| Commands ran | 450 | -+---------------------+------------+ -| Unique commands ran | 213 | -+---------------------+------------+ - -# A few more examples: -$ atuin stats 2018-04-01 -$ atuin stats April 1 -$ atuin stats 01/04/22 -$ atuin stats last thursday 3pm # between last thursday 3:00pm and the following friday 3:00pm -``` - -## Full history stats - -``` -$ atuin stats -# or -$ atuin stats all - -+---------------------+-------+ -| Statistic | Value | -+---------------------+-------+ -| Most used command | ls | -+---------------------+-------+ -| Commands ran | 8190 | -+---------------------+-------+ -| Unique commands ran | 2996 | -+---------------------+-------+ -``` diff --git a/docs/docs/reference/sync.md b/docs/docs/reference/sync.md deleted file mode 100644 index ac30ddae..00000000 --- a/docs/docs/reference/sync.md +++ /dev/null @@ -1,77 +0,0 @@ -# sync - -Atuin can back up your history to a server, and use this to ensure multiple -machines have the same shell history. This is all encrypted end-to-end, so the -server operator can _never_ see your data! - -Anyone can host a server (see the [self-hosting docs](../self-hosting/server-setup.md)), but I -host one at https://api.atuin.sh. This is the default server address, which can -be changed in the [config](../configuration/config.md#sync_address). Again, I _cannot_ see your data, and -do not want to. - -## Sync frequency - -Syncing will happen automatically, unless configured otherwise. The sync -frequency is configurable in [config](../configuration/config.md#sync_frequency) - -## Sync - -You can manually trigger a sync with `atuin sync` - -## Register - -Register for a sync account with - -``` -atuin register -u <USERNAME> -e <EMAIL> -p <PASSWORD> -``` - -If you don't want to have your password be included in shell history, you can omit -the password flag and you will be prompted to provide it through stdin. - -Usernames must be unique and only contain alphanumerics or hyphens, -and emails shall only be used for important notifications (security breaches, changes to service, etc). - -Upon success, you are also logged in :) Syncing should happen automatically from -here! - -## Delete - -You can delete your sync account with - -``` -atuin account delete -``` - -This will remove your account and all synchronized history from the server. Local data will not be touched! - -## Key - -As all your data is encrypted, Atuin generates a key for you. It's stored in the -Atuin data directory (`~/.local/share/atuin` on Linux). - -You can also get this with - -``` -atuin key -``` - -Never share this with anyone! - -## Login - -If you want to log in to a new machine, you will require your encryption key -(`atuin key`). - -``` -atuin login -u <USERNAME> -p <PASSWORD> -k <KEY> -``` - -If you don't want to have your password or encryption key be included in shell history, you can omit -the corresponding flag and you will be prompted to provide it through stdin. - -## Logout - -``` -atuin logout -``` diff --git a/docs/docs/self-hosting/docker.md b/docs/docs/self-hosting/docker.md deleted file mode 100644 index e6296ff1..00000000 --- a/docs/docs/self-hosting/docker.md +++ /dev/null @@ -1,131 +0,0 @@ -# Docker - -!!! warning - If you are self hosting, we strongly suggest you stick to [tagged releases](https://github.com/atuinsh/atuin/releases), and do not follow `main` or `latest` - - Follow the GitHub releases, and please read the notes for each release. Most of the time, upgrades can occur without any manual intervention. - - We cannot guarantee that all updates will apply cleanly, and some may require some extra steps. - -There is a supplied docker image to make deploying a server as a container easier. The "LATEST TAGGED RELEASE" can be found on the [releases page](https://github.com/atuinsh/atuin/releases). - -```sh -CONFIG="$HOME/.config/atuin" -mkdir "$CONFIG" -chown 1000:1000 "$CONFIG" -docker run -d -v "$CONFIG:/config" ghcr.io/atuinsh/atuin:<LATEST TAGGED RELEASE> start -``` - -## Docker Compose - -Using the already build docker image hosting your own Atuin can be done using the supplied docker-compose file. - -Create a `docker-compose.yml`: - -```yaml -services: - atuin: - restart: always - image: ghcr.io/atuinsh/atuin:<LATEST TAGGED RELEASE> - command: start - volumes: - - "./config:/config" - ports: - - 8888:8888 - environment: - ATUIN_HOST: "0.0.0.0" - ATUIN_OPEN_REGISTRATION: "true" - ATUIN_DB_URI: postgres://${ATUIN_DB_USERNAME}:${ATUIN_DB_PASSWORD}@db/${ATUIN_DB_NAME} - RUST_LOG: info,atuin_server=debug - depends_on: - - db - db: - image: postgres:18 - restart: unless-stopped - volumes: # Don't remove permanent storage for index database files! - - "./database:/var/lib/postgresql/" - environment: - POSTGRES_USER: ${ATUIN_DB_USERNAME} - POSTGRES_PASSWORD: ${ATUIN_DB_PASSWORD} - POSTGRES_DB: ${ATUIN_DB_NAME} -``` - -Create a `.env` file next to `docker-compose.yml` with contents like this: - -```ini -ATUIN_DB_NAME=atuin -ATUIN_DB_USERNAME=atuin -# Choose your own secure password. Stick to [A-Za-z0-9.~_-] -ATUIN_DB_PASSWORD=really-insecure -``` - - -Start the services using `docker compose`: - -```sh -mkdir config -chown 1000:1000 config -docker compose up -d -``` - -## Using systemd to manage your atuin server - -The following `systemd` unit file to manage your `docker-compose` managed service: - -```ini -[Unit] -Description=Docker Compose Atuin Service -Requires=docker.service -After=docker.service - -[Service] -# Where the docker-compose file is located -WorkingDirectory=/srv/atuin-server -ExecStart=/usr/bin/docker compose up -ExecStop=/usr/bin/docker compose down -TimeoutStartSec=0 -Restart=on-failure -StartLimitBurst=3 - -[Install] -WantedBy=multi-user.target -``` - -Start and enable the service with: - -```sh -systemctl enable --now atuin -``` - -Check if its running with: - -```sh -systemctl status atuin -``` - -## Creating backups of the Postgres database - -You can add another service to your `docker-compose.yml` file to have it run daily backups. It should look like this: - -```yaml - backup: - container_name: atuin_db_dumper - image: prodrigestivill/postgres-backup-local - env_file: - - .env - environment: - POSTGRES_HOST: postgresql - POSTGRES_DB: ${ATUIN_DB_NAME} - POSTGRES_USER: ${ATUIN_DB_USERNAME} - POSTGRES_PASSWORD: ${ATUIN_DB_PASSWORD} - SCHEDULE: "@daily" - BACKUP_DIR: /db_dumps - volumes: - - ./db_dumps:/db_dumps - depends_on: - - postgresql -``` - -This will create daily backups of your database for that additional layer of comfort. - -PLEASE NOTE: The `./db_dumps` mount MUST be a POSIX-compliant filesystem to store the backups (mainly with support for hardlinks and softlinks). So filesystems like VFAT, EXFAT, SMB/CIFS, ... can't be used with this docker image. See https://github.com/prodrigestivill/docker-postgres-backup-local for more details on how this works. There are additional settings for the number of backups retained, etc., all explained on the linked page. diff --git a/docs/docs/self-hosting/kubernetes.md b/docs/docs/self-hosting/kubernetes.md deleted file mode 100644 index 463a3f96..00000000 --- a/docs/docs/self-hosting/kubernetes.md +++ /dev/null @@ -1,289 +0,0 @@ -# Kubernetes - -!!! warning - If you are self hosting, we strongly suggest you stick to tagged releases, and do not follow `main` or `latest` - - Follow the GitHub releases, and please read the notes for each release. Most of the time, upgrades can occur without any manual intervention. - - We cannot guarantee that all updates will apply cleanly, and some may require some extra steps. - -You could host your own Atuin server using the Kubernetes platform. - -Create a [`secrets.yaml`](https://github.com/atuinsh/atuin/blob/main/k8s/secrets.yaml) file for the database credentials: - -```yaml -apiVersion: v1 -kind: Secret -metadata: - name: atuin-secrets -type: Opaque -stringData: - ATUIN_DB_USERNAME: atuin - ATUIN_DB_PASSWORD: seriously-insecure - ATUIN_HOST: "127.0.0.1" - ATUIN_PORT: "8888" - ATUIN_OPEN_REGISTRATION: "true" - ATUIN_DB_URI: "postgres://atuin:seriously-insecure@postgres/atuin" -immutable: true -``` - -Create a [`atuin.yaml`](https://github.com/atuinsh/atuin/blob/main/k8s/atuin.yaml) file for the Atuin server: - -```yaml ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: postgres - namespace: atuin -spec: - replicas: 1 - strategy: - type: Recreate # This is important to ensure duplicate pods don't run and cause corruption - selector: - matchLabels: - io.kompose.service: postgres - template: - metadata: - labels: - io.kompose.service: postgres - spec: - containers: - - name: postgresql - image: postgres:14 - ports: - - containerPort: 5432 - env: - - name: POSTGRES_DB - value: atuin - - name: POSTGRES_PASSWORD - valueFrom: - secretKeyRef: - name: atuin-secrets - key: ATUIN_DB_PASSWORD - optional: false - - name: POSTGRES_USER - valueFrom: - secretKeyRef: - name: atuin-secrets - key: ATUIN_DB_USERNAME - optional: false - lifecycle: - preStop: - exec: - # This ensures graceful shutdown see: https://stackoverflow.com/a/75829325/3437018 - # Potentially consider using a `StatefulSet` instead of a `Deployment` - command: ["/usr/local/bin/pg_ctl stop -D /var/lib/postgresql/data -w -t 60 -m fast"] - resources: - requests: - cpu: 100m - memory: 100Mi - limits: - cpu: 250m - memory: 600Mi - volumeMounts: - - mountPath: /var/lib/postgresql/data/ - name: database - volumes: - - name: database - persistentVolumeClaim: - claimName: database ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: atuin -spec: - replicas: 1 - selector: - matchLabels: - io.kompose.service: atuin - template: - metadata: - labels: - io.kompose.service: atuin - spec: - containers: - - args: - - start - env: - - name: ATUIN_DB_URI - valueFrom: - secretKeyRef: - name: atuin-secrets - key: ATUIN_DB_URI - optional: false - - name: ATUIN_HOST - value: 0.0.0.0 - - name: ATUIN_PORT - value: "8888" - - name: ATUIN_OPEN_REGISTRATION - value: "true" - image: ghcr.io/atuinsh/atuin:latest - name: atuin - ports: - - containerPort: 8888 - resources: - limits: - cpu: 250m - memory: 1Gi - requests: - cpu: 250m - memory: 1Gi - volumeMounts: - - mountPath: /config - name: atuin-claim0 - volumes: - - name: atuin-claim0 - persistentVolumeClaim: - claimName: atuin-claim0 ---- -apiVersion: v1 -kind: Service -metadata: - labels: - io.kompose.service: atuin - name: atuin -spec: - type: NodePort - ports: - - name: "8888" - port: 8888 - nodePort: 30530 - selector: - io.kompose.service: atuin ---- -apiVersion: v1 -kind: Service -metadata: - labels: - io.kompose.service: postgres - name: postgres -spec: - type: ClusterIP - selector: - io.kompose.service: postgres - ports: - - protocol: TCP - port: 5432 - targetPort: 5432 ---- -kind: PersistentVolume -apiVersion: v1 -metadata: - name: database-pv - labels: - app: database - type: local -spec: - storageClassName: manual - capacity: - storage: 300Mi - accessModes: - - ReadWriteOnce - hostPath: - path: "/Users/firstname.lastname/.kube/database" ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - labels: - io.kompose.service: database - name: database -spec: - storageClassName: manual - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 300Mi ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - labels: - io.kompose.service: atuin-claim0 - name: atuin-claim0 -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 10Mi -``` - -Finally, you may want to use a separate namespace for atuin, by creating a [`namespaces.yaml`](https://github.com/atuinsh/atuin/blob/main/k8s/namespaces.yaml) file: - -```yaml -apiVersion: v1 -kind: Namespace -metadata: - name: atuin-namespace - labels: - name: atuin -``` - -Note that this configuration will store the database folder _outside_ the kubernetes cluster, in the folder `/Users/firstname.lastname/.kube/database` of the host system by configuring the `storageClassName` to be `manual`. In a real enterprise setup, you would probably want to store the database content permanently in the cluster, and not in the host system. - -You should also change the password string in `ATUIN_DB_PASSWORD` and `ATUIN_DB_URI` in the`secrets.yaml` file to a more secure one. - -The atuin service on the port `30530` of the host system. That is configured by the `nodePort` property. Kubernetes has a strict rule that you are not allowed to expose a port numbered lower than 30000. To make the clients work, you can simply set the port in your `config.toml` file, e.g. `sync_address = "http://192.168.1.10:30530"`. - -Deploy the Atuin server using `kubectl`: - -```shell - kubectl apply -f ./namespaces.yaml - kubectl apply -n atuin-namespace \ - -f ./secrets.yaml \ - -f ./atuin.yaml -``` - -The sample files above are also in the [k8s folder](https://github.com/atuinsh/atuin/tree/main/k8s) of the atuin repository. - -## Creating backups of the Postgres database - -Now you're up and running it's a good time to think about backups. - -You can create a [`CronJob`](https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/) which uses [`pg_dump`](https://www.postgresql.org/docs/current/app-pgdump.html) to create a backup of the database. This example runs weekly and dumps to the local disk on the node. - -```yaml -apiVersion: batch/v1 -kind: CronJob -metadata: - name: atuin-db-backup -spec: - schedule: "0 0 * * 0" # Run every Sunday at midnight - jobTemplate: - spec: - template: - spec: - containers: - - name: atuin-db-backup-pg-dump - image: postgres:14 - command: [ - "/bin/bash", - "-c", - "pg_dump --host=postgres --username=atuin --format=c --file=/backup/atuin-backup-$(date +'%Y-%m-%d').pg_dump", - ] - env: - - name: PGPASSWORD - valueFrom: - secretKeyRef: - name: atuin-secrets - key: ATUIN_DB_PASSWORD - optional: false - volumeMounts: - - name: backup-volume - mountPath: /backup - restartPolicy: OnFailure - volumes: - - name: backup-volume - hostPath: - path: /somewhere/on/node/for/database-backups - type: Directory -``` - -Configure/update the example `yaml` with the following: -- Set a more or less frequent schedule with the `schedule` property. -- Replace `/somewhere/on/node/for/database-backups` with a path on your node or reconfigure to use a `PersistentVolume` instead of `hostPath`. -- `--format=c` outputs a format that can be restored with `pg_restore`. Use [`plain`](https://www.postgresql.org/docs/current/app-pgdump.html) if you want `.sql` files outputted instead. diff --git a/docs/docs/self-hosting/server-setup.md b/docs/docs/self-hosting/server-setup.md deleted file mode 100644 index 2d5706f4..00000000 --- a/docs/docs/self-hosting/server-setup.md +++ /dev/null @@ -1,73 +0,0 @@ -# Server setup - -While we offer a public sync server, and cannot view your data (as it is encrypted), you may still wish to self host your own Atuin sync server. - -The requirements to do so are pretty minimal! You need to be able to run a binary or docker container, and have a PostgreSQL database setup. Atuin requires PostgreSQL 14 or above. - -Atuin also supports sqlite 3 and above. - -The server is distributed as a separate binary, `atuin-server`. Prebuilt binaries and an installer are published with every release on the [GitHub releases page](https://github.com/atuinsh/atuin/releases). For example, to install the latest release: - -```shell -curl --proto '=https' --tlsv1.2 -LsSf https://github.com/atuinsh/atuin/releases/latest/download/atuin-server-installer.sh | sh -``` - -Once installed, start the server with: - -```shell -atuin-server start -``` - -!!! note - Prior to v18.12.0, the server was bundled into the main `atuin` binary and started with `atuin server start`. If you are upgrading from an older release, you will need to install the new `atuin-server` binary and update any service files (systemd, docker, k8s) to invoke `atuin-server` instead of `atuin server`. See the [release notes](https://github.com/atuinsh/atuin/releases) for details. - -## Configuration - -The server's config lives at `~/.config/atuin/server.toml`, separate from the -client's config. - -It looks something like this for PostgreSQL: - -```toml -host = "0.0.0.0" -port = 8888 -open_registration = true -db_uri="postgres://user:password@hostname/database" -``` - -Alternatively, configuration can also be provided with environment variables. - -```sh -ATUIN_HOST="0.0.0.0" -ATUIN_PORT=8888 -ATUIN_OPEN_REGISTRATION=true -ATUIN_DB_URI="postgres://user:password@hostname/database" -``` - -| Parameter | Description | -| ------------------- | -------------------------------------------------------------- | -| `host` | The host to listen on (default: 127.0.0.1) | -| `port` | The TCP port to listen on (default: 8888) | -| `open_registration` | If `true`, accept new user registrations (default: false) | -| `db_uri` | A valid PostgreSQL URI, for saving history (default: false) | -| `path` | A path to prepend to all routes of the server (default: false) | - -For sqlite, use the following in your server.toml: - -```toml -db_uri="sqlite:///config/atuin.db" -``` - -Alternatively, provide the Database URI via an environment variable - -```sh -ATUIN_DB_URI="sqlite:///config/atuin.db" -``` - -These will create the database in the `/config` directory. Be sure to map a persistent volume to the `/config` directory that is writable by the atuin server. - -### TLS - -For TLS/HTTPS support, we recommend using a reverse proxy such as nginx, caddy, or traefik in front of the Atuin server. This is the standard approach for containerized applications and provides better flexibility for certificate management. - -> **Note:** The built-in `[tls]` configuration option has been removed. If you were previously using it, please migrate to a reverse proxy setup. Any existing `[tls]` sections in your config will be ignored. diff --git a/docs/docs/self-hosting/systemd.md b/docs/docs/self-hosting/systemd.md deleted file mode 100644 index c959e351..00000000 --- a/docs/docs/self-hosting/systemd.md +++ /dev/null @@ -1,71 +0,0 @@ -# Systemd - -!!! note - These instructions assume the `atuin-server` binary is on your `PATH`. Since - v18.12.0, the server is distributed as a separate binary — install it from - the [releases page](https://github.com/atuinsh/atuin/releases) (see [Server - setup](./server-setup.md) for the installer). - -First, create the service unit file -[`atuin-server.service`](https://github.com/atuinsh/atuin/raw/main/systemd/atuin-server.service) at -`/etc/systemd/system/atuin-server.service` with contents like this: - -```ini -[Unit] -Description=Start the Atuin server syncing service -After=network-online.target -Wants=network-online.target systemd-networkd-wait-online.service - -[Service] -ExecStart=atuin-server start -Restart=on-failure -User=atuin -Group=atuin - -Environment=ATUIN_CONFIG_DIR=/etc/atuin -ReadWritePaths=/etc/atuin - -# Hardening options -CapabilityBoundingSet= -AmbientCapabilities= -NoNewPrivileges=true -ProtectHome=true -ProtectSystem=strict -ProtectKernelTunables=true -ProtectKernelModules=true -ProtectControlGroups=true -PrivateTmp=true -PrivateDevices=true -LockPersonality=true - -[Install] -WantedBy=multi-user.target -``` - -This is the official Atuin service unit file which includes a lot of hardening options to increase -security. - -Next, create [`atuin-server.conf`](https://github.com/atuinsh/atuin/raw/main/systemd/atuin-server.sysusers) at -`/etc/sysusers.d/atuin-server.conf` with contents like this: - -``` -u atuin - "Atuin synchronized shell history" -``` -This file will ensure a system user is created in the proper manner. - -Afterwards, run -```sh -systemctl restart systemd-sysusers -``` -to make sure the file is read. A new `atuin-server` user should then be available. - -Now, you can attempt to run the Atuin server: -```sh -systemctl enable --now atuin-server -``` - -```sh -systemctl status atuin-server -``` - -If it started fine, it should have created the default config inside `/etc/atuin/`. diff --git a/docs/docs/self-hosting/usage.md b/docs/docs/self-hosting/usage.md deleted file mode 100644 index c5f598e8..00000000 --- a/docs/docs/self-hosting/usage.md +++ /dev/null @@ -1,14 +0,0 @@ -# Using a self hosted server - -!!! warning - If you are self hosting, we strongly suggest you stick to tagged releases, and do not follow `main` or `latest` - - Follow the GitHub releases, and please read the notes for each release. Most of the time, upgrades can occur without any manual intervention. - - We cannot guarantee that all updates will apply cleanly, and some may require some extra steps. - -## Client setup - -In order use a self hosted server with Atuin, you'll have to set up the `sync_address` in the config file at `~/.config/atuin/config.toml`. See the [config](../configuration/config.md#sync_address) page for more details on how to set the `sync_address`. - -Alternatively you can set the environment variable `ATUIN_SYNC_ADDRESS` to the correct host ie.: `ATUIN_SYNC_ADDRESS=https://api.atuin.sh`. diff --git a/docs/docs/sync-v2.md b/docs/docs/sync-v2.md deleted file mode 100644 index 8821b2f5..00000000 --- a/docs/docs/sync-v2.md +++ /dev/null @@ -1,27 +0,0 @@ -# Sync v2 - -Just installed Atuin? Don't worry about this page, everything should be set up -for you. - -If you've been using Atuin for a while, you might not be using the best sync. A -long time ago, we shipped sync v1. It was "good enough", but never intended for -the wide use it ended up getting. - -After evaluating issues and feedback from users, we developed sync v2. It -includes a whole bunch of changes that I'll save writing about for a future -blog post or deep dive, but suffice to say it's - -1. Faster -2. More reliable -3. Uses less bandwidth -4. Supports many more features -5. Recovers from issues more effectively - -There's really no reason to not use it. - -You can opt in with the following configuration - -```toml -[sync] -records = true -``` diff --git a/docs/docs/uninstall.md b/docs/docs/uninstall.md deleted file mode 100644 index a608a5c8..00000000 --- a/docs/docs/uninstall.md +++ /dev/null @@ -1,20 +0,0 @@ -# Uninstalling Atuin - -Sorry to see you go! - -If you used the Atuin installer, you can totally delete it by removing the following - -1. Delete the ~/.atuin directory -2. Delete the ~/.config/atuin directory -3. Delete the ~/.local/share/atuin directory -4. Remove the line referencing "atuin init" from your shell config - -Otherwise, uninstalling Atuin depends on your system, and how you installed it. - -EG, on macOS, you'd want to run - -``` -brew uninstall atuin -``` - -and then remove the shell integration. diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml deleted file mode 100644 index b0fb2491..00000000 --- a/docs/mkdocs.yml +++ /dev/null @@ -1,169 +0,0 @@ -site_name: Atuin CLI Docs -site_url: https://docs.atuin.sh/cli/ - -repo_name: atuinsh/atuin -repo_url: https://github.com/atuinsh/atuin -edit_uri: edit/main/docs/docs/ - -theme: - name: material - palette: - - scheme: default - primary: deep purple - accent: deep purple - toggle: - icon: material/brightness-7 - name: Switch to dark mode - - scheme: slate - primary: deep purple - accent: deep purple - toggle: - icon: material/brightness-4 - name: Switch to light mode - features: - - navigation.sections - - navigation.expand - - search.suggest - - search.highlight - - content.code.copy - - content.action.edit - - content.action.view - -# NOTE: to enable ToC and heading anchor links in local (non-multirepo) development, -# comment out the `multirepo` plugin and all its settings. -# Note that this changes the top-level directory when developing locally -# from `/cli/CLI/` to `/cli/. - -plugins: - - search - - multirepo: - imported_repo: true - url: https://github.com/atuinsh/docs - section_name: CLI - paths: ["mkdocs.yml", "docs/index.md", "docs/stylesheets/*"] - yml_file: mkdocs.yml - branch: mkt/docs-migration - - llmstxt: - base_url: https://docs.atuin.sh/cli - full_output: llms-full.txt - markdown_description: | - Atuin replaces your shell's built-in history with a SQLite database, adding context - (cwd, exit code, duration, hostname) and optionally syncing across machines with - end-to-end encryption. These docs cover the CLI tool - installation, configuration, - usage, self-hosting, and AI features. - sections: - Overview: - - index.md: Getting started with Atuin - quickstart, supported shells, and links. - Guide: - - guide/getting-started.md: First steps - install, import history, and start using Atuin. - - guide/installation.md: Install via script, Homebrew, WinGet, Cargo, Nix, or from source. - - guide/sync.md: Register an account and set up end-to-end encrypted history sync. - - guide/import.md: Import existing shell history from bash, zsh, fish, and others. - - guide/basic-usage.md: What Atuin records, how to use the TUI, and common config tweaks. - - guide/advanced-usage.md: Filter modes (global, host, session, directory, workspace) and search modes (fuzzy, full-text, skim). - - guide/shell-integration.md: How shell hooks work, environment variables, embedded terminals, and excluding commands. - - guide/agent-hooks.md: Capture commands from AI coding agents (Claude Code, Codex, pi) and filter by author. - - guide/delete-history.md: Delete single entries, bulk delete by query, remove duplicates, or wipe everything. - - guide/dotfiles.md: Sync shell aliases and environment variables across machines. - - guide/theming.md: Customize the TUI with color themes. - Configuration: - - configuration/config.md: Complete reference for ~/.config/atuin/config.toml - all settings with defaults and examples. - - configuration/key-binding.md: Custom up-arrow filter mode, disable up-arrow or ctrl-r, vim mode. - - configuration/advanced-key-binding.md: Full keymap customization with emacs, vim-normal, vim-insert, and inspector modes. - Reference: - - reference/config.md: The `atuin config` command - get, set, list, and resolve configuration values. - - reference/daemon.md: Background daemon for faster writes, auto-sync, and in-memory fuzzy search. - - reference/doctor.md: Diagnose common problems and dump system info for bug reports. - - reference/gen-completions.md: Generate shell completions for bash, fish, zsh, nushell, powershell, elvish. - - reference/hex.md: The old name for `atuin pty-proxy` - - reference/pty-proxy.md: Experimental PTY proxy with popup rendering over existing terminal output. - - reference/import.md: Import history from bash, fish, zsh, replxx, mcfly, resh, and xonsh. - - reference/info.md: Show config file paths, env vars, and version info. - - reference/list.md: List history entries with formatting, filtering by cwd/session, and custom output templates. - - reference/prune.md: Delete entries matching history_filter config (useful after updating filters). - - reference/search.md: Search history with wildcards, filters (cwd, exit code, before/after), and delete mode. - - reference/stats.md: Compute stats for a time period - most used command, command count, unique commands. - - reference/sync.md: Sync commands - register, login, manual sync, and account management. - Self Hosting: - - self-hosting/server-setup.md: Run your own Atuin sync server with PostgreSQL or SQLite. - - self-hosting/usage.md: Configure the client to use a self-hosted server. - - self-hosting/docker.md: Deploy with Docker or Docker Compose. - - self-hosting/kubernetes.md: Full Kubernetes deployment with Postgres, secrets, and ingress. - - self-hosting/systemd.md: Systemd service unit with hardening options. - AI: - - ai/introduction.md: Atuin AI - command generation and lookup via LLM from your terminal. - - ai/settings.md: AI configuration in config.toml - enabled, endpoint, session timeout. - - ai/user-context.md: Send additional context to the LLM via TERMINAL.md files and dynamic shell substitution. - - ai/skills.md: Reusable instruction sets (skills) for Atuin AI - playbooks, conventions, workflows. - - ai/tools-permissions.md: Tools the AI can use (shell, filesystem) and permission files to control access. - Misc: - - known-issues.md: Known issues with ZFS and network filesystems. - - integrations.md: Integrations with zsh-autosuggestions, zsh-vi-mode, ble.sh, and mcfly. - - faq.md: Frequently asked questions - IDE terminals, history filtering, up-arrow, uninstalling. - - uninstall.md: How to uninstall Atuin and remove all data. - - sync-v2.md: Upgrading from sync v1 to v2 - faster, more reliable, less bandwidth. - -markdown_extensions: - - pymdownx.highlight: - anchor_linenums: true - - pymdownx.superfences - - pymdownx.tabbed: - alternate_style: true - - admonition - - pymdownx.details - - attr_list - - md_in_html - - tables - - pymdownx.keys - - pymdownx.emoji: - emoji_index: !!python/name:material.extensions.emoji.twemoji - emoji_generator: !!python/name:material.extensions.emoji.to_svg - -nav: - - Home: index.md - - Guide: - - Getting Started: guide/getting-started.md - - Installation: guide/installation.md - - Setting up sync: guide/sync.md - - Import existing history: guide/import.md - - Basic usage: guide/basic-usage.md - - Advanced usage: guide/advanced-usage.md - - Shell Integration: guide/shell-integration.md - - AI Agent Hooks: guide/agent-hooks.md - - Deleting history: guide/delete-history.md - - Syncing dotfiles: guide/dotfiles.md - - Theming: guide/theming.md - - Configuration: - - Config: configuration/config.md - - Key Binding: configuration/key-binding.md - - Advanced Key Binding: configuration/advanced-key-binding.md - - Reference: - - config: reference/config.md - - daemon: reference/daemon.md - - doctor: reference/doctor.md - - gen-completions: reference/gen-completions.md - - pty-proxy: reference/pty-proxy.md - - import: reference/import.md - - info: reference/info.md - - history list: reference/list.md - - history prune: reference/prune.md - - search: reference/search.md - - stats: reference/stats.md - - sync: reference/sync.md - - Self Hosting: - - Server Setup: self-hosting/server-setup.md - - Usage: self-hosting/usage.md - - Docker: self-hosting/docker.md - - Kubernetes: self-hosting/kubernetes.md - - Systemd: self-hosting/systemd.md - - AI: - - Introduction: ai/introduction.md - - Settings: ai/settings.md - - "User-Defined Context": ai/user-context.md - - Skills: ai/skills.md - - "Tools & Permissions": ai/tools-permissions.md - - Known Issues: known-issues.md - - Integrations: integrations.md - - FAQ: faq.md - - Uninstall: uninstall.md - - Sync v2: sync-v2.md diff --git a/docs/pyproject.toml b/docs/pyproject.toml deleted file mode 100644 index bb6009d0..00000000 --- a/docs/pyproject.toml +++ /dev/null @@ -1,21 +0,0 @@ -[project] -name = "atuin-cli-docs" -version = "1.0.0" -description = "Atuin CLI documentation" -requires-python = ">=3.11" -dependencies = [ - "mkdocs-material>=9.5", - "mkdocs-multirepo-plugin @ git+https://github.com/atuinsh/mkdocs-multirepo-plugin@mkt/imported_repo", - "mkdocs-git-revision-date-localized-plugin>=1.2", - "mkdocs-glightbox>=0.4", - "mkdocs-redirects>=1.2.2", - "mkdocs-llmstxt>=0.5", -] - -[tool.uv] -override-dependencies = [ - "click==8.2.1", -] - -[dependency-groups] -dev = [] diff --git a/docs/uv.lock b/docs/uv.lock deleted file mode 100644 index ec92abfc..00000000 --- a/docs/uv.lock +++ /dev/null @@ -1,860 +0,0 @@ -version = 1 -revision = 3 -requires-python = ">=3.11" - -[manifest] -overrides = [{ name = "click", specifier = "==8.2.1" }] - -[[package]] -name = "atuin-cli-docs" -version = "1.0.0" -source = { virtual = "." } -dependencies = [ - { name = "mkdocs-git-revision-date-localized-plugin" }, - { name = "mkdocs-glightbox" }, - { name = "mkdocs-llmstxt" }, - { name = "mkdocs-material" }, - { name = "mkdocs-multirepo-plugin" }, - { name = "mkdocs-redirects" }, -] - -[package.metadata] -requires-dist = [ - { name = "mkdocs-git-revision-date-localized-plugin", specifier = ">=1.2" }, - { name = "mkdocs-glightbox", specifier = ">=0.4" }, - { name = "mkdocs-llmstxt", specifier = ">=0.5" }, - { name = "mkdocs-material", specifier = ">=9.5" }, - { name = "mkdocs-multirepo-plugin", git = "https://github.com/atuinsh/mkdocs-multirepo-plugin?rev=mkt%2Fimported_repo" }, - { name = "mkdocs-redirects", specifier = ">=1.2.2" }, -] - -[package.metadata.requires-dev] -dev = [] - -[[package]] -name = "babel" -version = "2.17.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7d/6b/d52e42361e1aa00709585ecc30b3f9684b3ab62530771402248b1b1d6240/babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d", size = 9951852, upload-time = "2025-02-01T15:17:41.026Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2", size = 10182537, upload-time = "2025-02-01T15:17:37.39Z" }, -] - -[[package]] -name = "backrefs" -version = "6.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/86/e3/bb3a439d5cb255c4774724810ad8073830fac9c9dee123555820c1bcc806/backrefs-6.1.tar.gz", hash = "sha256:3bba1749aafe1db9b915f00e0dd166cba613b6f788ffd63060ac3485dc9be231", size = 7011962, upload-time = "2025-11-15T14:52:08.323Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3b/ee/c216d52f58ea75b5e1841022bbae24438b19834a29b163cb32aa3a2a7c6e/backrefs-6.1-py310-none-any.whl", hash = "sha256:2a2ccb96302337ce61ee4717ceacfbf26ba4efb1d55af86564b8bbaeda39cac1", size = 381059, upload-time = "2025-11-15T14:51:59.758Z" }, - { url = "https://files.pythonhosted.org/packages/e6/9a/8da246d988ded941da96c7ed945d63e94a445637eaad985a0ed88787cb89/backrefs-6.1-py311-none-any.whl", hash = "sha256:e82bba3875ee4430f4de4b6db19429a27275d95a5f3773c57e9e18abc23fd2b7", size = 392854, upload-time = "2025-11-15T14:52:01.194Z" }, - { url = "https://files.pythonhosted.org/packages/37/c9/fd117a6f9300c62bbc33bc337fd2b3c6bfe28b6e9701de336b52d7a797ad/backrefs-6.1-py312-none-any.whl", hash = "sha256:c64698c8d2269343d88947c0735cb4b78745bd3ba590e10313fbf3f78c34da5a", size = 398770, upload-time = "2025-11-15T14:52:02.584Z" }, - { url = "https://files.pythonhosted.org/packages/eb/95/7118e935b0b0bd3f94dfec2d852fd4e4f4f9757bdb49850519acd245cd3a/backrefs-6.1-py313-none-any.whl", hash = "sha256:4c9d3dc1e2e558965202c012304f33d4e0e477e1c103663fd2c3cc9bb18b0d05", size = 400726, upload-time = "2025-11-15T14:52:04.093Z" }, - { url = "https://files.pythonhosted.org/packages/1d/72/6296bad135bfafd3254ae3648cd152980a424bd6fed64a101af00cc7ba31/backrefs-6.1-py314-none-any.whl", hash = "sha256:13eafbc9ccd5222e9c1f0bec563e6d2a6d21514962f11e7fc79872fd56cbc853", size = 412584, upload-time = "2025-11-15T14:52:05.233Z" }, - { url = "https://files.pythonhosted.org/packages/02/e3/a4fa1946722c4c7b063cc25043a12d9ce9b4323777f89643be74cef2993c/backrefs-6.1-py39-none-any.whl", hash = "sha256:a9e99b8a4867852cad177a6430e31b0f6e495d65f8c6c134b68c14c3c95bf4b0", size = 381058, upload-time = "2025-11-15T14:52:06.698Z" }, -] - -[[package]] -name = "beautifulsoup4" -version = "4.14.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "soupsieve" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/c3/b0/1c6a16426d389813b48d95e26898aff79abbde42ad353958ad95cc8c9b21/beautifulsoup4-4.14.3.tar.gz", hash = "sha256:6292b1c5186d356bba669ef9f7f051757099565ad9ada5dd630bd9de5fa7fb86", size = 627737, upload-time = "2025-11-30T15:08:26.084Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl", hash = "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb", size = 107721, upload-time = "2025-11-30T15:08:24.087Z" }, -] - -[[package]] -name = "certifi" -version = "2025.11.12" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a2/8c/58f469717fa48465e4a50c014a0400602d3c437d7c0c468e17ada824da3a/certifi-2025.11.12.tar.gz", hash = "sha256:d8ab5478f2ecd78af242878415affce761ca6bc54a22a27e026d7c25357c3316", size = 160538, upload-time = "2025-11-12T02:54:51.517Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl", hash = "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b", size = 159438, upload-time = "2025-11-12T02:54:49.735Z" }, -] - -[[package]] -name = "charset-normalizer" -version = "3.4.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ed/27/c6491ff4954e58a10f69ad90aca8a1b6fe9c5d3c6f380907af3c37435b59/charset_normalizer-3.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8", size = 206988, upload-time = "2025-10-14T04:40:33.79Z" }, - { url = "https://files.pythonhosted.org/packages/94/59/2e87300fe67ab820b5428580a53cad894272dbb97f38a7a814a2a1ac1011/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0", size = 147324, upload-time = "2025-10-14T04:40:34.961Z" }, - { url = "https://files.pythonhosted.org/packages/07/fb/0cf61dc84b2b088391830f6274cb57c82e4da8bbc2efeac8c025edb88772/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3", size = 142742, upload-time = "2025-10-14T04:40:36.105Z" }, - { url = "https://files.pythonhosted.org/packages/62/8b/171935adf2312cd745d290ed93cf16cf0dfe320863ab7cbeeae1dcd6535f/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc", size = 160863, upload-time = "2025-10-14T04:40:37.188Z" }, - { url = "https://files.pythonhosted.org/packages/09/73/ad875b192bda14f2173bfc1bc9a55e009808484a4b256748d931b6948442/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897", size = 157837, upload-time = "2025-10-14T04:40:38.435Z" }, - { url = "https://files.pythonhosted.org/packages/6d/fc/de9cce525b2c5b94b47c70a4b4fb19f871b24995c728e957ee68ab1671ea/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381", size = 151550, upload-time = "2025-10-14T04:40:40.053Z" }, - { url = "https://files.pythonhosted.org/packages/55/c2/43edd615fdfba8c6f2dfbd459b25a6b3b551f24ea21981e23fb768503ce1/charset_normalizer-3.4.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815", size = 149162, upload-time = "2025-10-14T04:40:41.163Z" }, - { url = "https://files.pythonhosted.org/packages/03/86/bde4ad8b4d0e9429a4e82c1e8f5c659993a9a863ad62c7df05cf7b678d75/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0", size = 150019, upload-time = "2025-10-14T04:40:42.276Z" }, - { url = "https://files.pythonhosted.org/packages/1f/86/a151eb2af293a7e7bac3a739b81072585ce36ccfb4493039f49f1d3cae8c/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161", size = 143310, upload-time = "2025-10-14T04:40:43.439Z" }, - { url = "https://files.pythonhosted.org/packages/b5/fe/43dae6144a7e07b87478fdfc4dbe9efd5defb0e7ec29f5f58a55aeef7bf7/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4", size = 162022, upload-time = "2025-10-14T04:40:44.547Z" }, - { url = "https://files.pythonhosted.org/packages/80/e6/7aab83774f5d2bca81f42ac58d04caf44f0cc2b65fc6db2b3b2e8a05f3b3/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89", size = 149383, upload-time = "2025-10-14T04:40:46.018Z" }, - { url = "https://files.pythonhosted.org/packages/4f/e8/b289173b4edae05c0dde07f69f8db476a0b511eac556dfe0d6bda3c43384/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569", size = 159098, upload-time = "2025-10-14T04:40:47.081Z" }, - { url = "https://files.pythonhosted.org/packages/d8/df/fe699727754cae3f8478493c7f45f777b17c3ef0600e28abfec8619eb49c/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224", size = 152991, upload-time = "2025-10-14T04:40:48.246Z" }, - { url = "https://files.pythonhosted.org/packages/1a/86/584869fe4ddb6ffa3bd9f491b87a01568797fb9bd8933f557dba9771beaf/charset_normalizer-3.4.4-cp311-cp311-win32.whl", hash = "sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a", size = 99456, upload-time = "2025-10-14T04:40:49.376Z" }, - { url = "https://files.pythonhosted.org/packages/65/f6/62fdd5feb60530f50f7e38b4f6a1d5203f4d16ff4f9f0952962c044e919a/charset_normalizer-3.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016", size = 106978, upload-time = "2025-10-14T04:40:50.844Z" }, - { url = "https://files.pythonhosted.org/packages/7a/9d/0710916e6c82948b3be62d9d398cb4fcf4e97b56d6a6aeccd66c4b2f2bd5/charset_normalizer-3.4.4-cp311-cp311-win_arm64.whl", hash = "sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1", size = 99969, upload-time = "2025-10-14T04:40:52.272Z" }, - { url = "https://files.pythonhosted.org/packages/f3/85/1637cd4af66fa687396e757dec650f28025f2a2f5a5531a3208dc0ec43f2/charset_normalizer-3.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394", size = 208425, upload-time = "2025-10-14T04:40:53.353Z" }, - { url = "https://files.pythonhosted.org/packages/9d/6a/04130023fef2a0d9c62d0bae2649b69f7b7d8d24ea5536feef50551029df/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25", size = 148162, upload-time = "2025-10-14T04:40:54.558Z" }, - { url = "https://files.pythonhosted.org/packages/78/29/62328d79aa60da22c9e0b9a66539feae06ca0f5a4171ac4f7dc285b83688/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef", size = 144558, upload-time = "2025-10-14T04:40:55.677Z" }, - { url = "https://files.pythonhosted.org/packages/86/bb/b32194a4bf15b88403537c2e120b817c61cd4ecffa9b6876e941c3ee38fe/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d", size = 161497, upload-time = "2025-10-14T04:40:57.217Z" }, - { url = "https://files.pythonhosted.org/packages/19/89/a54c82b253d5b9b111dc74aca196ba5ccfcca8242d0fb64146d4d3183ff1/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8", size = 159240, upload-time = "2025-10-14T04:40:58.358Z" }, - { url = "https://files.pythonhosted.org/packages/c0/10/d20b513afe03acc89ec33948320a5544d31f21b05368436d580dec4e234d/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86", size = 153471, upload-time = "2025-10-14T04:40:59.468Z" }, - { url = "https://files.pythonhosted.org/packages/61/fa/fbf177b55bdd727010f9c0a3c49eefa1d10f960e5f09d1d887bf93c2e698/charset_normalizer-3.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a", size = 150864, upload-time = "2025-10-14T04:41:00.623Z" }, - { url = "https://files.pythonhosted.org/packages/05/12/9fbc6a4d39c0198adeebbde20b619790e9236557ca59fc40e0e3cebe6f40/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f", size = 150647, upload-time = "2025-10-14T04:41:01.754Z" }, - { url = "https://files.pythonhosted.org/packages/ad/1f/6a9a593d52e3e8c5d2b167daf8c6b968808efb57ef4c210acb907c365bc4/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc", size = 145110, upload-time = "2025-10-14T04:41:03.231Z" }, - { url = "https://files.pythonhosted.org/packages/30/42/9a52c609e72471b0fc54386dc63c3781a387bb4fe61c20231a4ebcd58bdd/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf", size = 162839, upload-time = "2025-10-14T04:41:04.715Z" }, - { url = "https://files.pythonhosted.org/packages/c4/5b/c0682bbf9f11597073052628ddd38344a3d673fda35a36773f7d19344b23/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15", size = 150667, upload-time = "2025-10-14T04:41:05.827Z" }, - { url = "https://files.pythonhosted.org/packages/e4/24/a41afeab6f990cf2daf6cb8c67419b63b48cf518e4f56022230840c9bfb2/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9", size = 160535, upload-time = "2025-10-14T04:41:06.938Z" }, - { url = "https://files.pythonhosted.org/packages/2a/e5/6a4ce77ed243c4a50a1fecca6aaaab419628c818a49434be428fe24c9957/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0", size = 154816, upload-time = "2025-10-14T04:41:08.101Z" }, - { url = "https://files.pythonhosted.org/packages/a8/ef/89297262b8092b312d29cdb2517cb1237e51db8ecef2e9af5edbe7b683b1/charset_normalizer-3.4.4-cp312-cp312-win32.whl", hash = "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26", size = 99694, upload-time = "2025-10-14T04:41:09.23Z" }, - { url = "https://files.pythonhosted.org/packages/3d/2d/1e5ed9dd3b3803994c155cd9aacb60c82c331bad84daf75bcb9c91b3295e/charset_normalizer-3.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525", size = 107131, upload-time = "2025-10-14T04:41:10.467Z" }, - { url = "https://files.pythonhosted.org/packages/d0/d9/0ed4c7098a861482a7b6a95603edce4c0d9db2311af23da1fb2b75ec26fc/charset_normalizer-3.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3", size = 100390, upload-time = "2025-10-14T04:41:11.915Z" }, - { url = "https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", size = 208091, upload-time = "2025-10-14T04:41:13.346Z" }, - { url = "https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", size = 147936, upload-time = "2025-10-14T04:41:14.461Z" }, - { url = "https://files.pythonhosted.org/packages/89/c5/adb8c8b3d6625bef6d88b251bbb0d95f8205831b987631ab0c8bb5d937c2/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", size = 144180, upload-time = "2025-10-14T04:41:15.588Z" }, - { url = "https://files.pythonhosted.org/packages/91/ed/9706e4070682d1cc219050b6048bfd293ccf67b3d4f5a4f39207453d4b99/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328", size = 161346, upload-time = "2025-10-14T04:41:16.738Z" }, - { url = "https://files.pythonhosted.org/packages/d5/0d/031f0d95e4972901a2f6f09ef055751805ff541511dc1252ba3ca1f80cf5/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede", size = 158874, upload-time = "2025-10-14T04:41:17.923Z" }, - { url = "https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894", size = 153076, upload-time = "2025-10-14T04:41:19.106Z" }, - { url = "https://files.pythonhosted.org/packages/75/1e/5ff781ddf5260e387d6419959ee89ef13878229732732ee73cdae01800f2/charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1", size = 150601, upload-time = "2025-10-14T04:41:20.245Z" }, - { url = "https://files.pythonhosted.org/packages/d7/57/71be810965493d3510a6ca79b90c19e48696fb1ff964da319334b12677f0/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490", size = 150376, upload-time = "2025-10-14T04:41:21.398Z" }, - { url = "https://files.pythonhosted.org/packages/e5/d5/c3d057a78c181d007014feb7e9f2e65905a6c4ef182c0ddf0de2924edd65/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44", size = 144825, upload-time = "2025-10-14T04:41:22.583Z" }, - { url = "https://files.pythonhosted.org/packages/e6/8c/d0406294828d4976f275ffbe66f00266c4b3136b7506941d87c00cab5272/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133", size = 162583, upload-time = "2025-10-14T04:41:23.754Z" }, - { url = "https://files.pythonhosted.org/packages/d7/24/e2aa1f18c8f15c4c0e932d9287b8609dd30ad56dbe41d926bd846e22fb8d/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3", size = 150366, upload-time = "2025-10-14T04:41:25.27Z" }, - { url = "https://files.pythonhosted.org/packages/e4/5b/1e6160c7739aad1e2df054300cc618b06bf784a7a164b0f238360721ab86/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e", size = 160300, upload-time = "2025-10-14T04:41:26.725Z" }, - { url = "https://files.pythonhosted.org/packages/7a/10/f882167cd207fbdd743e55534d5d9620e095089d176d55cb22d5322f2afd/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc", size = 154465, upload-time = "2025-10-14T04:41:28.322Z" }, - { url = "https://files.pythonhosted.org/packages/89/66/c7a9e1b7429be72123441bfdbaf2bc13faab3f90b933f664db506dea5915/charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac", size = 99404, upload-time = "2025-10-14T04:41:29.95Z" }, - { url = "https://files.pythonhosted.org/packages/c4/26/b9924fa27db384bdcd97ab83b4f0a8058d96ad9626ead570674d5e737d90/charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14", size = 107092, upload-time = "2025-10-14T04:41:31.188Z" }, - { url = "https://files.pythonhosted.org/packages/af/8f/3ed4bfa0c0c72a7ca17f0380cd9e4dd842b09f664e780c13cff1dcf2ef1b/charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2", size = 100408, upload-time = "2025-10-14T04:41:32.624Z" }, - { url = "https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd", size = 207746, upload-time = "2025-10-14T04:41:33.773Z" }, - { url = "https://files.pythonhosted.org/packages/10/9a/97c8d48ef10d6cd4fcead2415523221624bf58bcf68a802721a6bc807c8f/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb", size = 147889, upload-time = "2025-10-14T04:41:34.897Z" }, - { url = "https://files.pythonhosted.org/packages/10/bf/979224a919a1b606c82bd2c5fa49b5c6d5727aa47b4312bb27b1734f53cd/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e", size = 143641, upload-time = "2025-10-14T04:41:36.116Z" }, - { url = "https://files.pythonhosted.org/packages/ba/33/0ad65587441fc730dc7bd90e9716b30b4702dc7b617e6ba4997dc8651495/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14", size = 160779, upload-time = "2025-10-14T04:41:37.229Z" }, - { url = "https://files.pythonhosted.org/packages/67/ed/331d6b249259ee71ddea93f6f2f0a56cfebd46938bde6fcc6f7b9a3d0e09/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191", size = 159035, upload-time = "2025-10-14T04:41:38.368Z" }, - { url = "https://files.pythonhosted.org/packages/67/ff/f6b948ca32e4f2a4576aa129d8bed61f2e0543bf9f5f2b7fc3758ed005c9/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838", size = 152542, upload-time = "2025-10-14T04:41:39.862Z" }, - { url = "https://files.pythonhosted.org/packages/16/85/276033dcbcc369eb176594de22728541a925b2632f9716428c851b149e83/charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6", size = 149524, upload-time = "2025-10-14T04:41:41.319Z" }, - { url = "https://files.pythonhosted.org/packages/9e/f2/6a2a1f722b6aba37050e626530a46a68f74e63683947a8acff92569f979a/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e", size = 150395, upload-time = "2025-10-14T04:41:42.539Z" }, - { url = "https://files.pythonhosted.org/packages/60/bb/2186cb2f2bbaea6338cad15ce23a67f9b0672929744381e28b0592676824/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c", size = 143680, upload-time = "2025-10-14T04:41:43.661Z" }, - { url = "https://files.pythonhosted.org/packages/7d/a5/bf6f13b772fbb2a90360eb620d52ed8f796f3c5caee8398c3b2eb7b1c60d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090", size = 162045, upload-time = "2025-10-14T04:41:44.821Z" }, - { url = "https://files.pythonhosted.org/packages/df/c5/d1be898bf0dc3ef9030c3825e5d3b83f2c528d207d246cbabe245966808d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152", size = 149687, upload-time = "2025-10-14T04:41:46.442Z" }, - { url = "https://files.pythonhosted.org/packages/a5/42/90c1f7b9341eef50c8a1cb3f098ac43b0508413f33affd762855f67a410e/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828", size = 160014, upload-time = "2025-10-14T04:41:47.631Z" }, - { url = "https://files.pythonhosted.org/packages/76/be/4d3ee471e8145d12795ab655ece37baed0929462a86e72372fd25859047c/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec", size = 154044, upload-time = "2025-10-14T04:41:48.81Z" }, - { url = "https://files.pythonhosted.org/packages/b0/6f/8f7af07237c34a1defe7defc565a9bc1807762f672c0fde711a4b22bf9c0/charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9", size = 99940, upload-time = "2025-10-14T04:41:49.946Z" }, - { url = "https://files.pythonhosted.org/packages/4b/51/8ade005e5ca5b0d80fb4aff72a3775b325bdc3d27408c8113811a7cbe640/charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c", size = 107104, upload-time = "2025-10-14T04:41:51.051Z" }, - { url = "https://files.pythonhosted.org/packages/da/5f/6b8f83a55bb8278772c5ae54a577f3099025f9ade59d0136ac24a0df4bde/charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2", size = 100743, upload-time = "2025-10-14T04:41:52.122Z" }, - { url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" }, -] - -[[package]] -name = "click" -version = "8.2.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/60/6c/8ca2efa64cf75a977a0d7fac081354553ebe483345c734fb6b6515d96bbc/click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", size = 286342, upload-time = "2025-05-20T23:19:49.832Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/85/32/10bb5764d90a8eee674e9dc6f4db6a0ab47c8c4d0d83c27f7c39ac415a4d/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b", size = 102215, upload-time = "2025-05-20T23:19:47.796Z" }, -] - -[[package]] -name = "colorama" -version = "0.4.6" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, -] - -[[package]] -name = "dacite" -version = "1.9.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/55/a0/7ca79796e799a3e782045d29bf052b5cde7439a2bbb17f15ff44f7aacc63/dacite-1.9.2.tar.gz", hash = "sha256:6ccc3b299727c7aa17582f0021f6ae14d5de47c7227932c47fec4cdfefd26f09", size = 22420, upload-time = "2025-02-05T09:27:29.757Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/94/35/386550fd60316d1e37eccdda609b074113298f23cef5bddb2049823fe666/dacite-1.9.2-py3-none-any.whl", hash = "sha256:053f7c3f5128ca2e9aceb66892b1a3c8936d02c686e707bee96e19deef4bc4a0", size = 16600, upload-time = "2025-02-05T09:27:24.345Z" }, -] - -[[package]] -name = "ghp-import" -version = "2.1.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "python-dateutil" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/d9/29/d40217cbe2f6b1359e00c6c307bb3fc876ba74068cbab3dde77f03ca0dc4/ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343", size = 10943, upload-time = "2022-05-02T15:47:16.11Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619", size = 11034, upload-time = "2022-05-02T15:47:14.552Z" }, -] - -[[package]] -name = "gitdb" -version = "4.0.12" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "smmap" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/72/94/63b0fc47eb32792c7ba1fe1b694daec9a63620db1e313033d18140c2320a/gitdb-4.0.12.tar.gz", hash = "sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571", size = 394684, upload-time = "2025-01-02T07:20:46.413Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl", hash = "sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf", size = 62794, upload-time = "2025-01-02T07:20:43.624Z" }, -] - -[[package]] -name = "gitpython" -version = "3.1.45" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "gitdb" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/9a/c8/dd58967d119baab745caec2f9d853297cec1989ec1d63f677d3880632b88/gitpython-3.1.45.tar.gz", hash = "sha256:85b0ee964ceddf211c41b9f27a49086010a190fd8132a24e21f362a4b36a791c", size = 215076, upload-time = "2025-07-24T03:45:54.871Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/01/61/d4b89fec821f72385526e1b9d9a3a0385dda4a72b206d28049e2c7cd39b8/gitpython-3.1.45-py3-none-any.whl", hash = "sha256:8908cb2e02fb3b93b7eb0f2827125cb699869470432cc885f019b8fd0fccff77", size = 208168, upload-time = "2025-07-24T03:45:52.517Z" }, -] - -[[package]] -name = "idna" -version = "3.11" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, -] - -[[package]] -name = "jinja2" -version = "3.1.6" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "markupsafe" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, -] - -[[package]] -name = "markdown" -version = "3.10" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7d/ab/7dd27d9d863b3376fcf23a5a13cb5d024aed1db46f963f1b5735ae43b3be/markdown-3.10.tar.gz", hash = "sha256:37062d4f2aa4b2b6b32aefb80faa300f82cc790cb949a35b8caede34f2b68c0e", size = 364931, upload-time = "2025-11-03T19:51:15.007Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/70/81/54e3ce63502cd085a0c556652a4e1b919c45a446bd1e5300e10c44c8c521/markdown-3.10-py3-none-any.whl", hash = "sha256:b5b99d6951e2e4948d939255596523444c0e677c669700b1d17aa4a8a464cb7c", size = 107678, upload-time = "2025-11-03T19:51:13.887Z" }, -] - -[[package]] -name = "markdown-it-py" -version = "3.0.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "mdurl" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596, upload-time = "2023-06-03T06:41:14.443Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528, upload-time = "2023-06-03T06:41:11.019Z" }, -] - -[[package]] -name = "markdownify" -version = "1.2.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "beautifulsoup4" }, - { name = "six" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/3f/bc/c8c8eea5335341306b0fa7e1cb33c5e1c8d24ef70ddd684da65f41c49c92/markdownify-1.2.2.tar.gz", hash = "sha256:b274f1b5943180b031b699b199cbaeb1e2ac938b75851849a31fd0c3d6603d09", size = 18816, upload-time = "2025-11-16T19:21:18.565Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/43/ce/f1e3e9d959db134cedf06825fae8d5b294bd368aacdd0831a3975b7c4d55/markdownify-1.2.2-py3-none-any.whl", hash = "sha256:3f02d3cc52714084d6e589f70397b6fc9f2f3a8531481bf35e8cc39f975e186a", size = 15724, upload-time = "2025-11-16T19:21:17.622Z" }, -] - -[[package]] -name = "markupsafe" -version = "3.0.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/08/db/fefacb2136439fc8dd20e797950e749aa1f4997ed584c62cfb8ef7c2be0e/markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad", size = 11631, upload-time = "2025-09-27T18:36:18.185Z" }, - { url = "https://files.pythonhosted.org/packages/e1/2e/5898933336b61975ce9dc04decbc0a7f2fee78c30353c5efba7f2d6ff27a/markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a", size = 12058, upload-time = "2025-09-27T18:36:19.444Z" }, - { url = "https://files.pythonhosted.org/packages/1d/09/adf2df3699d87d1d8184038df46a9c80d78c0148492323f4693df54e17bb/markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50", size = 24287, upload-time = "2025-09-27T18:36:20.768Z" }, - { url = "https://files.pythonhosted.org/packages/30/ac/0273f6fcb5f42e314c6d8cd99effae6a5354604d461b8d392b5ec9530a54/markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf", size = 22940, upload-time = "2025-09-27T18:36:22.249Z" }, - { url = "https://files.pythonhosted.org/packages/19/ae/31c1be199ef767124c042c6c3e904da327a2f7f0cd63a0337e1eca2967a8/markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f", size = 21887, upload-time = "2025-09-27T18:36:23.535Z" }, - { url = "https://files.pythonhosted.org/packages/b2/76/7edcab99d5349a4532a459e1fe64f0b0467a3365056ae550d3bcf3f79e1e/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a", size = 23692, upload-time = "2025-09-27T18:36:24.823Z" }, - { url = "https://files.pythonhosted.org/packages/a4/28/6e74cdd26d7514849143d69f0bf2399f929c37dc2b31e6829fd2045b2765/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115", size = 21471, upload-time = "2025-09-27T18:36:25.95Z" }, - { url = "https://files.pythonhosted.org/packages/62/7e/a145f36a5c2945673e590850a6f8014318d5577ed7e5920a4b3448e0865d/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a", size = 22923, upload-time = "2025-09-27T18:36:27.109Z" }, - { url = "https://files.pythonhosted.org/packages/0f/62/d9c46a7f5c9adbeeeda52f5b8d802e1094e9717705a645efc71b0913a0a8/markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19", size = 14572, upload-time = "2025-09-27T18:36:28.045Z" }, - { url = "https://files.pythonhosted.org/packages/83/8a/4414c03d3f891739326e1783338e48fb49781cc915b2e0ee052aa490d586/markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01", size = 15077, upload-time = "2025-09-27T18:36:29.025Z" }, - { url = "https://files.pythonhosted.org/packages/35/73/893072b42e6862f319b5207adc9ae06070f095b358655f077f69a35601f0/markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c", size = 13876, upload-time = "2025-09-27T18:36:29.954Z" }, - { url = "https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615, upload-time = "2025-09-27T18:36:30.854Z" }, - { url = "https://files.pythonhosted.org/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020, upload-time = "2025-09-27T18:36:31.971Z" }, - { url = "https://files.pythonhosted.org/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332, upload-time = "2025-09-27T18:36:32.813Z" }, - { url = "https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947, upload-time = "2025-09-27T18:36:33.86Z" }, - { url = "https://files.pythonhosted.org/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962, upload-time = "2025-09-27T18:36:35.099Z" }, - { url = "https://files.pythonhosted.org/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760, upload-time = "2025-09-27T18:36:36.001Z" }, - { url = "https://files.pythonhosted.org/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529, upload-time = "2025-09-27T18:36:36.906Z" }, - { url = "https://files.pythonhosted.org/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015, upload-time = "2025-09-27T18:36:37.868Z" }, - { url = "https://files.pythonhosted.org/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540, upload-time = "2025-09-27T18:36:38.761Z" }, - { url = "https://files.pythonhosted.org/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105, upload-time = "2025-09-27T18:36:39.701Z" }, - { url = "https://files.pythonhosted.org/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906, upload-time = "2025-09-27T18:36:40.689Z" }, - { url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" }, - { url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" }, - { url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" }, - { url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" }, - { url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" }, - { url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" }, - { url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" }, - { url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" }, - { url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" }, - { url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" }, - { url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" }, - { url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" }, - { url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" }, - { url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" }, - { url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" }, - { url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" }, - { url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" }, - { url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" }, - { url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" }, - { url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" }, - { url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" }, - { url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" }, - { url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" }, - { url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" }, - { url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" }, - { url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005, upload-time = "2025-09-27T18:37:10.58Z" }, - { url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048, upload-time = "2025-09-27T18:37:11.547Z" }, - { url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821, upload-time = "2025-09-27T18:37:12.48Z" }, - { url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606, upload-time = "2025-09-27T18:37:13.485Z" }, - { url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043, upload-time = "2025-09-27T18:37:14.408Z" }, - { url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747, upload-time = "2025-09-27T18:37:15.36Z" }, - { url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341, upload-time = "2025-09-27T18:37:16.496Z" }, - { url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073, upload-time = "2025-09-27T18:37:17.476Z" }, - { url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661, upload-time = "2025-09-27T18:37:18.453Z" }, - { url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069, upload-time = "2025-09-27T18:37:19.332Z" }, - { url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670, upload-time = "2025-09-27T18:37:20.245Z" }, - { url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598, upload-time = "2025-09-27T18:37:21.177Z" }, - { url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261, upload-time = "2025-09-27T18:37:22.167Z" }, - { url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835, upload-time = "2025-09-27T18:37:23.296Z" }, - { url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733, upload-time = "2025-09-27T18:37:24.237Z" }, - { url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672, upload-time = "2025-09-27T18:37:25.271Z" }, - { url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" }, - { url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" }, - { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, -] - -[[package]] -name = "mdformat" -version = "0.7.22" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "markdown-it-py" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/fc/eb/b5cbf2484411af039a3d4aeb53a5160fae25dd8c84af6a4243bc2f3fedb3/mdformat-0.7.22.tar.gz", hash = "sha256:eef84fa8f233d3162734683c2a8a6222227a229b9206872e6139658d99acb1ea", size = 34610, upload-time = "2025-01-30T18:00:51.418Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f2/6f/94a7344f6d634fe3563bea8b33bccedee37f2726f7807e9a58440dc91627/mdformat-0.7.22-py3-none-any.whl", hash = "sha256:61122637c9e1d9be1329054f3fa216559f0d1f722b7919b060a8c2a4ae1850e5", size = 34447, upload-time = "2025-01-30T18:00:48.708Z" }, -] - -[[package]] -name = "mdformat-tables" -version = "1.0.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "mdformat" }, - { name = "wcwidth" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/64/fc/995ba209096bdebdeb8893d507c7b32b7e07d9a9f2cdc2ec07529947794b/mdformat_tables-1.0.0.tar.gz", hash = "sha256:a57db1ac17c4a125da794ef45539904bb8a9592e80557d525e1f169c96daa2c8", size = 6106, upload-time = "2024-08-23T23:41:33.413Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2a/37/d78e37d14323da3f607cd1af7daf262cb87fe614a245c15ad03bb03a2706/mdformat_tables-1.0.0-py3-none-any.whl", hash = "sha256:94cd86126141b2adc3b04c08d1441eb1272b36c39146bab078249a41c7240a9a", size = 5104, upload-time = "2024-08-23T23:41:31.863Z" }, -] - -[[package]] -name = "mdurl" -version = "0.1.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, -] - -[[package]] -name = "mergedeep" -version = "1.3.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/3a/41/580bb4006e3ed0361b8151a01d324fb03f420815446c7def45d02f74c270/mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8", size = 4661, upload-time = "2021-02-05T18:55:30.623Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307", size = 6354, upload-time = "2021-02-05T18:55:29.583Z" }, -] - -[[package]] -name = "mkdocs" -version = "1.6.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "click" }, - { name = "colorama", marker = "sys_platform == 'win32'" }, - { name = "ghp-import" }, - { name = "jinja2" }, - { name = "markdown" }, - { name = "markupsafe" }, - { name = "mergedeep" }, - { name = "mkdocs-get-deps" }, - { name = "packaging" }, - { name = "pathspec" }, - { name = "pyyaml" }, - { name = "pyyaml-env-tag" }, - { name = "watchdog" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/bc/c6/bbd4f061bd16b378247f12953ffcb04786a618ce5e904b8c5a01a0309061/mkdocs-1.6.1.tar.gz", hash = "sha256:7b432f01d928c084353ab39c57282f29f92136665bdd6abf7c1ec8d822ef86f2", size = 3889159, upload-time = "2024-08-30T12:24:06.899Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl", hash = "sha256:db91759624d1647f3f34aa0c3f327dd2601beae39a366d6e064c03468d35c20e", size = 3864451, upload-time = "2024-08-30T12:24:05.054Z" }, -] - -[[package]] -name = "mkdocs-get-deps" -version = "0.2.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "mergedeep" }, - { name = "platformdirs" }, - { name = "pyyaml" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/98/f5/ed29cd50067784976f25ed0ed6fcd3c2ce9eb90650aa3b2796ddf7b6870b/mkdocs_get_deps-0.2.0.tar.gz", hash = "sha256:162b3d129c7fad9b19abfdcb9c1458a651628e4b1dea628ac68790fb3061c60c", size = 10239, upload-time = "2023-11-20T17:51:09.981Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9f/d4/029f984e8d3f3b6b726bd33cafc473b75e9e44c0f7e80a5b29abc466bdea/mkdocs_get_deps-0.2.0-py3-none-any.whl", hash = "sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134", size = 9521, upload-time = "2023-11-20T17:51:08.587Z" }, -] - -[[package]] -name = "mkdocs-git-revision-date-localized-plugin" -version = "1.5.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "babel" }, - { name = "gitpython" }, - { name = "mkdocs" }, - { name = "tzdata", marker = "sys_platform == 'win32'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/0f/c5/1d3c4e6ddae6230b89d09105cb79de711655e3ebd6745f7a92efea0f5160/mkdocs_git_revision_date_localized_plugin-1.5.0.tar.gz", hash = "sha256:17345ccfdf69a1905dc96fb1070dce82d03a1eb6b0d48f958081a7589ce3c248", size = 460697, upload-time = "2025-10-31T16:11:34.44Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/bc/51/fe0e3fdb16f6eed65c9459d12bae6a4e1f0bb4e2228cb037e7907b002678/mkdocs_git_revision_date_localized_plugin-1.5.0-py3-none-any.whl", hash = "sha256:933f9e35a8c135b113f21bb57610d82e9b7bcc71dd34fb06a029053c97e99656", size = 26153, upload-time = "2025-10-31T16:11:32.987Z" }, -] - -[[package]] -name = "mkdocs-glightbox" -version = "0.5.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "selectolax" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/8d/26/c793459622da8e31f954c6f5fb51e8f098143fdfc147b1e3c25bf686f4aa/mkdocs_glightbox-0.5.2.tar.gz", hash = "sha256:c7622799347c32310878e01ccf14f70648445561010911c80590cec0353370ac", size = 510586, upload-time = "2025-10-23T14:55:18.909Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4e/ca/03624e017e5ee2d7ce8a08d89f81c1e535eb3c30d7b2dc4a435ea3fbbeae/mkdocs_glightbox-0.5.2-py3-none-any.whl", hash = "sha256:23a431ea802b60b1030c73323db2eed6ba859df1a0822ce575afa43e0ea3f47e", size = 26458, upload-time = "2025-10-23T14:55:17.43Z" }, -] - -[[package]] -name = "mkdocs-llmstxt" -version = "0.5.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "beautifulsoup4" }, - { name = "markdownify" }, - { name = "mdformat" }, - { name = "mdformat-tables" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/7f/f5/4c31cdffa7c09bf48d8c7a50d8342dc100abac98ac4150826bc11afc0c9f/mkdocs_llmstxt-0.5.0.tar.gz", hash = "sha256:b2fa9e6d68df41d7467e948a4745725b6c99434a36b36204857dbd7bb3dfe041", size = 33909, upload-time = "2025-11-20T14:02:24.861Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ad/2b/82928cc9e8d9269cd79e7ebf015efdc4945e6c646e86ec1d4dba1707f215/mkdocs_llmstxt-0.5.0-py3-none-any.whl", hash = "sha256:753c699913d2d619a9072604b26b6dc9f5fb6d257d9b107857f80c8a0b787533", size = 12040, upload-time = "2025-11-20T14:02:23.483Z" }, -] - -[[package]] -name = "mkdocs-material" -version = "9.7.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "babel" }, - { name = "backrefs" }, - { name = "colorama" }, - { name = "jinja2" }, - { name = "markdown" }, - { name = "mkdocs" }, - { name = "mkdocs-material-extensions" }, - { name = "paginate" }, - { name = "pygments" }, - { name = "pymdown-extensions" }, - { name = "requests" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/9c/3b/111b84cd6ff28d9e955b5f799ef217a17bc1684ac346af333e6100e413cb/mkdocs_material-9.7.0.tar.gz", hash = "sha256:602b359844e906ee402b7ed9640340cf8a474420d02d8891451733b6b02314ec", size = 4094546, upload-time = "2025-11-11T08:49:09.73Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/04/87/eefe8d5e764f4cf50ed91b943f8e8f96b5efd65489d8303b7a36e2e79834/mkdocs_material-9.7.0-py3-none-any.whl", hash = "sha256:da2866ea53601125ff5baa8aa06404c6e07af3c5ce3d5de95e3b52b80b442887", size = 9283770, upload-time = "2025-11-11T08:49:06.26Z" }, -] - -[[package]] -name = "mkdocs-material-extensions" -version = "1.3.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/79/9b/9b4c96d6593b2a541e1cb8b34899a6d021d208bb357042823d4d2cabdbe7/mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443", size = 11847, upload-time = "2023-11-22T19:09:45.208Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31", size = 8728, upload-time = "2023-11-22T19:09:43.465Z" }, -] - -[[package]] -name = "mkdocs-multirepo-plugin" -version = "0.8.3" -source = { git = "https://github.com/atuinsh/mkdocs-multirepo-plugin?rev=mkt%2Fimported_repo#e2aed29184af719cce2bc0dddb90ceec99af21b9" } -dependencies = [ - { name = "dacite" }, - { name = "mkdocs" }, - { name = "python-slugify" }, - { name = "typing-inspect" }, -] - -[[package]] -name = "mkdocs-redirects" -version = "1.2.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "mkdocs" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/f1/a8/6d44a6cf07e969c7420cb36ab287b0669da636a2044de38a7d2208d5a758/mkdocs_redirects-1.2.2.tar.gz", hash = "sha256:3094981b42ffab29313c2c1b8ac3969861109f58b2dd58c45fc81cd44bfa0095", size = 7162, upload-time = "2024-11-07T14:57:21.109Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c4/ec/38443b1f2a3821bbcb24e46cd8ba979154417794d54baf949fefde1c2146/mkdocs_redirects-1.2.2-py3-none-any.whl", hash = "sha256:7dbfa5647b79a3589da4401403d69494bd1f4ad03b9c15136720367e1f340ed5", size = 6142, upload-time = "2024-11-07T14:57:19.143Z" }, -] - -[[package]] -name = "mypy-extensions" -version = "1.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, -] - -[[package]] -name = "packaging" -version = "25.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, -] - -[[package]] -name = "paginate" -version = "0.5.7" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ec/46/68dde5b6bc00c1296ec6466ab27dddede6aec9af1b99090e1107091b3b84/paginate-0.5.7.tar.gz", hash = "sha256:22bd083ab41e1a8b4f3690544afb2c60c25e5c9a63a30fa2f483f6c60c8e5945", size = 19252, upload-time = "2024-08-25T14:17:24.139Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl", hash = "sha256:b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591", size = 13746, upload-time = "2024-08-25T14:17:22.55Z" }, -] - -[[package]] -name = "pathspec" -version = "0.12.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, -] - -[[package]] -name = "platformdirs" -version = "4.5.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/cf/86/0248f086a84f01b37aaec0fa567b397df1a119f73c16f6c7a9aac73ea309/platformdirs-4.5.1.tar.gz", hash = "sha256:61d5cdcc6065745cdd94f0f878977f8de9437be93de97c1c12f853c9c0cdcbda", size = 21715, upload-time = "2025-12-05T13:52:58.638Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cb/28/3bfe2fa5a7b9c46fe7e13c97bda14c895fb10fa2ebf1d0abb90e0cea7ee1/platformdirs-4.5.1-py3-none-any.whl", hash = "sha256:d03afa3963c806a9bed9d5125c8f4cb2fdaf74a55ab60e5d59b3fde758104d31", size = 18731, upload-time = "2025-12-05T13:52:56.823Z" }, -] - -[[package]] -name = "pygments" -version = "2.19.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, -] - -[[package]] -name = "pymdown-extensions" -version = "10.19" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "markdown" }, - { name = "pyyaml" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/1f/4e/e73e88f4f2d0b26cbd2e100074107470984f0a6055869805fc181b847ac7/pymdown_extensions-10.19.tar.gz", hash = "sha256:01bb917ea231f9ce14456fa9092cdb95ac3e5bd32202a3ee61dbd5ad2dd9ef9b", size = 847701, upload-time = "2025-12-11T18:20:46.093Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d4/56/fa9edaceb3805e03ac9faf68ca1ddc660a75b49aee5accb493511005fef5/pymdown_extensions-10.19-py3-none-any.whl", hash = "sha256:dc5f249fc3a1b6d8a6de4634ba8336b88d0942cee75e92b18ac79eaf3503bf7c", size = 266670, upload-time = "2025-12-11T18:20:44.736Z" }, -] - -[[package]] -name = "python-dateutil" -version = "2.9.0.post0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "six" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, -] - -[[package]] -name = "python-slugify" -version = "8.0.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "text-unidecode" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/87/c7/5e1547c44e31da50a460df93af11a535ace568ef89d7a811069ead340c4a/python-slugify-8.0.4.tar.gz", hash = "sha256:59202371d1d05b54a9e7720c5e038f928f45daaffe41dd10822f3907b937c856", size = 10921, upload-time = "2024-02-08T18:32:45.488Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a4/62/02da182e544a51a5c3ccf4b03ab79df279f9c60c5e82d5e8bec7ca26ac11/python_slugify-8.0.4-py2.py3-none-any.whl", hash = "sha256:276540b79961052b66b7d116620b36518847f52d5fd9e3a70164fc8c50faa6b8", size = 10051, upload-time = "2024-02-08T18:32:43.911Z" }, -] - -[[package]] -name = "pyyaml" -version = "6.0.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6d/16/a95b6757765b7b031c9374925bb718d55e0a9ba8a1b6a12d25962ea44347/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e", size = 185826, upload-time = "2025-09-25T21:31:58.655Z" }, - { url = "https://files.pythonhosted.org/packages/16/19/13de8e4377ed53079ee996e1ab0a9c33ec2faf808a4647b7b4c0d46dd239/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824", size = 175577, upload-time = "2025-09-25T21:32:00.088Z" }, - { url = "https://files.pythonhosted.org/packages/0c/62/d2eb46264d4b157dae1275b573017abec435397aa59cbcdab6fc978a8af4/pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c", size = 775556, upload-time = "2025-09-25T21:32:01.31Z" }, - { url = "https://files.pythonhosted.org/packages/10/cb/16c3f2cf3266edd25aaa00d6c4350381c8b012ed6f5276675b9eba8d9ff4/pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00", size = 882114, upload-time = "2025-09-25T21:32:03.376Z" }, - { url = "https://files.pythonhosted.org/packages/71/60/917329f640924b18ff085ab889a11c763e0b573da888e8404ff486657602/pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d", size = 806638, upload-time = "2025-09-25T21:32:04.553Z" }, - { url = "https://files.pythonhosted.org/packages/dd/6f/529b0f316a9fd167281a6c3826b5583e6192dba792dd55e3203d3f8e655a/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a", size = 767463, upload-time = "2025-09-25T21:32:06.152Z" }, - { url = "https://files.pythonhosted.org/packages/f2/6a/b627b4e0c1dd03718543519ffb2f1deea4a1e6d42fbab8021936a4d22589/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4", size = 794986, upload-time = "2025-09-25T21:32:07.367Z" }, - { url = "https://files.pythonhosted.org/packages/45/91/47a6e1c42d9ee337c4839208f30d9f09caa9f720ec7582917b264defc875/pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b", size = 142543, upload-time = "2025-09-25T21:32:08.95Z" }, - { url = "https://files.pythonhosted.org/packages/da/e3/ea007450a105ae919a72393cb06f122f288ef60bba2dc64b26e2646fa315/pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf", size = 158763, upload-time = "2025-09-25T21:32:09.96Z" }, - { url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" }, - { url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" }, - { url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" }, - { url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" }, - { url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" }, - { url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" }, - { url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" }, - { url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" }, - { url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" }, - { url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" }, - { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, - { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, - { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, - { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, - { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, - { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, - { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, - { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, - { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, - { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, - { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, - { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, - { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, - { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, - { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, - { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, - { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, - { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, - { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, - { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, - { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, - { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, - { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, - { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, - { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, - { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, - { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, - { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, -] - -[[package]] -name = "pyyaml-env-tag" -version = "1.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pyyaml" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/eb/2e/79c822141bfd05a853236b504869ebc6b70159afc570e1d5a20641782eaa/pyyaml_env_tag-1.1.tar.gz", hash = "sha256:2eb38b75a2d21ee0475d6d97ec19c63287a7e140231e4214969d0eac923cd7ff", size = 5737, upload-time = "2025-05-13T15:24:01.64Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl", hash = "sha256:17109e1a528561e32f026364712fee1264bc2ea6715120891174ed1b980d2e04", size = 4722, upload-time = "2025-05-13T15:23:59.629Z" }, -] - -[[package]] -name = "requests" -version = "2.32.5" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "certifi" }, - { name = "charset-normalizer" }, - { name = "idna" }, - { name = "urllib3" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, -] - -[[package]] -name = "selectolax" -version = "0.4.6" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/fb/c5/959b8661d200d9fd3cf52061ce6f1d7087ec94823bb324fe1ca76c80b250/selectolax-0.4.6.tar.gz", hash = "sha256:bd9326cfc9bbd5bfcda980b0452b9761b3cf134015154e95d83fa32cbfbb751b", size = 4793248, upload-time = "2025-12-06T12:35:48.513Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a0/76/9b5358d82353b68c5828cc8ceae4ff1073495462979d2035c1089f4421dd/selectolax-0.4.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:751f727c9963584fcfa101b2696e0dd31236142901bbe7866a8e39f2ec346cc4", size = 2052057, upload-time = "2025-12-06T12:34:24.448Z" }, - { url = "https://files.pythonhosted.org/packages/e3/d1/9f8c8841f414a1b72174acef916d4ed38cc0fa041d3e933013e2b3213f30/selectolax-0.4.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d6f45737b638836b9fe2a4e7ccfbcd48a315ebb96da76a79a04b8227c1a967ee", size = 2050379, upload-time = "2025-12-06T12:34:26.383Z" }, - { url = "https://files.pythonhosted.org/packages/bc/c4/8e5ab9275a185a31d06b5ea58e3ba61d57e57700964cbd56fe074dbe458c/selectolax-0.4.6-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:15a22c5cd9c23f09227b2b9c227d986396125a9b0eb21be655f22fe4ccc5679a", size = 2238005, upload-time = "2025-12-06T12:34:28.2Z" }, - { url = "https://files.pythonhosted.org/packages/ea/af/f4299d931a8e11ba1998cac70d407c5338436978325232eb252ac7f5aba2/selectolax-0.4.6-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e64f771807f1a7353f4d6878c303bfbd6c6fe58897e301aa6d0de7e5e60cef61", size = 2272927, upload-time = "2025-12-06T12:34:29.955Z" }, - { url = "https://files.pythonhosted.org/packages/7b/5e/9afbb0e8495846bf97fa7725a6f97622ad85efc654cb3cbf4c881bd345de/selectolax-0.4.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a0144a37fbf01695ccf2d0d24caaa058a28449cecb2c754bb9e616f339468d74", size = 2250901, upload-time = "2025-12-06T12:34:31.442Z" }, - { url = "https://files.pythonhosted.org/packages/d5/6b/914cc9c977fd21949af5776d25b9c011b6e72fb38569161ab6ca83d6130a/selectolax-0.4.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3c9bdd4a9b3f71f28a0ee558a105451debd33cbe1ed350ebba7ad6b68d62815c", size = 2279842, upload-time = "2025-12-06T12:34:32.739Z" }, - { url = "https://files.pythonhosted.org/packages/e1/30/b32d79d31c893cf5ccea5a5be4565db1eda9bbf458ddfe402559267f2d31/selectolax-0.4.6-cp311-cp311-win32.whl", hash = "sha256:b91c34b854fdd5d21c8353f130899f8413b7104a96078acbca59c8b2d57e9352", size = 1730462, upload-time = "2025-12-06T12:34:34.435Z" }, - { url = "https://files.pythonhosted.org/packages/8f/f1/c7ba048d4fcc4c8d5857233c59d07f18e60b21400a8ad8e8d7da670024c2/selectolax-0.4.6-cp311-cp311-win_amd64.whl", hash = "sha256:901064121e706bc86ed13f6e0dbe478398ad05ab112f5efbc8d722320a087b93", size = 1831442, upload-time = "2025-12-06T12:34:35.846Z" }, - { url = "https://files.pythonhosted.org/packages/d5/55/b33853f66b1f875bbbbfc2294ce7a4065774621ab6ebf20e8abf19965846/selectolax-0.4.6-cp311-cp311-win_arm64.whl", hash = "sha256:609c6c19f5b7cb669a6321a1d4133d2e2b443f23f7d454de76904118a91236a6", size = 1781850, upload-time = "2025-12-06T12:34:37.175Z" }, - { url = "https://files.pythonhosted.org/packages/ee/81/1fdf6633df840afd9d7054a3441f04cfb1fc9d098c6c9f3bd46a64fb632e/selectolax-0.4.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:20615062d6062b197b61fd646e667591e987be3a894e8a8408d2a482ccddc747", size = 2051021, upload-time = "2025-12-06T12:34:38.495Z" }, - { url = "https://files.pythonhosted.org/packages/cc/54/d59738d090cb4df3a3a6297b7ec216b86d3ba7f320013c4bc8d4841c9f5d/selectolax-0.4.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c436006e2af6ade80b96411cf46652c11ced4f230032e25e1f5210b7522a4fe3", size = 2047409, upload-time = "2025-12-06T12:34:39.875Z" }, - { url = "https://files.pythonhosted.org/packages/fc/67/3b163ec18a128df3a3b59ce676a2dacfb26e714da81ba8a98e184b4ef187/selectolax-0.4.6-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:705a70b6f4e553e8c5299881269d3735a7df8a23711927a33caa16b4eaef580f", size = 2237052, upload-time = "2025-12-06T12:34:41.24Z" }, - { url = "https://files.pythonhosted.org/packages/f0/04/c3ae4a77e8cfa647b9177e727a7e80f64b160b65ad0db0dcb3738a4ef4a0/selectolax-0.4.6-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c04fd180689ed9450ad2453a3cba74cff2475a4281f76db9e18a658b7823e594", size = 2275615, upload-time = "2025-12-06T12:34:43.114Z" }, - { url = "https://files.pythonhosted.org/packages/12/de/aaa016c44e63a1efd5525f6da6eac807388a06c70671091c735d93f13b74/selectolax-0.4.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cb33eb0809e70ba4a475105d164c3f90a4bb711744ca69e20037298256b8e9d7", size = 2249186, upload-time = "2025-12-06T12:34:44.84Z" }, - { url = "https://files.pythonhosted.org/packages/76/9a/a9cf9f0158b0804c7ea404d790af031830eb6452a4948853f7582eea6c51/selectolax-0.4.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:97f30b7c731f9f3328e9c6aef7ca3c17fbcbc4495e286a2cdad9a77bcadfadf1", size = 2282041, upload-time = "2025-12-06T12:34:46.19Z" }, - { url = "https://files.pythonhosted.org/packages/4c/ea/85de7ab8a9fc0301d1b428e69dc0bced9c1cd7379872d576a2b88eb91933/selectolax-0.4.6-cp312-cp312-win32.whl", hash = "sha256:f4375b352b609508e4a6980431dc6cc1812b97658ad1aa8caa61e01565de0d7d", size = 1727544, upload-time = "2025-12-06T12:34:47.541Z" }, - { url = "https://files.pythonhosted.org/packages/50/70/4aac2df64920112672cda846941d85c90b8152b2eddc9cf2615181551957/selectolax-0.4.6-cp312-cp312-win_amd64.whl", hash = "sha256:1d02637a6746bf1ba7de1dfc00a0344ffb30bedd1b5d4e61727c960225bf6ce0", size = 1827825, upload-time = "2025-12-06T12:34:49.283Z" }, - { url = "https://files.pythonhosted.org/packages/8d/b0/09648383afed1a10df97ce30527d30714edc4072086915b4bb1a0d81a728/selectolax-0.4.6-cp312-cp312-win_arm64.whl", hash = "sha256:bb0b371c3e2a94e6658ba4b5af88fc35aaf44f57f5a066ecaf96b4875a47aec4", size = 1775233, upload-time = "2025-12-06T12:34:51.576Z" }, - { url = "https://files.pythonhosted.org/packages/4d/87/7ed053cce7de8b29746c602851c67654287e25ec404d575911c6f40b671f/selectolax-0.4.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8303af0eeef6ab2f06f2b18e3c825df4f6984405a862c8e9e654621c26558aca", size = 2050412, upload-time = "2025-12-06T12:34:53.086Z" }, - { url = "https://files.pythonhosted.org/packages/44/74/e8cd9b9b53da0e849b27a2ef68580915321ee52a662f015275a1cf6cca85/selectolax-0.4.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d8b1fb5507d90e719de705d93eaa3bdd5f2d69facf012fb67b7da8a9cd20ea6b", size = 2046513, upload-time = "2025-12-06T12:34:54.583Z" }, - { url = "https://files.pythonhosted.org/packages/a0/ca/c1cc7f03b681d272dbb0dc47cf9d0df857ae156d7ea54d88cc25ec23c8e9/selectolax-0.4.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:30ac51bd5bfcd6bffe58720b1fc5f97666681f0793d79d292069b3a3f8599ef0", size = 2234404, upload-time = "2025-12-06T12:34:55.971Z" }, - { url = "https://files.pythonhosted.org/packages/df/00/a6e5c4d65243147fbd8837951267f098d9bee66ada4dc0c99d97259e052c/selectolax-0.4.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cfee4d1269fd462256641abdf6c2ee4dd799ba82c578acab0bcde07547637826", size = 2272678, upload-time = "2025-12-06T12:34:57.3Z" }, - { url = "https://files.pythonhosted.org/packages/ab/a2/05351e0f0da62d1bc01b7820a990f1e4dec688206e0278ee8faeeb878940/selectolax-0.4.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:fce09eeb5dd19fba672a829f63e3c40238af4a929ce1e5fd16dcbc4fd253e300", size = 2247471, upload-time = "2025-12-06T12:34:59.048Z" }, - { url = "https://files.pythonhosted.org/packages/ea/95/1ab9e3ad2d53dbcd7141af149c7259c693dc2dc46e27d72b7a68f17f3364/selectolax-0.4.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b4e97ca71d545cab9c57ba3b18358cbc96ef0dcd01920ea903a531386ca1f849", size = 2278271, upload-time = "2025-12-06T12:35:00.487Z" }, - { url = "https://files.pythonhosted.org/packages/04/41/ca80ca68fb9990cb46d753363d8dc0771225bc9bb9a77247a1987e52d2d5/selectolax-0.4.6-cp313-cp313-win32.whl", hash = "sha256:98fce08839cb8fd5d8788cbed2724cd892c78182cd923e246ef586d552a29a94", size = 1727514, upload-time = "2025-12-06T12:35:02.081Z" }, - { url = "https://files.pythonhosted.org/packages/f0/47/f048994ab32773fda8eda57a874afb30d0b2bf30952c009006e81737e07e/selectolax-0.4.6-cp313-cp313-win_amd64.whl", hash = "sha256:cdc8e7833d2456331e519fe901d1c8844d120a26b21b6429f47ae946e65b0c04", size = 1829070, upload-time = "2025-12-06T12:35:03.857Z" }, - { url = "https://files.pythonhosted.org/packages/50/94/ab0d86b1a719c090e2bde9f7d9037439900e86fb50c258b5fd9f6530521b/selectolax-0.4.6-cp313-cp313-win_arm64.whl", hash = "sha256:d6f8c976ad067a6607b2a052b141149ae23584819b73288c32f08a1ece23d60a", size = 1774935, upload-time = "2025-12-06T12:35:05.323Z" }, - { url = "https://files.pythonhosted.org/packages/d2/38/93b4907c596487e13f8261129b1663559c96fc37ea2c973c98a393307484/selectolax-0.4.6-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:961c037ac41a12bf9db35a95d6076461f9b127d361c9ef26a77f76c45b1056eb", size = 2069131, upload-time = "2025-12-06T12:35:06.737Z" }, - { url = "https://files.pythonhosted.org/packages/f6/04/d29769a8313ccb9db6278401840e79662f341b716d268f7468b6270d15e1/selectolax-0.4.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:f2be076a69a12657a38933b99d31c604d95d63911e0799f89305da8e89918874", size = 2066134, upload-time = "2025-12-06T12:35:08.163Z" }, - { url = "https://files.pythonhosted.org/packages/29/a2/1c26b4cc6a708d234e39199bd75acdc1cfdcf4f3138e16d25e3e7aa0295d/selectolax-0.4.6-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:25ae5dd7c20035312211de43952934981e8ff4e1502467ce78665f57bc5eaf7f", size = 2240810, upload-time = "2025-12-06T12:35:09.556Z" }, - { url = "https://files.pythonhosted.org/packages/1f/de/b021342d306bd08c92d0d9e9072a3ed6a3038f78387187d37fb775196fa0/selectolax-0.4.6-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cfe1274930affe2b986fd20cbf2916ddf4a760edf30a7eeb9151b31e8cbe6027", size = 2274401, upload-time = "2025-12-06T12:35:11.023Z" }, - { url = "https://files.pythonhosted.org/packages/29/77/b2816be2f4878f4e86fabca5932610401dc88d956948d97a82947e27d8bc/selectolax-0.4.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e52174a75236c1321f0f0353b5d97ba575c61428f16c2d78159cb154fa407e97", size = 2271054, upload-time = "2025-12-06T12:35:12.878Z" }, - { url = "https://files.pythonhosted.org/packages/1f/3a/ae48b9febf2af21a0fdd4fba07861ae3e13bd7235df3fa39918d33004058/selectolax-0.4.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5032187ed8f8d77da6dee5467a87fe9b1553c10c63671fe830e87a2d347ef8ae", size = 2297773, upload-time = "2025-12-06T12:35:14.383Z" }, - { url = "https://files.pythonhosted.org/packages/f9/8c/4e120b2b6dc55543bf2ffc43e78589022e59c02fa93dea0b4d22dfe3fc27/selectolax-0.4.6-cp314-cp314-win32.whl", hash = "sha256:8a4f50eb37abffe118730c062827a204a732cc1b9cd28b5dbf40752c371e9339", size = 1838289, upload-time = "2025-12-06T12:35:16.278Z" }, - { url = "https://files.pythonhosted.org/packages/c4/2f/51f15b06f4fcf9d5845d6bba534f7f2ed531f148c77ed8fff105cd770aa5/selectolax-0.4.6-cp314-cp314-win_amd64.whl", hash = "sha256:11527cd430cb6d1d1a422209d87aec5767befff424f2affaa3daa2789878cf9f", size = 1938201, upload-time = "2025-12-06T12:35:17.694Z" }, - { url = "https://files.pythonhosted.org/packages/f3/8d/c099dcbb385e7d2145c4f19da183639bf4e429e1524dcba31ea311c5d276/selectolax-0.4.6-cp314-cp314-win_arm64.whl", hash = "sha256:254d7f59580631dac1fcb861bb01f45039e3ac53187f07d8ccc3519110bacad0", size = 1886188, upload-time = "2025-12-06T12:35:19.538Z" }, - { url = "https://files.pythonhosted.org/packages/54/ce/f3fa904517745ecd289b6ce18845ae968cf7d0b17e65ab781259f2746254/selectolax-0.4.6-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:48a9bce389c281fec8bf3b5a36bd376f1ad1f36ff072dcedaa977188b3882be1", size = 2088107, upload-time = "2025-12-06T12:35:21.061Z" }, - { url = "https://files.pythonhosted.org/packages/4f/18/359da9723d3ec1235819cea0958bc417ce6a12699977920854b300ad4529/selectolax-0.4.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ff1632c1767f6005adc2dff7b72ea9d0b6493702e86e04ee5cf934ab630172aa", size = 2090836, upload-time = "2025-12-06T12:35:22.421Z" }, - { url = "https://files.pythonhosted.org/packages/e2/20/199f2a05ca8dfd9bc146af03fbfaa1e2050601d3141267070a2a023ea68f/selectolax-0.4.6-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:64a56dd91c22e809305e127bbd4cd75ad1016dd329a4e945a176c6f3376d00e2", size = 2248608, upload-time = "2025-12-06T12:35:23.946Z" }, - { url = "https://files.pythonhosted.org/packages/f9/67/261c06cdae29fad287008d39f51a80431f3fce66c2865b880e61d04cdfd2/selectolax-0.4.6-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:223471d2c9095406d69faf461aa217782575d62362d36809e350f6d3c2f69f4e", size = 2275653, upload-time = "2025-12-06T12:35:25.423Z" }, - { url = "https://files.pythonhosted.org/packages/10/80/f2519487a86b5366acadd9e07c212b38fb657bb62b9e01de9fb24c3ada27/selectolax-0.4.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8c1043e61df29f4f8ef49f9f623b3d710f0c545d9a7939eee52c49987b06aef7", size = 2283495, upload-time = "2025-12-06T12:35:26.843Z" }, - { url = "https://files.pythonhosted.org/packages/66/cc/35a0fd896371e0b5a84365b03f88c7dbe8984862e34ce32baed81ee6f486/selectolax-0.4.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b323ad4ebcf2edad2488022402fbc73ee158ffe81607ec1ce5eb1039eab94086", size = 2300207, upload-time = "2025-12-06T12:35:28.23Z" }, - { url = "https://files.pythonhosted.org/packages/51/b2/dc83cce2f38a3c72d6bf9268ef6c1708ab1b4d546074384e7e0d097bf4f6/selectolax-0.4.6-cp314-cp314t-win32.whl", hash = "sha256:f5017f6e2408160604c87fb21490d9af802d09dbc1b91ac89acd9922b7b04d31", size = 1890595, upload-time = "2025-12-06T12:35:29.625Z" }, - { url = "https://files.pythonhosted.org/packages/87/f9/8da49637643b1dffbcadc8972f1fee519c126978acaf5df59405e48424f4/selectolax-0.4.6-cp314-cp314t-win_amd64.whl", hash = "sha256:56adb0f014ab55627f20f53888a7bf1ec53aac8189fe344aec3d5077a7ad9889", size = 2005252, upload-time = "2025-12-06T12:35:31.116Z" }, - { url = "https://files.pythonhosted.org/packages/94/7f/f783e2254db082df4f6bc00fe3b32b9dd27c3b7302a44c8c37728bb67fb7/selectolax-0.4.6-cp314-cp314t-win_arm64.whl", hash = "sha256:66558cfb1c7402fed0f47b9a2692eed53e3e2f345526314b493b5093cb951e21", size = 1906079, upload-time = "2025-12-06T12:35:32.951Z" }, -] - -[[package]] -name = "six" -version = "1.17.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, -] - -[[package]] -name = "smmap" -version = "5.0.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/44/cd/a040c4b3119bbe532e5b0732286f805445375489fceaec1f48306068ee3b/smmap-5.0.2.tar.gz", hash = "sha256:26ea65a03958fa0c8a1c7e8c7a58fdc77221b8910f6be2131affade476898ad5", size = 22329, upload-time = "2025-01-02T07:14:40.909Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/04/be/d09147ad1ec7934636ad912901c5fd7667e1c858e19d355237db0d0cd5e4/smmap-5.0.2-py3-none-any.whl", hash = "sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e", size = 24303, upload-time = "2025-01-02T07:14:38.724Z" }, -] - -[[package]] -name = "soupsieve" -version = "2.8.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7b/ae/2d9c981590ed9999a0d91755b47fc74f74de286b0f5cee14c9269041e6c4/soupsieve-2.8.3.tar.gz", hash = "sha256:3267f1eeea4251fb42728b6dfb746edc9acaffc4a45b27e19450b676586e8349", size = 118627, upload-time = "2026-01-20T04:27:02.457Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl", hash = "sha256:ed64f2ba4eebeab06cc4962affce381647455978ffc1e36bb79a545b91f45a95", size = 37016, upload-time = "2026-01-20T04:27:01.012Z" }, -] - -[[package]] -name = "text-unidecode" -version = "1.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ab/e2/e9a00f0ccb71718418230718b3d900e71a5d16e701a3dae079a21e9cd8f8/text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93", size = 76885, upload-time = "2019-08-30T21:36:45.405Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a6/a5/c0b6468d3824fe3fde30dbb5e1f687b291608f9473681bbf7dabbf5a87d7/text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8", size = 78154, upload-time = "2019-08-30T21:37:03.543Z" }, -] - -[[package]] -name = "typing-extensions" -version = "4.15.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, -] - -[[package]] -name = "typing-inspect" -version = "0.8.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "mypy-extensions" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/72/23/bed3ea644bcd77ffe9a7f591eb058c00739747e33ab94d80cc4319ddee8e/typing_inspect-0.8.0.tar.gz", hash = "sha256:8b1ff0c400943b6145df8119c41c244ca8207f1f10c9c057aeed1560e4806e3d", size = 13550, upload-time = "2022-08-17T14:00:05.915Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/be/01/59b743dca816c4b6ca891b9e0f84d20513cd61bdbbaa8615de8f5aab68c1/typing_inspect-0.8.0-py3-none-any.whl", hash = "sha256:5fbf9c1e65d4fa01e701fe12a5bca6c6e08a4ffd5bc60bfac028253a447c5188", size = 8710, upload-time = "2022-08-17T14:00:03.093Z" }, -] - -[[package]] -name = "tzdata" -version = "2025.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/95/32/1a225d6164441be760d75c2c42e2780dc0873fe382da3e98a2e1e48361e5/tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9", size = 196380, upload-time = "2025-03-23T13:54:43.652Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", size = 347839, upload-time = "2025-03-23T13:54:41.845Z" }, -] - -[[package]] -name = "urllib3" -version = "2.6.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1e/24/a2a2ed9addd907787d7aa0355ba36a6cadf1768b934c652ea78acbd59dcd/urllib3-2.6.2.tar.gz", hash = "sha256:016f9c98bb7e98085cb2b4b17b87d2c702975664e4f060c6532e64d1c1a5e797", size = 432930, upload-time = "2025-12-11T15:56:40.252Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl", hash = "sha256:ec21cddfe7724fc7cb4ba4bea7aa8e2ef36f607a4bab81aa6ce42a13dc3f03dd", size = 131182, upload-time = "2025-12-11T15:56:38.584Z" }, -] - -[[package]] -name = "watchdog" -version = "6.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/db/7d/7f3d619e951c88ed75c6037b246ddcf2d322812ee8ea189be89511721d54/watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282", size = 131220, upload-time = "2024-11-01T14:07:13.037Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e0/24/d9be5cd6642a6aa68352ded4b4b10fb0d7889cb7f45814fb92cecd35f101/watchdog-6.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c", size = 96393, upload-time = "2024-11-01T14:06:31.756Z" }, - { url = "https://files.pythonhosted.org/packages/63/7a/6013b0d8dbc56adca7fdd4f0beed381c59f6752341b12fa0886fa7afc78b/watchdog-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2", size = 88392, upload-time = "2024-11-01T14:06:32.99Z" }, - { url = "https://files.pythonhosted.org/packages/d1/40/b75381494851556de56281e053700e46bff5b37bf4c7267e858640af5a7f/watchdog-6.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c", size = 89019, upload-time = "2024-11-01T14:06:34.963Z" }, - { url = "https://files.pythonhosted.org/packages/39/ea/3930d07dafc9e286ed356a679aa02d777c06e9bfd1164fa7c19c288a5483/watchdog-6.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948", size = 96471, upload-time = "2024-11-01T14:06:37.745Z" }, - { url = "https://files.pythonhosted.org/packages/12/87/48361531f70b1f87928b045df868a9fd4e253d9ae087fa4cf3f7113be363/watchdog-6.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860", size = 88449, upload-time = "2024-11-01T14:06:39.748Z" }, - { url = "https://files.pythonhosted.org/packages/5b/7e/8f322f5e600812e6f9a31b75d242631068ca8f4ef0582dd3ae6e72daecc8/watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0", size = 89054, upload-time = "2024-11-01T14:06:41.009Z" }, - { url = "https://files.pythonhosted.org/packages/68/98/b0345cabdce2041a01293ba483333582891a3bd5769b08eceb0d406056ef/watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c", size = 96480, upload-time = "2024-11-01T14:06:42.952Z" }, - { url = "https://files.pythonhosted.org/packages/85/83/cdf13902c626b28eedef7ec4f10745c52aad8a8fe7eb04ed7b1f111ca20e/watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134", size = 88451, upload-time = "2024-11-01T14:06:45.084Z" }, - { url = "https://files.pythonhosted.org/packages/fe/c4/225c87bae08c8b9ec99030cd48ae9c4eca050a59bf5c2255853e18c87b50/watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b", size = 89057, upload-time = "2024-11-01T14:06:47.324Z" }, - { url = "https://files.pythonhosted.org/packages/a9/c7/ca4bf3e518cb57a686b2feb4f55a1892fd9a3dd13f470fca14e00f80ea36/watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13", size = 79079, upload-time = "2024-11-01T14:06:59.472Z" }, - { url = "https://files.pythonhosted.org/packages/5c/51/d46dc9332f9a647593c947b4b88e2381c8dfc0942d15b8edc0310fa4abb1/watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379", size = 79078, upload-time = "2024-11-01T14:07:01.431Z" }, - { url = "https://files.pythonhosted.org/packages/d4/57/04edbf5e169cd318d5f07b4766fee38e825d64b6913ca157ca32d1a42267/watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e", size = 79076, upload-time = "2024-11-01T14:07:02.568Z" }, - { url = "https://files.pythonhosted.org/packages/ab/cc/da8422b300e13cb187d2203f20b9253e91058aaf7db65b74142013478e66/watchdog-6.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f", size = 79077, upload-time = "2024-11-01T14:07:03.893Z" }, - { url = "https://files.pythonhosted.org/packages/2c/3b/b8964e04ae1a025c44ba8e4291f86e97fac443bca31de8bd98d3263d2fcf/watchdog-6.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26", size = 79078, upload-time = "2024-11-01T14:07:05.189Z" }, - { url = "https://files.pythonhosted.org/packages/62/ae/a696eb424bedff7407801c257d4b1afda455fe40821a2be430e173660e81/watchdog-6.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c", size = 79077, upload-time = "2024-11-01T14:07:06.376Z" }, - { url = "https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2", size = 79078, upload-time = "2024-11-01T14:07:07.547Z" }, - { url = "https://files.pythonhosted.org/packages/07/f6/d0e5b343768e8bcb4cda79f0f2f55051bf26177ecd5651f84c07567461cf/watchdog-6.0.0-py3-none-win32.whl", hash = "sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a", size = 79065, upload-time = "2024-11-01T14:07:09.525Z" }, - { url = "https://files.pythonhosted.org/packages/db/d9/c495884c6e548fce18a8f40568ff120bc3a4b7b99813081c8ac0c936fa64/watchdog-6.0.0-py3-none-win_amd64.whl", hash = "sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680", size = 79070, upload-time = "2024-11-01T14:07:10.686Z" }, - { url = "https://files.pythonhosted.org/packages/33/e8/e40370e6d74ddba47f002a32919d91310d6074130fe4e17dabcafc15cbf1/watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f", size = 79067, upload-time = "2024-11-01T14:07:11.845Z" }, -] - -[[package]] -name = "wcwidth" -version = "0.7.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2c/ee/afaf0f85a9a18fe47a67f1e4422ed6cf1fe642f0ae0a2f81166231303c52/wcwidth-0.7.0.tar.gz", hash = "sha256:90e3a7ea092341c44b99562e75d09e4d5160fe7a3974c6fb842a101a95e7eed0", size = 182132, upload-time = "2026-05-02T16:04:12.653Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/41/52/e465037f5375f43533d1a80b6923955201596a99142ed524d77b571a1418/wcwidth-0.7.0-py3-none-any.whl", hash = "sha256:5d69154c429a82910e241c738cd0e2976fac8a2dd47a1a805f4afed1c0f136f2", size = 110825, upload-time = "2026-05-02T16:04:11.033Z" }, -] |
