DEV Community

matias yoon
matias yoon

Posted on

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

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

터미널에서 AI를 활용한 개발 워크플로우는 점점 더 중요해지고 있습니다. 이 가이드는 로컬 AI 에이전트를 구축하여 터미널에서 직접 사용할 수 있도록 도와주는 실질적인 방법을 제공합니다.

1. CLI AI 에이전트 생태계

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

Aider: GitHub Copilot과 유사한 기능을 제공하는 오픈소스 도구

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

Continue.dev: VSCode 확장 프로그램에서 개발된 터미널 지원 도구

npm install -g continue
Enter fullscreen mode Exit fullscreen mode

OpenCode: 라이브러리 기반 접근 방식으로 기존 코드를 분석하는 도구

pip install opencode
Enter fullscreen mode Exit fullscreen mode

커스텀 스크립트: 직접 구축한 커스터마이징 가능한 솔루션

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

로컬 모델을 터미널에서 사용하려면 API 서버를 실행해야 합니다:

# LM Studio 설치
git clone https://github.com/lm-s Studio/lm-studio.git
cd lm-studio
npm install
npm run dev

# 또는 Ollama 사용
curl -fsSL https://ollama.com/install.sh | sh
ollama run llama3
Enter fullscreen mode Exit fullscreen mode

API 엔드포인트 확인:

curl -X POST http://localhost:11434/api/generate \
  -H "Content-Type: application/json" \
  -d '{
    "model": "llama3",
    "prompt": "Hello, how are you?",
    "stream": false
  }'
Enter fullscreen mode Exit fullscreen mode

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

다음은 기능 호출을 지원하는 간단한 CLI 에이전트입니다:

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

class TerminalAgent:
    def __init__(self, model: str = "llama3"):
        self.model = model
        self.client = openai.OpenAI(
            base_url="http://localhost:11434/v1",
            api_key="ollama"
        )

    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 call_function(self, func_name: str, args: Dict) -> str:
        """함수 호출"""
        if func_name == "run_command":
            return self.execute_command(args.get("command", ""))
        elif func_name == "list_files":
            return self.execute_command("ls -la")
        return "Function not found"

    def chat(self, message: str) -> str:
        """AI와 대화"""
        response = self.client.chat.completions.create(
            model=self.model,
            messages=[
                {"role": "user", "content": message}
            ],
            functions=[
                {
                    "name": "run_command",
                    "description": "터미널 명령어 실행",
                    "parameters": {
                        "type": "object",
                        "properties": {
                            "command": {"type": "string"}
                        },
                        "required": ["command"]
                    }
                },
                {
                    "name": "list_files",
                    "description": "현재 디렉토리 파일 목록 보기",
                    "parameters": {"type": "object", "properties": {}}
                }
            ]
        )
        return response.choices[0].message.content

# 사용 예시
if __name__ == "__main__":
    agent = TerminalAgent()
    while True:
        user_input = input("AI> ")
        if user_input.lower() in ['quit', 'exit']:
            break
        response = agent.chat(user_input)
        print(response)
Enter fullscreen mode Exit fullscreen mode

4. tmux와 통합

tmux를 사용하여 여러 세션을 관리하는 에이전트입니다:

# tmux 세션 생성
tmux new-session -d -s ai-agent

# 세션 내에서 명령어 실행
tmux send-keys -t ai-agent "python ai_agent.py" Enter

# 세션 정보 확인
tmux list-sessions
Enter fullscreen mode Exit fullscreen mode
# tmux_integration.py
import subprocess
import json

class TmuxAgent:
    def __init__(self, session_name: str = "ai-agent"):
        self.session_name = session_name

    def create_session(self):
        """새 tmux 세션 생성"""
        subprocess.run([
            "tmux", "new-session", "-d", "-s", self.session_name
        ])

    def run_in_session(self, command: str):
        """세션 내에서 명령어 실행"""
        subprocess.run([
            "tmux", "send-keys", "-t", self.session_name, command, "Enter"
        ])

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

# 사용 예시
tmux_agent = TmuxAgent("my-ai-session")
tmux_agent.create_session()
tmux_agent.run_in_session("ls -la")
Enter fullscreen mode Exit fullscreen mode

5. 커스텀 도구 개발

코드 검색과 Git 연동 기능을 포함한 커스텀 도구:

# custom_tools.py
import os
import subprocess
import re

class CustomTools:
    @staticmethod
    def search_code(pattern: str, directory: str = ".") -> List[Dict]:
        """코드 검색"""
        results = []
        for root, dirs, files in os.walk(directory):
            for file in files:
                if file.endswith(('.py', '.js', '.ts', '.java', '.cpp')):
                    filepath = os.path.join(root, file)
                    try:
                        with open(filepath, 'r', encoding='utf-8') as f:
                            content = f.read()
                            matches = re.finditer(pattern, content)
                            for match in matches:
                                results.append({
                                    'file': filepath,
                                    'line': content[:match.start()].count('\n') + 1,
                                    'context': content[max(0, match.start()-20):match.end()+20]
                                })
                    except Exception:
                        continue
        return results

    @staticmethod
    def git_status() -> str:
        """Git 상태 확인"""
        try:
            result = subprocess.run(['git', 'status', '--porcelain'], 
                                   capture_output=True, text=True)
            return result.stdout
        except Exception:
            return "Git repository not found"

    @staticmethod
    def git_diff() -> str:
        """Git 변경 내용"""
        try:
            result = subprocess.run(['git', 'diff'], 
                                   capture_output=True, text=True)
            return result.stdout
        except Exception:
            return "Git error"

# 사용 예시
tools = CustomTools()
search_results = tools.search_code(r"def.*main")
print(json.dumps(search_results, indent=2))
Enter fullscreen mode Exit fullscreen mode

6. 컨텍스트 윈도우 관리

대규모 코드베이스를 위한 컨텍스트 관리:


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

class ContextManager:
    def __init__(self, max_context_size: int = 20000):
        self.max_context_size = max_context_size
        self.context = []
        self.history = []

    def add_file(self, filepath: str) -> bool:
        """파일을 컨텍스트에 추가"""
        try:
            with open(filepath, 'r') as f:
                content = f.read()

            # 파일 크기 제한
            if len(content) > 5000:
                content = content[:5000] + "... [TRUNCATED]"

            file_info = {
                'path': filepath,
                'content': content,
                'size': len(content),
                'hash': hashlib.md5(content.encode()).hexdigest()
            }

            self.context.append(file_info)
            return True
        except Exception as e:
            print(f"Error reading {filepath}: {e}")
            return False

    def get_context_summary(self) -> str:
        """컨텍스트 요약"""
        total_size = sum(item['size'] for item in self.context)
        files = [item['path'] for item in self.context]

        summary = f"Context: {len(files)} files, {total_size} chars\n"
        summary += "Files: " + ", ".join(files[:5]) + ("..." if len(files) > 5 else "")
        return summary

    def trim_context(self) -> None:
        """컨텍스트 크기 조정"""
        total_size = sum(item['size'] for item in self.context)


---

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

Top comments (0)