diff options
| author | Michelle Tilley <michelle@michelletilley.net> | 2026-02-24 11:48:20 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-02-24 11:48:20 -0800 |
| commit | 6ea760bb6b36da241961e8ecd60cb2c5e15c0a78 (patch) | |
| tree | 18ebbb710cea24e30bc69b5d6bc807518a950746 /crates/atuin-ai/test-renders.json | |
| parent | fix: forward $PATH to tmux popup in zsh (#3198) (diff) | |
| download | atuin-6ea760bb6b36da241961e8ecd60cb2c5e15c0a78.zip | |
feat: Generate commands or ask questions with `atuin ai` (#3199)
This PR refines the system created in #3178 to be suitable for a v1
release.
---
## Overview
`atuin-ai` is a separate binary that allows for generating commands and
asking questions from the command line.
It is fully opt-in.
## Usage
`atuin ai init` will output bindings for your shell. Currently, bash,
zsh, and fish are supported.
```bash
eval "$(atuin ai init)"
```
Once the hooks are installed, just press `?` on an empty prompt line to
call up the TUI.
`atuin ai` requires an account on [Atuin Hub](https://hub.atuin.sh/);
you will be prompted to log in on first use.
## Features
### Command generation
Prompt the LLM to create a command, and get one back, no fuss. Press
`enter` to run, or `tab` to insert.
```
┌Ask questions or generate a command:──────────────────────────┐
│ │
│ > Get a list of running docker containers │
│ │
├──────────────────────────────────────────────────────────────┤
│ │
│ $ docker ps │
│ │
└────[Enter]: Run [Tab]: Insert [f]: Follow-up [Esc]: Cancel┘
```
### Follow-up
You can follow-up with `f` to specify a refinement prompt to update the
command that will be inserted.
```
┌Ask questions or generate a command:──────────────────────────┐
│ │
│ > Get a list of running docker containers │
│ │
├──────────────────────────────────────────────────────────────┤
│ │
│ $ docker ps │
│ │
├──────────────────────────────────────────────────────────────┤
│ │
│ > Actually I want to get all docker containers │
│ │
├──────────────────────────────────────────────────────────────┤
│ │
│ $ docker ps -a │
│ │
└────[Enter]: Run [Tab]: Insert [f]: Follow-up [Esc]: Cancel┘
```
You can also follow-up with questions to get responses in natural
language.
```
┌Ask questions or generate a command:──────────────────────────┐
│ │
│ > Get a list of running docker containers │
│ │
├──────────────────────────────────────────────────────────────┤
│ │
│ $ docker ps │
│ │
├──────────────────────────────────────────────────────────────┤
│ │
│ > Actually I want to get all docker containers │
│ │
├──────────────────────────────────────────────────────────────┤
│ │
│ $ docker ps -a │
│ │
├──────────────────────────────────────────────────────────────┤
│ │
│ > What other useful flags to `docker ps` should I know? │
│ │
├──────────────────────────────────────────────────────────────┤
│ │
│ Here are some handy `docker ps` flags: │
│ │
│ - `-q` — Only show container IDs (great for piping to │
│ other commands) │
│ - `-s` — Show container sizes │
│ - `-n 5` — Show the last 5 created containers │
│ - `-l` — Show only the latest created container │
│ - `--no-trunc` — Don't truncate output (shows full IDs and │
│ commands) │
│ - `-f` or `--filter` — Filter by condition, e.g.: │
│ - `-f status=exited` — only exited containers │
│ - `-f name=myapp` — filter by name │
│ - `-f ancestor=nginx` — filter by image │
│ - `--format` — Custom output using Go templates, e.g.: │
│ `--format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"` │
│ │
│ A common combo is `docker ps -aq` to get all container │
│ IDs, useful for bulk operations like `docker rm $(docker │
│ ps -aq)`. │
│ │
└────[Enter]: Run [Tab]: Insert [f]: Follow-up [Esc]: Cancel┘
```
You can use `enter` or `tab` at any time to run or insert the last
suggested command, even if it was suggested in a previous turn.
### Conversational and search usage
If you prompt the LLM with a question that doesn't imply you want to
generate a command, it can respond in natural language, and use web
search if necessary to fetch the data it needs.
```
┌Ask questions or generate a command:──────────────────────────┐
│ │
│ > What is the latest version of atuin? │
│ │
├──────────────────────────────────────────────────────────────┤
│ │
│ ✓ Used 2 tools │
│ │
│ The latest version of Atuin is **v18.12.0**, available on │
│ the [GitHub releases │
│ page](https://github.com/atuinsh/atuin/releases). │
│ │
└─────────────────────────────────[f]: Follow-up [Esc]: Cancel┘
```
### Dangerous or low-confidence command detection
The LLM scores its confidence in the command, as well as how dangerous
the command is. This information is shown if a threshold is exceeded,
and requires an extra confirmation step before running automatically
with `enter`.
The Atuin Hub server also monitors suggested commands for dangerous
patterns the LLM didn't catch, and appends its own assessment at the end
of the LLM's own assessment.
```
┌Ask questions or generate a command:──────────────────────────┐
│ │
│ > Delete all files from $HOME │
│ │
├──────────────────────────────────────────────────────────────┤
│ │
│ $ rm -rf $HOME/* │
│ │
│ ! ⚠️ This will PERMANENTLY delete ALL files and directories │
│ in your home directory, including documents, downloads, │
│ configurations, SSH keys, and everything else. This is │
│ irreversible and will likely break your system. Also note │
│ this won't delete hidden (dot) files — if you want those │
│ too, that's even more destructive.; [Server] Recursive │
│ delete of critical directory │
│ │
└────[Enter]: Run [Tab]: Insert [f]: Follow-up [Esc]: Cancel┘
```
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'crates/atuin-ai/test-renders.json')
| -rw-r--r-- | crates/atuin-ai/test-renders.json | 295 |
1 files changed, 295 insertions, 0 deletions
diff --git a/crates/atuin-ai/test-renders.json b/crates/atuin-ai/test-renders.json new file mode 100644 index 00000000..31c180fa --- /dev/null +++ b/crates/atuin-ai/test-renders.json @@ -0,0 +1,295 @@ +[ + { + "name": "01_empty_input", + "description": "Initial state with empty input prompt", + "state": { + "events": [], + "mode": "Input", + "input": "", + "cursor_pos": 0 + } + }, + { + "name": "02_typing_input", + "description": "User typing in input field", + "state": { + "events": [], + "mode": "Input", + "input": "list all files", + "cursor_pos": 14 + } + }, + { + "name": "03_generating_spinner", + "description": "Waiting for API response (spinner)", + "state": { + "events": [ + {"type": "user_message", "content": "list all files"} + ], + "mode": "Generating", + "spinner_frame": 0 + } + }, + { + "name": "04_streaming_text", + "description": "Text streaming in from API", + "state": { + "events": [ + {"type": "user_message", "content": "what is rust?"} + ], + "mode": "Streaming", + "streaming_text": "Rust is a systems programming language focused on safety, speed, and", + "spinner_frame": 2 + } + }, + { + "name": "05_simple_command", + "description": "Simple command suggestion", + "state": { + "events": [ + {"type": "user_message", "content": "list all files"}, + {"type": "tool_call", "id": "1", "name": "suggest_command", "input": {"command": "ls -la"}} + ], + "mode": "Review" + } + }, + { + "name": "06_command_with_long_text", + "description": "Command that wraps to multiple lines", + "state": { + "events": [ + {"type": "user_message", "content": "find large files"}, + {"type": "tool_call", "id": "1", "name": "suggest_command", "input": {"command": "find /home -type f -size +100M -exec ls -lh {} \\; 2>/dev/null | sort -k5 -h"}} + ], + "mode": "Review" + } + }, + { + "name": "07_conversation_only_response", + "description": "Response without command (conversation mode)", + "state": { + "events": [ + {"type": "user_message", "content": "what does the -la flag do?"}, + {"type": "text", "content": "The `-la` flags combine two options:\n\n- `-l` shows long format with permissions, owner, size, and date\n- `-a` shows all files including hidden ones (starting with .)"} + ], + "mode": "Review" + } + }, + { + "name": "08_multi_turn_conversation", + "description": "Multiple turns of conversation", + "state": { + "events": [ + {"type": "user_message", "content": "list all files"}, + {"type": "tool_call", "id": "1", "name": "suggest_command", "input": {"command": "ls -la"}}, + {"type": "user_message", "content": "can you explain those flags?"}, + {"type": "text", "content": "The -l flag shows long format with permissions, -a shows hidden files."} + ], + "mode": "Review" + } + }, + { + "name": "09_tool_call_in_progress", + "description": "Tool being executed (spinner)", + "state": { + "events": [ + {"type": "user_message", "content": "what is the latest version of node?"}, + {"type": "tool_call", "id": "1", "name": "web_search", "input": {"query": "nodejs latest version"}} + ], + "mode": "Streaming", + "streaming_text": "", + "spinner_frame": 1 + } + }, + { + "name": "10_tool_calls_completed_with_text", + "description": "Tools finished, text streaming", + "state": { + "events": [ + {"type": "user_message", "content": "what is the latest version of node?"}, + {"type": "tool_call", "id": "1", "name": "web_search", "input": {"query": "nodejs latest version"}}, + {"type": "tool_result", "tool_use_id": "1", "content": "Node.js v22.0.0"} + ], + "mode": "Streaming", + "streaming_text": "The latest version of Node.js is v22.0.0, released in April 2024.", + "spinner_frame": 0 + } + }, + { + "name": "11_tool_calls_in_review", + "description": "Completed tools shown in review mode", + "state": { + "events": [ + {"type": "user_message", "content": "what is the latest version of node?"}, + {"type": "tool_call", "id": "1", "name": "web_search", "input": {"query": "nodejs latest version"}}, + {"type": "tool_result", "tool_use_id": "1", "content": "Node.js v22.0.0"}, + {"type": "tool_call", "id": "2", "name": "web_fetch", "input": {"url": "https://nodejs.org"}}, + {"type": "tool_result", "tool_use_id": "2", "content": "..."}, + {"type": "text", "content": "The latest version of Node.js is **v22.0.0**, released in April 2024. Key features include:\n\n- Native WebSocket client\n- Improved ES modules support\n- Better performance"} + ], + "mode": "Review" + } + }, + { + "name": "12_error_state", + "description": "Error message displayed", + "state": { + "events": [ + {"type": "user_message", "content": "do something"} + ], + "mode": "Error", + "error": "Failed to connect to API: connection timeout" + } + }, + { + "name": "13_dangerous_command", + "description": "Dangerous command with warning", + "state": { + "events": [ + {"type": "user_message", "content": "delete all files in home"}, + {"type": "tool_call", "id": "1", "name": "suggest_command", "input": { + "command": "rm -rf ~/*", + "dangerous": true, + "warning": "This will permanently delete all files in your home directory including documents, configurations, and SSH keys." + }} + ], + "mode": "Review", + "confirmation_pending": false + } + }, + { + "name": "14_dangerous_command_confirming", + "description": "Dangerous command awaiting second Enter", + "state": { + "events": [ + {"type": "user_message", "content": "delete all files in home"}, + {"type": "tool_call", "id": "1", "name": "suggest_command", "input": { + "command": "rm -rf ~/*", + "dangerous": true, + "warning": "This will permanently delete all files in your home directory." + }} + ], + "mode": "Review", + "confirmation_pending": true + } + }, + { + "name": "15_low_confidence", + "description": "Low confidence command with warning", + "state": { + "events": [ + {"type": "user_message", "content": "do that thing with the files"}, + {"type": "tool_call", "id": "1", "name": "suggest_command", "input": { + "command": "ls -la", + "confidence": "low", + "warning": "I'm not entirely sure what you mean by 'that thing'. This lists files - is that what you wanted?" + }} + ], + "mode": "Review" + } + }, + { + "name": "16_long_user_input", + "description": "User input that wraps", + "state": { + "events": [ + {"type": "user_message", "content": "I need a command that will find all JavaScript files in my project, excluding node_modules, and count the total lines of code"} + ], + "mode": "Generating", + "spinner_frame": 0 + } + }, + { + "name": "17_long_text_response", + "description": "Long text response that wraps multiple times", + "state": { + "events": [ + {"type": "user_message", "content": "explain git"}, + {"type": "text", "content": "Git is a distributed version control system created by Linus Torvalds in 2005. It tracks changes to files and enables collaboration between developers. Key concepts include:\n\n- **Repository**: A directory containing your project and its history\n- **Commit**: A snapshot of your changes with a message\n- **Branch**: An independent line of development\n- **Merge**: Combining changes from different branches\n- **Remote**: A version of your repository hosted elsewhere (like GitHub)"} + ], + "mode": "Review" + } + }, + { + "name": "18_streaming_with_tool_in_progress", + "description": "Tool in progress while streaming", + "state": { + "events": [ + {"type": "user_message", "content": "search for rust async patterns"}, + {"type": "text", "content": "Let me search for that..."}, + {"type": "tool_call", "id": "1", "name": "web_search", "input": {"query": "rust async patterns"}} + ], + "mode": "Streaming", + "streaming_text": "", + "spinner_frame": 2 + } + }, + { + "name": "19_multiple_commands_in_conversation", + "description": "Multiple command suggestions across turns", + "state": { + "events": [ + {"type": "user_message", "content": "create a new directory called test"}, + {"type": "tool_call", "id": "1", "name": "suggest_command", "input": {"command": "mkdir test"}}, + {"type": "user_message", "content": "now cd into it"}, + {"type": "tool_call", "id": "2", "name": "suggest_command", "input": {"command": "cd test"}}, + {"type": "user_message", "content": "create a file"}, + {"type": "tool_call", "id": "3", "name": "suggest_command", "input": {"command": "touch file.txt"}} + ], + "mode": "Review" + } + }, + { + "name": "20_empty_command_with_description", + "description": "Tool call with null command (conversation only)", + "state": { + "events": [ + {"type": "user_message", "content": "what's the weather like?"}, + {"type": "tool_call", "id": "1", "name": "suggest_command", "input": { + "command": null, + "description": "I can't check the weather directly, but you could use: curl wttr.in" + }} + ], + "mode": "Review" + } + }, + { + "name": "21_status_processing", + "description": "Streaming with Processing status", + "state": { + "events": [ + {"type": "user_message", "content": "analyze this code"} + ], + "mode": "Streaming", + "streaming_text": "", + "streaming_status": "Processing", + "spinner_frame": 0 + } + }, + { + "name": "22_status_thinking", + "description": "Streaming with Thinking status", + "state": { + "events": [ + {"type": "user_message", "content": "how do I optimize this query?"} + ], + "mode": "Streaming", + "streaming_text": "", + "streaming_status": "Thinking", + "spinner_frame": 1 + } + }, + { + "name": "23_follow_up_input", + "description": "Follow-up input after command", + "state": { + "events": [ + {"type": "user_message", "content": "list files"}, + {"type": "tool_call", "id": "1", "name": "suggest_command", "input": {"command": "ls -la"}} + ], + "mode": "Input", + "input": "but only show directories", + "cursor_pos": 24 + } + } +] |
