Skip to main content

AI-terminal-app

A sleek, asynchronous, terminal-native AI assistant — engineered as a proper installable CLI tool, not just a script. Built with Textual, orchestrated by LangChain, routed through OpenRouter, and now voice-enabled end to end.


1. Project Overview

ai-terminal-app is a professionally packaged, terminal-based AI assistant that brings large language model conversations directly into your shell. Under the hood, it combines a fully asynchronous Textual TUI with a LangChain-orchestrated conversation layer, dispatching every prompt through the OpenRouter API to access a rotating catalog of free and premium models.

This isn't a one-off script wrapped in a shell file — it's a pip-installable Python package, built around pyproject.toml, that registers itself as a real command-line executable. Once installed, the assistant launches from anywhere on your system with a single word: ai-agent.

Key highlights:

  • Fully async architecture — the TUI never blocks, even mid-generation
  • Installable, packaged CLI tool (no more ./launch.sh or launch.bat)
  • Markdown-rendered responses directly in the terminal, with full conversation history preserved on screen
  • Dynamic model routing via OpenRouter's model slug system, filtered to text-chat-capable models only
  • Voice in, voice out — local Whisper transcription (F5) and spoken responses via edge-tts (F6)
  • Built-in agent tools (/shell, /read, /write, /fetch) for an optional Agent mode
  • Secure .env-based credential management, with a guided first-run setup screen if you skip it
  • Mouse + keyboard driven Textual interface

2. See it in Action

A quick walkthrough of ai-terminal-app: launching via ai-agent, streaming a Markdown-rendered response, and clearing memory with Ctrl + L.

ai-terminal-app v2.1 screenshot

Updated look at v2.1 — voice controls, Agent mode, and the refreshed input panel.


3. System Architecture

ai-terminal-app follows a modular, asynchronous, three-layer architecture. Each layer owns a single responsibility, communicates through async boundaries, and can be extended or swapped independently.

┌───────────────────────────────────────────┐
│            Presentation Layer               │
│            Textual TUI                      │
│  • Markdown rendering of AI responses        │
│  • Async @work tasks — zero UI blocking      │
│  • Mouse + keyboard driven navigation        │
│  • Voice I/O: STT input (F5), TTS output (F6)│
└───────────────────┬───────────────────────────┘
                    │ async event dispatch
┌───────────────────▼───────────────────────────┐
│            Orchestration Layer                 │
│            LangChain                            │
│  • In-memory conversation state management       │
│  • Prompt templating & chat history assembly       │
│  • Agent tool dispatch (/shell, /read, /write, /fetch) │
└───────────────────┬───────────────────────────┘
                    │ HTTPS requests
┌───────────────────▼───────────────────────────┐
│            Routing Layer                        │
│            OpenRouter API                        │
│  • Dynamic model slug resolution                   │
│  • Text-chat-only filtering (excludes TTS/image/   │
│    music generation models from the picker)          │
│  • Routes to free/premium LLM backends              │
└───────────────────────────────────────────────┘

🖥️ Presentation Layer — Textual

The UI is built entirely on Textual's reactive, async-first framework. AI responses are rendered as live Markdown (headings, code blocks, lists) rather than raw text, and the full conversation transcript is re-rendered on every turn so nothing gets overwritten. Every network-bound operation — most importantly, the call out to OpenRouter — runs inside a Textual @work worker task, keeping the interface fully interactive (scrolling, typing, mouse clicks) while a response streams in.

🧩 Orchestration Layer — LangChain

LangChain manages the conversational brain of the app: assembling prompt templates, maintaining in-memory chat history for the current session, and structuring the request payload sent downstream. In Agent mode, it also dispatches slash-command tool calls. This abstraction means swapping prompt strategies or memory backends later (see Roadmap) won't require touching the UI layer at all.

🌐 Routing Layer — OpenRouter

