codex-review

安装量: 224
排名: #3892

安装

npx skills add https://github.com/benedictking/codex-review --skill codex-review

Codex Code Review Skill Trigger Conditions Triggered when user input contains: "代码审核", "代码审查", "审查代码", "审核代码" "review", "code review", "review code", "codex 审核" "帮我审核", "检查代码", "审一下", "看看代码" Core Concept: Intention vs Implementation Running codex review --uncommitted alone only shows AI "what was done (Implementation)". Recording intention first tells AI "what you wanted to do (Intention)". "Code changes + intention description" as combined input is the most effective way to improve AI code review quality. Skill Architecture This skill operates in two phases: Preparation Phase (current context): Check working directory, update CHANGELOG Review Phase (isolated context): Invoke Task tool to execute Lint + codex review (using context: fork to reduce context waste) Execution Steps 0. [First] Check Working Directory Status git diff --name-only && git status --short Decide review mode based on output: Has uncommitted changes → Continue with steps 1-4 (normal flow) Clean working directory → Directly invoke codex-runner: codex review --commit HEAD 1. [Mandatory] Check if CHANGELOG is Updated Before any review, must check if CHANGELOG.md contains description of current changes.

Check if CHANGELOG.md is in uncommitted changes

git
diff
--name-only
|
grep
-E
"(CHANGELOG|changelog)"
If CHANGELOG is not updated, you must automatically perform the following (don't ask user to do it manually):
Analyze changes
Run
git diff --stat
and
git diff
to get complete changes
Auto-generate CHANGELOG entry
Generate compliant entry based on code changes
Write to CHANGELOG.md
Use Edit tool to insert entry at top of
[Unreleased]
section
Continue review flow
Immediately proceed to next steps after CHANGELOG update Auto-generated CHANGELOG entry format:

[Unreleased]

Added / Changed / Fixed

Feature description: what problem was solved or what functionality was implemented

Affected files: main modified files/modules Example - Auto-generation Flow: 1. Detected CHANGELOG not updated 2. Run git diff --stat, found handlers/responses.go modified (+88 lines) 3. Run git diff to analyze details: added CompactHandler function 4. Auto-generate entry:

Added

  • Added /v1/responses/compact endpoint for conversation context compression
  • Supports multi-channel failover and request body size limits
  • Use Edit tool to write to CHANGELOG.md
  • Continue with lint and codex review
  • [Critical] Stage All New Files Before invoking codex review, must add all new files (untracked files) to git staging area, otherwise codex will report P1 error.

Check for new files

git status --short | grep "^??" If there are new files, automatically execute:

Safely stage all new files (handles empty list and special filenames)

git ls-files --others --exclude-standard -z | while IFS = read -r -d '' f ; do git add -- " $f " ; done Explanation: -z uses null character to separate filenames, correctly handles filenames with spaces/newlines while IFS= read -r -d '' reads filenames one by one git add -- "$f" uses -- separator, correctly handles filenames starting with - When no new files exist, loop body doesn't execute, safely skipped This won't stage modified files, only handles new files codex needs files to be tracked by git for proper review 3. Evaluate Task Difficulty and Invoke codex-runner Count change scale:

Get summary line for ALL changes (staged + unstaged)

IMPORTANT: Must use 'HEAD' as base to include both staged and unstaged changes

git diff --stat HEAD | tail -1 Why use git diff --stat HEAD : git diff --stat only shows unstaged changes git diff --cached --stat only shows staged changes git diff --stat HEAD shows BOTH staged and unstaged changes combined The last line ( tail -1 ) is the summary line with total file count and line changes Difficulty Assessment Criteria: Model + Reasoning Effort Combinations: Combination Quality Time Timeout Recommended For model=gpt-5.2 model_reasoning_effort=xhigh Best ~15-20 min 40 min Critical code, architecture changes model=gpt-5.3-codex model_reasoning_effort=xhigh High ~8-9 min 15 min Difficult tasks (default) model=gpt-5.2 model_reasoning_effort=high High ~8-9 min 15 min Alternative for difficult tasks model=gpt-5.3-codex model_reasoning_effort=high Good ~5-6 min 10 min Normal tasks (default) Critical Tasks (meets any condition, use best quality model): Modified files ≥ 30 Total code changes (insertions + deletions) ≥ 2000 lines Involves core architecture/algorithm changes (user explicitly mentioned) Config: --config model=gpt-5.2 --config model_reasoning_effort=xhigh , timeout 40 minutes Difficult Tasks (meets any condition): Modified files ≥ 10 Total code changes (insertions + deletions) ≥ 500 lines Single metric: insertions ≥ 300 lines OR deletions ≥ 300 lines Cross-module refactoring Default config: --config model=gpt-5.3-codex --config model_reasoning_effort=xhigh , timeout 15 minutes Normal Tasks (other cases): Default config: --config model=gpt-5.3-codex --config model_reasoning_effort=high , timeout 10 minutes Evaluation Method: You MUST parse the git diff --stat HEAD output correctly to determine difficulty:

Get the summary line (last line of git diff --stat HEAD)

git diff --stat HEAD | tail -1

Example outputs:

"20 files changed, 342 insertions(+), 985 deletions(-)"

"1 file changed, 50 insertions(+)" # No deletions

"3 files changed, 120 deletions(-)" # No insertions

Critical: Why the summary line matters: Each file shows individual stats: file.go | 171 ++++++++++++++++++++- Only the LAST line has the total: 6 files changed, 1341 insertions(+), 18 deletions(-) You must extract the last line with tail -1 to get accurate totals Parsing Rules: Extract file count from "X file(s) changed" (handle both "1 file" and "N files") Extract insertions from "Y insertion(s)(+)" if present (handle both "1 insertion" and "N insertions"), otherwise 0 Extract deletions from "Z deletion(s)(-)" if present (handle both "1 deletion" and "N deletions"), otherwise 0 Calculate total changes = insertions + deletions Important Edge Cases: Single file: "1 file changed" (singular form) No insertions: Git omits "insertions(+)" entirely → treat as 0 No deletions: Git omits "deletions(-)" entirely → treat as 0 Pure rename: May show "0 insertions(+), 0 deletions(-)" or omit both Decision Logic (check in order, first match wins): IF file_count >= 30 OR total_changes >= 2000 → Critical (gpt-5.2 + xhigh) IF file_count >= 10 → Difficult (gpt-5.3-codex + xhigh) IF total_changes >= 500 → Difficult (gpt-5.3-codex + xhigh) IF insertions >= 300 OR deletions >= 300 → Difficult (gpt-5.3-codex + xhigh) ELSE → Normal (gpt-5.3-codex + high) Example Cases: ⭐ "50 files changed, 2000 insertions(+), 1500 deletions(-)" → 关键任务 ,使用 model=gpt-5.2 model_reasoning_effort=xhigh ,超时 40 分钟(核心架构变更) ✅ "20 files changed, 342 insertions(+), 985 deletions(-)" → 困难任务 ,使用 model=gpt-5.3-codex model_reasoning_effort=xhigh ,超时 15 分钟 ✅ "5 files changed, 600 insertions(+), 50 deletions(-)" → 困难任务 ,使用 model=gpt-5.3-codex model_reasoning_effort=xhigh ,超时 15 分钟 ❌ "3 files changed, 150 insertions(+), 80 deletions(-)" → 普通任务 ,使用 model=gpt-5.3-codex model_reasoning_effort=high ,超时 10 分钟 ❌ "1 file changed, 50 insertions(+)" → 普通任务 ,使用 model=gpt-5.3-codex model_reasoning_effort=high ,超时 10 分钟 Invoke codex-runner Subtask: Use Task tool to invoke codex-runner, passing complete command (including Lint + codex review): Task parameters: - subagent_type: Bash - description: "Execute Lint and codex review" - timeout: 900000 (15 minutes for difficult tasks) or 600000 (10 minutes for normal tasks) - prompt: Choose corresponding command based on project type and difficulty Go project - Difficult task: go fmt ./... && go vet ./... && codex review --uncommitted --config model=gpt-5.3-codex --config model_reasoning_effort=xhigh (timeout: 900000) Go project - Normal task: go fmt ./... && go vet ./... && codex review --uncommitted --config model=gpt-5.3-codex --config model_reasoning_effort=high (timeout: 600000) Node project - Difficult task: npm run lint:fix && codex review --uncommitted --config model=gpt-5.3-codex --config model_reasoning_effort=xhigh (timeout: 900000) Node project - Normal task: npm run lint:fix && codex review --uncommitted --config model=gpt-5.3-codex --config model_reasoning_effort=high (timeout: 600000) Python project - Difficult task: black . && ruff check --fix . && codex review --uncommitted --config model=gpt-5.3-codex --config model_reasoning_effort=xhigh (timeout: 900000) Python project - Normal task: black . && ruff check --fix . && codex review --uncommitted --config model=gpt-5.3-codex --config model_reasoning_effort=high (timeout: 600000) Clean working directory: codex review --commit HEAD --config model=gpt-5.3-codex --config model_reasoning_effort=high (timeout: 600000) 4. Self-Correction If Codex finds Changelog description inconsistent with code logic: Code error → Fix code Description inaccurate → Update Changelog Complete Review Protocol [GATE] Check CHANGELOG - Auto-generate and write if not updated (leverage current context to understand change intention) [PREPARE] Stage Untracked Files - Add all new files to git staging area (avoid codex P1 error) [EXEC] Task → Lint + codex review - Invoke Task tool to execute Lint and codex (isolated context, reduce waste) [FIX] Self-Correction - Fix code or update description when intention ≠ implementation Codex Review Command Reference Basic Syntax codex review [ OPTIONS ] [ PROMPT ] Note : [PROMPT] parameter cannot be used with --uncommitted , --base , or --commit . Common Options Option Description Example --uncommitted Review all uncommitted changes in working directory (staged + unstaged + untracked) codex review --uncommitted --base Review changes relative to specified base branch codex review --base main --commit Review changes introduced by specified commit codex review --commit HEAD --title Optional commit title, displayed in review summary codex review --uncommitted --title "feat: add JSON parser" -c, --config <key=value> Override configuration values codex review --uncommitted -c model="o3" Usage Examples</p> <h1 id="1-review-all-uncommitted-changes-most-common">1. Review all uncommitted changes (most common)</h1> <p>codex review --uncommitted</p> <h1 id="2-review-latest-commit">2. Review latest commit</h1> <p>codex review --commit HEAD</p> <h1 id="3-review-specific-commit">3. Review specific commit</h1> <p>codex review --commit abc1234</p> <h1 id="4-review-all-changes-in-current-branch-relative-to-main">4. Review all changes in current branch relative to main</h1> <p>codex review --base main</p> <h1 id="5-review-changes-in-current-branch-relative-to-develop">5. Review changes in current branch relative to develop</h1> <p>codex review --base develop</p> <h1 id="6-review-with-title-title-shown-in-review-summary">6. Review with title (title shown in review summary)</h1> <p>codex review --uncommitted --title "fix: resolve JSON parsing errors"</p> <h1 id="7-review-using-specific-model">7. Review using specific model</h1> <dl> <dt>codex review</dt> <dt>--uncommitted</dt> <dt>-c</dt> <dt>model</dt> <dt>=</dt> <dt>"o3"</dt> <dt>Important Limitations</dt> <dt>--uncommitted</dt> <dt>,</dt> <dt>--base</dt> <dt>,</dt> <dt>--commit</dt> <dt>are mutually exclusive, cannot be used together</dt> <dt>[PROMPT]</dt> <dt>parameter is mutually exclusive with the above three options</dt> <dt>Must be executed in a git repository directory</dt> <dt>Important Notes</dt> <dt>Ensure execution in git repository directory</dt> <dt>Timeout automatically adjusted based on task difficulty:</dt> <dt>Difficult tasks: 15 minutes (</dt> <dt>timeout: 900000</dt> <dt>)</dt> <dt>Normal tasks: 10 minutes (</dt> <dt>timeout: 600000</dt> <dt>)</dt> <dt>codex command must be properly configured and logged in</dt> <dt>codex automatically processes in batches for large changes</dt> <dt>CHANGELOG.md must be in uncommitted changes, otherwise Codex cannot see intention description</dt> <dt>Design Rationale</dt> <dt>Why separate contexts?</dt> <dt>CHANGELOG update needs current context</dt> <dd> <dl> <dt>Understanding user's previous conversation and task intention to generate accurate change description</dt> <dt>Codex review doesn't need conversation history</dt> <dd> <dl> <dt>Only needs code changes and CHANGELOG, more efficient to run independently</dt> <dt>Reduce token consumption</dt> <dd>codex review as independent subtask, doesn't carry irrelevant conversation context</dd> </dl> </dd> </dl> </dd> </dl> </article> <a href="/" class="back-link">← <span data-i18n="detail.backToLeaderboard">返回排行榜</span></a> </div> <aside class="sidebar"> <section class="related-skills" id="relatedSkillsSection"> <h2 class="related-title" data-i18n="detail.relatedSkills">相关 Skills</h2> <div class="related-list" id="relatedSkillsList"> <div class="skeleton-card"></div> <div class="skeleton-card"></div> <div class="skeleton-card"></div> </div> </section> </aside> </div> </div> <script src="https://unpkg.com/i18next@23.11.5/i18next.min.js" defer></script> <script src="https://unpkg.com/i18next-browser-languagedetector@7.2.1/i18nextBrowserLanguageDetector.min.js" defer></script> <script defer> // Language resources - same pattern as index page const resources = { 'zh-CN': null, 'en': null, 'ja': null, 'ko': null, 'zh-TW': null, 'es': null, 'fr': null }; // Load language files (only current + fallback for performance) async function loadLanguageResources() { const savedLang = localStorage.getItem('i18nextLng') || 'en'; const langsToLoad = new Set([savedLang, 'en']); // current + fallback await Promise.all([...langsToLoad].map(async (lang) => { try { const response = await fetch(`/locales/${lang}.json`); if (response.ok) { resources[lang] = { translation: await response.json() }; } } catch (error) { console.warn(`Failed to load ${lang} language file:`, error); } })); } // Load a single language on demand (for language switching) async function loadLanguage(lang) { if (resources[lang]) return; try { const response = await fetch(`/locales/${lang}.json`); if (response.ok) { resources[lang] = { translation: await response.json() }; i18next.addResourceBundle(lang, 'translation', resources[lang].translation); } } catch (error) { console.warn(`Failed to load ${lang} language file:`, error); } } // Initialize i18next async function initI18n() { try { await loadLanguageResources(); // Filter out null values from resources const validResources = {}; for (const [lang, data] of Object.entries(resources)) { if (data !== null) { validResources[lang] = data; } } console.log('Loaded languages:', Object.keys(validResources)); console.log('zh-CN resource:', validResources['zh-CN']); console.log('detail.home in resource:', validResources['zh-CN']?.translation?.detail?.home); // 检查是否有保存的语言偏好 const savedLang = localStorage.getItem('i18nextLng'); // 如果没有保存的语言偏好,默认使用英文 const defaultLang = savedLang && ['zh-CN', 'en', 'ja', 'ko', 'zh-TW', 'es', 'fr'].includes(savedLang) ? savedLang : 'en'; await i18next .use(i18nextBrowserLanguageDetector) .init({ lng: defaultLang, // 强制设置初始语言 fallbackLng: 'en', supportedLngs: ['zh-CN', 'en', 'ja', 'ko', 'zh-TW', 'es', 'fr'], resources: validResources, detection: { order: ['localStorage'], // 只使用 localStorage,不检测浏览器语言 caches: ['localStorage'], lookupLocalStorage: 'i18nextLng' }, interpolation: { escapeValue: false } }); console.log('i18next initialized, language:', i18next.language); console.log('Test translation:', i18next.t('detail.home')); // Set initial language in selector const langSwitcher = document.getElementById('langSwitcher'); langSwitcher.value = i18next.language; // Update page language updatePageLanguage(); // Language switch event langSwitcher.addEventListener('change', async (e) => { await loadLanguage(e.target.value); // load on demand i18next.changeLanguage(e.target.value).then(() => { updatePageLanguage(); localStorage.setItem('i18nextLng', e.target.value); }); }); } catch (error) { console.error('i18next init failed:', error); } } // Translation helper function t(key, options = {}) { return i18next.t(key, options); } // Update all translatable elements function updatePageLanguage() { // Update HTML lang attribute document.documentElement.lang = i18next.language; // Update elements with data-i18n attribute document.querySelectorAll('[data-i18n]').forEach(el => { const key = el.getAttribute('data-i18n'); el.textContent = t(key); }); } // Copy command function function copyCommand() { const command = document.getElementById('installCommand').textContent; const btn = document.getElementById('copyBtn'); navigator.clipboard.writeText(command).then(() => { btn.textContent = t('copied'); btn.classList.add('copied'); setTimeout(() => { btn.textContent = t('copy'); btn.classList.remove('copied'); }, 2000); }).catch(() => { // Fallback for non-HTTPS const textArea = document.createElement('textarea'); textArea.value = command; textArea.style.position = 'fixed'; textArea.style.left = '-9999px'; document.body.appendChild(textArea); textArea.select(); document.execCommand('copy'); document.body.removeChild(textArea); btn.textContent = t('copied'); btn.classList.add('copied'); setTimeout(() => { btn.textContent = t('copy'); btn.classList.remove('copied'); }, 2000); }); } // Initialize document.getElementById('copyBtn').addEventListener('click', copyCommand); initI18n(); // 异步加载相关 Skills async function loadRelatedSkills() { const owner = 'sickn33'; const skillName = 'codex-review'; const currentLang = 'zh-CN'; const listContainer = document.getElementById('relatedSkillsList'); const section = document.getElementById('relatedSkillsSection'); try { const response = await fetch(`/api/related-skills/${encodeURIComponent(owner)}/${encodeURIComponent(skillName)}?limit=6`); if (!response.ok) { throw new Error('Failed to load'); } const data = await response.json(); const relatedSkills = data.related_skills || []; if (relatedSkills.length === 0) { // 没有相关推荐时隐藏整个区域 section.style.display = 'none'; return; } // 渲染相关 Skills listContainer.innerHTML = relatedSkills.map(skill => { const desc = skill.description || ''; const truncatedDesc = desc.length > 60 ? desc.substring(0, 60) + '...' : desc; return ` <a href="${currentLang === 'en' ? '' : '/' + currentLang}/skill/${skill.owner}/${skill.repo}/${skill.skill_name}" class="related-card"> <div class="related-name">${escapeHtml(skill.skill_name)}</div> <div class="related-meta"> <span class="related-owner">${escapeHtml(skill.owner)}</span> <span class="related-installs">${skill.installs}</span> </div> <div class="related-desc">${escapeHtml(truncatedDesc)}</div> </a> `; }).join(''); } catch (error) { console.error('Failed to load related skills:', error); // 加载失败时显示提示或隐藏 listContainer.innerHTML = '<div class="related-empty">暂无相关推荐</div>'; } } // HTML 转义 function escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } // 页面加载完成后异步加载相关 Skills if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', loadRelatedSkills); } else { loadRelatedSkills(); } </script> </body> </html>