DEV Community

matias yoon
matias yoon

Posted on

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

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

터미널에서 작동하는 AI 에이전트는 개발자에게 실시간 코드 보조, 자동화, 문제 해결을 제공하는 강력한 도구입니다. 이 가이드에서는 실제 개발 환경에서 활용 가능한 터미널 AI 에이전트를 구축하는 방법을 단계별로 설명합니다.

1. CLI AI 에이전트 생태계 분석

현재 터미널 기반 AI 에이전트 시장은 다음과 같은 주요 플랫폼으로 구성되어 있습니다:

Aider

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

Continue.dev

# 설치
npm install -g continue
# 실행
continue start
Enter fullscreen mode Exit fullscreen mode

OpenCode

# 코드 검색 및 자동완성
pip install opencode
opencode --model gpt-4
Enter fullscreen mode Exit fullscreen mode

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

로컬 머신에서 작동하는 LLM API를 설정하여 데이터 보안과 속도 문제를 해결합니다.

# Ollama 설치 (1GB RAM 이상 권장)
curl -fsSL https://ollama.com/install.sh | sh

# 모델 다운로드
ollama pull llama3.2:1b

# API 서버 시작
ollama serve

# 테스트 요청
curl http://localhost:11434/api/generate \
  -d '{
    "model": "llama3.2:1b",
    "prompt": "Hello, how are you?",
    "stream": false
  }'
Enter fullscreen mode Exit fullscreen mode

3. Python CLI 에이전트 구축

다음은 간단한 Python CLI 에이전트 코드입니다:

# aider_agent.py
import os
import json
import subprocess
from openai import OpenAI
import argparse

class TerminalAgent:
    def __init__(self):
        # 로컬 API 사용
        self.client = OpenAI(
            base_url="http://localhost:11434/v1",
            api_key="ollama"
        )

    def get_context(self):
        """현재 디렉토리 정보 수집"""
        context = {
            "current_dir": os.getcwd(),
            "git_status": self.get_git_status(),
            "files": self.list_files()
        }
        return context

    def get_git_status(self):
        try:
            result = subprocess.run(['git', 'status', '--porcelain'], 
                                  capture_output=True, text=True)
            return result.stdout.strip()
        except:
            return "No git repository"

    def list_files(self):
        return [f for f in os.listdir('.') if not f.startswith('.')]

    def generate_code(self, prompt):
        """코드 생성"""
        context = self.get_context()
        full_prompt = f"""
        Context:
        Directory: {context['current_dir']}
        Git Status: {context['git_status']}

        Prompt: {prompt}
        """

        response = self.client.chat.completions.create(
            model="llama3.2:1b",
            messages=[
                {"role": "system", "content": "You are a helpful coding assistant that writes code in the terminal."},
                {"role": "user", "content": full_prompt}
            ],
            max_tokens=1000
        )

        return response.choices[0].message.content

def main():
    parser = argparse.ArgumentParser(description='Terminal AI Agent')
    parser.add_argument('prompt', nargs='*', help='Prompt for code generation')
    args = parser.parse_args()

    agent = TerminalAgent()

    if args.prompt:
        prompt = ' '.join(args.prompt)
        result = agent.generate_code(prompt)
        print(result)
    else:
        print("Usage: python aider_agent.py \"your prompt here\"")

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

실행 방법:

# 설치
pip install openai

# 사용
python aider_agent.py "Create a Python function to calculate Fibonacci numbers"
Enter fullscreen mode Exit fullscreen mode

4. tmux 통합

tmux를 활용하여 에이전트가 작업을 분리하고 관리할 수 있습니다:

# tmux 세션 생성
tmux new-session -s ai_agent -d

# 세션에 명령 실행
tmux send-keys -t ai_agent "python aider_agent.py 'create a web scraper'" Enter

# 세션 목록 확인
tmux ls

# 세션 연결
tmux attach -t ai_agent
Enter fullscreen mode Exit fullscreen mode

5. 커스텀 툴 개발