Rather than hardcoding a single model, requests are routed through OpenRouter using dynamic model slugs (e.g. switching between different free-tier models at runtime). The model list is filtered through _is_text_chat_model(), which checks architecture.output_modalities for "text" and applies a regex safety net to exclude non-chat families (lyria, veo, imagen, music, -tts, whisper, dall-e, stable-diffusion) — so the dropdown only ever shows models that can actually hold a conversation.


4. 📦 Dependencies

Package Purpose
textual Powers the asynchronous, mouse-and-keyboard-driven terminal UI
langchain Orchestrates prompts, chains, and conversational memory
langchain-core Core abstractions and primitives used throughout LangChain
langchain-openrouter Integration layer connecting LangChain to the OpenRouter API
python-dotenv Loads API credentials securely from a local .env file

Optional voice extras (pip install -e ".[voice]")

Package Purpose
faster-whisper Local speech-to-text transcription (F5)
sounddevice Microphone audio capture
numpy Audio buffer processing for STT
edge-tts Text-to-speech playback of AI responses (F6)

5. ⚙️ Modern Installation & Setup

This project has moved past shell/batch launch scripts. It's now a proper Python package defined by pyproject.toml, meaning it installs like any other CLI tool and registers a real executable on your system.

🚀 Fastest way — install from PyPI

If you just want to use the tool, skip everything below and run:

pip install multi-model-term-ai

or, for a true global install outside any virtual environment:

pipx install multi-model-term-ai

Either way, you still need an OpenRouter API key — on first launch, a setup screen opens automatically and walks you through getting one and pasting it in, so you don't need to touch a .env file by hand. Then launch with:

ai-agent

🛠️ Installing from source (for contributors / latest main)

Want to modify the code, or run the very latest unreleased changes? Install from source instead:

Step 1 — Clone the repository

git clone https://github.com/Devesh-tiw/Term-AI.git
cd Term-AI

Step 2 — Create and activate a virtual environment

🐧 Linux / macOS

python3 -m venv venv
source venv/bin/activate

🪟 Windows (PowerShell)

python -m venv venv
venv\Scripts\Activate.ps1

Step 3 — Configure your environment variables 🔐

Copy the provided example file and fill in your own OpenRouter API key:

cp .env.example .env       # Linux/macOS
copy .env.example .env     # Windows

Open .env and add your key:

OPENROUTER_API_KEY=your_api_key_here

⚠️ .env is git-ignored by default — never commit real credentials. python-dotenv loads this file automatically at runtime via load_dotenv().

Prefer not to edit .env by hand? You can skip this step entirely — if OPENROUTER_API_KEY isn't set when the app launches, a one-time setup screen opens automatically and walks you through getting a key and pasting it in, saving it to .env for you.

Step 4 — Install the package 📦

pip install -e .

The -e (editable) flag installs the project in development mode — pointing directly at your local source — while pip reads pyproject.toml to register the console entry point.

Want voice features too? Install with the optional voice extra, which pulls in faster-whisper, sounddevice, numpy, and edge-tts:

pip install -e ".[voice]"

ℹ️ On first launch, the Whisper model preloads in a background thread (on_mount) so the F5 voice key is ready immediately instead of stalling on first use.

Step 5 — Launch it from anywhere

Once installed, forget python ai_app.py or ./launch.sh entirely. The package registers a global command:

ai-agent

You can now run ai-agent from any directory, in any shell session, as long as your virtual environment is active.

(Optional) True global installation with pipx

If you'd like ai-agent available system-wide, outside of any virtual environment, use pipx:

pipx install .

pipx installs the package into its own isolated environment while still exposing the ai-agent command globally — giving you a real, standalone OS-level CLI tool.


6. ⌨️ Keybindings & Usage

Launch the assistant with ai-agent and start chatting immediately.

Key Action
Enter Submit your prompt to the AI
Ctrl + L Clear conversation memory
Ctrl + P Toggle the rich input panel (paste code, docs, images, or file paths)
Ctrl + Y Copy the last AI reply to your clipboard
Ctrl + C Quit the application
F5 Toggle voice recording — transcribes via local Whisper and sends automatically, no Enter needed
F6 Toggle text-to-speech — AI responses are spoken aloud via edge-tts
F7 Toggle Agent mode (enables the slash-command tools below)
🖱️ Mouse Scroll response history, click to focus input, and navigate the UI

