Skip to content

Latest commit

 

History

16 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ET — Extraordinary Terminal

An AI that lives in your terminal.

ET is a Linux-first AI terminal assistant. It helps you understand, write, debug and execute shell commands using natural language — right where you already work.

ET is not a chatbot inside a terminal. It understands your shell, your filesystem, your commands and your environment, and it never blindly executes anything: every command is classified by an independent safety engine and must be confirmed before it runs.

et ❯ what is using port 8080?

╭─────── SAFE ────────╮
│                     │
│  ss -ltnp | grep :8080 │
│                     │
│  Shows which process listens on port 8080. │
╰─────────────────────╯

Run? [y/N] y

Features

  • Natural language → shell command — describe what you want, get a command with an explanation and a risk rating.
  • Explain modeet explain "sudo pacman -Syu".
  • Command execution with a safety layer — commands are classified safe / moderate / dangerous by deterministic rules, not by the AI. Dangerous commands require typing CONFIRM.
  • Error debugging — ask "why did that fail?" and ET analyzes the last command's exit code, stdout and stderr.
  • Local-first, API-ready — works offline with Ollama, or through any OpenAI-compatible API (OpenAI, Groq, Mistral, DeepSeek…), OpenRouter, or Google Gemini.
  • Persistent local history — every interaction is stored in SQLite.
  • Extensible tools — a tool registry ready for plugins, MCP and more.
  • et doctor — check your installation and environment.

Requirements

  • Python 3.12+
  • Linux (Arch Linux fully supported; most distros work)
  • Any one backend: a local Ollama server, an OpenRouter key, an OpenAI key (or any OpenAI-compatible API), or a Google Gemini key

Installation

# recommended — isolated install
pipx install et

# or from source
git clone https://github.com/you/et.git
cd et
pip install .

Development install

python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

Quick start

# interactive session
et

# one-shot question or command request
et "find files larger than 500MB"

# explain a command
et explain "git rebase -i HEAD~3"

# generate, confirm, then run
et run "list running docker containers"

# inspect your setup
et doctor

Interactive session

et ❯ find running docker containers

╭──── SAFE ────╮
│  docker ps   │
│  Lists currently running Docker containers. │
╰──────────────╯

Run? [y/N] y

CONTAINER ID   IMAGE    COMMAND   STATUS   PORTS   NAMES
…
  • Ctrl+C cancels a request.
  • Ctrl+D or exit leaves the session.
  • Type help for usage hints.

Configuration

ET reads ~/.config/et/config.toml. Run et config to see its location, or et config --open to edit it. A default file is created on first use:

[ai]
provider = "ollama"                 # ollama | openrouter | openai | gemini
ollama_host = "http://localhost:11434"
ollama_model = "qwen2.5-coder"
openrouter_model = "anthropic/claude-3.5-sonnet"
openai_base_url = "https://api.openai.com/v1"
openai_model = "gpt-4o-mini"
gemini_model = "gemini-2.0-flash"

[ui]
show_thinking = true
theme = "auto"
max_output_lines = 200

[safety]
auto_confirm_safe = false
require_typing_for_dangerous = true
confirm_word = "CONFIRM"

[history]
enabled = true
max_entries = 2000

default_shell = "/bin/zsh"          # optional; autodetected when empty
telemetry = false

API keys are never stored in the config file. Use environment variables (see .env.example):

# OpenRouter — one key for Claude, GPT, Gemini, Llama…
export OPENROUTER_API_KEY="sk-or-..."

# OpenAI / OpenAI-compatible — OpenAI, Groq, Mistral, DeepSeek, local vLLM…
export OPENAI_API_KEY="sk-..."
export OPENAI_BASE_URL="https://api.groq.com/openai/v1"   # optional
export OPENAI_MODEL="llama-3.3-70b-versatile"              # optional

# Google Gemini (native)
export GEMINI_API_KEY="AIza..."

Data locations

Purpose Path
Config ~/.config/et/config.toml
Data ~/.local/share/et/ (history in et.db)
Cache ~/.cache/et/

Ollama (local, offline)

# install & start
curl -fsSL https://ollama.com/install.sh | sh
ollama serve

# pull a coding model
ollama pull qwen2.5-coder
[ai]
provider = "ollama"
ollama_model = "qwen2.5-coder"

