터미널 AI 에이전트 구축 (v38)
터미널에서 작동하는 AI 에이전트를 구축하여 개발 생산성을 향상시킬 수 있습니다. 이 가이드에서는 로컬 LLM API 엔드포인트 설정부터 커스텀 CLI 에이전트 구축까지 실질적인 방법을 설명합니다.
1. CLI AI 에이전트 생태계
현재 CLI AI 에이전트 시장은 다양한 도구로 구성되어 있습니다:
대표 도구 비교
Aider: GitHub Copilot과 유사한 기능, 실시간 코드 생성
pip install aider
aider --help
Continue.dev: VS Code 확장으로 구동되는 터미널 통합
npm install -g continue
continue server
OpenCode: 오픈소스 커뮤니티 기반 터미널 에이전트
git clone https://github.com/opencode/open-code-agent.git
커스텀 스크립트: 최소한의 요구사항만 만족하는 가벼운 에이전트
2. 로컬 LLM API 엔드포인트 설정
로컬 LLM을 터미널에서 사용하려면 API 서버를 설정해야 합니다.
LM Studio 설치 및 실행
# macOS
brew install lm-studio
# 또는 직접 다운로드
wget https://github.com/lmstudio-ai/LMStudio/releases/latest/download/LMStudio-macOS.dmg
# 실행
open /Applications/LMStudio.app
LocalAI 설정
# Docker를 통한 LocalAI 실행
docker run -p 8080:8080 -v ~/.localai:/models localai/localai:latest
# 모델 다운로드 및 설정
curl -X POST http://localhost:8080/models \
-H "Content-Type: application/json" \
-d '{
"name": "llama3",
"url": "https://huggingface.co/TheBloke/Llama-3-8B-Instruct-GGUF/resolve/main/llama-3-8b-instruct.Q4_K_M.gguf"
}'
3. 간단한 Python CLI 에이전트 구축
다음은 기능 호출을 지원하는 간단한 CLI 에이전트입니다:
# ai_agent.py
import os
import json
import requests
from typing import Dict, List, Any
import argparse
class TerminalAgent:
def __init__(self, api_url: str = "http://localhost:8080"):
self.api_url = api_url
self.headers = {"Content-Type": "application/json"}
def call_llm(self, prompt: str, functions: List[Dict] = None) -> Dict:
payload = {
"model": "llama3",
"prompt": prompt,
"stream": False
}
if functions:
payload["functions"] = functions
response = requests.post(
f"{self.api_url}/generate",
headers=self.headers,
json=payload
)
return response.json()
def execute_code(self, code: str) -> str:
"""코드 실행 기능"""
try:
exec(code)
return "코드가 성공적으로 실행되었습니다."
except Exception as e:
return f"오류 발생: {str(e)}"
def search_files(self, pattern: str, directory: str = ".") -> List[str]:
"""파일 검색"""
import glob
search_path = os.path.join(directory, pattern)
return glob.glob(search_path)
def main():
parser = argparse.ArgumentParser(description="터미널 AI 에이전트")
parser.add_argument("prompt", help="LLM에게 전달할 프롬프트")
parser.add_argument("--execute", action="store_true", help="코드 실행")
parser.add_argument("--search", help="파일 검색 패턴")
args = parser.parse_args()
agent = TerminalAgent()
if args.search:
files = agent.search_files(args.search)
print("검색된 파일들:")
for file in files:
print(f" {file}")
return
# 기능 정의
functions = [
{
"name": "execute_code",
"description": "Python 코드를 실행합니다",
"parameters": {
"type": "object",
"properties": {
"code": {"type": "string", "description": "실행할 코드"}
},
"required": ["code"]
}
}
]
result = agent.call_llm(args.prompt, functions)
if args.execute and result.get("generated_code"):
print("생성된 코드:")
print(result["generated_code"])
response = input("코드를 실행하시겠습니까? (y/n): ")
if response.lower() == 'y':
agent.execute_code(result["generated_code"])
else:
print("AI 응답:")
print(result.get("response", "응답 없음"))
if __name__ == "__main__":
main()
실행 방법:
# 기본 사용
python ai_agent.py "Python으로 factorial 함수를 만들어줘"
# 파일 검색
python ai_agent.py --search "*.py"
# 코드 실행
python ai_agent.py --execute "import math; print(math.sqrt(16))"
4. tmux와 통합
터미널 에이전트를 tmux 세션과 통합하여 작업 흐름을 개선합니다:
# tmux 세션 생성
tmux new-session -s ai-agent -d
# 세션에 명령어 전달
tmux send-keys -t ai-agent "python ai_agent.py '작업 내용'" Enter
# 세션 목록 보기
tmux ls
# 특정 세션 연결
tmux attach -t ai-agent
tmux 스크립트 자동화
#!/bin/bash
# ai_workflow.sh
# 새로운 tmux 세션 생성
tmux new-session -s developer -d
# 세션에 명령어 실행
tmux send-keys -t developer "cd /path/to/project && git status" Enter
# 세션에 AI 에이전트 실행
tmux send-keys -t developer "python ai_agent.py '필요한 코드를 생성해줘'" Enter
# 세션 연결
tmux attach -t developer
5. 사용자 정의 도구 개발
코드 검색 도구
# code_search.py
import os
import re
from typing import List, Dict
class CodeSearcher:
def __init__(self, root_dir: str = "."):
self.root_dir = root_dir
self.supported_extensions = {'.py', '.js', '.ts', '.java', '.cpp', '.c'}
def search_patterns(self, pattern: str, case_sensitive: bool = True) -> List[Dict]:
results = []
search_flags = 0 if case_sensitive else re.IGNORECASE
for root, dirs, files in os.walk(self.root_dir):
for file in files:
if os.path.splitext(file)[1] in self.supported_extensions:
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, search_flags)
for match in matches:
results.append({
'file': file_path,
'line': content[:match.start()].count('\n') + 1,
'context': self.get_context(content, match.start(), match.end())
})
except Exception:
continue
return results
def get_context(self, content: str, start: int, end: int, context_lines: int = 3) -> str:
lines = content.split('\n')
line_num = content[:start].count('\n')
start_line = max(0, line_num - context_lines)
end_line = min(len(lines), line_num + context_lines + 1)
return '\n'.join(lines[start_line:end_line])
# 사용 예제
if __name__ == "__main__":
searcher = CodeSearcher(".")
results = searcher.search_patterns("def.*create.*")
for result in results:
print(f"{result['file']}:{result['line']}")
print(f" {result['context']}")
Git 통합 도구
python
# git_tools.py
import subprocess
import json
from typing import Dict, List
class GitTools:
@staticmethod
def get_staged_files() -> List[str]:
result = subprocess.run(['git', 'diff', '--cached', '--name-only'],
capture_output=True, text=True)
return result.stdout.strip().split('\n') if result.stdout.strip() else []
@staticmethod
def get_diff_stats() -> Dict:
result = subprocess.run(['git', 'diff', '--stat'],
capture_output=True, text=True)
return {
'stat': result.stdout.strip(),
'status': result.returncode
}
@
---
📥 **Get the full guide on Gumroad**: https://gumroad.com/l/auto ($5)
Top comments (0)