DEV Community

matias yoon
matias yoon

Posted on

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

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

개발자를 위한 터미널 AI 에이전트 구축 가이드

최근 몇 년 동안 개발자들은 로컬 AI 에이전트를 구축하여 코드 작업을 자동화하고 효율성을 높이는 데 집중하고 있습니다. 이 가이드에서는 실제 개발자가 사용할 수 있는 터미널 기반 AI 에이전트 구축 방법을 안내합니다.

1. CLI AI 에이전트 생태계

현재 터미널에서 작동하는 AI 에이전트는 다음과 같은 주요 플랫폼들로 구성되어 있습니다:

Aider

가장 인기 있는 CLI 기반 AI 에이전트입니다. Git 통합과 코드 변경 기능이 강력합니다.

# Aider 설치
pip install aider
aider --help

# 프로젝트에서 작업 시작
aider --yes --no-stream myproject/
Enter fullscreen mode Exit fullscreen mode

Continue.dev

VSCode 확장이지만 터미널에서도 작동하는 커스터마이징 가능한 에이전트입니다.

OpenCode

최근 등장한 터미널 기반 오픈소스 에이전트로, Python 기반 툴체인을 포함합니다.

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

로컬 모델을 터미널에서 사용하기 위해 API 엔드포인트를 설정해야 합니다.

Ollama를 통한 로컬 LLM 설정

# Ollama 설치 (Ubuntu/Debian)
curl -fsSL https://ollama.com/install.sh | sh

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

# API 서버 시작
ollama serve

# 백그라운드에서 실행
nohup ollama serve > /dev/null 2>&1 &
Enter fullscreen mode Exit fullscreen mode

FastAPI 기반 API 엔드포인트

# server.py
from fastapi import FastAPI
from pydantic import BaseModel
import ollama

app = FastAPI()

class ChatRequest(BaseModel):
    messages: list
    model: str = "llama3.2"

@app.post("/chat")
async def chat(request: ChatRequest):
    response = ollama.chat(
        model=request.model,
        messages=request.messages
    )
    return {"response": response["message"]["content"]}

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="127.0.0.1", port=8000)
Enter fullscreen mode Exit fullscreen mode
# 서버 실행
uvicorn server:app --host 127.0.0.1 --port 8000 --reload
Enter fullscreen mode Exit fullscreen mode

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

# aider_agent.py
import requests
import json
import sys
from typing import List, Dict
import subprocess

class TerminalAgent:
    def __init__(self, api_url="http://localhost:8000"):
        self.api_url = api_url
        self.system_prompt = """
        You are a helpful coding assistant that works in terminal environment.
        You can only use the provided tools and return valid JSON responses.
        Always be concise and practical.
        """

    def chat(self, message: str, history: List[Dict] = None) -> str:
        if history is None:
            history = []

        messages = [
            {"role": "system", "content": self.system_prompt}
        ] + history + [{"role": "user", "content": message}]

        try:
            response = requests.post(
                f"{self.api_url}/chat",
                json={"messages": messages},
                timeout=30
            )
            return response.json()["response"]
        except Exception as e:
            return f"Error: {str(e)}"

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

# 사용 예시
if __name__ == "__main__":
    agent = TerminalAgent()

    # 기본 대화
    response = agent.chat("Hello! What can you help me with?")
    print("Agent:", response)

    # 코드 생성 요청
    code_request = """
    Create a Python function that reads a JSON file and returns its contents.
    Include error handling for missing files.
    """
    response = agent.chat(code_request)
    print("Code:", response)
Enter fullscreen mode Exit fullscreen mode

4. tmux와의 통합

터미널 에이전트를 tmux 세션과 통합하여 작업 흐름을 자동화합니다.

# tmux 세션 생성 및 관리 스크립트
#!/bin/bash
# tmux_agent.sh

SESSION_NAME="ai_dev_session"
if tmux has-session -t $SESSION_NAME 2>/dev/null; then
    tmux attach -t $SESSION_NAME
else
    tmux new-session -d -s $SESSION_NAME

    # 터미널 분할
    tmux split-window -h
    tmux split-window -v

    # 에이전트 실행
    tmux send-keys -t $SESSION_NAME:0.0 "python aider_agent.py" Enter
    tmux send-keys -t $SESSION_NAME:0.1 "vim" Enter

    tmux attach -t $SESSION_NAME
fi
Enter fullscreen mode Exit fullscreen mode
# 실행 권한 부여
chmod +x tmux_agent.sh
./tmux_agent.sh
Enter fullscreen mode Exit fullscreen mode

5. 사용자 정의 도구 개발

코드 검색 도구

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

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

    def search_pattern(self, pattern: str, file_extensions: List[str] = None) -> List[str]:
        """코드 패턴 검색"""
        if file_extensions is None:
            file_extensions = ['.py', '.js', '.ts', '.java', '.cpp']

        cmd = [
            'find', self.project_root,
            '-type', 'f',
            '-name', f"*.*"
        ]

        # 확장자 필터
        if file_extensions:
            extensions = ' -o '.join([f"-name '*{ext}'" for ext in file_extensions])
            cmd[4] = f"({extensions})"

        try:
            result = subprocess.run(cmd, capture_output=True, text=True)
            files = result.stdout.strip().split('\n')
            return [f for f in files if f]
        except Exception as e:
            return []

    def grep_in_files(self, pattern: str, files: List[str]) -> List[str]:
        """특정 파일에서 패턴 검색"""
        results = []
        for file in files:
            try:
                cmd = ['grep', '-n', pattern, file]
                result = subprocess.run(cmd, capture_output=True, text=True)
                if result.stdout:
                    results.append({
                        'file': file,
                        'matches': result.stdout.strip().split('\n')
                    })
            except Exception:
                continue
        return results

# 사용 예시
search_tool = CodeSearchTool("./myproject")
files = search_tool.search_pattern("def initialize")
matches = search_tool.grep_in_files("config", files)
Enter fullscreen mode Exit fullscreen mode

Git 통합 도구

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

class GitTool:
    def __init__(self):
        self.repo_path = "."

    def get_status(self) -> Dict:
        """Git 상태 조회"""
        try:
            status = subprocess.run(
                ['git', 'status', '--porcelain'],
                capture_output=True, text=True, cwd=self.repo_path
            )
            return {"status": status.stdout.strip().split('\n')}
        except Exception as e:
            return {"error": str(e)}

    def get_commits(self, limit: int = 5) -> List[Dict]:
        """최근 커밋 목록"""
        try:
            cmd = [
                'git', 'log', '--oneline', f'-{limit}',
                '--format=%H|%an|%ae|%s'
            ]
            result = subprocess.run(cmd, capture_output=True, text=True)

            commits = []
            for line in result.stdout.strip().split('\n'):
                if line:
                    parts = line.split('|')
                    commits.append({
                        "hash": parts[0],
                        "author": parts[1],
                        "email": parts[2],
                        "message": parts[3]
                    })
            return commits
        except Exception as e:
            return [{"error": str(e)}]

# Git 도구 사용
git_tool = GitTool()
status = git_tool.get_status()
commits = git_tool.get_commits(3)
Enter fullscreen mode Exit fullscreen mode

6. 컨텍스트 윈도우 관리

대규모 코드베이스를 처리하기 위해 컨텍스트


📥 Get the full guide on Gumroad: https://gumroad.com/l/auto ($5)

Top comments (0)