OpenRouter (cloud)

export OPENROUTER_API_KEY="sk-or-..."
[ai]
provider = "openrouter"
openrouter_model = "anthropic/claude-3.5-sonnet"

OpenRouter proxies models from many vendors behind one key.

OpenAI & OpenAI-compatible APIs

ET speaks the universal /chat/completions API, so it works with OpenAI, Groq, Mistral, DeepSeek, Together, and local servers (vLLM, llama.cpp, LM Studio) with no extra code:

export OPENAI_API_KEY="sk-..."
export OPENAI_BASE_URL="https://api.openai.com/v1"        # default: OpenAI
export OPENAI_MODEL="gpt-4o-mini"

Examples of OPENAI_BASE_URL:

Provider OPENAI_BASE_URL
OpenAI https://api.openai.com/v1 (default)
Groq https://api.groq.com/openai/v1
Mistral https://api.mistral.ai/v1
DeepSeek https://api.deepseek.com/v1
Together https://api.together.xyz/v1
local vLLM http://127.0.0.1:8000/v1
local LM Studio http://127.0.0.1:1234/v1

Local servers (localhost / 127.0.0.1) can run without an API key.

[ai]
provider = "openai"
openai_base_url = "https://api.groq.com/openai/v1"
openai_model = "llama-3.3-70b-versatile"

Google Gemini (native)

export GEMINI_API_KEY="AIza..."   # https://aistudio.google.com/apikey
[ai]
provider = "gemini"
gemini_model = "gemini-2.0-flash"

GOOGLE_API_KEY works as an alias for GEMINI_API_KEY. GEMINI_BASE_URL overrides the endpoint (useful for proxies or regional endpoints).

Safety model

ET never trusts the AI. The flow is:

  1. The AI proposes a command and a risk rating.
  2. The safety engine independently classifies the command using deterministic rules (rm -rf /, mkfs, dd, reboot, fork bombs…).
  3. The effective risk is the highest of the two.
  4. The user decides — nothing runs without approval.
  • safe commands are shown; confirmation still applies unless safety.auto_confirm_safe is enabled.
  • moderate commands ask Run? [y/N].
  • dangerous commands demand the literal word CONFIRM.

Unknown commands default to moderate, never safe. In non-interactive (piped) contexts, execution is always refused.

ET also sanitizes context: secrets like API keys, tokens, passwords and .env values are stripped before anything is sent to an AI provider.

Architecture

et/
├── cli.py            CLI entry (Typer) + default-command routing
├── cli_group.py      custom Typer group (free-form prompt + subcommands)
├── ai/               provider abstraction: Ollama, OpenAI-compatible,
│                     OpenRouter, Gemini
├── core/             agent, context, executor, permissions, session, doctor
├── memory/           SQLite history + short-term conversation buffer
├── tools/            tool registry: shell, filesystem, system
├── config/           pydantic models, TOML loading, XDG paths
└── ui/               Rich console, renderer, prompts
User prompt
    │
    ▼
 Agent ──► AI provider (Ollama / OpenRouter)
    │              │
    │              └── structured JSON {intent, command, explanation, risk}
    ▼
 Safety engine ────► independent classification (safe/moderate/dangerous)
    │
    ▼
 Renderer ──► confirm? ──► CommandExecutor ──► SQLite history

See docs/architecture.md for details and docs/development.md for contribution guidance.

Development

source .venv/bin/activate
pip install -e ".[dev]"

# run tests
pytest

# type-check (optional)
python -m pip install mypy && mypy src/et

Testing

pytest

The suite covers CLI routing, config loading and env overrides, risk classification, command execution, provider abstraction (via mock HTTP transports), system context sanitization, history, the tool registry and the end-to-end session flow. Tests never execute destructive commands.

Roadmap

  • Plugin system and MCP support
  • Git / Docker / Kubernetes integrations
  • SSH assistant and remote management
  • Terminal command autocomplete and shell integration
  • Semantic memory with local embeddings

Contributing

Contributions are welcome. Please:

  1. Open an issue for discussion before large changes.
  2. Keep commits small and focused.
  3. Run pytest before opening a PR.
  4. Follow the style of the existing code (type hints, docstrings, no global state, small functions).

License

MIT

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages