feat: Gemini CLI Extension 전역 설치 지원

한 줄 요약
Claude Code·Codex CLI에 이어 Gemini CLI(Antigravity)에서도 전역 설치 후
/humanize-korean 커맨드로 한글 AI 티 제거 윤문을 사용할 수 있게 패키징.

변경 내용

- gemini-extension.json: Gemini CLI Extension 매니페스트 신규
- GEMINI.md: 에이전트 컨텍스트 — monolith 룰 + quick-rules 인라인
- commands/humanize-korean.toml: /humanize-korean 커스텀 명령
- commands/humanize.toml: /humanize 별칭 명령
- commands/humanize-redo.toml: /humanize-redo 2차 윤문 명령
- install.sh: gemini CLI 자동 감지 + extensions link 블록 추가
  --gemini-only / --no-gemini 옵션 추가
- uninstall.sh: gemini extensions uninstall 블록 추가
- update.sh: ver() 함수에 gemini-extension.json fallback
- INSTALL.md: Gemini CLI 섹션 + 도구 표 갱신
- CLAUDE.md: 디렉토리 구조에 Gemini 파일 반영

설치: gemini extensions install https://github.com/epoko77-ai/im-not-ai.git
또는: git clone ... && ./install.sh --gemini-only
Gemini는 Codex와 동일하게 Fast(단일 호출) 모드만 제공.
strict 5인 파이프라인은 Claude Code 전용.
This commit is contained in:
dlskawns96 2026-06-09 10:19:56 +09:00
commit d83ecf2255
10 changed files with 319 additions and 12 deletions

View file

@ -20,7 +20,10 @@ im-not-ai/
├── .claude-plugin/ # Claude 플러그인 + 마켓플레이스 매니페스트
│ ├── plugin.json # skills: ./.claude/skills/ · 에이전트는 루트 agents/ 자동탐색
│ └── marketplace.json # /plugin marketplace add epoko77-ai/im-not-ai
├── install.sh / uninstall.sh # Claude·Codex 전역 설치/제거 (심링크 기본)
├── gemini-extension.json # Gemini CLI Extension 매니페스트
├── GEMINI.md # Gemini 에이전트 컨텍스트 (monolith 룰 인라인)
├── commands/ # Gemini CLI 커스텀 명령 (/humanize-korean, /humanize, /humanize-redo)
├── install.sh / uninstall.sh # Claude·Codex·Gemini 전역 설치/제거 (심링크 기본)
├── agents/ # 서브에이전트 12종 (플러그인 컨벤션 — 루트 agents/에 둬야 로드됨)
│ ├── humanize-monolith.md # Fast 단일 호출
│ ├── ai-tell-detector.md · korean-style-rewriter.md

179
GEMINI.md Normal file
View file

