mirror of
https://github.com/cexll/myclaude.git
synced 2026-02-13 03:31:49 +08:00
fix codex skill eof
This commit is contained in:
@@ -17,25 +17,40 @@ Execute Codex CLI commands and parse structured JSON responses. Supports file re
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
**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).
|
**Mandatory**: Run every automated invocation through the Bash tool in the foreground with **HEREDOC syntax** to avoid shell quoting issues, 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>" [working_dir]
|
uv run ~/.claude/skills/codex/scripts/codex.py - [working_dir] <<'EOF'
|
||||||
|
<task content here>
|
||||||
|
EOF
|
||||||
```
|
```
|
||||||
|
|
||||||
**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.
|
**Why HEREDOC?** Tasks often contain code blocks, nested quotes, shell metacharacters (`$`, `` ` ``, `\`), and multiline text. HEREDOC (Here Document) syntax passes these safely without shell interpretation, eliminating quote-escaping nightmares.
|
||||||
|
|
||||||
**Optional methods** (direct execution or via 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.
|
||||||
|
|
||||||
|
**Simple tasks** (backward compatibility):
|
||||||
|
For simple single-line tasks without special characters, you can still use direct quoting:
|
||||||
```bash
|
```bash
|
||||||
~/.claude/skills/codex/scripts/codex.py "<task>" [working_dir]
|
uv run ~/.claude/skills/codex/scripts/codex.py "simple task here" [working_dir]
|
||||||
# or
|
|
||||||
python3 ~/.claude/skills/codex/scripts/codex.py "<task>" [working_dir]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Resume a session:
|
**Resume a session with HEREDOC:**
|
||||||
```bash
|
```bash
|
||||||
uv run ~/.claude/skills/codex/scripts/codex.py resume <session_id> "<task>" [working_dir]
|
uv run ~/.claude/skills/codex/scripts/codex.py resume <session_id> - [working_dir] <<'EOF'
|
||||||
|
<task content>
|
||||||
|
EOF
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Cross-platform notes:**
|
||||||
|
- **Bash/Zsh**: Use `<<'EOF'` (single quotes prevent variable expansion)
|
||||||
|
- **PowerShell 5.1+**: Use `@'` and `'@` (here-string syntax)
|
||||||
|
```powershell
|
||||||
|
uv run ~/.claude/skills/codex/scripts/codex.py - @'
|
||||||
|
task content
|
||||||
|
'@
|
||||||
|
```
|
||||||
|
|
||||||
## Environment Variables
|
## Environment Variables
|
||||||
- **CODEX_TIMEOUT**: Override timeout in milliseconds (default: 7200000 = 2 hours)
|
- **CODEX_TIMEOUT**: Override timeout in milliseconds (default: 7200000 = 2 hours)
|
||||||
- Example: `export CODEX_TIMEOUT=3600000` for 1 hour
|
- Example: `export CODEX_TIMEOUT=3600000` for 1 hour
|
||||||
@@ -72,63 +87,82 @@ Return only the final agent message and session ID—do not paste raw `BashOutpu
|
|||||||
|
|
||||||
### Invocation Pattern
|
### Invocation Pattern
|
||||||
|
|
||||||
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):
|
All automated executions must use HEREDOC syntax through the Bash tool in the foreground, with `timeout` fixed at `7200000` (non-negotiable):
|
||||||
|
|
||||||
```
|
```
|
||||||
Bash tool parameters:
|
Bash tool parameters:
|
||||||
- command: uv run ~/.claude/skills/codex/scripts/codex.py "<task>" [working_dir]
|
- command: uv run ~/.claude/skills/codex/scripts/codex.py - [working_dir] <<'EOF'
|
||||||
|
<task content>
|
||||||
|
EOF
|
||||||
- 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.
|
Run every call in the foreground—never append `&` to background it—so logs and errors stay visible for timely interruption or diagnosis.
|
||||||
|
|
||||||
Alternatives:
|
**Important:** Use HEREDOC (`<<'EOF'`) for all but the simplest tasks. This prevents shell interpretation of quotes, variables, and special characters.
|
||||||
```
|
|
||||||
# Direct execution (simplest)
|
|
||||||
- command: ~/.claude/skills/codex/scripts/codex.py "<task>" [working_dir]
|
|
||||||
|
|
||||||
# Using python3
|
|
||||||
- command: python3 ~/.claude/skills/codex/scripts/codex.py "<task>" [working_dir]
|
|
||||||
```
|
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
**Basic code analysis:**
|
**Basic code analysis:**
|
||||||
```bash
|
```bash
|
||||||
# Recommended: via uv run (auto-manages Python environment)
|
# Recommended: via uv run with HEREDOC (handles any special characters)
|
||||||
uv run ~/.claude/skills/codex/scripts/codex.py "explain @src/main.ts"
|
uv run ~/.claude/skills/codex/scripts/codex.py - <<'EOF'
|
||||||
|
explain @src/main.ts
|
||||||
|
EOF
|
||||||
# timeout: 7200000
|
# timeout: 7200000
|
||||||
|
|
||||||
# Alternative: direct execution
|
# Alternative: simple direct quoting (if task is simple)
|
||||||
~/.claude/skills/codex/scripts/codex.py "explain @src/main.ts"
|
uv run ~/.claude/skills/codex/scripts/codex.py "explain @src/main.ts"
|
||||||
```
|
```
|
||||||
|
|
||||||
**Refactoring with custom model (via environment variable):**
|
**Refactoring with multiline instructions:**
|
||||||
```bash
|
```bash
|
||||||
# Set model via environment variable
|
uv run ~/.claude/skills/codex/scripts/codex.py - <<'EOF'
|
||||||
uv run ~/.claude/skills/codex/scripts/codex.py "refactor @src/utils for performance"
|
refactor @src/utils for performance:
|
||||||
|
- Extract duplicate code into helpers
|
||||||
|
- Use memoization for expensive calculations
|
||||||
|
- Add inline comments for non-obvious logic
|
||||||
|
EOF
|
||||||
# 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" "/path/to/project"
|
uv run ~/.claude/skills/codex/scripts/codex.py - "/path/to/project" <<'EOF'
|
||||||
|
analyze @. and find security issues:
|
||||||
|
1. Check for SQL injection vulnerabilities
|
||||||
|
2. Identify XSS risks in templates
|
||||||
|
3. Review authentication/authorization logic
|
||||||
|
4. Flag hardcoded credentials or secrets
|
||||||
|
EOF
|
||||||
# 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"
|
uv run ~/.claude/skills/codex/scripts/codex.py - <<'EOF'
|
||||||
|
add comments to @utils.js explaining the caching logic
|
||||||
|
EOF
|
||||||
# Output includes: SESSION_ID: 019a7247-ac9d-71f3-89e2-a823dbd8fd14
|
# Output includes: SESSION_ID: 019a7247-ac9d-71f3-89e2-a823dbd8fd14
|
||||||
|
|
||||||
# Continue the conversation
|
# Continue the conversation with more context
|
||||||
uv run ~/.claude/skills/codex/scripts/codex.py resume 019a7247-ac9d-71f3-89e2-a823dbd8fd14 "now add type hints"
|
uv run ~/.claude/skills/codex/scripts/codex.py resume 019a7247-ac9d-71f3-89e2-a823dbd8fd14 - <<'EOF'
|
||||||
|
now add TypeScript type hints and handle edge cases where cache is null
|
||||||
|
EOF
|
||||||
# timeout: 7200000
|
# timeout: 7200000
|
||||||
```
|
```
|
||||||
|
|
||||||
**Using python3 directly (alternative):**
|
**Task with code snippets and special characters:**
|
||||||
```bash
|
```bash
|
||||||
python3 ~/.claude/skills/codex/scripts/codex.py "your task here"
|
uv run ~/.claude/skills/codex/scripts/codex.py - <<'EOF'
|
||||||
|
Fix the bug in @app.js where the regex /\d+/ doesn't match "123"
|
||||||
|
The current code is:
|
||||||
|
const re = /\d+/;
|
||||||
|
if (re.test(input)) { ... }
|
||||||
|
Add proper escaping and handle $variables correctly.
|
||||||
|
EOF
|
||||||
```
|
```
|
||||||
|
|
||||||
### Large Task Protocol
|
### Large Task Protocol
|
||||||
@@ -139,8 +173,8 @@ python3 ~/.claude/skills/codex/scripts/codex.py "your task here"
|
|||||||
|
|
||||||
| ID | Description | Scope | Dependencies | Tests | Command |
|
| 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" |
|
| T1 | Review @spec.md to extract requirements | docs/, @spec.md | None | None | `uv run ~/.claude/skills/codex/scripts/codex.py - <<'EOF'`<br/>`analyze requirements @spec.md`<br/>`EOF` |
|
||||||
| 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" |
|
| T2 | Implement the module and add test cases | src/module | T1 | npm test -- --runInBand | `uv run ~/.claude/skills/codex/scripts/codex.py - <<'EOF'`<br/>`implement and test @src/module`<br/>`EOF` |
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ Codex CLI wrapper with cross-platform support and session management.
|
|||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
New session: uv run codex.py "task" [workdir]
|
New session: uv run codex.py "task" [workdir]
|
||||||
|
Stdin mode: uv run codex.py - [workdir]
|
||||||
Resume: uv run codex.py resume <session_id> "task" [workdir]
|
Resume: uv run codex.py resume <session_id> "task" [workdir]
|
||||||
|
Resume stdin: uv run codex.py resume <session_id> - [workdir]
|
||||||
Alternative: python3 codex.py "task"
|
Alternative: python3 codex.py "task"
|
||||||
Direct exec: ./codex.py "task"
|
Direct exec: ./codex.py "task"
|
||||||
|
|
||||||
@@ -80,19 +82,23 @@ def parse_args():
|
|||||||
if len(sys.argv) < 4:
|
if len(sys.argv) < 4:
|
||||||
log_error('Resume mode requires: resume <session_id> <task>')
|
log_error('Resume mode requires: resume <session_id> <task>')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
task_arg = sys.argv[3]
|
||||||
return {
|
return {
|
||||||
'mode': 'resume',
|
'mode': 'resume',
|
||||||
'session_id': sys.argv[2],
|
'session_id': sys.argv[2],
|
||||||
'task': sys.argv[3],
|
'task': task_arg,
|
||||||
'workdir': sys.argv[4] if len(sys.argv) > 4 else DEFAULT_WORKDIR
|
'explicit_stdin': task_arg == '-',
|
||||||
}
|
'workdir': sys.argv[4] if len(sys.argv) > 4 else DEFAULT_WORKDIR,
|
||||||
else:
|
|
||||||
return {
|
|
||||||
'mode': 'new',
|
|
||||||
'task': sys.argv[1],
|
|
||||||
'workdir': sys.argv[2] if len(sys.argv) > 2 else DEFAULT_WORKDIR
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task_arg = sys.argv[1]
|
||||||
|
return {
|
||||||
|
'mode': 'new',
|
||||||
|
'task': task_arg,
|
||||||
|
'explicit_stdin': task_arg == '-',
|
||||||
|
'workdir': sys.argv[2] if len(sys.argv) > 2 else DEFAULT_WORKDIR,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def read_piped_task() -> Optional[str]:
|
def read_piped_task() -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
@@ -100,19 +106,10 @@ def read_piped_task() -> Optional[str]:
|
|||||||
- 如果 stdin 是管道(非 tty)且存在内容,返回读取到的字符串
|
- 如果 stdin 是管道(非 tty)且存在内容,返回读取到的字符串
|
||||||
- 否则返回 None
|
- 否则返回 None
|
||||||
"""
|
"""
|
||||||
import select
|
|
||||||
|
|
||||||
stdin = sys.stdin
|
stdin = sys.stdin
|
||||||
if stdin is None or stdin.isatty():
|
if stdin is None or stdin.isatty():
|
||||||
log_info("Stdin is tty or None, skipping pipe read")
|
log_info("Stdin is tty or None, skipping pipe read")
|
||||||
return None
|
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...")
|
log_info("Reading from stdin pipe...")
|
||||||
data = stdin.read()
|
data = stdin.read()
|
||||||
if not data:
|
if not data:
|
||||||
@@ -153,6 +150,7 @@ def build_codex_args(params: dict, target_arg: str) -> list:
|
|||||||
if params['mode'] == 'resume':
|
if params['mode'] == 'resume':
|
||||||
return [
|
return [
|
||||||
'codex', 'e',
|
'codex', 'e',
|
||||||
|
'-m', DEFAULT_MODEL,
|
||||||
'--skip-git-repo-check',
|
'--skip-git-repo-check',
|
||||||
'--json',
|
'--json',
|
||||||
'resume',
|
'resume',
|
||||||
@@ -276,16 +274,28 @@ def main():
|
|||||||
timeout_sec = resolve_timeout()
|
timeout_sec = resolve_timeout()
|
||||||
log_info(f"Timeout: {timeout_sec}s")
|
log_info(f"Timeout: {timeout_sec}s")
|
||||||
|
|
||||||
piped_task = read_piped_task()
|
explicit_stdin = params.get('explicit_stdin', False)
|
||||||
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 explicit_stdin:
|
||||||
|
log_info("Explicit stdin mode: reading task from stdin")
|
||||||
|
task_text = sys.stdin.read()
|
||||||
|
if not task_text:
|
||||||
|
log_error("Explicit stdin mode requires task input from stdin")
|
||||||
|
sys.exit(1)
|
||||||
|
piped = not sys.stdin.isatty()
|
||||||
|
else:
|
||||||
|
piped_task = read_piped_task()
|
||||||
|
piped = piped_task is not None
|
||||||
|
task_text = piped_task if piped else params['task']
|
||||||
|
|
||||||
|
use_stdin = explicit_stdin or should_stream_via_stdin(task_text, piped)
|
||||||
|
|
||||||
if use_stdin:
|
if use_stdin:
|
||||||
reasons = []
|
reasons = []
|
||||||
if piped:
|
if piped:
|
||||||
reasons.append('piped input')
|
reasons.append('piped input')
|
||||||
|
if explicit_stdin:
|
||||||
|
reasons.append('explicit "-"')
|
||||||
if '\n' in task_text:
|
if '\n' in task_text:
|
||||||
reasons.append('newline')
|
reasons.append('newline')
|
||||||
if '\\' in task_text:
|
if '\\' in task_text:
|
||||||
|
|||||||
Reference in New Issue
Block a user