Локальный AI-помощник для терминала на Python без зависимостей | AiManual
AiManual Logo Ai / Manual.
19 Фев 2026 Гайд

Терминальный амнезиак: 50 строк Python, которые заставят LLM вспоминать команды за вас

Создайте скрипт на 50 строк Python для перевода запросов на естественном языке в команды терминала. Без внешних зависимостей, с подтверждением выполнения.

Проблема, которая сводит с ума: забытые флаги и потерянные часы

Вы стоите перед терминалом. В голове - четкая задача: "распаковать архив tar.gz, посмотреть что внутри, удалить старые логи старше недели". Руки замирают над клавиатурой. tar -xzf? tar -xvzf? А как там смотреть содержимое без распаковки? tar -tzf? Или -tf? Гугл уже открыт в соседней вкладке. Снова.

Это не недостаток знаний. Это проклятие современного разработчика: слишком много команд, слишком много флагов, слишком много вариантов. Особенно когда дело доходит до одноразовых операций вроде конвертации видео, работы с сетью или анализа логов.

Статистика 2025 года от JetBrains показывает: разработчики тратят в среднем 17 минут в день на поиск забытых команд и синтаксиса. За год это 85 часов. Больше двух рабочих недель.

Решение: не запоминать, а описывать

Вместо того чтобы зубрить man-страницы, давайте заставим компьютер понимать нас на человеческом языке. Не "как сделать tar с прогресс-баром", а просто сказать: "распаковать архив project.tar.gz и показать прогресс".

Ключевая идея проста до безобразия: берем любой LLM-бэкенд (локальный через API или облачный), пишем к нему тонкую обертку на чистом Python, и получаем переводчика с человеческого на bash.

