DEV Community

matias yoon
matias yoon

Posted on

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

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

터미널에서 작동하는 AI 에이전트로 개발 생산성을 높이는 방법을 실전 가이드로 안내드립니다. 이 가이드는 30불 이하의 가격으로 구입할 수 있는 실용적인 도구와 기술을 중심으로 구성되었습니다.

1. CLI AI 에이전트 생태계

현재 터미널 AI 에이전트 시장은 다양한 솔루션으로 구성되어 있습니다:

주요 도구 비교

Aider: Python 기반으로 개발된 코드 생성 도구

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

Continue.dev: VSCode 확장기반의 AI 코딩 도우미

# Continue는 VSCode 확장으로 설치
# 하지만 CLI 버전도 제공
npm install -g continue-cli
Enter fullscreen mode Exit fullscreen mode

OpenCode: 오픈소스 CLI 기반 AI 에이전트

git clone https://github.com/opencode/opencode-cli
cd opencode-cli && pip install -r requirements.txt
Enter fullscreen mode Exit fullscreen mode

사용자 정의 스크립트: 최소한의 기능을 가진 커스텀 에이전트

# 예제: 간단한 질문-응답 시스템
echo "function ai_query() { curl -s -X POST http://localhost:11434/api/generate -d '{\"model\":\"llama3\",\"prompt\":\"$1\"}' | jq -r '.response'; }" >> ~/.bashrc
Enter fullscreen mode Exit fullscreen mode

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

로컬 LLM을 사용하여 최대한의 성능과 비용 절감을 위해 Ollama를 사용합니다:

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

# 모델 다운로드
ollama pull llama3
ollama pull codellama:7b

# API 서버 실행 (기본 포트 11434)
ollama serve
Enter fullscreen mode Exit fullscreen mode

테스트를 위해 간단한 API 호출 수행:

curl -s http://localhost:11434/api/generate \
  -d '{
    "model": "llama3",
    "prompt": "Python으로 Fibonacci 수열을 구현해주세요.",
    "stream": false
  }' | jq -r '.response'
Enter fullscreen mode Exit fullscreen mode

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

다음은 기본적인 기능을 갖춘 CLI 에이전트입니다:

# ai_agent.py
#!/usr/bin/env python3
import os
import sys
import json
import subprocess
import requests
from typing import Dict, List, Optional

