aboutsummaryrefslogtreecommitdiffstats
path: root/Cargo.lock (follow)
Commit message (Collapse)AuthorAge
* perf: Reduce AI TUI rendering overhead for long conversations (#3447)Michelle Tilley2026-04-23
| | | | | | | | | | | | | | | | | | | | | | | | Fixes keystroke lag in Atuin AI that scales with conversation length. After extended use (many turns, lots of tool calls with output viewports), pressing a key had noticeable delay before the letter appeared. Three layers of optimization: - **Skip `sync_view_state` for `InputUpdated`** — every keystroke was cloning all events, tools, and archived data even though no FSM state changed. Uses `handle.update_tracked()` (eye_declare 0.5) to skip rebuilds when values haven't actually changed. - **Pre-compute turns and `has_command` on the driver thread** — the view function was rebuilding the full turn structure from raw events and scanning for `suggest_command` tool calls 3× per render frame. Now computed once per FSM state change and cached in ViewState. - **Commit-based element tree pruning** — turns that scroll into terminal scrollback are tracked via `on_commit` and filtered from the element tree, keeping rendering work proportional to visible content. Turn views are now direct children of the root VStack (not nested inside AtuinAi) so `detect_committed` can see them.
* feat: Add skill discovery, loading, and invocation (#3444)Michelle Tilley2026-04-23
| | | Adds a skills system that lets users define reusable LLM instructions as `SKILL.md` files with YAML frontmatter.
* feat: AI tool rendering overhaul + edit_file tool (#3423)Michelle Tilley2026-04-21
| | | | | | Overhaul of how AI tool calls are modeled, rendered, and displayed in the Atuin AI TUI. Fixes bugs in shell command output capture, implements the `edit_file` tool with full safety infrastructure, and adds a diff preview for edits.
* chore(release): prepare for release 18.15.2 (#3421)Michelle Tilley2026-04-16
| | | | | | | | ## 18.15.2 ### Bug Fixes - Tab doesn't insert suggested command ([#3420](https://github.com/atuinsh/atuin/issues/3420))
* chore(release): prepare for release 18.15.1 (#3419)Michelle Tilley2026-04-15
|
* fix: Enter runs suggested command when selecting permissions (#3418)Michelle Tilley2026-04-15
|
* chore(release): prepare for release 18.15.0 (#3417)Michelle Tilley2026-04-15
|
* feat: Allow resuming previous AI sessions (#3407)Michelle Tilley2026-04-15
| | | | | | | | | | | | | | | | | | | | | | | | | | | | This PR introduces session continuation to Atuin AI. * Conversations with Atuin AI are stored in a local SQLite database * Upon startup, Atuin AI tries to find a session to resume based on its directory/workspace and the time since the last event * If found, Atuin AI will show a note that the session has been resumed, and an event is added to help the LLM know where the invocation boundaries are * If not, Atuin AI will create a new conversation * The user can create a new conversation with `/new` * The new setting `ai.session_continue_minutes`, which defaults to `60`, controls how old the last event in a session can be before it's no longer considered for automatic resuming. <img width="1055" height="593" alt="image" src="https://github.com/user-attachments/assets/3f9ff01a-ef64-44a9-b0e2-3a4252c5746f" /> ## Architecture A new `SessionService` trait defines an API contract for a service that can manage session data. `LocalSessionService` implements this, with `DaemonSessionService` a possible future extension point. `SessionManager` owns a `dyn SessionService` and delegates as appropriate.
* feat: Enable atuin hex for illumos (#3413)Michael Zeller2026-04-14
| | | | | | | | | | | | | This bumps the `portable-pty` dep which itself has a dependency on a newer termios that knows about illumos. Unless this was pinned for a particular reason I think this is fine. With this dep bumped we can enable `atuin hex` on illumos. ## Checks - [x] I am happy for maintainers to push small adjustments to this PR, to speed up the review cycle - [x] I have checked that there are no existing pull requests for the same thing
* chore(release): prepare for release 18.14.1 (#3405)Ellie Huxtable2026-04-13
| | | | | | | | | | | | <!-- Thank you for making a PR! Bug fixes are always welcome, but if you're adding a new feature or changing an existing one, we'd really appreciate if you open an issue, post on the forum, or drop in on Discord --> ## Checks - [ ] I am happy for maintainers to push small adjustments to this PR, to speed up the review cycle - [ ] I have checked that there are no existing pull requests for the same thing
* chore(release): prepare for release 18.14.0 (#3401)Ellie Huxtable2026-04-13
| | | | | | | | | | | | <!-- Thank you for making a PR! Bug fixes are always welcome, but if you're adding a new feature or changing an existing one, we'd really appreciate if you open an issue, post on the forum, or drop in on Discord --> ## Checks - [ ] I am happy for maintainers to push small adjustments to this PR, to speed up the review cycle - [ ] I have checked that there are no existing pull requests for the same thing
* chore: Prepare 18.14.0-beta.1 release (#3393)Michelle Tilley2026-04-10
|
* feat: Client-tool execution + permission system (#3370)Michelle Tilley2026-04-10
| | | | | | Adds client-side tool execution to Atuin AI, starting with `atuin_history`. The server can request tool calls, which are executed locally with a permission system, and results are sent back to continue the conversation.
* chore: Update to eye-declare 0.3.0 (#3365)Michelle Tilley2026-03-30
|
* chore: Prepare 18.13.6 release (#3356)Michelle Tilley2026-03-27
|
* chore(deps): Update to eye-declare v0.2.0 (#3355)Michelle Tilley2026-03-27
| | | | | | | | | | | eye-declare v0.2.0 includes two relevant changes: * "Capture-phase" event handling lets us remove the special-case event handling in `InputBox` that allowed global keyboard binds to work; the `AtuinAi` component now handles this directly. * `Tracked::read()` allows reading fields in tracked state without triggering the dirty-tracking from the `DerefMut` implementation, allowing us to send messages on the app event bus without marking the containing state as dirty.
* feat: Use eye-declare for more performant and flexible AI TUI (#3343)Michelle Tilley2026-03-27
| | | | | | | | | | | | | | | | This PR replaces the mess of custom rendering code in Atuin AI with [eye-declare](https://github.com/BinaryMuse/eye-declare), and updates the TUI to feel more terminal-native: output appears inline and persists in scrollback, so you can scroll up and look at previous conversations for reference. The "review" state — which used to exist between the LLM generating a response and the user either executing or following up — has been removed; just start typing to follow up with the LLM, or press `enter` at the empty input box to execute the suggested command. <img width="1203" height="633" alt="image" src="https://github.com/user-attachments/assets/159ee447-9a2a-4edd-b56e-a79bf1aaaa94" />
* fix: remove unnecessary arboard/image-data default feature (#3345)Ross Williams2026-03-25
|
* chore: Prepare 18.13.5 (#3342)Michelle Tilley2026-03-24
|
* chore(release): prepare for release 18.13.4 (#3336)Michelle Tilley2026-03-23
|
* feat: Allow running `atuin search -i` as subcommand on Windows (#3250)Lucas Trzesniewski2026-03-20
| | | | | | | | | | | | | | | | | This is the equivalent of #3208, but for Windows. ~The rendering performance is noticeably slower in this mode when refreshing a large part of the screen, but it's better than not having the feature at all.~ Fixed 🙂 The second commit fixes some unrelated warnings. /cc @BinaryMuse FYI ## Checks - [x] I am happy for maintainers to push small adjustments to this PR, to speed up the review cycle - [x] I have checked that there are no existing pull requests for the same thing
* chore(release): prepare for release 18.13.3Ellie Huxtable2026-03-16
|
* vendor nucleo fork into atuin workspaceEllie Huxtable2026-03-16
| | | | | | | | | | | | Rename crates (nucleo → atuin-nucleo, nucleo-matcher → atuin-nucleo-matcher), add to workspace members and dependencies, update all import paths, remove vendored CI workflow, and suppress upstream clippy warnings. format codespell fixes clippy clappy
* chore(release): prepare for release 18.13.2 (#3264)Ellie Huxtable2026-03-13
| | | | | | | | | | | I tried adding a windows arm64 build to the last release, which was perhaps a little naive of me. I thought it working on x86 windows and arm everything else would be enough 💀 ## Checks - [ ] I am happy for maintainers to push small adjustments to this PR, to speed up the review cycle - [ ] I have checked that there are no existing pull requests for the same thing
* chore(release): prepare for release 18.13.1 (#3263)Ellie Huxtable2026-03-13
| | | | | | | | | | We were using buildjet as our runners previously, but it looks like they have gone under. Luckily, GitHub now provides the arm runners we need ## Checks - [ ] I am happy for maintainers to push small adjustments to this PR, to speed up the review cycle - [ ] I have checked that there are no existing pull requests for the same thing
* chore(release): prepare for release 18.13.0 (#3262)Ellie Huxtable2026-03-13
| | | | | | | | | | | | <!-- Thank you for making a PR! Bug fixes are always welcome, but if you're adding a new feature or changing an existing one, we'd really appreciate if you open an issue, post on the forum, or drop in on Discord --> ## Checks - [ ] I am happy for maintainers to push small adjustments to this PR, to speed up the review cycle - [ ] I have checked that there are no existing pull requests for the same thing
* chore(release): prepare for release 18.13.0-beta.7 (#3259)Ellie Huxtable2026-03-12
| | | | | | | | | | | | <!-- Thank you for making a PR! Bug fixes are always welcome, but if you're adding a new feature or changing an existing one, we'd really appreciate if you open an issue, post on the forum, or drop in on Discord --> ## Checks - [ ] I am happy for maintainers to push small adjustments to this PR, to speed up the review cycle - [ ] I have checked that there are no existing pull requests for the same thing
* feat: Add `atuin setup` (#3257)Michelle Tilley2026-03-12
|
* chore(release): prepare for release 18.13.0-beta.6 (#3258)Ellie Huxtable2026-03-12
| | | | | | | | | | | | <!-- Thank you for making a PR! Bug fixes are always welcome, but if you're adding a new feature or changing an existing one, we'd really appreciate if you open an issue, post on the forum, or drop in on Discord --> ## Checks - [ ] I am happy for maintainers to push small adjustments to this PR, to speed up the review cycle - [ ] I have checked that there are no existing pull requests for the same thing
* chore(release): prepare for release 18.13.0-beta.5 (#3253)Ellie Huxtable2026-03-11
| | | | | | | | | | | | <!-- Thank you for making a PR! Bug fixes are always welcome, but if you're adding a new feature or changing an existing one, we'd really appreciate if you open an issue, post on the forum, or drop in on Discord --> ## Checks - [ ] I am happy for maintainers to push small adjustments to this PR, to speed up the review cycle - [ ] I have checked that there are no existing pull requests for the same thing
* chore(release): prepare for release 18.13.0-beta.4 (#3252)Ellie Huxtable2026-03-10
| | | | | | | | | | | | <!-- Thank you for making a PR! Bug fixes are always welcome, but if you're adding a new feature or changing an existing one, we'd really appreciate if you open an issue, post on the forum, or drop in on Discord --> ## Checks - [ ] I am happy for maintainers to push small adjustments to this PR, to speed up the review cycle - [ ] I have checked that there are no existing pull requests for the same thing
* chore: upgrade axum 0.7 to 0.8 to deduplicate with tonic's axumEllie Huxtable2026-03-09
| | | | | | | atuin-server used axum 0.7 while tonic already pulled in axum 0.8, resulting in both versions compiled into the binary. Migrates to axum 0.8: path params use {param} syntax, FromRequestParts uses native async traits (dropping async-trait dep from atuin-server).
* chore: upgrade thiserror 1.x to 2.x to deduplicate dependencyEllie Huxtable2026-03-09
| | | | | | Our crates used thiserror 1.x while the ratatui ecosystem already pulled in thiserror 2.x, resulting in both versions in the binary. The API is compatible; this consolidates to a single version.
* feat: use pty proxy for rendering tui popups without clearing the terminal ↵Ellie Huxtable2026-03-09
| | | | | | | | | | | | | | | | | | (#3234) It feels much, much nicer this way. This has also been asked for pretty consistently since we made inline rendering the default. Now we can have everything :) Maintains a shadow vt100 renderer so that we can restore the terminal state upon popup close. This happens on a background thread, so our impact on terminal performance should still be super minimal, if anything ## Checks - [ ] I am happy for maintainers to push small adjustments to this PR, to speed up the review cycle - [ ] I have checked that there are no existing pull requests for the same thing
* feat: Allow setting multipliers for frequency, recency, and frecency scores ↵Michelle Tilley2026-03-05
| | | | (#3235)
* feat: initial draft of atuin-shell (#3206)Ellie Huxtable2026-03-04
| | | | | | | | | | | | | | | | <!-- Thank you for making a PR! Bug fixes are always welcome, but if you're adding a new feature or changing an existing one, we'd really appreciate if you open an issue, post on the forum, or drop in on Discord --> ## Checks - [ ] I am happy for maintainers to push small adjustments to this PR, to speed up the review cycle - [ ] I have checked that there are no existing pull requests for the same thing --------- Co-authored-by: Claude <noreply@anthropic.com>
* chore(release): prepare for release 18.13.0-beta.3 (#3228)Ellie Huxtable2026-03-02
| | | | | | | | | | | | <!-- Thank you for making a PR! Bug fixes are always welcome, but if you're adding a new feature or changing an existing one, we'd really appreciate if you open an issue, post on the forum, or drop in on Discord --> ## Checks - [ ] I am happy for maintainers to push small adjustments to this PR, to speed up the review cycle - [ ] I have checked that there are no existing pull requests for the same thing
* chore(deps): bump rustix from 0.38.44 to 1.1.4 (#3220)dependabot[bot]2026-03-02
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Bumps [rustix](https://github.com/bytecodealliance/rustix) from 0.38.44 to 1.1.4. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/bytecodealliance/rustix/releases">rustix's releases</a>.</em></p> <blockquote> <h2>1.0.0</h2> <p>This release introduces the <a href="https://docs.rs/rustix/1.0.0/rustix/buffer/trait.Buffer.html"><code>Buffer</code> trait</a>, which is used in <a href="https://docs.rs/rustix/1.0.0/rustix/io/fn.read.html"><code>read</code></a>, <a href="https://docs.rs/rustix/1.0.0/rustix/io/fn.pread.html"><code>pread</code></a>, <a href="https://docs.rs/rustix/1.0.0/rustix/net/fn.recv.html"><code>recv</code></a>, <a href="https://docs.rs/rustix/1.0.0/rustix/net/fn.recvfrom.html"><code>recvfrom</code></a>, <a href="https://docs.rs/rustix/1.0.0/rustix/rand/fn.getrandom.html"><code>getrandom</code></a>, <a href="https://docs.rs/rustix/1.0.0/rustix/fs/fn.readlinkat_raw.html"><code>readlinkat_raw</code></a>, <a href="https://docs.rs/rustix/1.0.0/rustix/event/epoll/fn.wait.html"><code>epoll::wait</code></a>, <a href="https://docs.rs/rustix/1.0.0/x86_64-unknown-freebsd/rustix/event/kqueue/fn.kevent.html"><code>kevent</code></a>, <a href="https://docs.rs/rustix/1.0.0/x86_64-unknown-illumos/rustix/event/port/fn.getn.html"><code>port::getn</code></a>, <a href="https://docs.rs/rustix/1.0.0/rustix/fs/fn.getxattr.html"><code>getxattr</code></a>, <a href="https://docs.rs/rustix/1.0.0/rustix/fs/fn.lgetxattr.html"><code>lgetxattr</code></a>, <a href="https://docs.rs/rustix/1.0.0/rustix/fs/fn.fgetxattr.html"><code>fgetxattr</code></a>, <a href="https://docs.rs/rustix/1.0.0/rustix/fs/fn.listxattr.html"><code>listxattr</code></a>, <a href="https://docs.rs/rustix/1.0.0/rustix/fs/fn.llistxattr.html"><code>llistxattr</code></a>, and <a href="https://docs.rs/rustix/1.0.0/rustix/fs/fn.flistxattr.html"><code>flistxattr</code></a>, and adds support for reading data into uninitialized buffers, as well as safely reading data into the spare capacity of <code>Vec</code>s.</p> <p>This release also simplifies the way network addresses are handled. Instead of having separate functions with <code>_v4</code>, <code>_v6</code>, <code>_unix</code>, <code>_xdp</code>, and now <code>_netlink</code> suffixes, rustix now uses a <a href="https://docs.rs/rustix/1.0.0/rustix/net/trait.SocketAddrArg.html"><code>SocketAddrArg</code> trait</a> so that functions such as <a href="https://docs.rs/rustix/1.0.0/rustix/net/fn.bind.html"><code>bind</code></a>, <a href="https://docs.rs/rustix/1.0.0/rustix/net/fn.connect.html"><code>connect</code></a>, <a href="https://docs.rs/rustix/1.0.0/rustix/net/fn.sendto.html"><code>sendto</code></a>, and <a href="https://docs.rs/rustix/1.0.0/rustix/net/fn.sendmsg_addr.html"><code>sendmsg_addr</code></a> can accept any type of address, and are easier to extend to new address types in the future.</p> <p>And, this release simplifies the <code>ioctl</code> API, replacing opcode wrapper types with const generics.</p> <p>This updates several APIs to add Linux 6.13 features, and raw linux-raw-sys types are no longer exposed in the public API, so it should be easier to stay up to date with new Linux releases.</p> <p>And many more new features, bug fixes, and cleanups. See the <a href="https://github.com/bytecodealliance/rustix/blob/main/CHANGES.md#changes-from-038x-to-1x">CHANGES.md file</a> for the full list of breaking changes.</p> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/bytecodealliance/rustix/commit/c4caf5caaa7e93828a2e4a4cdba1dd0171e45717"><code>c4caf5c</code></a> chore: Release rustix version 1.1.4</li> <li><a href="https://github.com/bytecodealliance/rustix/commit/5953a2c6bc7bc97c308a8e6a0fd4a8bf79997117"><code>5953a2c</code></a> Prune pins in CI that are no longer needed. (<a href="https://redirect.github.com/bytecodealliance/rustix/issues/1588">#1588</a>)</li> <li><a href="https://github.com/bytecodealliance/rustix/commit/9116c05d2eab3484748a629e72bdff17117c4f5b"><code>9116c05</code></a> Bump dependencies (<a href="https://redirect.github.com/bytecodealliance/rustix/issues/1567">#1567</a>)</li> <li><a href="https://github.com/bytecodealliance/rustix/commit/5ee0ca360f41b3699b7c543d1153e94c65988610"><code>5ee0ca3</code></a> hurd: Fix l_type and l_whence types (<a href="https://redirect.github.com/bytecodealliance/rustix/issues/1569">#1569</a>)</li> <li><a href="https://github.com/bytecodealliance/rustix/commit/89505893fc3b4b9b9a22625cd3a670f6d6cf2f44"><code>8950589</code></a> Clobber vector registers and do not use preserves_flags in riscv64 syscalls (...</li> <li><a href="https://github.com/bytecodealliance/rustix/commit/7b0d2ae013976c959627598c057644ae8922708e"><code>7b0d2ae</code></a> Update pins for MSRV compatibility (<a href="https://redirect.github.com/bytecodealliance/rustix/issues/1585">#1585</a>)</li> <li><a href="https://github.com/bytecodealliance/rustix/commit/99458d830840dafb8a8c5b8b54cf05beabc2e581"><code>99458d8</code></a> feat(redox): <code>renameat</code> and <code>renameat_with</code> (<a href="https://redirect.github.com/bytecodealliance/rustix/issues/1586">#1586</a>)</li> <li><a href="https://github.com/bytecodealliance/rustix/commit/a9c8dcbbb74df7a7c4ec6cf50629a810bab6500d"><code>a9c8dcb</code></a> Remove reference to yanked crate in README.md (<a href="https://redirect.github.com/bytecodealliance/rustix/issues/1587">#1587</a>)</li> <li><a href="https://github.com/bytecodealliance/rustix/commit/8bf15a0eb444087e4c3ed04e01ed488cc429af2d"><code>8bf15a0</code></a> Drop custom makedev implementation for Redox (<a href="https://redirect.github.com/bytecodealliance/rustix/issues/1582">#1582</a>)</li> <li><a href="https://github.com/bytecodealliance/rustix/commit/74b886d40d7b5209a8d448550e4595e8e06158a1"><code>74b886d</code></a> Update pins for MSRV compatibility (<a href="https://redirect.github.com/bytecodealliance/rustix/issues/1584">#1584</a>)</li> <li>Additional commits viewable in <a href="https://github.com/bytecodealliance/rustix/compare/v0.38.44...v1.1.4">compare view</a></li> </ul> </details> <br /> [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=rustix&package-manager=cargo&previous-version=0.38.44&new-version=1.1.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* chore(deps): bump dashmap from 5.5.3 to 6.1.0 (#3221)dependabot[bot]2026-03-02
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Bumps [dashmap](https://github.com/xacrimon/dashmap) from 5.5.3 to 6.1.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/xacrimon/dashmap/releases">dashmap's releases</a>.</em></p> <blockquote> <h2>v6.1.0</h2> <ul> <li><a href="https://redirect.github.com/xacrimon/dashmap/pull/308">xacrimon/dashmap#308</a></li> </ul> <h2>v6.0.1</h2> <p>This is a patch release, now the main release for v6 as v6.0.0 was yanked shortly after release.</p> <p>Thanks to <a href="https://github.com/JesusGuzmanJr"><code>@​JesusGuzmanJr</code></a> for notifying me about a critical bug that was introduced so that I could resolve it: <a href="https://redirect.github.com/xacrimon/dashmap/issues/304">#304</a>.</p> <p>PRs for this release: <a href="https://redirect.github.com/xacrimon/dashmap/issues/305">#305</a> + <a href="https://github.com/xacrimon/dashmap/commit/d5c8be6213ca85d7e3ccbcc1eb5b95651ce7e253">https://github.com/xacrimon/dashmap/commit/d5c8be6213ca85d7e3ccbcc1eb5b95651ce7e253</a></p> <h2>v6.0.0</h2> <p>This release contains performance optimizations, most notably 10-40% gains on Apple Silicon but also 5-10% gains when measured in Intel Sapphire Rapids. This work was accomplished in:</p> <ul> <li><a href="https://redirect.github.com/xacrimon/dashmap/issues/303">#303</a></li> <li><a href="https://redirect.github.com/xacrimon/dashmap/issues/287">#287</a></li> </ul> <p>Minor QoL improvements were made in:</p> <ul> <li><a href="https://redirect.github.com/xacrimon/dashmap/issues/302">#302</a></li> <li><a href="https://redirect.github.com/xacrimon/dashmap/issues/300">#300</a></li> </ul> <p>Special to the following contributors for making this release possible:</p> <ul> <li><a href="https://github.com/conradludgate"><code>@​conradludgate</code></a></li> <li><a href="https://github.com/arthurprs"><code>@​arthurprs</code></a></li> <li><a href="https://github.com/joshtriplett"><code>@​joshtriplett</code></a></li> <li><a href="https://github.com/dtzxporter"><code>@​dtzxporter</code></a></li> </ul> <h2>v6.0.0-rc.1</h2> <p>This release contains performance optimizations, most notably 10-40% gains on Apple Silicon but also 5-10% gains when measured in Intel Sapphire Rapids. This work was accomplished in:</p> <ul> <li><a href="https://redirect.github.com/xacrimon/dashmap/issues/303">#303</a></li> <li><a href="https://redirect.github.com/xacrimon/dashmap/issues/287">#287</a></li> </ul> <p>Minor QoL improvements were made in:</p> <ul> <li><a href="https://redirect.github.com/xacrimon/dashmap/issues/302">#302</a></li> <li><a href="https://redirect.github.com/xacrimon/dashmap/issues/300">#300</a></li> </ul> <p>Special to the following contributors for making this release possible:</p> <ul> <li><a href="https://github.com/conradludgate"><code>@​conradludgate</code></a></li> <li><a href="https://github.com/arthurprs"><code>@​arthurprs</code></a></li> <li><a href="https://github.com/joshtriplett"><code>@​joshtriplett</code></a></li> <li><a href="https://github.com/dtzxporter"><code>@​dtzxporter</code></a></li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/xacrimon/dashmap/commit/f2d248eb59fe4a06decd8b54a4365ef41400b73c"><code>f2d248e</code></a> v6.1.0</li> <li><a href="https://github.com/xacrimon/dashmap/commit/da6ac5eab31165c57c8487fafd81ade9adb6d158"><code>da6ac5e</code></a> Add typesize::TypeSize implementation for DashMap/DashSet (<a href="https://redirect.github.com/xacrimon/dashmap/issues/308">#308</a>)</li> <li><a href="https://github.com/xacrimon/dashmap/commit/633aadbd812151a54a60b1845d48c312a2135a14"><code>633aadb</code></a> v6.0.1</li> <li><a href="https://github.com/xacrimon/dashmap/commit/d5c8be6213ca85d7e3ccbcc1eb5b95651ce7e253"><code>d5c8be6</code></a> add shrink_to_fit test</li> <li><a href="https://github.com/xacrimon/dashmap/commit/488dbfa908ada92551560991b0b8a0d17e6679f3"><code>488dbfa</code></a> fix deadlock in shrink_to_fit (<a href="https://redirect.github.com/xacrimon/dashmap/issues/305">#305</a>)</li> <li><a href="https://github.com/xacrimon/dashmap/commit/458238c114b5d21b26432ac620835166e07eb115"><code>458238c</code></a> v6.0.0</li> <li><a href="https://github.com/xacrimon/dashmap/commit/1e3df1aa8eb1b2c266eac83765136f0d10d8e21d"><code>1e3df1a</code></a> v6.0.0-rc.1</li> <li><a href="https://github.com/xacrimon/dashmap/commit/bdb86b03b4194a209094f146f250c9d9f62baa85"><code>bdb86b0</code></a> Merge branch 'arthurprs-small-optimizations'</li> <li><a href="https://github.com/xacrimon/dashmap/commit/4cdfc396a35713afdb8feb7183b8ea57c100fbbe"><code>4cdfc39</code></a> fix: merge errors</li> <li><a href="https://github.com/xacrimon/dashmap/commit/74b34f836d7aa65a1f11c86465c7a96a80346624"><code>74b34f8</code></a> Merge branch 'small-optimizations' of github.com:arthurprs/dashmap into arthu...</li> <li>Additional commits viewable in <a href="https://github.com/xacrimon/dashmap/compare/v.5.5.3...v6.1.0">compare view</a></li> </ul> </details> <br /> [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dashmap&package-manager=cargo&previous-version=5.5.3&new-version=6.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* chore: Move atuin ai subcommand into core binary (#3212)Michelle Tilley2026-03-02
|
* fix: Dramatically decrease daemon memory usage (#3211)Michelle Tilley2026-02-26
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Reduces memory usage of the atuin-daemon search index by ~80% through string interning, compact UUID storage, and eliminating redundant data. ## Changes * **Eliminate Vec\<Invocation\>**: Replaced the per-command `Vec<Invocation>` with just `most_recent_id: [u8; 16]` and `most_recent_timestamp: i64`. We only ever needed the most recent history ID for search results - the full invocation history was never used. * **UUID byte storage**: Store UUIDs as `[u8; 16]` instead of 36-byte strings, saving 40 bytes per UUID. * **String interning with lasso**: Use `ThreadedRodeo` to deduplicate `cwd` and `hostname` strings in the filter sets. These values are highly repetitive (most commands run from a small set of directories on the same host), so interning has an outsized effect. * **DashSet → HashSet**: Since `CommandData` lives inside a `DashMap` (already synchronized), the inner sets don't need their own locks. Switched to `HashSet<Spur>` for directories/hosts and `HashSet<[u8; 16]>` for sessions. * **Arc\<str\> for commands**: Changed the `commands` DashMap key and `frecency_map` keys from `String` to `Arc<str>`, enabling zero-copy sharing between the two maps. * **Remove dead code**: Removed `CommandData.command` field that was duplicating the DashMap key. ## Results With 60k history entries, observed memory usage dropped from ~200MB to ~40MB.
* chore(release): prepare for release 18.13.0-beta.2 (#3209)Ellie Huxtable2026-02-26
| | | | | | | | | | | | <!-- Thank you for making a PR! Bug fixes are always welcome, but if you're adding a new feature or changing an existing one, we'd really appreciate if you open an issue, post on the forum, or drop in on Discord --> ## Checks - [ ] I am happy for maintainers to push small adjustments to this PR, to speed up the review cycle - [ ] I have checked that there are no existing pull requests for the same thing
* feat: In-memory search index with atuin daemon (#3201)Michelle Tilley2026-02-26
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ## Summary This PR adds a persistent, in-memory search index to the Atuin daemon, enabling fast fuzzy search without the startup delay of building an index each time the TUI opens. ### Key Changes - **Daemon search service**: A new gRPC service that maintains a Nucleo fuzzy search index in memory - **Real-time index updates**: The daemon listens for history events (new commands, synced records) and updates the index immediately - **Filter mode support**: All existing filter modes work (Global, Host, Session, Directory, Workspace) - **New search engine**: `daemon-fuzzy` search mode that queries the daemon instead of building a local index - **Paged history loading**: Database pagination support for efficient initial index loading - **Configurable logging**: New `[logs]` settings section for daemon and search log configuration - **Component-based daemon architecture**: Refactored daemon internals into a modular, event-driven system - **Fallback to DB search for regex**: Since Nucleo doesn't support regex matching ## Daemon Architecture The daemon has been refactored to use a component-based, event-driven architecture that makes it easier to add new functionality and reason about the system. ### Core Concepts ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ Atuin Daemon │ │ │ │ ┌─────────────┐ ┌──────────────────────────────────────────────────┐ │ │ │ Daemon │ │ Components │ │ │ │ Handle │────▶│ │ │ │ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌────────────┐ │ │ │ │ • emit() │ │ │ History │ │ Search │ │ Sync │ │ │ │ │ • subscribe │ │ │ Component │ │ Component │ │ Component │ │ │ │ │ • settings │ │ │ │ │ │ │ │ │ │ │ │ • databases │ │ │ gRPC service│ │ gRPC service│ │ background │ │ │ │ └─────────────┘ │ │ WIP history │ │ Nucleo index│ │ sync │ │ │ │ │ │ └─────────────┘ └─────────────┘ └────────────┘ │ │ │ │ └──────────────────────────────────────────────────┘ │ │ │ ▲ │ │ ▼ │ │ │ ┌─────────────────────────────────────┴────────────────────────────────┐ │ │ │ Event Bus (broadcast) │ │ │ │ │ │ │ │ HistoryStarted │ HistoryEnded │ RecordsAdded │ SyncCompleted │ ... │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ ▲ │ │ ┌───────────────────────────────────┴──────────────────────────────────┐ │ │ │ Control Service (gRPC) │ │ │ │ External event injection from CLI commands │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────────┘ ``` ### DaemonHandle A lightweight, cloneable handle that provides access to shared daemon resources: - **Event emission**: `handle.emit(DaemonEvent::...)` broadcasts to all components - **Event subscription**: `handle.subscribe()` returns a receiver for the event bus - **Settings**: `handle.settings()` for configuration access - **Databases**: `handle.history_db()` and `handle.store()` for data access ### Component Trait Components implement a simple lifecycle: ```rust #[async_trait] trait Component: Send + Sync { fn name(&self) -> &'static str; async fn start(&mut self, handle: DaemonHandle) -> Result<()>; async fn handle_event(&mut self, event: &DaemonEvent) -> Result<()>; async fn stop(&mut self) -> Result<()>; } ``` ### Event-Driven Design Components communicate via events rather than direct coupling: | Event | Emitted By | Consumed By | |-------|-----------|-------------| | `HistoryStarted` | History gRPC | Search (logging) | | `HistoryEnded` | History gRPC | Search (index update) | | `RecordsAdded` | Sync | Search (index update) | | `HistoryPruned` | CLI (via Control) | Search (index rebuild) | | `HistoryDeleted` | CLI (via Control) | Search (index rebuild) | | `ForceSync` | CLI (via Control) | Sync | | `ShutdownRequested` | Signal handler | All (graceful shutdown) | ### External Event Injection CLI commands can inject events into a running daemon: ```rust // After `atuin history prune` emit_event(DaemonEvent::HistoryPruned).await?; // After deleting specific items emit_event(DaemonEvent::HistoryDeleted { ids }).await?; // Request immediate sync emit_event(DaemonEvent::ForceSync).await?; ``` This ensures the daemon's search index stays in sync with database changes made by CLI commands. ## Search Architecture The search service uses a [forked version of Nucleo](https://github.com/atuinsh/nucleo-ext) that adds filter and scorer callbacks, enabling efficient filtering and frecency-based ranking. ``` ┌────────────────────────────────────────────────────────────────┐ │ Atuin Daemon │ │ │ │ ┌─────────────────┐ ┌──────────────────────────────────┐ │ │ │ Event System │───▶│ Search Component │ │ │ │ │ │ │ │ │ │ • RecordsAdded │ │ ┌────────────────────────────┐ │ │ │ │ • HistoryEnded │ │ │ Deduplicated Index │ │ │ │ │ • HistoryPruned │ │ │ │ │ │ │ └─────────────────┘ │ │ CommandData per command: │ │ │ │ │ │ • Global frecency │ │ │ │ ┌─────────────────┐ │ │ • Filter indexes (sets) │ │ │ │ │ Background Task │ │ │ • Invocation history │ │ │ │ │ │ │ └────────────────────────────┘ │ │ │ │ Rebuilds │ │ │ │ │ │ │ frecency map │ │ ▼ │ │ │ │ every 60s │───▶│ ┌────────────────────────────┐ │ │ │ └─────────────────┘ │ │ Nucleo (forked) │ │ │ │ │ │ │ │ │ │ │ │ • Filter callback │ │ │ │ │ │ • Scorer callback │ │ │ │ │ │ • Fuzzy matching │ │ │ │ │ └────────────────────────────┘ │ │ │ └──────────────────────────────────┘ │ │ │ │ │ │ gRPC (Unix socket) │ └──────────────────────────────────────│─────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ Search TUI (Client) │ │ │ │ 1. Send query + filter mode + context to daemon │ │ 2. Receive matching history IDs (ranked by frecency) │ │ 3. Hydrate full records from local SQLite database │ │ 4. Display results in TUI │ └─────────────────────────────────────────────────────────────────┘ ``` ### Nucleo Fork The [nucleo-ext fork](https://github.com/atuinsh/nucleo-ext) adds two key features to Nucleo: 1. **Filter callback**: Pre-filter items before fuzzy matching (used for directory/host/session filtering) 2. **Scorer callback**: Compute custom scores after matching (used for frecency ranking) ```rust // Filter: only include commands run in current directory nucleo.set_filter(Some(Arc::new(|cmd: &String| { passing_commands.contains(cmd) }))); // Scorer: combine fuzzy score with frecency nucleo.set_scorer(Some(Arc::new(|cmd: &String, fuzzy_score: u32| { let frecency = frecency_map.get(cmd).unwrap_or(0); fuzzy_score + (frecency * 10) }))); ``` ### Deduplicated Index Commands are stored once per unique command text, with metadata tracking all invocations: ```rust struct CommandData { command: String, invocations: Vec<Invocation>, // All times this command was run global_frecency: FrecencyData, // Precomputed frecency score // O(1) filter indexes directories: HashSet<String>, // All cwds where command was run hosts: HashSet<String>, // All hostnames sessions: HashSet<String>, // All session IDs } ``` This deduplication means: - **Fewer items to match**: ~13K unique commands vs ~62K history entries - **O(1) filter checks**: HashSet lookups instead of scanning invocations - **Single frecency score**: Global frecency computed once, used for all filter modes ### Frecency Scoring Frecency (frequency + recency) scoring prioritizes recently and frequently used commands: ```rust fn compute_frecency(count: u32, last_used: i64, now: i64) -> u32 { let age_hours = (now - last_used) / 3600; // Recency: decays over time (half-life ~24 hours) let recency = (100.0 * (-age_hours as f64 / 24.0).exp()) as u32; // Frequency: logarithmic scaling let frequency = (count.ln() * 20.0).min(100.0) as u32; recency + frequency } ``` The frecency map is: - **Precomputed by background task** every 60 seconds - **Never computed inline** during search (no latency impact) - **Graceful fallback**: If unavailable, search works without frecency ranking ### Filter Mode Implementation | Filter Mode | Implementation | |-------------|----------------| | Global | No filter (all commands) | | Directory | `command.directories.contains(cwd)` | | Workspace | `command.directories.any(\|d\| d.starts_with(git_root))` | | Host | `command.hosts.contains(hostname)` | | Session | `command.sessions.contains(session_id)` | Filters are pre-computed into a HashSet before the search, making the filter callback O(1). ### Search Flow 1. **Daemon startup**: Loads history from SQLite in pages, builds deduplicated index 2. **Frecency precompute**: Background task builds frecency map after history loads 3. **Search request**: Client sends query with filter mode and context 4. **Filter**: Pre-computed HashSet determines which commands pass the filter 5. **Match**: Nucleo fuzzy matches the query against command text 6. **Score**: Frecency scorer ranks results (fuzzy score + frecency * 10) 7. **Response**: Returns history IDs for the most recent invocation of each matching command 8. **Hydration**: Client fetches full records from local SQLite ### Configuration ```toml # Enable daemon + autostart [daemon] enabled = true autostart = true # Enable daemon-based fuzzy search [search] search_mode = "daemon-fuzzy" ``` ## Performance Performance varies based on several factors, but in most initial testing with the new architecture shows improvement: * **Nucleo performs searches up to 4.5x faster**: direct DB search averages 18.07ms, but the daemon completes the same queries in 3.99ms. * **IPC overhead is significant, but acceptable**: a significant amount of wall-time is taken up by the transfer of data over IPC (via UDS in this case). This averages to about ~7.8ms and accounts for 66% of client-side wall time. * **Tail latency improves at every layer**: p99 times correspond to initial requests, worst-case query patterns, etc. but the average p99 daemon-based response time is 3.6x better than the associated DB-based search p99 time * **Query complexity no longer impacts performance**: the Nucleo-based search shows consistent 2-7ms times regardless of query pattern. The DB-based search had a 17x variance (3.59ms to 62.46ms). Interestingly, @ellie - who has a larger history store than I do - gets even better performance on the IPC layer. This could use a lot more testing in various edge cases and on various hardware, but seems promising. ### Regular DB search ``` Individual calls for: db_search -------------------------------------------------------------------------------------------------------------- # Wall Busy Idle Fields -------------------------------------------------------------------------------------------------------------- 1 32.25ms 32.20ms 47.70µs {"mode":"Fuzzy","query":"^"} 2 19.48ms 19.40ms 84.20µs {"mode":"Fuzzy","query":"^c"} 3 20.40ms 20.10ms 297.00µs {"mode":"Fuzzy","query":"^ca"} 4 13.07ms 13.00ms 69.90µs {"mode":"Fuzzy","query":"^car"} 5 12.17ms 12.10ms 67.10µs {"mode":"Fuzzy","query":"^carg"} 6 20.78ms 20.70ms 76.60µs {"mode":"Fuzzy","query":"^cargo"} 7 9.15ms 9.10ms 53.20µs {"mode":"Fuzzy","query":"^cargo "} 8 10.24ms 10.00ms 237.00µs {"mode":"Fuzzy","query":"^cargo b"} 9 10.01ms 9.68ms 325.00µs {"mode":"Fuzzy","query":"^cargo bu"} 10 5.89ms 5.83ms 57.20µs {"mode":"Fuzzy","query":"^cargo bui"} 11 8.85ms 8.28ms 568.00µs {"mode":"Fuzzy","query":"^cargo buil"} 12 7.70ms 7.49ms 212.00µs {"mode":"Fuzzy","query":"^cargo build"} 13 3.59ms 3.53ms 57.00µs {"mode":"Fuzzy","query":"^cargo build$"} 14 6.50ms 6.44ms 63.60µs {"mode":"Fuzzy","query":"^cargo "} 15 6.48ms 6.38ms 100.00µs {"mode":"Fuzzy","query":"!"} 16 31.68ms 31.60ms 75.90µs {"mode":"Fuzzy","query":"!g"} 17 62.46ms 62.40ms 58.90µs {"mode":"Fuzzy","query":"!gi"} 18 30.35ms 30.30ms 46.90µs {"mode":"Fuzzy","query":"!git"} 19 53.84ms 53.80ms 40.80µs {"mode":"Fuzzy","query":"!git "} 20 19.24ms 19.20ms 39.70µs {"mode":"Fuzzy","query":"!git c"} 21 22.03ms 22.00ms 34.70µs {"mode":"Fuzzy","query":"!git co"} 22 17.13ms 17.00ms 133.00µs {"mode":"Fuzzy","query":"!git com"} 23 16.14ms 15.90ms 242.00µs {"mode":"Fuzzy","query":"!git comm"} 24 5.11ms 5.08ms 28.60µs {"mode":"Fuzzy","query":"!git commi"} 25 7.31ms 7.26ms 52.70µs {"mode":"Fuzzy","query":"!git commit"} Summary: 25 calls Wall: avg=18.07ms, min=3.59ms, max=62.46ms, p50=13.07ms, p99=62.46ms Busy: avg=17.95ms, min=3.53ms, max=62.40ms, p50=13.00ms, p99=62.40ms ``` ### Daemon-based search **Client** ``` Individual calls for: daemon_search -------------------------------------------------------------------------------------------------------------- # Wall Busy Idle Fields -------------------------------------------------------------------------------------------------------------- 1 13.05ms 2.55ms 10.50ms {"query":"^"} 2 10.65ms 1.40ms 9.25ms {"query":"^c"} 3 10.72ms 1.18ms 9.54ms {"query":"^ca"} 4 5.54ms 485.00µs 5.06ms {"query":"^car"} 5 15.02ms 1.02ms 14.00ms {"query":"^carg"} 6 9.49ms 840.00µs 8.65ms {"query":"^cargo"} 7 5.53ms 555.00µs 4.97ms {"query":"^cargo "} 8 8.56ms 717.00µs 7.84ms {"query":"^cargo b"} 9 12.34ms 1.24ms 11.10ms {"query":"^cargo bu"} 10 8.38ms 650.00µs 7.73ms {"query":"^cargo bui"} 11 13.07ms 770.00µs 12.30ms {"query":"^cargo buil"} 12 17.11ms 709.00µs 16.40ms {"query":"^cargo build"} 13 15.41ms 907.00µs 14.50ms {"query":"^cargo build$"} 14 8.19ms 665.00µs 7.52ms {"query":"^cargo "} 15 7.98ms 1.72ms 6.26ms {"query":"!"} 16 13.56ms 856.00µs 12.70ms {"query":"!g"} 17 8.11ms 624.00µs 7.49ms {"query":"!gi"} 18 14.57ms 775.00µs 13.80ms {"query":"!git"} 19 14.18ms 779.00µs 13.40ms {"query":"!git "} 20 9.62ms 802.00µs 8.82ms {"query":"!git c"} 21 15.50ms 1.50ms 14.00ms {"query":"!git co"} 22 11.58ms 1.48ms 10.10ms {"query":"!git com"} 23 13.82ms 2.12ms 11.70ms {"query":"!git comm"} 24 17.48ms 2.18ms 15.30ms {"query":"!git commi"} 25 14.81ms 1.71ms 13.10ms {"query":"!git commit"} Summary: 25 calls Wall: avg=11.77ms, min=5.53ms, max=17.48ms, p50=12.34ms, p99=17.48ms Busy: avg=1.13ms, min=485.00µs, max=2.55ms, p50=856.00µs, p99=2.55ms ``` **Daemon** ``` Individual calls for: daemon_search_query -------------------------------------------------------------------------------------------------------------- # Wall Busy Idle Fields -------------------------------------------------------------------------------------------------------------- 1 1.75ms 250ns 1.75ms {"query":"^","query_id":1} 2 4.58ms 125ns 4.58ms {"query":"^c","query_id":2} 3 4.39ms 250ns 4.39ms {"query":"^ca","query_id":3} 4 2.52ms 125ns 2.52ms {"query":"^car","query_id":4} 5 4.44ms 250ns 4.44ms {"query":"^carg","query_id":5} 6 3.66ms 167ns 3.66ms {"query":"^cargo","query_id":6} 7 2.38ms 84ns 2.38ms {"query":"^cargo ","query_id":7} 8 4.13ms 84ns 4.13ms {"query":"^cargo b","query_id":8} 9 4.40ms 167ns 4.40ms {"query":"^cargo bu","query_id":9} 10 3.87ms 125ns 3.87ms {"query":"^cargo bui","query_id":10} 11 4.36ms 84ns 4.36ms {"query":"^cargo buil","query_id":11} 12 3.96ms 333ns 3.96ms {"query":"^cargo build","query_id":12} 13 4.61ms 167ns 4.61ms {"query":"^cargo build$","query_id":13} 14 4.20ms 209ns 4.20ms {"query":"^cargo ","query_id":14} 15 238.17µs 167ns 238.00µs {"query":"!","query_id":15} 16 4.44ms 125ns 4.44ms {"query":"!g","query_id":16} 17 3.47ms 83ns 3.47ms {"query":"!gi","query_id":17} 18 4.57ms 125ns 4.57ms {"query":"!git","query_id":18} 19 7.15ms 167ns 7.15ms {"query":"!git ","query_id":19} 20 4.27ms 250ns 4.27ms {"query":"!git c","query_id":20} 21 5.19ms 292ns 5.19ms {"query":"!git co","query_id":21} 22 4.29ms 417ns 4.29ms {"query":"!git com","query_id":22} 23 4.08ms 125ns 4.08ms {"query":"!git comm","query_id":23} 24 4.50ms 167ns 4.50ms {"query":"!git commi","query_id":24} 25 4.35ms 208ns 4.35ms {"query":"!git commit","query_id":25} Summary: 25 calls Wall: avg=3.99ms, min=238.17µs, max=7.15ms, p50=4.29ms, p99=7.15ms Busy: avg=182ns, min=83ns, max=417ns, p50=167ns, p99=417ns ``` **Nucleo matching time (in daemon)** ``` Individual calls for: nucleo_match -------------------------------------------------------------------------------------------------------------- # Wall Busy Idle Fields -------------------------------------------------------------------------------------------------------------- 1 1.73ms 125ns 1.73ms {"query":"^","query_id":1} 2 4.57ms 167ns 4.57ms {"query":"^c","query_id":2} 3 4.37ms 125ns 4.37ms {"query":"^ca","query_id":3} 4 2.51ms 84ns 2.51ms {"query":"^car","query_id":4} 5 4.43ms 125ns 4.43ms {"query":"^carg","query_id":5} 6 3.64ms 125ns 3.64ms {"query":"^cargo","query_id":6} 7 2.37ms 84ns 2.37ms {"query":"^cargo ","query_id":7} 8 4.11ms 125ns 4.11ms {"query":"^cargo b","query_id":8} 9 4.36ms 208ns 4.36ms {"query":"^cargo bu","query_id":9} 10 3.85ms 125ns 3.85ms {"query":"^cargo bui","query_id":10} 11 4.35ms 125ns 4.35ms {"query":"^cargo buil","query_id":11} 12 3.94ms 250ns 3.94ms {"query":"^cargo build","query_id":12} 13 4.59ms 125ns 4.59ms {"query":"^cargo build$","query_id":13} 14 4.18ms 84ns 4.18ms {"query":"^cargo ","query_id":14} 15 220.13µs 125ns 220.00µs {"query":"!","query_id":15} 16 4.43ms 125ns 4.43ms {"query":"!g","query_id":16} 17 3.45ms 125ns 3.45ms {"query":"!gi","query_id":17} 18 4.55ms 125ns 4.55ms {"query":"!git","query_id":18} 19 7.12ms 209ns 7.12ms {"query":"!git ","query_id":19} 20 4.25ms 166ns 4.25ms {"query":"!git c","query_id":20} 21 5.18ms 125ns 5.18ms {"query":"!git co","query_id":21} 22 4.27ms 125ns 4.27ms {"query":"!git com","query_id":22} 23 4.06ms 292ns 4.06ms {"query":"!git comm","query_id":23} 24 4.46ms 166ns 4.46ms {"query":"!git commi","query_id":24} 25 4.31ms 208ns 4.31ms {"query":"!git commit","query_id":25} Summary: 25 calls Wall: avg=3.97ms, min=220.13µs, max=7.12ms, p50=4.27ms, p99=7.12ms Busy: avg=147ns, min=84ns, max=292ns, p50=125ns, p99=292ns ```
* feat: Generate commands or ask questions with `atuin ai` (#3199)Michelle Tilley2026-02-24
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This PR refines the system created in #3178 to be suitable for a v1 release. --- ## Overview `atuin-ai` is a separate binary that allows for generating commands and asking questions from the command line. It is fully opt-in. ## Usage `atuin ai init` will output bindings for your shell. Currently, bash, zsh, and fish are supported. ```bash eval "$(atuin ai init)" ``` Once the hooks are installed, just press `?` on an empty prompt line to call up the TUI. `atuin ai` requires an account on [Atuin Hub](https://hub.atuin.sh/); you will be prompted to log in on first use. ## Features ### Command generation Prompt the LLM to create a command, and get one back, no fuss. Press `enter` to run, or `tab` to insert. ``` ┌Ask questions or generate a command:──────────────────────────┐ │ │ │ > Get a list of running docker containers │ │ │ ├──────────────────────────────────────────────────────────────┤ │ │ │ $ docker ps │ │ │ └────[Enter]: Run [Tab]: Insert [f]: Follow-up [Esc]: Cancel┘ ``` ### Follow-up You can follow-up with `f` to specify a refinement prompt to update the command that will be inserted. ``` ┌Ask questions or generate a command:──────────────────────────┐ │ │ │ > Get a list of running docker containers │ │ │ ├──────────────────────────────────────────────────────────────┤ │ │ │ $ docker ps │ │ │ ├──────────────────────────────────────────────────────────────┤ │ │ │ > Actually I want to get all docker containers │ │ │ ├──────────────────────────────────────────────────────────────┤ │ │ │ $ docker ps -a │ │ │ └────[Enter]: Run [Tab]: Insert [f]: Follow-up [Esc]: Cancel┘ ``` You can also follow-up with questions to get responses in natural language. ``` ┌Ask questions or generate a command:──────────────────────────┐ │ │ │ > Get a list of running docker containers │ │ │ ├──────────────────────────────────────────────────────────────┤ │ │ │ $ docker ps │ │ │ ├──────────────────────────────────────────────────────────────┤ │ │ │ > Actually I want to get all docker containers │ │ │ ├──────────────────────────────────────────────────────────────┤ │ │ │ $ docker ps -a │ │ │ ├──────────────────────────────────────────────────────────────┤ │ │ │ > What other useful flags to `docker ps` should I know? │ │ │ ├──────────────────────────────────────────────────────────────┤ │ │ │ Here are some handy `docker ps` flags: │ │ │ │ - `-q` — Only show container IDs (great for piping to │ │ other commands) │ │ - `-s` — Show container sizes │ │ - `-n 5` — Show the last 5 created containers │ │ - `-l` — Show only the latest created container │ │ - `--no-trunc` — Don't truncate output (shows full IDs and │ │ commands) │ │ - `-f` or `--filter` — Filter by condition, e.g.: │ │ - `-f status=exited` — only exited containers │ │ - `-f name=myapp` — filter by name │ │ - `-f ancestor=nginx` — filter by image │ │ - `--format` — Custom output using Go templates, e.g.: │ │ `--format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"` │ │ │ │ A common combo is `docker ps -aq` to get all container │ │ IDs, useful for bulk operations like `docker rm $(docker │ │ ps -aq)`. │ │ │ └────[Enter]: Run [Tab]: Insert [f]: Follow-up [Esc]: Cancel┘ ``` You can use `enter` or `tab` at any time 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. ``` ┌Ask questions or generate a command:──────────────────────────┐ │ │ │ > What is the latest version of atuin? │ │ │ ├──────────────────────────────────────────────────────────────┤ │ │ │ ✓ Used 2 tools │ │ │ │ The latest version of Atuin is **v18.12.0**, available on │ │ the [GitHub releases │ │ page](https://github.com/atuinsh/atuin/releases). │ │ │ └─────────────────────────────────[f]: Follow-up [Esc]: Cancel┘ ``` ### 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. ``` ┌Ask questions or generate a command:──────────────────────────┐ │ │ │ > Delete all files from $HOME │ │ │ ├──────────────────────────────────────────────────────────────┤ │ │ │ $ rm -rf $HOME/* │ │ │ │ ! ⚠️ This will PERMANENTLY delete ALL files and directories │ │ in your home directory, including documents, downloads, │ │ configurations, SSH keys, and everything else. This is │ │ irreversible and will likely break your system. Also note │ │ this won't delete hidden (dot) files — if you want those │ │ too, that's even more destructive.; [Server] Recursive │ │ delete of critical directory │ │ │ └────[Enter]: Run [Tab]: Insert [f]: Follow-up [Esc]: Cancel┘ ``` --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* chore(deps): Bump prost-related crates (#3203)Cristian Le2026-02-24
| | | | | | | | | | | | | | | | <!-- Thank you for making a PR! Bug fixes are always welcome, but if you're adding a new feature or changing an existing one, we'd really appreciate if you open an issue, post on the forum, or drop in on Discord --> Bumping the prost related crates and avoiding as much compat packages as possible. There's still the axum0.7 compat which is introduced with this change, but the update to get rid of that seems more involved ## Checks - [x] I am happy for maintainers to push small adjustments to this PR, to speed up the review cycle - [x] I have checked that there are no existing pull requests for the same thing (https://github.com/atuinsh/atuin/pull/2896)
* chore(release): prepare for release 18.13.0-beta.1 (#3187)Ellie Huxtable2026-02-13
| | | | | | | | | | | | <!-- Thank you for making a PR! Bug fixes are always welcome, but if you're adding a new feature or changing an existing one, we'd really appreciate if you open an issue, post on the forum, or drop in on Discord --> ## Checks - [ ] I am happy for maintainers to push small adjustments to this PR, to speed up the review cycle - [ ] I have checked that there are no existing pull requests for the same thing
* feat: add autostart and pid management to daemon (#3180)Ellie Huxtable2026-02-13
|
* feat: add Atuin AI inline CLI MVP (#3178)Michelle Tilley2026-02-13
|
* chore(deps): bump time + bytes (#3175)Cristian Le2026-02-12
| | | | | | | | | | | | | | | | | | | | - time >= 0.3.47: RUSTSEC-2026-0009 - bytes >= 1.11.1: RUSTSEC-2026-0007 Did not dive deeply in if this is actually impacting atuin, just picked up the CVE patches that were reported in Fedora downstream. <!-- Thank you for making a PR! Bug fixes are always welcome, but if you're adding a new feature or changing an existing one, we'd really appreciate if you open an issue, post on the forum, or drop in on Discord --> ## Checks - [x] I am happy for maintainers to push small adjustments to this PR, to speed up the review cycle - [x] I have checked that there are no existing pull requests for the same thing Supersedes #3124
* feat: add Hub authentication for future sync + extra features (#3010)Ellie Huxtable2026-02-12
|