mirror of
https://github.com/cexll/myclaude.git
synced 2026-02-10 03:14:32 +08:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5183c7711 | ||
|
|
3fab18a6bb | ||
|
|
12af992d8c | ||
|
|
bbd2f50c38 | ||
|
|
3f7652f992 | ||
|
|
2cbe36b532 | ||
|
|
fdb152872d | ||
|
|
916b970665 | ||
|
|
10070a9bef | ||
|
|
b18439f268 | ||
|
|
4230479ff4 | ||
|
|
18c26a252a | ||
|
|
f6fc9a338f | ||
|
|
6223d59042 | ||
|
|
e6b229645a | ||
|
|
9dc3e8f43d | ||
|
|
e9faa0bc2d | ||
|
|
70caa8d7fc | ||
|
|
4f74d5afa1 |
@@ -175,6 +175,57 @@
|
|||||||
"skills": [
|
"skills": [
|
||||||
"./skills/SKILL.md"
|
"./skills/SKILL.md"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "codex-cli",
|
||||||
|
"source": "./skills/codex/",
|
||||||
|
"description": "Execute Codex CLI for code analysis, refactoring, and automated code changes with file references (@syntax) and structured output",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"author": {
|
||||||
|
"name": "Claude Code Dev Workflows",
|
||||||
|
"url": "https://github.com/cexll/myclaude"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/cexll/myclaude",
|
||||||
|
"repository": "https://github.com/cexll/myclaude",
|
||||||
|
"license": "MIT",
|
||||||
|
"keywords": [
|
||||||
|
"codex",
|
||||||
|
"code-analysis",
|
||||||
|
"refactoring",
|
||||||
|
"automation",
|
||||||
|
"gpt-5",
|
||||||
|
"ai-coding"
|
||||||
|
],
|
||||||
|
"category": "essentials",
|
||||||
|
"strict": false,
|
||||||
|
"skills": [
|
||||||
|
"./SKILL.md"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "gemini-cli",
|
||||||
|
"source": "./skills/gemini/",
|
||||||
|
"description": "Execute Gemini CLI for AI-powered code analysis and generation with Google's latest Gemini models",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"author": {
|
||||||
|
"name": "Claude Code Dev Workflows",
|
||||||
|
"url": "https://github.com/cexll/myclaude"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/cexll/myclaude",
|
||||||
|
"repository": "https://github.com/cexll/myclaude",
|
||||||
|
"license": "MIT",
|
||||||
|
"keywords": [
|
||||||
|
"gemini",
|
||||||
|
"google-ai",
|
||||||
|
"code-analysis",
|
||||||
|
"code-generation",
|
||||||
|
"ai-reasoning"
|
||||||
|
],
|
||||||
|
"category": "essentials",
|
||||||
|
"strict": false,
|
||||||
|
"skills": [
|
||||||
|
"./SKILL.md"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,4 +1,3 @@
|
|||||||
CLAUDE.md
|
CLAUDE.md
|
||||||
.claude/
|
.claude/
|
||||||
|
.claude-trace
|
||||||
|
|
||||||
|
|||||||
163
dev-workflow/README.md
Normal file
163
dev-workflow/README.md
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
# /dev - 极简开发工作流
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
全新设计的轻量级开发工作流,无历史包袱,专注快速交付高质量代码。
|
||||||
|
|
||||||
|
## 工作流程
|
||||||
|
|
||||||
|
```
|
||||||
|
/dev 触发
|
||||||
|
↓
|
||||||
|
AskUserQuestion(需求澄清)
|
||||||
|
↓
|
||||||
|
Codex 分析(提取要点和任务)
|
||||||
|
↓
|
||||||
|
develop-doc-generator(生成开发文档)
|
||||||
|
↓
|
||||||
|
Codex 并发开发(2-5个任务)
|
||||||
|
↓
|
||||||
|
Codex 测试验证(≥90%覆盖率)
|
||||||
|
↓
|
||||||
|
完成(生成总结)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 6个步骤
|
||||||
|
|
||||||
|
### 1. 需求澄清
|
||||||
|
- 使用 **AskUserQuestion** 直接问用户
|
||||||
|
- 无评分系统,无复杂逻辑
|
||||||
|
- 2-3 轮问答直到需求明确
|
||||||
|
|
||||||
|
### 2. Codex 分析
|
||||||
|
- 调用 codex 分析需求
|
||||||
|
- 提取:核心功能、技术要点、任务列表(2-5个)
|
||||||
|
- 输出结构化分析结果
|
||||||
|
|
||||||
|
### 3. 生成开发文档
|
||||||
|
- 调用 **develop-doc-generator** agent
|
||||||
|
- 生成 `dev-plan.md`(单一开发文档)
|
||||||
|
- 包含:任务分解、文件范围、依赖关系、测试命令
|
||||||
|
|
||||||
|
### 4. 并发开发
|
||||||
|
- 基于 dev-plan.md 的任务列表
|
||||||
|
- 无依赖任务 → 并发执行
|
||||||
|
- 有冲突任务 → 串行执行
|
||||||
|
|
||||||
|
### 5. 测试验证
|
||||||
|
- 每个 codex 任务自己:
|
||||||
|
- 实现功能
|
||||||
|
- 编写测试
|
||||||
|
- 运行覆盖率
|
||||||
|
- 报告结果(≥90%)
|
||||||
|
|
||||||
|
### 6. 完成
|
||||||
|
- 汇总任务状态
|
||||||
|
- 记录覆盖率
|
||||||
|
|
||||||
|
## 使用方法
|
||||||
|
|
||||||
|
```bash
|
||||||
|
/dev "实现用户登录功能,支持邮箱和密码验证"
|
||||||
|
```
|
||||||
|
|
||||||
|
**无选项**,流程固定,开箱即用。
|
||||||
|
|
||||||
|
## 输出结构
|
||||||
|
|
||||||
|
```
|
||||||
|
.claude/specs/{feature_name}/
|
||||||
|
├── dev-plan.md # 开发文档(agent生成)
|
||||||
|
```
|
||||||
|
|
||||||
|
仅 2 个文件,极简清晰。
|
||||||
|
|
||||||
|
## 核心组件
|
||||||
|
|
||||||
|
### 工具
|
||||||
|
- **AskUserQuestion**:交互式需求澄清
|
||||||
|
- **codex**:分析、开发、测试
|
||||||
|
- **develop-doc-generator**:生成开发文档(subagent,节省上下文)
|
||||||
|
|
||||||
|
## 核心特性
|
||||||
|
|
||||||
|
### ✅ 全新设计
|
||||||
|
- 无历史项目残留
|
||||||
|
- 无复杂评分逻辑
|
||||||
|
- 无多余抽象层
|
||||||
|
|
||||||
|
### ✅ 极简编排
|
||||||
|
- orchestrator 直接控制流程
|
||||||
|
- 只用 3 个工具/组件
|
||||||
|
- 步骤清晰易懂
|
||||||
|
|
||||||
|
### ✅ 并发能力
|
||||||
|
- 2-5 个任务并行
|
||||||
|
- 自动检测依赖和冲突
|
||||||
|
- codex 独立执行
|
||||||
|
|
||||||
|
### ✅ 质量保证
|
||||||
|
- 强制 90% 覆盖率
|
||||||
|
- codex 自己测试和验证
|
||||||
|
- 失败自动重试
|
||||||
|
|
||||||
|
## 示例
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 触发
|
||||||
|
/dev "添加用户登录功能"
|
||||||
|
|
||||||
|
# 步骤 1: 需求澄清
|
||||||
|
Q: 支持哪些登录方式?
|
||||||
|
A: 邮箱 + 密码
|
||||||
|
Q: 需要记住登录状态吗?
|
||||||
|
A: 是,使用 JWT token
|
||||||
|
|
||||||
|
# 步骤 2: Codex 分析
|
||||||
|
输出:
|
||||||
|
- 核心功能:邮箱密码登录 + JWT认证
|
||||||
|
- 任务 1:后端 API
|
||||||
|
- 任务 2:密码加密
|
||||||
|
- 任务 3:前端表单
|
||||||
|
|
||||||
|
# 步骤 3: 生成文档
|
||||||
|
dev-plan.md 已生成 ✓
|
||||||
|
|
||||||
|
# 步骤 4-5: 并发开发
|
||||||
|
[task-1] 后端API → 测试 → 92% ✓
|
||||||
|
[task-2] 密码加密 → 测试 → 95% ✓
|
||||||
|
[task-3] 前端表单 → 测试 → 91% ✓
|
||||||
|
```
|
||||||
|
|
||||||
|
## 目录结构
|
||||||
|
|
||||||
|
```
|
||||||
|
dev-workflow/
|
||||||
|
├── README.md # 本文档
|
||||||
|
├── commands/
|
||||||
|
│ └── dev.md # 工作流定义
|
||||||
|
└── agents/
|
||||||
|
└── develop-doc-generator.md # 文档生成器
|
||||||
|
```
|
||||||
|
|
||||||
|
极简结构,只有 3 个文件。
|
||||||
|
|
||||||
|
## 适用场景
|
||||||
|
|
||||||
|
✅ **适合**:
|
||||||
|
- 任何规模的功能开发
|
||||||
|
- 需要快速迭代
|
||||||
|
- 需要高测试覆盖率
|
||||||
|
- 希望并发提速
|
||||||
|
|
||||||
|
## 设计原则
|
||||||
|
|
||||||
|
1. **KISS**:保持简单愚蠢
|
||||||
|
2. **即用即抛**:无持久化配置
|
||||||
|
3. **质量优先**:强制 90% 覆盖率
|
||||||
|
4. **并发优先**:充分利用 codex 能力
|
||||||
|
5. **无历史包袱**:全新设计,不受其他项目影响
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**哲学**:像 Linus 一样对复杂度零容忍,交付能立刻用的最小方案。
|
||||||
114
dev-workflow/agents/dev-plan-generator.md
Normal file
114
dev-workflow/agents/dev-plan-generator.md
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
---
|
||||||
|
name: dev-plan-generator
|
||||||
|
description: Use this agent when you need to generate a structured development plan document (`dev-plan.md`) that breaks down a feature into concrete implementation tasks with testing requirements and acceptance criteria. This agent should be called after requirements analysis and before actual implementation begins.\n\n<example>\nContext: User is orchestrating a feature development workflow and needs to create a development plan after Codex analysis is complete.\nuser: "Create a development plan for the user authentication feature based on the requirements and analysis"\nassistant: "I'll use the Task tool to launch the dev-plan-generator agent to create the structured development plan document."\n<commentary>\nThe user needs a dev-plan.md document generated from requirements and analysis. Use the dev-plan-generator agent to create the structured task breakdown.\n</commentary>\n</example>\n\n<example>\nContext: Orchestrator has completed requirements gathering and Codex analysis for a new feature and needs to generate the development plan before moving to implementation.\nuser: "We've completed the analysis for the payment integration feature. Generate the development plan."\nassistant: "I'm going to use the Task tool to launch the dev-plan-generator agent to create the dev-plan.md document with task breakdown and testing requirements."\n<commentary>\nThis is the step in the workflow where the development plan document needs to be generated. Use the dev-plan-generator agent to create the structured plan.\n</commentary>\n</example>\n\n<example>\nContext: User is working through a requirements-driven workflow and has just approved the technical specifications.\nuser: "The specs look good. Let's move forward with creating the implementation plan."\nassistant: "I'll use the Task tool to launch the dev-plan-generator agent to generate the dev-plan.md document with the task breakdown."\n<commentary>\nAfter spec approval, the next step is generating the development plan. Use the dev-plan-generator agent to create the structured document.\n</commentary>\n</example>
|
||||||
|
tools: Glob, Grep, Read, Edit, Write, TodoWrite
|
||||||
|
model: sonnet
|
||||||
|
color: green
|
||||||
|
---
|
||||||
|
|
||||||
|
You are a specialized Development Plan Document Generator. Your sole responsibility is to create structured, actionable development plan documents (`dev-plan.md`) that break down features into concrete implementation tasks.
|
||||||
|
|
||||||
|
## Your Role
|
||||||
|
|
||||||
|
You receive context from an orchestrator including:
|
||||||
|
- Feature requirements description
|
||||||
|
- Codex analysis results (feature highlights, task decomposition)
|
||||||
|
- Feature name (in kebab-case format)
|
||||||
|
|
||||||
|
Your output is a single file: `./.claude/specs/{feature_name}/dev-plan.md`
|
||||||
|
|
||||||
|
## Document Structure You Must Follow
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# {Feature Name} - 开发计划
|
||||||
|
|
||||||
|
## 功能概述
|
||||||
|
[一句话描述核心功能]
|
||||||
|
|
||||||
|
## 任务分解
|
||||||
|
|
||||||
|
### 任务 1: [任务名称]
|
||||||
|
- **ID**: task-1
|
||||||
|
- **描述**: [具体要做什么]
|
||||||
|
- **文件范围**: [涉及的目录或文件,如 src/auth/**, tests/auth/]
|
||||||
|
- **依赖**: [无 或 依赖 task-x]
|
||||||
|
- **测试命令**: [如 pytest tests/auth --cov=src/auth --cov-report=term]
|
||||||
|
- **测试重点**: [需要覆盖的场景]
|
||||||
|
|
||||||
|
### 任务 2: [任务名称]
|
||||||
|
...
|
||||||
|
|
||||||
|
(2-5个任务)
|
||||||
|
|
||||||
|
## 验收标准
|
||||||
|
- [ ] 功能点 1
|
||||||
|
- [ ] 功能点 2
|
||||||
|
- [ ] 所有单元测试通过
|
||||||
|
- [ ] 代码覆盖率 ≥90%
|
||||||
|
|
||||||
|
## 技术要点
|
||||||
|
- [关键技术决策]
|
||||||
|
- [需要注意的约束]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Generation Rules You Must Enforce
|
||||||
|
|
||||||
|
1. **Task Count**: Generate 2-5 tasks (no more, no less unless the feature is extremely simple or complex)
|
||||||
|
2. **Task Requirements**: Each task MUST include:
|
||||||
|
- Clear ID (task-1, task-2, etc.)
|
||||||
|
- Specific description of what needs to be done
|
||||||
|
- Explicit file scope (directories or files affected)
|
||||||
|
- Dependency declaration ("无" or "依赖 task-x")
|
||||||
|
- Complete test command with coverage parameters
|
||||||
|
- Testing focus points (scenarios to cover)
|
||||||
|
3. **Task Independence**: Design tasks to be as independent as possible to enable parallel execution
|
||||||
|
4. **Test Commands**: Must include coverage parameters (e.g., `--cov=module --cov-report=term` for pytest, `--coverage` for npm)
|
||||||
|
5. **Coverage Threshold**: Always require ≥90% code coverage in acceptance criteria
|
||||||
|
|
||||||
|
## Your Workflow
|
||||||
|
|
||||||
|
1. **Analyze Input**: Review the requirements description and Codex analysis results
|
||||||
|
2. **Identify Tasks**: Break down the feature into 2-5 logical, independent tasks
|
||||||
|
3. **Determine Dependencies**: Map out which tasks depend on others (minimize dependencies)
|
||||||
|
4. **Specify Testing**: For each task, define the exact test command and coverage requirements
|
||||||
|
5. **Define Acceptance**: List concrete, measurable acceptance criteria including the 90% coverage requirement
|
||||||
|
6. **Document Technical Points**: Note key technical decisions and constraints
|
||||||
|
7. **Write File**: Use the Write tool to create `./.claude/specs/{feature_name}/dev-plan.md`
|
||||||
|
|
||||||
|
## Quality Checks Before Writing
|
||||||
|
|
||||||
|
- [ ] Task count is between 2-5
|
||||||
|
- [ ] Every task has all 6 required fields (ID, 描述, 文件范围, 依赖, 测试命令, 测试重点)
|
||||||
|
- [ ] Test commands include coverage parameters
|
||||||
|
- [ ] Dependencies are explicitly stated
|
||||||
|
- [ ] Acceptance criteria includes 90% coverage requirement
|
||||||
|
- [ ] File scope is specific (not vague like "all files")
|
||||||
|
- [ ] Testing focus is concrete (not generic like "test everything")
|
||||||
|
|
||||||
|
## Critical Constraints
|
||||||
|
|
||||||
|
- **Document Only**: You generate documentation. You do NOT execute code, run tests, or modify source files.
|
||||||
|
- **Single Output**: You produce exactly one file: `dev-plan.md` in the correct location
|
||||||
|
- **Path Accuracy**: The path must be `./.claude/specs/{feature_name}/dev-plan.md` where {feature_name} matches the input
|
||||||
|
- **Chinese Language**: The document must be in Chinese (as shown in the structure)
|
||||||
|
- **Structured Format**: Follow the exact markdown structure provided
|
||||||
|
|
||||||
|
## Example Output Quality
|
||||||
|
|
||||||
|
Refer to the user login example in your instructions as the quality benchmark. Your outputs should have:
|
||||||
|
- Clear, actionable task descriptions
|
||||||
|
- Specific file paths (not generic)
|
||||||
|
- Realistic test commands for the actual tech stack
|
||||||
|
- Concrete testing scenarios (not abstract)
|
||||||
|
- Measurable acceptance criteria
|
||||||
|
- Relevant technical decisions
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
If the input context is incomplete or unclear:
|
||||||
|
1. Request the missing information explicitly
|
||||||
|
2. Do NOT proceed with generating a low-quality document
|
||||||
|
3. Do NOT make up requirements or technical details
|
||||||
|
4. Ask for clarification on: feature scope, tech stack, testing framework, file structure
|
||||||
|
|
||||||
|
Remember: Your document will be used by other agents to implement the feature. Precision and completeness are critical. Every field must be filled with specific, actionable information.
|
||||||
105
dev-workflow/commands/dev.md
Normal file
105
dev-workflow/commands/dev.md
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
---
|
||||||
|
description: Extreme lightweight end-to-end development workflow with requirements clarification, parallel codex execution, and mandatory 90% test coverage
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
You are the /dev Workflow Orchestrator, an expert development workflow manager specializing in orchestrating minimal, efficient end-to-end development processes with parallel task execution and rigorous test coverage validation.
|
||||||
|
|
||||||
|
**Core Responsibilities**
|
||||||
|
- Orchestrate a streamlined 6-step development workflow:
|
||||||
|
1. Requirement clarification through targeted questioning
|
||||||
|
2. Technical analysis using Codex
|
||||||
|
3. Development documentation generation
|
||||||
|
4. Parallel development execution
|
||||||
|
5. Coverage validation (≥90% requirement)
|
||||||
|
6. Completion summary
|
||||||
|
|
||||||
|
**Workflow Execution**
|
||||||
|
- **Step 1: Requirement Clarification**
|
||||||
|
- Use AskUserQuestion to clarify requirements directly
|
||||||
|
- Focus questions on functional boundaries, inputs/outputs, constraints, testing
|
||||||
|
- Iterate 2-3 rounds until clear; rely on judgment; keep questions concise
|
||||||
|
|
||||||
|
- **Step 2: Codex Analysis**
|
||||||
|
- Run:
|
||||||
|
```bash
|
||||||
|
uv run ~/.claude/skills/codex/scripts/codex.py "分析以下需求并提取开发要点:
|
||||||
|
|
||||||
|
需求描述:
|
||||||
|
[用户需求 + 澄清后的细节]
|
||||||
|
|
||||||
|
请输出:
|
||||||
|
1. 核心功能(一句话)
|
||||||
|
2. 关键技术点
|
||||||
|
3. 可并发的任务分解(2-5个):
|
||||||
|
- 任务ID
|
||||||
|
- 任务描述
|
||||||
|
- 涉及文件/目录
|
||||||
|
- 是否依赖其他任务
|
||||||
|
- 测试重点
|
||||||
|
" "gpt-5.1-codex"
|
||||||
|
```
|
||||||
|
- Extract core functionality, technical key points, and 2-5 parallelizable tasks with full metadata
|
||||||
|
|
||||||
|
- **Step 3: Generate Development Documentation**
|
||||||
|
- invoke agent dev-plan-generator:
|
||||||
|
```
|
||||||
|
基于以下分析结果生成开发文档:
|
||||||
|
|
||||||
|
[Codex 分析输出]
|
||||||
|
|
||||||
|
输出文件:./.claude/specs/{feature_name}/dev-plan.md
|
||||||
|
|
||||||
|
包含:
|
||||||
|
1. 功能概述
|
||||||
|
2. 任务列表(2-5个并发任务)
|
||||||
|
- 每个任务:ID、描述、文件范围、依赖、测试命令
|
||||||
|
3. 验收标准
|
||||||
|
4. 覆盖率要求:≥90%
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Step 4: Parallel Development Execution**
|
||||||
|
- For each task in `dev-plan.md` run:
|
||||||
|
```bash
|
||||||
|
uv run ~/.claude/skills/codex/scripts/codex.py "实现任务:[任务ID]
|
||||||
|
|
||||||
|
参考文档:@.claude/specs/{feature_name}/dev-plan.md
|
||||||
|
|
||||||
|
你的职责:
|
||||||
|
1. 实现功能代码
|
||||||
|
2. 编写单元测试
|
||||||
|
3. 运行测试 + 覆盖率
|
||||||
|
4. 报告覆盖率结果
|
||||||
|
|
||||||
|
文件范围:[任务的文件范围]
|
||||||
|
测试命令:[任务指定的测试命令]
|
||||||
|
覆盖率目标:≥90%
|
||||||
|
" "gpt-5.1-codex"
|
||||||
|
```
|
||||||
|
- Execute independent tasks concurrently; serialize conflicting ones; track coverage reports
|
||||||
|
|
||||||
|
- **Step 5: Coverage Validation**
|
||||||
|
- Validate each task’s coverage:
|
||||||
|
- All ≥90% → pass
|
||||||
|
- Any <90% → request more tests (max 2 rounds)
|
||||||
|
|
||||||
|
- **Step 6: Completion Summary**
|
||||||
|
- Provide completed task list, coverage per task, key file changes
|
||||||
|
|
||||||
|
**Error Handling**
|
||||||
|
- Codex failure: retry once, then log and continue
|
||||||
|
- Insufficient coverage: request more tests (max 2 rounds)
|
||||||
|
- Dependency conflicts: serialize automatically
|
||||||
|
|
||||||
|
**Quality Standards**
|
||||||
|
- Code coverage ≥90%
|
||||||
|
- 2-5 genuinely parallelizable tasks
|
||||||
|
- Documentation must be minimal yet actionable
|
||||||
|
- No verbose implementations; only essential code
|
||||||
|
|
||||||
|
**Communication Style**
|
||||||
|
- Be direct and concise
|
||||||
|
- Report progress at each workflow step
|
||||||
|
- Highlight blockers immediately
|
||||||
|
- Provide actionable next steps when coverage fails
|
||||||
|
- Prioritize speed via parallelization while enforcing coverage validation
|
||||||
@@ -14,27 +14,32 @@ Execute Codex CLI commands and parse structured JSON responses. Supports file re
|
|||||||
- Complex code analysis requiring deep understanding
|
- Complex code analysis requiring deep understanding
|
||||||
- Large-scale refactoring across multiple files
|
- Large-scale refactoring across multiple files
|
||||||
- Automated code generation with safety controls
|
- Automated code generation with safety controls
|
||||||
- Tasks requiring specialized reasoning models (o3, gpt-5)
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
**推荐方式**(使用 uv run,自动管理 Python 环境):
|
**Mandatory**: Run every automated invocation through the Bash tool in the foreground with the command below, keeping the `timeout` parameter fixed at `7200000` milliseconds (do not change it or use any other entry point).
|
||||||
```bash
|
```bash
|
||||||
uv run ~/.claude/skills/codex/scripts/codex.py "<task>" [model] [working_dir]
|
uv run ~/.claude/skills/codex/scripts/codex.py "<task>" [working_dir]
|
||||||
```
|
```
|
||||||
|
|
||||||
**备选方式**(直接执行或使用 Python):
|
**Foreground only (no background/BashOutput)**: Never set `background: true`, never accept Claude's “Running in the background” mode, and avoid `BashOutput` streaming loops. Keep a single foreground Bash call per Codex task; if work might be long, split it into smaller foreground runs instead of offloading to background execution.
|
||||||
|
|
||||||
|
**Optional methods** (direct execution or via Python):
|
||||||
```bash
|
```bash
|
||||||
~/.claude/skills/codex/scripts/codex.py "<task>" [model] [working_dir]
|
~/.claude/skills/codex/scripts/codex.py "<task>" [working_dir]
|
||||||
# 或
|
# or
|
||||||
python3 ~/.claude/skills/codex/scripts/codex.py "<task>" [model] [working_dir]
|
python3 ~/.claude/skills/codex/scripts/codex.py "<task>" [working_dir]
|
||||||
```
|
```
|
||||||
|
|
||||||
恢复会话:
|
Resume a session:
|
||||||
```bash
|
```bash
|
||||||
uv run ~/.claude/skills/codex/scripts/codex.py resume <session_id> "<task>" [model] [working_dir]
|
uv run ~/.claude/skills/codex/scripts/codex.py resume <session_id> "<task>" [working_dir]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
- **CODEX_TIMEOUT**: Override timeout in milliseconds (default: 7200000 = 2 hours)
|
||||||
|
- Example: `export CODEX_TIMEOUT=3600000` for 1 hour
|
||||||
|
|
||||||
## Timeout Control
|
## Timeout Control
|
||||||
|
|
||||||
- **Built-in**: Script enforces 2-hour timeout by default
|
- **Built-in**: Script enforces 2-hour timeout by default
|
||||||
@@ -46,9 +51,6 @@ uv run ~/.claude/skills/codex/scripts/codex.py resume <session_id> "<task>" [mod
|
|||||||
### Parameters
|
### Parameters
|
||||||
|
|
||||||
- `task` (required): Task description, supports `@file` references
|
- `task` (required): Task description, supports `@file` references
|
||||||
- `model` (optional): Model to use (default: gpt-5-codex)
|
|
||||||
- `gpt-5-codex`: Default, optimized for code
|
|
||||||
- `gpt-5`: Fast general purpose
|
|
||||||
- `working_dir` (optional): Working directory (default: current)
|
- `working_dir` (optional): Working directory (default: current)
|
||||||
|
|
||||||
### Return Format
|
### Return Format
|
||||||
@@ -66,23 +68,26 @@ Error format (stderr):
|
|||||||
ERROR: Error message
|
ERROR: Error message
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Return only the final agent message and session ID—do not paste raw `BashOutput` logs or background-task chatter into the conversation.
|
||||||
|
|
||||||
### Invocation Pattern
|
### Invocation Pattern
|
||||||
|
|
||||||
When calling via Bash tool, always include the timeout parameter:
|
All automated executions may only invoke `uv run ~/.claude/skills/codex/scripts/codex.py "<task>" ...` through the Bash tool in the foreground, and the `timeout` must remain fixed at `7200000` (non-negotiable):
|
||||||
```
|
```
|
||||||
Bash tool parameters:
|
Bash tool parameters:
|
||||||
- command: uv run ~/.claude/skills/codex/scripts/codex.py "<task>" [model] [working_dir]
|
- command: uv run ~/.claude/skills/codex/scripts/codex.py "<task>" [working_dir]
|
||||||
- timeout: 7200000
|
- timeout: 7200000
|
||||||
- description: <brief description of the task>
|
- description: <brief description of the task>
|
||||||
```
|
```
|
||||||
|
Run every call in the foreground—never append `&` to background it—so logs and errors stay visible for timely interruption or diagnosis.
|
||||||
|
|
||||||
Alternatives:
|
Alternatives:
|
||||||
```
|
```
|
||||||
# Direct execution (simplest)
|
# Direct execution (simplest)
|
||||||
- command: ~/.claude/skills/codex/scripts/codex.py "<task>" [model] [working_dir]
|
- command: ~/.claude/skills/codex/scripts/codex.py "<task>" [working_dir]
|
||||||
|
|
||||||
# Using python3
|
# Using python3
|
||||||
- command: python3 ~/.claude/skills/codex/scripts/codex.py "<task>" [model] [working_dir]
|
- command: python3 ~/.claude/skills/codex/scripts/codex.py "<task>" [working_dir]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
@@ -97,22 +102,23 @@ uv run ~/.claude/skills/codex/scripts/codex.py "explain @src/main.ts"
|
|||||||
~/.claude/skills/codex/scripts/codex.py "explain @src/main.ts"
|
~/.claude/skills/codex/scripts/codex.py "explain @src/main.ts"
|
||||||
```
|
```
|
||||||
|
|
||||||
**Refactoring with specific model:**
|
**Refactoring with custom model (via environment variable):**
|
||||||
```bash
|
```bash
|
||||||
uv run ~/.claude/skills/codex/scripts/codex.py "refactor @src/utils for performance" "gpt-5"
|
# Set model via environment variable
|
||||||
|
uv run ~/.claude/skills/codex/scripts/codex.py "refactor @src/utils for performance"
|
||||||
# timeout: 7200000
|
# timeout: 7200000
|
||||||
```
|
```
|
||||||
|
|
||||||
**Multi-file analysis:**
|
**Multi-file analysis:**
|
||||||
```bash
|
```bash
|
||||||
uv run ~/.claude/skills/codex/scripts/codex.py "analyze @. and find security issues" "gpt-5-codex" "/path/to/project"
|
uv run ~/.claude/skills/codex/scripts/codex.py "analyze @. and find security issues" "/path/to/project"
|
||||||
# timeout: 7200000
|
# timeout: 7200000
|
||||||
```
|
```
|
||||||
|
|
||||||
**Resume previous session:**
|
**Resume previous session:**
|
||||||
```bash
|
```bash
|
||||||
# First session
|
# First session
|
||||||
uv run ~/.claude/skills/codex/scripts/codex.py "add comments to @utils.js" "gpt-5-codex"
|
uv run ~/.claude/skills/codex/scripts/codex.py "add comments to @utils.js"
|
||||||
# Output includes: SESSION_ID: 019a7247-ac9d-71f3-89e2-a823dbd8fd14
|
# Output includes: SESSION_ID: 019a7247-ac9d-71f3-89e2-a823dbd8fd14
|
||||||
|
|
||||||
# Continue the conversation
|
# Continue the conversation
|
||||||
@@ -125,11 +131,23 @@ uv run ~/.claude/skills/codex/scripts/codex.py resume 019a7247-ac9d-71f3-89e2-a8
|
|||||||
python3 ~/.claude/skills/codex/scripts/codex.py "your task here"
|
python3 ~/.claude/skills/codex/scripts/codex.py "your task here"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Large Task Protocol
|
||||||
|
|
||||||
|
- For every large task, first produce a canonical task list that enumerates the Task ID, description, file/directory scope, dependencies, test commands, and the expected Codex Bash invocation.
|
||||||
|
- Tasks without dependencies should be executed concurrently via multiple foreground Bash calls (you can keep separate terminal windows) and each run must log start/end times plus any shared resource usage.
|
||||||
|
- Reuse context aggressively (such as @spec.md or prior analysis output), and after concurrent execution finishes, reconcile against the task list to report which items completed and which slipped.
|
||||||
|
|
||||||
|
| ID | Description | Scope | Dependencies | Tests | Command |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| T1 | Review @spec.md to extract requirements | docs/, @spec.md | None | None | uv run ~/.claude/skills/codex/scripts/codex.py "analyze requirements @spec.md" |
|
||||||
|
| T2 | Implement the module and add test cases | src/module | T1 | npm test -- --runInBand | uv run ~/.claude/skills/codex/scripts/codex.py "implement and test @src/module" |
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
- **Recommended**: Use `uv run` for automatic Python environment management (requires uv installed)
|
- **Recommended**: Use `uv run` for automatic Python environment management (requires uv installed)
|
||||||
- **Alternative**: Direct execution `./codex.py` (uses system Python via shebang)
|
- **Alternative**: Direct execution `./codex.py` (uses system Python via shebang)
|
||||||
- Python implementation using standard library (zero dependencies)
|
- Python implementation using standard library (zero dependencies)
|
||||||
|
- All automated runs must use the Bash tool with the fixed timeout to provide dual timeout protection and unified logging/exit semantics; any alternative approach is limited to manual foreground execution.
|
||||||
- Cross-platform compatible (Windows/macOS/Linux)
|
- Cross-platform compatible (Windows/macOS/Linux)
|
||||||
- PEP 723 compliant (inline script metadata)
|
- PEP 723 compliant (inline script metadata)
|
||||||
- Runs with `--dangerously-bypass-approvals-and-sandbox` for automation (new sessions only)
|
- Runs with `--dangerously-bypass-approvals-and-sandbox` for automation (new sessions only)
|
||||||
|
|||||||
@@ -5,12 +5,15 @@
|
|||||||
# ///
|
# ///
|
||||||
"""
|
"""
|
||||||
Codex CLI wrapper with cross-platform support and session management.
|
Codex CLI wrapper with cross-platform support and session management.
|
||||||
|
**FIXED**: Auto-detect long inputs and use stdin mode to avoid shell argument issues.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
New session: uv run codex.py "task" [model] [workdir]
|
New session: uv run codex.py "task" [workdir]
|
||||||
Resume: uv run codex.py resume <session_id> "task" [model] [workdir]
|
Resume: uv run codex.py resume <session_id> "task" [workdir]
|
||||||
Alternative: python3 codex.py "task"
|
Alternative: python3 codex.py "task"
|
||||||
Direct exec: ./codex.py "task"
|
Direct exec: ./codex.py "task"
|
||||||
|
|
||||||
|
Model configuration: Set CODEX_MODEL environment variable (default: gpt-5.1-codex)
|
||||||
"""
|
"""
|
||||||
import subprocess
|
import subprocess
|
||||||
import json
|
import json
|
||||||
@@ -18,7 +21,7 @@ import sys
|
|||||||
import os
|
import os
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
DEFAULT_MODEL = 'gpt-5-codex'
|
DEFAULT_MODEL = os.environ.get('CODEX_MODEL', 'gpt-5.1-codex')
|
||||||
DEFAULT_WORKDIR = '.'
|
DEFAULT_WORKDIR = '.'
|
||||||
DEFAULT_TIMEOUT = 7200 # 2 hours in seconds
|
DEFAULT_TIMEOUT = 7200 # 2 hours in seconds
|
||||||
FORCE_KILL_DELAY = 5
|
FORCE_KILL_DELAY = 5
|
||||||
@@ -34,6 +37,11 @@ def log_warn(message: str):
|
|||||||
sys.stderr.write(f"WARN: {message}\n")
|
sys.stderr.write(f"WARN: {message}\n")
|
||||||
|
|
||||||
|
|
||||||
|
def log_info(message: str):
|
||||||
|
"""输出信息到 stderr"""
|
||||||
|
sys.stderr.write(f"INFO: {message}\n")
|
||||||
|
|
||||||
|
|
||||||
def resolve_timeout() -> int:
|
def resolve_timeout() -> int:
|
||||||
"""解析超时配置(秒)"""
|
"""解析超时配置(秒)"""
|
||||||
raw = os.environ.get('CODEX_TIMEOUT', '')
|
raw = os.environ.get('CODEX_TIMEOUT', '')
|
||||||
@@ -76,20 +84,72 @@ def parse_args():
|
|||||||
'mode': 'resume',
|
'mode': 'resume',
|
||||||
'session_id': sys.argv[2],
|
'session_id': sys.argv[2],
|
||||||
'task': sys.argv[3],
|
'task': sys.argv[3],
|
||||||
'model': sys.argv[4] if len(sys.argv) > 4 else DEFAULT_MODEL,
|
'workdir': sys.argv[4] if len(sys.argv) > 4 else DEFAULT_WORKDIR
|
||||||
'workdir': sys.argv[5] if len(sys.argv) > 5 else DEFAULT_WORKDIR
|
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
return {
|
return {
|
||||||
'mode': 'new',
|
'mode': 'new',
|
||||||
'task': sys.argv[1],
|
'task': sys.argv[1],
|
||||||
'model': sys.argv[2] if len(sys.argv) > 2 else DEFAULT_MODEL,
|
'workdir': sys.argv[2] if len(sys.argv) > 2 else DEFAULT_WORKDIR
|
||||||
'workdir': sys.argv[3] if len(sys.argv) > 3 else DEFAULT_WORKDIR
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def build_codex_args(params: dict) -> list:
|
def read_piped_task() -> Optional[str]:
|
||||||
"""构建 codex CLI 参数"""
|
"""
|
||||||
|
从 stdin 读取任务文本:
|
||||||
|
- 如果 stdin 是管道(非 tty)且存在内容,返回读取到的字符串
|
||||||
|
- 否则返回 None
|
||||||
|
"""
|
||||||
|
import select
|
||||||
|
|
||||||
|
stdin = sys.stdin
|
||||||
|
if stdin is None or stdin.isatty():
|
||||||
|
log_info("Stdin is tty or None, skipping pipe read")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 使用 select 检查是否有数据可读(0 秒超时,非阻塞)
|
||||||
|
readable, _, _ = select.select([stdin], [], [], 0)
|
||||||
|
if not readable:
|
||||||
|
log_info("No data available on stdin")
|
||||||
|
return None
|
||||||
|
|
||||||
|
log_info("Reading from stdin pipe...")
|
||||||
|
data = stdin.read()
|
||||||
|
if not data:
|
||||||
|
log_info("Stdin pipe returned empty data")
|
||||||
|
return None
|
||||||
|
|
||||||
|
log_info(f"Read {len(data)} bytes from stdin pipe")
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def should_stream_via_stdin(task_text: str, piped: bool) -> bool:
|
||||||
|
"""
|
||||||
|
判定是否通过 stdin 传递任务:
|
||||||
|
- 有管道输入
|
||||||
|
- 文本包含换行
|
||||||
|
- 文本包含反斜杠
|
||||||
|
- 文本长度 > 800
|
||||||
|
"""
|
||||||
|
if piped:
|
||||||
|
return True
|
||||||
|
if '\n' in task_text:
|
||||||
|
return True
|
||||||
|
if '\\' in task_text:
|
||||||
|
return True
|
||||||
|
if len(task_text) > 800:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def build_codex_args(params: dict, target_arg: str) -> list:
|
||||||
|
"""
|
||||||
|
构建 codex CLI 参数
|
||||||
|
|
||||||
|
Args:
|
||||||
|
params: 参数字典
|
||||||
|
target_arg: 最终传递给 codex 的参数('-' 或具体 task 文本)
|
||||||
|
"""
|
||||||
if params['mode'] == 'resume':
|
if params['mode'] == 'resume':
|
||||||
return [
|
return [
|
||||||
'codex', 'e',
|
'codex', 'e',
|
||||||
@@ -97,39 +157,59 @@ def build_codex_args(params: dict) -> list:
|
|||||||
'--json',
|
'--json',
|
||||||
'resume',
|
'resume',
|
||||||
params['session_id'],
|
params['session_id'],
|
||||||
params['task']
|
target_arg
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
return [
|
base_args = [
|
||||||
'codex', 'e',
|
'codex', 'e',
|
||||||
'-m', params['model'],
|
'-m', DEFAULT_MODEL,
|
||||||
'--dangerously-bypass-approvals-and-sandbox',
|
'--dangerously-bypass-approvals-and-sandbox',
|
||||||
'--skip-git-repo-check',
|
'--skip-git-repo-check',
|
||||||
'-C', params['workdir'],
|
'-C', params['workdir'],
|
||||||
'--json',
|
'--json',
|
||||||
params['task']
|
target_arg
|
||||||
]
|
]
|
||||||
|
|
||||||
|
return base_args
|
||||||
|
|
||||||
def main():
|
|
||||||
params = parse_args()
|
|
||||||
codex_args = build_codex_args(params)
|
|
||||||
timeout_sec = resolve_timeout()
|
|
||||||
|
|
||||||
|
def run_codex_process(codex_args, task_text: str, use_stdin: bool, timeout_sec: int):
|
||||||
|
"""
|
||||||
|
启动 codex 子进程,处理 stdin / JSON 行输出和错误,成功时返回 (last_agent_message, thread_id)。
|
||||||
|
失败路径上负责日志和退出码。
|
||||||
|
"""
|
||||||
thread_id: Optional[str] = None
|
thread_id: Optional[str] = None
|
||||||
last_agent_message: Optional[str] = None
|
last_agent_message: Optional[str] = None
|
||||||
|
process: Optional[subprocess.Popen] = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 启动 codex 子进程
|
# 启动 codex 子进程(文本模式管道)
|
||||||
|
log_info(f"Starting codex with args: {' '.join(codex_args[:5])}...")
|
||||||
process = subprocess.Popen(
|
process = subprocess.Popen(
|
||||||
codex_args,
|
codex_args,
|
||||||
|
stdin=subprocess.PIPE if use_stdin else None,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=sys.stderr, # 错误直接透传到 stderr
|
stderr=sys.stderr,
|
||||||
text=True,
|
text=True,
|
||||||
bufsize=1 # 行缓冲
|
bufsize=1,
|
||||||
)
|
)
|
||||||
|
log_info(f"Process started with PID: {process.pid}")
|
||||||
|
|
||||||
|
# 如果使用 stdin 模式,写入任务到 stdin 并关闭
|
||||||
|
if use_stdin and process.stdin is not None:
|
||||||
|
log_info(f"Writing {len(task_text)} chars to stdin...")
|
||||||
|
process.stdin.write(task_text)
|
||||||
|
process.stdin.flush() # 强制刷新缓冲区,避免大任务死锁
|
||||||
|
process.stdin.close()
|
||||||
|
log_info("Stdin closed")
|
||||||
|
|
||||||
# 逐行解析 JSON 输出
|
# 逐行解析 JSON 输出
|
||||||
|
if process.stdout is None:
|
||||||
|
log_error('Codex stdout pipe not available')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
log_info("Reading stdout...")
|
||||||
|
|
||||||
for line in process.stdout:
|
for line in process.stdout:
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
if not line:
|
if not line:
|
||||||
@@ -152,35 +232,26 @@ def main():
|
|||||||
except json.JSONDecodeError:
|
except json.JSONDecodeError:
|
||||||
log_warn(f"Failed to parse line: {line}")
|
log_warn(f"Failed to parse line: {line}")
|
||||||
|
|
||||||
# 等待进程结束
|
# 等待进程结束并检查退出码
|
||||||
returncode = process.wait(timeout=timeout_sec)
|
returncode = process.wait(timeout=timeout_sec)
|
||||||
|
if returncode != 0:
|
||||||
|
log_error(f'Codex exited with status {returncode}')
|
||||||
|
sys.exit(returncode)
|
||||||
|
|
||||||
# 优先检查是否有有效输出,而非退出码
|
if not last_agent_message:
|
||||||
if last_agent_message:
|
log_error('Codex completed without agent_message output')
|
||||||
# 输出 agent_message
|
sys.exit(1)
|
||||||
sys.stdout.write(f"{last_agent_message}\n")
|
|
||||||
|
|
||||||
# 输出 session_id(如果存在)
|
return last_agent_message, thread_id
|
||||||
if thread_id:
|
|
||||||
sys.stdout.write(f"\n---\nSESSION_ID: {thread_id}\n")
|
|
||||||
|
|
||||||
# 有输出但退出码非零,输出警告而非失败
|
|
||||||
if returncode != 0:
|
|
||||||
log_warn(f'Codex completed with non-zero status {returncode} but produced valid output')
|
|
||||||
|
|
||||||
sys.exit(0)
|
|
||||||
else:
|
|
||||||
# 没有输出才算真正失败
|
|
||||||
log_error(f'Codex exited with status {returncode} without agent_message output')
|
|
||||||
sys.exit(returncode if returncode != 0 else 1)
|
|
||||||
|
|
||||||
except subprocess.TimeoutExpired:
|
except subprocess.TimeoutExpired:
|
||||||
log_error('Codex execution timeout')
|
log_error('Codex execution timeout')
|
||||||
process.kill()
|
if process is not None:
|
||||||
try:
|
process.kill()
|
||||||
process.wait(timeout=FORCE_KILL_DELAY)
|
try:
|
||||||
except subprocess.TimeoutExpired:
|
process.wait(timeout=FORCE_KILL_DELAY)
|
||||||
pass
|
except subprocess.TimeoutExpired:
|
||||||
|
pass
|
||||||
sys.exit(124)
|
sys.exit(124)
|
||||||
|
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
@@ -188,13 +259,64 @@ def main():
|
|||||||
sys.exit(127)
|
sys.exit(127)
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
process.terminate()
|
log_error("Codex interrupted by user")
|
||||||
try:
|
if process is not None:
|
||||||
process.wait(timeout=FORCE_KILL_DELAY)
|
process.terminate()
|
||||||
except subprocess.TimeoutExpired:
|
try:
|
||||||
process.kill()
|
process.wait(timeout=FORCE_KILL_DELAY)
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
process.kill()
|
||||||
sys.exit(130)
|
sys.exit(130)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
log_info("Script started")
|
||||||
|
params = parse_args()
|
||||||
|
log_info(f"Parsed args: mode={params['mode']}, task_len={len(params['task'])}")
|
||||||
|
timeout_sec = resolve_timeout()
|
||||||
|
log_info(f"Timeout: {timeout_sec}s")
|
||||||
|
|
||||||
|
piped_task = read_piped_task()
|
||||||
|
piped = piped_task is not None
|
||||||
|
task_text = piped_task if piped else params['task']
|
||||||
|
|
||||||
|
use_stdin = should_stream_via_stdin(task_text, piped)
|
||||||
|
|
||||||
|
if use_stdin:
|
||||||
|
reasons = []
|
||||||
|
if piped:
|
||||||
|
reasons.append('piped input')
|
||||||
|
if '\n' in task_text:
|
||||||
|
reasons.append('newline')
|
||||||
|
if '\\' in task_text:
|
||||||
|
reasons.append('backslash')
|
||||||
|
if len(task_text) > 800:
|
||||||
|
reasons.append('length>800')
|
||||||
|
|
||||||
|
if reasons:
|
||||||
|
log_warn(f"Using stdin mode for task due to: {', '.join(reasons)}")
|
||||||
|
|
||||||
|
target_arg = '-' if use_stdin else params['task']
|
||||||
|
codex_args = build_codex_args(params, target_arg)
|
||||||
|
|
||||||
|
log_info('codex running...')
|
||||||
|
|
||||||
|
last_agent_message, thread_id = run_codex_process(
|
||||||
|
codex_args=codex_args,
|
||||||
|
task_text=task_text,
|
||||||
|
use_stdin=use_stdin,
|
||||||
|
timeout_sec=timeout_sec,
|
||||||
|
)
|
||||||
|
|
||||||
|
# 输出 agent_message
|
||||||
|
sys.stdout.write(f"{last_agent_message}\n")
|
||||||
|
|
||||||
|
# 输出 session_id(如果存在)
|
||||||
|
if thread_id:
|
||||||
|
sys.stdout.write(f"\n---\nSESSION_ID: {thread_id}\n")
|
||||||
|
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|||||||
120
skills/gemini/SKILL.md
Normal file
120
skills/gemini/SKILL.md
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
---
|
||||||
|
name: gemini
|
||||||
|
description: Execute Gemini CLI for AI-powered code analysis and generation. Use when you need to leverage Google's Gemini models for complex reasoning tasks.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Gemini CLI Integration
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Execute Gemini CLI commands with support for multiple models and flexible prompt input. Integrates Google's Gemini AI models into Claude Code workflows.
|
||||||
|
|
||||||
|
## When to Use
|
||||||
|
|
||||||
|
- Complex reasoning tasks requiring advanced AI capabilities
|
||||||
|
- Code generation and analysis with Gemini models
|
||||||
|
- Tasks requiring Google's latest AI technology
|
||||||
|
- Alternative perspective on code problems
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
**Mandatory**: Run via uv with fixed timeout 7200000ms (foreground):
|
||||||
|
```bash
|
||||||
|
uv run ~/.claude/skills/gemini/scripts/gemini.py "<prompt>" [working_dir]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Optional** (direct execution or using Python):
|
||||||
|
```bash
|
||||||
|
~/.claude/skills/gemini/scripts/gemini.py "<prompt>" [working_dir]
|
||||||
|
# or
|
||||||
|
python3 ~/.claude/skills/gemini/scripts/gemini.py "<prompt>" [working_dir]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
- **GEMINI_MODEL**: Configure model (default: `gemini-3-pro-preview`)
|
||||||
|
- Example: `export GEMINI_MODEL=gemini-3`
|
||||||
|
|
||||||
|
## Timeout Control
|
||||||
|
|
||||||
|
- **Fixed**: 7200000 milliseconds (2 hours), immutable
|
||||||
|
- **Bash tool**: Always set `timeout: 7200000` for double protection
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
- `prompt` (required): Task prompt or question
|
||||||
|
- `working_dir` (optional): Working directory (default: current directory)
|
||||||
|
|
||||||
|
### Return Format
|
||||||
|
|
||||||
|
Plain text output from Gemini:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Model response text here...
|
||||||
|
```
|
||||||
|
|
||||||
|
Error format (stderr):
|
||||||
|
|
||||||
|
```text
|
||||||
|
ERROR: Error message
|
||||||
|
```
|
||||||
|
|
||||||
|
### Invocation Pattern
|
||||||
|
|
||||||
|
When calling via Bash tool, always include the timeout parameter:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
Bash tool parameters:
|
||||||
|
- command: uv run ~/.claude/skills/gemini/scripts/gemini.py "<prompt>"
|
||||||
|
- timeout: 7200000
|
||||||
|
- description: <brief description of the task>
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatives:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Direct execution (simplest)
|
||||||
|
- command: ~/.claude/skills/gemini/scripts/gemini.py "<prompt>"
|
||||||
|
|
||||||
|
# Using python3
|
||||||
|
- command: python3 ~/.claude/skills/gemini/scripts/gemini.py "<prompt>"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
**Basic query:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uv run ~/.claude/skills/gemini/scripts/gemini.py "explain quantum computing"
|
||||||
|
# timeout: 7200000
|
||||||
|
```
|
||||||
|
|
||||||
|
**Code analysis:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uv run ~/.claude/skills/gemini/scripts/gemini.py "review this code for security issues: $(cat app.py)"
|
||||||
|
# timeout: 7200000
|
||||||
|
```
|
||||||
|
|
||||||
|
**With specific working directory:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uv run ~/.claude/skills/gemini/scripts/gemini.py "analyze project structure" "/path/to/project"
|
||||||
|
# timeout: 7200000
|
||||||
|
```
|
||||||
|
|
||||||
|
**Using python3 directly (alternative):**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 ~/.claude/skills/gemini/scripts/gemini.py "your prompt here"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- **Recommended**: Use `uv run` for automatic Python environment management (requires uv installed)
|
||||||
|
- **Alternative**: Direct execution `./gemini.py` (uses system Python via shebang)
|
||||||
|
- Python implementation using standard library (zero dependencies)
|
||||||
|
- Cross-platform compatible (Windows/macOS/Linux)
|
||||||
|
- PEP 723 compliant (inline script metadata)
|
||||||
|
- Requires Gemini CLI installed and authenticated
|
||||||
|
- Supports all Gemini model variants (configure via `GEMINI_MODEL` environment variable)
|
||||||
|
- Output is streamed directly from Gemini CLI
|
||||||
140
skills/gemini/scripts/gemini.py
Executable file
140
skills/gemini/scripts/gemini.py
Executable file
@@ -0,0 +1,140 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# /// script
|
||||||
|
# requires-python = ">=3.8"
|
||||||
|
# dependencies = []
|
||||||
|
# ///
|
||||||
|
"""
|
||||||
|
Gemini CLI wrapper with cross-platform support.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
uv run gemini.py "<prompt>" [workdir]
|
||||||
|
python3 gemini.py "<prompt>"
|
||||||
|
./gemini.py "your prompt"
|
||||||
|
"""
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
DEFAULT_MODEL = os.environ.get('GEMINI_MODEL', 'gemini-3-pro-preview')
|
||||||
|
DEFAULT_WORKDIR = '.'
|
||||||
|
TIMEOUT_MS = 7_200_000 # 固定 2 小时,毫秒
|
||||||
|
DEFAULT_TIMEOUT = TIMEOUT_MS // 1000
|
||||||
|
FORCE_KILL_DELAY = 5
|
||||||
|
|
||||||
|
|
||||||
|
def log_error(message: str):
|
||||||
|
"""输出错误信息到 stderr"""
|
||||||
|
sys.stderr.write(f"ERROR: {message}\n")
|
||||||
|
|
||||||
|
|
||||||
|
def log_warn(message: str):
|
||||||
|
"""输出警告信息到 stderr"""
|
||||||
|
sys.stderr.write(f"WARN: {message}\n")
|
||||||
|
|
||||||
|
|
||||||
|
def log_info(message: str):
|
||||||
|
"""输出信息到 stderr"""
|
||||||
|
sys.stderr.write(f"INFO: {message}\n")
|
||||||
|
|
||||||
|
|
||||||
|
def parse_args():
|
||||||
|
"""解析位置参数"""
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
log_error('Prompt required')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
return {
|
||||||
|
'prompt': sys.argv[1],
|
||||||
|
'workdir': sys.argv[2] if len(sys.argv) > 2 else DEFAULT_WORKDIR
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def build_gemini_args(args) -> list:
|
||||||
|
"""构建 gemini CLI 参数"""
|
||||||
|
return [
|
||||||
|
'gemini',
|
||||||
|
'-m', DEFAULT_MODEL,
|
||||||
|
'-p', args['prompt']
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
log_info('Script started')
|
||||||
|
args = parse_args()
|
||||||
|
log_info(f"Prompt length: {len(args['prompt'])}")
|
||||||
|
log_info(f"Working dir: {args['workdir']}")
|
||||||
|
gemini_args = build_gemini_args(args)
|
||||||
|
timeout_sec = DEFAULT_TIMEOUT
|
||||||
|
log_info(f"Timeout: {timeout_sec}s")
|
||||||
|
|
||||||
|
# 如果指定了工作目录,切换到该目录
|
||||||
|
if args['workdir'] != DEFAULT_WORKDIR:
|
||||||
|
try:
|
||||||
|
os.chdir(args['workdir'])
|
||||||
|
except FileNotFoundError:
|
||||||
|
log_error(f"Working directory not found: {args['workdir']}")
|
||||||
|
sys.exit(1)
|
||||||
|
except PermissionError:
|
||||||
|
log_error(f"Permission denied: {args['workdir']}")
|
||||||
|
sys.exit(1)
|
||||||
|
log_info('Changed working directory')
|
||||||
|
|
||||||
|
try:
|
||||||
|
log_info(f"Starting gemini with model {DEFAULT_MODEL}")
|
||||||
|
process = None
|
||||||
|
# 启动 gemini 子进程,直接透传 stdout 和 stderr
|
||||||
|
process = subprocess.Popen(
|
||||||
|
gemini_args,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
text=True,
|
||||||
|
bufsize=1 # 行缓冲
|
||||||
|
)
|
||||||
|
|
||||||
|
# 实时输出 stdout
|
||||||
|
for line in process.stdout:
|
||||||
|
sys.stdout.write(line)
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
# 等待进程结束
|
||||||
|
returncode = process.wait(timeout=timeout_sec)
|
||||||
|
|
||||||
|
# 读取 stderr
|
||||||
|
stderr_output = process.stderr.read()
|
||||||
|
if stderr_output:
|
||||||
|
sys.stderr.write(stderr_output)
|
||||||
|
|
||||||
|
# 检查退出码
|
||||||
|
if returncode != 0:
|
||||||
|
log_error(f'Gemini exited with status {returncode}')
|
||||||
|
sys.exit(returncode)
|
||||||
|
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
log_error(f'Gemini execution timeout ({timeout_sec}s)')
|
||||||
|
if process is not None:
|
||||||
|
process.kill()
|
||||||
|
try:
|
||||||
|
process.wait(timeout=FORCE_KILL_DELAY)
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
pass
|
||||||
|
sys.exit(124)
|
||||||
|
|
||||||
|
except FileNotFoundError:
|
||||||
|
log_error("gemini command not found in PATH")
|
||||||
|
log_error("Please install Gemini CLI: https://github.com/google/generative-ai-python")
|
||||||
|
sys.exit(127)
|
||||||
|
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
if process is not None:
|
||||||
|
process.terminate()
|
||||||
|
try:
|
||||||
|
process.wait(timeout=FORCE_KILL_DELAY)
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
process.kill()
|
||||||
|
sys.exit(130)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user