mirror of
https://github.com/cexll/myclaude.git
synced 2026-02-08 02:54:09 +08:00
Compare commits
6 Commits
v4.7-alpha
...
v4.7.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
11afae2dff | ||
|
|
3df4fec6dd | ||
|
|
aea19f0e1f | ||
|
|
291a4e3d0a | ||
|
|
957b737126 | ||
|
|
3e30f4e207 |
@@ -1,95 +0,0 @@
|
||||
# Claude Code Plugin System
|
||||
|
||||
本项目已支持Claude Code插件系统,可以将命令和代理打包成可安装的插件包。
|
||||
|
||||
## 插件配置
|
||||
|
||||
插件配置文件位于 `.claude-plugin/marketplace.json`,定义了所有可用的插件包。
|
||||
|
||||
## 可用插件
|
||||
|
||||
### 1. Requirements-Driven Development
|
||||
- **描述**: 需求驱动的开发工作流,包含90%质量门控
|
||||
- **命令**: `/requirements-pilot`
|
||||
- **代理**: requirements-generate, requirements-code, requirements-testing, requirements-review
|
||||
|
||||
### 2. BMAD Agile Workflow
|
||||
- **描述**: 完整的BMAD敏捷工作流(产品负责人→架构师→SM→开发→QA)
|
||||
- **命令**: `/bmad-pilot`
|
||||
- **代理**: bmad-po, bmad-architect, bmad-sm, bmad-dev, bmad-qa, bmad-orchestrator
|
||||
|
||||
### 3. Development Essentials
|
||||
- **描述**: 核心开发命令套件
|
||||
- **命令**: `/code`, `/debug`, `/test`, `/optimize`, `/review`, `/bugfix`, `/refactor`, `/docs`, `/ask`, `/think`
|
||||
- **代理**: code, bugfix, bugfix-verify, code-optimize, debug, develop
|
||||
|
||||
### 4. Advanced AI Agents
|
||||
- **描述**: 高级AI代理,集成GPT-5进行深度分析
|
||||
- **代理**: gpt5
|
||||
|
||||
## 使用插件命令
|
||||
|
||||
### 列出所有可用插件
|
||||
```bash
|
||||
/plugin list
|
||||
```
|
||||
|
||||
### 查看插件详情
|
||||
```bash
|
||||
/plugin info <plugin-name>
|
||||
```
|
||||
例如:`/plugin info requirements-driven-development`
|
||||
|
||||
### 安装插件
|
||||
```bash
|
||||
/plugin install <plugin-name>
|
||||
```
|
||||
例如:`/plugin install bmad-agile-workflow`
|
||||
|
||||
### 移除插件
|
||||
```bash
|
||||
/plugin remove <plugin-name>
|
||||
```
|
||||
|
||||
## 创建自定义插件
|
||||
|
||||
要创建自己的插件:
|
||||
|
||||
1. 在 `.claude-plugin/marketplace.json` 中添加新的插件定义
|
||||
2. 指定插件包含的命令和代理文件路径
|
||||
3. 设置适当的元数据(版本、作者、关键词等)
|
||||
|
||||
示例插件结构:
|
||||
```json
|
||||
{
|
||||
"name": "my-custom-plugin",
|
||||
"source": "./",
|
||||
"description": "自定义插件描述",
|
||||
"version": "1.0.0",
|
||||
"commands": [
|
||||
"./commands/my-command.md"
|
||||
],
|
||||
"agents": [
|
||||
"./agents/my-agent.md"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 分享插件
|
||||
|
||||
要分享插件给其他项目:
|
||||
1. 复制整个 `.claude-plugin` 目录到目标项目
|
||||
2. 确保相关的命令和代理文件存在
|
||||
3. 在新项目中使用 `/plugin` 命令管理插件
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 插件系统遵循Claude Code的插件规范
|
||||
- 所有命令和代理文件必须是有效的Markdown格式
|
||||
- 插件配置支持版本管理和依赖关系
|
||||
- 插件可以包含多个命令、代理和输出样式
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Claude Code插件文档](https://docs.claude.com/en/docs/claude-code/plugins)
|
||||
- [示例插件仓库](https://github.com/wshobson/agents)
|
||||
@@ -92,7 +92,7 @@ make install
|
||||
|
||||
**Codex Wrapper** (Go binary for Codex CLI)
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/chenwenjie/myclaude/master/install.sh | bash
|
||||
curl -fsSL https://raw.githubusercontent.com/cexll/myclaude/refs/heads/master/install.sh | bash
|
||||
```
|
||||
|
||||
**Method 1: Plugin Install** (One command)
|
||||
|
||||
@@ -24,9 +24,9 @@ const (
|
||||
|
||||
// Test hooks for dependency injection
|
||||
var (
|
||||
stdinReader io.Reader = os.Stdin
|
||||
isTerminalFn = defaultIsTerminal
|
||||
codexCommand = "codex"
|
||||
stdinReader io.Reader = os.Stdin
|
||||
isTerminalFn = defaultIsTerminal
|
||||
codexCommand = "codex"
|
||||
)
|
||||
|
||||
// Config holds CLI configuration
|
||||
@@ -347,9 +347,7 @@ func runCodexProcess(codexArgs []string, taskText string, useStdin bool, timeout
|
||||
|
||||
func parseJSONStream(r io.Reader) (message, threadID string) {
|
||||
scanner := bufio.NewScanner(r)
|
||||
// Set larger buffer for long lines
|
||||
buf := make([]byte, 0, 64*1024)
|
||||
scanner.Buffer(buf, 1024*1024)
|
||||
scanner.Buffer(make([]byte, 64*1024), 10*1024*1024)
|
||||
|
||||
for scanner.Scan() {
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
@@ -369,18 +367,15 @@ func parseJSONStream(r io.Reader) (message, threadID string) {
|
||||
}
|
||||
|
||||
// Capture agent_message
|
||||
if event.Type == "item.completed" && event.Item != nil {
|
||||
if event.Item.Type == "agent_message" {
|
||||
text := normalizeText(event.Item.Text)
|
||||
if text != "" {
|
||||
message = text
|
||||
}
|
||||
if event.Type == "item.completed" && event.Item != nil && event.Item.Type == "agent_message" {
|
||||
if text := normalizeText(event.Item.Text); text != "" {
|
||||
message = text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
logWarn("Scanner error: " + err.Error())
|
||||
if err := scanner.Err(); err != nil && err != io.EOF {
|
||||
logWarn("Read stdout error: " + err.Error())
|
||||
}
|
||||
|
||||
return message, threadID
|
||||
|
||||
@@ -330,12 +330,16 @@ func TestNormalizeText(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestParseJSONStream(t *testing.T) {
|
||||
tests := []struct {
|
||||
type testCase struct {
|
||||
name string
|
||||
input string
|
||||
wantMessage string
|
||||
wantThreadID string
|
||||
}{
|
||||
}
|
||||
|
||||
longText := strings.Repeat("a", 2*1024*1024) // >1MB agent_message payload
|
||||
|
||||
tests := []testCase{
|
||||
{
|
||||
name: "thread started and agent message",
|
||||
input: `{"type":"thread.started","thread_id":"abc-123"}
|
||||
@@ -364,6 +368,12 @@ func TestParseJSONStream(t *testing.T) {
|
||||
wantMessage: "Valid",
|
||||
wantThreadID: "",
|
||||
},
|
||||
{
|
||||
name: "super long single line (>1MB)",
|
||||
input: `{"type":"item.completed","item":{"type":"agent_message","text":"` + longText + `"}}`,
|
||||
wantMessage: longText,
|
||||
wantThreadID: "",
|
||||
},
|
||||
{
|
||||
name: "empty input",
|
||||
input: "",
|
||||
@@ -371,23 +381,25 @@ func TestParseJSONStream(t *testing.T) {
|
||||
wantThreadID: "",
|
||||
},
|
||||
{
|
||||
name: "invalid JSON (skipped)",
|
||||
input: "not valid json\n{\"type\":\"thread.started\",\"thread_id\":\"xyz\"}",
|
||||
name: "item completed with nil item",
|
||||
input: strings.Join([]string{
|
||||
`{"type":"thread.started","thread_id":"nil-item-thread"}`,
|
||||
`{"type":"item.completed","item":null}`,
|
||||
}, "\n"),
|
||||
wantMessage: "",
|
||||
wantThreadID: "xyz",
|
||||
wantThreadID: "nil-item-thread",
|
||||
},
|
||||
{
|
||||
name: "blank lines ignored",
|
||||
input: "\n\n{\"type\":\"thread.started\",\"thread_id\":\"test\"}\n\n",
|
||||
name: "agent message with non-string text",
|
||||
input: `{"type":"item.completed","item":{"type":"agent_message","text":12345}}`,
|
||||
wantMessage: "",
|
||||
wantThreadID: "test",
|
||||
wantThreadID: "",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := strings.NewReader(tt.input)
|
||||
gotMessage, gotThreadID := parseJSONStream(r)
|
||||
gotMessage, gotThreadID := parseJSONStream(strings.NewReader(tt.input))
|
||||
|
||||
if gotMessage != tt.wantMessage {
|
||||
t.Errorf("parseJSONStream() message = %q, want %q", gotMessage, tt.wantMessage)
|
||||
|
||||
@@ -62,6 +62,15 @@ You are the /dev Workflow Orchestrator, an expert development workflow manager s
|
||||
|
||||
- **Step 3: Generate Development Documentation**
|
||||
- invoke agent dev-plan-generator
|
||||
- Output a brief summary of dev-plan.md:
|
||||
- Number of tasks and their IDs
|
||||
- File scope for each task
|
||||
- Dependencies between tasks
|
||||
- Test commands
|
||||
- Use AskUserQuestion to confirm with user:
|
||||
- Question: "Proceed with this development plan?"
|
||||
- Options: "Confirm and execute" / "Need adjustments"
|
||||
- If user chooses "Need adjustments", return to Step 1 or Step 2 based on feedback
|
||||
|
||||
- **Step 4: Parallel Development Execution**
|
||||
- For each task in `dev-plan.md`, invoke Codex with this brief:
|
||||
|
||||
@@ -13,7 +13,7 @@ case "$ARCH" in
|
||||
esac
|
||||
|
||||
# Build download URL
|
||||
REPO="chenwenjie/myclaude"
|
||||
REPO="cexll/myclaude"
|
||||
VERSION="latest"
|
||||
BINARY_NAME="codex-wrapper-${OS}-${ARCH}"
|
||||
URL="https://github.com/${REPO}/releases/${VERSION}/download/${BINARY_NAME}"
|
||||
|
||||
Reference in New Issue
Block a user