터미널 AI 에이전트 구축 (v48)
개발자들을 위한 로컬 AI 코딩 에이전트 구축 가이드
1. CLI AI 에이전트 생태계
현재 CLI AI 에이전트 시장은 다양한 솔루션으로 분산되어 있습니다:
주요 플랫폼 비교
Aider: GitHub Copilot 기반의 실시간 코드 작성 도구
pip install aider
aider --help
Continue.dev: VSCode 기반 AI 코딩 도우미
npm install -g continue
OpenCode: 커스텀 AI 모델 연동 가능
git clone https://github.com/open-code/open-code.git
커스텀 스크립트: 최대한의 커스터마이징이 가능한 방법
2. 로컬 LLM API 엔드포인트 설정
로컬 LLM을 사용하여 프라이버시와 성능 문제를 해결합니다:
LMStudio 설치 및 실행
# macOS
brew install lmstudio
# 또는 Windows/Linux
wget https://github.com/lmstudio-ai/LMStudio/releases/download/v0.1.25/LMStudio-0.1.25-x86_64.AppImage
# 서버 실행 (기본 포트 1234)
./LMStudio-0.1.25-x86_64.AppImage --port 1234 --model-path ./models/
API 테스트
curl -X POST http://localhost:1234/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "local-model",
"messages": [
{"role": "user", "content": "Hello, how are you?"}
],
"temperature": 0.7
}'
3. 간단한 Python CLI 에이전트 구축
# smart_agent.py
import openai
import json
import os
import subprocess
from typing import Dict, List
import argparse
class TerminalAgent:
def __init__(self, api_key: str = None, model: str = "gpt-4"):
# 로컬 API 설정
if api_key:
openai.api_key = api_key
else:
# 로컬 모델을 위한 설정
openai.base_url = "http://localhost:1234/v1/"
openai.api_key = "not-needed"
self.model = model
self.functions = [
{
"name": "run_command",
"description": "터미널 명령어 실행",
"parameters": {
"type": "object",
"properties": {
"command": {"type": "string", "description": "실행할 명령어"}
},
"required": ["command"]
}
},
{
"name": "read_file",
"description": "파일 내용 읽기",
"parameters": {
"type": "object",
"properties": {
"file_path": {"type": "string", "description": "파일 경로"}
},
"required": ["file_path"]
}
}
]
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"Error: {str(e)}"
def read_file(self, file_path: str) -> str:
"""파일 내용 읽기"""
try:
with open(file_path, 'r') as f:
return f.read()
except Exception as e:
return f"Error reading file: {str(e)}"
def process_function_call(self, function_name: str, arguments: Dict) -> str:
"""함수 호출 처리"""
if function_name == "run_command":
return self.run_command(arguments['command'])
elif function_name == "read_file":
return self.read_file(arguments['file_path'])
return "Unknown function"
def ask(self, question: str) -> str:
"""질문에 대한 답변 생성"""
response = openai.ChatCompletion.create(
model=self.model,
messages=[
{"role": "system", "content": "You are a helpful coding assistant that can execute commands and read files."},
{"role": "user", "content": question}
],
functions=self.functions,
function_call="auto"
)
message = response.choices[0].message
if message.get('function_call'):
function_name = message['function_call']['name']
arguments = json.loads(message['function_call']['arguments'])
result = self.process_function_call(function_name, arguments)
return result
return message.content
def main():
parser = argparse.ArgumentParser(description='Terminal AI Agent')
parser.add_argument('question', nargs='*', help='질문 내용')
args = parser.parse_args()
agent = TerminalAgent()
question = ' '.join(args.question) if args.question else "help"
print(f"Question: {question}")
answer = agent.ask(question)
print(answer)
if __name__ == "__main__":
main()
4. tmux와 통합
tmux 세션을 활용한 멀티탭 환경 구축:
# tmux 세션 생성
tmux new-session -s smart_agent -d
# 세션에 윈도우 추가 (코드 편집용)
tmux new-window -t smart_agent -n editor
# 세션에 윈도우 추가 (터미널용)
tmux new-window -t smart_agent -n terminal
# 세션 실행
tmux attach -t smart_agent
tmux 스크립트 파일
# agent_tmux.sh
#!/bin/bash
SESSION="smart_agent"
# 세션이 없으면 생성
if ! tmux has-session -t $SESSION 2>/dev/null; then
tmux new-session -d -s $SESSION
tmux new-window -t $SESSION -n "editor"
tmux new-window -t $SESSION -n "terminal"
tmux new-window -t $SESSION -n "logs"
fi
# 세션에 연결
tmux attach -t $SESSION
5. 사용자 정의 도구 개발
코드 검색 도구
# tools/code_search.py
import os
import re
from pathlib import Path
class CodeSearcher:
def __init__(self, root_path: str = "."):
self.root_path = Path(root_path)
def search_function(self, function_name: str, file_extensions: list = ['.py', '.js', '.ts']) -> list:
"""함수 정의 검색"""
results = []
for file_path in self.root_path.rglob("*"):
if file_path.suffix in file_extensions:
try:
with open(file_path, 'r') as f:
content = f.read()
if f"def {function_name}" in content or f"function {function_name}" in content:
lines = content.split('\n')
for i, line in enumerate(lines):
if function_name in line and ('def ' in line or 'function ' in line):
results.append({
'file': str(file_path),
'line': i + 1,
'content': line.strip()
})
except:
continue
return results
def search_pattern(self, pattern: str, case_sensitive: bool = True) -> list:
"""정규표현식으로 패턴 검색"""
results = []
regex = re.compile(pattern, 0 if case_sensitive else re.IGNORECASE)
for file_path in self.root_path.rglob("*"):
if file_path.is_file():
try:
with open(file_path, 'r') as f:
content = f.read()
matches = regex.finditer(content)
for match in matches:
results.append({
'file': str(file_path),
'line': content[:match.start()].count('\n') + 1,
'content': match.group().strip()
})
except:
continue
return results
Git 연동 도구
python
# tools/git_tools.py
import subprocess
import json
from typing import Dict, List
class GitTools:
def __init__(self):
pass
def get_staged_files(self) -> List[str]:
"""스테이징된 파일 목록"""
try:
result = subprocess.run(['git', 'diff', '--cached', '--name-only'],
capture_output=True, text=True)
return result.stdout.strip().split('\n') if result.stdout.strip() else []
except:
return []
def get_git_log(self, limit: int = 10) -> List[Dict]:
"""Git 로그 가져오기"""
try:
result = subprocess.run([
'git', 'log', '--oneline', f'-{limit}'
], capture_output=True, text=True)
logs
---
📥 **Get the full guide on Gumroad**: https://gumroad.com/l/auto ($5)
Top comments (0)