selvage


Nameselvage JSON
Version 0.1.2 PyPI version JSON
download
home_pageNone
SummaryLLM 기반 코드 리뷰 도구
upload_time2025-07-17 08:30:37
maintainerNone
docs_urlNone
authorSelvage Team
requires_python>=3.10
licenseMIT
keywords code-review llm ai git cli python
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            <h1 align="center">Selvage: AI 기반 코드 리뷰 자동화 도구</h1>

<p align="center"><strong>Git diff를 AI가 분석하여 코드 품질 향상, 버그 발견, 보안 취약점 식별을 도와주는 현대적인 CLI 도구입니다.</strong></p>

<p align="center">
  <a href="https://pypi.org/project/selvage/"><img alt="PyPI" src="https://img.shields.io/pypi/v/selvage"></a>
  <a href="LICENSE"><img alt="License" src="https://img.shields.io/badge/license-MIT-blue.svg"></a>
  <img alt="Python" src="https://img.shields.io/badge/python-3.10+-blue">
  <img alt="AI Models" src="https://img.shields.io/badge/AI-GPT--4o%20%7C%20Claude%20%7C%20Gemini-green">
</p>

<!-- TODO: 데모 GIF 추가 -->
<!-- <p align="center"> <img src="[데모 GIF URL]" width="100%" alt="Selvage Demo"/> </p> -->

<p align="center">
  <img src="assets/demo.gif" width="100%" alt="Selvage Demo"/>
</p>

**Selvage : 코드 마감까지 탄탄하게!**

동료의 리뷰를 기다리며 작업이 늦어지거나, 퇴근 무렵 쌓인 리뷰 요청에 발목 잡힌 경험이 있으신가요?  
Selvage는 이런 코드 리뷰 병목 현상을 해결하는 AI 기반 도구입니다.

Selvage는 최첨단 AI 모델(OpenAI GPT, Anthropic Claude, Google Gemini 등)을 활용하여 Git diff를 분석하는 커맨드 라인 도구입니다.  
Selvage에게 코드 변경사항에 대한 리뷰를 요청하면, AI가 코드를 분석하여 피드백을 즉시 제공합니다.  
이를 통해 코드 품질 향상, 잠재적 버그 조기 발견, 보안 강화는 물론, 개발자 생산성까지 크게 향상시킬 수 있습니다.

<details>
<summary><strong>Table of Contents</strong></summary>

