DEV Community

matias yoon
matias yoon

Posted on

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

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

터미널에서 AI를 활용한 개발 흐름을 구축하는 것은 현대 개발자에게 필수적인 기술입니다. 이 가이드에서는 실제 개발자들이 실제로 사용할 수 있는 터미널 AI 에이전트를 구축하는 방법을 단계별로 안내합니다.

1. CLI AI 에이전트 랜드스케이프

현재 터미널 AI 에이전트 시장은 다양합니다:

Aider: GitHub의 오픈소스 에이전트로, VS Code와 같은 IDE에서 사용할 수 있습니다. 하지만 명령줄에서 사용하기에는 제한적입니다.

Continue.dev: VS Code 확장 프로그램으로, 터미널에서 직접 작동하지 않습니다.

OpenCode: GitHub에서 제공하는 LLM 기반 코드 생성 도구로, API 기반 접근이 필요합니다.

커스텀 스크립트: 가장 유연한 접근 방식으로, 필요에 맞게 정확하게 커스터마이징 가능합니다.

# 현재 터미널에서 사용 가능한 대안들 확인
pip install aider
pip install openai
Enter fullscreen mode Exit fullscreen mode

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

로컬에서 LLM을 실행하여 빠르고 안전하게 작업을 수행하려면 로컬 API 서버를 설정해야 합니다.

# GGUF 모델 다운로드 및 실행
git clone https://github.com/ggerganov/llama.cpp.git
cd llama.cpp
make

# 모델 다운로드
wget https://huggingface.co/TheBloke/Mistral-7B-v0.1-GGUF/resolve/main/mistral-7b-v0.1.Q4_K_M.gguf

# 로컬 서버 실행
./server -m ./mistral-7b-v0.1.Q4_K_M.gguf -c 2048 --host 127.0.0.1 --port 8080
Enter fullscreen mode Exit fullscreen mode
# api_client.py - 로컬 API 클라이언트
import requests
import json

class LocalLLMClient:
    def __init__(self, base_url="http://127.0.0.1:8080"):
        self.base_url = base_url

    def generate(self, prompt, max_tokens=500):
        response = requests.post(
            f"{self.base_url}/completion",
            json={
                "prompt": prompt,
                "max_tokens": max_tokens,
                "temperature": 0.7
            }
        )
        return response.json()['content']

# 사용 예시
client = LocalLLMClient()
result = client.generate("Hello, world!")
Enter fullscreen mode Exit fullscreen mode

3. 함수 호출 기능이 있는 간단한 Python CLI 에이전트

# ai_agent.py
import subprocess
import json
import sys
from typing import Dict, Any

class TerminalAgent:
    def __init__(self):
        self.llm = LocalLLMClient()

    def execute_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 analyze_code(self, file_path: str) -> str:
        """코드 분석"""
        with open(file_path, 'r') as f:
            code = f.read()

        prompt = f"""
        Analyze the following code and provide:
        1. Code quality assessment
        2. Potential bugs or improvements
        3. Performance suggestions

        Code:
        {code}
        """

        return self.llm.generate(prompt, max_tokens=1000)

    def generate_test(self, file_path: str) -> str:
        """테스트 코드 생성"""
        with open(file_path, 'r') as f:
            code = f.read()

        prompt = f"""
        Generate unit tests for this code:
        {code}
        """

        return self.llm.generate(prompt, max_tokens=1000)

# CLI 사용법
if __name__ == "__main__":
    agent = TerminalAgent()

    if len(sys.argv) > 1:
        action = sys.argv[1]
        if action == "analyze":
            print(agent.analyze_code(sys.argv[2]))
        elif action == "test":
            print(agent.generate_test(sys.argv[2]))
Enter fullscreen mode Exit fullscreen mode

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

# tmux 세션 생성 및 스크립트 실행
tmux new-session -d -s ai_agent
tmux send-keys -t ai_agent 'python ai_agent.py' Enter
Enter fullscreen mode Exit fullscreen mode
# terminal_integration.py
import os
import subprocess
import json

