Add CLI endpoints documentation and unified script template for Bash and Python

- Updated AGENTS.md to include CLI tools usage and configuration details.
- Introduced a new script template for both Bash and Python, outlining usage context, calling conventions, and implementation guidelines.
- Provided examples for common patterns in both Bash and Python scripts.
- Established a directory convention for script organization and naming.
This commit is contained in:
catlog22
2026-01-28 21:29:21 +08:00
parent 24dad8cefd
commit b361a8c041
8 changed files with 648 additions and 2137 deletions

View File

@@ -9,12 +9,7 @@
**Strictly follow the cli-tools.json configuration**
Available CLI endpoints are dynamically defined by the config file:
- Built-in tools and their enable/disable status
- Custom API endpoints registered via the Dashboard
- Managed through the CCW Dashboard Status page
Available CLI endpoints are dynamically defined by the config file
## Tool Execution
- **Context Requirements**: @~/.claude/workflows/context-tools.md

View File

@@ -105,8 +105,7 @@ Phase 01 → Phase 02 → Phase 03 → ... → Phase N
| [templates/autonomous-action.md](templates/autonomous-action.md) | Autonomous Action 模板 |
| [templates/code-analysis-action.md](templates/code-analysis-action.md) | 代码分析 Action 模板 |
| [templates/llm-action.md](templates/llm-action.md) | LLM Action 模板 |
| [templates/script-bash.md](templates/script-bash.md) | Bash 脚本模板 |
| [templates/script-python.md](templates/script-python.md) | Python 脚本模板 |
| [templates/script-template.md](templates/script-template.md) | 统一脚本模板 (Bash + Python) |
### 规范文档 (按需阅读)
@@ -371,8 +370,7 @@ ELSE IF execution_mode === "autonomous":
| [autonomous-action.md](templates/autonomous-action.md) | Action files | Phase 3 |
| [code-analysis-action.md](templates/code-analysis-action.md) | Code analysis actions | Phase 3 |
| [llm-action.md](templates/llm-action.md) | LLM-powered actions | Phase 3 |
| [script-bash.md](templates/script-bash.md) | Bash scripts | Phase 3/4 |
| [script-python.md](templates/script-python.md) | Python scripts | Phase 3/4 |
| [script-template.md](templates/script-template.md) | Bash + Python scripts | Phase 3/4 |
## Output Structure

View File