다음은 특정 기능을 위한 커스텀 툴입니다:

# tools.py
import subprocess
import os
import json
from typing import Dict, List

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

    def search_in_files(self, pattern: str, file_extensions: List[str] = None) -> List[Dict]:
        """파일 내에서 패턴 검색"""
        results = []
        if file_extensions is None:
            file_extensions = ['.py', '.js', '.ts', '.java', '.cpp']

        for root, dirs, files in os.walk(self.project_root):
            for file in files:
                if any(file.endswith(ext) for ext in file_extensions):
                    filepath = os.path.join(root, file)
                    try:
                        with open(filepath, 'r', encoding='utf-8') as f:
                            content = f.read()
                            if pattern in content:
                                lines = content.split('\n')
                                matching_lines = [
                                    i+1 for i, line in enumerate(lines) 
                                    if pattern in line
                                ]
                                results.append({
                                    'file': filepath,
                                    'lines': matching_lines,
                                    'context': self.get_context(content, matching_lines)
                                })
                    except Exception as e:
                        print(f"Error reading {filepath}: {e}")
        return results

    def get_context(self, content: str, lines: List[int], context_lines: int = 3) -> List[str]:
        """문맥 줄 반환"""
        lines_list = content.split('\n')
        context = []
        for line_num in lines:
            start = max(0, line_num - context_lines)
            end = min(len(lines_list), line_num + context_lines)
            context.extend(lines_list[start:end])
        return context

class GitTool:
    def __init__(self):
        pass

    def get_recent_commits(self, limit: int = 5) -> List[Dict]:
        """최근 커밋 정보 가져오기"""
        try:
            result = subprocess.run([
                'git', 'log', '--oneline', f'-{limit}'
            ], capture_output=True, text=True)

            commits = []
            for line in result.stdout.strip().split('\n'):
                if line:
                    parts = line.split(' ', 1)
                    commits.append({
                        'hash': parts[0],
                        'message': parts[1] if len(parts) > 1 else ''
                    })
            return commits
        except Exception as e:
            return []

# 사용 예제
search_tool = CodeSearchTool()
results = search_tool.search_in_files("def calculate")
print(json.dumps(results, indent=2))
Enter fullscreen mode Exit fullscreen mode

6. 컨텍스트 윈도우 관리

대규모 코드베이스의 컨텍스트 윈도우를 관리하기 위한 최적화:

# context_manager.py
import os
from typing import List, Dict

class ContextWindowManager:
    def __init__(self, max_tokens: int = 4000):
        self.max_tokens = max_tokens
        self.current_context = []

    def add_file_context(self, filepath: str, max_lines: int = 100) -> Dict:
        """파일 컨텍스트 추가"""
        try:
            with open(filepath, 'r') as f:
                lines = f.readlines()[:max_lines]
                return {
                    'file': filepath,
                    'content': ''.join(lines),
                    'line_count': len(lines)
                }
        except Exception as e:
            return {'file': filepath, 'error': str(e)}

    def get_optimized_context(self, files: List[str]) -> str:
        """최적화된 컨텍스트 생성"""
        context_parts = []
        total_tokens = 0

        for filepath in files:
            if os.path.exists(filepath):
                file_context = self.add_file_context(filepath)
                file_tokens = len(file_context['content']) // 4  # 예상 토큰 수

                if total_tokens + file_tokens > self.max_tokens:
                    break

                context_parts.append(f"File: {filepath}\n{file_context['content']}")
                total_tokens += file_tokens

        return '\n\n'.join(context_parts)

# 사용 예제
manager = ContextWindowManager(2000)
context = manager.get_optimized_context(['main.py', 'utils.py'])
Enter fullscreen mode Exit fullscreen mode

7. 비용 및 속도 최적화

로컬 vs API 모델 사용 최적화:


python
# model_optimizer.py
import subprocess
import time
from enum import Enum

class ModelType(Enum):
    LOCAL = "local"
    API = "api"

class ModelOptimizer:
    def __init__(self):
        self.models = {


---

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

Top comments (0)