class TerminalIntegration:
    def __init__(self):
        self.tmux_session = "ai_agent"

    def create_tmux_session(self):
        """tmux 세션 생성"""
        subprocess.run([
            'tmux', 'new-session', '-d', '-s', self.tmux_session
        ])

    def send_to_tmux(self, command: str):
        """tmux 세션에 명령어 전송"""
        subprocess.run([
            'tmux', 'send-keys', '-t', self.tmux_session, command, 'Enter'
        ])

    def get_tmux_output(self):
        """tmux 세션 출력 가져오기"""
        result = subprocess.run([
            'tmux', 'capture-pane', '-p', '-t', self.tmux_session
        ], capture_output=True, text=True)
        return result.stdout

# 사용 예시
integration = TerminalIntegration()
integration.create_tmux_session()
Enter fullscreen mode Exit fullscreen mode

5. 커스텀 도구 개발

# custom_tools.py
import os
import subprocess
from pathlib import Path

class CodeSearchTool:
    def __init__(self, project_root: str):
        self.project_root = Path(project_root)

    def find_files_by_extension(self, extension: str) -> list:
        """확장자별 파일 찾기"""
        files = list(self.project_root.rglob(f"*.{extension}"))
        return [str(f) for f in files]

    def search_in_files(self, pattern: str, file_extensions: list = None) -> dict:
        """파일 내에서 패턴 검색"""
        results = {}

        if file_extensions:
            files = []
            for ext in file_extensions:
                files.extend(self.project_root.rglob(f"*.{ext}"))
        else:
            files = self.project_root.rglob("*")

        for file_path in files:
            if file_path.is_file():
                try:
                    with open(file_path, 'r', encoding='utf-8') as f:
                        content = f.read()
                        if pattern in content:
                            results[str(file_path)] = self.extract_context(content, pattern)
                except Exception:
                    continue
        return results

    def extract_context(self, content: str, pattern: str, context_lines: int = 3) -> list:
        """패턴 주변의 문맥 추출"""
        lines = content.split('\n')
        matches = []

        for i, line in enumerate(lines):
            if pattern in line:
                start = max(0, i - context_lines)
                end = min(len(lines), i + context_lines + 1)
                matches.append({
                    'line_number': i + 1,
                    'context': lines[start:end]
                })
        return matches

# Git 통합 도구
class GitTool:
    def __init__(self):
        pass

    def get_changed_files(self) -> list:
        """변경된 파일 목록 가져오기"""
        result = subprocess.run(
            ['git', 'diff', '--name-only', 'HEAD~1', 'HEAD'],
            capture_output=True, text=True
        )
        return result.stdout.strip().split('\n') if result.stdout.strip() else []

    def get_git_log(self, limit: int = 5) -> str:
        """Git 로그 가져오기"""
        result = subprocess.run(
            ['git', 'log', f'-{limit}', '--oneline'],
            capture_output=True, text=True
        )
        return result.stdout
Enter fullscreen mode Exit fullscreen mode

6. 대용량 코드베이스를 위한 컨텍스트 창 관리


python
# context_manager.py
import hashlib
from typing import List, Dict

class ContextManager:
    def __init__(self, max_context_tokens: int = 4000):
        self.max_context_tokens = max_context_tokens
        self.context_cache = {}

    def add_file_context(self, file_path: str, content: str) -> str:
        """파일 컨텍스트 추가"""
        file_hash = hashlib.md5(file_path.encode()).hexdigest()
        self.context_cache[file_hash] = {
            'path': file_path,
            'content': content,
            'tokens': self.estimate_tokens(content)
        }
        return file_hash

    def get_context_window(self, file_hashes: List[str]) -> str:
        """컨텍스트 창 구성"""
        window_content = ""
        total

---

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

Top comments (0)