@@ -84,10 +84,42 @@ return {
| `{{error_handling_table}}` | 错误处理表格 |
| `{{next_actions_hints}}` | 后续动作提示 |
## 动作生命周期
```
状态驱动执行流:
state.status === 'pending'
┌─ Init ─┐ ← 1次执行环境准备
│ 创建工作目录 │
│ 初始化 context │
│ status → running │
└────┬────┘
┌─ CRUD Loop ─┐ ← N次迭代核心业务
│ 编排器选择动作 │ List / Create / Edit / Delete
│ execute(state) │ 共享模式: 收集输入 → 操作 context.items → 返回更新
│ 更新 state │
└────┬────┘
┌─ Complete ─┐ ← 1次执行保存结果
│ 序列化输出 │
│ status → completed │
└──────────┘
共享状态结构:
state.status → 'pending' | 'running' | 'completed'
state.context.items → 业务数据数组
state.completed_actions → 已执行动作 ID 列表
```
## 动作类型模板
### 1. 初始化动作 (Init)
**触发条件**: `state.status === 'pending'`,仅执行一次
```markdown
# Action: Initialize
@@ -105,101 +137,29 @@ return {
\`\`\`javascript
async function execute(state) {
// 1. 创建工作目录
Bash(\`mkdir -p "\${workDir}"\`);
// 2. 初始化数据
const initialData = {
items: [],
metadata: {}
};
// 3. 返回状态更新
return {
stateUpdates: {
status: 'running',
context: initialData
started_at: new Date().toISOString(),
context: { items: [], metadata: {} }
}
};
}
\`\`\`
## State Updates
\`\`\`javascript
return {
stateUpdates: {
status: 'running',
started_at: new Date().toISOString(),
context: { /* 初始数据 */ }
}
};
\`\`\`
## Next Actions
- 成功: 进入主处理循环
- 成功: 进入主处理循环 (由编排器选择首个 CRUD 动作)
- 失败: action-abort
```
### 2. 列表动作 (List)
### 2. CRUD 动作 (List / Create / Edit / Delete)
```markdown
# Action: List Items
**触发条件**: `state.status === 'running'`,循环执行直至用户退出
显示当前项目列表
## Purpose
展示所有项目供用户查看和选择。
## Preconditions
- [ ] state.status === 'running'
## Execution
\`\`\`javascript
async function execute(state) {
const items = state.context.items || [];
if (items.length === 0) {
console.log('暂无项目');
} else {
console.log('项目列表:');
items.forEach((item, i) => {
console.log(\`\${i + 1}. \${item.name} - \${item.status}\`);
});
}
return {
stateUpdates: {
last_action: 'list',
current_view: 'list'
}
};
}
\`\`\`
## State Updates
\`\`\`javascript
return {
stateUpdates: {
current_view: 'list',
last_viewed_at: new Date().toISOString()
}
};
\`\`\`
## Next Actions
- 用户选择创建: action-create
- 用户选择编辑: action-edit
- 用户退出: action-complete
```
### 3. 创建动作 (Create)
> 以 Create 为示例展示共享模式。List / Edit / Delete 遵循同一结构,仅 `执行逻辑` 和 `状态更新字段` 不同
```markdown
# Action: Create Item
@@ -208,7 +168,7 @@ return {
## Purpose
引导用户创建新项目
收集用户输入,向 context.items 追加新记录
## Preconditions
@@ -218,26 +178,24 @@ return {
\`\`\`javascript
async function execute(state) {
// 1. 收集信息
// 1. 收集输入
const input = await AskUserQuestion({
questions: [{
question: "请输入项目名称:",
header: "名称",
multiSelect: false,
options: [
{ label: "手动输入", description: "输入自定义名称" }
]
options: [{ label: "手动输入", description: "输入自定义名称" }]
}]
});
// 2. 创建项目
// 2. 操作 context.items (核心逻辑因动作类型而异)
const newItem = {
id: Date.now().toString(),
name: input["名称"],
status: 'pending',
created_at: new Date().toISOString()
};
// 3. 返回状态更新
return {
stateUpdates: {
@@ -245,177 +203,30 @@ async function execute(state) {
...state.context,
items: [...(state.context.items || []), newItem]
},
last_created_id: newItem.id
last_action: 'create'
}
};
}
\`\`\`
## State Updates
\`\`\`javascript
return {
stateUpdates: {
'context.items': [...items, newItem],
last_action: 'create',
last_created_id: newItem.id
}
};
\`\`\`
## Next Actions
- 继续创建: action-create
- 返回列表: action-list
- 继续操作: 编排器根据 state 选择下一动作
- 用户退出: action-complete
```
### 4. 编辑动作 (Edit)
**其他 CRUD 动作差异对照:**
```markdown
# Action: Edit Item
| 动作 | 核心逻辑 | 额外前置条件 | 关键状态字段 |
|------|---------|------------|------------|
| List | `items.forEach(→ console.log)` | 无 | `current_view: 'list'` |
| Create | `items.push(newItem)` | 无 | `last_created_id` |
| Edit | `items.map(→ 替换匹配项)` | `selected_item_id !== null` | `updated_at` |
| Delete | `items.filter(→ 排除匹配项)` | `selected_item_id !== null` | 确认对话 → 执行 |
编辑现有项目。
### 3. 完成动作 (Complete)
## Purpose
修改已存在的项目。
## Preconditions
- [ ] state.status === 'running'
- [ ] state.selected_item_id !== null
## Execution
\`\`\`javascript
async function execute(state) {
const itemId = state.selected_item_id;
const items = state.context.items || [];
const item = items.find(i => i.id === itemId);
if (!item) {
throw new Error(\`Item not found: \${itemId}\`);
}
// 1. 显示当前值
console.log(\`当前名称: \${item.name}\`);
// 2. 收集新值
const input = await AskUserQuestion({
questions: [{
question: "请输入新名称(留空保持不变):",
header: "新名称",
multiSelect: false,
options: [
{ label: "保持不变", description: \`当前: \${item.name}\` },
{ label: "手动输入", description: "输入新名称" }
]
}]
});
// 3. 更新项目
const updatedItems = items.map(i =>
i.id === itemId
? { ...i, name: input["新名称"] || i.name, updated_at: new Date().toISOString() }
: i
);
return {
stateUpdates: {
context: { ...state.context, items: updatedItems },
selected_item_id: null
}
};
}
\`\`\`
## State Updates
\`\`\`javascript
return {
stateUpdates: {
'context.items': updatedItems,
selected_item_id: null,
last_action: 'edit'
}
};
\`\`\`
## Next Actions
- 返回列表: action-list
```
### 5. 删除动作 (Delete)
```markdown
# Action: Delete Item
删除项目。
## Purpose
从列表中移除项目。
## Preconditions
- [ ] state.status === 'running'
- [ ] state.selected_item_id !== null
## Execution
\`\`\`javascript
async function execute(state) {
const itemId = state.selected_item_id;
const items = state.context.items || [];
// 1. 确认删除
const confirm = await AskUserQuestion({
questions: [{
question: "确认删除此项目?",
header: "确认",
multiSelect: false,
options: [
{ label: "确认删除", description: "不可恢复" },
{ label: "取消", description: "返回列表" }
]
}]
});
if (confirm["确认"] === "取消") {
return { stateUpdates: { selected_item_id: null } };
}
// 2. 执行删除
const updatedItems = items.filter(i => i.id !== itemId);
return {
stateUpdates: {
context: { ...state.context, items: updatedItems },
selected_item_id: null
}
};
}
\`\`\`
## State Updates
\`\`\`javascript
return {
stateUpdates: {
'context.items': filteredItems,
selected_item_id: null,
last_action: 'delete'
}
};
\`\`\`
## Next Actions
- 返回列表: action-list
```
### 6. 完成动作 (Complete)
**触发条件**: 用户明确退出或终止条件满足,仅执行一次
```markdown
# Action: Complete
@@ -424,7 +235,7 @@ return {
## Purpose
保存最终状态,结束 Skill 执行。
序列化最终状态,结束 Skill 执行。
## Preconditions
@@ -434,41 +245,26 @@ return {
\`\`\`javascript
async function execute(state) {
// 1. 保存最终数据
Write(\`\${workDir}/final-output.json\`, JSON.stringify(state.context, null, 2));
// 2. 生成摘要
const summary = {
total_items: state.context.items?.length || 0,
duration: Date.now() - new Date(state.started_at).getTime(),
actions_executed: state.completed_actions.length
};
console.log('任务完成');
console.log(\`处理项目: \${summary.total_items}\`);
console.log(\`执行动作: \${summary.actions_executed}\`);
console.log(\`任务完成: \${summary.total_items} 项, \${summary.actions_executed} 次操作\`);
return {
stateUpdates: {
status: 'completed',
summary: summary
completed_at: new Date().toISOString(),
summary
}
};
}
\`\`\`
## State Updates
\`\`\`javascript
return {
stateUpdates: {
status: 'completed',
completed_at: new Date().toISOString(),
summary: { /* 统计信息 */ }
}
};
\`\`\`
## Next Actions
- 无(终止状态)

View File

@@ -1,291 +0,0 @@
# Bash Script Template
Bash 脚本模板,用于生成技能中的确定性脚本。
## Purpose
为 Skill 生成 Bash 脚本,用于执行确定性操作(文件处理、系统命令、数据转换等)。
## Usage Context
| Phase | Usage |
|-------|-------|
| Optional | Phase/Action 中声明 `## Scripts` 时使用 |
| Execution | 通过 `ExecuteScript('script-id', params)` 调用 |
| Output Location | `.claude/skills/{skill-name}/scripts/{script-id}.sh` |
---
## 模板代码
```bash
#!/bin/bash
# {{script_description}}
set -euo pipefail
# ============================================================
# 参数解析
# ============================================================
INPUT_PATH=""
OUTPUT_DIR="" # 由调用方指定,不设默认值
show_help() {
echo "用法: $0 --input-path <path> --output-dir <dir>"
echo ""
echo "参数:"
echo " --input-path 输入文件路径 (必需)"
echo " --output-dir 输出目录 (必需,由调用方指定)"
echo " --help 显示帮助信息"
}
while [[ "$#" -gt 0 ]]; do
case $1 in
--input-path)
INPUT_PATH="$2"
shift
;;
--output-dir)
OUTPUT_DIR="$2"
shift
;;
--help)
show_help
exit 0
;;
*)
echo "错误: 未知参数 $1" >&2
show_help >&2
exit 1
;;
esac
shift
done
# ============================================================
# 参数验证
# ============================================================
if [[ -z "$INPUT_PATH" ]]; then
echo "错误: --input-path 是必需参数" >&2
exit 1
fi
if [[ -z "$OUTPUT_DIR" ]]; then
echo "错误: --output-dir 是必需参数" >&2
exit 1
fi
if [[ ! -f "$INPUT_PATH" ]]; then
echo "错误: 输入文件不存在: $INPUT_PATH" >&2
exit 1
fi
# 检查 jq 是否可用(用于 JSON 输出)
if ! command -v jq &> /dev/null; then
echo "错误: 需要安装 jq" >&2
exit 1
fi
mkdir -p "$OUTPUT_DIR"
# ============================================================
# 核心逻辑
# ============================================================
OUTPUT_FILE="$OUTPUT_DIR/result.txt"
ITEMS_COUNT=0
# TODO: 实现处理逻辑
# 示例:处理输入文件
while IFS= read -r line; do
echo "$line" >> "$OUTPUT_FILE"
((ITEMS_COUNT++))
done < "$INPUT_PATH"
# ============================================================
# 输出 JSON 结果(使用 jq 构建,避免特殊字符问题)
# ============================================================
jq -n \
--arg output_file "$OUTPUT_FILE" \
--argjson items_processed "$ITEMS_COUNT" \
'{output_file: $output_file, items_processed: $items_processed, status: "success"}'
```
## 变量说明
| 变量 | 说明 |
|------|------|
| `{{script_description}}` | 脚本功能描述 |
## 使用规范
### 脚本头部
```bash
#!/bin/bash
set -euo pipefail # 严格模式:出错退出、未定义变量报错、管道错误传递
```
### 参数解析模式
```bash
while [[ "$#" -gt 0 ]]; do
case $1 in
--param-name)
PARAM_VAR="$2"
shift
;;
--flag)
FLAG_VAR=true
;;
*)
echo "Unknown: $1" >&2
exit 1
;;
esac
shift
done
```
### 输出格式
- 最后一行打印单行 JSON
- **强烈推荐使用 `jq`**:自动处理转义和类型
```bash
# 推荐:使用 jq 构建(安全、可靠)
jq -n \
--arg file "$FILE" \
--argjson count "$COUNT" \
'{output_file: $file, items_processed: $count}'
# 备选:简单场景手动拼接(注意特殊字符转义)
echo "{\"file\": \"$FILE\", \"count\": $COUNT}"
```
**jq 参数类型**
- `--arg name value`:字符串类型
- `--argjson name value`:数字/布尔/null 类型
### 错误处理
```bash
# 验证错误
if [[ -z "$PARAM" ]]; then
echo "错误: 参数不能为空" >&2
exit 1
fi
# 命令错误
if ! command -v jq &> /dev/null; then
echo "错误: 需要安装 jq" >&2
exit 1
fi
# 运行时错误
if ! some_command; then
echo "错误: 命令执行失败" >&2
exit 1
fi
```
## 常用模式
### 文件遍历
```bash
for file in "$INPUT_DIR"/*.json; do
[[ -f "$file" ]] || continue
echo "处理: $file"
# 处理逻辑...
done
```
### 临时文件
```bash
TEMP_FILE=$(mktemp)
trap "rm -f $TEMP_FILE" EXIT
echo "data" > "$TEMP_FILE"
```
### 调用其他工具
```bash
# 检查工具存在
require_command() {
if ! command -v "$1" &> /dev/null; then
echo "错误: 需要 $1" >&2
exit 1
fi
}
require_command jq
require_command curl
```
### JSON 处理(使用 jq
```bash
# 读取 JSON 字段
VALUE=$(jq -r '.field' "$INPUT_PATH")
# 修改 JSON
jq '.field = "new_value"' "$INPUT_PATH" > "$OUTPUT_FILE"
# 合并 JSON 文件
jq -s 'add' file1.json file2.json > merged.json
```
## 生成函数
```javascript
function generateBashScript(scriptConfig) {
return `#!/bin/bash
# ${scriptConfig.description}
set -euo pipefail
# 参数定义
${scriptConfig.inputs.map(i =>
`${i.name.toUpperCase().replace(/-/g, '_')}="${i.default || ''}"`
).join('\n')}
# 参数解析
while [[ "$#" -gt 0 ]]; do
case $1 in
${scriptConfig.inputs.map(i =>
` --${i.name})
${i.name.toUpperCase().replace(/-/g, '_')}="$2"
shift
;;`
).join('\n')}
*)
echo "未知参数: $1" >&2
exit 1
;;
esac
shift
done
# 参数验证
${scriptConfig.inputs.filter(i => i.required).map(i =>
`if [[ -z "$${i.name.toUpperCase().replace(/-/g, '_')}" ]]; then
echo "错误: --${i.name} 是必需参数" >&2
exit 1
fi`
).join('\n\n')}
# TODO: 实现处理逻辑
# 输出结果
echo "{${scriptConfig.outputs.map(o =>
`\\"${o.name}\\": \\"\\$${o.name.toUpperCase().replace(/-/g, '_')}\\"`
).join(', ')}}"
`;
}
```