@ -0,0 +1,179 @@
# Humanize KR — AI 한글 티 제거 (Gemini CLI Extension)
> **v1.5 · Fast(monolith) 모드 전용** — Gemini CLI에서 한 번의 대화로 탐지·윤문·자체검증을 일괄 처리합니다.
> 정밀 strict 5인 파이프라인은 Claude Code 전용입니다.
## 개요
AI(ChatGPT·Claude·Gemini 등)가 쓴 한글 텍스트를 "사람이 쓴 글처럼" 윤문합니다.
번역투·영어 인용 과다·기계적 병렬·관용구·피동태 남용·접속사 남발·리듬 균일성·이모지/불릿 과다 등
**10대 카테고리 40+ AI 티 패턴**을 탐지·분류해 **내용은 한 글자도 건드리지 않고** 문체·리듬·표현만 재작성합니다.
## 커스텀 명령
- `/humanize-korean [텍스트]` — 메인 윤문 명령
- `/humanize [텍스트]``/humanize-korean`과 동일
- `/humanize-redo [조정 지시]` — 2차 윤문 / 부분 재실행
자연어 트리거도 동작합니다: "이 글 AI 티 없애줘", "AI 윤문", "ChatGPT 티 제거", "번역투 고쳐", "사람이 쓴 것처럼".
## 철칙 (위반 시 즉시 롤백)
1. **의미 불변 (Fidelity First)** — 사실·주장·수치·고유명사·인용은 100% 원문 보존.
2. **근거 기반 (Span-Grounded)** — 아래 패턴 목록에 매핑되지 않는 구간은 건드리지 않음.
3. **장르 유지 (Tone Match)** — 칼럼을 문학으로, 리포트를 에세이로 옮기지 않음.
4. **register 보존** — 원문 격식체면 결과도 격식체. AI 티는 문법·수사이지 격식 자체가 아님.
5. **과윤문 금지** — 변경률 30% 초과 시 경고, 50% 초과 시 강제 중단.
## Do-NOT (탐지·윤문 모두 제외)
고유명사·제품명·모델명·기관명, 수치·날짜·단위, 큰따옴표 안 직접 인용, 법률 조문,
수학·화학·통계 표기, 영어 약어(LLM·GPU·MCP·API 등 업계 표준).
## 절차
1. **입력 확보**: 사용자가 붙여넣은 텍스트를 원문으로 한다. 파일 경로(.txt/.md)면 그 파일을 읽는다.
2. **장르 추정**: 첫 300자로 장르 추정(사용자 명시 시 우선). 칼럼 | 리포트 | 블로그 | 공적.
3. **탐지**: 아래 A~J 카테고리 패턴을 스캔해 (ID, span, severity, fix) 수집. Do-NOT span은 제외.
4. **윤문**: D(관용구 삭제) → A → I → G → H → F → B → C·J → E 순서로 문단 단위 처리.
5. **자체검증**: 아래 체크리스트 6항 점검. 위반 시 해당 edit 롤백 → 부분 재실행(최대 1회).
6. **출력**: 윤문본 + 메트릭 요약 반환.
## 응답 형식
사용자에게 4가지 반환:
1. 한 줄 상태: `완료. 변경률 X% / 등급 Y / 자체검증 N/6 통과`
2. 윤문본 본문 (마크다운 블록)
3. 카테고리별 탐지 건수 before/after + 주요 변경 하이라이트 3~5건
4. 등급 B 이하면 "정밀 검증이 필요하면 Claude Code의 strict 5인 파이프라인 권장" 안내
## 옵션 (인자 끝에 자연어로)
- `장르: 칼럼|리포트|블로그|공적` — 장르 명시 (생략 시 자동 추정)
- `강도: 보수|기본|적극` — 윤문 강도 (기본값: 기본)
- `최소심각도: S1|S2|S3` — 탐지 임계값 (기본값: S2)
---
## AI 티 패턴 목록 (Quick Rules)
### A. 번역투 (Translation-ese)
| ID | 패턴 | 심각도 | 처방 |
|---|---|---|---|
| A-1 | "~에 대해(서)" | S1 | 목적격 조사로 직결("X에 대해 논의" → "X를 논의") |
| A-2 | "~를 통해/통하여" 남발 | S1 | "~로", "~해서", "~함으로써"로 분산 |
| A-3 | "~에 있어(서)" | S1 | "~에서", "~을 볼 때" |
| A-4 | "~라는 점에서" 3회+ | S2 | "~서", "~라는 이유로" |
| A-5 | "~와 관련하여/관련된" | S2 | "~에", "~의" |
| A-6 | "~에 기반하여/바탕으로" 남발 | S2 | "~로", "~을 보고" |
| A-7 | "가지고 있다" / have·make·take·give + N 직역 | S1 | 형용사·동사 환원 |
| A-8 | 이중 피동 "~되어진다" | S1 | 능동 또는 단일 피동 |
| A-9 | "~에 의해" 피동 | S2 | 행위자를 주어로 |
| A-10 | "~할 수 있다" 남발 | S2 | 단언으로 |
| A-11 | "~을 위해" 목적절 남발 | S2 | "~려고", "~위한" |
| A-15 | 추상 주어 + 만능 동사 | S2 | 구체 주어로 환원 |
| A-16 | "그/그녀/그것/그들" 단락 ≥3회 | S1 | 영형(생략) 또는 호칭·명사구 |
| A-18 | 명사 앞 ≥3어절 관형구 | S2 | 문장 분리 또는 후치 동격절 |
| A-19 | 이중 조사 "~에서의/~에로의" | S2 | 절·구로 풀어쓰기 |
### B. 영어 인용·용어 과다
| ID | 패턴 | 심각도 | 처방 |
|---|---|---|---|
| B-1 | 한글 + 괄호 영어 매번 | S2 | 첫 등장만 병기, 이후 한글만 |
| B-2 | 영어 어휘 직역 가능한데 그대로 | S2 | 한국어로 옮기되 업계 표준은 유지 |
### C. 구조적 AI 패턴
| ID | 패턴 | 심각도 | 처방 |
|---|---|---|---|
| C-5 | 이모지 남발 | S1 | 장르 칼럼·리포트면 전부 삭제 |
| C-7 | "먼저·반면·결국" 3단 공식 | S2 | 접속사 1~2개로 줄이거나 제거 |
| C-8 | "A인가·B인가" 대구 반복 | S2 | 한 번만 살리고 나머지 평서문 |
| C-9 | 숫자 괄호 인덱싱 "(1)·(2)·(3)" | S2 | 본문에 녹이거나 단순 줄바꿈 |
| C-10 | 콜론 부제 헤딩 "X: Y" 반복 | S1 | 헤딩 짧게 또는 평서 헤딩 |
| C-11 | 연결어미 뒤 쉼표 | S1 | 쉼표 제거 |
### D. AI 특유 관용구 (Signature Phrases)
| ID | 패턴 | 심각도 | 처방 |
|---|---|---|---|
| D-1 | 결산 피벗 lexicon "결론적으로/따라서/이를 통해" | S1 | 3회 초과 시 1~2건 치환, 나머지 삭제 |
| D-2 | "시사하는 바가 크다/주목할 만하다" | S1 | 삭제 또는 구체 결론 |
| D-3 | "본질적으로/핵심적으로" | S1 | 삭제 |
| D-4 | hype 어휘(파격적·압도적·강력한·획기적) 3회+ | S1 | 구체 수치·사실로 환원 |
| D-5 | 의인화 추상 주어 | S1 | 사람·기관 주어로 |
| D-6 | 결말 공식 "~할 때다/~해야 한다/~지금이야말로" | S1 | 평서로 닫거나 삭제 |
| D-7 | 변환 공식 "X에서 Y로" 반복 | S2 | 한 번만, 나머지 일반 서술 |
### E. 리듬·종결어미
| ID | 패턴 | 심각도 | 처방 |
|---|---|---|---|
| E-1 | 문장 길이 균일(stdev 8 미만) | S2 | 단문·장문 의도적 삽입 |
| E-2 | 동일 종결어미 "~다" 4문장 연속 | S2 | 다양화 |
### F. 과도한 수식·중복
| ID | 패턴 | 심각도 | 처방 |
|---|---|---|---|
| F-4 | 한자어 명사화 -성/-적/-화 누적 12회+ | S2 | 동사·형용사 어근 환원 |
| F-5 | "~적 N" 추상 체인 | S2 | 풀어쓰기 |
### G. Hedging
| ID | 패턴 | 심각도 | 처방 |
|---|---|---|---|
| G-1 | "~것이다/~할 것이다" 남발 | S2 | 현재형·확정형 |
| G-2 | "~로 보인다/~인 듯하다" 남발 | S2 | 단언 가능한 곳은 단언 |
| G-3 | 안전 균형 lexicon 4회 초과 | S2 | 1~2건 화자 입장으로 치환 |
### H. 접속사 남발
| ID | 패턴 | 심각도 | 처방 |
|---|---|---|---|
| H-1 | 문두 접속사 "또한·따라서·즉·나아가" 5회+ | S1 | 대량 제거 |
| H-3 | 메타 진입 "이는·이 점에서" 3회+ | S1 | 본문에 녹이거나 삭제 |
| H-4 | "즉" 남발 | S2 | 1회로 제한 |
### I. 형식명사·의존명사
| ID | 패턴 | 심각도 | 처방 |
|---|---|---|---|
| I-1 | "~인 것이다/~한 것이다" 결말 | S1 | 평서형 |
| I-2 | "X은 ~라는 점에 있다" | S2 | 직설 |
| I-3 | "~다는 뜻이다/~다는 의미다" 결말 | S2 | 풀어 쓰기 |
| I-4 | 권고형 결말 "~해야 한다" 반복 | S2 | 평서·단언 |
### J. 시각 장식
| ID | 패턴 | 심각도 | 처방 |
|---|---|---|---|
| J-1 | 헤딩 마크다운 ** 강조 남발 | S2 | 거의 다 제거 |
| J-2 | 따옴표 강조 5회+ | S1 | 핵심 한두 개만 |
| J-3 | 불릿 리스트 (칼럼·리포트 장르) | S2 | 문단 산문으로 통합 |
---
## 자체검증 체크리스트 (윤문 후 자가 점검)
1. **고유명사·수치·날짜·인용 100% 보존**: 원문 대비 한 글자도 다르지 않은가
2. **변경률**: 30% 이하인가 (50% 초과는 작업 중단)
3. **장르 이탈 없음**: 칼럼이 에세이·문학으로 변하지 않았는가
4. **register 보존**: 원문 격식체면 결과도 격식체
5. **잔존 S1 패턴 0건**: D-1~D-7, A-7, A-8, A-16, C-5, C-10, C-11, H-1, I-1, J-2 핵심 S1이 남아있지 않은가
6. **인공 표현 자제**: 원문에 없던 비유·수사·문학적 표현을 임의로 추가하지 않았는가
## 등급 기준
- **A**: S1 잔존 0, S2 잔존 2 이하, 변경률 10~25%, 자체검증 6항 모두 통과
- **B**: S1 잔존 0, S2 잔존 4 이하, 자체검증 5항 이상 통과
- **C**: S1 잔존 1~2 또는 자체검증 4항 이하 통과 — strict 모드 권고
- **D**: S1 잔존 3+ 또는 변경률 50% 초과 — 작업 중단 권고
## 참고 자료
- 분류 체계 본진: `.claude/skills/humanize-korean/references/ai-tell-taxonomy.md`
- 윤문 처방: `.claude/skills/humanize-korean/references/rewriting-playbook.md`
- 슬림 룰북: `.claude/skills/humanize-korean/references/quick-rules.md`

