Forgotten the exact form of that terminal command? No problem!
clai (clai) lets you describe what you want in natural language, then drafts the command for you to review.
If you forget to specify an important variable, such as a branch name, clai will prompt for it in a small wizard before showing the final command, which you are free to run, edit, or cancel.
Suggested commands are coloured with a simple 🟢 Green, 🟠 Amber, 🔴 Red traffic-light system so you get an immediate visual feel for their risk level.
clai is an AI-powered Bash terminal assistant. It uses modern LLM APIs to answer terminal questions, suggest commands, and support tool-based extensions through its local plugin system.
> clai is a hard fork of the original bash-ai project by @Hezkore, which itself was inspired by Your AI.
This fork exists because I intend to completely rewrite the project and prefer to have more immediate decision-making capability while doing that work.
> clai is intentionally a Bash-first project. It may be invoked from zsh and other shells, but the script itself is expected to run under Bash rather than natively under multiple shell interpreters.
This keeps the implementation and test surface narrower, and it lets the project stay focused on Bash compatibility, including older Bash versions such as the default Bash shipped on macOS.
End users do not need the test framework. bats and shellcheck are only needed for local development and CI.
On Ubuntu, install the development dependencies with:
sudo apt update
sudo apt install bats shellcheck jq curlRun all checks:
make checkRun only the shell linter:
make lintRun only the test suite:
make testThe Bats suite currently covers:
- first-run config bootstrap and private state creation
- installer download failure and overridden install-target success paths
- request payload generation and API transport / HTTP error handling
- history persistence, trimming, normalization, and deprecated config fallback behavior
- tool-call round trips, including the non-associative-array fallback path used for older Bash compatibility
- command suggestion accept, decline, and edit flows
- malformed response fallbacks, including truncated JSON, missing content, and malformed tool arguments
The suite stays deterministic and avoids making successful live API calls.
One PTY-backed edit-path test is enabled in CI and skipped locally unless CLAI_ENABLE_PTY_TESTS=true is set.
CLAI offers the following features:
-
100% Shell Script
No need to install anything. Just run it! -
Plugins!
Extend CLAI's functionality by adding plugins known as "tools". -
Natural Language Interface
Communicate with the terminal using everyday language. -
Question Answering
Get answers to all your terminal questions by ending your request with a question mark (but note special consideration for zsh users below) -
Command Suggestions
Receive intelligent command suggestions based on your input. -
Command Information
Get detailed information about the suggested commands. -
Distribution Awareness
Get answers and commands that are compatible with, and related to, your specific Linux distribution. -
Command Execution
Choose to execute the suggested commands directly from CLAI. -
Command Editing
Edit the suggested commands before execution. -
Error Examination
Examine the error messages generated by the suggested commands and attempt to fix them. -
Persistent Memory
Remembers your previous requests and uses them to improve future suggestions. -
Directory Awareness
Automatically detects and uses the current directory when executing commands. -
Locale Awareness
Automatically detects your system's locale and uses it to provide localized responses.
These are candidate product directions for CLAI after the current hardening and test coverage work. Each theme is tagged with a rough implementation priority, how well it fits CLAI's current product shape, and expected complexity.
| Theme | Priority | Fit | Complexity | Description |
|---|---|---|---|---|
| Built-in docs and help index | High | High | Low | Add a local, curated self-documentation layer for CLAI's own paths, config, tools, history, and troubleshooting so self-questions do not depend entirely on the model. |
| Repo-aware mode | High | High | Medium | Detect repository context such as current branch, changed files, project scripts, and likely test commands so CLAI can give project-aware answers instead of generic shell suggestions. |
| Approval policies | High | High | Medium | Let users define command safety rules such as auto-approve read-only commands, always confirm package installs, or always block destructive patterns. |
| Two-step risk classification | Medium | High | Medium | Split command generation from risk scoring so CLAI can first produce cmd and info, then run a second, narrower pass that rates the proposed command as none, reversible change, or danger zone using the user request, command, and described effect together. |
clai doctor diagnostics |
Medium | High | Medium | Add a built-in diagnostics command that checks common local problems such as missing dependencies, broken PATH entries, config mistakes, permission problems, and basic connectivity issues. |
| Command plan mode | Medium | Medium | Medium | For larger tasks, let CLAI propose a short plan of steps before suggesting or executing commands, so the user can approve the approach before any action is taken. |
| Session snapshots | Low | Medium | Medium | Save and restore named working contexts including conversation state, current directory, and relevant notes so users can resume project-specific sessions more deliberately. |
| Safer file edit workflow | Medium | High | High | Move beyond plain shell command suggestions for editing by supporting structured previews, diffs, patch application, and possibly an undo path for CLAI-driven edits. |
| Tool sandbox classes | Medium | High | High | Classify tools as read-only, local-write, networked, or dangerous and use that metadata in prompts, approval flow, and future policy controls. |
| Structured task workflows | Medium | Medium | High | Add reusable higher-level workflows for common tasks such as setting up a Python environment, triaging a failing test, or walking through a release checklist. |
| Command result learning | Low | Medium | High | Let users mark CLAI suggestions as correct, unsafe, or unhelpful and use that local feedback to steer future prompt context and approval behavior. |
- To setup CLAI quickly, you can run the following command:
curl -sS https://raw.githubusercontent.com/merefield/clai/main/install.sh | bashWarning
Never run unknown scripts without reviewing them for safety. Read the install script here.
- Run
claito start CLAI.
By default, the installer downloads the real script to /usr/local/lib/clai/clai.sh and exposes clai by creating a symlink in /usr/local/bin, which is typically already on your PATH.
On the first invocation without a configured key, CLAI starts a setup wizard and prompts for:
- API key
- API base URL
- model
The defaults are:
- API base URL:
https://api.openai.com/v1/chat/completions - model:
gpt-4.1
You can point CLAI at:
- OpenAI
- Anthropic
- Gemini / Google AI
- a local or self-hosted OpenAI-compatible endpoint by setting
api=andmodel=accordingly
You can re-run that setup wizard at any time with either:
clai setupor:
clai --setupManual Setup
-
Clone or download the repository:
git clone https://github.com/merefield/clai.git
-
Make the script executable:
chmod +x clai.sh
-
Execute CLAI directly:
./clai.sh
-
Expose
claion your command line. The recommended approach is to place a symlink in a directory that is already on yourPATH:-
System-wide default: symlink into
/usr/local/bin:ln -s path/to/clai.sh /usr/local/bin/clai
-
User-local alternative without
sudo: symlink into~/.local/binand ensure that directory is on yourPATH:mkdir -p ~/.local/bin ln -s path/to/clai.sh ~/.local/bin/clai
-
An alias is possible, but it is less universal than a symlink because it only applies to a specific shell configuration:
alias clai='path/to/clai.sh'
-
Unfortunately, zsh treats “?” and “*” as filename-globs.
If your question ends with a “?”, either:
– quote it (clai "how to list contents of a directory?") – or create an alias that disables globbing: alias clai='noglob clai'.
On the first run, a configuration file named clai.cfg will be created in your ~/.config directory.
CLAI will create ~/.config automatically if needed and will write clai.cfg with restrictive permissions.
Important
Always remove clai.cfg before updating CLAI to avoid compatibility issues.
If there is no configured key, CLAI will start the setup wizard automatically on invocation and prompt for the key, base URL, and model. You can also re-run that flow explicitly with clai setup or clai --setup.
You can still edit the file manually. The key= value should contain the credential for your configured provider. For local or self-hosted OpenAI-compatible endpoints, CLAI still expects key= to be non-empty, so use whatever token or placeholder value your endpoint accepts.
Caution
Keeping the key in a plain text file is dangerous, and it is your responsibility to keep it secure.
You can also change the model name, sampling temperature, base URL, and many other settings in this file.
The history retention setting is max_history_turns=. It controls how many user conversation turns CLAI persists across sessions.
| Key | Default | Purpose |
|---|---|---|
key |
empty | Credential for the configured provider. CLAI requires this to be non-empty before it will make requests. |
hi_contrast |
false |
Uses less muted info text output. |
expose_current_dir |
true |
Includes the current working directory in the runtime context sent to the model. |
max_history_turns |
10 |
Number of user conversation turns to persist across sessions. |
api |
https://api.openai.com/v1/chat/completions |
Chat Completions API endpoint. |
model |
gpt-4.1 |
Model name sent in the request payload. |
json_mode |
false |
Requests structured JSON output from the API. OpenAI, Anthropic, and Gemini use native JSON Schema-style structured outputs; unknown endpoints fall back to the existing OpenAI-compatible JSON object mode. |
temp |
0.1 |
Sampling temperature. Invalid values fall back to 0.1. |
tokens |
500 |
Maximum token count requested from the API. Invalid values fall back to 500. |
share_command_results |
false |
Shares structured command stdout, stderr, exit code, and edited state with later CLAI turns by storing it in history after execution. Enabling this can expose sensitive command output to later model context. |
result_lines |
20 |
Maximum number of stdout and stderr lines to keep per stored command result. Invalid values fall back to 20. |
confirm_dangerous_commands |
true |
Requires a second confirmation before executing commands marked as danger zone. |
exec_query |
empty | Optional extra system guidance for normal command-generation mode. |
question_query |
empty | Optional extra system guidance for question-answering mode. |
error_query |
empty | Optional extra system guidance for error-recovery mode. |
If exec_query, question_query, or error_query are left empty, CLAI uses its built-in defaults.
Provider notes:
- OpenAI-compatible and Anthropic endpoints send the configured
modeldirectly in the request body. - For Gemini endpoints, CLAI treats
modelas authoritative and rewrites the effective request URL to target that model, even if the configuredapiURL template contains a different model name. - Local or self-hosted OpenAI-compatible endpoints can be used by pointing
apiat the compatible base URL and setting the desiredmodel. - Local CLAI tool calls are currently only sent on OpenAI-compatible endpoints. Anthropic and Gemini still use native structured outputs for normal responses, but CLAI tells those models not to rely on tool calls.
When json_mode=true, CLAI asks the model to return structured cmd, info, risk, and variables fields. The risk value must be one of:
nonereversible changedanger zone
CLAI uses that risk value to color suggested commands in the terminal.
The variables field is an array of missing user-specified values that CLAI must collect before it can run the command. When a command is missing a value, the model returns {{variable_name}} placeholders in cmd and info, plus matching variables entries with a name and prompt. CLAI shell-escapes collected values before inserting them into cmd, and it refuses to run commands that still contain unresolved placeholders.
To toggle share_command_results directly from the CLI, run:
clai --toggle-results-sharingWhen you enable it, CLAI warns that shared command results may contain sensitive stdout/stderr, will be stored in history, and may be sent back to CLAI in later context.
To see whether command results are currently being shared, run:
clai --show-results-sharingTo view the currently persisted CLAI history in a readable form, run:
clai --show-historyBy default, stored command-result stdout and stderr are shown as compact previews containing the first 3 lines of each block.
For full stored stdout/stderr blocks in command results, use:
clai --show-history --verbosePersistent CLAI state, including conversation history, is stored under ${XDG_STATE_HOME:-~/.local/state}/clai/.
To clear persisted CLAI history explicitly, run:
clai --clear-historyThis clears CLAI's persisted history file under the CLAI state directory.
Transient request payloads, API responses, and tool logs are written to secure temporary files created with mktemp and are deleted automatically when the session exits.
API requests are built as structured JSON and CLAI distinguishes transport failures, HTTP errors, and successful JSON responses when reporting errors.
CLAI operates in two modes: Interactive Mode and Command Mode.
To enter Interactive Mode, you simply run clai without any request. This allows you to continuously interact with CLAI without needing to re-run the command.
In Command Mode, you run clai followed by your request, like so: clai your request here
Example usage:
clai create a new directory with a name of your choice, then create a text file inside it
You can also ask questions by ending your request with a question mark:
clai what is the current time?
For direct built-in history reset without going through the model, you can also run:
clai clear your historyWhen CLAI suggests a command, it shows the command and a short explanation, then prompts:
y: execute the suggested commande: edit the suggested command before executionNor Enter: cancel the command
In interactive mode, this lets you inspect or adjust the generated command before anything runs.
If the model marks any command inputs as missing in the structured variables field, CLAI prompts for those values first, substitutes them into the command and explanation, and only then shows the final command for confirmation.
You can think of this as a small variable wizard. For example, if CLAI suggests git checkout -b {{branch_name}}, it will first ask you for the branch name, substitute that value into the command, and only then ask whether to run it.
Suggested commands are color-coded by the model-reported risk field:
- green:
none - yellow:
reversible change - red:
danger zone
If confirm_dangerous_commands=true, danger-zone commands require an extra confirmation after the initial y:
- first prompt:
execute command? [y/e/N]: - second prompt for red commands:
danger zone command, are you sure? [y/N]:
If an executed command fails, CLAI shows the error and prompts:
y: ask CLAI to examine the error and suggest a fixNor Enter: stop there and return without further analysis
This uses CLAI's error mode, which sends the failed command and captured error text back through the model so it can propose a repair.
Plugins are local CLAI tools that expand CLAI's functionality, but they are not included in the default CLAI setup.
All tools should be placed in your ~/.clai_tools directory.
You can see which tools are currently installed by running clai, and CLAI will list them for you.
Local tool calling currently uses the OpenAI-compatible tool format. If you point CLAI at Anthropic or Gemini endpoints, CLAI will still use provider-native structured outputs for normal responses, but it will not send local tools in the request and will tell the model not to rely on tool calls.
Tools are nothing more than a shell script with a init and execute function.
You can find examples and available tools in the tools folder.
Feel free to move them to your ~/.clai_tools directory to enable them!
- In Command Mode, avoid using single quotes in your requests.
For instance, the commandclai what's the current time?will not work. However, bothclai "what's the current time?"andclai what is the current time?will execute successfully.
Please note that this issue is specific to the terminal, and does not occur in Interactive Mode.
- A configured non-empty
key=value accepted by one of:- OpenAI
- Anthropic
- Gemini / Google AI
- a local/self-hosted OpenAI-compatible endpoint
- curl
- jq