View File

@@ -1,212 +0,0 @@
# Python Script Template
Python 脚本模板,用于生成技能中的确定性脚本。
## Purpose
为 Skill 生成 Python 脚本,用于执行确定性操作(数据处理、分析、转换等),比 Bash 提供更强的数据处理能力。
## Usage Context
| Phase | Usage |
|-------|-------|
| Optional | Phase/Action 中声明 `## Scripts` 时使用 |
| Execution | 通过 `ExecuteScript('script-id', params)` 调用 |
| Output Location | `.claude/skills/{skill-name}/scripts/{script-id}.py` |
---
## 模板代码
```python
#!/usr/bin/env python3
"""
{{script_description}}
"""
import argparse
import json
import sys
from pathlib import Path
def main():
# 1. 定义参数
parser = argparse.ArgumentParser(description='{{script_description}}')
parser.add_argument('--input-path', type=str, required=True,
help='输入文件路径')
parser.add_argument('--output-dir', type=str, required=True,
help='输出目录(由调用方指定)')
# 添加更多参数...
args = parser.parse_args()
# 2. 验证输入
input_path = Path(args.input_path)
if not input_path.exists():
print(f"错误: 输入文件不存在: {input_path}", file=sys.stderr)
sys.exit(1)
output_dir = Path(args.output_dir)
output_dir.mkdir(parents=True, exist_ok=True)
# 3. 执行核心逻辑
try:
result = process(input_path, output_dir)
except Exception as e:
print(f"错误: {e}", file=sys.stderr)
sys.exit(1)
# 4. 输出 JSON 结果
print(json.dumps(result))
def process(input_path: Path, output_dir: Path) -> dict:
"""
核心处理逻辑
Args:
input_path: 输入文件路径
output_dir: 输出目录
Returns:
dict: 包含输出结果的字典
"""
# TODO: 实现处理逻辑
output_file = output_dir / 'result.json'
# 示例:读取并处理数据
with open(input_path, 'r', encoding='utf-8') as f:
data = json.load(f)
# 处理数据...
processed_count = len(data) if isinstance(data, list) else 1
# 写入输出
with open(output_file, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
return {
'output_file': str(output_file),
'items_processed': processed_count,
'status': 'success'
}
if __name__ == '__main__':
main()
```
## 变量说明
| 变量 | 说明 |
|------|------|
| `{{script_description}}` | 脚本功能描述 |
## 使用规范
### 输入参数
- 使用 `argparse` 定义参数
- 参数名使用 kebab-case`--input-path`
- 必需参数设置 `required=True`
- 可选参数提供 `default`
### 输出格式
- 最后一行打印单行 JSON
- 包含所有输出文件路径和关键数据
- 错误信息输出到 stderr
### 错误处理
```python
# 验证错误 - 直接退出
if not valid:
print("错误信息", file=sys.stderr)
sys.exit(1)
# 运行时错误 - 捕获并退出
try:
result = process()
except Exception as e:
print(f"错误: {e}", file=sys.stderr)
sys.exit(1)
```
## 常用模式
### 文件处理
```python
def process_files(input_dir: Path, pattern: str = '*.json') -> list:
results = []
for file in input_dir.glob(pattern):
with open(file, 'r') as f:
data = json.load(f)
results.append({'file': str(file), 'data': data})
return results
```
### 数据转换
```python
def transform_data(data: dict) -> dict:
return {
'id': data.get('id'),
'name': data.get('name', '').strip(),
'timestamp': datetime.now().isoformat()
}
```
### 调用外部命令
```python
import subprocess
def run_command(cmd: list) -> str:
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
raise RuntimeError(result.stderr)
return result.stdout
```
## 生成函数
```javascript
function generatePythonScript(scriptConfig) {
return `#!/usr/bin/env python3
"""
${scriptConfig.description}
"""
import argparse
import json
import sys
from pathlib import Path
def main():
parser = argparse.ArgumentParser(description='${scriptConfig.description}')
${scriptConfig.inputs.map(i =>
` parser.add_argument('--${i.name}', type=${i.type || 'str'}, ${i.required ? 'required=True' : `default='${i.default}'`},
help='${i.description}')`
).join('\n')}
args = parser.parse_args()
# TODO: 实现处理逻辑
result = {
${scriptConfig.outputs.map(o =>
` '${o.name}': None # ${o.description}`
).join(',\n')}
}
print(json.dumps(result))
if __name__ == '__main__':
main()
`;
}
```

