Tools: 터미널 AI 에이전트 구축 (v41) (2026)

Tools: 터미널 AI 에이전트 구축 (v41) (2026)

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

1. CLI AI 에이전트 생태계

Continue.dev

OpenCode

사용자 정의 스크립트

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

LM Studio 설치

LocalAI 설정

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

기초적인 에이전트 구조

4. tmux/터미널 멀티플렉서 통합

tmux 스크립트

tmux 파이썬 통합

5. 사용자 정의 도구 개발

코드 검색 도구

Git 연동 도구

6. 컨텍스트 윈도우 관리

7. 비용/속도 최적화

로컬 모델 최적화

성능 비교 스크립트

8. 실제 워크플로우 예시

빠른 코드 생성 워크플로우 터미널에서 작동하는 AI 에이전트를 구축하는 것은 개발자들이 코드를 더 빠르고 효율적으로 작성할 수 있게 해주는 실용적인 도구입니다. 이번 가이드에서는 로컬 환경에서 작동하는 AI 에이전트를 구축하고 최적화하는 방법을 단계별로 설명합니다. 현재 CLI AI 에이전트 시장은 다음과 같은 주요 도구들로 구성되어 있습니다: 가장 인기 있는 도구 중 하나로, Git 기반 코드 생성과 수정 기능을 제공합니다. VS Code 확장으로 시작되었지만 터미널에서도 작동할 수 있습니다. Python 기반으로 로컬 LLM을 사용하는 솔루션입니다. 모든 도구는 기본적으로 Python 스크립트로 작성되어야 합니다. 로컬 LLM 서버를 실행하여 더 빠르고 안전한 작업을 수행할 수 있습니다. 터미널에서 여러 작업을 동시에 관리할 수 있도록 tmux와 연동합니다. 대규모 코드베이스에서 효율적으로 작업하기 위해 컨텍스트 윈도우를 관리합니다. Templates let you quickly answer FAQs or store snippets for re-use. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse

Command

Copy

