DEV Community

matias yoon
matias yoon

Posted on

터미널 AI 에이전트 구축 (v33)

터미널 AI 에이전트 구축 (v33)

개요

터미널에서 동작하는 AI 에이전트는 개발자에게 코드 생성, 분석, 리팩토링을 위한 실시간 도우미를 제공합니다. 이 가이드에서는 오픈소스 AI 에이전트를 구축하고 최적화하는 실전 방법을 소개합니다.

1. CLI AI 에이전트 생태계

현재 CLI AI 에이전트는 다음과 같은 주요 도구들로 구성되어 있습니다:

Aider

가장 인기 있는 오픈소스 도구로, 실시간 코드 수정을 지원합니다:

pip install aider
aider --help
aider --model llama3
Enter fullscreen mode Exit fullscreen mode

Continue.dev

VSCode 확장으로 시작했지만 CLI에서도 사용 가능:

npm install -g @continue/core
continue start
Enter fullscreen mode Exit fullscreen mode

OpenCode

특정 언어에 최적화된 에이전트:

pip install opencode-agent
opencode --language python
Enter fullscreen mode Exit fullscreen mode

사용자 정의 스크립트

다음과 같은 간단한 스크립트로 시작할 수 있습니다:

# aider-like script
import openai
import subprocess

def get_code_context(file_path):
    return subprocess.run(['git', 'show', f'HEAD:{file_path}'], 
                         capture_output=True, text=True)

def ai_assistant(prompt, context=""):
    client = openai.OpenAI(api_key="your-key")
    response = client.chat.completions.create(
        model="gpt-4",
        messages=[
            {"role": "system", "content": context},
            {"role": "user", "content": prompt}
        ]
    )
    return response.choices[0].message.content
Enter fullscreen mode Exit fullscreen mode

2. 로컬 LLM API 엔드포인트 설정

LocalAI 설치

# Docker로 설치
docker run -p 1234:1234 --name localai \
  -v /path/to/models:/models \
  localai/localai:latest

# 또는 직접 설치
git clone https://github.com/go-skynet/LocalAI
cd LocalAI
make build
./local-ai --models-path /models
Enter fullscreen mode Exit fullscreen mode

모델 다운로드

# Qwen 모델 다운로드
mkdir -p /models
curl -L -o /models/qwen-7b-chat.bin \
  https://huggingface.co/Qwen/Qwen-7B-Chat/resolve/main/qwen-7b-chat.bin

# LLaMA 모델 다운로드
wget -O /models/llama2-7b.gguf \
  https://huggingface.co/TheBloke/Llama-2-7B-GGUF/resolve/main/llama-2-7b.Q4_K_M.gguf
Enter fullscreen mode Exit fullscreen mode

API 테스트

# 로컬 API 테스트
curl -X POST http://localhost:1234/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen-7b-chat",
    "messages": [{"role": "user", "content": "Hello"}]
  }'
Enter fullscreen mode Exit fullscreen mode

3. 간단한 Python CLI 에이전트 구축

#!/usr/bin/env python3
# terminal_agent.py

import argparse
import json
import os
import subprocess
import sys
from typing import List, Dict, Any
import openai

