터미널 AI 에이전트 구축 (v36)
터미널에서 작동하는 AI 에이전트를 구축하는 것은 현대 개발 워크플로우에서 핵심적인 도구로 자리 잡고 있습니다. 이 가이드는 실질적인 비용 ($3-$7)의 가치를 제공하는 터미널 기반 AI 에이전트를 구축하는 방법을 다룹니다.
1. CLI AI 에이전트 생태계
현재 CLI AI 에이전트는 다양한 솔루션으로 구성되어 있습니다:
Aider: Git 기반 코드 생성 도구
pip install aider
aider --help
Continue.dev: VS Code 확장이지만 CLI에서도 사용 가능
npm install -g continue
OpenCode: 직접 구축한 커스텀 에이전트
# 커스텀 스크립트 예시
pip install openai
내부 에이전트: 최소한의 기능을 가진 자체 구축 도구
2. 로컬 LLM API 엔드포인트 설정
로컬 LLM을 위한 API 엔드포인트를 설정하여 성능과 비용을 최적화합니다:
# Ollama 설치 (가장 간단한 방법)
curl -fsSL https://ollama.com/install.sh | sh
# 로컬 모델 실행
ollama run llama3.2:3b
ollama run codellama:7b
# API 엔드포인트 시작
ollama serve
API 엔드포인트 구성:
# server.py
from flask import Flask, request, jsonify
import requests
app = Flask(__name__)
@app.route('/chat', methods=['POST'])
def chat():
data = request.json
prompt = data.get('prompt', '')
response = requests.post(
'http://localhost:11434/api/generate',
json={
'model': 'llama3.2:3b',
'prompt': prompt,
'stream': False
}
)
return jsonify(response.json())
if __name__ == '__main__':
app.run(port=8000)
3. 함수 호출 기능을 가진 간단한 Python CLI 에이전트
# agent.py
import openai
import json
import subprocess
from typing import List, Dict
import os
class TerminalAgent:
def __init__(self, api_key: str = None):
self.client = openai.OpenAI(
base_url="http://localhost:8000",
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, function_name: str, args: Dict) -> str:
"""함수 호출"""
functions = {
'execute_command': self.execute_command,
'list_files': self.list_files,
'git_status': self.git_status
}
if function_name in functions:
return functions[function_name](**args)
return f"Function {function_name} not found"
def list_files(self, path: str = ".") -> str:
"""파일 목록 조회"""
try:
files = os.listdir(path)
return json.dumps(files, indent=2)
except Exception as e:
return f"Error listing files: {str(e)}"
def git_status(self) -> str:
"""Git 상태 조회"""
return self.execute_command("git status --porcelain")
def chat(self, prompt: str, functions: List[Dict] = None) -> str:
"""AI 채팅 메시지 처리"""
messages = [
{
"role": "system",
"content": "You are a helpful terminal assistant that can execute commands and provide code assistance."
},
{
"role": "user",
"content": prompt
}
]
response = self.client.chat.completions.create(
model="llama3.2:3b",
messages=messages,
functions=functions,
function_call="auto"
)
return response.choices[0].message.content
# 사용법
if __name__ == "__main__":
agent = TerminalAgent()
result = agent.chat("git 상태를 확인해줘")
print(result)
4. tmux/터미널 멀티플렉서 통합
터미널 에이전트와 tmux를 통합하여 복잡한 작업 처리:
# tmux 스크립트 생성
cat > tmux_agent.sh << 'EOF'
#!/bin/bash
# tmux 세션에 에이전트 실행
SESSION_NAME="ai_agent"
# 새 세션 생성
tmux new-session -d -s $SESSION_NAME
# 에이전트 실행
tmux send-keys -t $SESSION_NAME "python agent.py" Enter
# 세션을 포그라운드로 전환
tmux attach -t $SESSION_NAME
EOF
chmod +x tmux_agent.sh
# enhanced_agent.py
import subprocess
import os
import sys
import time
class EnhancedTerminalAgent(TerminalAgent):
def create_tmux_session(self, session_name: str, command: str):
"""tmux 세션 생성"""
try:
# 새 세션 생성
subprocess.run([
'tmux', 'new-session', '-d', '-s', session_name
], check=True)
# 명령어 실행
subprocess.run([
'tmux', 'send-keys', '-t', session_name, command, 'Enter'
], check=True)
return True
except subprocess.CalledProcessError:
return False
def get_tmux_session_status(self, session_name: str) -> str:
"""tmux 세션 상태 확인"""
try:
result = subprocess.run([
'tmux', 'list-sessions', '-F', '#{session_name}: #{session_attached}'
], capture_output=True, text=True)
return result.stdout
except:
return "Error checking session"
# 사용 예시
agent = EnhancedTerminalAgent()
agent.create_tmux_session("coding_session", "vim main.py")
5. 커스텀 도구 개발
python
# custom_tools.py
import os
import glob
from pathlib import Path
class CustomTools:
@staticmethod
def find_files(pattern: str, directory: str = ".") -> str:
"""파일 찾기"""
try:
search_path = os.path.join(directory, pattern)
files = glob.glob(search_path, recursive=True)
return json.dumps(files, indent=2)
except Exception as e:
return f"Error: {str(e)}"
@staticmethod
def search_code(pattern: str, directory: str = ".") -> str:
"""코드 검색"""
try:
results = []
for root, dirs, files in os.walk(directory):
for file in files:
if file.endswith(('.py', '.js', '.ts', '.html', '.css')):
filepath = os.path.join(root, file)
with open(filepath, 'r') as f:
content = f.read()
if pattern in content:
results.append({
'file': filepath,
'line': content.count('\n', 0, content.find(pattern)) + 1
})
return json.dumps(results, indent=2)
except Exception as e:
return f"Error: {str(e)}"
@staticmethod
def get_project_info(directory: str = ".") -> str:
"""프로젝트 정보 조회"""
info = {
'current_directory': os.getcwd(),
'git_status': subprocess.getoutput('git status --porcelain'),
'file_count': len([f for f in Path(directory).rglob('*') if f.is_file()]),
'python_files': len([f for f in Path(directory).rglob('*.py') if f.is_file()]),
'node_modules': os.path.exists(os.path.join(directory, 'node_modules'))
}
return json.dumps(info, indent=2)
# 도구 등록
functions = [
{
"name": "execute_command",
"description": "명령어 실행",
"parameters": {
"type": "object",
"properties": {
"command": {"type": "string"}
},
"required": ["command"]
}
},
{
"name": "find_files",
"description": "파일 찾기",
"parameters": {
"type": "object",
"properties": {
"pattern": {"type": "string"},
"directory": {"type": "string"}
},
"required": ["pattern"]
}
},
{
"name": "search_code",
"description": "코드 검색",
"parameters": {
"type": "object",
"properties": {
---
📥 **Get the full guide on Gumroad**: https://gumroad.com/l/auto ($5)
Top comments (0)