aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2026-06-10 21:32:08 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2026-06-10 21:32:08 +0200
commit796a8f59a61ed6e54d0d2b41a5d0155c5bb9696b (patch)
tree538a0b1dac22b5aec2b65e67a0115369f44a1d88
parentfeat: Capture command output + expose to new `atuin_output` tool (#3510) (diff)
downloadatuin-796a8f59a61ed6e54d0d2b41a5d0155c5bb9696b.zip
chore: Remove unneeded files
-rw-r--r--.atuin/skills/release/SKILL.md213
-rw-r--r--.claude/skills/hunk/SKILL.md154
-rw-r--r--.claude/skills/release/SKILL.md269
-rw-r--r--.depot/workflows/codespell.yml28
-rw-r--r--.depot/workflows/installer.yml36
-rw-r--r--.depot/workflows/nix.yml33
-rw-r--r--.depot/workflows/rust.yml187
-rw-r--r--.depot/workflows/shellcheck.yml20
-rw-r--r--.depot/workflows/update-nix-deps.yml25
-rw-r--r--.dockerignore2
-rw-r--r--.fossier.dbbin1576960 -> 0 bytes
-rw-r--r--.github/DISCUSSION_TEMPLATE/support.yml84
-rw-r--r--.github/FUNDING.yml13
-rw-r--r--.github/ISSUE_TEMPLATE/bug.yaml39
-rw-r--r--.github/dependabot.yml19
-rw-r--r--.github/pull_request_template.md5
-rw-r--r--.github/workflows/codespell.yml28
-rw-r--r--.github/workflows/docker.yaml61
-rw-r--r--.github/workflows/fossier-scan.yml51
-rw-r--r--.github/workflows/fossier.yml29
-rw-r--r--.github/workflows/installer.yml38
-rw-r--r--.github/workflows/nix.yml34
-rw-r--r--.github/workflows/release.yml304
-rw-r--r--.github/workflows/rust.yml230
-rw-r--r--.github/workflows/shellcheck.yml18
-rw-r--r--.github/workflows/update-nix-deps.yml21
-rw-r--r--.rustfmt.toml4
-rw-r--r--AGENTS.md71
-rw-r--r--Dockerfile36
-rw-r--r--VOUCHED.td278
-rw-r--r--atuin.plugin.zsh6
l---------contrib/pi/atuin.ts1
-rw-r--r--demo.gifbin372559 -> 0 bytes
-rw-r--r--depot.json1
-rw-r--r--dist-workspace.toml29
-rw-r--r--docs-i18n/.gitignore20
-rw-r--r--docs-i18n/ru/config_ru.md146
-rw-r--r--docs-i18n/ru/import_ru.md27
-rw-r--r--docs-i18n/ru/key-binding_ru.md39
-rw-r--r--docs-i18n/ru/list_ru.md11
-rw-r--r--docs-i18n/ru/search_ru.md38
-rw-r--r--docs-i18n/ru/server_ru.md160
-rw-r--r--docs-i18n/ru/shell-completions_ru.md20
-rw-r--r--docs-i18n/ru/stats_ru.md40
-rw-r--r--docs-i18n/ru/sync_ru.md60
-rw-r--r--docs-i18n/zh-CN/README.md234
-rw-r--r--docs-i18n/zh-CN/config.md137
-rw-r--r--docs-i18n/zh-CN/docker.md90
-rw-r--r--docs-i18n/zh-CN/import.md25
-rw-r--r--docs-i18n/zh-CN/k8s.md195
-rw-r--r--docs-i18n/zh-CN/key-binding.md48
-rw-r--r--docs-i18n/zh-CN/list.md11
-rw-r--r--docs-i18n/zh-CN/search.md37
-rw-r--r--docs-i18n/zh-CN/server.md75
-rw-r--r--docs-i18n/zh-CN/shell-completions.md19
-rw-r--r--docs-i18n/zh-CN/stats.md35
-rw-r--r--docs-i18n/zh-CN/sync.md51
-rw-r--r--fossier.toml17
-rwxr-xr-xinstall.sh197
-rw-r--r--k8s/atuin.yaml156
-rw-r--r--k8s/namespaces.yaml6
-rw-r--r--k8s/secrets.yaml13
-rw-r--r--rust-toolchain.toml2
-rwxr-xr-xscripts/release.sh508
-rwxr-xr-xscripts/span-table.ts420
65 files changed, 2 insertions, 5202 deletions
diff --git a/.atuin/skills/release/SKILL.md b/.atuin/skills/release/SKILL.md
deleted file mode 100644
index bfe49f4d..00000000
--- a/.atuin/skills/release/SKILL.md
+++ /dev/null
@@ -1,213 +0,0 @@
----
-name: release
-description: >
- Orchestrate a multi-step Atuin CLI release — version bumping, changelog
- generation, PR creation, tagging, and crates.io publishing. Invoke with
- /release or /release <version>.
-disable-model-invocation: true
-argument-hint: [version]
----
-
-# Atuin CLI Release
-
-You are orchestrating a release of the Atuin CLI. Follow the steps below
-**in order**, pausing at each checkpoint for user confirmation. Do not skip
-steps or combine them.
-
-## Current State
-
-- Workspace version: !`sed -n '/^\[workspace\.package\]/,/^\[/s/^version = "\(.*\)"/\1/p' Cargo.toml`
-- Latest tag: !`git describe --tags --abbrev=0 2>/dev/null || echo "none"`
-- Suggested next version: !`git-cliff --bumped-version 2>/dev/null | sed 's/^v//' || echo "(unknown)"`
-
----
-
-## Step 1 — Check Dependencies
-
-Verify these tools are installed: `git`, `gsed`, `cargo`, `gh`, `git-cliff`.
-
-Use `command -v` for each. If any are missing, report which ones and stop.
-
-Remember to use `gsed`, or else macOS flags to regular `sed`, later in the workflow.
-
----
-
-## Step 2 — Determine Version
-
-The target version may be provided as `$ARGUMENTS`. If it's empty, use
-AskUserQuestion to ask for the new version (show the current state above
-for reference).
-
-After determining the version:
-- If it contains a `-` (e.g. `18.15.0-beta.1`), it is a **prerelease**.
- Note this — it affects changelog and publish behavior later.
-- Show the user: `current → new` and whether it's a prerelease.
-- **Checkpoint:** Ask the user to confirm before proceeding.
-
----
-
-## Step 3 — Set Up Working Directory
-
-Clone a fresh copy into a temp directory:
-
-```bash
-WORKDIR=$(mktemp -d)
-git clone git@github.com:atuinsh/atuin.git "$WORKDIR"
-```
-
-Print the working directory path so the user can find it if needed.
-
-NOTE:
-ALL subsequent Bash commands run from `$WORKDIR`.
-
----
-
-## Step 4 — Create Branch & Update Versions
-
-1. Create a release branch named after the version (no `v` prefix):
- `git checkout -b <VERSION>`
-
-2. Replace the old version with the new one in all `Cargo.toml` files.
- **Escape dots** in the old version so sed treats them literally:
-
- ```bash
- VERSION_PATTERN="${OLD_VERSION//./\\.}"
- find . -type f -name 'Cargo.toml' -not -path './.git/*' \
- -exec gsed -i "s/$VERSION_PATTERN/$NEW_VERSION/g" {} \;
- ```
-
-3. Run `cargo check` to update `Cargo.lock`.
-
-4. Show `git diff --stat` and the version-related lines from the diff:
- ```bash
- git diff --unified=0 -- '*.toml' | grep '^\+.*version' | grep -vF '+++'
- ```
- Remember to use macOS grep arguments on macOS systems.
-
-5. Verify the workspace version was actually updated by re-reading it
- from `Cargo.toml`.
-
-6. **Checkpoint:** Show the diff summary and ask the user to confirm the
- version changes look correct.
-
----
-
-## Step 5 — Update Changelog
-
-The changelog strategy differs for prereleases vs stable releases:
-
-- **Prerelease:** Maintain a running `## [unreleased]` section containing
- all changes since the last stable release. Use:
- `git-cliff --unreleased --strip all`
- (cliff.toml's `ignore_tags` already ignores beta/alpha tags, so
- `--unreleased` spans back to the last stable release automatically.)
-
-- **Stable release:** Generate a versioned entry that replaces the
- `[unreleased]` section. Use:
- `git-cliff --unreleased --tag "v<VERSION>" --strip all`
-
-Then update `CHANGELOG.md`:
-
-1. If an existing `## [unreleased]` or `## [Unreleased]` section exists,
- **remove it entirely** (the heading and all content up to the next
- `## ` heading).
-
-2. Insert the new entry before the first existing `## ` version heading.
-
-3. **Checkpoint:** Read and display the new changelog entry to the user.
- Ask if they want any edits. If so, make the requested changes using
- the Edit tool. Repeat until they're satisfied.
-
----
-
-## Step 6 — Commit & Push
-
-Stage all changes and commit:
-
-```
-chore(release): prepare for release <VERSION>
-```
-
-Push the branch with `--set-upstream origin`.
-
----
-
-## Step 7 — Create PR & Wait for Merge
-
-### Create the PR
-
-Extract the changelog entry body (everything between the new `## ` heading
-and the next one) for the PR description.
-
-For prereleases, the heading to match is `## [unreleased]`.
-For stable releases, it's `## <VERSION>` (escape dots in the awk pattern).
-
-Create the PR:
-```bash
-gh pr create \
- --title "chore(release): prepare for release <VERSION>" \
- --body "<body with changelog>" \
- --repo atuinsh/atuin
- --draft
-```
-
-Show the PR URL to the user. Tell the user to go review and merge the PR.
-
-When the user reports the PR is merged, proceed to the next step.
-
----
-
-## Step 8 — Tag Release
-
-Back in the working directory:
-
-```bash
-git checkout main
-git pull
-git tag "v<VERSION>"
-git push --tags
-```
-
-Tell the user the tag was pushed and the release CI workflow has been
-triggered.
-
----
-
-## Step 9 — Publish to crates.io
-
-**If this is a prerelease**, skip this step entirely and tell the user.
-
-**If this is a stable release**, ask the user whether to publish.
-
-If yes, publish each crate **in dependency order** using `--no-verify`
-(the code already passed CI, and verification fails when crates.io
-hasn't indexed a freshly-published dependency yet):
-
-```
-atuin-common, atuin-client, atuin-ai, atuin-dotfiles, atuin-history,
-atuin-nucleo/matcher, atuin-nucleo, atuin-daemon, atuin-kv,
-atuin-scripts, atuin-server-database, atuin-server-postgres,
-atuin-server-sqlite, atuin-server, atuin-pty-proxy, atuin
-```
-
-For each crate, run from `crates/<name>`:
-```bash
-cargo publish --no-verify 2>&1
-```
-
-If it fails with "already uploaded", report it as a skip (not an error) —
-some crates like `atuin-nucleo` are versioned independently and may
-already be published at their current version.
-
-If it fails for any other reason, stop and report the error.
-
----
-
-## Completion
-
-Summarize what was done:
-- Version released
-- PR URL
-- Tag name
-- Which crates were published (if any)
-- Working directory path and how to clean it up (`rm -rf`)
diff --git a/.claude/skills/hunk/SKILL.md b/.claude/skills/hunk/SKILL.md
deleted file mode 100644
index 2306293f..00000000
--- a/.claude/skills/hunk/SKILL.md
+++ /dev/null
@@ -1,154 +0,0 @@
----
-name: hunk-review
-description: Interacts with live Hunk diff review sessions via CLI. Inspects review focus, navigates files and hunks, reloads session contents, and adds inline review comments. Use when the user has a Hunk session running or wants to review diffs interactively.
----
-
-# Hunk Review
-
-Hunk is an interactive terminal diff viewer. The TUI is for the user -- do NOT run `hunk diff`, `hunk show`, or other interactive commands directly. Use `hunk session *` CLI commands to inspect and control live sessions through the local daemon.
-
-If no session exists, ask the user to launch Hunk in their terminal first.
-
-## Workflow
-
-```text
-1. hunk session list # find live sessions
-2. hunk session get --repo . # inspect path / repo / source
-3. hunk session review --repo . --json # inspect file/hunk structure first
-4. hunk session review --repo . --include-patch --json # opt into raw diff text only when needed
-5. hunk session context --repo . # check current focus when needed
-6. hunk session navigate ... # move to the right place
-7. hunk session reload -- <command> # swap contents if needed
-8. hunk session comment add ... # leave one review note
-9. hunk session comment apply ... # apply many agent notes in one stdin batch
-```
-
-## Session selection
-
-Most session commands accept:
-
-- `--repo <path>` -- match the live session by its current loaded repo root (most common)
-- `<session-id>` -- match by exact ID (use when multiple sessions share a repo)
-- If only one session exists, it auto-resolves
-
-`reload` also supports:
-
-- `--session-path <path>` -- match the live Hunk window by its current working directory
-- `--source <path>` -- load the replacement `diff` / `show` command from a different directory
-
-Use `--source` only for advanced reloads where the live session you want to control is not already associated with the checkout you want to load next. For a normal worktree session, prefer selecting it directly with `--repo /path/to/worktree`.
-
-## Commands
-
-### Inspect
-
-```bash
-hunk session list [--json]
-hunk session get (--repo . | <id>) [--json]
-hunk session context (--repo . | <id>) [--json]
-hunk session review (--repo . | <id>) [--json] [--include-patch]
-```
-
-- `get` shows the session `Path`, `Repo`, and `Source`, which helps when choosing between `--repo` and `--session-path`
-- `Repo` is what `--repo` matches; `Path` is what `--session-path` matches
-- `review --json` returns file and hunk structure by default; add `--include-patch` only when a caller truly needs raw unified diff text
-
-### Navigate
-
-Absolute navigation requires `--file` and exactly one of `--hunk`, `--new-line`, or `--old-line`:
-
-```bash
-hunk session navigate --repo . --file src/App.tsx --hunk 2
-hunk session navigate --repo . --file src/App.tsx --new-line 372
-hunk session navigate --repo . --file src/App.tsx --old-line 355
-```
-
-Relative comment navigation jumps between annotated hunks and does not require `--file`:
-
-```bash
-hunk session navigate --repo . --next-comment
-hunk session navigate --repo . --prev-comment
-```
-
-- `--hunk <n>` is 1-based
-- `--new-line` / `--old-line` are 1-based line numbers on that diff side
-- Use either `--next-comment` or `--prev-comment`, not both
-
-### Reload
-
-Swaps the live session's contents. Pass a Hunk review command after `--`:
-
-```bash
-hunk session reload --repo . -- diff
-hunk session reload --repo . -- diff main...feature -- src/ui
-hunk session reload --repo . -- show HEAD~1
-hunk session reload --repo . -- show HEAD~1 -- README.md
-hunk session reload --repo /path/to/worktree -- diff
-hunk session reload --session-path /path/to/live-window --source /path/to/other-checkout -- diff
-```
-
-- Always include `--` before the nested Hunk command
-- `--repo` or `<session-id>` usually selects the session you want
-- `--source` is advanced: it does not select the session; it only changes where the replacement review command runs
-- If the live session is already showing the target worktree, prefer `hunk session reload --repo /path/to/worktree -- diff`
-- `--session-path` targets the live window when you need to keep session selection separate from reload source
-
-### Comments
-
-```bash
-hunk session comment add --repo . --file README.md --new-line 103 --summary "Tighten this wording" [--rationale "..."] [--author "agent"] [--focus]
-printf '%s\n' '{"comments":[{"filePath":"README.md","newLine":103,"summary":"Tighten this wording"}]}' | hunk session comment apply --repo . --stdin [--focus]
-hunk session comment list --repo . [--file README.md]
-hunk session comment rm --repo . <comment-id>
-hunk session comment clear --repo . --yes [--file README.md]
-```
-
-- `comment add` is best for one note; `comment apply` is best when an agent already has several notes ready
-- `comment add` requires `--file`, `--summary`, and exactly one of `--old-line` or `--new-line`
-- `comment apply` payload items require `filePath`, `summary`, and exactly one target such as `hunk`, `hunkNumber`, `oldLine`, or `newLine`
-- `comment apply` reads a JSON batch from stdin and validates the full batch before mutating the live session
-- Pass `--focus` when you want to jump to the new note or the first note in a batch
-- `comment list` and `comment clear` accept optional `--file`
-- Quote `--summary` and `--rationale` defensively in the shell
-
-## New files in working-tree reviews
-
-`hunk diff` includes untracked files by default. If the user wants tracked changes only, reload with `--exclude-untracked`:
-
-```bash
-hunk session reload --repo . -- diff --exclude-untracked
-```
-
-## Guiding a review
-
-The user may ask you to walk them through a changeset or review code using Hunk. Start with `hunk session review --json` to understand the file/hunk structure without inflating agent context, then use `--include-patch` only for the files you truly need to read in raw diff form. Use `context` and `navigate` to line up the user's current view before adding comments.
-
-Your role is to narrate: steer the user's view to what matters and leave comments that explain what they're looking at.
-
-Typical flow:
-
-1. Load the right content (`reload` if needed)
-2. Navigate to the first interesting file / hunk
-3. Add a comment explaining what's happening and why
-4. If you already have several notes ready, prefer one `comment apply` batch over many separate shell invocations
-5. Summarize when done
-
-Guidelines:
-
-- Work in the order that tells the clearest story, not necessarily file order
-- Navigate before commenting so the user sees the code you're discussing
-- Use `comment apply` for agent-generated batches and `comment add` for one-off notes
-- Use `--focus` sparingly when the note itself should actively steer the review
-- Keep comments focused: intent, structure, risks, or follow-ups
-- Don't comment on every hunk -- highlight what the user wouldn't spot themselves
-
-## Common errors
-
-- **"No visible diff file matches ..."** -- the file is not in the loaded review. Check `context`, then `reload` if needed.
-- **"No active Hunk sessions"** -- ask the user to open Hunk in their terminal.
-- **"Multiple active sessions match"** -- pass `<session-id>` explicitly.
-- **"No active Hunk session matches session path ..."** -- for advanced split-path reloads, verify the live window `Path` via `hunk session get` or `list`, then use `--session-path`.
-- **"Pass the replacement Hunk command after `--`"** -- include `--` before the nested `diff` / `show` command.
-- **"Pass --stdin to read batch comments from stdin JSON."** -- `comment apply` only reads its batch payload from stdin.
-- **"Specify exactly one navigation target"** -- pick one of `--hunk`, `--old-line`, or `--new-line`.
-- **"Specify either --next-comment or --prev-comment, not both."** -- choose one comment-navigation direction.
diff --git a/.claude/skills/release/SKILL.md b/.claude/skills/release/SKILL.md
deleted file mode 100644
index a90efc69..00000000
--- a/.claude/skills/release/SKILL.md
+++ /dev/null
@@ -1,269 +0,0 @@
----
-name: release
-description: >
- Orchestrate a multi-step Atuin CLI release — version bumping, changelog
- generation, PR creation, tagging, and crates.io publishing. Invoke with
- /release or /release <version>.
-disable-model-invocation: true
-argument-hint: [version]
----
-
-# Atuin CLI Release
-
-You are orchestrating a release of the Atuin CLI. Follow the steps below
-**in order**, pausing at each checkpoint for user confirmation. Do not skip
-steps or combine them.
-
-## Current State
-
-- Workspace version: !`sed -n '/^\[workspace\.package\]/,/^\[/s/^version = "\(.*\)"/\1/p' Cargo.toml`
-- Latest tag: !`git describe --tags --abbrev=0 2>/dev/null || echo "none"`
-- Suggested next version: !`git-cliff --bumped-version 2>/dev/null | sed 's/^v//' || echo "(unknown)"`
-
----
-
-## Step 1 — Check Dependencies
-
-Verify these tools are installed: `git`, `gsed`, `cargo`, `gh`, `git-cliff`.
-
-Use `command -v` for each. If any are missing, report which ones and stop.
-
----
-
-## Step 2 — Determine Version
-
-The target version may be provided as `$ARGUMENTS`. If it's empty, use
-AskUserQuestion to ask for the new version (show the current state above
-for reference).
-
-After determining the version:
-- If it contains a `-` (e.g. `18.15.0-beta.1`), it is a **prerelease**.
- Note this — it affects changelog and publish behavior later.
-- Show the user: `current → new` and whether it's a prerelease.
-- **Checkpoint:** Ask the user to confirm before proceeding.
-
----
-
-## Step 3 — Set Up Working Directory
-
-Clone a fresh copy into a temp directory:
-
-```bash
-WORKDIR=$(mktemp -d)
-git clone git@github.com:atuinsh/atuin.git "$WORKDIR"
-```
-
-Print the working directory path so the user can find it if needed.
-All subsequent Bash commands run from `$WORKDIR`.
-
----
-
-## Step 4 — Create Branch & Update Versions
-
-1. Create a release branch named after the version (no `v` prefix):
- `git checkout -b <VERSION>`
-
-2. Replace the old version with the new one in all `Cargo.toml` files.
- **Escape dots** in the old version so sed treats them literally:
-
- ```bash
- VERSION_PATTERN="${OLD_VERSION//./\\.}"
- find . -type f -name 'Cargo.toml' -not -path './.git/*' \
- -exec gsed -i "s/$VERSION_PATTERN/$NEW_VERSION/g" {} \;
- ```
-
-3. Run `cargo check` to update `Cargo.lock`.
-
-4. Show `git diff --stat` and the version-related lines from the diff:
- ```bash
- git diff --unified=0 -- '*.toml' | grep -E '^\+.*version' | grep -v '^\+\+\+'
- ```
-
-5. Verify the workspace version was actually updated by re-reading it
- from `Cargo.toml`.
-
-6. **Checkpoint:** Show the diff summary and ask the user to confirm the
- version changes look correct.
-
----
-
-## Step 5 — Update Changelog
-
-The changelog strategy differs for prereleases vs stable releases:
-
-- **Prerelease:** Maintain a running `## [unreleased]` section containing
- all changes since the last stable release. Use:
- `git-cliff --unreleased --strip all`
- (cliff.toml's `ignore_tags` already ignores beta/alpha tags, so
- `--unreleased` spans back to the last stable release automatically.)
-
-- **Stable release:** Generate a versioned entry that replaces the
- `[unreleased]` section. Use:
- `git-cliff --unreleased --tag "v<VERSION>" --strip all`
-
-Then update `CHANGELOG.md`:
-
-1. If an existing `## [unreleased]` or `## [Unreleased]` section exists,
- **remove it entirely** (the heading and all content up to the next
- `## ` heading).
-
-2. Insert the new entry before the first existing `## ` version heading.
-
-3. **Checkpoint:** Read and display the new changelog entry to the user.
- Ask if they want any edits. If so, make the requested changes using
- the Edit tool. Repeat until they're satisfied.
-
----
-
-## Step 6 — Commit & Push
-
-Stage all changes and commit:
-
-```
-chore(release): prepare for release <VERSION>
-```
-
-Push the branch with `--set-upstream origin`.
-
----
-
-## Step 7 — Create PR & Wait for Merge
-
-### Create the PR
-
-Extract the changelog entry body (everything between the new `## ` heading
-and the next one) for the PR description.
-
-For prereleases, the heading to match is `## [unreleased]`.
-For stable releases, it's `## <VERSION>` (escape dots in the awk pattern).
-
-Create the PR:
-```bash
-gh pr create \
- --title "chore(release): prepare for release <VERSION>" \
- --body "<body with changelog>" \
- --repo atuinsh/atuin
-```
-
-Show the PR URL to the user.
-
-### Wait for merge
-
-Start a **persistent Monitor** that polls the PR status every 30 seconds.
-The monitor script must:
-- **Only emit output** on meaningful state changes: all checks green, PR
- merged, or PR closed. Silent polls keep the monitor quiet and avoid
- flooding notifications.
-- Handle transient API errors gracefully (don't crash on a single failure)
-- Exit 0 on `MERGED`, exit 1 on `CLOSED`
-
-The rollup mixes two entry shapes: `CheckRun` entries use `status` +
-`conclusion`, while `StatusContext` entries use `state`. A check counts
-as "passing" when it's in a terminal state with a non-failing outcome.
-Treat `SUCCESS`, `SKIPPED`, and `NEUTRAL` as passing — some release
-workflows (e.g. `announce`, `build-global-artifacts`) are conditional
-and report `SKIPPED` on non-tag events, which is expected, not a
-failure.
-
-Example monitor script (substitute the actual PR number):
-```bash
-checks_passed=false
-while true; do
- json=$(gh pr view PR_NUM --repo atuinsh/atuin --json state,statusCheckRollup 2>/dev/null) || { sleep 30; continue; }
- state=$(echo "$json" | jq -r '.state')
- case "$state" in
- MERGED) echo "PR #PR_NUM has been merged!"; exit 0 ;;
- CLOSED) echo "PR #PR_NUM was closed without merging."; exit 1 ;;
- esac
- # Only notify once when all checks reach a terminal passing state.
- # CheckRun entries carry `status`/`conclusion`; StatusContext entries
- # carry `state`. SKIPPED and NEUTRAL count as passing.
- if [ "$checks_passed" = false ]; then
- counts=$(echo "$json" | jq -r '
- [.statusCheckRollup[]?] as $all
- | ($all | map(select(
- (.status == "COMPLETED" and (.conclusion | IN("SUCCESS","SKIPPED","NEUTRAL")))
- or .state == "SUCCESS"
- )) | length) as $passing
- | ($all | map(select(
- (.status == "COMPLETED" and (.conclusion | IN("FAILURE","TIMED_OUT","CANCELLED","ACTION_REQUIRED","STALE")))
- or (.state | IN("FAILURE","ERROR"))
- )) | length) as $failing
- | "\($all | length) \($passing) \($failing)"
- ' 2>/dev/null)
- read -r total passing failing <<<"$counts"
- if [ "${failing:-0}" -gt 0 ] 2>/dev/null; then
- echo "PR #PR_NUM has $failing failing check(s) — investigate before merging."
- checks_passed=true # don't re-notify
- elif [ "${total:-0}" -gt 0 ] 2>/dev/null && [ "$total" = "$passing" ]; then
- echo "All $total checks passed on PR #PR_NUM — ready to merge!"
- checks_passed=true
- fi
- fi
- sleep 30
-done
-```
-
-Tell the user to go review and merge the PR. While the monitor runs, you
-can respond to other questions — the monitor notifications will arrive
-asynchronously.
-
-When the monitor reports `MERGED`, proceed to the next step.
-If it reports `CLOSED`, inform the user and stop the release.
-
----
-
-## Step 8 — Tag Release
-
-Back in the working directory:
-
-```bash
-git checkout main
-git pull
-git tag "v<VERSION>"
-git push --tags
-```
-
-Tell the user the tag was pushed and the release CI workflow has been
-triggered.
-
----
-
-## Step 9 — Publish to crates.io
-
-**If this is a prerelease**, skip this step entirely and tell the user.
-
-**If this is a stable release**, ask the user whether to publish.
-
-If yes, publish each crate **in dependency order** using `--no-verify`
-(the code already passed CI, and verification fails when crates.io
-hasn't indexed a freshly-published dependency yet):
-
-```
-atuin-common, atuin-client, atuin-ai, atuin-dotfiles, atuin-history,
-atuin-nucleo/matcher, atuin-nucleo, atuin-daemon, atuin-kv,
-atuin-scripts, atuin-server-database, atuin-server-postgres,
-atuin-server-sqlite, atuin-server, atuin-pty-proxy, atuin
-```
-
-For each crate, run from `crates/<name>`:
-```bash
-cargo publish --no-verify 2>&1
-```
-
-If it fails with "already uploaded", report it as a skip (not an error) —
-some crates like `atuin-nucleo` are versioned independently and may
-already be published at their current version.
-
-If it fails for any other reason, stop and report the error.
-
----
-
-## Completion
-
-Summarize what was done:
-- Version released
-- PR URL
-- Tag name
-- Which crates were published (if any)
-- Working directory path and how to clean it up (`rm -rf`)
diff --git a/.depot/workflows/codespell.yml b/.depot/workflows/codespell.yml
deleted file mode 100644
index 2647cb49..00000000
--- a/.depot/workflows/codespell.yml
+++ /dev/null
@@ -1,28 +0,0 @@
-# Depot CI Migration
-# Source: .github/workflows/codespell.yml
-#
-# No changes were necessary.
-
-# Codespell configuration is within .codespellrc
-name: Codespell
-on:
- push:
- branches: [main]
- pull_request:
- branches: [main]
-permissions:
- contents: read
-jobs:
- codespell:
- name: Check for spelling errors
- runs-on: depot-ubuntu-24.04
- steps:
- - name: Checkout
- uses: actions/checkout@v6
- - name: Codespell
- uses: codespell-project/actions-codespell@v2
- with:
- # This is regenerated from commit history
- # we cannot rewrite commit history, and I'd rather not correct it
- # every time
- exclude_file: CHANGELOG.md
diff --git a/.depot/workflows/installer.yml b/.depot/workflows/installer.yml
deleted file mode 100644
index 57a6a466..00000000
--- a/.depot/workflows/installer.yml
+++ /dev/null
@@ -1,36 +0,0 @@
-# Depot CI Migration
-# Source: .github/workflows/installer.yml
-#
-# No changes were necessary.
-
-name: Install
-on:
- push:
- branches: [main]
- pull_request:
- paths: .github/workflows/installer.yml
-env:
- CARGO_TERM_COLOR: always
-jobs:
- install:
- strategy:
- matrix:
- os: [depot-ubuntu-24.04, macos-14]
- runs-on: ${{ matrix.os }}
- steps:
- - uses: actions/checkout@v6
- - name: Install zsh for ubuntu
- if: matrix.os == 'depot-ubuntu-24.04'
- run: |
- sudo apt install zsh
- - name: Test install script on bash
- run: |
- /bin/bash -c "$(curl --proto '=https' --tlsv1.2 -sSf https://setup.atuin.sh)"
- [ -d "$HOME/.atuin" ] && source $HOME/.atuin/bin/env
- atuin --help
- - name: Test install script on zsh
- shell: zsh {0}
- run: |
- /bin/bash -c "$(curl --proto '=https' --tlsv1.2 -sSf https://setup.atuin.sh)"
- [ -d "$HOME/.atuin" ] && source $HOME/.atuin/bin/env
- atuin --help
diff --git a/.depot/workflows/nix.yml b/.depot/workflows/nix.yml
deleted file mode 100644
index 3b5a360a..00000000
--- a/.depot/workflows/nix.yml
+++ /dev/null
@@ -1,33 +0,0 @@
-# Depot CI Migration
-# Source: .github/workflows/nix.yml
-#
-# No changes were necessary.
-
-# Verify the Nix build is working
-# Failures will usually occur due to an out of date Rust version
-# That can be updated to the latest version in nixpkgs-unstable with `nix flake update`
-name: Nix
-on:
- push:
- branches: [main]
- paths-ignore:
- - 'ui/**'
- pull_request:
- branches: [main]
- paths-ignore:
- - 'ui/**'
-jobs:
- check:
- runs-on: depot-ubuntu-24.04
- steps:
- - uses: actions/checkout@v6
- - uses: cachix/install-nix-action@v31
- - name: Run nix flake check
- run: nix flake check --print-build-logs
- build-test:
- runs-on: depot-ubuntu-24.04
- steps:
- - uses: actions/checkout@v6
- - uses: cachix/install-nix-action@v31
- - name: Run nix build
- run: nix build --print-build-logs
diff --git a/.depot/workflows/rust.yml b/.depot/workflows/rust.yml
deleted file mode 100644
index 550995d7..00000000
--- a/.depot/workflows/rust.yml
+++ /dev/null
@@ -1,187 +0,0 @@
-# Depot CI Migration
-# Source: .github/workflows/rust.yml
-#
-# No changes were necessary.
-
-name: Rust
-on:
- push:
- branches: [main]
- paths-ignore:
- - "ui/**"
- pull_request:
- branches: [main]
- paths-ignore:
- - "ui/**"
-env:
- CARGO_TERM_COLOR: always
-jobs:
- build:
- strategy:
- matrix:
- os: [depot-ubuntu-24.04, macos-14, windows-latest]
- runs-on: ${{ matrix.os }}
- steps:
- - uses: actions/checkout@v6
- - name: Install rust
- uses: dtolnay/rust-toolchain@master
- with:
- toolchain: 1.94.0
- - uses: actions/cache@v5
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- target
- key: ${{ runner.os }}-cargo-release-${{ hashFiles('**/Cargo.lock') }}
- - name: Run cargo build common
- run: cargo build -p atuin-common --locked --release
- - name: Run cargo build client
- run: cargo build -p atuin-client --locked --release
- - name: Run cargo build server
- run: cargo build -p atuin-server --locked --release
- - name: Run cargo build main
- run: cargo build --all --locked --release
- cross-compile:
- strategy:
- matrix:
- # There was an attempt to make cross-compiles also work on FreeBSD, but that failed with:
- #
- # warning: libelf.so.2, needed by <...>/libkvm.so, not found (try using -rpath or -rpath-link)
- target: [x86_64-unknown-illumos]
- runs-on: depot-ubuntu-24.04
- steps:
- - uses: actions/checkout@v6
- - name: Install cross
- uses: taiki-e/install-action@v2
- with:
- tool: cross
- - uses: actions/cache@v5
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- target
- key: ${{ matrix.target }}-cross-compile-${{ hashFiles('**/Cargo.lock') }}
- - name: Run cross build common
- run: cross build -p atuin-common --locked --target ${{ matrix.target }}
- - name: Run cross build client
- run: cross build -p atuin-client --locked --target ${{ matrix.target }}
- - name: Run cross build server
- run: cross build -p atuin-server --locked --target ${{ matrix.target }}
- - name: Run cross build main
- run: |
- cross build --all --locked --target ${{ matrix.target }}
- unit-test:
- strategy:
- matrix:
- os: [depot-ubuntu-24.04, macos-14, windows-latest]
- runs-on: ${{ matrix.os }}
- steps:
- - uses: actions/checkout@v6
- - name: Install rust
- uses: dtolnay/rust-toolchain@master
- with:
- toolchain: 1.94.0
- - uses: taiki-e/install-action@v2
- name: Install nextest
- with:
- tool: cargo-nextest
- - uses: actions/cache@v5
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- target
- key: ${{ runner.os }}-cargo-debug-${{ hashFiles('**/Cargo.lock') }}
- - name: Run cargo test
- run: cargo nextest run --lib --bins
- check:
- strategy:
- matrix:
- os: [depot-ubuntu-24.04, macos-14, windows-latest]
- runs-on: ${{ matrix.os }}
- steps:
- - uses: actions/checkout@v6
- - name: Install rust
- uses: dtolnay/rust-toolchain@master
- with:
- toolchain: 1.94.0
- - uses: actions/cache@v5
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- target
- key: ${{ runner.os }}-cargo-debug-${{ hashFiles('**/Cargo.lock') }}
- - name: Run cargo check (all features)
- run: cargo check --all-features --workspace
- - name: Run cargo check (no features)
- run: cargo check --no-default-features --workspace
- - name: Run cargo check (sync)
- run: cargo check --no-default-features --features sync --workspace
- - name: Run cargo check (server)
- run: cargo check -p atuin-server
- - name: Run cargo check (client only)
- run: cargo check --no-default-features --features client --workspace
- integration-test:
- runs-on: depot-ubuntu-24.04
- services:
- postgres:
- image: postgres
- env:
- POSTGRES_USER: atuin
- POSTGRES_PASSWORD: pass
- POSTGRES_DB: atuin
- ports:
- - 5432:5432
- steps:
- - uses: actions/checkout@v6
- - name: Install rust
- uses: dtolnay/rust-toolchain@master
- with:
- toolchain: 1.94.0
- - uses: taiki-e/install-action@v2
- name: Install nextest
- with:
- tool: cargo-nextest
- - uses: actions/cache@v5
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- target
- key: ${{ runner.os }}-cargo-debug-${{ hashFiles('**/Cargo.lock') }}
- - name: Run cargo test
- run: cargo nextest run --test '*'
- env:
- ATUIN_DB_URI: postgres://atuin:pass@localhost:5432/atuin
- clippy:
- runs-on: depot-ubuntu-24.04
- steps:
- - uses: actions/checkout@v6
- - name: Install latest rust
- uses: dtolnay/rust-toolchain@master
- with:
- toolchain: 1.94.0
- components: clippy
- - uses: actions/cache@v5
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- target
- key: ${{ runner.os }}-cargo-debug-${{ hashFiles('**/Cargo.lock') }}
- - name: Run clippy
- run: cargo clippy -- -D warnings -D clippy::redundant_clone
- format:
- runs-on: depot-ubuntu-24.04
- steps:
- - uses: actions/checkout@v6
- - name: Install latest rust
- uses: dtolnay/rust-toolchain@master
- with:
- toolchain: 1.94.0
- components: rustfmt
- - name: Format
- run: cargo fmt -- --check
diff --git a/.depot/workflows/shellcheck.yml b/.depot/workflows/shellcheck.yml
deleted file mode 100644
index 99a2c434..00000000
--- a/.depot/workflows/shellcheck.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-# Depot CI Migration
-# Source: .github/workflows/shellcheck.yml
-#
-# No changes were necessary.
-
-name: Shellcheck
-on:
- push:
- branches: [main]
- pull_request:
- branches: [main]
-jobs:
- shellcheck:
- runs-on: depot-ubuntu-24.04
- steps:
- - uses: actions/checkout@v6
- - name: Run shellcheck
- uses: ludeeus/action-shellcheck@master
- env:
- SHELLCHECK_OPTS: "-e SC2148"
diff --git a/.depot/workflows/update-nix-deps.yml b/.depot/workflows/update-nix-deps.yml
deleted file mode 100644
index 6c83816a..00000000
--- a/.depot/workflows/update-nix-deps.yml
+++ /dev/null
@@ -1,25 +0,0 @@
-# Depot CI Migration
-# Source: .github/workflows/update-nix-deps.yml
-#
-# No changes were necessary.
-
-name: Update Nix Deps
-on:
- workflow_dispatch: # allows manual triggering
- schedule:
- - cron: '0 0 1 * *' # runs monthly on the first day of the month at 00:00
-jobs:
- lockfile:
- runs-on: depot-ubuntu-24.04
- if: github.repository == 'atuinsh/atuin'
- steps:
- - name: Checkout repository
- uses: actions/checkout@v6
- - name: Install Nix
- uses: DeterminateSystems/nix-installer-action@main
- - name: Update flake.lock
- uses: DeterminateSystems/update-flake-lock@main
- with:
- pr-title: "chore(deps): update flake.lock"
- pr-labels: |
- dependencies
diff --git a/.dockerignore b/.dockerignore
deleted file mode 100644
index 1f5346b7..00000000
--- a/.dockerignore
+++ /dev/null
@@ -1,2 +0,0 @@
-./target
-Dockerfile
diff --git a/.fossier.db b/.fossier.db
deleted file mode 100644
index 216c685e..00000000
--- a/.fossier.db
+++ /dev/null
Binary files differ
diff --git a/.github/DISCUSSION_TEMPLATE/support.yml b/.github/DISCUSSION_TEMPLATE/support.yml
deleted file mode 100644
index b6a6ae40..00000000
--- a/.github/DISCUSSION_TEMPLATE/support.yml
+++ /dev/null
@@ -1,84 +0,0 @@
-body:
- - type: input
- attributes:
- label: Operating System
- description: What operating system are you using?
- placeholder: "Example: macOS Big Sur"
- validations:
- required: true
-
- - type: input
- attributes:
- label: Shell
- description: What shell are you using?
- placeholder: "Example: zsh 5.8.1"
- validations:
- required: true
-
- - type: dropdown
- attributes:
- label: Version
- description: What version of atuin are you running?
- multiple: false
- options: # how often will I forget to update this? a lot.
- - v17.0.0 (Default)
- - v16.0.0
- - v15.0.0
- - v14.0.1
- - v14.0.0
- - v13.0.1
- - v13.0.0
- - v12.0.0
- - v11.0.0
- - v0.10.0
- - v0.9.1
- - v0.9.0
- - v0.8.1
- - v0.8.0
- - v0.7.2
- - v0.7.1
- - v0.7.0
- - v0.6.4
- - v0.6.3
- default: 0
- validations:
- required: true
-
- - type: checkboxes
- attributes:
- label: Self hosted
- description: Are you self hosting atuin server?
- options:
- - label: I am self hosting atuin server
-
- - type: checkboxes
- attributes:
- label: Search the issues
- description: Did you search the issues and discussions for your problem?
- options:
- - label: I checked that someone hasn't already asked about the same issue
- required: true
-
- - type: textarea
- attributes:
- label: Behaviour
- description: "Please describe the issue - what you expected to happen, what actually happened"
-
- - type: textarea
- attributes:
- label: Logs
- description: "If possible, please include logs from atuin, especially if you self host the server - ATUIN_LOG=debug"
-
- - type: textarea
- attributes:
- label: Extra information
- description: "Anything else you'd like to add?"
-
- - type: checkboxes
- attributes:
- label: Code of Conduct
- description: The Code of Conduct helps create a safe space for everyone. We require
- that everyone agrees to it.
- options:
- - label: I agree to follow this project's [Code of Conduct](https://github.com/atuinsh/atuin/blob/main/CODE_OF_CONDUCT.md)
- required: true
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
deleted file mode 100644
index 8b9c8039..00000000
--- a/.github/FUNDING.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-# These are supported funding model platforms
-
-github: [atuinsh]
-patreon: # Replace with a single Patreon username
-open_collective: # Replace with a single Open Collective username
-ko_fi: # Replace with a single Ko-fi username
-tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
-community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
-liberapay: # Replace with a single Liberapay username
-issuehunt: # Replace with a single IssueHunt username
-otechie: # Replace with a single Otechie username
-lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
-custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
diff --git a/.github/ISSUE_TEMPLATE/bug.yaml b/.github/ISSUE_TEMPLATE/bug.yaml
deleted file mode 100644
index 54cc46d7..00000000
--- a/.github/ISSUE_TEMPLATE/bug.yaml
+++ /dev/null
@@ -1,39 +0,0 @@
-name: Bug Report
-description: File a bug report
-title: "[Bug]: "
-labels: ["bug", "triage"]
-body:
- - type: markdown
- attributes:
- value: |
- Thanks for taking the time to fill out this bug report!
- - type: textarea
- id: what-expected
- attributes:
- label: What did you expect to happen?
- placeholder: Tell us what you expected to see!
- validations:
- required: true
- - type: textarea
- id: what-happened
- attributes:
- label: What happened?
- placeholder: Tell us what you see!
- validations:
- required: true
- - type: textarea
- id: doctor
- validations:
- required: true
- attributes:
- label: Atuin doctor output
- description: Please run 'atuin doctor' and share the output. If it fails to run, share any errors. This requires Atuin >=v18.1.0
- render: yaml
- - type: checkboxes
- id: terms
- attributes:
- label: Code of Conduct
- description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/atuinsh/atuin/blob/main/CODE_OF_CONDUCT.md)
- options:
- - label: I agree to follow this project's Code of Conduct
- required: true
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
deleted file mode 100644
index 9380a5ce..00000000
--- a/.github/dependabot.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-# To get started with Dependabot version updates, you'll need to specify which
-# package ecosystems to update and where the package manifests are located.
-# Please see the documentation for all configuration options:
-# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
-
-version: 2
-updates:
- - package-ecosystem: "cargo" # See documentation for possible values
- directory: "/" # Location of package manifests
- schedule:
- interval: "weekly"
- - package-ecosystem: "docker" # See documentation for possible values
- directory: "/" # Location of package manifests
- schedule:
- interval: "weekly"
- - package-ecosystem: "github-actions"
- directory: "/"
- schedule:
- interval: "weekly"
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
deleted file mode 100644
index 4621b63c..00000000
--- a/.github/pull_request_template.md
+++ /dev/null
@@ -1,5 +0,0 @@
-<!-- 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
diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml
deleted file mode 100644
index 7d941112..00000000
--- a/.github/workflows/codespell.yml
+++ /dev/null
@@ -1,28 +0,0 @@
-# Codespell configuration is within .codespellrc
----
-name: Codespell
-
-on:
- push:
- branches: [main]
- pull_request:
- branches: [main]
-
-permissions:
- contents: read
-
-jobs:
- codespell:
- name: Check for spelling errors
- runs-on: depot-ubuntu-24.04
-
- steps:
- - name: Checkout
- uses: actions/checkout@v6
- - name: Codespell
- uses: codespell-project/actions-codespell@v2
- with:
- # This is regenerated from commit history
- # we cannot rewrite commit history, and I'd rather not correct it
- # every time
- exclude_file: CHANGELOG.md
diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml
deleted file mode 100644
index 8761aaf6..00000000
--- a/.github/workflows/docker.yaml
+++ /dev/null
@@ -1,61 +0,0 @@
-name: build-docker
-
-on:
- push:
- branches: [main]
- tags:
- - 'v*'
-
-jobs:
- publish:
- concurrency:
- group: ${{ github.ref }}-docker
- cancel-in-progress: true
- permissions:
- packages: write
- contents: read
- id-token: write
-
- runs-on: depot-ubuntu-24.04
- steps:
- - uses: actions/checkout@v6
-
- - name: Get Repo Owner
- id: get_repo_owner
- run: echo "REPO_OWNER=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')" > $GITHUB_ENV
-
- - uses: depot/setup-action@v1
-
- - name: Login to container Registry
- uses: docker/login-action@v3
- with:
- username: ${{ github.repository_owner }}
- password: ${{ secrets.GITHUB_TOKEN }}
- registry: ghcr.io
-
- - name: Docker meta
- id: meta
- uses: docker/metadata-action@v5
- with:
- images: ghcr.io/${{ env.REPO_OWNER }}/atuin
- flavor: |
- latest=false
- tags: |
- type=ref,event=branch
- type=sha,prefix=
- type=semver,pattern={{version}}
- type=semver,pattern={{major}}.{{minor}}
-
- - name: Build and push
- uses: depot/build-push-action@v1
- with:
- push: true
- platforms: linux/amd64,linux/arm64
- file: ./Dockerfile
- context: .
- provenance: false
- build-args: |
- Version=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] || 'dev' }}
- GitCommit=${{ github.sha }}
- tags: ${{ steps.meta.outputs.tags }}
- labels: ${{ steps.meta.outputs.labels }}
diff --git a/.github/workflows/fossier-scan.yml b/.github/workflows/fossier-scan.yml
deleted file mode 100644
index 5c89be67..00000000
--- a/.github/workflows/fossier-scan.yml
+++ /dev/null
@@ -1,51 +0,0 @@
-name: Fossier Scan All PRs
-
-on:
- workflow_dispatch:
- inputs:
- dry-run:
- description: "Dry run - evaluate but don't take actions"
- type: boolean
- default: false
-
-permissions:
- contents: read
- pull-requests: write
- issues: write
-
-jobs:
- scan:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
-
- - name: Set up uv
- uses: astral-sh/setup-uv@v4
-
- - name: Set up Python
- uses: actions/setup-python@v5
- with:
- python-version: "3.13"
-
- - name: Install fossier
- run: uv tool install git+https://github.com/pthorpe92/fossier.git
-
- - name: Restore DB cache
- uses: actions/cache@v4
- with:
- path: .fossier.db
- key: fossier-db-${{ github.repository }}
- restore-keys: |
- fossier-db-${{ github.repository }}
-
- - name: Scan open PRs
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: |
- FLAGS="--format table"
- if [ "${{ inputs.dry-run }}" = "true" ]; then
- FLAGS="$FLAGS --dry-run"
- else
- FLAGS="$FLAGS --execute"
- fi
- fossier scan $FLAGS
diff --git a/.github/workflows/fossier.yml b/.github/workflows/fossier.yml
deleted file mode 100644
index e582e2d3..00000000
--- a/.github/workflows/fossier.yml
+++ /dev/null
@@ -1,29 +0,0 @@
-name: Fossier PR Check
-on:
- pull_request_target:
- types: [opened, synchronize]
- issue_comment:
- types: [created]
-
-permissions:
- contents: write
- pull-requests: write
- issues: write
-
-jobs:
- check:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
-
- - uses: PThorpe92/fossier@6e7f2a6c1c727949e2a6c94d7dc6904d7bb40928
- id: fossier
- with:
- contact-url: "https://discord.gg/Fq8bJSKPHh"
- github-token: ${{ secrets.GITHUB_TOKEN }}
- # Optional: connect to the global spam registry
- # registry-api-key: ${{ secrets.FOSSIER_REGISTRY_API_KEY }}
-
- - name: Handle result
- if: steps.fossier.outputs.outcome == 'deny'
- run: echo "PR denied with score ${{ steps.fossier.outputs.score }}"
diff --git a/.github/workflows/installer.yml b/.github/workflows/installer.yml
deleted file mode 100644
index 2cc4f89f..00000000
--- a/.github/workflows/installer.yml
+++ /dev/null
@@ -1,38 +0,0 @@
-name: Install
-
-on:
- push:
- branches: [main]
- pull_request:
- paths: .github/workflows/installer.yml
-
-env:
- CARGO_TERM_COLOR: always
-
-jobs:
- install:
- strategy:
- matrix:
- os: [depot-ubuntu-24.04, macos-14]
- runs-on: ${{ matrix.os }}
-
- steps:
- - uses: actions/checkout@v6
-
- - name: Install zsh for ubuntu
- if: matrix.os == 'depot-ubuntu-24.04'
- run: |
- sudo apt install zsh
-
- - name: Test install script on bash
- run: |
- /bin/bash -c "$(curl --proto '=https' --tlsv1.2 -sSf https://setup.atuin.sh)"
- [ -d "$HOME/.atuin" ] && source $HOME/.atuin/bin/env
- atuin --help
-
- - name: Test install script on zsh
- shell: zsh {0}
- run: |
- /bin/bash -c "$(curl --proto '=https' --tlsv1.2 -sSf https://setup.atuin.sh)"
- [ -d "$HOME/.atuin" ] && source $HOME/.atuin/bin/env
- atuin --help
diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml
deleted file mode 100644
index 515a05eb..00000000
--- a/.github/workflows/nix.yml
+++ /dev/null
@@ -1,34 +0,0 @@
-# Verify the Nix build is working
-# Failures will usually occur due to an out of date Rust version
-# That can be updated to the latest version in nixpkgs-unstable with `nix flake update`
-name: Nix
-on:
- push:
- branches: [ main ]
- paths-ignore:
- - 'ui/**'
- pull_request:
- branches: [ main ]
- paths-ignore:
- - 'ui/**'
-
-jobs:
- check:
- runs-on: depot-ubuntu-24.04
-
- steps:
- - uses: actions/checkout@v6
- - uses: cachix/install-nix-action@v31
-
- - name: Run nix flake check
- run: nix flake check --print-build-logs
-
- build-test:
- runs-on: depot-ubuntu-24.04
-
- steps:
- - uses: actions/checkout@v6
- - uses: cachix/install-nix-action@v31
-
- - name: Run nix build
- run: nix build --print-build-logs
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
deleted file mode 100644
index 5da97452..00000000
--- a/.github/workflows/release.yml
+++ /dev/null
@@ -1,304 +0,0 @@
-# This file was autogenerated by dist: https://axodotdev.github.io/cargo-dist
-#
-# Copyright 2022-2024, axodotdev
-# SPDX-License-Identifier: MIT or Apache-2.0
-#
-# CI that:
-#
-# * checks for a Git Tag that looks like a release
-# * builds artifacts with dist (archives, installers, hashes)
-# * uploads those artifacts to temporary workflow zip
-# * on success, uploads the artifacts to a GitHub Release
-#
-# Note that the GitHub Release will be created with a generated
-# title/body based on your changelogs.
-
-name: Release
-permissions:
- "contents": "write"
-
-# This task will run whenever you push a git tag that looks like a version
-# like "1.0.0", "v0.1.0-prerelease.1", "my-app/0.1.0", "releases/v1.0.0", etc.
-# Various formats will be parsed into a VERSION and an optional PACKAGE_NAME, where
-# PACKAGE_NAME must be the name of a Cargo package in your workspace, and VERSION
-# must be a Cargo-style SemVer Version (must have at least major.minor.patch).
-#
-# If PACKAGE_NAME is specified, then the announcement will be for that
-# package (erroring out if it doesn't have the given version or isn't dist-able).
-#
-# If PACKAGE_NAME isn't specified, then the announcement will be for all
-# (dist-able) packages in the workspace with that version (this mode is
-# intended for workspaces with only one dist-able package, or with all dist-able
-# packages versioned/released in lockstep).
-#
-# If you push multiple tags at once, separate instances of this workflow will
-# spin up, creating an independent announcement for each one. However, GitHub
-# will hard limit this to 3 tags per commit, as it will assume more tags is a
-# mistake.
-#
-# If there's a prerelease-style suffix to the version, then the release(s)
-# will be marked as a prerelease.
-on:
- pull_request:
- push:
- tags:
- - '**[0-9]+.[0-9]+.[0-9]+*'
-
-jobs:
- # Run 'dist plan' (or host) to determine what tasks we need to do
- plan:
- runs-on: "ubuntu-22.04"
- outputs:
- val: ${{ steps.plan.outputs.manifest }}
- tag: ${{ !github.event.pull_request && github.ref_name || '' }}
- tag-flag: ${{ !github.event.pull_request && format('--tag={0}', github.ref_name) || '' }}
- publishing: ${{ !github.event.pull_request }}
- env:
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- steps:
- - uses: actions/checkout@v6
- with:
- persist-credentials: false
- submodules: recursive
- - name: Install dist
- # we specify bash to get pipefail; it guards against the `curl` command
- # failing. otherwise `sh` won't catch that `curl` returned non-0
- shell: bash
- run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.31.0/cargo-dist-installer.sh | sh"
- - name: Cache dist
- uses: actions/upload-artifact@v6
- with:
- name: cargo-dist-cache
- path: ~/.cargo/bin/dist
- # sure would be cool if github gave us proper conditionals...
- # so here's a doubly-nested ternary-via-truthiness to try to provide the best possible
- # functionality based on whether this is a pull_request, and whether it's from a fork.
- # (PRs run on the *source* but secrets are usually on the *target* -- that's *good*
- # but also really annoying to build CI around when it needs secrets to work right.)
- - id: plan
- run: |
- dist ${{ (!github.event.pull_request && format('host --steps=create --tag={0}', github.ref_name)) || 'plan' }} --output-format=json > plan-dist-manifest.json
- echo "dist ran successfully"
- cat plan-dist-manifest.json
- echo "manifest=$(jq -c "." plan-dist-manifest.json)" >> "$GITHUB_OUTPUT"
- - name: "Upload dist-manifest.json"
- uses: actions/upload-artifact@v6
- with:
- name: artifacts-plan-dist-manifest
- path: plan-dist-manifest.json
-
- # Build and packages all the platform-specific things
- build-local-artifacts:
- name: build-local-artifacts (${{ join(matrix.targets, ', ') }})
- # Let the initial task tell us to not run (currently very blunt)
- needs:
- - plan
- if: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix.include != null && (needs.plan.outputs.publishing == 'true' || fromJson(needs.plan.outputs.val).ci.github.pr_run_mode == 'upload') }}
- strategy:
- fail-fast: false
- # Target platforms/runners are computed by dist in create-release.
- # Each member of the matrix has the following arguments:
- #
- # - runner: the github runner
- # - dist-args: cli flags to pass to dist
- # - install-dist: expression to run to install dist on the runner
- #
- # Typically there will be:
- # - 1 "global" task that builds universal installers
- # - N "local" tasks that build each platform's binaries and platform-specific installers
- matrix: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix }}
- runs-on: ${{ matrix.runner }}
- container: ${{ matrix.container && matrix.container.image || null }}
- env:
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- BUILD_MANIFEST_NAME: target/distrib/${{ join(matrix.targets, '-') }}-dist-manifest.json
- permissions:
- "attestations": "write"
- "contents": "read"
- "id-token": "write"
- steps:
- - name: enable windows longpaths
- run: |
- git config --global core.longpaths true
- - uses: actions/checkout@v6
- with:
- persist-credentials: false
- submodules: recursive
- - name: Install Rust non-interactively if not already installed
- if: ${{ matrix.container }}
- run: |
- if ! command -v cargo > /dev/null 2>&1; then
- curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
- echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- fi
- - name: Install dist
- run: ${{ matrix.install_dist.run }}
- # Get the dist-manifest
- - name: Fetch local artifacts
- uses: actions/download-artifact@v7
- with:
- pattern: artifacts-*
- path: target/distrib/
- merge-multiple: true
- - name: Install dependencies
- run: |
- ${{ matrix.packages_install }}
- - name: Build artifacts
- run: |
- # Actually do builds and make zips and whatnot
- dist build ${{ needs.plan.outputs.tag-flag }} --print=linkage --output-format=json ${{ matrix.dist_args }} > dist-manifest.json
- echo "dist ran successfully"
- - name: Attest
- uses: actions/attest-build-provenance@v3
- with:
- subject-path: "target/distrib/*${{ join(matrix.targets, ', ') }}*"
- - id: cargo-dist
- name: Post-build
- # We force bash here just because github makes it really hard to get values up
- # to "real" actions without writing to env-vars, and writing to env-vars has
- # inconsistent syntax between shell and powershell.
- shell: bash
- run: |
- # Parse out what we just built and upload it to scratch storage
- echo "paths<<EOF" >> "$GITHUB_OUTPUT"
- dist print-upload-files-from-manifest --manifest dist-manifest.json >> "$GITHUB_OUTPUT"
- echo "EOF" >> "$GITHUB_OUTPUT"
-
- cp dist-manifest.json "$BUILD_MANIFEST_NAME"
- - name: "Upload artifacts"
- uses: actions/upload-artifact@v6
- with:
- name: artifacts-build-local-${{ join(matrix.targets, '_') }}
- path: |
- ${{ steps.cargo-dist.outputs.paths }}
- ${{ env.BUILD_MANIFEST_NAME }}
-
- # Build and package all the platform-agnostic(ish) things
- build-global-artifacts:
- needs:
- - plan
- - build-local-artifacts
- runs-on: "ubuntu-22.04"
- env:
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- BUILD_MANIFEST_NAME: target/distrib/global-dist-manifest.json
- steps:
- - uses: actions/checkout@v6
- with:
- persist-credentials: false
- submodules: recursive
- - name: Install cached dist
- uses: actions/download-artifact@v7
- with:
- name: cargo-dist-cache
- path: ~/.cargo/bin/
- - run: chmod +x ~/.cargo/bin/dist
- # Get all the local artifacts for the global tasks to use (for e.g. checksums)
- - name: Fetch local artifacts
- uses: actions/download-artifact@v7
- with:
- pattern: artifacts-*
- path: target/distrib/
- merge-multiple: true
- - id: cargo-dist
- shell: bash
- run: |
- dist build ${{ needs.plan.outputs.tag-flag }} --output-format=json "--artifacts=global" > dist-manifest.json
- echo "dist ran successfully"
-
- # Parse out what we just built and upload it to scratch storage
- echo "paths<<EOF" >> "$GITHUB_OUTPUT"
- jq --raw-output ".upload_files[]" dist-manifest.json >> "$GITHUB_OUTPUT"
- echo "EOF" >> "$GITHUB_OUTPUT"
-
- cp dist-manifest.json "$BUILD_MANIFEST_NAME"
- - name: "Upload artifacts"
- uses: actions/upload-artifact@v6
- with:
- name: artifacts-build-global
- path: |
- ${{ steps.cargo-dist.outputs.paths }}
- ${{ env.BUILD_MANIFEST_NAME }}
- # Determines if we should publish/announce
- host:
- needs:
- - plan
- - build-local-artifacts
- - build-global-artifacts
- # Only run if we're "publishing", and only if plan, local and global didn't fail (skipped is fine)
- if: ${{ always() && needs.plan.result == 'success' && needs.plan.outputs.publishing == 'true' && (needs.build-global-artifacts.result == 'skipped' || needs.build-global-artifacts.result == 'success') && (needs.build-local-artifacts.result == 'skipped' || needs.build-local-artifacts.result == 'success') }}
- env:
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- runs-on: "ubuntu-22.04"
- outputs:
- val: ${{ steps.host.outputs.manifest }}
- steps:
- - uses: actions/checkout@v6
- with:
- persist-credentials: false
- submodules: recursive
- - name: Install cached dist
- uses: actions/download-artifact@v7
- with:
- name: cargo-dist-cache
- path: ~/.cargo/bin/
- - run: chmod +x ~/.cargo/bin/dist
- # Fetch artifacts from scratch-storage
- - name: Fetch artifacts
- uses: actions/download-artifact@v7
- with:
- pattern: artifacts-*
- path: target/distrib/
- merge-multiple: true
- - id: host
- shell: bash
- run: |
- dist host ${{ needs.plan.outputs.tag-flag }} --steps=upload --steps=release --output-format=json > dist-manifest.json
- echo "artifacts uploaded and released successfully"
- cat dist-manifest.json
- echo "manifest=$(jq -c "." dist-manifest.json)" >> "$GITHUB_OUTPUT"
- - name: "Upload dist-manifest.json"
- uses: actions/upload-artifact@v6
- with:
- # Overwrite the previous copy
- name: artifacts-dist-manifest
- path: dist-manifest.json
- # Create a GitHub Release while uploading all files to it
- - name: "Download GitHub Artifacts"
- uses: actions/download-artifact@v7
- with:
- pattern: artifacts-*
- path: artifacts
- merge-multiple: true
- - name: Cleanup
- run: |
- # Remove the granular manifests
- rm -f artifacts/*-dist-manifest.json
- - name: Create GitHub Release
- env:
- PRERELEASE_FLAG: "${{ fromJson(steps.host.outputs.manifest).announcement_is_prerelease && '--prerelease' || '' }}"
- ANNOUNCEMENT_TITLE: "${{ fromJson(steps.host.outputs.manifest).announcement_title }}"
- ANNOUNCEMENT_BODY: "${{ fromJson(steps.host.outputs.manifest).announcement_github_body }}"
- RELEASE_COMMIT: "${{ github.sha }}"
- run: |
- # Write and read notes from a file to avoid quoting breaking things
- echo "$ANNOUNCEMENT_BODY" > $RUNNER_TEMP/notes.txt
-
- gh release create "${{ needs.plan.outputs.tag }}" --target "$RELEASE_COMMIT" $PRERELEASE_FLAG --title "$ANNOUNCEMENT_TITLE" --notes-file "$RUNNER_TEMP/notes.txt" artifacts/*
-
- announce:
- needs:
- - plan
- - host
- # use "always() && ..." to allow us to wait for all publish jobs while
- # still allowing individual publish jobs to skip themselves (for prereleases).
- # "host" however must run to completion, no skipping allowed!
- if: ${{ always() && needs.host.result == 'success' }}
- runs-on: "ubuntu-22.04"
- env:
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- steps:
- - uses: actions/checkout@v6
- with:
- persist-credentials: false
- submodules: recursive
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
deleted file mode 100644
index 96c8ebc7..00000000
--- a/.github/workflows/rust.yml
+++ /dev/null
@@ -1,230 +0,0 @@
-name: Rust
-
-on:
- push:
- branches: [main]
- paths-ignore:
- - "ui/**"
- pull_request:
- branches: [main]
- paths-ignore:
- - "ui/**"
-
-env:
- CARGO_TERM_COLOR: always
-
-jobs:
- build:
- strategy:
- matrix:
- os: [depot-ubuntu-24.04, macos-14, windows-latest]
- runs-on: ${{ matrix.os }}
-
- steps:
- - uses: actions/checkout@v6
-
- - name: Install rust
- uses: dtolnay/rust-toolchain@master
- with:
- toolchain: 1.96.0
-
- - uses: actions/cache@v5
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- target
- key: ${{ runner.os }}-cargo-release-${{ hashFiles('**/Cargo.lock') }}
-
- - name: Run cargo build common
- run: cargo build -p atuin-common --locked --release
-
- - name: Run cargo build client
- run: cargo build -p atuin-client --locked --release
-
- - name: Run cargo build server
- run: cargo build -p atuin-server --locked --release
-
- - name: Run cargo build main
- run: cargo build --all --locked --release
-
- cross-compile:
- strategy:
- matrix:
- # There was an attempt to make cross-compiles also work on FreeBSD, but that failed with:
- #
- # warning: libelf.so.2, needed by <...>/libkvm.so, not found (try using -rpath or -rpath-link)
- target: [x86_64-unknown-illumos]
- runs-on: depot-ubuntu-24.04
- steps:
- - uses: actions/checkout@v6
-
- - name: Install cross
- uses: taiki-e/install-action@v2
- with:
- tool: cross
-
- - uses: actions/cache@v5
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- target
- key: ${{ matrix.target }}-cross-compile-${{ hashFiles('**/Cargo.lock') }}
-
- - name: Run cross build common
- run: cross build -p atuin-common --locked --target ${{ matrix.target }}
-
- - name: Run cross build client
- run: cross build -p atuin-client --locked --target ${{ matrix.target }}
-
- - name: Run cross build server
- run: cross build -p atuin-server --locked --target ${{ matrix.target }}
-
- - name: Run cross build main
- run: |
- cross build --all --locked --target ${{ matrix.target }}
-
- unit-test:
- strategy:
- matrix:
- os: [depot-ubuntu-24.04, macos-14, windows-latest]
- runs-on: ${{ matrix.os }}
-
- steps:
- - uses: actions/checkout@v6
-
- - name: Install rust
- uses: dtolnay/rust-toolchain@master
- with:
- toolchain: 1.96.0
-
- - uses: taiki-e/install-action@v2
- name: Install nextest
- with:
- tool: cargo-nextest
-
- - uses: actions/cache@v5
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- target
- key: ${{ runner.os }}-cargo-debug-${{ hashFiles('**/Cargo.lock') }}
-
- - name: Run cargo test
- run: cargo nextest run --lib --bins
-
- check:
- strategy:
- matrix:
- os: [depot-ubuntu-24.04, macos-14, windows-latest]
- runs-on: ${{ matrix.os }}
-
- steps:
- - uses: actions/checkout@v6
-
- - name: Install rust
- uses: dtolnay/rust-toolchain@master
- with:
- toolchain: 1.96.0
-
- - uses: actions/cache@v5
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- target
- key: ${{ runner.os }}-cargo-debug-${{ hashFiles('**/Cargo.lock') }}
-
- - name: Run cargo check (all features)
- run: cargo check --all-features --workspace
-
- - name: Run cargo check (no features)
- run: cargo check --no-default-features --workspace
-
- - name: Run cargo check (sync)
- run: cargo check --no-default-features --features sync --workspace
-
- - name: Run cargo check (server)
- run: cargo check -p atuin-server
-
- - name: Run cargo check (client only)
- run: cargo check --no-default-features --features client --workspace
-
- integration-test:
- runs-on: depot-ubuntu-24.04
-
- services:
- postgres:
- image: postgres
- env:
- POSTGRES_USER: atuin
- POSTGRES_PASSWORD: pass
- POSTGRES_DB: atuin
- ports:
- - 5432:5432
-
- steps:
- - uses: actions/checkout@v6
-
- - name: Install rust
- uses: dtolnay/rust-toolchain@master
- with:
- toolchain: 1.96.0
-
- - uses: taiki-e/install-action@v2
- name: Install nextest
- with:
- tool: cargo-nextest
-
- - uses: actions/cache@v5
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- target
- key: ${{ runner.os }}-cargo-debug-${{ hashFiles('**/Cargo.lock') }}
-
- - name: Run cargo test
- run: cargo nextest run --test '*'
- env:
- ATUIN_DB_URI: postgres://atuin:pass@localhost:5432/atuin
-
- clippy:
- runs-on: depot-ubuntu-24.04
-
- steps:
- - uses: actions/checkout@v6
-
- - name: Install latest rust
- uses: dtolnay/rust-toolchain@master
- with:
- toolchain: 1.96.0
- components: clippy
-
- - uses: actions/cache@v5
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- target
- key: ${{ runner.os }}-cargo-debug-${{ hashFiles('**/Cargo.lock') }}
-
- - name: Run clippy
- run: cargo clippy -- -D warnings -D clippy::redundant_clone
-
- format:
- runs-on: depot-ubuntu-24.04
-
- steps:
- - uses: actions/checkout@v6
-
- - name: Install latest rust
- uses: dtolnay/rust-toolchain@master
- with:
- toolchain: 1.96.0
- components: rustfmt
-
- - name: Format
- run: cargo fmt -- --check
diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml
deleted file mode 100644
index e85381fd..00000000
--- a/.github/workflows/shellcheck.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-name: Shellcheck
-
-on:
- push:
- branches: [ main ]
- pull_request:
- branches: [ main ]
-
-jobs:
- shellcheck:
- runs-on: depot-ubuntu-24.04
-
- steps:
- - uses: actions/checkout@v6
- - name: Run shellcheck
- uses: ludeeus/action-shellcheck@master
- env:
- SHELLCHECK_OPTS: "-e SC2148"
diff --git a/.github/workflows/update-nix-deps.yml b/.github/workflows/update-nix-deps.yml
deleted file mode 100644
index 2ed5ff78..00000000
--- a/.github/workflows/update-nix-deps.yml
+++ /dev/null
@@ -1,21 +0,0 @@
-name: Update Nix Deps
-on:
- workflow_dispatch: # allows manual triggering
- schedule:
- - cron: '0 0 1 * *' # runs monthly on the first day of the month at 00:00
-
-jobs:
- lockfile:
- runs-on: depot-ubuntu-24.04
- if: github.repository == 'atuinsh/atuin'
- steps:
- - name: Checkout repository
- uses: actions/checkout@v6
- - name: Install Nix
- uses: DeterminateSystems/nix-installer-action@main
- - name: Update flake.lock
- uses: DeterminateSystems/update-flake-lock@main
- with:
- pr-title: "chore(deps): update flake.lock"
- pr-labels: |
- dependencies
diff --git a/.rustfmt.toml b/.rustfmt.toml
index ec1e17ff..76387ac0 100644
--- a/.rustfmt.toml
+++ b/.rustfmt.toml
@@ -1,4 +1,4 @@
reorder_imports = true
# uncomment once stable
-#imports_granularity = "crate"
-#group_imports = "StdExternalCrate"
+imports_granularity = "crate"
+group_imports = "StdExternalCrate"
diff --git a/AGENTS.md b/AGENTS.md
deleted file mode 100644
index 4aba8ed2..00000000
--- a/AGENTS.md
+++ /dev/null
@@ -1,71 +0,0 @@
-# Atuin
-
-Shell history tool. Replaces your shell's built-in history with a SQLite database, adds context (cwd, exit code, duration, hostname), and optionally syncs across machines with end-to-end encryption.
-
-## Workspace crates
-
-```
-atuin CLI binary + TUI (clap, ratatui, crossterm)
-atuin-client Client library: local DB, encryption, sync, settings
-atuin-common Shared types, API models, utils
-atuin-daemon Background gRPC daemon (tonic) for shell hooks
-atuin-dotfiles Alias/var sync via record store
-atuin-history Sorting algorithms, stats
-atuin-kv Key-value store (synced)
-atuin-scripts Script management (minijinja)
-atuin-server HTTP sync server (axum) - lib + standalone binary
-atuin-server-database Database trait for server
-atuin-server-postgres Postgres implementation (sqlx)
-atuin-server-sqlite SQLite implementation (sqlx)
-```
-
-## Two sync protocols
-
-- **V1 (legacy)**: Syncs history entries directly. Being phased out. Toggleable via `sync_v1_enabled`.
-- **V2 (current)**: Record store abstraction. All data types (history, KV, aliases, vars, scripts) share the same sync infrastructure using tagged records. Envelope-encrypted with PASETO V4 and per-record CEKs.
-
-## Encryption
-
-- **V1**: XSalsa20Poly1305 (secretbox). Key at `~/.local/share/atuin/key`.
-- **V2**: PASETO V4 Local (XChaCha20-Poly1305 + Blake2b). Envelope encryption: each record gets a random CEK wrapped with the master key. Record metadata (id, idx, version, tag, host) is authenticated as implicit assertions.
-
-## Databases
-
-- **Client**: SQLite everywhere. Separate DBs for history, record store, KV, scripts. All use sqlx + WAL mode.
-- **Server**: Postgres (primary) or SQLite. Auto-detected from URI prefix.
-- Migrations live alongside each crate. Never modify existing migrations, only add new ones.
-
-## Hot paths
-
-`history start`, `history end`, and `init` skip database initialization for latency. Don't add DB calls to these without good reason.
-
-## Conventions
-
-- Rust 2024 edition, toolchain 1.93.1.
-- Errors: `eyre::Result` in binaries, `thiserror` for typed errors in libraries.
-- Async: tokio. Client uses `current_thread`; server uses `multi_thread`.
-- `#![deny(unsafe_code)]` on client/common, `#![forbid(unsafe_code)]` on server.
-- Clippy: `pedantic` + `nursery` on main crate. CI enforces `-D warnings -D clippy::redundant_clone`.
-- Format: `cargo fmt`. Only non-default: `reorder_imports = true`.
-- IDs: UUIDv7 (time-ordered), newtype wrappers (`HistoryId`, `RecordId`, `HostId`).
-- Serialization: MessagePack for encrypted payloads, JSON for API, TOML for config.
-- Storage traits: `Database` (client), `Store` (record store), `Database` (server) -- all `async_trait`.
-- History builders: `HistoryImported`, `HistoryCaptured`, `HistoryFromDb` with compile-time field validation.
-- Feature flags: `client`, `sync`, `daemon`, `clipboard`, `check-update`.
-
-## Testing
-
-- Unit tests inline with `#[cfg(test)]`, async via `#[tokio::test]`.
-- Integration tests in `crates/atuin/tests/` need Postgres (`ATUIN_DB_URI` env var).
-- Use `":memory:"` SQLite for unit tests needing a database.
-- Runner: `cargo nextest`.
-- Benchmarks: `divan` in `atuin-history`.
-
-## Build and check
-
-```sh
-cargo build
-cargo test
-cargo clippy -- -D warnings
-cargo fmt --check
-```
diff --git a/Dockerfile b/Dockerfile
deleted file mode 100644
index 37e40ffe..00000000
--- a/Dockerfile
+++ /dev/null
@@ -1,36 +0,0 @@
-FROM lukemathwalker/cargo-chef:latest-rust-1.96.0-slim-bookworm AS chef
-WORKDIR app
-
-FROM chef AS planner
-COPY . .
-RUN cargo chef prepare --recipe-path recipe.json
-
-FROM chef AS builder
-
-# Ensure working C compile setup (not installed by default in arm64 images)
-RUN apt update && apt install build-essential -y
-
-COPY --from=planner /app/recipe.json recipe.json
-RUN cargo chef cook --release --recipe-path recipe.json
-
-COPY . .
-RUN cargo build --release --bin atuin-server
-
-FROM debian:bookworm-20260518-slim AS runtime
-LABEL org.opencontainers.image.source="https://github.com/atuinsh/atuin" \
- org.opencontainers.image.url="https://atuin.sh" \
- org.opencontainers.image.licenses="MIT"
-
-RUN useradd -c 'atuin user' atuin && mkdir /config && chown atuin:atuin /config
-# Install ca-certificates for webhooks to work
-RUN apt update && apt install ca-certificates -y && rm -rf /var/lib/apt/lists/*
-WORKDIR app
-
-USER atuin
-
-ENV TZ=Etc/UTC
-ENV RUST_LOG=atuin_server=info
-ENV ATUIN_CONFIG_DIR=/config
-
-COPY --from=builder /app/target/release/atuin-server /usr/local/bin
-ENTRYPOINT ["/usr/local/bin/atuin-server"]
diff --git a/VOUCHED.td b/VOUCHED.td
deleted file mode 100644
index 031e7ccf..00000000
--- a/VOUCHED.td
+++ /dev/null
@@ -1,278 +0,0 @@
-+ 0x4A6F
-+ 13werwolf13
-+ abatkin
-+ Absolucy
-+ Adda0
-+ Aehmlo
-+ ajjahn
-+ akinomyoga
-+ akirk
-+ alerque
-+ alexandregv
-+ Aloxaf
-+ amosbird
-+ andrewaylett
-+ ap-1
-+ arcuru
-+ ardrigh
-+ aschey
-+ ataraxia937
-+ AtomicRobotMan0101
-+ avinassh
-+ azzamsa
-+ b3nj5m1n
-+ bahdotsh
-+ baprx
-+ bdavj
-+ benwr
-+ BinaryMuse
-+ bjschafer
-+ bradrf
-+ braelyn-ai
-+ briankung
-+ bvergnaud
-+ c-14
-+ c-git
-+ caio96
-+ candrewlee14
-+ Carthaca
-+ chitao1234
-+ clouserw
-+ conradludgate
-+ cosgroveb
-+ CosmicHorrorDev
-+ cultpony
-+ cyqsimon
-+ dacog
-+ DanielAtCosmicDNA
-+ DaniPopes
-+ david-crespo
-+ davidolrik
-+ davlgd
-+ dcarosone
-+ deicon
-+ dennis-tra
-+ dependabot[bot]
-+ dhth
-+ digital-cuttlefish
-+ dongxuwang
-+ dotfrag
-+ dotsam
-+ drbrain
-+ drmorr0
-+ ds-cbo
-+ eatradish
-+ eclairevoyant
-+ edeustua
-+ edwardloveall
-+ ekroon
-+ ellie
-+ elsbrock
-+ ElvishJerricco
-+ enchantednatures
-+ eopb
-+ EricCrosson
-+ eripa
-+ etbyrd
-+ eth3lbert
-+ evanpurkhiser
-+ felixonmars
-+ filviu
-+ fragmede
-+ frankh
-+ frukto
-+ fzakaria
-+ github-actions[bot]
-+ hack3ric
-+ happenslol
-+ haristhohir
-+ helbing
-+ herbygillot
-+ hesampakdaman
-+ hezhizhen
-+ hhamud
-+ hlxid
-+ hunger
-+ iamkroot
-+ IanManske
-+ ibayramli
-+ ijanos
-+ iloveitaly
-+ InCogNiTo124
-+ Indy2222
-+ injust
-+ IoSonoPiero
-+ ismith
-+ ivan-toriya
-+ ivvvve
-+ jamesbrooks
-+ jamestrew
-+ janlarres
-+ jaxvanyang
-+ jbaiter
-+ jean-santos
-+ jeremycline
-+ jfmontanaro
-+ jhult
-+ jingmian
-+ jinnatar
-+ jinnko
-+ jirutka
-+ JoaquinTrinanes
-+ jonaylor89
-+ Jongy
-+ Josef-Friedrich
-+ josegonzalez
-+ JRGould
-+ julienp
-+ jyn514
-+ karlding
-+ keithamus
-+ kejadlen
-+ keysmashes
-+ kianmeng
-+ kjetijor
-+ KorvinSzanto
-+ kosak
-+ laurentlbm
-+ lazzurs
-+ lchausmann
-+ LecrisUT
-+ LeoniePhiline
-+ liljaylj
-+ lilydjwg
-+ lmBored
-+ lmburns
-+ ltrzesniewski
-+ lucacome
-+ lugoues
-+ lukebaker
-+ lukekarrys
-+ m42e
-+ macno
-+ majiayu000
-+ manelvf
-+ marius
-+ mateuscomh
-+ mattgodbolt
-+ matthewberryman
-+ matthiasbeyer
-+ Matthieu-LAURENT39
-+ maxim-uvarov
-+ mb6ockatf
-+ Mellbourn
-+ mentalisttraceur
-+ merc1031
-+ michaelmior
-+ millette
-+ morguldir
-+ mozzieongit
-+ mrcjkb
-+ mrjones2014
-+ mrkbac
-+ mundry
-+ musicinmybrain
-+ mwotton
-+ mwpastore
-+ nc7s
-+ nebkor
-+ nekowinston
-+ Nelyah
-+ Nemo157
-+ NeoPhi
-+ networkException
-+ nh2
-+ notjedi
-+ notrudyyy
-+ notsatyarth
-+ noyez
-+ offbyone
-+ onedr0p
-+ OnePieceJoker
-+ onkelT2
-+ orhun
-+ overhacked
-+ oxo42
-+ pamburus
-+ panekj
-+ papertigers
-+ paulbarton90
-+ pdecat
-+ pevogam
-+ philn
-+ philtweir
-+ phinze
-+ piec
-+ pmarschik
-+ pmodin
-+ poliorcetics
-+ popsu
-+ postmath
-+ printfn
-+ r-vdp
-+ rektide
-+ remmycat
-+ Reverier-Xu
-+ RichardDRJ
-+ rightaditya
-+ rigrig
-+ Rohan5commit
-+ rriski
-+ rufo
-+ s0
-+ s1ck
-+ sashkab
-+ SAY-5
-+ schrej
-+ Sciencentistguy
-+ sdr135284
-+ senekor
-+ sftblw
-+ shgew
-+ shreve
-+ shymega
-+ simon-b
-+ skx
-+ slamp
-+ snaggen
-+ sophiajt
-+ sowbug
-+ Sped0n
-+ sporeventexplosion
-+ starsep
-+ stevenxxiu
-+ stuartcarnie
-+ sunshowers
-+ SuperSandro2000
-+ svenstaro
-+ szinn
-+ takac
-+ tessus
-+ thedrow
-+ thePanz
-+ tobiasge
-+ tombh
-+ tpoliaw
-+ tranzystorekk
-+ trygveaa
-+ Tyarel8
-+ TymanWasTaken
-+ UbiquitousPhoton
-+ utterstep
-+ VuiMuich
-+ Vynce
-+ waldyrious
-+ WindSoilder
-+ wpbrz
-+ wzzrd
-+ xav-ie
-+ xfzv
-+ xqm32
-+ xvello
-+ yan
-+ yannickulrich
-+ yarikoptic
-+ yolo2h
-+ YummyOreo
-+ yuvipanda
-+ zygous
diff --git a/atuin.plugin.zsh b/atuin.plugin.zsh
deleted file mode 100644
index 9ad5284f..00000000
--- a/atuin.plugin.zsh
+++ /dev/null
@@ -1,6 +0,0 @@
-# shellcheck disable=2148,SC2168,SC1090,SC2125
-local FOUND_ATUIN=$+commands[atuin]
-
-if [[ $FOUND_ATUIN -eq 1 ]]; then
- source <(atuin init zsh)
-fi
diff --git a/contrib/pi/atuin.ts b/contrib/pi/atuin.ts
deleted file mode 120000
index d5e7a533..00000000
--- a/contrib/pi/atuin.ts
+++ /dev/null
@@ -1 +0,0 @@
-../../crates/atuin/contrib/pi/atuin.ts \ No newline at end of file
diff --git a/demo.gif b/demo.gif
deleted file mode 100644
index 6eac1abf..00000000
--- a/demo.gif
+++ /dev/null
Binary files differ
diff --git a/depot.json b/depot.json
deleted file mode 100644
index e51895a6..00000000
--- a/depot.json
+++ /dev/null
@@ -1 +0,0 @@
-{"id":"v6vqpk6559"}
diff --git a/dist-workspace.toml b/dist-workspace.toml
deleted file mode 100644
index bd4a56cb..00000000
--- a/dist-workspace.toml
+++ /dev/null
@@ -1,29 +0,0 @@
-[workspace]
-members = ["cargo:."]
-
-# Config for 'dist'
-[dist]
-# Path that installers should place binaries in
-install-path = "~/.atuin/bin"
-# The preferred dist version to use in CI (Cargo.toml SemVer syntax)
-cargo-dist-version = "0.31.0"
-# CI backends to support
-ci = "github"
-# The installers to generate for each app
-installers = ["shell", "powershell"]
-# Target platforms to build apps for (Rust target-triple syntax)
-targets = ["aarch64-apple-darwin", "aarch64-unknown-linux-gnu", "aarch64-unknown-linux-musl", "x86_64-unknown-linux-gnu", "x86_64-unknown-linux-musl", "x86_64-pc-windows-msvc"]
-# Which actions to run on pull requests
-pr-run-mode = "plan"
-# Whether to install an updater program
-install-updater = true
-# The archive format to use for non-windows builds (defaults .tar.xz)
-unix-archive = ".tar.gz"
-# Whether to enable GitHub Attestations
-github-attestations = true
-
-[dist.github-custom-runners]
-aarch64-unknown-linux-gnu = "depot-ubuntu-24.04-arm-8"
-aarch64-unknown-linux-musl = "depot-ubuntu-24.04-arm-8"
-x86_64-unknown-linux-gnu = "depot-ubuntu-24.04-8"
-x86_64-unknown-linux-musl = "depot-ubuntu-24.04-8"
diff --git a/docs-i18n/.gitignore b/docs-i18n/.gitignore
deleted file mode 100644
index b2d6de30..00000000
--- a/docs-i18n/.gitignore
+++ /dev/null
@@ -1,20 +0,0 @@
-# Dependencies
-/node_modules
-
-# Production
-/build
-
-# Generated files
-.docusaurus
-.cache-loader
-
-# Misc
-.DS_Store
-.env.local
-.env.development.local
-.env.test.local
-.env.production.local
-
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
diff --git a/docs-i18n/ru/config_ru.md b/docs-i18n/ru/config_ru.md
deleted file mode 100644
index b1e64218..00000000
--- a/docs-i18n/ru/config_ru.md
+++ /dev/null
@@ -1,146 +0,0 @@
-# Конфигурация
-
-Autin использует два файла конфигурации. Они хранятся в `~/.config/atuin/`. Данные
-хранятся в `~/.local/share/atuin` (если не определено другое в XDG\_\*).
-
-Путь до катклога конфигурации может быть изменён установкой
-параметра `ATUIN_CONFIG_DIR`. Например
-
-```
-export ATUIN_CONFIG_DIR = /home/ellie/.atuin
-```
-
-## Пользовательская конфигурация
-
-```
-~/.config/atuin/config.toml
-```
-
-Этот файл используется когда клиент работает на локальной машине (не сервере).
-
-See [config.toml](../../atuin-client/config.toml) for an example
-
-### `dialect`
-
-Этот параметр контролирует как [stats](stats.md) команда обрабатывает данные.
-Может принимать одно из двух допустимых значений:
-
-```
-dialect = "uk"
-```
-
-или
-
-```
-dialect = "us"
-```
-
-По умолчанию - "us".
-
-### `auto_sync`
-
-Синхронизироваться ли автоматически если выполнен вход. По умолчанию - да (true)
-```
-auto_sync = true/false
-```
-
-### `sync_address`
-
-Адрес сервера для синхронизации. По умолчанию `https://api.atuin.sh`.
-
-```
-sync_address = "https://api.atuin.sh"
-```
-
-### `sync_frequency`
-
-Как часто клиент синхронизируется с сервером. Может быть указано в
-понятном для человека формате. Например, `10s`, `20m`, `1h`, и т.д.
-По умолчанию `1h`
-
-Если стоит значение 0, Autin будет синхронизироваться после каждой выполненной команды.
-Помните, что сервера могут иметь ограничение на количество отправленных запросов.
-
-```
-sync_frequency = "1h"
-```
-
-### `db_path`
-
-Путь до базы данных SQlite. По умолчанию это
-`~/.local/share/atuin/history.db`.
-
-```
-db_path = "~/.history.db"
-```
-
-### `key_path`
-
-Путь до ключа шифрования Autin. По умолчанию,
-`~/.local/share/atuin/key`.
-
-```
-key = "~/.atuin-key"
-```
-
-### `session_path`
-
-Путь до серверного файла сессии Autin. По умолчанию,
-`~/.local/share/atuin/session`. На самом деле это просто API токен.
-
-```
-key = "~/.atuin-session"
-```
-
-### `search_mode`
-
-Определяет, какой режим поиска будет использоваться. Autin поддерживает "prefix",
-текст целиком (fulltext) и неточный ("fuzzy") поиск. Режим "prefix" производит
-поиск по "запрос\*", "fulltext" по "\*запрос\*", и "fuzzy" использует
-[вот такой](#fuzzy-search-syntax) синтаксис.
-
-По умолчанию стоит значение "fuzzy"
-
-### `filter_mode`
-
-Фильтр, по-умолчанию использующийся для поиска
-
-| Столбец 1 | Столбец 2 |
-|------------------|----------------------------------------------------------|
-| global (default) | Искать историю команд со всех хостов, сессий и каталогов |
-| host | Искать историю команд с этого хоста |
-| session | Искать историю команд этой сессии |
-| directory | Искать историю команд, выполненных в текущей папке |
-
-Режимы поиска могут быть изменены через ctrl-r
-
-
-```
-search_mode = "fulltext"
-```
-
-#### fuzzy search syntax
-
-Режим поиска "fuzzy" основан на
-[fzf search syntax](https://github.com/junegunn/fzf#search-syntax).
-
-| Токен | Тип совпадений | Описание |
-|-----------|----------------------------|-------------------------------------|
-| `sbtrkt` | fuzzy-match | Всё, что совпадает с `sbtrkt` |
-| `'wild` | exact-match (В кавычках) | Всё, что включает в себя `wild` |
-| `^music` | prefix-exact-match | Всё, что начинается с `music` |
-| `.mp3$` | suffix-exact-match | Всё, что заканчивается на `.mp3` |
-| `!fire` | inverse-exact-match | Всё, что не включает в себя `fire` |
-| `!^music` | inverse-prefix-exact-match | Всё, что не начинается с `music` |
-| `!.mp3$` | inverse-suffix-exact-match | Всё, что не заканчивается на `.mp3` |
-
-Знак вертикальной черты означает логическое ИЛИ. Например, запрос ниже вернет
-всё, что начинается с `core` и заканчивается либо на `go`, либо на `rb`, либо на `py`.
-
-```
-^core go$ | rb$ | py$
-```
-
-## Серверная конфигурация
-
-`// TODO`
diff --git a/docs-i18n/ru/import_ru.md b/docs-i18n/ru/import_ru.md
deleted file mode 100644
index 993d89b8..00000000
--- a/docs-i18n/ru/import_ru.md
+++ /dev/null
@@ -1,27 +0,0 @@
-# `atuin import`
-
-Autin может импортировать историю из "старого" файла истории
-
-`atuin import auto` предпринимает попытку определить тип командного интерфейса
-(через \$SHELL) и запускает нужный скрипт импорта.
-
-К сожалению, эти файлы содержат не так много информации, как Autin, так что не
-все функции будут доступны с импортированными данными.
-
-# zsh
-
-```
-atuin import zsh
-```
-
-Если у вас есть HISTFILE, то эта команда должна сработать. Иначе, попробуйте
-
-```
-HISTFILE=/path/to/history/file atuin import zsh
-```
-
-Этот параметр поддерживает как и упрощённый, так и полный формат.
-
-# bash
-
-TODO
diff --git a/docs-i18n/ru/key-binding_ru.md b/docs-i18n/ru/key-binding_ru.md
deleted file mode 100644
index d6917e4e..00000000
--- a/docs-i18n/ru/key-binding_ru.md
+++ /dev/null
@@ -1,39 +0,0 @@
-# Key binding
-
-По умолчанию, Autin будет переназначать <kbd>Ctrl-r</kbd> и клавишу 'стрелка вверх'.
-Если вы не хотите этого, установите параметр ATUIN_NOBIND прежде чем вызывать `atuin init`
-
-Например,
-
-```
-export ATUIN_NOBIND="true"
-eval "$(atuin init zsh)"
-```
-
-Таким образом вы можете разрешить переназначение клавиш Autin, если это необходимо.
-Делайте это до инициализирующего вызова.
-
-# zsh
-
-Autin устанавливает виджет ZLE "atuin-search"
-
-```
-export ATUIN_NOBIND="true"
-eval "$(atuin init zsh)"
-
-bindkey '^r' atuin-search
-
-# зависит от режима терминала
-bindkey '^[[A' atuin-search
-bindkey '^[OA' atuin-search
-```
-
-# bash
-
-```
-export ATUIN_NOBIND="true"
-eval "$(atuin init bash)"
-
-# Переопределите ctrl-r, и любые другие сочетания горячих клавиш тут
-bind -x '"\C-r": __atuin_history'
-```
diff --git a/docs-i18n/ru/list_ru.md b/docs-i18n/ru/list_ru.md
deleted file mode 100644
index e40d3045..00000000
--- a/docs-i18n/ru/list_ru.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Вывад истории на экран
-
-```
-atuin history list
-```
-
-| Аргумент | Описание |
-| -------------- | ------------------------------------------------------------------------------ |
-| `--cwd/-c` | Каталог, историю команд которой необходимо вывести (по умолчанию все каталоги) |
-| `--session/-s` | Выводит историю команд только текущей сессии (по умолчанию false) |
-| `--human` | Читаемый формат для времени и периодов времени (по умолчанию false) |
diff --git a/docs-i18n/ru/search_ru.md b/docs-i18n/ru/search_ru.md
deleted file mode 100644
index 8302decc..00000000
--- a/docs-i18n/ru/search_ru.md
+++ /dev/null
@@ -1,38 +0,0 @@
-# `atuin search`
-
-```
-atuin search <query>
-```
-
-Поиск в Atuin также поддерживает wildcards со знаками `*` или `%`.
-По умолчанию, должен быть указан префикс (т.е. все запросы автоматически дополняются wildcard -ами)
-
-| Аргумент | Описание |
-| ------------------ | ------------------------------------------------------------------------------------------- |
-| `--cwd/-c` | Каталог, для которого отображается история (по умолчанию, все каталоги)) |
-| `--exclude-cwd` | Исключить команды которые запускались в этом каталоге (по умолчанию none) |
-| `--exit/-e` | Фильтровать по exit code (по умолчанию none) |
-| `--exclude-exit` | Исключить команды, которые завершились с указанным значением (по умолчанию none) |
-| `--before` | Включить только команды, которые были запущены до указанного времени (по умолчанию none) |
-| `--after` | Включить только команды, которые были запущены после указанного времени (по умолчанию none) |
-| `--interactive/-i` | Открыть интерактивный поисковой графический интерфейс (по умолчанию false) |
-| `--human` | Использовать читаемое формавтирование для времени и периодов времени (по умолчанию false) |
-
-## Примеры
-
-```
-# Начать интерактивный поиск с текстовым пользовательским интерфейсом
-atuin search -i
-
-# Начать интерактивный поиск с текстовым пользовательским интерфейсом и уже введённым запросом
-atuin search -i atuin
-
-# Искать по всем командам, начиная с cargo, которые успешно завершились
-atuin search --exit 0 cargo
-
-# Искать по всем командам которые завершились ошибками и были вызваны в текущей папке и были запущены до первого апреля 2021
-atuin search --exclude-exit 0 --before 01/04/2021 --cwd .
-
-# Искать по всем командам, начиная с cargo, которые успешно завершились и были запущены после трёх часо дня вчера
-atuin search --exit 0 --after "yesterday 3pm" cargo
-```
diff --git a/docs-i18n/ru/server_ru.md b/docs-i18n/ru/server_ru.md
deleted file mode 100644
index 25b45abf..00000000
--- a/docs-i18n/ru/server_ru.md
+++ /dev/null
@@ -1,160 +0,0 @@
-# `atuin server`
-
-Autin позволяет запустить свой собственный сервер синхронизации, если вы
-не хотите использовать мой :)
-
-Здесь есть только одна субкоманда, `atuin server start`, которая запустит
-Autin http-сервер синхронизации
-
-```
-USAGE:
- atuin server start [OPTIONS]
-
-FLAGS:
- --help Prints help information
- -V, --version Prints version information
-
-OPTIONS:
- -h, --host <host>
- -p, --port <port>
-```
-
-## config
-
-Серверная конфигурация лежит отдельно от файла пользовательсокй, даже если
-это один и тот же бинарный файл. Серверная конфигурация лежит в `~/.config/atuin/server.toml`.
-
-Этот файл выглядит как-то так:
-
-```toml
-host = "0.0.0.0"
-port = 8888
-open_registration = true
-db_uri="postgres://user:password@hostname/database"
-```
-
-Конфигурация так же может находииться в переменных окружения.
-
-```sh
-ATUIN_HOST="0.0.0.0"
-ATUIN_PORT=8888
-ATUIN_OPEN_REGISTRATION=true
-ATUIN_DB_URI="postgres://user:password@hostname/database"
-```
-
-### host
-
-Адрес хоста, который будет прослушиваться сервером Autin
-
-По умолчанию это `127.0.0.1`.
-
-### post
-
-POST, который будет прослушиваться сервером Autin.
-
-По умолчанию это `8888`.
-
-### open_registration
-
-Если `true`, autin будет разрешать регистрацию новых пользователей.
-Установите флаг `false`, если после создания вашего аккаута вы не хотите, чтобы другие
-могли пользоваться вашим сервером.
-
-По умолчанию `false`.
-
-### db_uri
-
-Действующий URI postgres, где будет сохранён аккаунт пользователя и история.
-
-## Docker
-
-Поддерживается образ Docker чтобы сделать проще развертывание сервера в контейнере.
-
-```sh
-docker run -d -v "$USER/.config/atuin:/config" ghcr.io/ellie/atuin:latest server start
-```
-
-## Docker Compose
-
-Использование вашего собственного docker-образа с хостингом вашего собственного Autin может быть реализовано через
-файл docker-compose.
-
-Создайте файл `.env` рядом с `docker-compode.yml` с содержанием наподобие этому:
-
-```
-ATUIN_DB_USERNAME=atuin
-# Choose your own secure password
-ATUIN_DB_PASSWORD=really-insecure
-```
-
-Создайте `docker-compose.yml`:
-
-```yaml
-version: '3.5'
-services:
- atuin:
- restart: always
- image: ghcr.io/ellie/atuin:main
- command: server start
- volumes:
- - "./config:/config"
- links:
- - postgresql:db
- ports:
- - 8888:8888
- environment:
- ATUIN_HOST: "0.0.0.0"
- ATUIN_OPEN_REGISTRATION: "true"
- ATUIN_DB_URI: postgres://$ATUIN_DB_USERNAME:$ATUIN_DB_PASSWORD@db/atuin
- postgresql:
- image: postgres:14
- restart: unless-stopped
- volumes: # Don't remove permanent storage for index database files!
- - "./database:/var/lib/postgresql/data/"
- environment:
- POSTGRES_USER: $ATUIN_DB_USERNAME
- POSTGRES_PASSWORD: $ATUIN_DB_PASSWORD
- POSTGRES_DB: atuin
-```
-
-Запустите службы с помощью `docker-compose`:
-
-```sh
-docker-compose up -d
-```
-
-### Использование systemd для управления сервером Autin
-
-`systemd` юнит чтобы управлять службами, контролируемыми `docker-compose`:
-
-```
-[Unit]
-Description=Docker Compose Atuin Service
-Requires=docker.service
-After=docker.service
-
-[Service]
-# Where the docker-compose file is located
-WorkingDirectory=/srv/atuin-server
-ExecStart=/usr/bin/docker-compose up
-ExecStop=/usr/bin/docker-compose down
-TimeoutStartSec=0
-Restart=on-failure
-StartLimitBurst=3
-
-[Install]
-WantedBy=multi-user.target
-```
-
-Включите и запустите службу командой:
-
-```sh
-systemctl enable --now atuin
-```
-
-Проверьте, работает ли:
-
-```sh
-systemctl status atuin
-```
-
diff --git a/docs-i18n/ru/shell-completions_ru.md b/docs-i18n/ru/shell-completions_ru.md
deleted file mode 100644
index 56fb1602..00000000
--- a/docs-i18n/ru/shell-completions_ru.md
+++ /dev/null
@@ -1,20 +0,0 @@
-# `atuin gen-completions`
-
-[Shell completions](https://en.wikipedia.org/wiki/Command-line_completion) для Atuin
-могут бять сгенерированы путём указания каталога для вывода и желаемого shell через субкомманду `gen-completions`.
-
-```
-$ atuin gen-completions --shell bash --out-dir $HOME
-
-Shell completion for BASH is generated in "/home/user"
-```
-
-Возможные команды для аргумента `--shell`могут быть следующими:
-
-- `bash`
-- `fish`
-- `zsh`
-- `powershell`
-- `elvish`
-
-Также рекомендуем прочитать [supported shells](./../../README.md#supported-shells).
diff --git a/docs-i18n/ru/stats_ru.md b/docs-i18n/ru/stats_ru.md
deleted file mode 100644
index 842ad71b..00000000
--- a/docs-i18n/ru/stats_ru.md
+++ /dev/null
@@ -1,40 +0,0 @@
-# `atuin stats`
-
-Atuin также может выводить статистику, основанную на истории. Пока что в очень простом виде,
-но скоро должно появиться больше возможностей.
-
-Статистика выводится пока только на английском
-Statistics in english only
-# TODO
-
-```
-$ atuin stats day last friday
-
-+---------------------+------------+
-| Statistic | Value |
-+---------------------+------------+
-| Most used command | git status |
-+---------------------+------------+
-| Commands ran | 450 |
-+---------------------+------------+
-| Unique commands ran | 213 |
-+---------------------+------------+
-
-$ atuin stats day 01/01/21 # also accepts absolute dates
-```
-
-Также, может быть выведена статистика всей известной Autin истории:
-
-```
-$ atuin stats all
-
-+---------------------+-------+
-| Statistic | Value |
-+---------------------+-------+
-| Most used command | ls |
-+---------------------+-------+
-| Commands ran | 8190 |
-+---------------------+-------+
-| Unique commands ran | 2996 |
-+---------------------+-------+
-```
diff --git a/docs-i18n/ru/sync_ru.md b/docs-i18n/ru/sync_ru.md
deleted file mode 100644
index 08831cbd..00000000
--- a/docs-i18n/ru/sync_ru.md
+++ /dev/null
@@ -1,60 +0,0 @@
-# `atuin sync`
-
-Autin может сделать резервную копию вашей истории на сервер чтобы обеспечить использование
-разными компьютерами одной и той же истории. Вся история будет зашифрована двусторонним шифрованием,
-так что сервер _никогда_ не получит ваши данные!
-
-Можно сделать свой сервер (запустив `atuin server start`, об этом написано в других
-файлах документациии), но у меня есть свой https://api.atuin.sh. Это серверный адрес по умолчанию,
-который может быть изменён в [конфигурации](config_ru.md). Опять же, я _не_ могу получить ваши данные
-и они мне не нужны.
-
-## Частота синхронизации
-
-Синхронизация будет происходить автоматически, если обратное не было указано в конфигурации.
-Отконфигурировать сей параметр можно в [config](config_ru.md)
-
-## Синхронизация
-
-Синхронизироваться также можно вручную, используя команду `atuin sync`
-
-## Регистрация
-
-Можно зарегистрировать аккаунт для синхронизации:
-
-```
-atuin register -u <USERNAME> -e <EMAIL> -p <PASSWORD>
-```
-
-Имена пользователей должны быть уникальны, и электронная почта должна использваться
-только для срочных уведомлений (изменения политик, нарушения безопасности и т.д.)
-
-Псоле регистрации, вы уже сразу вошли в свой аккаунт :) С этого момента синхронизация
-будет проходить автоматически
-
-## Ключ
-
-Поскольку все данные шифруются, Autin при работе сгенерирует ваш ключ. Он будет сохранён в
-каталоге с данными Autin (`~/.local/share/atuin` на системах с GNU/Linux)
-
-Также можно сделать это самим:
-
-```
-atuin key
-```
-
-Никогда не передавайте никому этот ключ!
-
-## Вход
-
-Если вы хотите войти с другого компьютера, вам потребуется ключ безопасности (`atuin key`).
-
-```
-atuin login -u <USERNAME> -p <PASSWORD> -k <KEY>
-```
-
-## Выход
-
-```
-atuin logout
-```
diff --git a/docs-i18n/zh-CN/README.md b/docs-i18n/zh-CN/README.md
deleted file mode 100644
index 065d1b4d..00000000
--- a/docs-i18n/zh-CN/README.md
+++ /dev/null
@@ -1,234 +0,0 @@
-<p align="center">
- <picture>
- <source media="(prefers-color-scheme: dark)" srcset="https://github.com/atuinsh/atuin/assets/53315310/13216a1d-1ac0-4c99-b0eb-d88290fe0efd">
- <img alt="Text changing depending on mode. Light: 'So light!' Dark: 'So dark!'" src="https://github.com/atuinsh/atuin/assets/53315310/08bc86d4-a781-4aaa-8d7e-478ae6bcd129">
-</picture>
-</p>
-
-<p align="center">
-<em>神奇的 shell 历史记录</em>
-</p>
-
-<hr/>
-
-<p align="center">
- <a href="https://github.com/atuinsh/atuin/actions?query=workflow%3ARust"><img src="https://img.shields.io/github/actions/workflow/status/atuinsh/atuin/rust.yml?style=flat-square" /></a>
- <a href="https://crates.io/crates/atuin"><img src="https://img.shields.io/crates/v/atuin.svg?style=flat-square" /></a>
- <a href="https://crates.io/crates/atuin"><img src="https://img.shields.io/crates/d/atuin.svg?style=flat-square" /></a>
- <a href="https://github.com/atuinsh/atuin/blob/main/LICENSE"><img src="https://img.shields.io/crates/l/atuin.svg?style=flat-square" /></a>
- <a href="https://discord.gg/Fq8bJSKPHh"><img src="https://img.shields.io/discord/954121165239115808" /></a>
- <a rel="me" href="https://hachyderm.io/@atuin"><img src="https://img.shields.io/mastodon/follow/109944632283122560?domain=https%3A%2F%2Fhachyderm.io&style=social"/></a>
- <a href="https://twitter.com/atuinsh"><img src="https://img.shields.io/twitter/follow/atuinsh?style=social" /></a>
-</p>
-
-
-[English] | [简体中文]
-
-Atuin 使用 SQLite 数据库取代了你现有的 shell 历史,并为你的命令记录了额外的内容。此外,它还通过 Atuin 服务器,在机器之间提供可选的、完全加密的历史记录同步功能。
-
-<p align="center">
- <img src="../../demo.gif" alt="animated" width="80%" />
-</p>
-
-<p align="center">
-<em>显示退出代码、命令持续时间、上次执行时间和执行的命令</em>
-</p>
-
-除了搜索 UI,它还可以执行以下操作:
-
-```
-# 搜索昨天下午3点之后记录的所有成功的 `make` 命令
-atuin search --exit 0 --after "yesterday 3pm" make
-```
-
-你可以使用我(ellie)托管的服务器,也可以使用你自己的服务器!或者干脆不使用 sync 功能。所有的历史记录同步都是加密,即使我想,也无法访问你的数据。且我**真的**不想。
-
-## 功能
-
-- 重新绑定 `up` 和 `ctrl-r` 的全屏历史记录搜索UI界面
-- 使用 sqlite 数据库存储 shell 历史记录
-- 备份以及同步已加密的 shell 历史记录
-- 在不同的终端、不同的会话以及不同的机器上都有相同的历史记录
-- 记录退出代码、cwd、主机名、会话、命令持续时间,等等。
-- 计算统计数据,如 "最常用的命令"。
-- 不替换旧的历史文件
-- 通过 <kbd>Alt-\<num\></kbd> 快捷键快速跳转到之前的记录
-- 通过 ctrl-r 切换过滤模式;可以仅从当前会话、目录或全局来搜索历史记录
-
-## 文档
-
-- [快速开始](#快速开始)
-- [安装](#安装)
-- [导入](./import.md)
-- [配置](./config.md)
-- [历史记录搜索](./search.md)
-- [历史记录云端同步](./sync.md)
-- [历史记录统计](./stats.md)
-- [运行你自己的服务器](./server.md)
-- [键绑定](./key-binding.md)
-- [shell 补全](./shell-completions.md)
-
-## 支持的 Shells
-
-- zsh
-- bash
-- fish
-
-## 社区
-
-Atuin 有一个 Discord 社区, 可以在 [这里](https://discord.gg/Fq8bJSKPHh) 获得
-
-# 快速开始
-
-## 使用默认的同步服务器
-
-这将为您注册由我托管的默认同步服务器。 一切都是端到端加密的,所以你的秘密是安全的!
-
-阅读下面的更多信息,了解仅供离线使用或托管您自己的服务器。
-
-```
-bash <(curl https://raw.githubusercontent.com/ellie/atuin/main/install.sh)
-
-atuin register -u <USERNAME> -e <EMAIL> -p <PASSWORD>
-atuin import auto
-atuin sync
-```
-
-### 使用活跃图
-
-除了托管 Atuin 服务器外,还有一个服务可以用来生成你的 shell 历史记录使用活跃图!这个功能的灵感来自于 GitHub 的使用活跃图。
-
-例如,这是我的:
-
-![](https://api.atuin.sh/img/ellie.png?token=0722830c382b42777bdb652da5b71efb61d8d387)
-
-如果你也想要,请在登陆你的同步服务器后,执行
-
-```
-curl https://api.atuin.sh/enable -d $(cat ~/.local/share/atuin/session)
-```
-
-执行结果为你的活跃图 URL 地址。可以共享或嵌入这个 URL 地址,令牌(token)并<i>不是</i>加密的,只是用来防止被枚举攻击。
-
-## 仅离线 (不同步)
-
-```
-bash <(curl https://raw.githubusercontent.com/ellie/atuin/main/install.sh)
-
-atuin import auto
-```
-
-## 安装
-
-### 脚本 (推荐)
-
-安装脚本将帮助您完成设置,确保您的 shell 正确配置。 它还将使用以下方法之一,在可能的情况下首选系统包管理器(pacman、homebrew 等)。
-
-```
-# 不要以root身份运行,如果需要的话,会要求root。
-bash <(curl https://raw.githubusercontent.com/ellie/atuin/main/install.sh)
-```
-
-然后可直接看 <a href="#shell-plugin">Shell 插件</a>
-
-### 通过 cargo
-
-最好使用 [rustup](https://rustup.rs/) 来设置 Rust 工具链,然后你就可以运行下面的命令:
-
-```
-cargo install atuin
-```
-
-然后可直接看 <a href="#shell-plugin">Shell 插件</a>
-
-### Homebrew
-
-```
-brew install atuin
-```
-
-然后可直接看 <a href="#shell-plugin">Shell 插件</a>
-
-### MacPorts
-
-Atuin 也可以在 [MacPorts](https://ports.macports.org/port/atuin/) 中找到
-
-```
-sudo port install atuin
-```
-
-然后可直接看 <a href="#shell-plugin">Shell 插件</a>
-
-### Pacman
-
-Atuin 在 Arch Linux 的 [社区存储库](https://archlinux.org/packages/community/x86_64/atuin/) 中可用。
-
-```
-pacman -S atuin
-```
-
-然后可直接看 <a href="#shell-plugin">Shell 插件</a>
-
-### 从源码编译安装
-
-```
-git clone https://github.com/ellie/atuin.git
-cd atuin/crates/atuin
-cargo install --path .
-```
-
-然后可直接看 <a href="#shell-plugin">Shell 插件</a>
-
-## <a id="shell-plugin">Shell 插件</a>
-
-安装二进制文件后,需要安装 shell 插件。 如果你使用的是脚本安装,那么这一切应该都会帮您完成!
-
-### zsh
-
-```
-echo 'eval "$(atuin init zsh)"' >> ~/.zshrc
-```
-
-或使用插件管理器:
-
-```
-zinit load ellie/atuin
-```
-
-### bash
-
-我们需要设置一些钩子(hooks), 所以首先需要安装 bash-preexec :
-
-```
-curl https://raw.githubusercontent.com/rcaloras/bash-preexec/master/bash-preexec.sh -o ~/.bash-preexec.sh
-echo '[[ -f ~/.bash-preexec.sh ]] && source ~/.bash-preexec.sh' >> ~/.bashrc
-```
-
-然后设置 Atuin
-
-```
-echo 'eval "$(atuin init bash)"' >> ~/.bashrc
-```
-
-### fish
-
-添加
-
-```
-atuin init fish | source
-```
-
-到 `~/.config/fish/config.fish` 文件中的 `is-interactive` 块中
-
-### Fig
-
-通过 [Fig](https://fig.io) 可为 zsh, bash 或 fish 一键安装 `atuin` 脚本插件。
-
-<a href="https://fig.io/plugins/other/atuin" target="_blank"><img src="https://fig.io/badges/install-with-fig.svg" /></a>
-
-## ...这个名字是什么意思?
-
-Atuin 以 "The Great A'Tuin" 命名, 这是一只来自 Terry Pratchett 的 Discworld 系列书籍的巨龟。
-
-[English]: ../../README.md
-[简体中文]: ./README.md
diff --git a/docs-i18n/zh-CN/config.md b/docs-i18n/zh-CN/config.md
deleted file mode 100644
index 3aa63a9e..00000000
--- a/docs-i18n/zh-CN/config.md
+++ /dev/null
@@ -1,137 +0,0 @@
-# 配置
-
-Atuin 维护两个配置文件,存储在 `~/.config/atuin/` 中。 我们将数据存储在 `~/.local/share/atuin` 中(除非被 XDG\_\* 覆盖)。
-
-您可以通过设置更改配置目录的路径 `ATUIN_CONFIG_DIR`。 例如
-
-```
-export ATUIN_CONFIG_DIR = /home/ellie/.atuin
-```
-
-## 客户端配置
-
-```
-~/.config/atuin/config.toml
-```
-
-客户端运行在用户的机器上,除非你运行的是服务器,否则这就是你所关心的。
-
-见 [config.toml](../../atuin-client/config.toml) 中的例子
-
-### `dialect`
-
-这配置了 [stats](stats.md) 命令解析日期的方式。 它有两个可能的值
-
-```
-dialect = "uk"
-```
-
-或者
-
-```
-dialect = "us"
-```
-
-默认为 "us".
-
-### `auto_sync`
-
-配置登录时是否自动同步。默认为 true
-
-```
-auto_sync = true/false
-```
-
-### `sync_address`
-
-同步的服务器地址! 默认为 `https://api.atuin.sh`
-
-```
-sync_address = "https://api.atuin.sh"
-```
-
-### `sync_frequency`
-
-多长时间与服务器自动同步一次。这可以用一种"人类可读"的格式给出。例如,`10s`,`20m`,`1h`,等等。默认为 `1h` 。
-
-如果设置为 `0`,Atuin将在每个命令之后进行同步。一些服务器可能有潜在的速率限制,这不会造成任何问题。
-
-```
-sync_frequency = "1h"
-```
-
-### `db_path`
-
-Atuin SQlite数据库的路径。默认为
-`~/.local/share/atuin/history.db`
-
-```
-db_path = "~/.history.db"
-```
-
-### `key_path`
-
-Atuin加密密钥的路径。默认为
-`~/.local/share/atuin/key`
-
-```
-key = "~/.atuin-key"
-```
-
-### `session_path`
-
-Atuin服务器会话文件的路径。默认为
-`~/.local/share/atuin/session` 。 这本质上只是一个API令牌
-
-```
-key = "~/.atuin-session"
-```
-
-### `search_mode`
-
-使用哪种搜索模式。Atuin 支持 "prefix"(前缀)、"fulltext"(全文) 和 "fuzzy"(模糊)搜索模式。前缀(prefix)搜索语法为 "query\*",全文(fulltext)搜索语法为 "\*query\*",而模糊搜索适用的搜索语法 [如下所述](#fuzzy-search-syntax) 。
-
-默认配置为 "fuzzy"
-
-### `filter_mode`
-
-搜索时要使用的默认过滤器
-
-| 模式 | 描述 |
-|--------------- | --------------- |
-| global (default) | 从所有主机、所有会话、所有目录中搜索历史记录 |
-| host | 仅从该主机搜索历史记录 |
-| session | 仅从当前会话中搜索历史记录 |
-| directory | 仅从当前目录搜索历史记录|
-
-过滤模式仍然可以通过 ctrl-r 来切换
-
-
-```
-search_mode = "fulltext"
-```
-
-#### `fuzzy` 的搜索语法
-
-`fuzzy` 搜索语法的基础是 [fzf 搜索语法](https://github.com/junegunn/fzf#search-syntax) 。
-
-| 内容 | 匹配类型 | 描述 |
-| --------- | -------------------------- | ------------------------------------ |
-| `sbtrkt` | fuzzy-match | 匹配 `sbtrkt` 的项目 |
-| `'wild` | exact-match (quoted) | 包含 `wild` 的项目 |
-| `^music` | prefix-exact-match | 以 `music` 开头的项目 |
-| `.mp3$` | suffix-exact-match | 以 `.mp3` 结尾的项目 |
-| `!fire` | inverse-exact-match | 不包括 `fire` 的项目 |
-| `!^music` | inverse-prefix-exact-match | 不以 `music` 开头的项目 |
-| `!.mp3$` | inverse-suffix-exact-match | 不以 `.mp3` 结尾的项目 |
-
-
-单个条形字符术语充当 OR 运算符。 例如,以下查询匹配以 `core` 开头并以 `go`、`rb` 或 `py` 结尾的条目。
-
-```
-^core go$ | rb$ | py$
-```
-
-## 服务端配置
-
-`// TODO`
diff --git a/docs-i18n/zh-CN/docker.md b/docs-i18n/zh-CN/docker.md
deleted file mode 100644
index 64704679..00000000
--- a/docs-i18n/zh-CN/docker.md
+++ /dev/null
@@ -1,90 +0,0 @@
-# Docker
-
-Atuin 提供了一个 docker 镜像(image),可以更轻松地将服务器部署为容器(container)。
-
-```sh
-docker run -d -v "$USER/.config/atuin:/config" ghcr.io/ellie/atuin:latest server start
-```
-
-# Docker Compose
-
-使用已有的 docker 镜像(image)来托管你自己的 Atuin,可以使用提供的 docker-compose 文件来完成
-
-在 docker-compose.yml 同级目录下创建一个 .env 文件,内容如下:
-
-```
-ATUIN_DB_USERNAME=atuin
-# 填写你的密码
-ATUIN_DB_PASSWORD=really-insecure
-```
-
-创建 `docker-compose.yml` 文件:
-
-```yaml
-version: '3.5'
-services:
- atuin:
- restart: always
- image: ghcr.io/ellie/atuin:main
- command: server start
- volumes:
- - "./config:/config"
- links:
- - postgresql:db
- ports:
- - 8888:8888
- environment:
- ATUIN_HOST: "0.0.0.0"
- ATUIN_OPEN_REGISTRATION: "true"
- ATUIN_DB_URI: postgres://$ATUIN_DB_USERNAME:$ATUIN_DB_PASSWORD@db/atuin
- postgresql:
- image: postgres:14
- restart: unless-stopped
- volumes: # 不要删除索引数据库文件的永久存储空间!
- - "./database:/var/lib/postgresql/data/"
- environment:
- POSTGRES_USER: $ATUIN_DB_USERNAME
- POSTGRES_PASSWORD: $ATUIN_DB_PASSWORD
- POSTGRES_DB: atuin
-```
-
-使用 `docker-compose` 启动服务:
-
-```sh
-docker-compose up -d
-```
-
-## 使用 systemd 管理你的 atuin 服务器
-
-以下 `systemd` 的配置文件用来管理你的 `docker-compose` 托管服务:
-
-```
-[Unit]
-Description=Docker Compose Atuin Service
-Requires=docker.service
-After=docker.service
-
-[Service]
-# Where the docker-compose file is located
-WorkingDirectory=/srv/atuin-server
-ExecStart=/usr/bin/docker-compose up
-ExecStop=/usr/bin/docker-compose down
-TimeoutStartSec=0
-Restart=on-failure
-StartLimitBurst=3
-
-[Install]
-WantedBy=multi-user.target
-```
-
-启用服务:
-
-```sh
-systemctl enable --now atuin
-```
-
-检查服务是否正常运行:
-
-```sh
-systemctl status atuin
-```
diff --git a/docs-i18n/zh-CN/import.md b/docs-i18n/zh-CN/import.md
deleted file mode 100644
index c1f1d06d..00000000
--- a/docs-i18n/zh-CN/import.md
+++ /dev/null
@@ -1,25 +0,0 @@
-# `atuin import`
-
-Atuin 可以从您的“旧”历史文件中导入您的历史记录
-
-`atuin import auto` 将尝试找出你的 shell(通过 \$SHELL)并运行正确的导入器
-
-不幸的是,这些旧文件没有像 Atuin 那样存储尽可能多的信息,因此并非所有功能都可用于导入的数据。
-
-# zsh
-
-```
-atuin import zsh
-```
-
-如果你设置了 HISTFILE,这应该会被选中!如果没有,可以尝试以下操作
-
-```
-HISTFILE=/path/to/history/file atuin import zsh
-```
-
-这支持简单和扩展形式
-
-# bash
-
-TODO
diff --git a/docs-i18n/zh-CN/k8s.md b/docs-i18n/zh-CN/k8s.md
deleted file mode 100644
index ce63aab1..00000000
--- a/docs-i18n/zh-CN/k8s.md
+++ /dev/null
@@ -1,195 +0,0 @@
-# Kubernetes
-
-你可以使用 Kubernetes 来托管你的 Atuin 服务器。
-
-为数据库凭证创建 [`secrets.yaml`](../../k8s/secrets.yaml) 文件:
-
-```yaml
-apiVersion: v1
-kind: Secret
-metadata:
- name: atuin-secrets
-type: Opaque
-stringData:
- ATUIN_DB_USERNAME: atuin
- ATUIN_DB_PASSWORD: seriously-insecure
- ATUIN_HOST: "127.0.0.1"
- ATUIN_PORT: "8888"
- ATUIN_OPEN_REGISTRATION: "true"
- ATUIN_DB_URI: "postgres://atuin:seriously-insecure@localhost/atuin"
-immutable: true
-```
-
-为 Atuin 服务器创建 [`atuin.yaml`](../../k8s/atuin.yaml) 文件:
-
-
-```yaml
----
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: atuin
-spec:
- replicas: 1
- selector:
- matchLabels:
- io.kompose.service: atuin
- template:
- metadata:
- labels:
- io.kompose.service: atuin
- spec:
- containers:
- - args:
- - server
- - start
- env:
- - name: ATUIN_DB_URI
- valueFrom:
- secretKeyRef:
- name: atuin-secrets
- key: ATUIN_DB_URI
- optional: false
- - name: ATUIN_HOST
- value: 0.0.0.0
- - name: ATUIN_PORT
- value: "8888"
- - name: ATUIN_OPEN_REGISTRATION
- value: "true"
- image: ghcr.io/atuinsh/atuin:latest
- name: atuin
- ports:
- - containerPort: 8888
- resources:
- limits:
- cpu: 250m
- memory: 1Gi
- requests:
- cpu: 250m
- memory: 1Gi
- volumeMounts:
- - mountPath: /config
- name: atuin-claim0
- - name: postgresql
- image: postgres:14
- ports:
- - containerPort: 5432
- env:
- - name: POSTGRES_DB
- value: atuin
- - name: POSTGRES_PASSWORD
- valueFrom:
- secretKeyRef:
- name: atuin-secrets
- key: ATUIN_DB_PASSWORD
- optional: false
- - name: POSTGRES_USER
- valueFrom:
- secretKeyRef:
- name: atuin-secrets
- key: ATUIN_DB_USERNAME
- optional: false
- resources:
- limits:
- cpu: 250m
- memory: 1Gi
- requests:
- cpu: 250m
- memory: 1Gi
- volumeMounts:
- - mountPath: /var/lib/postgresql/data/
- name: database
- volumes:
- - name: database
- persistentVolumeClaim:
- claimName: database
- - name: atuin-claim0
- persistentVolumeClaim:
- claimName: atuin-claim0
----
-apiVersion: v1
-kind: Service
-metadata:
- labels:
- io.kompose.service: atuin
- name: atuin
-spec:
- type: NodePort
- ports:
- - name: "8888"
- port: 8888
- nodePort: 30530
- selector:
- io.kompose.service: atuin
----
-kind: PersistentVolume
-apiVersion: v1
-metadata:
- name: database-pv
- labels:
- app: database
- type: local
-spec:
- storageClassName: manual
- capacity:
- storage: 300Mi
- accessModes:
- - ReadWriteOnce
- hostPath:
- path: "/Users/firstname.lastname/.kube/database"
----
-apiVersion: v1
-kind: PersistentVolumeClaim
-metadata:
- labels:
- io.kompose.service: database
- name: database
-spec:
- storageClassName: manual
- accessModes:
- - ReadWriteOnce
- resources:
- requests:
- storage: 300Mi
----
-apiVersion: v1
-kind: PersistentVolumeClaim
-metadata:
- labels:
- io.kompose.service: atuin-claim0
- name: atuin-claim0
-spec:
- accessModes:
- - ReadWriteOnce
- resources:
- requests:
- storage: 10Mi
-```
-
-最后,你可能想让 atuin 使用单独的命名空间(namespace),创建 [`namespace.yaml`](../../k8s/namespaces.yaml) 文件:
-
-```yaml
-apiVersion: v1
-kind: Namespace
-metadata:
- name: atuin-namespace
- labels:
- name: atuin
-```
-
-在企业级安装部署时,你可能想要数据库内容永久存储在集群中,而不是在主机系统中。在上述配置中,`storageClassName` 配置为 `manual`,主机系统的挂载目录配置为 `/Users/firstname.lastname/.kube/database`,请注意,这些配置将会使得数据库内容存储在 kubernetes 集群<i>外部</i>中。
-
-你还应该将 `secrets.yaml` 文件中的 `ATUIN_DB_PASSWORD` 和 `ATUIN_DB_URI` 修改为更安全的加密字符串。
-
-Atuin 运行在主机系统的 `30530` 端口上。这是通过 `nodePort` 属性进行陪你的。Kubernetes 有一个严格规则,即不允许暴露小于 30000 的端口号。为了使客户端能够正常工作,你需要在你的 `config.toml` 文件中设置端口号,例如 `sync_address = "http://192.168.1.10:30530"`。
-
-使用 `kubectl` 部署 Atuin 服务器:
-
-```shell
- kubectl apply -f ./namespaces.yaml
- kubectl apply -n atuin-namespace \
- -f ./secrets.yaml \
- -f ./atuin.yaml
-```
-
-上面示例同时也位于 atuin 仓库(repository)的 [k8s](../../k8s) 目录下。
diff --git a/docs-i18n/zh-CN/key-binding.md b/docs-i18n/zh-CN/key-binding.md
deleted file mode 100644
index 54c68b37..00000000
--- a/docs-i18n/zh-CN/key-binding.md
+++ /dev/null
@@ -1,48 +0,0 @@
-# 键位绑定
-
-默认情况下, Atuin 将会重新绑定 <kbd>Ctrl-r</kbd> 和 `up` 键。如果你不想使用默认绑定,请在调用 `atuin init` 之前设置 ATUIN_NOBIND
-
-例如:
-
-```
-export ATUIN_NOBIND="true"
-eval "$(atuin init zsh)"
-```
-
-如果需要,你可以在调用 `atuin init` 之后对 Atuin 重新进行键绑定
-
-# zsh
-
-Atuin 定义了 ZLE 部件 "atuin-search"
-
-```
-export ATUIN_NOBIND="true"
-eval "$(atuin init zsh)"
-
-bindkey '^r' atuin-search
-
-# 取决于终端模式
-bindkey '^[[A' atuin-search
-bindkey '^[OA' atuin-search
-```
-
-# bash
-
-```
-export ATUIN_NOBIND="true"
-eval "$(atuin init bash)"
-
-# 绑定到 ctrl-r, 也可以在这里添加任何其他你想要的绑定方式
-bind -x '"\C-r": __atuin_history'
-```
-
-# fish
-
-```
-set -gx ATUIN_NOBIND "true"
-atuin init fish | source
-
-# 在 normal 和 insert 模式下绑定到 ctrl-r,你也可以在此处添加其他键位绑定
-bind \cr _atuin_search
-bind -M insert \cr _atuin_search
-```
diff --git a/docs-i18n/zh-CN/list.md b/docs-i18n/zh-CN/list.md
deleted file mode 100644
index fe03529f..00000000
--- a/docs-i18n/zh-CN/list.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# 历史记录列表
-
-```
-atuin history list
-```
-
-| 参数 | 描述 |
-| -------------- | ----------------------------------------------------- |
-| `--cwd/-c` | 要列出历史记录的目录(默认:所有目录) |
-| `--session/-s` | 只对当前会话启用列表历史(默认:false) |
-| `--human` | 对时间戳和持续时间使用人类可读的格式(默认:false)。 |
diff --git a/docs-i18n/zh-CN/search.md b/docs-i18n/zh-CN/search.md
deleted file mode 100644
index 24e320d5..00000000
--- a/docs-i18n/zh-CN/search.md
+++ /dev/null
@@ -1,37 +0,0 @@
-# `atuin search`
-
-```
-atuin search <query>
-```
-
-Atuin 搜索还支持带有 `*` 或 `%` 字符的通配符。 默认情况下,会执行前缀搜索(即,所有查询都会自动附加通配符)。
-
-| 参数 | 描述 |
-| ------------------ | ----------------------------------------------------- |
-| `--cwd/-c` | 列出历史记录的目录(默认:所有目录) |
-| `--exclude-cwd` | 不包括在此目录中运行的命令(默认值:none) |
-| `--exit/-e` | 按退出代码过滤(默认:none) |
-| `--exclude-exit` | 不包括以该值退出的命令(默认值:none) |
-| `--before` | 仅包括在此时间之前运行的命令(默认值:none) |
-| `--after` | 仅包含在此时间之后运行的命令(默认值:none) |
-| `--interactive/-i` | 打开交互式搜索 UI(默认值:false) |
-| `--human` | 对时间戳和持续时间使用人类可读的格式(默认值:false) |
-
-## 举例
-
-```
-# 打开交互式搜索 TUI
-atuin search -i
-
-# 打开预装了查询的交互式搜索 TUI
-atuin search -i atuin
-
-# 搜索所有以 cargo 开头且成功退出的命令。
-atuin search --exit 0 cargo
-
-# 从当前目录中搜索所有在2021年4月1日之前运行且失败的命令。
-atuin search --exclude-exit 0 --before 01/04/2021 --cwd .
-
-# 搜索所有以 cargo 开头,成功退出且是在昨天下午3点之后运行的命令。
-atuin search --exit 0 --after "yesterday 3pm" cargo
-```
diff --git a/docs-i18n/zh-CN/server.md b/docs-i18n/zh-CN/server.md
deleted file mode 100644
index 4cb39df9..00000000
--- a/docs-i18n/zh-CN/server.md
+++ /dev/null
@@ -1,75 +0,0 @@
-# `atuin server`
-
-Atuin 允许您运行自己的同步服务器,以防您不想使用我(ellie)托管的服务器 :)
-
-目前只有一个子命令,`atuin server start`,它将启动 Atuin http 同步服务器。
-
-```
-USAGE:
- atuin server start [OPTIONS]
-
-FLAGS:
- --help Prints help information
- -V, --version Prints version information
-
-OPTIONS:
- -h, --host <host>
- -p, --port <port>
-```
-
-## 配置
-
-服务器的配置与客户端的配置是分开的,即使它们是相同的二进制文件。服务器配置可以在 `~/.config/atuin/server.toml` 找到。
-
-它看起来像这样:
-
-```toml
-host = "0.0.0.0"
-port = 8888
-open_registration = true
-db_uri="postgres://user:password@hostname/database"
-```
-
-另外,配置也可以用环境变量来提供。
-
-```sh
-ATUIN_HOST="0.0.0.0"
-ATUIN_PORT=8888
-ATUIN_OPEN_REGISTRATION=true
-ATUIN_DB_URI="postgres://user:password@hostname/database"
-```
-
-### host
-
-Atuin 服务器应该监听的地址
-
-默认为 `127.0.0.1`.
-
-### port
-
-Atuin 服务器应该监听的端口
-
-默认为 `8888`.
-
-### open_registration
-
-如果为 `true` ,atuin 将接受新用户注册。如果您不希望其他人能够使用您的服务器,请在创建自己的账号后将此设置为 `false`
-
-默认为 `false`.
-
-### db_uri
-
-一个有效的 postgres URI, 用户和历史记录数据将被保存到其中。
-
-### path
-
-path 指的是给 server 添加的路由前缀。值为空字符串将不会添加路由前缀。
-
-默认为 `""`
-
-## 容器部署说明
-
-你可以在容器中部署自己的 atuin 服务器:
-
-* 有关 docker 配置的示例,请参考 [docker](docker.md)。
-* 有关 kubernetes 配置的示例,请参考 [k8s](k8s.md)。
diff --git a/docs-i18n/zh-CN/shell-completions.md b/docs-i18n/zh-CN/shell-completions.md
deleted file mode 100644
index 0979dcb0..00000000
--- a/docs-i18n/zh-CN/shell-completions.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# `atuin gen-completions`
-
-Atuin 的 [Shell 补全](https://en.wikipedia.org/wiki/Command-line_completion) 可以通过 `gen-completions` 子命令指定输出目录和所需的 shell 来生成。
-
-```
-$ atuin gen-completions --shell bash --out-dir $HOME
-
-Shell completion for BASH is generated in "/home/user"
-```
-
-`--shell` 参数的可能值如下:
-
-- `bash`
-- `fish`
-- `zsh`
-- `powershell`
-- `elvish`
-
-此外, 请参阅 [支持的 Shells](./README.md#支持的-Shells).
diff --git a/docs-i18n/zh-CN/stats.md b/docs-i18n/zh-CN/stats.md
deleted file mode 100644
index 2bf557ba..00000000
--- a/docs-i18n/zh-CN/stats.md
+++ /dev/null
@@ -1,35 +0,0 @@
-# `atuin stats`
-
-Atuin 还可以根据你的历史记录进行计算统计数据 - 目前这只是一个小的基本功能,但更多功能即将推出
-
-```
-$ atuin stats day last friday
-
-+---------------------+------------+
-| Statistic | Value |
-+---------------------+------------+
-| Most used command | git status |
-+---------------------+------------+
-| Commands ran | 450 |
-+---------------------+------------+
-| Unique commands ran | 213 |
-+---------------------+------------+
-
-$ atuin stats day 01/01/21 # 也接受绝对日期
-```
-
-它还可以计算所有已知历史记录的统计数据。
-
-```
-$ atuin stats all
-
-+---------------------+-------+
-| Statistic | Value |
-+---------------------+-------+
-| Most used command | ls |
-+---------------------+-------+
-| Commands ran | 8190 |
-+---------------------+-------+
-| Unique commands ran | 2996 |
-+---------------------+-------+
-```
diff --git a/docs-i18n/zh-CN/sync.md b/docs-i18n/zh-CN/sync.md
deleted file mode 100644
index 2fd451d8..00000000
--- a/docs-i18n/zh-CN/sync.md
+++ /dev/null
@@ -1,51 +0,0 @@
-# `atuin sync`
-
-Atuin 可以将您的历史记录备份到服务器,并使用它来确保多台机器具有相同的 shell 历史记录。 这都是端到端加密的,因此服务器操作员_永远_看不到您的数据!
-
-任何人都可以托管一个服务器(尝试 `atuin server start`,更多文档将在后面介绍),但我(ellie)在 https://api.atuin.sh 上托管了一个。这是默认的服务器地址,可以在 [配置](config.md) 中更改。 同样,我_不能_看到您的数据,也不想。
-
-## 同步频率
-
-除非另有配置,否则同步将自动执行。同步的频率可在 [配置](config.md) 中配置。
-
-## 同步
-
-你可以通过 `atuin sync` 来手动触发同步
-
-## 注册
-
-注册一个同步账号
-
-```
-atuin register -u <USERNAME> -e <EMAIL> -p <PASSWORD>
-```
-
-用户名(USERNAME)必须是唯一的,电子邮件(EMAIL)仅用于重要通知(安全漏洞、服务更改等)
-
-注册后,意味着你也已经登录了 :) 同步应该从这里自动发生!
-
-## 密钥
-
-由于你的数据是加密的, Atuin 将为你生成一个密钥。它被存储在 Atuin 的数据目录里( Linux 上为 `~/.local/share/atuin`)
-
-你也可以通过以下方式获得它
-
-```
-atuin key
-```
-
-千万不要跟任何人分享这个!
-
-## 登录
-
-如果你想登录到一个新的机器上,你需要你的加密密钥(`atuin key`)。
-
-```
-atuin login -u <USERNAME> -p <PASSWORD> -k <KEY>
-```
-
-## 登出
-
-```
-atuin logout
-```
diff --git a/fossier.toml b/fossier.toml
deleted file mode 100644
index 45ad0bcd..00000000
--- a/fossier.toml
+++ /dev/null
@@ -1,17 +0,0 @@
-[repo]
-owner = "atuinsh"
-name = "atuin"
-
-[thresholds]
-allow_score = 70.0
-deny_score = 40.0
-min_confidence = 0.5
-
-[actions.deny]
-close_pr = true
-comment = true
-label = "fossier:spam-likely"
-
-[actions.review]
-comment = true
-label = "fossier:needs-review"
diff --git a/install.sh b/install.sh
deleted file mode 100755
index bd82d6da..00000000
--- a/install.sh
+++ /dev/null
@@ -1,197 +0,0 @@
-#! /bin/sh
-set -eu
-
-ATUIN_NON_INTERACTIVE="no"
-
-for arg in "$@"; do
- case "$arg" in
- --non-interactive) ATUIN_NON_INTERACTIVE="yes" ;;
- *) ;;
- esac
-done
-
-if [ "$ATUIN_NON_INTERACTIVE" != "yes" ]; then
- if [ -t 0 ] || { true </dev/tty; } 2>/dev/null; then
- ATUIN_NON_INTERACTIVE="no"
- else
- ATUIN_NON_INTERACTIVE="yes"
- fi
-fi
-
-cat << EOF
- _______ _______ __ __ ___ __ _
-| _ || || | | || | | | | |
-| |_| ||_ _|| | | || | | |_| |
-| | | | | |_| || | | |
-| | | | | || | | _ |
-| _ | | | | || | | | | |
-|__| |__| |___| |_______||___| |_| |__|
-
-Magical shell history
-
-Atuin setup
-https://github.com/atuinsh/atuin
-https://forum.atuin.sh
-
-Please file an issue or reach out on the forum if you encounter any problems!
-
-===============================================================================
-
-EOF
-
-__atuin_install_binary(){
- curl --proto '=https' --tlsv1.2 -LsSf https://github.com/atuinsh/atuin/releases/latest/download/atuin-installer.sh | sh
-}
-
-if ! command -v curl > /dev/null; then
- echo "curl not installed. Please install curl."
- exit
-fi
-
-
-__atuin_install_binary
-
-# TODO: Check which shell is in use
-# Use of single quotes around $() is intentional here
-# shellcheck disable=SC2016
-if ! grep -q "atuin init zsh" "${ZDOTDIR:-$HOME}/.zshrc"; then
- printf '\neval "$(atuin init zsh)"\n' >> "${ZDOTDIR:-$HOME}/.zshrc"
-fi
-
-# Use of single quotes around $() is intentional here
-# shellcheck disable=SC2016
-
-if ! grep -q "atuin init bash" ~/.bashrc; then
- curl --proto '=https' --tlsv1.2 -LsSf https://raw.githubusercontent.com/rcaloras/bash-preexec/master/bash-preexec.sh -o ~/.bash-preexec.sh
- printf '\n[[ -f ~/.bash-preexec.sh ]] && source ~/.bash-preexec.sh\n' >> ~/.bashrc
- echo 'eval "$(atuin init bash)"' >> ~/.bashrc
-fi
-
-if [ -f "$HOME/.config/fish/config.fish" ]; then
- if ! grep -q "atuin init fish" "$HOME/.config/fish/config.fish"; then
- printf '\nif status is-interactive\n atuin init fish | source\nend\n' >> "$HOME/.config/fish/config.fish"
- fi
-fi
-
-ATUIN_BIN="$HOME/.atuin/bin/atuin"
-
-__atuin_install_agent_hook(){
- agent="$1"
- agent_name="$2"
- agent_config_dir="$3"
- shift 3
-
- detected="no"
-
- if [ -d "$agent_config_dir" ]; then
- detected="yes"
- else
- for agent_command in "$@"; do
- if command -v "$agent_command" > /dev/null 2>&1; then
- detected="yes"
- break
- fi
- done
- fi
-
- if [ "$detected" = "yes" ]; then
- echo "Detected $agent_name — installing Atuin hooks..."
- if ! "$ATUIN_BIN" hook install "$agent"; then
- echo "Failed to install Atuin hooks for $agent_name (this version of Atuin may not support it yet)."
- fi
- echo ""
- fi
-}
-
-__atuin_install_agent_hook "claude-code" "Claude Code" "$HOME/.claude" claude
-__atuin_install_agent_hook "codex" "Codex" "$HOME/.codex" codex
-__atuin_install_agent_hook "pi" "pi" "$HOME/.config/pi" pi
-
-echo ""
-echo "Atuin installed successfully!"
-echo ""
-
-if [ "$ATUIN_NON_INTERACTIVE" != "yes" ]; then
-
- printf "Would you like to import your existing shell history into Atuin? [Y/n] "
- read -r import_answer </dev/tty || import_answer="n"
- import_answer="${import_answer:-y}"
-
- case "$import_answer" in
- [yY]*)
- echo ""
- if ! "$ATUIN_BIN" import auto; then
- echo ""
- echo "History import failed. You can retry later with 'atuin import auto'."
- fi
- echo ""
- ;;
- *)
- echo "Skipping history import. You can always run 'atuin import auto' later."
- echo ""
- ;;
- esac
-
- cat << EOF
-Sync your history across all your machines with Atuin Cloud:
-
- - End-to-end encrypted — only you can read your data
- - Access your history from any device
- - Never lose your history, even if you wipe a machine
-
-EOF
-
- printf "Sign up for a sync account? [Y/n] "
- read -r sync_answer </dev/tty || sync_answer="n"
- sync_answer="${sync_answer:-y}"
-
- case "$sync_answer" in
- [yY]*)
- echo ""
- if ! "$ATUIN_BIN" register </dev/tty; then
- echo ""
- echo "Registration did not complete. You can run 'atuin register' any time to try again."
- fi
- ;;
- *)
- echo ""
- printf "Already have an account? Log in with 'atuin login'.\n"
- echo "You can also run 'atuin register' any time to create one."
- ;;
- esac
-
-else
- echo "Non-interactive environment detected — skipping setup prompts."
- echo "You can run the following commands manually after installation:"
- echo ""
- echo " atuin import auto Import your existing shell history"
- echo " atuin register Sign up for a sync account"
- echo " atuin login Log in to an existing sync account"
-fi
-
-if [ "$ATUIN_NON_INTERACTIVE" != "yes" ]; then
- "$ATUIN_BIN" setup </dev/tty
-fi
-
-cat << EOF
-
- _______ __ __ _______ __ _ ___ _ __ __ _______ __ __
-| || | | || _ || | | || | | | | | | || || | | |
-|_ _|| |_| || |_| || |_| || |_| | | |_| || _ || | | |
- | | | || || || _| | || | | || |_| |
- | | | || || _ || |_ |_ _|| |_| || |
- | | | _ || _ || | | || _ | | | | || |
- |___| |__| |__||__| |__||_| |__||___| |_| |___| |_______||_______|
-
-Thanks for installing Atuin! I really hope you like it.
-
-If you have any issues, please open an issue on GitHub or visit our forum (https://forum.atuin.sh)!
-
-If you love Atuin, please give us a star on GitHub! It really helps ⭐️ https://github.com/atuinsh/atuin
-
-===============================================================================
-
- ⚠️ Please restart your shell or open a new terminal for Atuin to take effect!
-
-===============================================================================
-EOF
diff --git a/k8s/atuin.yaml b/k8s/atuin.yaml
deleted file mode 100644
index e537e0ac..00000000
--- a/k8s/atuin.yaml
+++ /dev/null
@@ -1,156 +0,0 @@
----
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: atuin
-spec:
- replicas: 1
- selector:
- matchLabels:
- io.kompose.service: atuin
- template:
- metadata:
- labels:
- io.kompose.service: atuin
- spec:
- containers:
- - args:
- - start
- env:
- - name: ATUIN_DB_URI
- valueFrom:
- secretKeyRef:
- name: atuin-secrets
- key: ATUIN_DB_URI
- optional: false
- - name: ATUIN_HOST
- value: 0.0.0.0
- - name: ATUIN_PORT
- value: "8888"
- - name: ATUIN_OPEN_REGISTRATION
- value: "true"
- image: ghcr.io/atuinsh/atuin:latest
- name: atuin
- ports:
- - containerPort: &port 8888
- resources:
- limits:
- cpu: 250m
- memory: 1Gi
- requests:
- cpu: 250m
- memory: 1Gi
- startupProbe:
- httpGet:
- path: /healthz
- port: *port
- failureThreshold: 30
- periodSeconds: 10
- livenessProbe:
- httpGet:
- path: /healthz
- port: *port
- initialDelaySeconds: 3
- periodSeconds: 3
- readinessProbe:
- tcpSocket:
- port: *port
- initialDelaySeconds: 15
- periodSeconds: 10
- volumeMounts:
- - mountPath: /config
- name: atuin-claim0
- - name: postgresql
- image: postgres:14
- ports:
- - containerPort: 5432
- env:
- - name: POSTGRES_DB
- value: atuin
- - name: POSTGRES_PASSWORD
- valueFrom:
- secretKeyRef:
- name: atuin-secrets
- key: ATUIN_DB_PASSWORD
- optional: false
- - name: POSTGRES_USER
- valueFrom:
- secretKeyRef:
- name: atuin-secrets
- key: ATUIN_DB_USERNAME
- optional: false
- resources:
- limits:
- cpu: 250m
- memory: 1Gi
- requests:
- cpu: 250m
- memory: 1Gi
- volumeMounts:
- - mountPath: /var/lib/postgresql/data/
- name: database
- volumes:
- - name: database
- persistentVolumeClaim:
- claimName: database
- - name: atuin-claim0
- persistentVolumeClaim:
- claimName: atuin-claim0
----
-apiVersion: v1
-kind: Service
-metadata:
- labels:
- io.kompose.service: atuin
- name: atuin
-spec:
- type: NodePort
- ports:
- - name: "8888"
- port: 8888
- nodePort: 31929
- selector:
- io.kompose.service: atuin
----
-kind: PersistentVolume
-apiVersion: v1
-metadata:
- name: database-pv
- labels:
- app: database
- type: local
-spec:
- storageClassName: manual
- capacity:
- storage: 300Mi
- accessModes:
- - ReadWriteOnce
- hostPath:
- path: "/Users/firstname.lastname/.kube/database"
----
-apiVersion: v1
-kind: PersistentVolumeClaim
-metadata:
- labels:
- io.kompose.service: database
- name: database
-spec:
- storageClassName: manual
- accessModes:
- - ReadWriteOnce
- resources:
- requests:
- storage: 300Mi
----
-apiVersion: v1
-kind: PersistentVolumeClaim
-metadata:
- labels:
- io.kompose.service: atuin-claim0
- name: atuin-claim0
-spec:
- accessModes:
- - ReadWriteOnce
- resources:
- requests:
- storage: 10Mi
diff --git a/k8s/namespaces.yaml b/k8s/namespaces.yaml
deleted file mode 100644
index 20a401f6..00000000
--- a/k8s/namespaces.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-apiVersion: v1
-kind: Namespace
-metadata:
- name: atuin-namespace
- labels:
- name: atuin
diff --git a/k8s/secrets.yaml b/k8s/secrets.yaml
deleted file mode 100644
index d6391fad..00000000
--- a/k8s/secrets.yaml
+++ /dev/null
@@ -1,13 +0,0 @@
-apiVersion: v1
-kind: Secret
-metadata:
- name: atuin-secrets
-type: Opaque
-stringData:
- ATUIN_DB_USERNAME: atuin
- ATUIN_DB_PASSWORD: seriously-insecure
- ATUIN_HOST: "127.0.0.1"
- ATUIN_PORT: "8888"
- ATUIN_OPEN_REGISTRATION: "true"
- ATUIN_DB_URI: "postgres://atuin:seriously-insecure@localhost/atuin"
-immutable: true
diff --git a/rust-toolchain.toml b/rust-toolchain.toml
deleted file mode 100644
index 0f87b448..00000000
--- a/rust-toolchain.toml
+++ /dev/null
@@ -1,2 +0,0 @@
-[toolchain]
-channel = "1.96.0"
diff --git a/scripts/release.sh b/scripts/release.sh
deleted file mode 100755
index 8e0717a2..00000000
--- a/scripts/release.sh
+++ /dev/null
@@ -1,508 +0,0 @@
-#!/usr/bin/env bash
-#
-# Atuin CLI Release Script
-#
-# But first — make a cup of tea. Releases without tea are a crime. 🫖
-#
-
-set -euo pipefail
-
-WORKDIR=""
-
-cleanup_on_error() {
- if [[ $? -ne 0 && -n "$WORKDIR" ]]; then
- echo ""
- echo -e " \033[0;31m✗\033[0m Script failed. Working directory preserved at:"
- echo -e " \033[2m$WORKDIR\033[0m"
- fi
-}
-trap cleanup_on_error EXIT
-
-# ════════════════════════════════════════════════════════════════════
-# Formatting
-# ════════════════════════════════════════════════════════════════════
-
-RED='\033[0;31m'
-GREEN='\033[0;32m'
-YELLOW='\033[1;33m'
-BLUE='\033[0;34m'
-CYAN='\033[0;36m'
-MAGENTA='\033[0;35m'
-BOLD='\033[1m'
-DIM='\033[2m'
-NC='\033[0m'
-
-info() { echo -e " ${BLUE}▸${NC} $*"; }
-success() { echo -e " ${GREEN}✓${NC} $*"; }
-warn() { echo -e " ${YELLOW}⚠${NC} $*"; }
-die() { echo -e " ${RED}✗${NC} $*" >&2; exit 1; }
-
-step() {
- echo ""
- echo -e " ${MAGENTA}${BOLD}━━━ $* ━━━${NC}"
- echo ""
-}
-
-confirm() {
- echo -en " ${CYAN}▸${NC} $1 ${DIM}[y/N]${NC} "
- read -r reply
- [[ "$reply" =~ ^[Yy]$ ]]
-}
-
-# ════════════════════════════════════════════════════════════════════
-# Banner
-# ════════════════════════════════════════════════════════════════════
-
-banner() {
- echo ""
- echo -e "${CYAN}"
- cat <<'BANNER'
-
- :
- =#*#=
- #*+*#.
- #**++*+
- =#*++++#.
- **+++++**
- :#++++++*#.
- **+++++++*#
- -#*+++++++*#-
- ##*****#####*
- -*##########:.+####*.
- ***********####*****+
- :**#############*#+
- #+----------------*-
- -*###########**+++##-----=##=-----=##=#
- .#*-==.. =*------------------*
- -#-::::::*=----------#*---------=----=--=*
- +*:::::::--:::::::::::**---+#=----===---=*
- #*::::::::=::::::::::::**-----+#*=-----+#-
- .#+::::::::=-::::::::::::**--------=*####
- #=::::::::=*:::::::::::::+*---------=#-*#=
- ##-:::-**+=+*-:::::::::::-#=--------=#=##-
- :#+**+========++=::::-=++=#+--------+#+#*
- +##++============+*#+=====*+--------+#*#
- *=*#*+==+**++++*#++*====+###--------*###*
- *=-*##=+#=-------#**===+#+---------=##*=#
- *=-=*#**+---------#*+==+#----------*##--#
- :#*- ###=---------#+*==+#=-------=###=-=#
- +=---------#+#+++#*++++*##*== .. #
- ...... +=--*++*+=-#####+-. -+****=.
- ....... =*== . + ...........
- ............::-:............................
- ............................................
- ....###....########.##.....##.####.##....##.
- ...##.##......##....##.....##..##..###...##.
- ..##...##.....##....##.....##..##..####..##.
- .##.....##....##....##.....##..##..##.##.##.
- .#########....##....##.....##..##..##..####.
- .##.....##....##....##.....##..##..##...###.
- .##.....##....##.....#######..####.##....##.
- ............................................
-
- ~ Magical Shell History ~
- Release Script
-
-BANNER
- echo -e "${NC}"
- echo ""
-}
-
-# ════════════════════════════════════════════════════════════════════
-# 1. Dependency check
-# ════════════════════════════════════════════════════════════════════
-
-check_deps() {
- step "Dependencies"
-
- local missing=()
- local deps=(git gsed cargo gh git-cliff)
-
- for cmd in "${deps[@]}"; do
- if command -v "$cmd" &>/dev/null; then
- success "${BOLD}$cmd${NC} ${DIM}$(command -v "$cmd")${NC}"
- else
- echo -e " ${RED}✗${NC} ${BOLD}$cmd${NC} not found"
- missing+=("$cmd")
- fi
- done
-
- if (( ${#missing[@]} )); then
- echo ""
- die "Missing required tools: ${missing[*]}\n Install with: ${DIM}brew install ${missing[*]}${NC}"
- fi
-}
-
-# ════════════════════════════════════════════════════════════════════
-# 2. Clone into working directory
-# ════════════════════════════════════════════════════════════════════
-
-setup_workdir() {
- step "Working Directory"
-
- WORKDIR=$(mktemp -d)
- info "Created ${DIM}$WORKDIR${NC}"
-
- info "Cloning atuinsh/atuin..."
- git clone --quiet git@github.com:atuinsh/atuin.git "$WORKDIR"
- cd "$WORKDIR"
- success "Repository cloned"
-}
-
-# ════════════════════════════════════════════════════════════════════
-# 3. Version
-# ════════════════════════════════════════════════════════════════════
-
-detect_current_version() {
- sed -n '/^\[workspace\.package\]/,/^\[/s/^version = "\(.*\)"/\1/p' Cargo.toml
-}
-
-get_version() {
- step "Version"
-
- CURRENT_VERSION=$(detect_current_version)
- info "Current version: ${BOLD}$CURRENT_VERSION${NC}"
-
- # Suggest the next version based on conventional commits
- local suggested
- suggested=$(git-cliff --bumped-version 2>/dev/null | sed 's/^v//' || true)
- if [[ -n "$suggested" && "$suggested" != "$CURRENT_VERSION" ]]; then
- info "Suggested next: ${BOLD}$suggested${NC} ${DIM}(based on conventional commits)${NC}"
- fi
-
- echo ""
-
- if [[ -n "${NEW_VERSION:-}" ]]; then
- info "Using version from environment: ${BOLD}$NEW_VERSION${NC}"
- else
- echo -en " ${CYAN}▸${NC} New version ${DIM}(without 'v' prefix)${NC}: "
- read -r NEW_VERSION
- fi
-
- [[ -n "$NEW_VERSION" ]] || die "Version cannot be empty"
-
- IS_PRERELEASE=false
- if [[ "$NEW_VERSION" == *-* ]]; then
- IS_PRERELEASE=true
- warn "Pre-release detected"
- fi
-
- echo ""
- info "${BOLD}$CURRENT_VERSION${NC} → ${BOLD}$NEW_VERSION${NC}"
- echo ""
- confirm "Proceed with release?" || { info "Aborted."; exit 0; }
-}
-
-# ════════════════════════════════════════════════════════════════════
-# 4. Update version numbers
-# ════════════════════════════════════════════════════════════════════
-
-update_versions() {
- step "Updating Versions"
-
- info "Creating release branch: ${BOLD}$NEW_VERSION${NC}"
- git checkout -b "$NEW_VERSION" --quiet
-
- local version_pattern="${CURRENT_VERSION//./\\.}"
-
- info "Replacing ${DIM}$CURRENT_VERSION${NC} → ${DIM}$NEW_VERSION${NC} in Cargo.toml files..."
- find . -type f -name 'Cargo.toml' -not -path './.git/*' \
- -exec gsed -i "s/$version_pattern/$NEW_VERSION/g" {} \;
-
- info "Running ${DIM}cargo check${NC} to update Cargo.lock (this may take a moment)..."
- cargo check --quiet 2>&1 || cargo check
-
- echo ""
- info "Changed files:"
- git diff --stat | sed 's/^/ /'
-
- echo ""
-
- # Verify the workspace version was updated
- local new_ws_version
- new_ws_version=$(detect_current_version)
- if [[ "$new_ws_version" == "$NEW_VERSION" ]]; then
- success "Workspace version updated"
- else
- die "Workspace version is '$new_ws_version', expected '$NEW_VERSION'"
- fi
-
- # Verify we didn't break anything unexpected — show version-related
- # lines in the diff for review
- echo ""
- info "Version changes in diff:"
- git diff --unified=0 -- '*.toml' \
- | grep -E '^\+.*version' \
- | grep -v '^\+\+\+' \
- | sed 's/^/ /' || true
- echo ""
-
- confirm "Version changes look correct?" || { die "Aborting — fix versions manually in $WORKDIR"; }
-}
-
-# ════════════════════════════════════════════════════════════════════
-# 5. Changelog
-# ════════════════════════════════════════════════════════════════════
-
-update_changelog() {
- step "Changelog"
-
- # cliff.toml's ignore_tags already ignores beta/alpha tags, so
- # --unreleased always gives us everything since the last stable release.
- #
- # Prereleases: heading is ## [unreleased] (running tally)
- # Stable: heading is ## X.Y.Z (versioned entry)
- local cliff_args=(--unreleased --strip all)
-
- if $IS_PRERELEASE; then
- info "Updating ${BOLD}Unreleased${NC} section..."
- else
- cliff_args+=(--tag "v$NEW_VERSION")
- info "Generating changelog for ${BOLD}$NEW_VERSION${NC}..."
- fi
-
- local new_entry
- new_entry=$(git-cliff "${cliff_args[@]}" 2>/dev/null || true)
-
- # Check if the entry is empty (just a heading with no content)
- if [[ -z "$new_entry" ]] || [[ "$(echo "$new_entry" | grep -c '[a-zA-Z]')" -le 1 ]]; then
- warn "No unreleased changes detected by git-cliff"
- warn "You may want to add entries manually in the editor"
- if $IS_PRERELEASE; then
- new_entry="## [unreleased]"
- else
- new_entry="## $NEW_VERSION"
- fi
- else
- local commit_count
- commit_count=$(echo "$new_entry" | grep -c '^- ' || true)
- success "Generated entry with ${BOLD}$commit_count${NC} item(s)"
- fi
-
- # Remove any existing [unreleased] section — we'll replace it with
- # either an updated unreleased section or a versioned one
- if grep -qi '^\## \[unreleased\]' CHANGELOG.md; then
- info "Removing old Unreleased section..."
- awk '
- /^## \[[Uu]nreleased\]/ { skip=1; next }
- /^## / { skip=0 }
- !skip
- ' CHANGELOG.md > CHANGELOG.md.tmp
- mv CHANGELOG.md.tmp CHANGELOG.md
- fi
-
- # Insert the new entry before the first existing version heading
- local insert_line
- insert_line=$(grep -n '^## ' CHANGELOG.md | head -1 | cut -d: -f1)
-
- if [[ -n "$insert_line" ]]; then
- {
- head -n "$((insert_line - 1))" CHANGELOG.md
- echo "$new_entry"
- echo ""
- echo ""
- tail -n "+$insert_line" CHANGELOG.md
- } > CHANGELOG.md.tmp
- mv CHANGELOG.md.tmp CHANGELOG.md
- else
- warn "No existing version headings found — appending to end"
- echo "" >> CHANGELOG.md
- echo "$new_entry" >> CHANGELOG.md
- fi
-
- echo ""
- info "Opening CHANGELOG.md in your editor for review..."
- info "${DIM}Verify the entry, make any edits, then save and close.${NC}"
- echo ""
- echo -en " ${DIM}Press Enter to open editor...${NC}"
- read -r
- "${EDITOR:-${VISUAL:-vi}}" CHANGELOG.md
- success "Changelog finalized"
-}
-
-# ════════════════════════════════════════════════════════════════════
-# 6. Commit and push
-# ════════════════════════════════════════════════════════════════════
-
-commit_and_push() {
- step "Commit & Push"
-
- git add .
- git commit --quiet -m "chore(release): prepare for release $NEW_VERSION"
- success "Committed"
-
- info "Pushing branch..."
- git push --quiet --set-upstream origin "$(git branch --show-current)" 2>&1
- success "Pushed to origin/${BOLD}$NEW_VERSION${NC}"
-}
-
-# ════════════════════════════════════════════════════════════════════
-# 7. Pull request
-# ════════════════════════════════════════════════════════════════════
-
-extract_changelog_entry() {
- # Extract the changelog body (without the heading) for the entry we just wrote.
- # Prereleases use ## [unreleased], stable uses ## X.Y.Z
- local heading
- if $IS_PRERELEASE; then
- heading='## \[unreleased\]'
- else
- heading="## ${NEW_VERSION//./\\.}"
- fi
- awk "/^${heading}/{found=1; next} /^## /{if(found) exit} found" CHANGELOG.md
-}
-
-create_pr() {
- step "Pull Request"
-
- local changelog_body
- changelog_body=$(extract_changelog_entry)
-
- local pr_body
- pr_body="Release preparation for v${NEW_VERSION}."
- if [[ -n "$changelog_body" ]]; then
- pr_body="$(cat <<EOF
-Release preparation for v${NEW_VERSION}.
-
-## Changelog
-
-$changelog_body
-EOF
-)"
- fi
-
- info "Creating PR..."
- PR_URL=$(gh pr create \
- --title "chore(release): prepare for release $NEW_VERSION" \
- --body "$pr_body" \
- --repo atuinsh/atuin)
-
- success "PR created: ${BOLD}$PR_URL${NC}"
-
- local pr_number
- pr_number=$(echo "$PR_URL" | grep -o '[0-9]*$')
-
- echo ""
- info "Waiting for PR #${BOLD}$pr_number${NC} to be merged..."
- info "${DIM}Review and merge the PR — this script will detect it automatically.${NC}"
- echo ""
-
- while true; do
- local state
- state=$(gh pr view "$pr_number" --repo atuinsh/atuin --json state --jq '.state' 2>/dev/null || echo "UNKNOWN")
-
- case "$state" in
- MERGED)
- echo ""
- success "PR #$pr_number merged!"
- break
- ;;
- CLOSED)
- echo ""
- die "PR #$pr_number was closed without merging"
- ;;
- *)
- printf "\r ${DIM}⏳ PR #%s is %s — checking again in 5s...${NC} " "$pr_number" "$state"
- sleep 5
- ;;
- esac
- done
-}
-
-# ════════════════════════════════════════════════════════════════════
-# 8. Tag
-# ════════════════════════════════════════════════════════════════════
-
-tag_release() {
- step "Tag & Release"
-
- info "Switching to main and pulling..."
- git checkout main --quiet
- git pull --quiet
-
- info "Creating tag ${BOLD}v$NEW_VERSION${NC}"
- git tag "v$NEW_VERSION"
-
- info "Pushing tag..."
- git push --tags
- success "Tag ${BOLD}v$NEW_VERSION${NC} pushed — release workflow triggered"
-}
-
-# ════════════════════════════════════════════════════════════════════
-# 9. Publish to crates.io
-# ════════════════════════════════════════════════════════════════════
-
-publish_crates() {
- step "Publish to crates.io"
-
- if $IS_PRERELEASE; then
- warn "Pre-release — skipping crates.io publish"
- return
- fi
-
- if ! confirm "Publish to crates.io?"; then
- info "Skipping"
- return
- fi
-
- local crates=(
- atuin-common
- atuin-client
- atuin-ai
- atuin-dotfiles
- atuin-history
- atuin-nucleo/matcher
- atuin-nucleo
- atuin-daemon
- atuin-kv
- atuin-scripts
- atuin-server-database
- atuin-server-postgres
- atuin-server-sqlite
- atuin-server
- atuin-pty-proxy
- atuin
- )
-
- for crate in "${crates[@]}"; do
- info "Publishing ${BOLD}$crate${NC}..."
- local output
- # --no-verify: skip rebuild during publish — the code already passed
- # CI, and verification fails on workspace crates whose freshly-published
- # dependencies haven't been indexed by crates.io yet
- if output=$(cd "crates/$crate" && cargo publish --no-verify 2>&1); then
- success "$crate published"
- elif echo "$output" | grep -q "already uploaded"; then
- warn "$crate already published, skipping"
- else
- echo "$output" >&2
- die "Failed to publish $crate"
- fi
- done
-}
-
-# ════════════════════════════════════════════════════════════════════
-# Main
-# ════════════════════════════════════════════════════════════════════
-
-main() {
- banner
- check_deps
- setup_workdir
- get_version
- update_versions
- update_changelog
- commit_and_push
- create_pr
- tag_release
- publish_crates
-
- step "Done 🎉"
- success "Released ${BOLD}v$NEW_VERSION${NC}"
- echo ""
- info "Working directory: ${DIM}$WORKDIR${NC}"
- info "Clean up with: ${DIM}rm -rf $WORKDIR${NC}"
- echo ""
-}
-
-main "$@"
diff --git a/scripts/span-table.ts b/scripts/span-table.ts
deleted file mode 100755
index 3656f129..00000000
--- a/scripts/span-table.ts
+++ /dev/null
@@ -1,420 +0,0 @@
-#!/usr/bin/env bun
-/**
- * Analyze span timing JSON logs generated with ATUIN_SPAN
- *
- * Usage: bun scripts/span-table.ts <file.json> [options]
- * --filter <pattern> Only show spans matching pattern (regex)
- * --sort <field> Sort by: calls, avg, total, p99 (default: total)
- * --top <n> Show top N spans (default: 20)
- * --detail <span> Show individual calls for a specific span
- * --all Include internal/library spans
- */
-
-import { readFileSync } from "fs";
-
-interface SpanEvent {
- timestamp: string;
- level: string;
- fields: {
- message: string;
- "time.busy"?: string;
- "time.idle"?: string;
- };
- target: string;
- span?: {
- name: string;
- [key: string]: unknown;
- };
- spans?: Array<{ name: string; [key: string]: unknown }>;
-}
-
-interface SpanStats {
- name: string;
- calls: number;
- busyTimes: number[]; // in microseconds
- idleTimes: number[];
- parentCounts: Map<string, number>; // parent span name -> count
-}
-
-// Parse duration strings like "1.23ms", "456µs", "789ns" to microseconds
-function parseDuration(duration: string): number {
- const match = duration.match(/^([\d.]+)(ns|µs|us|ms|s)$/);
- if (!match) return 0;
-
- const value = parseFloat(match[1]);
- const unit = match[2];
-
- switch (unit) {
- case "ns":
- return value / 1000;
- case "µs":
- case "us":
- return value;
- case "ms":
- return value * 1000;
- case "s":
- return value * 1_000_000;
- default:
- return 0;
- }
-}
-
-// Format microseconds for display
-function formatDuration(us: number): string {
- if (us < 1) {
- return `${(us * 1000).toFixed(0)}ns`;
- } else if (us < 1000) {
- return `${us.toFixed(2)}µs`;
- } else if (us < 1_000_000) {
- return `${(us / 1000).toFixed(2)}ms`;
- } else {
- return `${(us / 1_000_000).toFixed(2)}s`;
- }
-}
-
-function percentile(arr: number[], p: number): number {
- if (arr.length === 0) return 0;
- const sorted = [...arr].sort((a, b) => a - b);
- const idx = Math.floor(sorted.length * p);
- return sorted[Math.min(idx, sorted.length - 1)];
-}
-
-function parseJsonLines(content: string): SpanEvent[] {
- const events: SpanEvent[] = [];
- for (const line of content.trim().split("\n")) {
- if (!line.trim()) continue;
- try {
- events.push(JSON.parse(line));
- } catch {
- // Skip malformed lines
- }
- }
- return events;
-}
-
-function main() {
- const args = process.argv.slice(2);
-
- // Parse arguments
- let filterPattern: RegExp | null = null;
- let sortField = "total";
- let topN = 20;
- let detailSpan: string | null = null;
- let showAll = false;
- const files: string[] = [];
-
- for (let i = 0; i < args.length; i++) {
- if (args[i] === "--filter" && args[i + 1]) {
- filterPattern = new RegExp(args[++i]);
- } else if (args[i] === "--sort" && args[i + 1]) {
- sortField = args[++i];
- } else if (args[i] === "--top" && args[i + 1]) {
- topN = parseInt(args[++i], 10);
- } else if (args[i] === "--detail" && args[i + 1]) {
- detailSpan = args[++i];
- } else if (args[i] === "--all") {
- showAll = true;
- } else if (!args[i].startsWith("-")) {
- files.push(args[i]);
- }
- }
-
- if (files.length === 0) {
- console.error("Usage: bun scripts/span-table.ts <file.json> [options]");
- console.error(" --filter <pattern> Only show spans matching pattern (regex)");
- console.error(" --sort <field> Sort by: calls, avg, total, p99 (default: total)");
- console.error(" --top <n> Show top N spans (default: 20)");
- console.error(" --detail <span> Show individual calls for a specific span");
- console.error(" --all Include internal/library spans");
- process.exit(1);
- }
-
- // Parse all files
- const allEvents: SpanEvent[] = [];
- for (const file of files) {
- const content = readFileSync(file, "utf-8");
- for (const event of parseJsonLines(content)) {
- allEvents.push(event);
- }
- }
-
- // Filter to close events and aggregate by span name
- const spans = new Map<string, SpanStats>();
-
- for (const event of allEvents) {
- if (event.fields?.message !== "close") continue;
- if (!event.span?.name) continue;
- if (!event.fields["time.busy"]) continue;
-
- const name = event.span.name;
-
- // Apply filter if specified
- if (filterPattern && !filterPattern.test(name)) continue;
-
- // Skip noisy internal spans unless explicitly requested
- if (
- !showAll &&
- !filterPattern &&
- !detailSpan &&
- (name.startsWith("FramedRead::") ||
- name.startsWith("FramedWrite::") ||
- name.startsWith("Prioritize::") ||
- name === "poll" ||
- name === "poll_ready" ||
- name === "Connection" ||
- name.startsWith("assign_") ||
- name.startsWith("reserve_") ||
- name.startsWith("try_") ||
- name.startsWith("send_") ||
- name.startsWith("pop_"))
- ) {
- continue;
- }
-
- if (!spans.has(name)) {
- spans.set(name, { name, calls: 0, busyTimes: [], idleTimes: [], parentCounts: new Map() });
- }
-
- const stats = spans.get(name)!;
- stats.calls++;
- stats.busyTimes.push(parseDuration(event.fields["time.busy"]));
- if (event.fields["time.idle"]) {
- stats.idleTimes.push(parseDuration(event.fields["time.idle"]));
- }
-
- // Track parent relationship (immediate parent is the last element in spans array)
- const parents = event.spans || [];
- const parentName = parents.length > 0 ? parents[parents.length - 1].name : "__root__";
- stats.parentCounts.set(parentName, (stats.parentCounts.get(parentName) || 0) + 1);
- }
-
- if (spans.size === 0) {
- console.error("No matching span close events found");
- process.exit(1);
- }
-
- // Detail mode: show individual calls for a specific span
- if (detailSpan) {
- const detailEvents: Array<{
- timestamp: string;
- busy: number;
- idle: number;
- fields: Record<string, unknown>;
- parents: string[];
- }> = [];
-
- for (const event of allEvents) {
- if (event.fields?.message !== "close") continue;
- if (event.span?.name !== detailSpan) continue;
- if (!event.fields["time.busy"]) continue;
-
- // Extract span fields (excluding name)
- const fields: Record<string, unknown> = {};
- if (event.span) {
- for (const [k, v] of Object.entries(event.span)) {
- if (k !== "name") fields[k] = v;
- }
- }
-
- // Get parent span names
- const parents = (event.spans || []).map((s) => s.name);
-
- detailEvents.push({
- timestamp: event.timestamp,
- busy: parseDuration(event.fields["time.busy"]),
- idle: event.fields["time.idle"] ? parseDuration(event.fields["time.idle"]) : 0,
- fields,
- parents,
- });
- }
-
- if (detailEvents.length === 0) {
- console.error(`No events found for span "${detailSpan}"`);
- process.exit(1);
- }
-
- console.log("");
- console.log(`Individual calls for: ${detailSpan}`);
- console.log("-".repeat(110));
- console.log(
- "#".padStart(4) +
- "Wall".padStart(12) +
- "Busy".padStart(12) +
- "Idle".padStart(12) +
- " Fields"
- );
- console.log("-".repeat(110));
-
- detailEvents.forEach((e, i) => {
- const fieldsStr = Object.keys(e.fields).length > 0
- ? JSON.stringify(e.fields)
- : "";
-
- console.log(
- (i + 1).toString().padStart(4) +
- formatDuration(e.busy + e.idle).padStart(12) +
- formatDuration(e.busy).padStart(12) +
- formatDuration(e.idle).padStart(12) +
- " " +
- fieldsStr
- );
- });
-
- // Summary stats
- const busyTimes = detailEvents.map((e) => e.busy);
- const wallTimes = detailEvents.map((e) => e.busy + e.idle);
- console.log("");
- console.log(
- `Summary: ${detailEvents.length} calls\n` +
- ` Wall: avg=${formatDuration(wallTimes.reduce((a, b) => a + b, 0) / wallTimes.length)}, ` +
- `min=${formatDuration(Math.min(...wallTimes))}, ` +
- `max=${formatDuration(Math.max(...wallTimes))}, ` +
- `p50=${formatDuration(percentile(wallTimes, 0.5))}, ` +
- `p99=${formatDuration(percentile(wallTimes, 0.99))}\n` +
- ` Busy: avg=${formatDuration(busyTimes.reduce((a, b) => a + b, 0) / busyTimes.length)}, ` +
- `min=${formatDuration(Math.min(...busyTimes))}, ` +
- `max=${formatDuration(Math.max(...busyTimes))}, ` +
- `p50=${formatDuration(percentile(busyTimes, 0.5))}, ` +
- `p99=${formatDuration(percentile(busyTimes, 0.99))}`
- );
- return;
- }
-
- // Calculate stats
- const results = [...spans.values()].map((s) => {
- // Calculate wall times (busy + idle) for each call
- const wallTimes = s.busyTimes.map((busy, i) => busy + (s.idleTimes[i] || 0));
-
- // Find most common parent
- let mostCommonParent = "__root__";
- let maxCount = 0;
- for (const [parent, count] of s.parentCounts) {
- if (count > maxCount) {
- maxCount = count;
- mostCommonParent = parent;
- }
- }
-
- return {
- name: s.name,
- calls: s.calls,
- total: s.busyTimes.reduce((a, b) => a + b, 0),
- avg: s.busyTimes.reduce((a, b) => a + b, 0) / s.calls,
- min: Math.min(...s.busyTimes),
- max: Math.max(...s.busyTimes),
- p50: percentile(s.busyTimes, 0.5),
- p99: percentile(s.busyTimes, 0.99),
- avgWall: wallTimes.reduce((a, b) => a + b, 0) / s.calls,
- p50Wall: percentile(wallTimes, 0.5),
- p99Wall: percentile(wallTimes, 0.99),
- parent: mostCommonParent,
- };
- });
-
- // Build tree structure
- const childrenOf = new Map<string, string[]>();
- childrenOf.set("__root__", []);
- for (const r of results) {
- if (!childrenOf.has(r.name)) {
- childrenOf.set(r.name, []);
- }
- if (!childrenOf.has(r.parent)) {
- childrenOf.set(r.parent, []);
- }
- childrenOf.get(r.parent)!.push(r.name);
- }
-
- // Sort children by the specified field
- const resultMap = new Map(results.map(r => [r.name, r]));
- const sortChildren = (children: string[]) => {
- children.sort((a, b) => {
- const ra = resultMap.get(a);
- const rb = resultMap.get(b);
- if (!ra || !rb) return 0;
- switch (sortField) {
- case "calls":
- return rb.calls - ra.calls;
- case "avg":
- return rb.avg - ra.avg;
- case "p99":
- return rb.p99 - ra.p99;
- case "total":
- default:
- return rb.total - ra.total;
- }
- });
- };
-
- // Traverse tree to build ordered display list with depths
- const displayResults: Array<{ result: typeof results[0]; depth: number }> = [];
- const visited = new Set<string>();
-
- function traverse(name: string, depth: number) {
- if (visited.has(name)) return;
- visited.add(name);
-
- const result = resultMap.get(name);
- if (result) {
- displayResults.push({ result, depth });
- }
-
- const children = childrenOf.get(name) || [];
- sortChildren(children);
- for (const child of children) {
- traverse(child, depth + 1);
- }
- }
-
- // Start from roots
- const roots = childrenOf.get("__root__") || [];
- sortChildren(roots);
- for (const root of roots) {
- traverse(root, 0);
- }
-
- // Add any orphaned spans (whose parent wasn't in our span list)
- for (const r of results) {
- if (!visited.has(r.name)) {
- displayResults.push({ result: r, depth: 0 });
- }
- }
-
- // Apply topN limit
- const limitedResults = displayResults.slice(0, topN);
-
- console.log("");
- console.log(
- "Span Name".padEnd(40) +
- "Calls".padStart(6) +
- "Avg(wall)".padStart(11) +
- "P50(wall)".padStart(11) +
- "P99(wall)".padStart(11) +
- "Avg(busy)".padStart(11) +
- "P50(busy)".padStart(11) +
- "P99(busy)".padStart(11)
- );
- console.log("-".repeat(112));
-
- for (const { result: r, depth } of limitedResults) {
- const indent = " ".repeat(depth);
- const maxNameLen = 38 - indent.length;
- const truncatedName = r.name.length > maxNameLen ? "..." + r.name.slice(-(maxNameLen - 3)) : r.name;
- const displayName = indent + truncatedName;
-
- console.log(
- displayName.padEnd(40) +
- r.calls.toString().padStart(6) +
- formatDuration(r.avgWall).padStart(11) +
- formatDuration(r.p50Wall).padStart(11) +
- formatDuration(r.p99Wall).padStart(11) +
- formatDuration(r.avg).padStart(11) +
- formatDuration(r.p50).padStart(11) +
- formatDuration(r.p99).padStart(11)
- );
- }
-
- console.log("");
- console.log(`Showing ${limitedResults.length} of ${results.length} spans (sorted by ${sortField})`);
-}
-
-main();