class TerminalAI:
    def __init__(self, model="llama3"):
        self.model = model
        self.base_url = "http://localhost:11434/api"

    def call_model(self, prompt: str, functions: Optional[List] = None) -> str:
        """LLM API 호출"""
        data = {
            "model": self.model,
            "prompt": prompt,
            "stream": False
        }

        if functions:
            data["functions"] = functions

        try:
            response = requests.post(f"{self.base_url}/generate", 
                                  json=data, timeout=30)
            response.raise_for_status()
            result = response.json()
            return result.get("response", "")
        except Exception as e:
            return f"Error: {str(e)}"

    def explain_code(self, code_file: str) -> str:
        """코드 설명 요청"""
        with open(code_file, 'r') as f:
            code = f.read()

        prompt = f"다음 코드를 설명해주세요:\n```
{% endraw %}
python\n{code}\n
{% raw %}
```"
        return self.call_model(prompt)

    def fix_bug(self, code_file: str, issue: str) -> str:
        """버그 수정 요청"""
        with open(code_file, 'r') as f:
            code = f.read()

        prompt = f"다음 코드의 문제점과 수정안을 제시해주세요:\n\n문제: {issue}\n\n코드:\n```
{% endraw %}
python\n{code}\n
{% raw %}
```"
        return self.call_model(prompt)

def main():
    if len(sys.argv) < 2:
        print("사용법: python ai_agent.py [explain|fix] [파일경로]")
        return

    agent = TerminalAI()

    if sys.argv[1] == "explain":
        result = agent.explain_code(sys.argv[2])
        print(result)

    elif sys.argv[1] == "fix":
        issue = " ".join(sys.argv[3:])
        result = agent.fix_bug(sys.argv[2], issue)
        print(result)

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

실행 방법:

chmod +x ai_agent.py
python ai_agent.py explain main.py
Enter fullscreen mode Exit fullscreen mode

4. tmux와 통합

터미널 창을 여러 개로 분할하여 효율적인 작업 환경을 구축합니다:

# tmux 세션 시작
tmux new-session -s ai-agent -d

# 세션 내에 창 분할 (하위창 생성)
tmux split-window -h -t ai-agent
tmux split-window -v -t ai-agent:0.0

# 각 창에 명령어 실행
tmux send-keys -t ai-agent:0.0 "watch -n 1 'git status'" Enter
tmux send-keys -t ai-agent:0.1 "python ai_agent.py explain main.py" Enter
tmux send-keys -t ai-agent:0.2 "vim main.py" Enter

# 세션 접속
tmux attach -t ai-agent
Enter fullscreen mode Exit fullscreen mode

5. 커스텀 도구 개발

코드 검색 도구

# code_search.py
import os
import subprocess
import re

class CodeSearcher:
    def __init__(self, project_path: str = "."):
        self.project_path = project_path

    def search_patterns(self, pattern: str, file_extensions: List[str] = None) -> List[str]:
        """정규표현식으로 코드 검색"""
        if file_extensions is None:
            file_extensions = ['.py', '.js', '.ts', '.go', '.rs']

        results = []
        cmd = ["find", self.project_path, "-type", "f"]
        cmd.extend(["-name", f"*.{file_extensions[0]}"])
        for ext in file_extensions[1:]:
            cmd.extend(["-o", "-name", f"*.{ext}"])

        try:
            files = subprocess.check_output(cmd, text=True).strip().split('\n')
            for file_path in files:
                if file_path.strip():
                    with open(file_path, 'r') as f:
                        content = f.read()
                        if re.search(pattern, content):
                            results.append(file_path)
        except Exception as e:
            print(f"Search error: {e}")

        return results

# 사용법
searcher = CodeSearcher()
results = searcher.search_patterns(r"def.*\(.*\):")
print("Found files:", results)
Enter fullscreen mode Exit fullscreen mode

Git 통합 도구

# git_tools.py
import subprocess
import json

class GitTools:
    @staticmethod
    def get_changed_files() -> List[str]:
        """변경된 파일 목록"""
        try:
            result = subprocess.run(
                ["git", "diff", "--name-only", "HEAD~1", "HEAD"],
                capture_output=True, text=True, check=True
            )
            return [f.strip() for f in result.stdout.split('\n') if f.strip()]
        except subprocess.CalledProcessError:
            return []

    @staticmethod
    def get_commit_history(limit: int = 5) -> str:
        """커밋 히스토리 가져오기"""
        try:
            result = subprocess.run(
                ["git", "log", "--oneline", f"-{limit}"],
                capture_output=True, text=True, check=True
            )
            return result.stdout.strip()
        except subprocess.CalledProcessError:
            return ""

# 사용 예
git_tools = GitTools()
changed_files = git_tools.get_changed_files()
print("Changed files:", changed_files)
Enter fullscreen mode Exit fullscreen mode

6. 컨텍스트 윈도우 관리

대규모 프로젝트의 경우 컨텍스트 윈도우를 제한하여 성능을 최적화합니다:


python
# context_manager.py
import os
from typing import List

class ContextManager:
    def __init__(self, max_tokens: int = 8000):
        self.max_tokens = max_tokens

    def get_context_window(self, files: List[str]) -> str:
        """최적화된 컨텍스트 윈도우 생성"""
        context = []
        total_tokens = 0

        for file_path in files[:10]:  # 최대 10개 파일만 포함
            try:
                with open(file_path, 'r') as f:
                    content = f.read()
                    token_count = len(content.split())  # 간단한 토큰 계산



---

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

Top comments (0)