@mcgrapeng/ccg 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +119 -0
- package/LICENSE +21 -0
- package/README.ja.md +220 -0
- package/README.ko.md +219 -0
- package/README.md +220 -0
- package/README.zh-CN.md +219 -0
- package/bin/ccg.js +391 -0
- package/ccg.md +303 -0
- package/ccg.sh +928 -0
- package/package.json +54 -0
- package/scripts/curl-install.sh +97 -0
- package/scripts/install.sh +55 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to /ccg.
|
|
4
|
+
|
|
5
|
+
## [3.1.0] — 2026-05-23
|
|
6
|
+
|
|
7
|
+
Documentation and discoverability release. No core behavior changes; safe drop-in upgrade from 3.0.0.
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- **`ccg about` subcommand** — 7-layer capability probe. Shows what ccg can do in *this* environment (not what the README claims), with green/yellow/red status per layer, environment readiness checks (Codex CLI / Gemini CLI / GEMINI_API_KEY / git / slash command installation), XDG storage state (ledger entries, usage entries, cache size), and a quick-reference command palette.
|
|
11
|
+
- Aliases: `ccg capabilities`, `ccg caps`
|
|
12
|
+
- Use case: "I'm a new user / contributor — what is ccg actually doing on my machine right now?"
|
|
13
|
+
- **`docs/ARCHITECTURE.md`** — 387-line engineering reference for contributors and integrators. Documents the 7-layer architecture (L1 Safe CLI scheduling → L7 Divergence synthesis), each layer's purpose / problem / solution / "what breaks if you remove it", end-to-end data flow, extension points (signed contract for new risk rules / new LLM providers / new storage paths / pricing customization), invariants enforced by the test suite, and load-bearing design decisions that look weird at first glance.
|
|
14
|
+
- **4-language ARCHITECTURE translations**: `docs/ARCHITECTURE.zh-CN.md`, `docs/ARCHITECTURE.ja.md`, `docs/ARCHITECTURE.ko.md`. Cross-linked from each language's README.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
- **README fully rewritten** with a concrete bcrypt walkthrough — actual output (not placeholder mockups) showing how AGREEMENT / DIVERGENCE / BLINDSPOT sections render in practice. The example shows two real-world disagreement: should `bcrypt` be wrapped with `subtle.ConstantTimeCompare`? Claude synthesizes that Codex's recommendation would break the comparison entirely because bcrypt uses a fresh salt every call.
|
|
18
|
+
- **"When to use ccg" rewritten** — replaced the security-only framing (auth / payments / migrations / crypto) with judgment-difficulty framing. New trigger: *feeling*, not *domain*. Added cross-domain examples across social platforms, data/AI infra, frontend, API design, distributed systems, database, and security — emphasizing that divergence detection earns its cost on *any* change where two reasonable engineers might disagree.
|
|
19
|
+
- **README structure** restructured into three-part flow: What / Why-vs-alternatives / Install / Walkthrough — designed to answer "what does it do" and "what does the output mean" before diving into config.
|
|
20
|
+
- README v-prefix removed from H1 headings (no more "v3" branding in titles; version lives in CHANGELOG + npm).
|
|
21
|
+
|
|
22
|
+
### Internal
|
|
23
|
+
- `PROMO.md` added to `.gitignore` (marketing copy file, not part of npm package).
|
|
24
|
+
|
|
25
|
+
## [3.0.0] — 2026-05-23
|
|
26
|
+
|
|
27
|
+
Repositioning: from "multi-model review tool" to **"code divergence detector"**. Three structural pillars added; product opinion sharpened. 99-test regression (stable across 3 consecutive runs).
|
|
28
|
+
|
|
29
|
+
### Identity shift
|
|
30
|
+
**Before (v2):** "Get multi-model second opinions, see consensus + disagreement + actions."
|
|
31
|
+
**After (v3):** "Surface where Codex and Gemini *disagree* — that's where you actually need to make a call. Agreement is low-signal; divergence is the gold."
|
|
32
|
+
|
|
33
|
+
This is a category change. v3 deliberately downgrades the AGREEMENT section (one-liners only) and elevates DIVERGENCE (full expansion + `NEEDS HUMAN DECISION` markers).
|
|
34
|
+
|
|
35
|
+
### Added — Pillar 1: Divergence Engine
|
|
36
|
+
- Structured `[FINDING]…[/FINDING]` prompt protocol; both reviewers must conform
|
|
37
|
+
- Three-section synthesis output: `AGREEMENT (N) / DIVERGENCE (M) / BLINDSPOT (≤2)`
|
|
38
|
+
- `VERDICT` line: merge | fix-required | discuss
|
|
39
|
+
- `NEEDS HUMAN DECISION` is an explicit signal, not implied
|
|
40
|
+
|
|
41
|
+
### Added — Pillar 2: Risk-Aware Routing
|
|
42
|
+
- `ccg_risk_score <diff_file>` — deterministic 0..100+ scoring
|
|
43
|
+
- Path signals: auth/payment/migration/crypto/security/infra/ci (+15..+40)
|
|
44
|
+
- Body signals: shell exec/SQL interp/fs delete/privilege ops (+5..+30)
|
|
45
|
+
- Size signals: lines and files-changed (+5..+25)
|
|
46
|
+
- Docs-only subtraction (-40)
|
|
47
|
+
- Auto mode selection: <20 cost, <60 balanced, ≥60 quality
|
|
48
|
+
- Manual `CCG_MODE=` override always wins
|
|
49
|
+
- Outputs reason string for full transparency: `auth+35 sql_interp+30 size>300+15`
|
|
50
|
+
- Pure rules, zero LLM cost, social-PR friendly
|
|
51
|
+
|
|
52
|
+
### Added — Pillar 3: Review Ledger
|
|
53
|
+
- `ccg_ledger_record <workdir>` — append JSONL row to `~/.ccg/ledger.jsonl`
|
|
54
|
+
- Fields: ts, repo, branch, sha, mode, risk, files, lines, paths[], synthesis (redacted, ≤400 chars)
|
|
55
|
+
- `ccg_ledger_query [path-substring]` — search prior reviews
|
|
56
|
+
- `CCG_LEDGER_LOG` env override
|
|
57
|
+
- Synthesis excerpt runs through `_ccg_redact` before write (secret hygiene)
|
|
58
|
+
|
|
59
|
+
### Fixed — diff capture deep gap
|
|
60
|
+
- Old behavior: `git diff HEAD` only → empty after commit
|
|
61
|
+
- New 4-level fallback: `worktree → staged → upstream:@{u}…HEAD → origin/HEAD…HEAD`
|
|
62
|
+
- Reports `CCG_DIFF_SOURCE=<level>` so caller knows what scope was captured
|
|
63
|
+
- Resolves "I committed and now /ccg sees nothing" footgun
|
|
64
|
+
|
|
65
|
+
### Changed
|
|
66
|
+
- Default `CCG_MODE=auto` (was `balanced`); auto uses risk score
|
|
67
|
+
- `ccg_init` now also exposes `CCG_SYNTHESIS_FILE` and `CCG_RISK_FILE` paths
|
|
68
|
+
- Dispatch subcommands added: `risk_score`, `ledger_record`, `ledger_query`
|
|
69
|
+
|
|
70
|
+
### Tests
|
|
71
|
+
- 13 new test cases (13.1 - 13.13) covering all three pillars + diff fallback
|
|
72
|
+
- All 99 tests pass; 31s runtime; stable across consecutive runs
|
|
73
|
+
|
|
74
|
+
## [2.0.0] — 2026-05-23
|
|
75
|
+
|
|
76
|
+
Major refactor based on honest self-critique: drop low-value features, add high-leverage ones.
|
|
77
|
+
86-test regression (stable across 10 consecutive runs).
|
|
78
|
+
|
|
79
|
+
### Removed
|
|
80
|
+
- **Pre-execution cost estimate** (`ccg_estimate`). Estimating output tokens by assumption produced 3-5× wrong predictions, misleading users. Post-execution `ccg_actual` remains — it uses real byte counts.
|
|
81
|
+
- **Asymmetric prompt split** (codex=architecture, gemini=UX). It was pure intuition with no evidence. v2 sends the **same prompt to both providers** — training-data differences create natural diversity.
|
|
82
|
+
- `ccg_mode_resolve` public subcommand (resolution is now internal/silent)
|
|
83
|
+
- `CCG_USD_CNY_RATE`, `CCG_OUTPUT_TOKENS_ESTIMATE`, `CCG_TOKEN_CHARS_RATIO` knobs (no one tuned them)
|
|
84
|
+
|
|
85
|
+
### Added
|
|
86
|
+
- **Auto `git diff` mode**: naked `/ccg` (no args) captures `git diff HEAD` and runs a pre-commit triangulated review. One-keystroke workflow.
|
|
87
|
+
- `ccg_diff_capture <out_file>` — captures `git diff HEAD`, falls back to `--cached`, returns `CCG_DIFF_OK/FAIL`
|
|
88
|
+
- **24h prompt-hash cache** keyed by SHA-256(model + prompt). Same prompt + same model → cached result, $0.00 cost. Iterating on the same code saves 90%+ on repeat calls.
|
|
89
|
+
- `CCG_CACHE_DIR` (default `~/.ccg/cache`) and `CCG_CACHE_TTL_HOURS` (default 24)
|
|
90
|
+
- `CCG_NO_CACHE=1` opt-out per-call
|
|
91
|
+
- **Usage log** at `~/.ccg/usage.log` (TSV: timestamp, provider, model, in_tokens, out_tokens, USD, cached). Only successful calls logged. Override path via `CCG_USAGE_LOG`.
|
|
92
|
+
- `ccg_usage [--this-month|--all|--since=YYYY-MM]` aggregates spend by provider with cache-hit count
|
|
93
|
+
- **Prompt size guard**: `CCG_MAX_PROMPT_KB=100` default. Hard reject prompts above this. Prevents the "I piped my whole repo and got a $5 bill" footgun.
|
|
94
|
+
- New dispatch subcommands: `diff_capture`, `usage`, `actual`
|
|
95
|
+
|
|
96
|
+
### Fixed
|
|
97
|
+
- Test suite now isolates cache via `CCG_CACHE_DIR` (not `HOME`), so test runs no longer break codex/gemini auth lookup
|
|
98
|
+
- Mock-mode test helpers always set `CCG_NO_CACHE=1` so failure-mode tests can't be masked by an earlier success-mode cache entry
|
|
99
|
+
|
|
100
|
+
## [1.0.0] — 2026-05-22
|
|
101
|
+
|
|
102
|
+
First production-ready release.
|
|
103
|
+
|
|
104
|
+
### Added
|
|
105
|
+
- `CCG_MODE=cost|balanced|quality` for model selection
|
|
106
|
+
- `CCG_CODEX_MODEL`/`CCG_GEMINI_MODEL` explicit overrides
|
|
107
|
+
- `ccg_codex` passes `-m <model>` when set
|
|
108
|
+
- LICENSE (MIT), CHANGELOG, scripts/install.sh
|
|
109
|
+
- 86-test regression in `tests/test_ccg.sh`
|
|
110
|
+
|
|
111
|
+
### Fixed
|
|
112
|
+
- **CRITICAL**: pure-bash timeout fallback lost stdin in async children. Real Codex/Gemini stdin delivery now works in all bash modes via explicit `<&0`.
|
|
113
|
+
- Timeout polling granularity: 1s → 0.1s + wall-clock deadline for sub-second responsiveness.
|
|
114
|
+
- Orphan sweep threshold: 60min → 1440min (24h).
|
|
115
|
+
- `eval`-safety for any printed shell-meta in mode descriptions.
|
|
116
|
+
|
|
117
|
+
## [0.x] — pre-release
|
|
118
|
+
|
|
119
|
+
Initial two-file plugin (commands/ccg.md + commands/ccg.sh).
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 zhangpeng
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.ja.md
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# ccg — Code Divergence Detector
|
|
2
|
+
|
|
3
|
+
> Claude Code のスラッシュコマンド。一度インストールして、diff の上で `/ccg` と入力するだけ。
|
|
4
|
+
|
|
5
|
+
[]()
|
|
6
|
+
[](https://www.npmjs.com/package/@mcgrapeng/ccg)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
|
|
9
|
+
[English](README.md) | [简体中文](README.zh-CN.md) | **日本語** | [한국어](README.ko.md) · [アーキテクチャ →](docs/ARCHITECTURE.ja.md)
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## ccg とは
|
|
14
|
+
|
|
15
|
+
あなたは `auth/login.go` を編集し終え、マージしようとしています。念のため確認したい。今の選択肢は 3 つしかなく、全て欠点があります:
|
|
16
|
+
|
|
17
|
+
- **単一モデルのレビュー**(Copilot、Cursor `/review`、Aider)は **1 つの視点** しか提供しません。Claude が timing attack を見逃せば、あなたも一緒に見逃します。
|
|
18
|
+
- **複数モデル集約ツール**(zen-mcp-server 等)は意見を **平均化** してしまい、優秀なモデル同士が意見を異にした箇所——人間が本当に助けを必要とする箇所——を覆い隠してしまいます。
|
|
19
|
+
- **手動の二重チェック** は時間が無限にあればやりますが、ありませんね。
|
|
20
|
+
|
|
21
|
+
ccg は Claude Code 用の `/ccg` スラッシュコマンドで、この 3 つを本当に解決します。任意の diff に対して:
|
|
22
|
+
|
|
23
|
+
1. 同じ prompt を **Codex(OpenAI)** と **Gemini(Google)** に並列で送信
|
|
24
|
+
2. **Claude** に両方のレポートを読ませ、**両者が意見を異にした箇所を浮かび上がらせる**——そこが人間の判断が必要な場所
|
|
25
|
+
3. コストを記録、リスクに応じて最安充足モデルを自動選択、過去のレビュー履歴を保持
|
|
26
|
+
|
|
27
|
+
**例え話**:別チームの 2 人のシニアエンジニアに同じ PR をレビューさせ、テックリードに統合させる:「ここは両方同意、ここは意見が分かれた——あなたが決めて、私の見解は以下」。
|
|
28
|
+
|
|
29
|
+
## いつ ccg を使うか
|
|
30
|
+
|
|
31
|
+
トリガーは **領域** ではなく **感覚** です。書き終えた自分の diff を見ながら、心の中で次のように考えていたら、ccg の場面です:
|
|
32
|
+
|
|
33
|
+
| 心の中の独り言 | ccg を使う? |
|
|
34
|
+
|---|---|
|
|
35
|
+
| 「これを間違えたら午前 3 時に呼び出される」 | ✅ Yes |
|
|
36
|
+
| 「これは判断問題 — 明らかに正しい答えはない」 | ✅ Yes |
|
|
37
|
+
| 「誰か他に先に見てほしい」 | ✅ Yes |
|
|
38
|
+
| 「変数の名前を変えただけ」 | ❌ No |
|
|
39
|
+
| 「ドキュメント変更だけ」 | ❌ No |
|
|
40
|
+
| 「単一モデルとストリーミング対話したい」 | ❌ No(CLI を直接使う) |
|
|
41
|
+
|
|
42
|
+
**ドメイン横断の実例** —— auth / 暗号ではないが、すべて「シニア 2 人が意見を異にしうる」瞬間:
|
|
43
|
+
|
|
44
|
+
- **ソーシャルプラットフォーム** —— フィードに新エンゲージメントシグナルを追加して再ランキング · コメントツリー fan-out 戦略 · A/B テストバケッティングロジック · 反スパムレート制限ポリシー · フォロー関係のグラフ DB スキーマ
|
|
45
|
+
- **データ / AI インフラ** —— embedding モデル切替(再インデックスする?) · chunking 戦略変更 · RAG 検索スコアリング · prompt injection 防御レイヤリング
|
|
46
|
+
- **フロントエンド** —— 新ページに SSR vs ISR vs RSC · キャッシュ無効化戦略 · 状態管理リファクタリング · アクセシビリティのトレードオフ
|
|
47
|
+
- **API 設計** —— cursor vs offset ページング · エラーレスポンスモデル · バージョニング方式 · 冪等性キーの扱い
|
|
48
|
+
- **分散システム** —— タイムアウト / 再試行ポリシー · cache TTL vs イベント駆動無効化 · partition tolerance トレードオフ · leader election のセマンティクス
|
|
49
|
+
- **データベース** —— マルチステップマイグレーションの順序 · ホットパスのインデックス選択 · トランザクション分離レベル · 論理削除 vs 物理削除
|
|
50
|
+
- **セキュリティ** —— ええ、auth / 暗号 / 決済もここ —— ただし多くのドメインの 1 つに過ぎない
|
|
51
|
+
|
|
52
|
+
**パターン**:「妥当なエンジニアが選択肢 A を選ぶこともあれば、別の妥当なエンジニアが B を選ぶこともある」変更 —— これが分岐検出が $0.04 を稼ぐ瞬間。
|
|
53
|
+
|
|
54
|
+
## なぜ ccg なのか(他ツールとの比較)
|
|
55
|
+
|
|
56
|
+
**1. 意見の相違こそがシグナル、ノイズではない。**
|
|
57
|
+
Codex が「`subtle.ConstantTimeCompare` を使え」と言い、Gemini が「bcrypt は既に恒定時間、それは cargo-cult」と言った時、**そここそ考える必要がある場所**。他のツールはこれを「timing attack に注意」とぼやかして混ぜます。ccg は両者の生の言葉を見せます。
|
|
58
|
+
|
|
59
|
+
**2. コスト可視化が組み込み。**
|
|
60
|
+
Codex / Gemini CLI は支出を教えません。ccg は全呼び出しを記録、リスクに応じて最安充足モデルを自動選択(リスクルーティング)、同一プロンプトは 24h キャッシュでゼロコスト。`ccg_usage --this-month` が「今月いくら使った?」に即答。
|
|
61
|
+
|
|
62
|
+
**3. セッションを跨いで残るレビュー履歴。**
|
|
63
|
+
「2 週間前、モデルは `src/auth.ts` について何と言ったか?」——ccg の追記専用台帳がこれに答えます。ステートレスなツールには不可能です。
|
|
64
|
+
|
|
65
|
+
## インストール
|
|
66
|
+
|
|
67
|
+
どちらかを選択:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# npm (推奨)
|
|
71
|
+
npx @mcgrapeng/ccg install
|
|
72
|
+
|
|
73
|
+
# または curl ワンライナー、Node 不要
|
|
74
|
+
curl -fsSL https://raw.githubusercontent.com/mcgrapeng/ccg/main/scripts/curl-install.sh | bash
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
次に AI CLI を一度だけインストール:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
npm i -g @openai/codex @google/gemini-cli
|
|
81
|
+
echo 'export GEMINI_API_KEY="<your-key>"' >> ~/.zshenv
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
確認:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
npx @mcgrapeng/ccg doctor # Codex / Gemini / API key をチェック
|
|
88
|
+
npx @mcgrapeng/ccg about # 7 層の機能と現在の環境状態を表示
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## 使い方の完全な例
|
|
92
|
+
|
|
93
|
+
`auth/login.go` を編集したとします:
|
|
94
|
+
|
|
95
|
+
```go
|
|
96
|
+
// before // after
|
|
97
|
+
func Login(user, pw string) bool { func Login(user, pw string) bool {
|
|
98
|
+
u := lookupUser(user) u := lookupUser(user)
|
|
99
|
+
- return u.Hash == sha256.Sum256([]byte(pw)) hashed, err := bcrypt.GenerateFromPassword([]byte(pw), 12)
|
|
100
|
+
+ if err != nil { return false }
|
|
101
|
+
+ return subtle.ConstantTimeCompare(u.Hash, hashed) == 1
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Claude Code を開いて入力:
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
/ccg
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
約 30 秒後に表示されるもの——**実際の出力例**、プレースホルダーではない:
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
📍 範囲:worktree · 1 ファイル · +4 -1 行
|
|
115
|
+
🎯 モード:quality (risk=65 · auth+35 size>0+5 crypto-mention+25)
|
|
116
|
+
🩺 両レビュアー正常:Codex ✓ · Gemini ✓
|
|
117
|
+
💰 コスト:$0.041
|
|
118
|
+
|
|
119
|
+
═══ AGREEMENT (2) — 両方が指摘、低シグナル ═══
|
|
120
|
+
• auth/login.go:3 — sha256 はパスワードハッシュでない;bcrypt が正しい
|
|
121
|
+
• auth/login.go:5 — bcrypt エラーは明示的に処理(やっている)
|
|
122
|
+
|
|
123
|
+
═══ DIVERGENCE (1) — 両モデルが意見不一致 ★ あなたが決定 ═══
|
|
124
|
+
|
|
125
|
+
▸ auth/login.go:6 — bcrypt ハッシュの比較方法
|
|
126
|
+
🔵 Codex: 「bcrypt を使っても timing attack を防ぐため
|
|
127
|
+
subtle.ConstantTimeCompare でラップせよ」
|
|
128
|
+
🟢 Gemini:「bcrypt.CompareHashAndPassword は既に恒定時間。
|
|
129
|
+
ラッピングは cargo-cult、長さ不一致 panic を生み得る」
|
|
130
|
+
⚖️ Claude: Gemini が正しい。bcrypt.CompareHashAndPassword が標準的な
|
|
131
|
+
比較方法;その生の出力に対する ConstantTimeCompare は
|
|
132
|
+
カテゴリ誤り——「ハッシュした pw」と「保存されたハッシュ」を
|
|
133
|
+
比較しているが、bcrypt は毎回新しいソルトを使うので
|
|
134
|
+
直接比較は常に false を返す。
|
|
135
|
+
➡️ アクション:ConstantTimeCompare 行を以下に置換:
|
|
136
|
+
`err := bcrypt.CompareHashAndPassword(u.Hash, []byte(pw))`
|
|
137
|
+
`return err == nil`
|
|
138
|
+
|
|
139
|
+
═══ BLINDSPOT (1) — どちらも見ていないが Claude が疑う ═══
|
|
140
|
+
• エラーパス:bcrypt エラー時に false を返すのは呼び出し側には正しいが、
|
|
141
|
+
インフラエラー(bcrypt OOM 等)を静かに飲み込む。ログを追加せよ。
|
|
142
|
+
|
|
143
|
+
═══ VERDICT: fix-required ═══
|
|
144
|
+
現在の比較ロジックは正しいパスワードを常に拒否する。DIVERGENCE の
|
|
145
|
+
アクションを適用 + エラーログ追加で、マージ可能。
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### この出力をどう読むか
|
|
149
|
+
|
|
150
|
+
| セクション | 意味 | 何をすべきか |
|
|
151
|
+
|---|---|---|
|
|
152
|
+
| **AGREEMENT** | Codex と Gemini の両方が同じ問題を指摘。単一の Claude でも見つかる可能性が高い——**新規情報量低**。 | 流し読み、未修正なら修正。 |
|
|
153
|
+
| **DIVERGENCE** ★ | 両モデルが意見不一致。**これが ccg の存在意義**。Claude の「アクション」行が推奨をくれるが、最終判断はあなた。 | 注意深く読む、Claude の判断を受け入れるかオーバーライド。 |
|
|
154
|
+
| **BLINDSPOT** | どちらのモデルも気付かなかったが Claude が合成時に疑った。**控えめに**——1 回あたり最大 2 件。 | ヒントとして扱う、聖典ではない。 |
|
|
155
|
+
| **VERDICT** | `merge` / `fix-required` / `discuss`。1 行サマリー。 | マージゲートとして使用。 |
|
|
156
|
+
|
|
157
|
+
レビュー後、`ccg_ledger_record` が JSONL 1 行を台帳に書きます。2 週間後:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
source ~/.claude/commands/ccg.sh
|
|
161
|
+
ccg_ledger_query "auth/login.go"
|
|
162
|
+
# → "auth/login.go: 3 レビュー · 最新 2026-05-23 (fix-required) · 2026-05-09 (merge) · 2026-04-28 (discuss)"
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## 設定(デフォルトで通常は十分)
|
|
166
|
+
|
|
167
|
+
モードとモデルの選択は自動です。必要なときだけ上書き:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
CCG_MODE=quality /ccg # 任意の diff で quality モデルを強制
|
|
171
|
+
CCG_CODEX_MODEL=o3 /ccg # 1 つのモデルだけ上書き
|
|
172
|
+
CCG_NO_CACHE=1 /ccg # この呼び出しのみ 24h キャッシュをスキップ
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
よく使うもの(全部は [アーキテクチャ §5](docs/ARCHITECTURE.ja.md#5-拡張ポイント)):
|
|
176
|
+
|
|
177
|
+
| 変数 | デフォルト | 用途 |
|
|
178
|
+
|---|---|---|
|
|
179
|
+
| `CCG_MODE` | `auto` | `auto` / `cost` / `balanced` / `quality` |
|
|
180
|
+
| `CCG_CACHE_TTL_HOURS` | `24` | キャッシュ TTL |
|
|
181
|
+
| `CCG_MAX_PROMPT_KB` | `100` | 1 回あたりのプロンプトサイズ上限 |
|
|
182
|
+
|
|
183
|
+
コスト目安(USD / 呼び出し、キャッシュヒット後):
|
|
184
|
+
|
|
185
|
+
| モード | Codex | Gemini | 標準コスト |
|
|
186
|
+
|---|---|---|---|
|
|
187
|
+
| `cost` | gpt-5-nano | gemini-2.5-flash-lite | ~$0.0007 |
|
|
188
|
+
| `balanced` | gpt-5-mini | gemini-2.5-flash | ~$0.0046 |
|
|
189
|
+
| `quality` | gpt-5 | gemini-2.5-pro | ~$0.0440 |
|
|
190
|
+
|
|
191
|
+
累計支出はいつでも確認可能:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
source ~/.claude/commands/ccg.sh
|
|
195
|
+
ccg_usage --this-month
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## 適さない用途
|
|
199
|
+
|
|
200
|
+
- Claude Code 以外の IDE([zen-mcp-server](https://github.com/BeehiveInnovations/zen-mcp-server) を試してください)
|
|
201
|
+
- 静的解析の置き換え(Semgrep / CodeQL と併用してください)
|
|
202
|
+
- 全 PR で自動実行(ccg はトリアージツール、ボットではありません)
|
|
203
|
+
- ストリーミング出力やマルチターン会話
|
|
204
|
+
|
|
205
|
+
## アーキテクチャとコントリビュート
|
|
206
|
+
|
|
207
|
+
ccg は **7 層** で構成されており、「分岐検出」は最上位 1 層にすぎません。下の 6 層(キャッシュ、台帳、使用量、リスクルーティング、スマート diff、安全な CLI スケジューリング)はそれぞれ独立して実問題を解決します。`ccg.sh` を変更する前に [docs/ARCHITECTURE.ja.md](docs/ARCHITECTURE.ja.md) を読んでください。
|
|
208
|
+
|
|
209
|
+
テスト:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
bash tests/test_ccg.sh # 99 個の回帰テスト、~31s
|
|
213
|
+
REAL_CLI=1 bash tests/test_ccg.sh # +2 個のライブ API テスト(課金あり)
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## ライセンスと謝辞
|
|
217
|
+
|
|
218
|
+
MIT —— [LICENSE](LICENSE) を参照。
|
|
219
|
+
|
|
220
|
+
[oh-my-claudecode](https://github.com/Yeachan-Heo/oh-my-claudecode) の元々の `/ccg` コンセプト · Claude Code · OpenAI Codex CLI · Google Gemini CLI を基に構築。
|
package/README.ko.md
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# ccg — Code Divergence Detector
|
|
2
|
+
|
|
3
|
+
> Claude Code 슬래시 명령. 한 번 설치하고 diff 위에서 `/ccg`를 입력하세요.
|
|
4
|
+
|
|
5
|
+
[]()
|
|
6
|
+
[](https://www.npmjs.com/package/@mcgrapeng/ccg)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
|
|
9
|
+
[English](README.md) | [简体中文](README.zh-CN.md) | [日本語](README.ja.md) | **한국어** · [아키텍처 →](docs/ARCHITECTURE.ko.md)
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## ccg란
|
|
14
|
+
|
|
15
|
+
`auth/login.go` 변경 후 머지하려고 합니다. 안전 점검을 하고 싶습니다. 오늘 선택지는 세 가지뿐이고, 모두 결함이 있습니다:
|
|
16
|
+
|
|
17
|
+
- **단일 모델 리뷰**(Copilot, Cursor `/review`, Aider)는 **한 가지 관점**만 제공합니다. Claude가 timing attack을 놓치면 당신도 함께 놓칩니다.
|
|
18
|
+
- **다중 모델 게이트웨이**(zen-mcp-server 등)는 의견을 **평균화**하여, 똑똑한 모델들이 의견을 달리한 곳 — 인간이 정말로 도움이 필요한 유일한 곳 — 을 정확히 가립니다.
|
|
19
|
+
- **수동 교차 검증**은 시간이 무한하다면 할 일. 당신에겐 없습니다.
|
|
20
|
+
|
|
21
|
+
ccg는 Claude Code용 `/ccg` 슬래시 명령으로, 이 세 가지 모두를 진짜로 해결합니다. 임의의 diff에 대해:
|
|
22
|
+
|
|
23
|
+
1. 같은 prompt를 **Codex(OpenAI)** 와 **Gemini(Google)** 에 병렬 전송
|
|
24
|
+
2. **Claude** 가 두 보고서를 읽고 **그들이 의견을 달리하는 곳을 부각** —— 인간 판단이 필요한 곳
|
|
25
|
+
3. 비용 추적, 위험 수준에 적합한 가장 저렴한 모델 자동 선택, 과거 리뷰 기억
|
|
26
|
+
|
|
27
|
+
**비유**: 다른 팀의 시니어 엔지니어 두 명에게 같은 PR을 리뷰시키고, 테크 리드가 종합: "이건 둘 다 동의, 이건 의견이 갈렸음 — 당신이 결정, 내 견해는 다음".
|
|
28
|
+
|
|
29
|
+
## 언제 ccg를 사용할까
|
|
30
|
+
|
|
31
|
+
트리거는 **도메인**이 아니라 **느낌**입니다. 방금 작성한 diff를 보면서 마음속으로 다음과 같이 생각하고 있다면 — ccg의 순간입니다:
|
|
32
|
+
|
|
33
|
+
| 마음속 독백 | ccg 사용? |
|
|
34
|
+
|---|---|
|
|
35
|
+
| "이걸 잘못하면 새벽 3시에 호출됨." | ✅ 예 |
|
|
36
|
+
| "이건 판단의 문제 — 명백히 정답이 있는 게 아님." | ✅ 예 |
|
|
37
|
+
| "누가 먼저 봐줬으면 좋겠다." | ✅ 예 |
|
|
38
|
+
| "변수 이름만 바꿨다." | ❌ 아니요 |
|
|
39
|
+
| "문서만 편집." | ❌ 아니요 |
|
|
40
|
+
| "단일 모델과 스트리밍 대화하고 싶음." | ❌ 아니요 (CLI 직접 사용) |
|
|
41
|
+
|
|
42
|
+
**도메인 횡단 실제 예시** — 모두 auth/암호화가 아니지만, 모두 "시니어 엔지니어 두 명이 의견이 갈릴" 순간입니다:
|
|
43
|
+
|
|
44
|
+
- **소셜 플랫폼** — 새 참여 신호로 피드 재정렬 · 댓글 트리 fan-out 전략 · A/B 테스트 버킷팅 로직 · 어뷰즈 방지 레이트 리밋 정책 · 팔로우 관계의 그래프 DB 스키마
|
|
45
|
+
- **데이터 / AI 인프라** — embedding 모델 교체(재인덱싱?) · 청킹 전략 변경 · RAG 검색 점수 · 프롬프트 인젝션 방어 레이어링
|
|
46
|
+
- **프론트엔드** — 새 페이지에 SSR vs ISR vs RSC · 캐시 무효화 전략 · 상태 관리 리팩토링 · 접근성 트레이드오프
|
|
47
|
+
- **API 설계** — 페이지네이션 cursor vs offset · 에러 응답 모델 · 버전 관리 방식 · 멱등성 키 처리
|
|
48
|
+
- **분산 시스템** — 타임아웃 / 재시도 정책 · cache TTL vs 이벤트 기반 무효화 · 분할 내성 트레이드오프 · 리더 선출 의미론
|
|
49
|
+
- **데이터베이스** — 다단계 마이그레이션 순서 · 핫 패스 인덱스 선택 · 트랜잭션 격리 수준 · 소프트 삭제 vs 하드 삭제
|
|
50
|
+
- **보안** — 네, auth / 암호화 / 결제도 여기 — 하지만 많은 도메인 중 하나일 뿐
|
|
51
|
+
|
|
52
|
+
**패턴**: 합리적인 엔지니어 한 명은 A를 선택하고 다른 합리적인 엔지니어는 B를 선택할 수 있는 모든 변경 — 그게 분기 검출이 $0.04를 회수하는 순간.
|
|
53
|
+
|
|
54
|
+
## 왜 ccg인가 (다른 도구와의 비교)
|
|
55
|
+
|
|
56
|
+
**1. 의견 불일치가 신호, 잡음이 아님.**
|
|
57
|
+
Codex가 "`subtle.ConstantTimeCompare`를 사용하라"고 하고 Gemini가 "bcrypt는 이미 constant-time, 그건 cargo-cult"라고 할 때, *그곳이* 당신이 생각해야 할 곳입니다. 다른 도구는 이런 충돌을 모호한 "timing attack 주의"로 섞어버립니다. ccg는 양쪽의 말을 그대로 보여줍니다.
|
|
58
|
+
|
|
59
|
+
**2. 내장 비용 텔레메트리.**
|
|
60
|
+
Codex / Gemini CLI는 지출을 알려주지 않습니다. ccg는 모든 호출을 기록하고, 위험에 따라 가장 저렴하고 충분한 모델을 자동 선택(위험 라우팅)하며, 같은 prompt는 24h 캐시로 비용 0. `ccg_usage --this-month`가 "지금까지 얼마 썼지?"에 답합니다.
|
|
61
|
+
|
|
62
|
+
**3. 세션 간에 살아남는 리뷰 이력.**
|
|
63
|
+
"2주 전에 모델이 `src/auth.ts`에 대해 뭐라고 했지?" —— ccg의 추가 전용 원장이 답합니다. 어떤 무상태 도구도 못 합니다.
|
|
64
|
+
|
|
65
|
+
## 설치
|
|
66
|
+
|
|
67
|
+
둘 중 선택:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# npm (권장)
|
|
71
|
+
npx @mcgrapeng/ccg install
|
|
72
|
+
|
|
73
|
+
# 또는 curl 한 줄 설치, Node 불필요
|
|
74
|
+
curl -fsSL https://raw.githubusercontent.com/mcgrapeng/ccg/main/scripts/curl-install.sh | bash
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
그다음 AI CLI를 한 번 설치:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
npm i -g @openai/codex @google/gemini-cli
|
|
81
|
+
echo 'export GEMINI_API_KEY="<your-key>"' >> ~/.zshenv
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
확인:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
npx @mcgrapeng/ccg doctor # Codex / Gemini / API key 점검
|
|
88
|
+
npx @mcgrapeng/ccg about # 7개 계층의 기능과 현재 환경 상태 확인
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## 사용법 — 완전한 예제
|
|
92
|
+
|
|
93
|
+
`auth/login.go`를 막 편집했다고 해봅시다:
|
|
94
|
+
|
|
95
|
+
```go
|
|
96
|
+
// before // after
|
|
97
|
+
func Login(user, pw string) bool { func Login(user, pw string) bool {
|
|
98
|
+
u := lookupUser(user) u := lookupUser(user)
|
|
99
|
+
- return u.Hash == sha256.Sum256([]byte(pw)) hashed, err := bcrypt.GenerateFromPassword([]byte(pw), 12)
|
|
100
|
+
+ if err != nil { return false }
|
|
101
|
+
+ return subtle.ConstantTimeCompare(u.Hash, hashed) == 1
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Claude Code를 열고 입력:
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
/ccg
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
약 30초 후 다음과 같은 출력 —— **실제 출력**, 플레이스홀더 아님:
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
📍 범위: worktree · 1 파일 · +4 -1 줄
|
|
115
|
+
🎯 모드: quality (risk=65 · auth+35 size>0+5 crypto-mention+25)
|
|
116
|
+
🩺 두 리뷰어 정상: Codex ✓ · Gemini ✓
|
|
117
|
+
💰 비용: $0.041
|
|
118
|
+
|
|
119
|
+
═══ AGREEMENT (2) — 양쪽 모두 지적, 낮은 신호 ═══
|
|
120
|
+
• auth/login.go:3 — sha256은 비밀번호 해시 아님; bcrypt가 맞음
|
|
121
|
+
• auth/login.go:5 — bcrypt 에러 명시적 처리 (당신이 했음)
|
|
122
|
+
|
|
123
|
+
═══ DIVERGENCE (1) — 두 모델이 의견 불일치 ★ 당신이 결정 ═══
|
|
124
|
+
|
|
125
|
+
▸ auth/login.go:6 — bcrypt 해시 비교 방법
|
|
126
|
+
🔵 Codex: "bcrypt를 사용해도 timing attack 방지를 위해
|
|
127
|
+
subtle.ConstantTimeCompare로 감싸라."
|
|
128
|
+
🟢 Gemini: "bcrypt.CompareHashAndPassword는 이미 constant-time.
|
|
129
|
+
감싸는 것은 cargo-cult이고 길이 불일치 panic을 유발할 수 있다."
|
|
130
|
+
⚖️ Claude: Gemini가 맞다. bcrypt.CompareHashAndPassword가 표준 비교
|
|
131
|
+
방법; 그 원시 출력에 ConstantTimeCompare는 카테고리 오류 ——
|
|
132
|
+
"막 해시한 pw"와 "저장된 해시"를 비교하지만 bcrypt는
|
|
133
|
+
매번 새 솔트를 쓰므로 직접 비교는 항상 false 반환.
|
|
134
|
+
➡️ 액션: ConstantTimeCompare 줄을 다음으로 교체:
|
|
135
|
+
`err := bcrypt.CompareHashAndPassword(u.Hash, []byte(pw))`
|
|
136
|
+
`return err == nil`
|
|
137
|
+
|
|
138
|
+
═══ BLINDSPOT (1) — 둘 다 못 봤지만 Claude 의심 ═══
|
|
139
|
+
• 에러 경로: bcrypt 오류 시 false 반환은 호출자에겐 맞지만,
|
|
140
|
+
인프라 오류(bcrypt OOM 등)를 조용히 삼킴. 로그를 추가하라.
|
|
141
|
+
|
|
142
|
+
═══ VERDICT: fix-required ═══
|
|
143
|
+
현재 비교 로직은 유효한 비밀번호도 항상 거부한다. DIVERGENCE 액션
|
|
144
|
+
적용 + 오류 로깅 추가 후 머지 가능.
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### 이 출력을 어떻게 읽는가
|
|
148
|
+
|
|
149
|
+
| 섹션 | 의미 | 무엇을 할까 |
|
|
150
|
+
|---|---|---|
|
|
151
|
+
| **AGREEMENT** | Codex와 Gemini 둘 다 같은 것을 지적. 단일 소스 Claude도 잡을 가능성 높음 —— **새로운 정보량 낮음**. | 훑어보고, 미수정 시 수정. |
|
|
152
|
+
| **DIVERGENCE** ★ | 두 모델이 의견 불일치. **ccg가 존재하는 진짜 이유**. Claude의 "액션" 줄이 추천을 주지만 최종 결정자는 당신. | 주의 깊게 읽고, Claude 판단 수용 또는 재정의. |
|
|
153
|
+
| **BLINDSPOT** | 어떤 모델도 제기하지 않았지만 Claude가 합성하면서 의심. **신중히 사용** —— 호출당 최대 2건. | 힌트로 다루고, 절대 진리 아님. |
|
|
154
|
+
| **VERDICT** | `merge` / `fix-required` / `discuss`. 한 줄 요약. | 머지 게이트로 사용. |
|
|
155
|
+
|
|
156
|
+
리뷰 후 `ccg_ledger_record`가 원장에 JSONL 한 줄 기록. 2주 후:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
source ~/.claude/commands/ccg.sh
|
|
160
|
+
ccg_ledger_query "auth/login.go"
|
|
161
|
+
# → "auth/login.go: 3 리뷰 · 최신 2026-05-23 (fix-required) · 2026-05-09 (merge) · 2026-04-28 (discuss)"
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## 설정 (기본값으로 보통 충분)
|
|
165
|
+
|
|
166
|
+
모드와 모델 선택은 자동입니다. 필요할 때만 재정의:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
CCG_MODE=quality /ccg # 모든 diff에 quality 모델 강제
|
|
170
|
+
CCG_CODEX_MODEL=o3 /ccg # 단일 모델만 재정의
|
|
171
|
+
CCG_NO_CACHE=1 /ccg # 이번 호출만 24h 캐시 우회
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
자주 쓰는 것 (전체는 [아키텍처 §5](docs/ARCHITECTURE.ko.md#5-확장-지점)):
|
|
175
|
+
|
|
176
|
+
| 변수 | 기본값 | 용도 |
|
|
177
|
+
|---|---|---|
|
|
178
|
+
| `CCG_MODE` | `auto` | `auto` / `cost` / `balanced` / `quality` |
|
|
179
|
+
| `CCG_CACHE_TTL_HOURS` | `24` | 캐시 TTL |
|
|
180
|
+
| `CCG_MAX_PROMPT_KB` | `100` | 호출당 프롬프트 크기 상한 |
|
|
181
|
+
|
|
182
|
+
비용 참고 (USD / 호출, 캐시 적중 후):
|
|
183
|
+
|
|
184
|
+
| 모드 | Codex | Gemini | 표준 비용 |
|
|
185
|
+
|---|---|---|---|
|
|
186
|
+
| `cost` | gpt-5-nano | gemini-2.5-flash-lite | ~$0.0007 |
|
|
187
|
+
| `balanced` | gpt-5-mini | gemini-2.5-flash | ~$0.0046 |
|
|
188
|
+
| `quality` | gpt-5 | gemini-2.5-pro | ~$0.0440 |
|
|
189
|
+
|
|
190
|
+
누적 지출은 언제든:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
source ~/.claude/commands/ccg.sh
|
|
194
|
+
ccg_usage --this-month
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## 적합하지 않은 경우
|
|
198
|
+
|
|
199
|
+
- Claude Code 이외의 IDE ([zen-mcp-server](https://github.com/BeehiveInnovations/zen-mcp-server) 시도)
|
|
200
|
+
- 정적 분석 대체 (Semgrep / CodeQL과 함께 사용)
|
|
201
|
+
- 모든 PR에 자동 실행 (ccg는 트리아지 도구, 봇이 아닙니다)
|
|
202
|
+
- 스트리밍 출력 또는 멀티턴 대화
|
|
203
|
+
|
|
204
|
+
## 아키텍처 및 기여
|
|
205
|
+
|
|
206
|
+
ccg는 **7개 계층**으로 구성되며, "분기 검출"은 최상위 1개 계층일 뿐입니다. 아래 6개 계층(캐시, 원장, 사용량, 위험 라우팅, 스마트 diff, 안전한 CLI 스케줄링)은 각각 독립적으로 실제 문제를 해결합니다. `ccg.sh`를 변경하기 전에 [docs/ARCHITECTURE.ko.md](docs/ARCHITECTURE.ko.md)를 읽어주세요.
|
|
207
|
+
|
|
208
|
+
테스트:
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
bash tests/test_ccg.sh # 99개 회귀 테스트, ~31s
|
|
212
|
+
REAL_CLI=1 bash tests/test_ccg.sh # +2개 실제 API 테스트 (비용 발생)
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## 라이선스 및 감사의 말
|
|
216
|
+
|
|
217
|
+
MIT —— [LICENSE](LICENSE) 참조.
|
|
218
|
+
|
|
219
|
+
[oh-my-claudecode](https://github.com/Yeachan-Heo/oh-my-claudecode)의 원래 `/ccg` 컨셉 · Claude Code · OpenAI Codex CLI · Google Gemini CLI 기반.
|