View file

@ -1,13 +1,14 @@
# 설치 가이드 (Install)
Humanize KR은 **Claude Code**와 **OpenAI Codex CLI** 양쪽에서 전역으로 쓸 수 있습니다.
Humanize KR은 **Claude Code**와 **OpenAI Codex CLI**, **Gemini CLI(Antigravity)** 에서 전역으로 쓸 수 있습니다.
| 도구 | 모드 | 설치 방법 |
|---|---|---|
| Claude Code | Fast + strict(5인 파이프라인) | ① 플러그인 마켓플레이스(권장) / ② 클론 + `install.sh` |
| Codex CLI | Fast(단일 호출)만 | 클론 + `install.sh` |
| Gemini CLI | Fast(단일 호출)만 | ① `gemini extensions install`(권장) / ② 클론 + `install.sh` |
> Codex는 Claude식 다중 서브에이전트 파이프라인을 결정적으로 실행하지 못해, 단일 호출 Fast Path만 제공합니다. 정밀 검증이 필요하면 Claude Code의 `--strict`를 사용하세요.
> Codex와 Gemini는 Claude식 다중 서브에이전트 파이프라인을 결정적으로 실행하지 못해, 단일 호출 Fast Path만 제공합니다. 정밀 검증이 필요하면 Claude Code의 `--strict`를 사용하세요.
---
@ -53,21 +54,22 @@ cd im-not-ai
---
## 한 번에 양쪽 모두
## 한 번에 양쪽 모두 (Claude + Codex + Gemini)
```bash
git clone https://github.com/epoko77-ai/im-not-ai.git
cd im-not-ai
./install.sh # 설치된 claude/codex를 자동 감지해 각각 연결
./install.sh # 설치된 claude/codex/gemini를 자동 감지해 각각 연결
```
### `install.sh` 옵션
| 옵션 | 설명 |
|---|---|
| (없음) | `claude`·`codex` 자동 감지 후 각각 설치 (심링크) |
| (없음) | `claude`·`codex`·`gemini` 자동 감지 후 각각 설치 (심링크) |
| `--copy` | 심링크 대신 복사. 저장소를 지워도 유지(references 심링크는 실체화). ⚠ 복사본은 `uninstall.sh`가 자동 삭제하지 않음 |
| `--claude-only` / `--codex-only` | 한쪽만 |
| `--claude-only` / `--codex-only` / `--gemini-only` | 한쪽만 |
| `--no-gemini` | Gemini 건너뜀 (Claude/Codex만) |
| `--force` | 대상에 일반 파일/디렉토리가 있어도 `.bak.<ts>`로 백업 후 덮어씀 |
| `--dry-run` | 실제 변경 없이 수행할 작업만 출력 |
| `-h`, `--help` | 도움말 |
@ -108,4 +110,33 @@ cd im-not-ai
- Claude Code: 마켓플레이스/플러그인 지원 버전(`claude plugin` 명령 사용 가능).
- Codex CLI: 0.121.0 이상(`~/.codex/skills` Skills 지원).
- Gemini CLI: 0.14.0 이상(`gemini extensions` 명령 사용 가능).
- macOS·Linux의 `bash`. (Windows는 WSL 권장 — 심링크 때문에.)
---
## Gemini CLI (Antigravity)
Gemini CLI 0.14.0 이상이 필요합니다.
### 방법 ① 원격 설치 — 클론 불필요 (권장)
```bash
gemini extensions install https://github.com/epoko77-ai/im-not-ai.git
```
- 설치 후 새 세션에서 `/humanize-korean`(또는 `/humanize`), 혹은 자연어 트리거("이 글 AI 티 없애줘")로 발동.
- 업데이트: `gemini extensions update im-not-ai`.
- 제거: `gemini extensions uninstall im-not-ai`.
### 방법 ② 클론 + 스크립트
```bash
git clone https://github.com/epoko77-ai/im-not-ai.git
cd im-not-ai
./install.sh --gemini-only
```
`gemini extensions link`로 저장소를 직접 링크합니다(저장소 수정 시 즉시 반영). 새 세션에서 `/humanize-korean`.
> Gemini는 **Fast(단일 호출) 모드만** 제공합니다. 정밀 strict 5인 파이프라인은 Claude Code 전용.