View File

@@ -0,0 +1,368 @@
# Script Template
统一的脚本模板,覆盖 Bash 和 Python 两种运行时。
## Usage Context
| Phase | Usage |
|-------|-------|
| Optional | Phase/Action 中声明 `## Scripts` 时使用 |
| Execution | 通过 `ExecuteScript('script-id', params)` 调用 |
| Output Location | `.claude/skills/{skill-name}/scripts/{script-id}.{ext}` |
---
## 调用接口规范
所有脚本共享相同的调用约定:
```
调用者
↓ ExecuteScript('script-id', { key: value })
脚本入口
├─ 参数解析 (--key value)
├─ 输入验证 (必需参数检查, 文件存在)
├─ 核心处理 (数据读取 → 转换 → 写入)
└─ 输出结果 (最后一行: 单行 JSON → stdout)
├─ 成功: {"status":"success", "output_file":"...", ...}
└─ 失败: stderr 输出错误信息, exit 1
```
### 返回格式
```typescript
interface ScriptResult {
success: boolean; // exit code === 0
stdout: string; // 标准输出
stderr: string; // 标准错误
outputs: object; // 从 stdout 最后一行解析的 JSON
}
```
### 参数约定
| 参数 | 必需 | 说明 |
|------|------|------|
| `--input-path` | ✓ | 输入文件路径 |
| `--output-dir` | ✓ | 输出目录(由调用方指定) |
| 其他 | 按需 | 脚本特定参数 |
---
## Bash 实现
```bash
#!/bin/bash
# {{script_description}}
set -euo pipefail
# ============================================================
# 参数解析
# ============================================================
INPUT_PATH=""
OUTPUT_DIR=""
while [[ "$#" -gt 0 ]]; do
case $1 in
--input-path) INPUT_PATH="$2"; shift ;;
--output-dir) OUTPUT_DIR="$2"; shift ;;
--help)
echo "用法: $0 --input-path <path> --output-dir <dir>"
exit 0
;;
*)
echo "错误: 未知参数 $1" >&2
exit 1
;;
esac
shift
done
# ============================================================
# 参数验证
# ============================================================
[[ -z "$INPUT_PATH" ]] && { echo "错误: --input-path 是必需参数" >&2; exit 1; }
[[ -z "$OUTPUT_DIR" ]] && { echo "错误: --output-dir 是必需参数" >&2; exit 1; }
[[ ! -f "$INPUT_PATH" ]] && { echo "错误: 输入文件不存在: $INPUT_PATH" >&2; exit 1; }
command -v jq &> /dev/null || { echo "错误: 需要安装 jq" >&2; exit 1; }
mkdir -p "$OUTPUT_DIR"
# ============================================================
# 核心逻辑
# ============================================================
OUTPUT_FILE="$OUTPUT_DIR/result.txt"
ITEMS_COUNT=0
# TODO: 实现处理逻辑
while IFS= read -r line; do
echo "$line" >> "$OUTPUT_FILE"
((ITEMS_COUNT++))
done < "$INPUT_PATH"
# ============================================================
# 输出 JSON 结果(使用 jq 构建,避免转义问题)
# ============================================================
jq -n \
--arg output_file "$OUTPUT_FILE" \
--argjson items_processed "$ITEMS_COUNT" \
'{output_file: $output_file, items_processed: $items_processed, status: "success"}'
```
### Bash 常用模式
```bash
# 文件遍历
for file in "$INPUT_DIR"/*.json; do
[[ -f "$file" ]] || continue
# 处理逻辑...
done
# 临时文件 (自动清理)
TEMP_FILE=$(mktemp)
trap "rm -f $TEMP_FILE" EXIT
# 工具依赖检查
require_command() {
command -v "$1" &> /dev/null || { echo "错误: 需要 $1" >&2; exit 1; }
}
require_command jq
# jq 处理
VALUE=$(jq -r '.field' "$INPUT_PATH") # 读取字段
jq '.field = "new"' input.json > output.json # 修改字段
jq -s 'add' file1.json file2.json > merged.json # 合并文件
```
---
## Python 实现
```python
#!/usr/bin/env python3
"""
{{script_description}}
"""
import argparse
import json
import sys
from pathlib import Path
def main():
parser = argparse.ArgumentParser(description='{{script_description}}')
parser.add_argument('--input-path', type=str, required=True, help='输入文件路径')
parser.add_argument('--output-dir', type=str, required=True, help='输出目录')
args = parser.parse_args()
# 验证输入
input_path = Path(args.input_path)
if not input_path.exists():
print(f"错误: 输入文件不存在: {input_path}", file=sys.stderr)
sys.exit(1)
output_dir = Path(args.output_dir)
output_dir.mkdir(parents=True, exist_ok=True)
# 执行处理
try:
result = process(input_path, output_dir)
except Exception as e:
print(f"错误: {e}", file=sys.stderr)
sys.exit(1)
# 输出 JSON 结果
print(json.dumps(result))
def process(input_path: Path, output_dir: Path) -> dict:
"""核心处理逻辑"""
# TODO: 实现处理逻辑
output_file = output_dir / 'result.json'
with open(input_path, 'r', encoding='utf-8') as f:
data = json.load(f)
processed_count = len(data) if isinstance(data, list) else 1
with open(output_file, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
return {
'output_file': str(output_file),
'items_processed': processed_count,
'status': 'success'
}
if __name__ == '__main__':
main()
```
### Python 常用模式
```python
# 文件遍历
def process_files(input_dir: Path, pattern: str = '*.json') -> list:
return [
{'file': str(f), 'data': json.load(f.open())}
for f in input_dir.glob(pattern)
]
# 数据转换
def transform(data: dict) -> dict:
return {
'id': data.get('id'),
'name': data.get('name', '').strip(),
'timestamp': datetime.now().isoformat()
}
# 外部命令调用
import subprocess
def run_command(cmd: list) -> str:
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
raise RuntimeError(result.stderr)
return result.stdout
```
---
## 运行时选择指南
```
任务特征
├─ 文件处理 / 系统命令 / 管道操作
│ └─ 选 Bash (.sh)
├─ JSON 数据处理 / 复杂转换 / 数据分析
│ └─ 选 Python (.py)
└─ 简单读写 / 格式转换
└─ 任选Bash 更轻量)
```
---
## 生成函数
```javascript
function generateScript(scriptConfig) {
const runtime = scriptConfig.runtime || 'bash'; // 'bash' | 'python'
const ext = runtime === 'python' ? '.py' : '.sh';
if (runtime === 'python') {
return generatePythonScript(scriptConfig);
}
return generateBashScript(scriptConfig);
}
function generateBashScript(scriptConfig) {
const { description, inputs = [], outputs = [] } = scriptConfig;
const paramDefs = inputs.map(i =>
`${i.name.toUpperCase().replace(/-/g, '_')}="${i.default || ''}"`
).join('\n');
const paramParse = inputs.map(i =>
` --${i.name}) ${i.name.toUpperCase().replace(/-/g, '_')}="$2"; shift ;;`
).join('\n');
const paramValidation = inputs.filter(i => i.required).map(i => {
const VAR = i.name.toUpperCase().replace(/-/g, '_');
return `[[ -z "$${VAR}" ]] && { echo "错误: --${i.name} 是必需参数" >&2; exit 1; }`;
}).join('\n');
return `#!/bin/bash
# ${description}
set -euo pipefail
${paramDefs}
while [[ "$#" -gt 0 ]]; do
case $1 in
${paramParse}
*) echo "未知参数: $1" >&2; exit 1 ;;
esac
shift
done
${paramValidation}
# TODO: 实现处理逻辑
# 输出结果 (jq 构建)
jq -n ${outputs.map(o =>
`--arg ${o.name} "$${o.name.toUpperCase().replace(/-/g, '_')}"`
).join(' \\\n ')} \
'{${outputs.map(o => `${o.name}: $${o.name}`).join(', ')}}'
`;
}
function generatePythonScript(scriptConfig) {
const { description, inputs = [], outputs = [] } = scriptConfig;
const argDefs = inputs.map(i =>
` parser.add_argument('--${i.name}', type=${i.type || 'str'}, ${
i.required ? 'required=True' : `default='${i.default || ''}'`
}, help='${i.description || i.name}')`
).join('\n');
const resultFields = outputs.map(o =>
` '${o.name}': None # ${o.description || o.name}`
).join(',\n');
return `#!/usr/bin/env python3
"""
${description}
"""
import argparse
import json
import sys
from pathlib import Path
def main():
parser = argparse.ArgumentParser(description='${description}')
${argDefs}
args = parser.parse_args()
# TODO: 实现处理逻辑
result = {
${resultFields}
}
print(json.dumps(result))
if __name__ == '__main__':
main()
`;
}
```
---
## 目录约定
```
scripts/
├── process-data.py # id: process-data, runtime: python
├── validate.sh # id: validate, runtime: bash
└── transform.js # id: transform, runtime: node
```
- **命名即 ID**: 文件名(不含扩展名)= 脚本 ID
- **扩展名即运行时**: `.py` → python, `.sh` → bash, `.js` → node

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,14 @@
# Codex Code Guidelines
## CLI Endpoints
- **CLI Tools Usage**: @~/.claude/workflows/cli-tools-usage.md
- **CLI Endpoints Config**: @~/.claude/cli-tools.json
**Strictly follow the cli-tools.json configuration**
Available CLI endpoints are dynamically defined by the config file
## Code Quality Standards
### Code Quality