터미널 AI 에이전트 구축 (v42)
터미널에서 AI를 활용한 개발 워크플로우는 점점 더 중요해지고 있습니다. 이 가이드는 로컬 AI 에이전트를 구축하여 터미널에서 직접 사용할 수 있도록 도와주는 실질적인 방법을 제공합니다.
1. CLI AI 에이전트 생태계
현재 터미널 AI 에이전트 시장은 다음과 같은 주요 플랫폼으로 구성되어 있습니다:
Aider: GitHub Copilot과 유사한 기능을 제공하는 오픈소스 도구
pip install aider
aider --help
Continue.dev: VSCode 확장 프로그램에서 개발된 터미널 지원 도구
npm install -g continue
OpenCode: 라이브러리 기반 접근 방식으로 기존 코드를 분석하는 도구
pip install opencode
커스텀 스크립트: 직접 구축한 커스터마이징 가능한 솔루션
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
API 엔드포인트 확인:
curl -X POST http://localhost:11434/api/generate \
-H "Content-Type: application/json" \
-d '{
"model": "llama3",
"prompt": "Hello, how are you?",
"stream": false
}'
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)
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
# 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")
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))
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)
Top comments (0)