class TerminalAgent:
    def __init__(self, model="qwen-7b-chat"):
        self.model = model
        self.client = openai.OpenAI(
            base_url="http://localhost:1234/v1/",
            api_key="localai"
        )

    def run_command(self, command: str) -> str:
        """터미널 명령어 실행"""
        try:
            result = subprocess.run(
                command, 
                shell=True, 
                capture_output=True, 
                text=True
            )
            return result.stdout + result.stderr
        except Exception as e:
            return f"Error: {str(e)}"

    def get_context(self, files: List[str]) -> str:
        """파일 컨텍스트 수집"""
        context = []
        for file_path in files:
            if os.path.exists(file_path):
                with open(file_path, 'r') as f:
                    content = f.read()
                    context.append(f"File: {file_path}\n{content}")
        return "\n\n".join(context)

    def execute_function_call(self, function_call: Dict[str, Any]) -> str:
        """함수 호출 실행"""
        name = function_call.get("name")
        arguments = function_call.get("arguments", {})

        if name == "run_command":
            return self.run_command(arguments.get("command", ""))
        elif name == "search_code":
            return self.search_code(arguments.get("pattern", ""))
        else:
            return f"Unknown function: {name}"

    def search_code(self, pattern: str) -> str:
        """코드 검색"""
        try:
            result = subprocess.run([
                "grep", "-r", pattern, ".", "--exclude-dir=.git"
            ], capture_output=True, text=True)
            return result.stdout
        except Exception as e:
            return f"Search error: {str(e)}"

    def chat(self, message: str, context_files: List[str] = None) -> str:
        """채팅 메시지 처리"""
        context = self.get_context(context_files) if context_files else ""

        try:
            response = self.client.chat.completions.create(
                model=self.model,
                messages=[
                    {"role": "system", "content": f"Context:\n{context}"},
                    {"role": "user", "content": message}
                ]
            )
            return response.choices[0].message.content
        except Exception as e:
            return f"AI Error: {str(e)}"

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--message", "-m", required=True)
    parser.add_argument("--files", "-f", nargs="*", default=[])
    parser.add_argument("--model", "-M", default="qwen-7b-chat")

    args = parser.parse_args()

    agent = TerminalAgent(model=args.model)
    result = agent.chat(args.message, args.files)
    print(result)

if __name__ == "__main__":
    main()
Enter fullscreen mode Exit fullscreen mode

사용 방법:

# 기본 사용
python terminal_agent.py -m "Write a Python function to reverse a string"

# 파일 컨텍스트 포함
python terminal_agent.py -m "Explain this function" -f "src/main.py"

# 사용자 정의 모델 사용
python terminal_agent.py -m "Optimize this code" -M "llama2-7b"
Enter fullscreen mode Exit fullscreen mode

4. tmux/터미널 멀티플렉서 통합

tmux 스크립트 생성

# ~/.tmux/ai-session.sh
#!/bin/bash
tmux new-session -d -s ai-agent
tmux split-window -h
tmux send-keys -t ai-agent:0 'python terminal_agent.py' Enter
tmux send-keys -t ai-agent:1 'watch -n 1 git status' Enter
tmux attach -t ai-agent
Enter fullscreen mode Exit fullscreen mode

tmux 키 바인딩 설정

# ~/.tmux.conf
bind-key C-a run-shell 'tmux new-session -d -s ai-agent'
bind-key C-b run-shell 'tmux send-keys -t ai-agent:0 "python terminal_agent.py" Enter'
Enter fullscreen mode Exit fullscreen mode

5. 사용자 정의 도구 개발

파일 검색 도구

# tools/file_search.py
import os
import subprocess
from typing import List

class FileSearchTool:
    @staticmethod
    def search_files(pattern: str, root_dir: str = ".") -> List[str]:
        """파일 검색"""
        try:
            result = subprocess.run([
                "find", root_dir, "-name", f"*{pattern}*"
            ], capture_output=True, text=True)
            return result.stdout.strip().split('\n')
        except Exception as e:
            return [f"Error: {str(e)}"]

    @staticmethod
    def search_in_files(pattern: str, file_extensions: List[str] = None) -> str:
        """파일 내부 검색"""
        if file_extensions:
            extensions = " -o ".join([f"-name '*.{ext}'" for ext in file_extensions])
            cmd = f"find . -type f \\( {extensions} \\) -exec grep -l '{pattern}' {{}} \\;"
        else:
            cmd = f"grep -r '{pattern}' ."

        try:
            result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
            return result.stdout
        except Exception as e:
            return f"Error: {str(e)}"
Enter fullscreen mode Exit fullscreen mode

Git 통합 도구


python
# tools/git_tool.py
import subprocess
import json

class GitTool:
    @staticmethod
    def get_staged_files() -> List[str]:
        """스테이징된 파일 목록"""
        try:
            result = subprocess.run(
                ['git', 'diff', '--cached', '--name-only'],


---

📥 **Get the full guide on Gumroad**: https://gumroad.com/l/auto ($5)
Enter fullscreen mode Exit fullscreen mode

Top comments (0)