View file

@ -0,0 +1,17 @@
prompt = """
GEMINI.md Humanize Korean .
:
1. 300 ( | | | ).
2. A~J (S1·S2) . Do-NOT .
3. D() A() I() G(hedging) H() F() B( ) C·J(·) E() .
4. 6 . edit ( 1).
5. :
- : `. X% / Y / N/6 `
- ( )
- before/after + 3~5
- B "정밀 검증이 필요하면 Claude Code의 strict 5인 파이프라인 권장"
:
{{args}}
"""

View file

@ -0,0 +1,19 @@
prompt = """
2 .
:
{{args}}
:
1. (cwd) `_workspace/` `final.md`( `01_input.txt`) run_id . "이전 실행이 없습니다. /humanize-korean으로 시작하세요" .
2. :
- ("번역투만", "관용구만") finding
- ("이 문단만") finding
- ("강도 낮춰" S1, "강도 높여" S1+S2+S3)
- finding round 2
3. GEMINI.md Humanize Korean .
4. 6 .
5. ( + ).
round 3. .
"""

18
commands/humanize.toml Normal file
View file

@ -0,0 +1,18 @@
prompt = """
GEMINI.md Humanize Korean .
/humanize-korean .
:
1. 300 ( | | | ).
2. A~J (S1·S2) . Do-NOT .
3. D() A() I() G(hedging) H() F() B( ) C·J(·) E() .
4. 6 . edit ( 1).
5. :
- : `. X% / Y / N/6 `
- ( )
- before/after + 3~5
- B "정밀 검증이 필요하면 Claude Code의 strict 5인 파이프라인 권장"
:
{{args}}
"""