💡
Важный нюанс: мы НЕ даем AI выполнять команды напрямую. Всегда показываем предложенную команду и спрашиваем подтверждение. Без этого - прямой путь к rm -rf /* по ошибке.

Архитектура: минимализм как искусство

Весь скрипт укладывается в 50 строк потому что мы отрезаем все лишнее:

  • Нет веб-сервера
  • Нет баз данных
  • Нет сложных фреймворков
  • Нет даже argparse - используем sys.argv

Только три компонента:

  1. Клиент к LLM API (любому)
  2. Парсер запроса пользователя
  3. Интерактивный подтверждатель

Если вам интересны более сложные архитектуры с несколькими агентами и контекстами, посмотрите это руководство по фреймворкам для локальных агентов.

1 Выбираем LLM-бэкенд: локальный vs облачный

На февраль 2026 года у нас есть изобилие вариантов:

Тип Примеры Плюсы Минусы
Локальный Ollama (Llama 3.2), LM Studio, KoboldCpp Конфиденциальность, нет лимитов Требует ресурсов, настройки
Облачный API OpenAI GPT-4o, Anthropic Claude 3.5, Google Gemini 2.0 Простота, качество Стоимость, зависимость от интернета
Самодельный Запуск через локальные LLM с KoboldCpp Полный контроль Сложность настройки

Для нашего скрипта подойдет любой вариант с HTTP API. Я буду использовать локальную Ollama с моделью Llama 3.2 7B - она отлично справляется с генерацией команд и работает даже на ноутбуке.

2 Пишем костяк: 50 строк чистого Python

Вот полный скрипт. Разберем его по косточкам:

#!/usr/bin/env python3
"""
Terminal AI Assistant - переводчик с человеческого на bash
Использование: ./ai_assist.py "найти все файлы .log старше 7 дней и удалить"
"""

import sys
import json
import subprocess
from http.client import HTTPConnection
from urllib.parse import urlencode

def query_llama(prompt, api_url="localhost:11434"):
    """Запрос к локальной Ollama API"""
    conn = HTTPConnection(api_url)
    data = json.dumps({
        "model": "llama3.2",
        "prompt": f"""Ты - эксперт по Linux командам. 
Преобразуй запрос в одну команду bash.
Запрос: {prompt}
Команда: """,
        "stream": False,
        "options": {"temperature": 0.1}
    })
    
    conn.request("POST", "/api/generate", data, {"Content-Type": "application/json"})
    response = conn.getresponse()
    
    if response.status == 200:
        result = json.loads(response.read().decode())
        # Извлекаем только команду, убирая пояснения
        command = result["response"].strip()
        # Удаляем все после первого перевода строки
        if "\n" in command:
            command = command.split("\n")[0]
        return command
    else:
        print(f"Ошибка API: {response.status}")
        return None

def confirm_and_execute(command):
    """Показать команду и спросить подтверждение"""
    print(f"\nКоманда: {command}")
    print("Выполнить? (y/n): ", end="")
    
    try:
        choice = input().strip().lower()
    except KeyboardInterrupt:
        print("\nОтменено")
        return
    
    if choice == 'y':
        print("Выполняю...\n")
        try:
            result = subprocess.run(command, shell=True, check=True, text=True)
            print(f"Успешно. Код возврата: {result.returncode}")
        except subprocess.CalledProcessError as e:
            print(f"Ошибка выполнения: {e}")
    else:
        print("Отменено")

def main():
    if len(sys.argv) < 2:
        print("Использование: ai_assist.py 'ваш запрос на естественном языке'")
        sys.exit(1)
    
    user_query = " ".join(sys.argv[1:])
    print(f"Запрос: {user_query}")
    
    command = query_llama(user_query)
    if command:
        confirm_and_execute(command)

if __name__ == "__main__":
    main()

Что здесь важно:

  • Строки 14-35: HTTP клиент без внешних библиотек. Используем стандартные модули.
  • Строки 20-23: Промпт заточен под генерацию команд. Температура 0.1 для детерминированности.
  • Строки 30-33: Чистим ответ LLM. Модели любят добавлять пояснения.
  • Строки 37-55: Защита от дурака. Всегда спрашиваем подтверждение.

НИКОГДА не убирайте confirm_and_execute! Я видел проекты, где AI сразу выполнял команды. В одном случае это закончилось удалением продакшн-базы. В другом - отправкой тестовых писем реальным клиентам.

3 Настройка и первые тесты

Сначала запускаем Ollama (если используем локальную модель):

# Устанавливаем Ollama если еще нет
curl -fsSL https://ollama.ai/install.sh | sh

# Скачиваем модель (на февраль 2026 актуальна llama3.2)
ollama pull llama3.2

# Запускаем сервер в фоне
ollama serve &

Делаем скрипт исполняемым и тестируем:

chmod +x ai_assist.py

# Простой тест
./ai_assist.py "показать текущую директорию"
# Должен предложить: pwd

# Более сложный
./ai_assist.py "найти все Python файлы измененные сегодня"
# Должен предложить: find . -name \"*.py\" -mtime 0

Почему это работает лучше гугла?

Потому что контекст. Когда вы гуглите "как удалить старые логи", вы получаете общий ответ. Когда вы говорите AI "удали логи nginx старше 30 дней из /var/log", он генерирует конкретную команду для вашего случая.

Пример из реальной жизни:

./ai_assist.py \
  "создать резервную копию базы данных postgres 'myapp', \
   сжать gzip, положить в /backups с именем включающим дату"

AI сгенерирует что-то вроде:

pg_dump myapp | gzip > /backups/myapp_$(date +%Y%m%d_%H%M%S).sql.gz

Попробуйте получить такой конкретный ответ из StackOverflow за 10 секунд.

Расширяем функциональность: три полезных улучшения

1. Кэширование частых запросов

Добавляем простой файловый кэш:

import hashlib
import os

CACHE_FILE = os.path.expanduser("~/.ai_assist_cache.json")

def get_cache_key(query):
    return hashlib.md5(query.encode()).hexdigest()

def get_cached_command(query):
    if not os.path.exists(CACHE_FILE):
        return None
    with open(CACHE_FILE, 'r') as f:
        cache = json.load(f)
    return cache.get(get_cache_key(query))

def cache_command(query, command):
    cache = {}
    if os.path.exists(CACHE_FILE):
        with open(CACHE_FILE, 'r') as f:
            cache = json.load(f)
    cache[get_cache_key(query)] = command
    with open(CACHE_FILE, 'w') as f:
        json.dump(cache, f)

2. Поддержка разных LLM провайдеров

Модифицируем query_llama в query_ai:

def query_ai(prompt, provider="ollama"):
    if provider == "ollama":
        return query_ollama(prompt)
    elif provider == "openai":
        return query_openai(prompt)
    elif provider == "claude":
        return query_claude(prompt)
    # ...

3. История браузера как контекст

Самое интересное улучшение. Если вы недавно гуглили что-то связанное с командой, AI может использовать это как контекст.

Для Chrome на Linux история хранится в ~/.config/google-chrome/Default/History. Читаем последние 10 запросов:

import sqlite3
import time

def get_chrome_history():
    history_path = os.path.expanduser(
        "~/.config/google-chrome/Default/History"
    )
    if not os.path.exists(history_path):
        return []
    
    # Копируем файл, потому что Chrome его блокирует
    temp_path = "/tmp/chrome_history_temp"
    subprocess.run(["cp", history_path, temp_path])
    
    conn = sqlite3.connect(temp_path)
    cursor = conn.cursor()
    
    # Ищем поисковые запросы (обычно в urls.title)
    cursor.execute("""
        SELECT title FROM urls 
        WHERE title LIKE '%google%search%' OR title LIKE '%how%to%'
        ORDER BY last_visit_time DESC 
        LIMIT 10
    """)
    
    results = [row[0] for row in cursor.fetchall()]
    conn.close()
    os.remove(temp_path)
    
    return results

Теперь в промпт можно добавить: "Пользователь недавно искал в Google: [история]. Учти это при генерации команды."

💡
Этот прием с историей браузера - палка о двух концах. С одной стороны, AI лучше понимает контекст. С другой - вы делитесь своей историей с моделью. Для локальных моделей это безопасно, для облачных - проверяйте политики конфиденциальности.

Ошибки, которые все совершают (и как их избежать)

Ошибка Последствия Решение
Без подтверждения AI выполнит rm -rf /* если неправильно поймет Всегда confirm_and_execute
Слишком креативный промпт Модель генерирует поэмы вместо команд Температура 0.1, четкие инструкции
Нет обработки ошибок API Скрипт падает если модель недоступна try/except вокруг HTTP запросов
Игнорирование shell injection Уязвимость к атакам Не передавайте пользовательский ввод напрямую в shell

А что если хочется голосового ассистента?

Этот скрипт - отличная основа для более сложных систем. Добавьте голосовой ввод через AnyTTS для работы с буфером обмена или соберите полноценного локального Jarvis за вечер.

Но предупреждаю: как только вы попробуете говорить с терминалом, обратного пути не будет. Особенно если подключите Whisper для распознавания речи и Ollama для локальных моделей.

Финал: почему это изменит ваш workflow

Через неделю использования этого скрипта произойдет странное: вы перестанете бояться терминала. Вместо "ой, как там работает ffmpeg для конвертации видео" вы просто скажете: "конвертировать video.mov в mp4 с битрейтом 5M".

Это не замена знаниям. Это костыль для памяти. Как калькулятор для математика: вы все еще знаете таблицу умножения, но зачем напрягаться?

Самое ироничное: после месяца использования вы начнете запоминать команды, которые AI генерирует чаще всего. Потому что видите их каждый день. В итоге станете лучше знать терминал, используя костыль.

Парадокс? Да. Эффективно? Еще как.

P.S. Если соберетесь делать что-то более амбициозное, посмотрите предостережения о безопасности локальных AI-ассистентов. Или как построить AI-монстра со всем функционалом в одной коробке.

А теперь откройте терминал и скажите ему, что делать. Он поймет.