- [✨ 주요 기능](#-주요-기능)
- [🚀 빠른 시작](#-빠른-시작)
  - [설치 방법](#설치-방법)
  - [설정](#설정)
  - [리뷰 실행하기](#리뷰-실행하기)
- [🌐 지원 언어 및 모델](#-지원-언어-및-모델)
  - [지원 파일 형식](#지원-파일-형식)
  - [지원 AI 모델](#지원-ai-모델)
- [⌨️ CLI 사용법](#️-cli-사용법)
  - [Selvage 설정하기](#selvage-설정하기)
  - [코드 리뷰하기](#코드-리뷰하기)
  - [결과 확인하기](#결과-확인하기)
- [📄 출력 형식](#-출력-형식)
- [🛠️ 고급 사용법](#️-고급-사용법)
- [🤝 기여하기](#-기여하기)
- [📜 라이선스](#-라이선스)
- [�� 문의 및 커뮤니티](#-문의-및-커뮤니티)

</details>

## ✨ 주요 기능

- **🤖 다양한 AI 모델 지원**: OpenAI GPT-4o, Anthropic Claude Sonnet-4, Google Gemini 등 최신 LLM 모델 활용
- **🔍 Git 워크플로우와 통합**: staged, unstaged, 특정 커밋/브랜치 간 변경사항 분석 지원
- **🐛 포괄적 코드 검토**: 버그 및 논리 오류 탐지, 코드 품질 및 가독성 향상 제안
- **🎯 컨텍스트 분석**: 변경점이 포함된 전체 파일 내용을 참고하는 분석 기능 제공
- **📖 오픈소스**: MIT 라이선스로 자유롭게 사용 및 수정 가능

## 🚀 빠른 시작

### 설치 방법

#### 기본 설치 (운영 환경)

```bash
# PyPI에서 설치 (정식 출시 후 예정)
pip install selvage

# 또는 개발 버전 설치
git clone https://github.com/anomie7/selvage.git
cd selvage
pip install -e .
```

#### 개발 환경 설치

```bash
# 개발 의존성 포함 설치 (pytest, build 등)
pip install -e .[dev]

# 개발 + E2E 테스트 환경 설치 (testcontainers, docker 등)
pip install -e .[dev,e2e]
```

### 설정

#### 1. API 키 설정

**환경 변수로 설정 (권장)**

터미널 세션용:

```bash
export OPENAI_API_KEY="your_openai_api_key_here"
export ANTHROPIC_API_KEY="your_anthropic_api_key_here"
export GEMINI_API_KEY="your_gemini_api_key_here"
```

영구 설정 (zsh 사용자):

```bash
echo 'export OPENAI_API_KEY="your_api_key_here"' >> ~/.zshrc
echo 'export ANTHROPIC_API_KEY="your_api_key_here"' >> ~/.zshrc
echo 'export GEMINI_API_KEY="your_api_key_here"' >> ~/.zshrc
source ~/.zshrc
```

**CLI 명령어로 설정**

```bash
# OpenAI API 키 설정
selvage --set-openai-key

# Anthropic API 키 설정
selvage --set-claude-key

# Gemini API 키 설정
selvage --set-gemini-key
```

#### 2. 기본 모델 설정 (선택사항)

```bash
# 기본 사용할 모델 설정
selvage config model claude-sonnet-4-thinking

# 설정 확인
selvage config list
```

### 리뷰 실행하기

```bash
# 현재 워킹 디렉토리의 변경사항 리뷰
selvage review

# 스테이징된 변경사항만 리뷰
selvage review --staged

# 특정 모델로 리뷰
selvage review --model gemini-2.5-pro

# 리뷰 후 자동으로 UI 열기 (터미널 출력 비활성화)
selvage review --open-ui

# 터미널에 출력하지 않고 파일로만 저장
selvage review --no-print
```

리뷰 결과는 기본적으로 터미널에 출력되며 자동으로 파일에도 저장됩니다. `--open-ui` 옵션으로 UI를 열거나 `--no-print` 옵션으로 터미널 출력을 비활성화할 수 있습니다.

## 🌐 지원 언어 및 모델

### 지원 파일 형식

- **Python** (`.py`)
- **JavaScript** (`.js`)
- **TypeScript** (`.ts`)
- **Java** (`.java`)
- **Kotlin** (`.kt`, `.kts`)
- **Go** (`.go`)
- **Ruby** (`.rb`)
- **PHP** (`.php`)
- **C#** (`.cs`)
- **C/C++** (`.c`, `.cpp`, `.h`, `.hpp`)
- **HTML** (`.html`)
- **CSS/SCSS** (`.css`, `.scss`)
- **Shell** (`.sh`, `.bash`)
- **SQL** (`.sql`)
- **Markdown** (`.md`)
- **JSON** (`.json`)
- **YAML** (`.yaml`, `.yml`)
- **XML** (`.xml`)
- 기타 텍스트 기반 코드 파일

### 지원 AI 모델

#### OpenAI 모델

- **gpt-4o**: 고급 코드 분석 및 텍스트 처리 능력 (128K 컨텍스트)
- **gpt-4.1**: 대용량 코드베이스 분석 지원 (1M+ 토큰 컨텍스트)
- **o4-mini-high**: 높은 정확도의 추론 모델 (200K 컨텍스트)
- **o4-mini**: 균형 잡힌 추론 모델 (별칭: o4-mini-medium) (200K 컨텍스트)

#### Anthropic 모델

- **claude-sonnet-4**: 하이브리드 추론 모델로 고급 코딩 최적화 (200K 컨텍스트)
- **claude-sonnet-4-thinking**: ⭐ **추천** - 확장 사고 프로세스 지원 (200K 컨텍스트)

#### Google 모델

- **gemini-2.5-pro**: ⭐ **추천** - 대용량 컨텍스트 및 고급 추론 (1M+ 토큰)
- **gemini-2.5-flash**: ⭐ **추천** - 응답 속도와 비용 효율성 최적화 (1M+ 토큰)

## ⌨️ CLI 사용법

### Selvage 설정하기

```bash
# 모든 설정 보기
selvage config list

# 기본 모델 설정
selvage config model <모델명>

# 디버그 모드 설정
selvage config debug-mode on

# diff-only 옵션 설정 (변경된 부분만 분석)
selvage config diff-only true
```

### 코드 리뷰하기

```bash
selvage review [OPTIONS]
```

#### 주요 옵션

- `--repo-path <경로>`: Git 저장소 경로 (기본값: 현재 디렉토리)
- `--staged`: 스테이징된 변경사항만 리뷰
- `--target-commit <커밋ID>`: 특정 커밋부터 HEAD까지의 변경사항 리뷰 (예: abc1234)
- `--target-branch <브랜치명>`: 현재 브랜치와 지정된 브랜치 간 변경사항 리뷰 (예: main)
- `--model <모델명>`: 사용할 AI 모델 (예: claude-sonnet-4-thinking)
- `--open-ui`: 리뷰 완료 후 자동으로 UI 실행
- `--no-print`: 터미널에 리뷰 결과를 출력하지 않음 (기본적으로 터미널 출력 활성화)
- `--diff-only`: 변경된 부분만 분석 (전체 파일 컨텍스트 제외)

#### 사용 예시

```bash
# 현재 워킹 디렉토리 변경사항 리뷰
selvage review

# 스테이징된 변경사항을 Claude로 리뷰
selvage review --staged --model claude-sonnet-4-thinking

# 리뷰 후 터미널에 출력하지 않음 (파일로만 저장)
selvage review --no-print --model gemini-2.5-flash

# main 브랜치와 현재 브랜치 간 차이점 리뷰 후 UI 열기
selvage review --target-branch main --open-ui

# 특정 커밋 이후 변경사항 리뷰 (기본적으로 터미널 출력)
selvage review --target-commit abc1234 --model gemini-2.5-pro
```

### 결과 확인하기

```bash
# 저장된 리뷰 결과를 UI로 보기
selvage view

# 다른 포트에서 UI 실행
selvage view --port 8502
```

**UI 주요 기능:**

- 📋 모든 리뷰 결과 목록 표시
- 🎨 마크다운 형식 표시
- 🗂️ JSON 구조화된 결과 보기

## 📄 출력 형식

<p align="center">
  <img src="assets/demo-ui.png" width="100%" alt="Selvage UI Demo"/>
</p>

### Markdown (기본값)

- 📖 사람이 읽기 편한 깔끔한 구조
- 📝 요약, 이슈 목록, 개선 제안 포함
- 🎯 중요도별 이슈 분류
- 💡 실행 가능한 개선 방안 제시

### JSON

- 🔧 프로그래밍 방식으로 처리 용이
- ⚙️ 구조화된 데이터 형식
- 🔗 다른 도구와의 통합에 유용
- 📊 자동화 파이프라인에 적합

## 🛠️ 고급 사용법

### 모델별 최적 사용 시나리오

```bash
# 복잡한 로직 분석 - Claude 추천
selvage review --model claude-sonnet-4-thinking

# 대용량 코드베이스 - Gemini 추천
selvage review --model gemini-2.5-pro

# 빠른 리뷰 - Gemini Flash 추천
selvage review --model gemini-2.5-flash
```

### 다양한 Git 워크플로우와 통합

```bash
# PR 리뷰 전 체크
selvage review --target-branch main

# 커밋 전 최종 검토
selvage review --staged --open-ui

# 특정 기능 브랜치 전체 리뷰
selvage review --target-branch develop
```

### 비용 최적화

```bash
# 변경 부분만 분석하여 토큰 절약
selvage review --diff-only

# 작은 변경사항에는 경제적인 모델 사용
selvage review --model gemini-2.5-flash
```

## 🤝 기여하기

Selvage는 오픈소스 프로젝트이며, 여러분의 기여를 언제나 환영합니다! 버그 리포트, 기능 제안, 문서 개선, 코드 기여 등 어떤 형태의 기여든 좋습니다.

**기여 방법:**

- 🐛 [GitHub Issues](https://github.com/anomie7/selvage/issues)에서 버그 리포트 또는 기능 제안
- 🔧 Pull Request를 통한 코드 기여
- 📚 문서 개선 및 번역

**상세한 기여 가이드라인은 [CONTRIBUTING.md](CONTRIBUTING.md)에서 확인하실 수 있습니다.**

## 📜 라이선스

Selvage는 [MIT License](LICENSE) 하에 배포됩니다. 이 라이선스는 상업적 이용, 수정, 배포를 허용하며, 라이선스 및 저작권 고지를 포함하는 한 자유롭게 사용할 수 있습니다.

## 📞 문의 및 커뮤니티

- **🐛 버그 리포트 및 기능 요청**: [GitHub Issues](https://github.com/anomie7/selvage/issues)
- **📧 직접 문의**: anomie7777@gmail.com

---

<p align="center">
  <strong>Selvage와 함께 더 나은 코드를 작성하세요! 🚀</strong><br>
  ⭐ 프로젝트가 도움이 되셨다면 GitHub에서 Star를 눌러주세요!
</p>

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "selvage",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": null,
    "keywords": "code-review, llm, ai, git, cli, python",
    "author": "Selvage Team",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/6b/a9/83410ae69e059f1b319c5db034e09f7ca3f146260c6759bf5177c982d1a3/selvage-0.1.2.tar.gz",
    "platform": null,
    "description": "<h1 align=\"center\">Selvage: AI \uae30\ubc18 \ucf54\ub4dc \ub9ac\ubdf0 \uc790\ub3d9\ud654 \ub3c4\uad6c</h1>\n\n<p align=\"center\"><strong>Git diff\ub97c AI\uac00 \ubd84\uc11d\ud558\uc5ec \ucf54\ub4dc \ud488\uc9c8 \ud5a5\uc0c1, \ubc84\uadf8 \ubc1c\uacac, \ubcf4\uc548 \ucde8\uc57d\uc810 \uc2dd\ubcc4\uc744 \ub3c4\uc640\uc8fc\ub294 \ud604\ub300\uc801\uc778 CLI \ub3c4\uad6c\uc785\ub2c8\ub2e4.</strong></p>\n\n<p align=\"center\">\n  <a href=\"https://pypi.org/project/selvage/\"><img alt=\"PyPI\" src=\"https://img.shields.io/pypi/v/selvage\"></a>\n  <a href=\"LICENSE\"><img alt=\"License\" src=\"https://img.shields.io/badge/license-MIT-blue.svg\"></a>\n  <img alt=\"Python\" src=\"https://img.shields.io/badge/python-3.10+-blue\">\n  <img alt=\"AI Models\" src=\"https://img.shields.io/badge/AI-GPT--4o%20%7C%20Claude%20%7C%20Gemini-green\">\n</p>\n\n<!-- TODO: \ub370\ubaa8 GIF \ucd94\uac00 -->\n<!-- <p align=\"center\"> <img src=\"[\ub370\ubaa8 GIF URL]\" width=\"100%\" alt=\"Selvage Demo\"/> </p> -->\n\n<p align=\"center\">\n  <img src=\"assets/demo.gif\" width=\"100%\" alt=\"Selvage Demo\"/>\n</p>\n\n**Selvage : \ucf54\ub4dc \ub9c8\uac10\uae4c\uc9c0 \ud0c4\ud0c4\ud558\uac8c!**\n\n\ub3d9\ub8cc\uc758 \ub9ac\ubdf0\ub97c \uae30\ub2e4\ub9ac\uba70 \uc791\uc5c5\uc774 \ub2a6\uc5b4\uc9c0\uac70\ub098, \ud1f4\uadfc \ubb34\ub835 \uc313\uc778 \ub9ac\ubdf0 \uc694\uccad\uc5d0 \ubc1c\ubaa9 \uc7a1\ud78c \uacbd\ud5d8\uc774 \uc788\uc73c\uc2e0\uac00\uc694?  \nSelvage\ub294 \uc774\ub7f0 \ucf54\ub4dc \ub9ac\ubdf0 \ubcd1\ubaa9 \ud604\uc0c1\uc744 \ud574\uacb0\ud558\ub294 AI \uae30\ubc18 \ub3c4\uad6c\uc785\ub2c8\ub2e4.\n\nSelvage\ub294 \ucd5c\ucca8\ub2e8 AI \ubaa8\ub378(OpenAI GPT, Anthropic Claude, Google Gemini \ub4f1)\uc744 \ud65c\uc6a9\ud558\uc5ec Git diff\ub97c \ubd84\uc11d\ud558\ub294 \ucee4\ub9e8\ub4dc \ub77c\uc778 \ub3c4\uad6c\uc785\ub2c8\ub2e4.  \nSelvage\uc5d0\uac8c \ucf54\ub4dc \ubcc0\uacbd\uc0ac\ud56d\uc5d0 \ub300\ud55c \ub9ac\ubdf0\ub97c \uc694\uccad\ud558\uba74, AI\uac00 \ucf54\ub4dc\ub97c \ubd84\uc11d\ud558\uc5ec \ud53c\ub4dc\ubc31\uc744 \uc989\uc2dc \uc81c\uacf5\ud569\ub2c8\ub2e4.  \n\uc774\ub97c \ud1b5\ud574 \ucf54\ub4dc \ud488\uc9c8 \ud5a5\uc0c1, \uc7a0\uc7ac\uc801 \ubc84\uadf8 \uc870\uae30 \ubc1c\uacac, \ubcf4\uc548 \uac15\ud654\ub294 \ubb3c\ub860, \uac1c\ubc1c\uc790 \uc0dd\uc0b0\uc131\uae4c\uc9c0 \ud06c\uac8c \ud5a5\uc0c1\uc2dc\ud0ac \uc218 \uc788\uc2b5\ub2c8\ub2e4.\n\n<details>\n<summary><strong>Table of Contents</strong></summary>\n\n- [\u2728 \uc8fc\uc694 \uae30\ub2a5](#-\uc8fc\uc694-\uae30\ub2a5)\n- [\ud83d\ude80 \ube60\ub978 \uc2dc\uc791](#-\ube60\ub978-\uc2dc\uc791)\n  - [\uc124\uce58 \ubc29\ubc95](#\uc124\uce58-\ubc29\ubc95)\n  - [\uc124\uc815](#\uc124\uc815)\n  - [\ub9ac\ubdf0 \uc2e4\ud589\ud558\uae30](#\ub9ac\ubdf0-\uc2e4\ud589\ud558\uae30)\n- [\ud83c\udf10 \uc9c0\uc6d0 \uc5b8\uc5b4 \ubc0f \ubaa8\ub378](#-\uc9c0\uc6d0-\uc5b8\uc5b4-\ubc0f-\ubaa8\ub378)\n  - [\uc9c0\uc6d0 \ud30c\uc77c \ud615\uc2dd](#\uc9c0\uc6d0-\ud30c\uc77c-\ud615\uc2dd)\n  - [\uc9c0\uc6d0 AI \ubaa8\ub378](#\uc9c0\uc6d0-ai-\ubaa8\ub378)\n- [\u2328\ufe0f CLI \uc0ac\uc6a9\ubc95](#\ufe0f-cli-\uc0ac\uc6a9\ubc95)\n  - [Selvage \uc124\uc815\ud558\uae30](#selvage-\uc124\uc815\ud558\uae30)\n  - [\ucf54\ub4dc \ub9ac\ubdf0\ud558\uae30](#\ucf54\ub4dc-\ub9ac\ubdf0\ud558\uae30)\n  - [\uacb0\uacfc \ud655\uc778\ud558\uae30](#\uacb0\uacfc-\ud655\uc778\ud558\uae30)\n- [\ud83d\udcc4 \ucd9c\ub825 \ud615\uc2dd](#-\ucd9c\ub825-\ud615\uc2dd)\n- [\ud83d\udee0\ufe0f \uace0\uae09 \uc0ac\uc6a9\ubc95](#\ufe0f-\uace0\uae09-\uc0ac\uc6a9\ubc95)\n- [\ud83e\udd1d \uae30\uc5ec\ud558\uae30](#-\uae30\uc5ec\ud558\uae30)\n- [\ud83d\udcdc \ub77c\uc774\uc120\uc2a4](#-\ub77c\uc774\uc120\uc2a4)\n- [\ufffd\ufffd \ubb38\uc758 \ubc0f \ucee4\ubba4\ub2c8\ud2f0](#-\ubb38\uc758-\ubc0f-\ucee4\ubba4\ub2c8\ud2f0)\n\n</details>\n\n## \u2728 \uc8fc\uc694 \uae30\ub2a5\n\n- **\ud83e\udd16 \ub2e4\uc591\ud55c AI \ubaa8\ub378 \uc9c0\uc6d0**: OpenAI GPT-4o, Anthropic Claude Sonnet-4, Google Gemini \ub4f1 \ucd5c\uc2e0 LLM \ubaa8\ub378 \ud65c\uc6a9\n- **\ud83d\udd0d Git \uc6cc\ud06c\ud50c\ub85c\uc6b0\uc640 \ud1b5\ud569**: staged, unstaged, \ud2b9\uc815 \ucee4\ubc0b/\ube0c\ub79c\uce58 \uac04 \ubcc0\uacbd\uc0ac\ud56d \ubd84\uc11d \uc9c0\uc6d0\n- **\ud83d\udc1b \ud3ec\uad04\uc801 \ucf54\ub4dc \uac80\ud1a0**: \ubc84\uadf8 \ubc0f \ub17c\ub9ac \uc624\ub958 \ud0d0\uc9c0, \ucf54\ub4dc \ud488\uc9c8 \ubc0f \uac00\ub3c5\uc131 \ud5a5\uc0c1 \uc81c\uc548\n- **\ud83c\udfaf \ucee8\ud14d\uc2a4\ud2b8 \ubd84\uc11d**: \ubcc0\uacbd\uc810\uc774 \ud3ec\ud568\ub41c \uc804\uccb4 \ud30c\uc77c \ub0b4\uc6a9\uc744 \ucc38\uace0\ud558\ub294 \ubd84\uc11d \uae30\ub2a5 \uc81c\uacf5\n- **\ud83d\udcd6 \uc624\ud508\uc18c\uc2a4**: MIT \ub77c\uc774\uc120\uc2a4\ub85c \uc790\uc720\ub86d\uac8c \uc0ac\uc6a9 \ubc0f \uc218\uc815 \uac00\ub2a5\n\n## \ud83d\ude80 \ube60\ub978 \uc2dc\uc791\n\n### \uc124\uce58 \ubc29\ubc95\n\n#### \uae30\ubcf8 \uc124\uce58 (\uc6b4\uc601 \ud658\uacbd)\n\n```bash\n# PyPI\uc5d0\uc11c \uc124\uce58 (\uc815\uc2dd \ucd9c\uc2dc \ud6c4 \uc608\uc815)\npip install selvage\n\n# \ub610\ub294 \uac1c\ubc1c \ubc84\uc804 \uc124\uce58\ngit clone https://github.com/anomie7/selvage.git\ncd selvage\npip install -e .\n```\n\n#### \uac1c\ubc1c \ud658\uacbd \uc124\uce58\n\n```bash\n# \uac1c\ubc1c \uc758\uc874\uc131 \ud3ec\ud568 \uc124\uce58 (pytest, build \ub4f1)\npip install -e .[dev]\n\n# \uac1c\ubc1c + E2E \ud14c\uc2a4\ud2b8 \ud658\uacbd \uc124\uce58 (testcontainers, docker \ub4f1)\npip install -e .[dev,e2e]\n```\n\n### \uc124\uc815\n\n#### 1. API \ud0a4 \uc124\uc815\n\n**\ud658\uacbd \ubcc0\uc218\ub85c \uc124\uc815 (\uad8c\uc7a5)**\n\n\ud130\ubbf8\ub110 \uc138\uc158\uc6a9:\n\n```bash\nexport OPENAI_API_KEY=\"your_openai_api_key_here\"\nexport ANTHROPIC_API_KEY=\"your_anthropic_api_key_here\"\nexport GEMINI_API_KEY=\"your_gemini_api_key_here\"\n```\n\n\uc601\uad6c \uc124\uc815 (zsh \uc0ac\uc6a9\uc790):\n\n```bash\necho 'export OPENAI_API_KEY=\"your_api_key_here\"' >> ~/.zshrc\necho 'export ANTHROPIC_API_KEY=\"your_api_key_here\"' >> ~/.zshrc\necho 'export GEMINI_API_KEY=\"your_api_key_here\"' >> ~/.zshrc\nsource ~/.zshrc\n```\n\n**CLI \uba85\ub839\uc5b4\ub85c \uc124\uc815**\n\n```bash\n# OpenAI API \ud0a4 \uc124\uc815\nselvage --set-openai-key\n\n# Anthropic API \ud0a4 \uc124\uc815\nselvage --set-claude-key\n\n# Gemini API \ud0a4 \uc124\uc815\nselvage --set-gemini-key\n```\n\n#### 2. \uae30\ubcf8 \ubaa8\ub378 \uc124\uc815 (\uc120\ud0dd\uc0ac\ud56d)\n\n```bash\n# \uae30\ubcf8 \uc0ac\uc6a9\ud560 \ubaa8\ub378 \uc124\uc815\nselvage config model claude-sonnet-4-thinking\n\n# \uc124\uc815 \ud655\uc778\nselvage config list\n```\n\n### \ub9ac\ubdf0 \uc2e4\ud589\ud558\uae30\n\n```bash\n# \ud604\uc7ac \uc6cc\ud0b9 \ub514\ub809\ud1a0\ub9ac\uc758 \ubcc0\uacbd\uc0ac\ud56d \ub9ac\ubdf0\nselvage review\n\n# \uc2a4\ud14c\uc774\uc9d5\ub41c \ubcc0\uacbd\uc0ac\ud56d\ub9cc \ub9ac\ubdf0\nselvage review --staged\n\n# \ud2b9\uc815 \ubaa8\ub378\ub85c \ub9ac\ubdf0\nselvage review --model gemini-2.5-pro\n\n# \ub9ac\ubdf0 \ud6c4 \uc790\ub3d9\uc73c\ub85c UI \uc5f4\uae30 (\ud130\ubbf8\ub110 \ucd9c\ub825 \ube44\ud65c\uc131\ud654)\nselvage review --open-ui\n\n# \ud130\ubbf8\ub110\uc5d0 \ucd9c\ub825\ud558\uc9c0 \uc54a\uace0 \ud30c\uc77c\ub85c\ub9cc \uc800\uc7a5\nselvage review --no-print\n```\n\n\ub9ac\ubdf0 \uacb0\uacfc\ub294 \uae30\ubcf8\uc801\uc73c\ub85c \ud130\ubbf8\ub110\uc5d0 \ucd9c\ub825\ub418\uba70 \uc790\ub3d9\uc73c\ub85c \ud30c\uc77c\uc5d0\ub3c4 \uc800\uc7a5\ub429\ub2c8\ub2e4. `--open-ui` \uc635\uc158\uc73c\ub85c UI\ub97c \uc5f4\uac70\ub098 `--no-print` \uc635\uc158\uc73c\ub85c \ud130\ubbf8\ub110 \ucd9c\ub825\uc744 \ube44\ud65c\uc131\ud654\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.\n\n## \ud83c\udf10 \uc9c0\uc6d0 \uc5b8\uc5b4 \ubc0f \ubaa8\ub378\n\n### \uc9c0\uc6d0 \ud30c\uc77c \ud615\uc2dd\n\n- **Python** (`.py`)\n- **JavaScript** (`.js`)\n- **TypeScript** (`.ts`)\n- **Java** (`.java`)\n- **Kotlin** (`.kt`, `.kts`)\n- **Go** (`.go`)\n- **Ruby** (`.rb`)\n- **PHP** (`.php`)\n- **C#** (`.cs`)\n- **C/C++** (`.c`, `.cpp`, `.h`, `.hpp`)\n- **HTML** (`.html`)\n- **CSS/SCSS** (`.css`, `.scss`)\n- **Shell** (`.sh`, `.bash`)\n- **SQL** (`.sql`)\n- **Markdown** (`.md`)\n- **JSON** (`.json`)\n- **YAML** (`.yaml`, `.yml`)\n- **XML** (`.xml`)\n- \uae30\ud0c0 \ud14d\uc2a4\ud2b8 \uae30\ubc18 \ucf54\ub4dc \ud30c\uc77c\n\n### \uc9c0\uc6d0 AI \ubaa8\ub378\n\n#### OpenAI \ubaa8\ub378\n\n- **gpt-4o**: \uace0\uae09 \ucf54\ub4dc \ubd84\uc11d \ubc0f \ud14d\uc2a4\ud2b8 \ucc98\ub9ac \ub2a5\ub825 (128K \ucee8\ud14d\uc2a4\ud2b8)\n- **gpt-4.1**: \ub300\uc6a9\ub7c9 \ucf54\ub4dc\ubca0\uc774\uc2a4 \ubd84\uc11d \uc9c0\uc6d0 (1M+ \ud1a0\ud070 \ucee8\ud14d\uc2a4\ud2b8)\n- **o4-mini-high**: \ub192\uc740 \uc815\ud655\ub3c4\uc758 \ucd94\ub860 \ubaa8\ub378 (200K \ucee8\ud14d\uc2a4\ud2b8)\n- **o4-mini**: \uade0\ud615 \uc7a1\ud78c \ucd94\ub860 \ubaa8\ub378 (\ubcc4\uce6d: o4-mini-medium) (200K \ucee8\ud14d\uc2a4\ud2b8)\n\n#### Anthropic \ubaa8\ub378\n\n- **claude-sonnet-4**: \ud558\uc774\ube0c\ub9ac\ub4dc \ucd94\ub860 \ubaa8\ub378\ub85c \uace0\uae09 \ucf54\ub529 \ucd5c\uc801\ud654 (200K \ucee8\ud14d\uc2a4\ud2b8)\n- **claude-sonnet-4-thinking**: \u2b50 **\ucd94\ucc9c** - \ud655\uc7a5 \uc0ac\uace0 \ud504\ub85c\uc138\uc2a4 \uc9c0\uc6d0 (200K \ucee8\ud14d\uc2a4\ud2b8)\n\n#### Google \ubaa8\ub378\n\n- **gemini-2.5-pro**: \u2b50 **\ucd94\ucc9c** - \ub300\uc6a9\ub7c9 \ucee8\ud14d\uc2a4\ud2b8 \ubc0f \uace0\uae09 \ucd94\ub860 (1M+ \ud1a0\ud070)\n- **gemini-2.5-flash**: \u2b50 **\ucd94\ucc9c** - \uc751\ub2f5 \uc18d\ub3c4\uc640 \ube44\uc6a9 \ud6a8\uc728\uc131 \ucd5c\uc801\ud654 (1M+ \ud1a0\ud070)\n\n## \u2328\ufe0f CLI \uc0ac\uc6a9\ubc95\n\n### Selvage \uc124\uc815\ud558\uae30\n\n```bash\n# \ubaa8\ub4e0 \uc124\uc815 \ubcf4\uae30\nselvage config list\n\n# \uae30\ubcf8 \ubaa8\ub378 \uc124\uc815\nselvage config model <\ubaa8\ub378\uba85>\n\n# \ub514\ubc84\uadf8 \ubaa8\ub4dc \uc124\uc815\nselvage config debug-mode on\n\n# diff-only \uc635\uc158 \uc124\uc815 (\ubcc0\uacbd\ub41c \ubd80\ubd84\ub9cc \ubd84\uc11d)\nselvage config diff-only true\n```\n\n### \ucf54\ub4dc \ub9ac\ubdf0\ud558\uae30\n\n```bash\nselvage review [OPTIONS]\n```\n\n#### \uc8fc\uc694 \uc635\uc158\n\n- `--repo-path <\uacbd\ub85c>`: Git \uc800\uc7a5\uc18c \uacbd\ub85c (\uae30\ubcf8\uac12: \ud604\uc7ac \ub514\ub809\ud1a0\ub9ac)\n- `--staged`: \uc2a4\ud14c\uc774\uc9d5\ub41c \ubcc0\uacbd\uc0ac\ud56d\ub9cc \ub9ac\ubdf0\n- `--target-commit <\ucee4\ubc0bID>`: \ud2b9\uc815 \ucee4\ubc0b\ubd80\ud130 HEAD\uae4c\uc9c0\uc758 \ubcc0\uacbd\uc0ac\ud56d \ub9ac\ubdf0 (\uc608: abc1234)\n- `--target-branch <\ube0c\ub79c\uce58\uba85>`: \ud604\uc7ac \ube0c\ub79c\uce58\uc640 \uc9c0\uc815\ub41c \ube0c\ub79c\uce58 \uac04 \ubcc0\uacbd\uc0ac\ud56d \ub9ac\ubdf0 (\uc608: main)\n- `--model <\ubaa8\ub378\uba85>`: \uc0ac\uc6a9\ud560 AI \ubaa8\ub378 (\uc608: claude-sonnet-4-thinking)\n- `--open-ui`: \ub9ac\ubdf0 \uc644\ub8cc \ud6c4 \uc790\ub3d9\uc73c\ub85c UI \uc2e4\ud589\n- `--no-print`: \ud130\ubbf8\ub110\uc5d0 \ub9ac\ubdf0 \uacb0\uacfc\ub97c \ucd9c\ub825\ud558\uc9c0 \uc54a\uc74c (\uae30\ubcf8\uc801\uc73c\ub85c \ud130\ubbf8\ub110 \ucd9c\ub825 \ud65c\uc131\ud654)\n- `--diff-only`: \ubcc0\uacbd\ub41c \ubd80\ubd84\ub9cc \ubd84\uc11d (\uc804\uccb4 \ud30c\uc77c \ucee8\ud14d\uc2a4\ud2b8 \uc81c\uc678)\n\n#### \uc0ac\uc6a9 \uc608\uc2dc\n\n```bash\n# \ud604\uc7ac \uc6cc\ud0b9 \ub514\ub809\ud1a0\ub9ac \ubcc0\uacbd\uc0ac\ud56d \ub9ac\ubdf0\nselvage review\n\n# \uc2a4\ud14c\uc774\uc9d5\ub41c \ubcc0\uacbd\uc0ac\ud56d\uc744 Claude\ub85c \ub9ac\ubdf0\nselvage review --staged --model claude-sonnet-4-thinking\n\n# \ub9ac\ubdf0 \ud6c4 \ud130\ubbf8\ub110\uc5d0 \ucd9c\ub825\ud558\uc9c0 \uc54a\uc74c (\ud30c\uc77c\ub85c\ub9cc \uc800\uc7a5)\nselvage review --no-print --model gemini-2.5-flash\n\n# main \ube0c\ub79c\uce58\uc640 \ud604\uc7ac \ube0c\ub79c\uce58 \uac04 \ucc28\uc774\uc810 \ub9ac\ubdf0 \ud6c4 UI \uc5f4\uae30\nselvage review --target-branch main --open-ui\n\n# \ud2b9\uc815 \ucee4\ubc0b \uc774\ud6c4 \ubcc0\uacbd\uc0ac\ud56d \ub9ac\ubdf0 (\uae30\ubcf8\uc801\uc73c\ub85c \ud130\ubbf8\ub110 \ucd9c\ub825)\nselvage review --target-commit abc1234 --model gemini-2.5-pro\n```\n\n### \uacb0\uacfc \ud655\uc778\ud558\uae30\n\n```bash\n# \uc800\uc7a5\ub41c \ub9ac\ubdf0 \uacb0\uacfc\ub97c UI\ub85c \ubcf4\uae30\nselvage view\n\n# \ub2e4\ub978 \ud3ec\ud2b8\uc5d0\uc11c UI \uc2e4\ud589\nselvage view --port 8502\n```\n\n**UI \uc8fc\uc694 \uae30\ub2a5:**\n\n- \ud83d\udccb \ubaa8\ub4e0 \ub9ac\ubdf0 \uacb0\uacfc \ubaa9\ub85d \ud45c\uc2dc\n- \ud83c\udfa8 \ub9c8\ud06c\ub2e4\uc6b4 \ud615\uc2dd \ud45c\uc2dc\n- \ud83d\uddc2\ufe0f JSON \uad6c\uc870\ud654\ub41c \uacb0\uacfc \ubcf4\uae30\n\n## \ud83d\udcc4 \ucd9c\ub825 \ud615\uc2dd\n\n<p align=\"center\">\n  <img src=\"assets/demo-ui.png\" width=\"100%\" alt=\"Selvage UI Demo\"/>\n</p>\n\n### Markdown (\uae30\ubcf8\uac12)\n\n- \ud83d\udcd6 \uc0ac\ub78c\uc774 \uc77d\uae30 \ud3b8\ud55c \uae54\ub054\ud55c \uad6c\uc870\n- \ud83d\udcdd \uc694\uc57d, \uc774\uc288 \ubaa9\ub85d, \uac1c\uc120 \uc81c\uc548 \ud3ec\ud568\n- \ud83c\udfaf \uc911\uc694\ub3c4\ubcc4 \uc774\uc288 \ubd84\ub958\n- \ud83d\udca1 \uc2e4\ud589 \uac00\ub2a5\ud55c \uac1c\uc120 \ubc29\uc548 \uc81c\uc2dc\n\n### JSON\n\n- \ud83d\udd27 \ud504\ub85c\uadf8\ub798\ubc0d \ubc29\uc2dd\uc73c\ub85c \ucc98\ub9ac \uc6a9\uc774\n- \u2699\ufe0f \uad6c\uc870\ud654\ub41c \ub370\uc774\ud130 \ud615\uc2dd\n- \ud83d\udd17 \ub2e4\ub978 \ub3c4\uad6c\uc640\uc758 \ud1b5\ud569\uc5d0 \uc720\uc6a9\n- \ud83d\udcca \uc790\ub3d9\ud654 \ud30c\uc774\ud504\ub77c\uc778\uc5d0 \uc801\ud569\n\n## \ud83d\udee0\ufe0f \uace0\uae09 \uc0ac\uc6a9\ubc95\n\n### \ubaa8\ub378\ubcc4 \ucd5c\uc801 \uc0ac\uc6a9 \uc2dc\ub098\ub9ac\uc624\n\n```bash\n# \ubcf5\uc7a1\ud55c \ub85c\uc9c1 \ubd84\uc11d - Claude \ucd94\ucc9c\nselvage review --model claude-sonnet-4-thinking\n\n# \ub300\uc6a9\ub7c9 \ucf54\ub4dc\ubca0\uc774\uc2a4 - Gemini \ucd94\ucc9c\nselvage review --model gemini-2.5-pro\n\n# \ube60\ub978 \ub9ac\ubdf0 - Gemini Flash \ucd94\ucc9c\nselvage review --model gemini-2.5-flash\n```\n\n### \ub2e4\uc591\ud55c Git \uc6cc\ud06c\ud50c\ub85c\uc6b0\uc640 \ud1b5\ud569\n\n```bash\n# PR \ub9ac\ubdf0 \uc804 \uccb4\ud06c\nselvage review --target-branch main\n\n# \ucee4\ubc0b \uc804 \ucd5c\uc885 \uac80\ud1a0\nselvage review --staged --open-ui\n\n# \ud2b9\uc815 \uae30\ub2a5 \ube0c\ub79c\uce58 \uc804\uccb4 \ub9ac\ubdf0\nselvage review --target-branch develop\n```\n\n### \ube44\uc6a9 \ucd5c\uc801\ud654\n\n```bash\n# \ubcc0\uacbd \ubd80\ubd84\ub9cc \ubd84\uc11d\ud558\uc5ec \ud1a0\ud070 \uc808\uc57d\nselvage review --diff-only\n\n# \uc791\uc740 \ubcc0\uacbd\uc0ac\ud56d\uc5d0\ub294 \uacbd\uc81c\uc801\uc778 \ubaa8\ub378 \uc0ac\uc6a9\nselvage review --model gemini-2.5-flash\n```\n\n## \ud83e\udd1d \uae30\uc5ec\ud558\uae30\n\nSelvage\ub294 \uc624\ud508\uc18c\uc2a4 \ud504\ub85c\uc81d\ud2b8\uc774\uba70, \uc5ec\ub7ec\ubd84\uc758 \uae30\uc5ec\ub97c \uc5b8\uc81c\ub098 \ud658\uc601\ud569\ub2c8\ub2e4! \ubc84\uadf8 \ub9ac\ud3ec\ud2b8, \uae30\ub2a5 \uc81c\uc548, \ubb38\uc11c \uac1c\uc120, \ucf54\ub4dc \uae30\uc5ec \ub4f1 \uc5b4\ub5a4 \ud615\ud0dc\uc758 \uae30\uc5ec\ub4e0 \uc88b\uc2b5\ub2c8\ub2e4.\n\n**\uae30\uc5ec \ubc29\ubc95:**\n\n- \ud83d\udc1b [GitHub Issues](https://github.com/anomie7/selvage/issues)\uc5d0\uc11c \ubc84\uadf8 \ub9ac\ud3ec\ud2b8 \ub610\ub294 \uae30\ub2a5 \uc81c\uc548\n- \ud83d\udd27 Pull Request\ub97c \ud1b5\ud55c \ucf54\ub4dc \uae30\uc5ec\n- \ud83d\udcda \ubb38\uc11c \uac1c\uc120 \ubc0f \ubc88\uc5ed\n\n**\uc0c1\uc138\ud55c \uae30\uc5ec \uac00\uc774\ub4dc\ub77c\uc778\uc740 [CONTRIBUTING.md](CONTRIBUTING.md)\uc5d0\uc11c \ud655\uc778\ud558\uc2e4 \uc218 \uc788\uc2b5\ub2c8\ub2e4.**\n\n## \ud83d\udcdc \ub77c\uc774\uc120\uc2a4\n\nSelvage\ub294 [MIT License](LICENSE) \ud558\uc5d0 \ubc30\ud3ec\ub429\ub2c8\ub2e4. \uc774 \ub77c\uc774\uc120\uc2a4\ub294 \uc0c1\uc5c5\uc801 \uc774\uc6a9, \uc218\uc815, \ubc30\ud3ec\ub97c \ud5c8\uc6a9\ud558\uba70, \ub77c\uc774\uc120\uc2a4 \ubc0f \uc800\uc791\uad8c \uace0\uc9c0\ub97c \ud3ec\ud568\ud558\ub294 \ud55c \uc790\uc720\ub86d\uac8c \uc0ac\uc6a9\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.\n\n## \ud83d\udcde \ubb38\uc758 \ubc0f \ucee4\ubba4\ub2c8\ud2f0\n\n- **\ud83d\udc1b \ubc84\uadf8 \ub9ac\ud3ec\ud2b8 \ubc0f \uae30\ub2a5 \uc694\uccad**: [GitHub Issues](https://github.com/anomie7/selvage/issues)\n- **\ud83d\udce7 \uc9c1\uc811 \ubb38\uc758**: anomie7777@gmail.com\n\n---\n\n<p align=\"center\">\n  <strong>Selvage\uc640 \ud568\uaed8 \ub354 \ub098\uc740 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc138\uc694! \ud83d\ude80</strong><br>\n  \u2b50 \ud504\ub85c\uc81d\ud2b8\uac00 \ub3c4\uc6c0\uc774 \ub418\uc168\ub2e4\uba74 GitHub\uc5d0\uc11c Star\ub97c \ub20c\ub7ec\uc8fc\uc138\uc694!\n</p>\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "LLM \uae30\ubc18 \ucf54\ub4dc \ub9ac\ubdf0 \ub3c4\uad6c",
    "version": "0.1.2",
    "project_urls": {
        "Bug Tracker": "https://github.com/anomie7/selvage//issues",
        "Documentation": "https://github.com/anomie7/selvage/#readme",
        "Homepage": "https://github.com/anomie7/selvage/",
        "Repository": "https://github.com/anomie7/selvage/"
    },
    "split_keywords": [
        "code-review",
        " llm",
        " ai",
        " git",
        " cli",
        " python"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "327ec6d1b2f1c395a96b0b2dac38d6d56c8c230cdccc4fec9dcf758e468f5e38",
                "md5": "a13ac0636fd6c847f75e8415e2364454",
                "sha256": "dac49a090786359c89b5edafd5e529f43ce09509c1a71a3bf0967341d90debe0"
            },
            "downloads": -1,
            "filename": "selvage-0.1.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "a13ac0636fd6c847f75e8415e2364454",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 99258,
            "upload_time": "2025-07-17T08:30:35",
            "upload_time_iso_8601": "2025-07-17T08:30:35.713870Z",
            "url": "https://files.pythonhosted.org/packages/32/7e/c6d1b2f1c395a96b0b2dac38d6d56c8c230cdccc4fec9dcf758e468f5e38/selvage-0.1.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "6ba983410ae69e059f1b319c5db034e09f7ca3f146260c6759bf5177c982d1a3",
                "md5": "08186f62fd4ed22af029f44a1779a267",
                "sha256": "7ef0189884ff03abb8b81c2ab9b246f0750b80840d8f796617d7f0147694fefd"
            },
            "downloads": -1,
            "filename": "selvage-0.1.2.tar.gz",
            "has_sig": false,
            "md5_digest": "08186f62fd4ed22af029f44a1779a267",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 101875,
            "upload_time": "2025-07-17T08:30:37",
            "upload_time_iso_8601": "2025-07-17T08:30:37.045940Z",
            "url": "https://files.pythonhosted.org/packages/6b/a9/83410ae69e059f1b319c5db034e09f7ca3f146260c6759bf5177c982d1a3/selvage-0.1.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-17 08:30:37",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "anomie7",
    "github_project": "selvage",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "selvage"
}
        
Elapsed time: 0.48936s