5
gemini-extension.json Normal file
View file

@ -0,0 +1,5 @@
{
"name": "im-not-ai",
"version": "1.5.0",
"description": "AI가 쓴 한글 텍스트를 사람이 쓴 글처럼 윤문 — Fast(monolith) 모드. 10대 카테고리 40+ AI 티 패턴 탐지·재작성. Gemini CLI Extension."
}

View file

@ -1,6 +1,6 @@
#!/usr/bin/env bash
# Humanize KR — Claude Code + Codex CLI 전역 설치 스크립트
# 저장소를 클론한 뒤 `./install.sh` 한 번이면 설치된 CLI(claude/codex)를 자동 감지해
# Humanize KR — Claude Code + Codex CLI + Gemini CLI 전역 설치 스크립트
# 저장소를 클론한 뒤 `./install.sh` 한 번이면 설치된 CLI(claude/codex/gemini)를 자동 감지해
# humanize-korean 스킬(+ 에이전트)을 전역으로 연결한다. 기본은 심링크(저장소 수정 즉시 반영).
set -euo pipefail
@ -11,6 +11,7 @@ CODEX_HOME="${CODEX_HOME:-$HOME/.codex}"
MODE=symlink # symlink | copy
DO_CLAUDE=auto # auto | yes | no
DO_CODEX=auto
DO_GEMINI=auto
FORCE=0
DRYRUN=0
TS="$(date +%Y%m%d-%H%M%S)"
@ -22,12 +23,15 @@ Usage: ./install.sh [options]
설치된 CLI를 자동 감지해 humanize-korean 스킬을 전역 설치한다.
Claude: ~/.claude/skills/{humanize-korean,humanize,humanize-redo} + ~/.claude/agents/*.md
Codex : ~/.codex/skills/humanize-korean
Gemini: gemini extensions link (gemini-extension.json + GEMINI.md + commands/)
Options:
--copy 심링크 대신 복사(저장소를 지워도 유지, references 심링크는 실체화).
※ 복사본은 uninstall.sh가 자동 삭제하지 않음(수동 삭제).
--claude-only Claude만 설치
--codex-only Codex만 설치
--gemini-only Gemini만 설치
--no-gemini Gemini 건너뜀 (claude/codex만)
--force 대상에 일반 파일/디렉토리가 있어도 .bak.<ts> 백업 후 덮어씀
--dry-run 실제 변경 없이 수행할 작업만 출력
-h, --help 이 도움말
@ -39,8 +43,10 @@ H
while [ $# -gt 0 ]; do
case "$1" in
--copy) MODE=copy ;;
--claude-only) DO_CODEX=no ;;
--codex-only) DO_CLAUDE=no ;;
--claude-only) DO_CODEX=no; DO_GEMINI=no ;;
--codex-only) DO_CLAUDE=no; DO_GEMINI=no ;;
--gemini-only) DO_CLAUDE=no; DO_CODEX=no; DO_GEMINI=yes ;;
--no-gemini) DO_GEMINI=no ;;
--force) FORCE=1 ;;
--dry-run) DRYRUN=1 ;;
-h|--help) print_help; exit 0 ;;
@ -105,9 +111,24 @@ else
echo "== Codex CLI: 건너뜀 (codex 미감지 — 강제하려면 --codex-only) =="
fi
# ---- Gemini CLI ----
if [ "$DO_GEMINI" != no ] && { [ "$DO_GEMINI" = yes ] || command -v gemini >/dev/null 2>&1; }; then
echo "== Gemini CLI =="
if [ "$DRYRUN" = 1 ]; then
echo "+ gemini extensions link $REPO (dry-run)"
else
echo "gemini extensions link \"$REPO\" 실행 (확장 등록)..."
echo "Y" | gemini extensions link "$REPO" 2>/dev/null && echo "installed: Gemini extension (im-not-ai)" \
|| echo " (이미 등록됨 또는 수동 등록 필요: gemini extensions link $REPO)"
fi
else
echo "== Gemini CLI: 건너뜀 (gemini 미감지 — 강제하려면 --gemini-only) =="
fi
echo ""
echo "완료 (mode=$MODE)."
echo " Claude: 새 세션에서 /humanize-korean (또는 /humanize)"
echo " Codex : \$humanize-korean"
echo " Gemini: 새 세션에서 /humanize-korean (또는 /humanize)"
echo " 업데이트: ./update.sh (새 버전 자동 감지 + 적용) · 제거: ./uninstall.sh"
exit 0

View file

@ -33,4 +33,15 @@ for a in "$REPO/agents"/*.md; do
remove_if_ours "$CLAUDE_HOME/agents/$(basename "$a")" "$a"
done
# ---- Gemini CLI ----
if command -v gemini >/dev/null 2>&1; then
echo "Gemini extension 제거 시도..."
if [ "$DRYRUN" = 1 ]; then
echo "+ gemini extensions uninstall im-not-ai (dry-run)"
else
gemini extensions uninstall im-not-ai 2>/dev/null && echo "removed: Gemini extension (im-not-ai)" \
|| echo " (Gemini extension 미설치 또는 이미 제거됨)"
fi
fi
echo "제거 완료. (.bak.* 백업·--copy 설치본은 보존)"

View file

@ -28,7 +28,10 @@ done
g rev-parse --is-inside-work-tree >/dev/null 2>&1 || { echo "git 저장소가 아닙니다: $REPO"; exit 2; }
ver() { grep -o '"version"[[:space:]]*:[[:space:]]*"[^"]*"' "$REPO/.claude-plugin/plugin.json" 2>/dev/null \
| head -1 | grep -o '[0-9][0-9.]*' || echo "?"; }
| head -1 | grep -o '[0-9][0-9.]*' \
|| grep -o '"version"[[:space:]]*:[[:space:]]*"[^"]*"' "$REPO/gemini-extension.json" 2>/dev/null \
| head -1 | grep -o '[0-9][0-9.]*' \
|| echo "?"; }
UPSTREAM="$(g rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null || echo origin/main)"
UP_REMOTE="${UPSTREAM%%/*}"