DEV Community

matias yoon
matias yoon

Posted on

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

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

터미널에서 직접 작동하는 AI 에이전트를 구축하는 것은 현대 개발자의 생산성을 높이는 가장 효과적인 방법 중 하나입니다. 이 가이드에서는 개발자가 직접 구축할 수 있는 로컬 LLM 기반 CLI AI 에이전트를 구축하는 방법을 설명합니다.

1. CLI AI 에이전트 생태계

현재 CLI 기반 AI 에이전트 생태계는 다음과 같은 주요 도구들로 구성되어 있습니다:

Aider

가장 인기 있는 도구 중 하나로, Git 기반 코드 수정을 지원합니다.

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

Continue.dev

VS Code 확장으로 개발되었지만, CLI 버전도 제공됩니다.

npm install -g continue
continue --help
Enter fullscreen mode Exit fullscreen mode

OpenCode

Python 기반으로 구축된 로컬 AI 에이전트입니다.

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

사용자 정의 스크립트

가장 유연한 접근 방식으로, 자신의 필요에 맞춘 에이전트를 직접 구축할 수 있습니다.

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

로컬 LLM을 사용하여 높은 성능과 낮은 지출로 AI 에이전트를 구축하려면 로컬 API 엔드포인트를 설정해야 합니다.

LM Studio 설치 및 실행

# macOS
brew install lm-studio

# Linux
wget https://github.com/lmstudio/lm-studio/releases/latest/download/LM-Studio-0.2.5-linux-x86_64.deb
sudo dpkg -i LM-Studio-0.2.5-linux-x86_64.deb

# 시작
lm-studio
Enter fullscreen mode Exit fullscreen mode

LocalAI로 API 서버 실행

# LocalAI 설치
git clone https://github.com/go-skynet/LocalAI.git
cd LocalAI

# Docker로 실행 (권장)
docker run -p 8080:8080 -v $(pwd)/models:/models localai/localai:latest

# 또는 로컬에서 직접 실행
make build
./local-ai server
Enter fullscreen mode Exit fullscreen mode

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

이제 로컬 LLM API에 연결하는 간단한 Python CLI 에이전트를 만들어보겠습니다.

# ai_agent.py
import os
import json
import requests
import argparse
from typing import Dict, List, Any

class TerminalAIAgent:
    def __init__(self, api_url: str = "http://localhost:8080/v1/chat/completions"):
        self.api_url = api_url
        self.headers = {"Content-Type": "application/json"}

    def chat(self, prompt: str, context: str = "") -> str:
        """LLM에 요청을 보내 응답을 받습니다"""
        messages = [
            {"role": "system", "content": "You are a helpful coding assistant. Respond in Markdown."}
        ]

        if context:
            messages.append({"role": "user", "content": f"Context: {context}"})

        messages.append({"role": "user", "content": prompt})

        data = {
            "model": "ggml-model.bin",  # 또는 사용하는 모델 이름
            "messages": messages,
            "temperature": 0.7,
            "max_tokens": 1024
        }

        try:
            response = requests.post(
                self.api_url,
                headers=self.headers,
                json=data,
                timeout=30
            )
            response.raise_for_status()
            return response.json()['choices'][0]['message']['content']
        except Exception as e:
            return f"Error: {str(e)}"

    def run(self, prompt: str, context: str = "") -> None:
        """에이전트 실행"""
        print(f"Prompt: {prompt}")
        response = self.chat(prompt, context)
        print(response)

def main():
    parser = argparse.ArgumentParser(description='Terminal AI Agent')
    parser.add_argument('--prompt', '-p', required=True, help='Prompt to send to AI')
    parser.add_argument('--context', '-c', help='Context information')
    parser.add_argument('--api-url', default="http://localhost:8080/v1/chat/completions", 
                       help='API endpoint URL')

    args = parser.parse_args()

    agent = TerminalAIAgent(api_url=args.api_url)
    agent.run(args.prompt, args.context)

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

실행 방법:

python ai_agent.py --prompt "Python에서 Flask 애플리케이션을 만드는 방법을 설명해주세요."
Enter fullscreen mode Exit fullscreen mode

4. tmux와 통합

터미널 세션 관리를 위해 tmux와 통합하는 방법을 살펴보겠습니다.

# tmux 설치
sudo apt install tmux  # Ubuntu/Debian
brew install tmux      # macOS

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

# 세션에 연결
tmux attach -t ai-agent
Enter fullscreen mode Exit fullscreen mode

tmux 스크립트 생성

# ai_session.sh
#!/bin/bash
SESSION="ai-agent"

# 새 세션 생성
tmux new-session -d -s $SESSION

# 첫 번째 윈도우 생성
tmux new-window -t $SESSION:1 -n "agent"

# 두 번째 윈도우 생성 (파일 탐색)
tmux new-window -t $SESSION:2 -n "files"

# 세 번째 윈도우 생성 (에이전트 테스트)
tmux new-window -t $SESSION:3 -n "test"

# 윈도우 전환
tmux select-window -t $SESSION:1

# 세션에 연결
tmux attach -t $SESSION
Enter fullscreen mode Exit fullscreen mode

실행:

chmod +x ai_session.sh
./ai_session.sh
Enter fullscreen mode Exit fullscreen mode

5. 사용자 정의 도구 개발

코드 검색 도구

# code_search.py
import os
import subprocess
import re
from typing import List

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

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

        results = []
        for root, dirs, files in os.walk(self.root_dir):
            for file in files:
                if any(file.endswith(ext) for ext in file_types):
                    file_path = os.path.join(root, file)
                    try:
                        with open(file_path, 'r', encoding='utf-8') as f:
                            content = f.read()
                            matches = re.finditer(pattern, content)
                            for match in matches:
                                results.append({
                                    'file': file_path,
                                    'line': content[:match.start()].count('\n') + 1,
                                    'match': match.group()
                                })
                    except Exception as e:
                        continue
        return results

    def search_code(self, query: str) -> str:
        """코드 검색 결과를 포맷팅하여 반환"""
        results = self.search_in_files(query)
        if not results:
            return f"No results found for '{query}'"

        formatted_results = [f"\nFile: {r['file']} (line {r['line']})" for r in results[:5]]
        return "\n".join(formatted_results) + f"\n... and {len(results) - 5} more results"

# 사용 예
search_tool = CodeSearchTool()
print(search_tool.search_code("def main"))
Enter fullscreen mode Exit fullscreen mode

Git 통합 도구


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

class GitTool:
    def __init__(self):
        pass

    def get_git_status(self) -> Dict:
        """Git 상태 정보 가져오기"""
        try:
            status = subprocess.run(['git', 'status', '--porcelain'], 
                                   capture_output=True, text=True)
            return {
                'status': status.stdout.strip(),
                'has_changes': bool(status.stdout.strip())
            }
        except Exception as e:
            return {'error': str(e)}

    def get_recent_commits(self, count: int = 5) -> List[Dict]:
        """최근 커밋 목록 가져오기"""
        try:
            result = subprocess.run([
                'git', 'log', f'-{count}', '--oneline', '--no-color'
            ], 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 [{'error': str(e)}]



---

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

Top comments (0)