| Commit message (Collapse) | Author | Age |
| |
|
|
|
| |
That helps remove duplicated code and rustc/cargo will now also show
dead code correctly.
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
## 18.16.1
### Bug Fixes
- *(shell/xonsh)* Use os.devnull instead of hard-coded /dev/null
([#3464](https://github.com/atuinsh/atuin/issues/3464))
- Atuin update on windows
([#3453](https://github.com/atuinsh/atuin/issues/3453))
- Ensure local key matches remote data before syncing
([#3474](https://github.com/atuinsh/atuin/issues/3474))
### Documentation
- Add related projects section to README
### Features
- *(ui)* Prominent banner for wrong-key errors at login/sync
([#3475](https://github.com/atuinsh/atuin/issues/3475))
### Miscellaneous Tasks
- Generate LLM-optimized docs
([#3468](https://github.com/atuinsh/atuin/issues/3468))
- Rename 'atuin hex' to 'atuin pty-proxy'
([#3473](https://github.com/atuinsh/atuin/issues/3473))
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We rely on the user to manage their keys. This is ok, and is
intentionally part of our security model
However. If the user messes up, they corrupt their remote store. It is
possible to work around and fix, but not without difficulty. This change
ensures that if the local key does not match the remote data, no data is
synced and the user has a chance to fix it before breaking things.
## 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
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
| |
## 18.15.2
### Bug Fixes
- Tab doesn't insert suggested command
([#3420](https://github.com/atuinsh/atuin/issues/3420))
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
| |
<!-- 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
|
| |
|
|
|
|
|
|
|
|
|
|
| |
<!-- 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
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
This is essentially not a useful place to search agent history
Right now, using the CLI is the best way to explore this. We are looking
into building another TUI for searching records more widely and in more
detail
## 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
|
| |
|
|
|
|
|
|
|
|
|
| |
https://github.com/user-attachments/assets/7868c7a4-6a91-4c93-ac6a-e8665cf1f799
## 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
|
| |
|
|
|
|
|
|
|
|
| |
Useful for watching what agents are doing, or viewing live info from
other machines. Regardless I am liking it for debugging
## 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
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
| |
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
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
|
|
|
|
|
| |
<!-- 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
|
| |
|
|
|
|
|
|
|
|
|
|
| |
<!-- 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
|
| |
|
|
|
|
|
|
|
|
|
|
| |
<!-- 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
|
| |
|
|
|
|
|
| |
* Run Atuin AI's `init` during main `init` for bash, zsh, and fish
* Note that logging into Hub will enable sync
* Add instructions for users with existing sync accounts
* Ensure daemon respects `auto_sync` setting
* Update docs on disabling Atuin AI
|
| |
|
|
|
|
|
|
|
|
|
|
| |
<!-- 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
|
| |
|
|
|
|
|
|
|
|
|
|
| |
<!-- 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
|
| |
|
|
| |
(#3235)
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
<!-- 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>
|
| |
|
|
|
|
|
|
|
|
|
|
| |
<!-- 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
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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 />
[](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>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
<!-- 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
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
## 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
```
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
<!-- Thank you for making a PR! Bug fixes are always welcome, but if
you're adding a new feature or changing an existing one, we'd really
appreciate if you open an issue, post on the forum, or drop in on
Discord -->
## Checks
- [x] I am happy for maintainers to push small adjustments to this PR,
to speed up the review cycle
- [x] I have checked that there are no existing pull requests for the
same thing
Adds `author` and `intent` to client history records and DB persistence,
including migration/backfill and CLI/daemon propagation.
Introduces V2 record-store history version `v1` while retaining read
compatibility for legacy `v0` records.
Adds `--author` and `--intent` flags to `atuin history start`, plus
`{author}` and `{intent}` format keys for listing/history output.
Updates shell-integration docs for `ATUIN_HISTORY_AUTHOR` and
`ATUIN_HISTORY_INTENT`, and updates related tests/fixtures.
Validated with `cargo test -p atuin-client --lib`, `cargo test -p
atuin-daemon --tests`, `cargo test -p atuin search::inspector`, and
`cargo fmt --check`.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
<!-- 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)
|
| |
|
|
|
|
|
|
|
|
|
|
| |
<!-- 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
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
| |
<!-- 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
|
| |
|
|
|
|
|
|
|
|
|
|
| |
<!-- 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
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
| |
<!-- 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
|
| |
|
|
|
|
|
|
|
|
|
|
| |
<!-- 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
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
These files have been known to have corruption issues. SQLite will
perform better across filesystems for reads/writes across threads, and
will lock as expected.
I've also put the session file in there, though I'm 50/50 on it - I'll
be replacing it with keyring storage asap anyway.
The key file is _not_ included. It should ~never be changed, and should
be easy for the user to secure + manage themselves
In the future, instead of creating more files, we can just use this as a
kv store
Resolves https://github.com/atuinsh/atuin/issues/2336, resolves
https://github.com/atuinsh/atuin/issues/1650
## 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
|
| |
|
|
|
|
|
|
|
|
|
|
| |
<!-- 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
|
| |
|
|
|
|
|
|
|
|
|
|
| |
<!-- 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
|
| |
|
|
|
|
|
|
|
|
|
|
| |
<!-- 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
|