Note: Agent mode toggling moved from Ctrl + A to F7 due to a terminal-emulator key conflict.

Responses stream in and render live as Markdown — code blocks, headings, and lists all display formatted, right in your terminal, with the full transcript preserved across turns.

🛠️ Agent Mode — Slash Commands

With Agent mode on (F7), the following tools are available directly from the input line:

Command Action
/shell <cmd> Run a shell command
/read <path> Read a file
/write <path> <text> Write a file
/fetch <url> Fetch a webpage as cleaned text

7. 🧾 What's New in v2.1

  • Fixed model loadingopenrouter_models.py now uses a relative-import-first, absolute-import-fallback pattern, resolving a silent failure that occurred under packaged execution.
  • Fixed chat memory not rendering — the transcript now accumulates in self.visible_transcript and re-renders in full each turn, instead of each reply overwriting the previous one.
  • Fixed voice "stuck transcribing" — the Whisper model now preloads at startup instead of lazy-loading on first F5 press, plus a 25s hard timeout with a clear error if transcription genuinely stalls.
  • Fixed non-chat models appearing in the picker — added _is_text_chat_model() plus a regex safety net to exclude music/image/TTS/whisper models (e.g. Lyria) that were slipping past the free-tier filter.
  • Voice now sends automatically — transcription is wired into a shared _submit_prompt() method, so speaking a prompt no longer requires an extra Enter press.
  • Added a guided first-run setup screen — if no API key is found on launch, a two-step wizard walks you through getting one from OpenRouter and saving it, instead of failing with a raw error.
  • Added one-key copyCtrl + Y copies the last AI reply straight to your clipboard.
  • Published to PyPI as multi-model-term-ai, so pip install multi-model-term-ai now works without cloning the repo.

8. 🛣️ Roadmap

ai-terminal-app is under active development. Planned upgrades include:

  • 💾 Permanent Database Memory — Replacing in-memory-only conversation state with a persistent SQLite + LangChain memory backend, so context and chat history survive across sessions and restarts.
  • 🖼️ Real Multimodal Image Support — Wiring image input properly into vision-capable models via proper multipart message construction, replacing the current placeholder that only embeds a base64-length note rather than the actual image content.

Contributions, issues, and feature requests are always welcome. 🌟


Developed by Devesh Tiwari
Amrita Vishwa Vidyapeetham

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

multi_model_term_ai-2.1.0.tar.gz (24.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

multi_model_term_ai-2.1.0-py3-none-any.whl (19.5 kB view details)

Uploaded Python 3

File details

Details for the file multi_model_term_ai-2.1.0.tar.gz.

File metadata

  • Download URL: multi_model_term_ai-2.1.0.tar.gz
  • Upload date:
  • Size: 24.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for multi_model_term_ai-2.1.0.tar.gz
Algorithm Hash digest
SHA256 7461f3069c7a7c5b5178d1c85e38bae229daa7c6ed4503919cfd6fa58b88f61a
MD5 ca597e746572d097452ab63823494c45
BLAKE2b-256 c1ca68046fb45cf06e2cad2ddcf9fee897dc0c52782a78d5d3a368f4d546f231

See more details on using hashes here.

Provenance

The following attestation bundles were made for multi_model_term_ai-2.1.0.tar.gz:

Publisher: publish.yaml on Devesh-tiw/Term-AI

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file multi_model_term_ai-2.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for multi_model_term_ai-2.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5c544e38bf0421e266896e0a4b69eaade92237f2c73406289293b27a8b0df569
MD5 1669ce405d919bc872ee600c6bbdcf09
BLAKE2b-256 b9fe87ad5328ea9ee230bc392b492780a38ad3612784470350c1ed141460c1d3

See more details on using hashes here.

Provenance

The following attestation bundles were made for multi_model_term_ai-2.1.0-py3-none-any.whl:

Publisher: publish.yaml on Devesh-tiw/Term-AI

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page