$ -weight: 500;">pip -weight: 500;">install aider aider --help -weight: 500;">pip -weight: 500;">install aider aider --help -weight: 500;">pip -weight: 500;">install aider aider --help -weight: 500;">npm -weight: 500;">install -g continue -weight: 500;">npm -weight: 500;">install -g continue -weight: 500;">npm -weight: 500;">install -g continue -weight: 500;">pip -weight: 500;">install opencode -weight: 500;">pip -weight: 500;">install opencode -weight: 500;">pip -weight: 500;">install opencode #!/usr/bin/env python3 import os import subprocess import sys #!/usr/bin/env python3 import os import subprocess import sys #!/usr/bin/env python3 import os import subprocess import sys # macOS -weight: 500;">brew -weight: 500;">install lm-studio # Ubuntu/Debian -weight: 500;">wget -O - https://repo.lm-studio.ai/gpg.key | -weight: 600;">sudo -weight: 500;">apt-key add - echo "deb [arch=amd64] https://repo.lm-studio.ai/ stable main" | -weight: 600;">sudo tee /etc/-weight: 500;">apt/sources.list.d/lm-studio.list -weight: 600;">sudo -weight: 500;">apt -weight: 500;">update && -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install lm-studio # macOS -weight: 500;">brew -weight: 500;">install lm-studio # Ubuntu/Debian -weight: 500;">wget -O - https://repo.lm-studio.ai/gpg.key | -weight: 600;">sudo -weight: 500;">apt-key add - echo "deb [arch=amd64] https://repo.lm-studio.ai/ stable main" | -weight: 600;">sudo tee /etc/-weight: 500;">apt/sources.list.d/lm-studio.list -weight: 600;">sudo -weight: 500;">apt -weight: 500;">update && -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install lm-studio # macOS -weight: 500;">brew -weight: 500;">install lm-studio # Ubuntu/Debian -weight: 500;">wget -O - https://repo.lm-studio.ai/gpg.key | -weight: 600;">sudo -weight: 500;">apt-key add - echo "deb [arch=amd64] https://repo.lm-studio.ai/ stable main" | -weight: 600;">sudo tee /etc/-weight: 500;">apt/sources.list.d/lm-studio.list -weight: 600;">sudo -weight: 500;">apt -weight: 500;">update && -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install lm-studio # Docker로 LocalAI 실행 -weight: 500;">docker run -p 8080:8080 localai/localai:latest # 모델 다운로드 -weight: 500;">curl -X POST http://localhost:8080/models -d '{ "name": "llama3", "url": "https://huggingface.co/TheBloke/Llama-3-8B-Instruct-GGUF/resolve/main/llama-3-8b-instruct.Q4_K_M.gguf" }' # Docker로 LocalAI 실행 -weight: 500;">docker run -p 8080:8080 localai/localai:latest # 모델 다운로드 -weight: 500;">curl -X POST http://localhost:8080/models -d '{ "name": "llama3", "url": "https://huggingface.co/TheBloke/Llama-3-8B-Instruct-GGUF/resolve/main/llama-3-8b-instruct.Q4_K_M.gguf" }' # Docker로 LocalAI 실행 -weight: 500;">docker run -p 8080:8080 localai/localai:latest # 모델 다운로드 -weight: 500;">curl -X POST http://localhost:8080/models -d '{ "name": "llama3", "url": "https://huggingface.co/TheBloke/Llama-3-8B-Instruct-GGUF/resolve/main/llama-3-8b-instruct.Q4_K_M.gguf" }' #!/usr/bin/env python3 import json import requests import subprocess import sys class TerminalAI: def __init__(self, api_url="http://localhost:8080"): self.api_url = api_url def call_model(self, prompt, functions=None): data = { "prompt": prompt, "model": "llama3" } if functions: data["functions"] = functions response = requests.post(f"{self.api_url}/completion", json=data) return response.json() def run(self, prompt): result = self.call_model(prompt) print(result["response"]) # 사용법 if __name__ == "__main__": ai = TerminalAI() ai.run(sys.argv[1]) #!/usr/bin/env python3 import json import requests import subprocess import sys class TerminalAI: def __init__(self, api_url="http://localhost:8080"): self.api_url = api_url def call_model(self, prompt, functions=None): data = { "prompt": prompt, "model": "llama3" } if functions: data["functions"] = functions response = requests.post(f"{self.api_url}/completion", json=data) return response.json() def run(self, prompt): result = self.call_model(prompt) print(result["response"]) # 사용법 if __name__ == "__main__": ai = TerminalAI() ai.run(sys.argv[1]) #!/usr/bin/env python3 import json import requests import subprocess import sys class TerminalAI: def __init__(self, api_url="http://localhost:8080"): self.api_url = api_url def call_model(self, prompt, functions=None): data = { "prompt": prompt, "model": "llama3" } if functions: data["functions"] = functions response = requests.post(f"{self.api_url}/completion", json=data) return response.json() def run(self, prompt): result = self.call_model(prompt) print(result["response"]) # 사용법 if __name__ == "__main__": ai = TerminalAI() ai.run(sys.argv[1]) #!/bin/bash # terminal-agent.sh tmux new-session -d -s ai-session tmux send-keys -t ai-session "python3 ai_agent.py 'write a python function to sort list'" Enter tmux attach -t ai-session #!/bin/bash # terminal-agent.sh tmux new-session -d -s ai-session tmux send-keys -t ai-session "python3 ai_agent.py 'write a python function to sort list'" Enter tmux attach -t ai-session #!/bin/bash # terminal-agent.sh tmux new-session -d -s ai-session tmux send-keys -t ai-session "python3 ai_agent.py 'write a python function to sort list'" Enter tmux attach -t ai-session import subprocess import os class TmuxManager: def __init__(self, session_name): self.session_name = session_name def create_session(self): subprocess.run(["tmux", "new-session", "-d", "-s", self.session_name]) def send_command(self, command): subprocess.run([ "tmux", "send-keys", "-t", self.session_name, command, "Enter" ]) def attach(self): subprocess.run(["tmux", "attach", "-t", self.session_name]) # 사용 예시 tmux = TmuxManager("dev-agent") tmux.create_session() tmux.send_command("ls -la") import subprocess import os class TmuxManager: def __init__(self, session_name): self.session_name = session_name def create_session(self): subprocess.run(["tmux", "new-session", "-d", "-s", self.session_name]) def send_command(self, command): subprocess.run([ "tmux", "send-keys", "-t", self.session_name, command, "Enter" ]) def attach(self): subprocess.run(["tmux", "attach", "-t", self.session_name]) # 사용 예시 tmux = TmuxManager("dev-agent") tmux.create_session() tmux.send_command("ls -la") import subprocess import os class TmuxManager: def __init__(self, session_name): self.session_name = session_name def create_session(self): subprocess.run(["tmux", "new-session", "-d", "-s", self.session_name]) def send_command(self, command): subprocess.run([ "tmux", "send-keys", "-t", self.session_name, command, "Enter" ]) def attach(self): subprocess.run(["tmux", "attach", "-t", self.session_name]) # 사용 예시 tmux = TmuxManager("dev-agent") tmux.create_session() tmux.send_command("ls -la") import os import re from pathlib import Path class CodeSearch: def __init__(self, root_dir="."): self.root_dir = Path(root_dir) def search_pattern(self, pattern, file_extensions=None): results = [] if file_extensions is None: file_extensions = [".py", ".js", ".ts", ".java", ".cpp"] for ext in file_extensions: for file_path in self.root_dir.rglob(f"*{ext}"): try: with open(file_path, 'r') as f: content = f.read() if re.search(pattern, content): results.append({ "file": str(file_path), "match": pattern }) except Exception: continue return results # 사용 예시 searcher = CodeSearch() results = searcher.search_pattern(r"def\s+(\w+)\s*\(.*?\):") print(json.dumps(results, indent=2)) import os import re from pathlib import Path class CodeSearch: def __init__(self, root_dir="."): self.root_dir = Path(root_dir) def search_pattern(self, pattern, file_extensions=None): results = [] if file_extensions is None: file_extensions = [".py", ".js", ".ts", ".java", ".cpp"] for ext in file_extensions: for file_path in self.root_dir.rglob(f"*{ext}"): try: with open(file_path, 'r') as f: content = f.read() if re.search(pattern, content): results.append({ "file": str(file_path), "match": pattern }) except Exception: continue return results # 사용 예시 searcher = CodeSearch() results = searcher.search_pattern(r"def\s+(\w+)\s*\(.*?\):") print(json.dumps(results, indent=2)) import os import re from pathlib import Path class CodeSearch: def __init__(self, root_dir="."): self.root_dir = Path(root_dir) def search_pattern(self, pattern, file_extensions=None): results = [] if file_extensions is None: file_extensions = [".py", ".js", ".ts", ".java", ".cpp"] for ext in file_extensions: for file_path in self.root_dir.rglob(f"*{ext}"): try: with open(file_path, 'r') as f: content = f.read() if re.search(pattern, content): results.append({ "file": str(file_path), "match": pattern }) except Exception: continue return results # 사용 예시 searcher = CodeSearch() results = searcher.search_pattern(r"def\s+(\w+)\s*\(.*?\):") print(json.dumps(results, indent=2)) import subprocess import json class GitManager: def get_changed_files(self): result = subprocess.run( ["-weight: 500;">git", "diff", "--name-only", "HEAD~1", "HEAD"], capture_output=True, text=True ) return [line.strip() for line in result.stdout.split('\n') if line.strip()] def get_commit_history(self, limit=5): result = subprocess.run([ "-weight: 500;">git", "log", f"--oneline", f"-{limit}" ], capture_output=True, text=True) return result.stdout.strip().split('\n') # 사용 예시 git_manager = GitManager() files = git_manager.get_changed_files() print(json.dumps(files, indent=2)) import subprocess import json class GitManager: def get_changed_files(self): result = subprocess.run( ["-weight: 500;">git", "diff", "--name-only", "HEAD~1", "HEAD"], capture_output=True, text=True ) return [line.strip() for line in result.stdout.split('\n') if line.strip()] def get_commit_history(self, limit=5): result = subprocess.run([ "-weight: 500;">git", "log", f"--oneline", f"-{limit}" ], capture_output=True, text=True) return result.stdout.strip().split('\n') # 사용 예시 git_manager = GitManager() files = git_manager.get_changed_files() print(json.dumps(files, indent=2)) import subprocess import json class GitManager: def get_changed_files(self): result = subprocess.run( ["-weight: 500;">git", "diff", "--name-only", "HEAD~1", "HEAD"], capture_output=True, text=True ) return [line.strip() for line in result.stdout.split('\n') if line.strip()] def get_commit_history(self, limit=5): result = subprocess.run([ "-weight: 500;">git", "log", f"--oneline", f"-{limit}" ], capture_output=True, text=True) return result.stdout.strip().split('\n') # 사용 예시 git_manager = GitManager() files = git_manager.get_changed_files() print(json.dumps(files, indent=2)) class ContextManager: def __init__(self, max_tokens=4096): self.max_tokens = max_tokens self.context = [] def add_file_context(self, file_path, max_lines=100): try: with open(file_path, 'r') as f: lines = f.readlines() if len(lines) > max_lines: # 중간 부분만 포함 -weight: 500;">start = len(lines) // 2 - max_lines // 2 end = -weight: 500;">start + max_lines context_lines = lines[-weight: 500;">start:end] else: context_lines = lines self.context.append({ "file": file_path, "lines": [line.rstrip() for line in context_lines] }) except Exception as e: print(f"Error reading {file_path}: {e}") def get_context_prompt(self): prompt = "Context information:\n" for item in self.context: prompt += f"\nFile: {item['file']}\n" for line in item['lines']: prompt += f"{line}\n" return prompt class ContextManager: def __init__(self, max_tokens=4096): self.max_tokens = max_tokens self.context = [] def add_file_context(self, file_path, max_lines=100): try: with open(file_path, 'r') as f: lines = f.readlines() if len(lines) > max_lines: # 중간 부분만 포함 -weight: 500;">start = len(lines) // 2 - max_lines // 2 end = -weight: 500;">start + max_lines context_lines = lines[-weight: 500;">start:end] else: context_lines = lines self.context.append({ "file": file_path, "lines": [line.rstrip() for line in context_lines] }) except Exception as e: print(f"Error reading {file_path}: {e}") def get_context_prompt(self): prompt = "Context information:\n" for item in self.context: prompt += f"\nFile: {item['file']}\n" for line in item['lines']: prompt += f"{line}\n" return prompt class ContextManager: def __init__(self, max_tokens=4096): self.max_tokens = max_tokens self.context = [] def add_file_context(self, file_path, max_lines=100): try: with open(file_path, 'r') as f: lines = f.readlines() if len(lines) > max_lines: # 중간 부분만 포함 -weight: 500;">start = len(lines) // 2 - max_lines // 2 end = -weight: 500;">start + max_lines context_lines = lines[-weight: 500;">start:end] else: context_lines = lines self.context.append({ "file": file_path, "lines": [line.rstrip() for line in context_lines] }) except Exception as e: print(f"Error reading {file_path}: {e}") def get_context_prompt(self): prompt = "Context information:\n" for item in self.context: prompt += f"\nFile: {item['file']}\n" for line in item['lines']: prompt += f"{line}\n" return prompt # LLM quantization python -m llama_cpp.quantize --model-path models/llama3-8b.Q4_K_M.gguf --output-path models/llama3-8b-q4.gguf # 메모리 최적화 export CUDA_VISIBLE_DEVICES=0 export LLM_CACHE_SIZE=1000 # LLM quantization python -m llama_cpp.quantize --model-path models/llama3-8b.Q4_K_M.gguf --output-path models/llama3-8b-q4.gguf # 메모리 최적화 export CUDA_VISIBLE_DEVICES=0 export LLM_CACHE_SIZE=1000 # LLM quantization python -m llama_cpp.quantize --model-path models/llama3-8b.Q4_K_M.gguf --output-path models/llama3-8b-q4.gguf # 메모리 최적화 export CUDA_VISIBLE_DEVICES=0 export LLM_CACHE_SIZE=1000 import time import requests def benchmark_model(api_url, prompt, iterations=5): times = [] for i in range(iterations): -weight: 500;">start = time.time() response = requests.post(f"{api_url}/completion", json={ "prompt": prompt, "model": "llama3" }) end = time.time() times.append(end - -weight: 500;">start) avg_time = sum(times) / len(times) print(f"Average time: {avg_time:.2f}s") return avg_time # 로컬 vs API 비교 local_time = benchmark_model("http://localhost:8080", "Hello world") import time import requests def benchmark_model(api_url, prompt, iterations=5): times = [] for i in range(iterations): -weight: 500;">start = time.time() response = requests.post(f"{api_url}/completion", json={ "prompt": prompt, "model": "llama3" }) end = time.time() times.append(end - -weight: 500;">start) avg_time = sum(times) / len(times) print(f"Average time: {avg_time:.2f}s") return avg_time # 로컬 vs API 비교 local_time = benchmark_model("http://localhost:8080", "Hello world") import time import requests def benchmark_model(api_url, prompt, iterations=5): times = [] for i in range(iterations): -weight: 500;">start = time.time() response = requests.post(f"{api_url}/completion", json={ "prompt": prompt, "model": "llama3" }) end = time.time() times.append(end - -weight: 500;">start) avg_time = sum(times) / len(times) print(f"Average time: {avg_time:.2f}s") return avg_time # 로컬 vs API 비교 local_time = benchmark_model("http://localhost:8080", "Hello world") bash # 1. 새 기능 생성 mkdir feature-auth touch feature-auth/auth_service.py # 2. AI 에이전트를 통한 코드 생성 python ai_agent.py "Create authentication -weight: 500;">service with login, register, and token refresh functions" # 3. tmux 세션 생성 ./ --- 📥 **Get the full guide on Gumroad**: https://gumroad.com/l/auto ($5) bash # 1. 새 기능 생성 mkdir feature-auth touch feature-auth/auth_service.py # 2. AI 에이전트를 통한 코드 생성 python ai_agent.py "Create authentication -weight: 500;">service with login, register, and token refresh functions" # 3. tmux 세션 생성 ./ --- 📥 **Get the full guide on Gumroad**: https://gumroad.com/l/auto ($5) bash # 1. 새 기능 생성 mkdir feature-auth touch feature-auth/auth_service.py # 2. AI 에이전트를 통한 코드 생성 python ai_agent.py "Create authentication -weight: 500;">service with login, register, and token refresh functions" # 3. tmux 세션 생성 ./ --- 📥 **Get the full guide on Gumroad**: https://gumroad.com/l/auto ($5)