├── ccpm ├── prds │ └── .gitkeep ├── epics │ └── .gitkeep ├── commands │ ├── pm │ │ ├── help.md │ │ ├── init.md │ │ ├── next.md │ │ ├── status.md │ │ ├── blocked.md │ │ ├── prd-list.md │ │ ├── standup.md │ │ ├── validate.md │ │ ├── prd-status.md │ │ ├── epic-list.md │ │ ├── in-progress.md │ │ ├── search.md │ │ ├── epic-show.md │ │ ├── epic-status.md │ │ ├── epic-edit.md │ │ ├── issue-reopen.md │ │ ├── prd-edit.md │ │ ├── epic-close.md │ │ ├── issue-edit.md │ │ ├── issue-status.md │ │ ├── sync.md │ │ ├── epic-oneshot.md │ │ ├── clean.md │ │ ├── import.md │ │ ├── issue-show.md │ │ ├── issue-close.md │ │ ├── epic-refresh.md │ │ ├── test-reference-update.md │ │ ├── issue-start.md │ │ ├── prd-new.md │ │ ├── issue-analyze.md │ │ ├── epic-start-worktree.md │ │ └── prd-parse.md │ ├── re-init.md │ ├── prompt.md │ ├── testing │ │ └── run.md │ ├── code-rabbit.md │ └── context │ │ └── prime.md ├── settings.json.example ├── scripts │ ├── pm │ │ ├── status.sh │ │ ├── search.sh │ │ ├── prd-status.sh │ │ ├── next.sh │ │ ├── blocked.sh │ │ ├── in-progress.sh │ │ ├── epic-status.sh │ │ ├── epic-show.sh │ │ ├── prd-list.sh │ │ ├── epic-list.sh │ │ ├── validate.sh │ │ ├── standup.sh │ │ └── help.sh │ ├── path-tools-README.md │ ├── fix-path-standards.sh │ ├── test-and-log.sh │ └── check-path-standards.sh ├── settings.local.json ├── rules │ ├── frontmatter-operations.md │ ├── test-execution.md │ ├── strip-frontmatter.md │ ├── github-operations.md │ ├── worktree-operations.md │ ├── branch-operations.md │ ├── datetime.md │ ├── standard-patterns.md │ ├── path-standards.md │ ├── use-ast-grep.md │ └── agent-coordination.md ├── ccpm.config ├── hooks │ └── README.md ├── context │ └── README.md └── agents │ ├── parallel-worker.md │ ├── file-analyzer.md │ └── code-analyzer.md ├── .gitignore ├── screenshot.webp ├── install ├── ccpm.sh ├── ccpm.bat └── README.md ├── LICENSE ├── doc ├── AGENTS_ZH.md └── COMMANDS_ZH.md ├── zh-docs ├── AGENTS_ZH.md └── COMMANDS_ZH.md ├── LOCAL_MODE.md ├── CONTEXT_ACCURACY.md └── AGENTS.md /ccpm/prds/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ccpm/epics/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea/ 3 | CLAUDE.md 4 | -------------------------------------------------------------------------------- /screenshot.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/automazeio/ccpm/HEAD/screenshot.webp -------------------------------------------------------------------------------- /ccpm/commands/pm/help.md: -------------------------------------------------------------------------------- 1 | --- 2 | allowed-tools: Bash(bash ccpm/scripts/pm/help.sh) 3 | --- 4 | 5 | Output: 6 | !bash ccpm/scripts/pm/help.sh 7 | -------------------------------------------------------------------------------- /ccpm/commands/pm/init.md: -------------------------------------------------------------------------------- 1 | --- 2 | allowed-tools: Bash(bash ccpm/scripts/pm/init.sh) 3 | --- 4 | 5 | Output: 6 | !bash ccpm/scripts/pm/init.sh 7 | -------------------------------------------------------------------------------- /ccpm/commands/pm/next.md: -------------------------------------------------------------------------------- 1 | --- 2 | allowed-tools: Bash(bash ccpm/scripts/pm/next.sh) 3 | --- 4 | 5 | Output: 6 | !bash ccpm/scripts/pm/next.sh 7 | -------------------------------------------------------------------------------- /ccpm/commands/pm/status.md: -------------------------------------------------------------------------------- 1 | --- 2 | allowed-tools: Bash(bash ccpm/scripts/pm/status.sh) 3 | --- 4 | 5 | Output: 6 | !bash ccpm/scripts/pm/status.sh 7 | -------------------------------------------------------------------------------- /ccpm/commands/pm/blocked.md: -------------------------------------------------------------------------------- 1 | --- 2 | allowed-tools: Bash(bash ccpm/scripts/pm/blocked.sh) 3 | --- 4 | 5 | Output: 6 | !bash ccpm/scripts/pm/blocked.sh 7 | -------------------------------------------------------------------------------- /ccpm/commands/pm/prd-list.md: -------------------------------------------------------------------------------- 1 | --- 2 | allowed-tools: Bash(bash ccpm/scripts/pm/prd-list.sh) 3 | --- 4 | 5 | Output: 6 | !bash ccpm/scripts/pm/prd-list.sh 7 | -------------------------------------------------------------------------------- /ccpm/commands/pm/standup.md: -------------------------------------------------------------------------------- 1 | --- 2 | allowed-tools: Bash(bash ccpm/scripts/pm/standup.sh) 3 | --- 4 | 5 | Output: 6 | !bash ccpm/scripts/pm/standup.sh 7 | -------------------------------------------------------------------------------- /ccpm/commands/pm/validate.md: -------------------------------------------------------------------------------- 1 | --- 2 | allowed-tools: Bash(bash ccpm/scripts/pm/validate.sh) 3 | --- 4 | 5 | Output: 6 | !bash ccpm/scripts/pm/validate.sh 7 | -------------------------------------------------------------------------------- /ccpm/commands/pm/prd-status.md: -------------------------------------------------------------------------------- 1 | --- 2 | allowed-tools: Bash(bash ccpm/scripts/pm/prd-status.sh) 3 | --- 4 | 5 | Output: 6 | !bash ccpm/scripts/pm/prd-status.sh 7 | -------------------------------------------------------------------------------- /ccpm/commands/pm/epic-list.md: -------------------------------------------------------------------------------- 1 | --- 2 | allowed-tools: Bash(bash ccpm/scripts/pm/epic-list.sh) 3 | --- 4 | 5 | Output: 6 | !bash ccpm/scripts/pm/epic-list.sh 7 | 8 | -------------------------------------------------------------------------------- /ccpm/commands/pm/in-progress.md: -------------------------------------------------------------------------------- 1 | --- 2 | allowed-tools: Bash(bash ccpm/scripts/pm/in-progress.sh) 3 | --- 4 | 5 | Output: 6 | !bash ccpm/scripts/pm/in-progress.sh 7 | -------------------------------------------------------------------------------- /ccpm/commands/pm/search.md: -------------------------------------------------------------------------------- 1 | --- 2 | allowed-tools: Bash(bash ccpm/scripts/pm/search.sh $ARGUMENTS) 3 | --- 4 | 5 | Output: 6 | !bash ccpm/scripts/pm/search.sh $ARGUMENTS 7 | -------------------------------------------------------------------------------- /ccpm/commands/pm/epic-show.md: -------------------------------------------------------------------------------- 1 | --- 2 | allowed-tools: Bash(bash ccpm/scripts/pm/epic-show.sh $ARGUMENTS) 3 | --- 4 | 5 | Output: 6 | !bash ccpm/scripts/pm/epic-show.sh $ARGUMENTS 7 | -------------------------------------------------------------------------------- /ccpm/commands/pm/epic-status.md: -------------------------------------------------------------------------------- 1 | --- 2 | allowed-tools: Bash(bash ccpm/scripts/pm/epic-status.sh $ARGUMENTS) 3 | --- 4 | 5 | Output: 6 | !bash ccpm/scripts/pm/epic-status.sh $ARGUMENTS 7 | -------------------------------------------------------------------------------- /ccpm/commands/re-init.md: -------------------------------------------------------------------------------- 1 | --- 2 | allowed-tools: Bash, Read, Write, LS 3 | --- 4 | 5 | # Enhance CLAUDE.md file 6 | 7 | Please update CLAUDE.md with the rules from .claude/CLAUDE.md. 8 | 9 | If CLAUDE.md does not exist, create it using the /init and include rules from .claude/CLAUDE.md. 10 | -------------------------------------------------------------------------------- /ccpm/commands/prompt.md: -------------------------------------------------------------------------------- 1 | --- 2 | allowed-tools: Bash, Read, Write, LS 3 | --- 4 | 5 | # This is an ephemeral command. 6 | 7 | Some complex prompts (with numerous @ references) may fail if entered directly into the prompt input. 8 | 9 | If that happens, write your prompt here and type in `/prompt` in the prompt command. 10 | -------------------------------------------------------------------------------- /ccpm/settings.json.example: -------------------------------------------------------------------------------- 1 | { 2 | "hooks": { 3 | "pre-tool-use": { 4 | "Bash": { 5 | "enabled": true, 6 | "script": ".claude/hooks/bash-worktree-fix.sh", 7 | "description": "Automatically prepends worktree path to Bash commands when in a worktree", 8 | "apply_to_subagents": true 9 | } 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /install/ccpm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | REPO_URL="https://github.com/automazeio/ccpm.git" 4 | TARGET_DIR="." 5 | 6 | echo "Cloning repository from $REPO_URL..." 7 | git clone "$REPO_URL" "$TARGET_DIR" 8 | 9 | if [ $? -eq 0 ]; then 10 | echo "Clone successful. Removing .git directory..." 11 | rm -rf .git .gitignore install 12 | echo "Git directory removed. Repository is now untracked." 13 | else 14 | echo "Error: Failed to clone repository." 15 | exit 1 16 | fi 17 | -------------------------------------------------------------------------------- /install/ccpm.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | set REPO_URL=https://github.com/automazeio/ccpm.git 4 | set TARGET_DIR=. 5 | 6 | echo Cloning repository from %REPO_URL%... 7 | git clone %REPO_URL% %TARGET_DIR% 8 | 9 | if %ERRORLEVEL% EQU 0 ( 10 | echo Clone successful. Removing .git directory... 11 | rmdir /s /q .git 2>nul 12 | rmdir /s /q install 2>nul 13 | del /q .gitignore 2>nul 14 | echo Git directory removed. Repository is now untracked. 15 | ) else ( 16 | echo Error: Failed to clone repository. 17 | exit /b 1 18 | ) 19 | -------------------------------------------------------------------------------- /install/README.md: -------------------------------------------------------------------------------- 1 | # Quick Install 2 | 3 | ## Unix/Linux/macOS 4 | 5 | ```bash 6 | curl -sSL https://automaze.io/ccpm/install | bash 7 | ``` 8 | 9 | Or with wget: 10 | 11 | ```bash 12 | wget -qO- https://automaze.io/ccpm/install | bash 13 | ``` 14 | 15 | ## Windows (PowerShell) 16 | 17 | ```powershell 18 | iwr -useb https://automaze.io/ccpm/install | iex 19 | ``` 20 | 21 | Or download and execute: 22 | 23 | ```powershell 24 | curl -o ccpm.bat https://automaze.io/ccpm/install && ccpm.bat 25 | ``` 26 | 27 | ## One-liner alternatives 28 | 29 | ### Unix/Linux/macOS (direct commands) 30 | ```bash 31 | git clone https://github.com/automazeio/ccpm.git . && rm -rf .git 32 | ``` 33 | 34 | ### Windows (cmd) 35 | ```cmd 36 | git clone https://github.com/automazeio/ccpm.git . && rmdir /s /q .git 37 | ``` 38 | 39 | ### Windows (PowerShell) 40 | ```powershell 41 | git clone https://github.com/automazeio/ccpm.git .; Remove-Item -Recurse -Force .git 42 | ``` 43 | -------------------------------------------------------------------------------- /ccpm/scripts/pm/status.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Getting status..." 4 | echo "" 5 | echo "" 6 | 7 | 8 | echo "📊 Project Status" 9 | echo "================" 10 | echo "" 11 | 12 | echo "📄 PRDs:" 13 | if [ -d ".claude/prds" ]; then 14 | total=$(ls .claude/prds/*.md 2>/dev/null | wc -l) 15 | echo " Total: $total" 16 | else 17 | echo " No PRDs found" 18 | fi 19 | 20 | echo "" 21 | echo "📚 Epics:" 22 | if [ -d ".claude/epics" ]; then 23 | total=$(ls -d .claude/epics/*/ 2>/dev/null | wc -l) 24 | echo " Total: $total" 25 | else 26 | echo " No epics found" 27 | fi 28 | 29 | echo "" 30 | echo "📝 Tasks:" 31 | if [ -d ".claude/epics" ]; then 32 | total=$(find .claude/epics -name "[0-9]*.md" 2>/dev/null | wc -l) 33 | open=$(find .claude/epics -name "[0-9]*.md" -exec grep -l "^status: *open" {} \; 2>/dev/null | wc -l) 34 | closed=$(find .claude/epics -name "[0-9]*.md" -exec grep -l "^status: *closed" {} \; 2>/dev/null | wc -l) 35 | echo " Open: $open" 36 | echo " Closed: $closed" 37 | echo " Total: $total" 38 | else 39 | echo " No tasks found" 40 | fi 41 | 42 | exit 0 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Ran Aroussi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ccpm/settings.local.json: -------------------------------------------------------------------------------- 1 | { 2 | "permissions": { 3 | "allow": [ 4 | "Bash(bash .claude/scripts/test-and-log.sh:*)", 5 | "Bash(.claude/scripts/test-and-log.sh:*)", 6 | "Bash(bash .claude/scripts/pm/*)", 7 | "Bash(.claude/scripts/pm/*)", 8 | 9 | "Bash(cat:*)", 10 | "Bash(cat:*)", 11 | "Bash(composer:*)", 12 | "Bash(fi)", 13 | "Bash(find:*)", 14 | "Bash(gh:*)", 15 | "Bash(git:*)", 16 | "Bash(grep:*)", 17 | "Bash(kill:*)", 18 | "Bash(ln:*)", 19 | "Bash(ls:*)", 20 | "Bash(mv:*)", 21 | "Bash(npm:*)", 22 | "Bash(npx:*)", 23 | "Bash(pnpm:*)", 24 | "Bash(pytest:*)", 25 | "Bash(python:*)", 26 | "Bash(mvn:*)", 27 | "Bash(gradle:*)", 28 | "Bash(dotnet:*)", 29 | "Bash(cargo:*)", 30 | "Bash(go:*)", 31 | "Bash(swift:*)", 32 | "Bash(flutter:*)", 33 | "Bash(bundle:*)", 34 | "Bash(ctest:*)", 35 | "Bash(make:*)", 36 | "Bash(rm:*)", 37 | "Bash(ruff:*)", 38 | "Bash(sed:*)", 39 | "Bash(touch:*)", 40 | "Bash(tree:*)", 41 | "List(**)", 42 | "WebFetch(domain:github.com)", 43 | "WebSearch" 44 | ] 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /ccpm/scripts/path-tools-README.md: -------------------------------------------------------------------------------- 1 | # Path Standards Tools 2 | 3 | ## Overview 4 | This directory contains tools for maintaining path format standards in project documentation. 5 | 6 | ## Available Scripts 7 | 8 | ### 1. Validation Script 9 | ```bash 10 | ./.claude/scripts/check-path-standards.sh 11 | ``` 12 | **Purpose**: Scans project documentation to detect path format violations 13 | **Output**: Colored validation report showing pass/fail status 14 | 15 | ### 2. Fix Script 16 | ```bash 17 | ./.claude/scripts/fix-path-standards.sh 18 | ``` 19 | **Purpose**: Automatically fixes absolute path issues in documentation 20 | **Safety**: Creates backup files automatically, supports rollback 21 | 22 | ## Usage Workflow 23 | 24 | ### Regular Maintenance 25 | 1. **Periodic Check**: Run `./check-path-standards.sh` 26 | 2. **When Issues Found**: Run `./fix-path-standards.sh` 27 | 3. **Verify Fixes**: Run the validation script again 28 | 29 | ### CI/CD Integration 30 | Add the validation script to your CI pipeline: 31 | ```yaml 32 | - name: Path Standards Check 33 | run: ./.claude/scripts/check-path-standards.sh 34 | ``` 35 | 36 | ### Clean Up Backups 37 | After confirming fixes are correct: 38 | ```bash 39 | find .claude/ -name '*.backup' -delete 40 | ``` 41 | 42 | ## Standards Reference 43 | For detailed path usage guidelines, see: `.claude/rules/path-standards.md` -------------------------------------------------------------------------------- /ccpm/commands/pm/epic-edit.md: -------------------------------------------------------------------------------- 1 | --- 2 | allowed-tools: Read, Write, LS 3 | --- 4 | 5 | # Epic Edit 6 | 7 | Edit epic details after creation. 8 | 9 | ## Usage 10 | ``` 11 | /pm:epic-edit 12 | ``` 13 | 14 | ## Instructions 15 | 16 | ### 1. Read Current Epic 17 | 18 | Read `.claude/epics/$ARGUMENTS/epic.md`: 19 | - Parse frontmatter 20 | - Read content sections 21 | 22 | ### 2. Interactive Edit 23 | 24 | Ask user what to edit: 25 | - Name/Title 26 | - Description/Overview 27 | - Architecture decisions 28 | - Technical approach 29 | - Dependencies 30 | - Success criteria 31 | 32 | ### 3. Update Epic File 33 | 34 | Get current datetime: `date -u +"%Y-%m-%dT%H:%M:%SZ"` 35 | 36 | Update epic.md: 37 | - Preserve all frontmatter except `updated` 38 | - Apply user's edits to content 39 | - Update `updated` field with current datetime 40 | 41 | ### 4. Option to Update GitHub 42 | 43 | If epic has GitHub URL in frontmatter: 44 | Ask: "Update GitHub issue? (yes/no)" 45 | 46 | If yes: 47 | ```bash 48 | gh issue edit {issue_number} --body-file .claude/epics/$ARGUMENTS/epic.md 49 | ``` 50 | 51 | ### 5. Output 52 | 53 | ``` 54 | ✅ Updated epic: $ARGUMENTS 55 | Changes made to: {sections_edited} 56 | 57 | {If GitHub updated}: GitHub issue updated ✅ 58 | 59 | View epic: /pm:epic-show $ARGUMENTS 60 | ``` 61 | 62 | ## Important Notes 63 | 64 | Preserve frontmatter history (created, github URL, etc.). 65 | Don't change task files when editing epic. 66 | Follow `/rules/frontmatter-operations.md`. -------------------------------------------------------------------------------- /ccpm/commands/pm/issue-reopen.md: -------------------------------------------------------------------------------- 1 | --- 2 | allowed-tools: Bash, Read, Write, LS 3 | --- 4 | 5 | # Issue Reopen 6 | 7 | Reopen a closed issue. 8 | 9 | ## Usage 10 | ``` 11 | /pm:issue-reopen [reason] 12 | ``` 13 | 14 | ## Instructions 15 | 16 | ### 1. Find Local Task File 17 | 18 | Search for task file with `github:.*issues/$ARGUMENTS` in frontmatter. 19 | If not found: "❌ No local task for issue #$ARGUMENTS" 20 | 21 | ### 2. Update Local Status 22 | 23 | Get current datetime: `date -u +"%Y-%m-%dT%H:%M:%SZ"` 24 | 25 | Update task file frontmatter: 26 | ```yaml 27 | status: open 28 | updated: {current_datetime} 29 | ``` 30 | 31 | ### 3. Reset Progress 32 | 33 | If progress file exists: 34 | - Keep original started date 35 | - Reset completion to previous value or 0% 36 | - Add note about reopening with reason 37 | 38 | ### 4. Reopen on GitHub 39 | 40 | ```bash 41 | # Reopen with comment 42 | echo "🔄 Reopening issue 43 | 44 | Reason: $ARGUMENTS 45 | 46 | --- 47 | Reopened at: {timestamp}" | gh issue comment $ARGUMENTS --body-file - 48 | 49 | # Reopen the issue 50 | gh issue reopen $ARGUMENTS 51 | ``` 52 | 53 | ### 5. Update Epic Progress 54 | 55 | Recalculate epic progress with this task now open again. 56 | 57 | ### 6. Output 58 | 59 | ``` 60 | 🔄 Reopened issue #$ARGUMENTS 61 | Reason: {reason_if_provided} 62 | Epic progress: {updated_progress}% 63 | 64 | Start work with: /pm:issue-start $ARGUMENTS 65 | ``` 66 | 67 | ## Important Notes 68 | 69 | Preserve work history in progress files. 70 | Don't delete previous progress, just reset status. -------------------------------------------------------------------------------- /ccpm/commands/pm/prd-edit.md: -------------------------------------------------------------------------------- 1 | --- 2 | allowed-tools: Read, Write, LS 3 | --- 4 | 5 | # PRD Edit 6 | 7 | Edit an existing Product Requirements Document. 8 | 9 | ## Usage 10 | ``` 11 | /pm:prd-edit 12 | ``` 13 | 14 | ## Instructions 15 | 16 | ### 1. Read Current PRD 17 | 18 | Read `.claude/prds/$ARGUMENTS.md`: 19 | - Parse frontmatter 20 | - Read all sections 21 | 22 | ### 2. Interactive Edit 23 | 24 | Ask user what sections to edit: 25 | - Executive Summary 26 | - Problem Statement 27 | - User Stories 28 | - Requirements (Functional/Non-Functional) 29 | - Success Criteria 30 | - Constraints & Assumptions 31 | - Out of Scope 32 | - Dependencies 33 | 34 | ### 3. Update PRD 35 | 36 | Get current datetime: `date -u +"%Y-%m-%dT%H:%M:%SZ"` 37 | 38 | Update PRD file: 39 | - Preserve frontmatter except `updated` field 40 | - Apply user's edits to selected sections 41 | - Update `updated` field with current datetime 42 | 43 | ### 4. Check Epic Impact 44 | 45 | If PRD has associated epic: 46 | - Notify user: "This PRD has epic: {epic_name}" 47 | - Ask: "Epic may need updating based on PRD changes. Review epic? (yes/no)" 48 | - If yes, show: "Review with: /pm:epic-edit {epic_name}" 49 | 50 | ### 5. Output 51 | 52 | ``` 53 | ✅ Updated PRD: $ARGUMENTS 54 | Sections edited: {list_of_sections} 55 | 56 | {If has epic}: ⚠️ Epic may need review: {epic_name} 57 | 58 | Next: /pm:prd-parse $ARGUMENTS to update epic 59 | ``` 60 | 61 | ## Important Notes 62 | 63 | Preserve original creation date. 64 | Keep version history in frontmatter if needed. 65 | Follow `/rules/frontmatter-operations.md`. -------------------------------------------------------------------------------- /ccpm/commands/pm/epic-close.md: -------------------------------------------------------------------------------- 1 | --- 2 | allowed-tools: Bash, Read, Write, LS 3 | --- 4 | 5 | # Epic Close 6 | 7 | Mark an epic as complete when all tasks are done. 8 | 9 | ## Usage 10 | ``` 11 | /pm:epic-close 12 | ``` 13 | 14 | ## Instructions 15 | 16 | ### 1. Verify All Tasks Complete 17 | 18 | Check all task files in `.claude/epics/$ARGUMENTS/`: 19 | - Verify all have `status: closed` in frontmatter 20 | - If any open tasks found: "❌ Cannot close epic. Open tasks remain: {list}" 21 | 22 | ### 2. Update Epic Status 23 | 24 | Get current datetime: `date -u +"%Y-%m-%dT%H:%M:%SZ"` 25 | 26 | Update epic.md frontmatter: 27 | ```yaml 28 | status: completed 29 | progress: 100% 30 | updated: {current_datetime} 31 | completed: {current_datetime} 32 | ``` 33 | 34 | ### 3. Update PRD Status 35 | 36 | If epic references a PRD, update its status to "complete". 37 | 38 | ### 4. Close Epic on GitHub 39 | 40 | If epic has GitHub issue: 41 | ```bash 42 | gh issue close {epic_issue_number} --comment "✅ Epic completed - all tasks done" 43 | ``` 44 | 45 | ### 5. Archive Option 46 | 47 | Ask user: "Archive completed epic? (yes/no)" 48 | 49 | If yes: 50 | - Move epic directory to `.claude/epics/.archived/{epic_name}/` 51 | - Create archive summary with completion date 52 | 53 | ### 6. Output 54 | 55 | ``` 56 | ✅ Epic closed: $ARGUMENTS 57 | Tasks completed: {count} 58 | Duration: {days_from_created_to_completed} 59 | 60 | {If archived}: Archived to .claude/epics/.archived/ 61 | 62 | Next epic: Run /pm:next to see priority work 63 | ``` 64 | 65 | ## Important Notes 66 | 67 | Only close epics with all tasks complete. 68 | Preserve all data when archiving. 69 | Update related PRD status. -------------------------------------------------------------------------------- /ccpm/rules/frontmatter-operations.md: -------------------------------------------------------------------------------- 1 | # Frontmatter Operations Rule 2 | 3 | Standard patterns for working with YAML frontmatter in markdown files. 4 | 5 | ## Reading Frontmatter 6 | 7 | Extract frontmatter from any markdown file: 8 | 1. Look for content between `---` markers at start of file 9 | 2. Parse as YAML 10 | 3. If invalid or missing, use sensible defaults 11 | 12 | ## Updating Frontmatter 13 | 14 | When updating existing files: 15 | 1. Preserve all existing fields 16 | 2. Only update specified fields 17 | 3. Always update `updated` field with current datetime (see `/rules/datetime.md`) 18 | 19 | ## Standard Fields 20 | 21 | ### All Files 22 | ```yaml 23 | --- 24 | name: {identifier} 25 | created: {ISO datetime} # Never change after creation 26 | updated: {ISO datetime} # Update on any modification 27 | --- 28 | ``` 29 | 30 | ### Status Values 31 | - PRDs: `backlog`, `in-progress`, `complete` 32 | - Epics: `backlog`, `in-progress`, `completed` 33 | - Tasks: `open`, `in-progress`, `closed` 34 | 35 | ### Progress Tracking 36 | ```yaml 37 | progress: {0-100}% # For epics 38 | completion: {0-100}% # For progress files 39 | ``` 40 | 41 | ## Creating New Files 42 | 43 | Always include frontmatter when creating markdown files: 44 | ```yaml 45 | --- 46 | name: {from_arguments_or_context} 47 | status: {initial_status} 48 | created: {current_datetime} 49 | updated: {current_datetime} 50 | --- 51 | ``` 52 | 53 | ## Important Notes 54 | 55 | - Never modify `created` field after initial creation 56 | - Always use real datetime from system (see `/rules/datetime.md`) 57 | - Validate frontmatter exists before trying to parse 58 | - Use consistent field names across all files -------------------------------------------------------------------------------- /ccpm/commands/pm/issue-edit.md: -------------------------------------------------------------------------------- 1 | --- 2 | allowed-tools: Bash, Read, Write, LS 3 | --- 4 | 5 | # Issue Edit 6 | 7 | Edit issue details locally and on GitHub. 8 | 9 | ## Usage 10 | ``` 11 | /pm:issue-edit 12 | ``` 13 | 14 | ## Instructions 15 | 16 | ### 1. Get Current Issue State 17 | 18 | ```bash 19 | # Get from GitHub 20 | gh issue view $ARGUMENTS --json title,body,labels 21 | 22 | # Find local task file 23 | # Search for file with github:.*issues/$ARGUMENTS 24 | ``` 25 | 26 | ### 2. Interactive Edit 27 | 28 | Ask user what to edit: 29 | - Title 30 | - Description/Body 31 | - Labels 32 | - Acceptance criteria (local only) 33 | - Priority/Size (local only) 34 | 35 | ### 3. Update Local File 36 | 37 | Get current datetime: `date -u +"%Y-%m-%dT%H:%M:%SZ"` 38 | 39 | Update task file with changes: 40 | - Update frontmatter `name` if title changed 41 | - Update body content if description changed 42 | - Update `updated` field with current datetime 43 | 44 | ### 4. Update GitHub 45 | 46 | If title changed: 47 | ```bash 48 | gh issue edit $ARGUMENTS --title "{new_title}" 49 | ``` 50 | 51 | If body changed: 52 | ```bash 53 | gh issue edit $ARGUMENTS --body-file {updated_task_file} 54 | ``` 55 | 56 | If labels changed: 57 | ```bash 58 | gh issue edit $ARGUMENTS --add-label "{new_labels}" 59 | gh issue edit $ARGUMENTS --remove-label "{removed_labels}" 60 | ``` 61 | 62 | ### 5. Output 63 | 64 | ``` 65 | ✅ Updated issue #$ARGUMENTS 66 | Changes: 67 | {list_of_changes_made} 68 | 69 | Synced to GitHub: ✅ 70 | ``` 71 | 72 | ## Important Notes 73 | 74 | Always update local first, then GitHub. 75 | Preserve frontmatter fields not being edited. 76 | Follow `/rules/frontmatter-operations.md`. -------------------------------------------------------------------------------- /ccpm/rules/test-execution.md: -------------------------------------------------------------------------------- 1 | # Test Execution Rule 2 | 3 | Standard patterns for running tests across all testing commands. 4 | 5 | ## Core Principles 6 | 7 | 1. **Always use test-runner agent** from `.claude/agents/test-runner.md` 8 | 2. **No mocking** - use real services for accurate results 9 | 3. **Verbose output** - capture everything for debugging 10 | 4. **Check test structure first** - before assuming code bugs 11 | 12 | ## Execution Pattern 13 | 14 | ```markdown 15 | Execute tests for: {target} 16 | 17 | Requirements: 18 | - Run with verbose output 19 | - No mock services 20 | - Capture full stack traces 21 | - Analyze test structure if failures occur 22 | ``` 23 | 24 | ## Output Focus 25 | 26 | ### Success 27 | Keep it simple: 28 | ``` 29 | ✅ All tests passed ({count} tests in {time}s) 30 | ``` 31 | 32 | ### Failure 33 | Focus on what failed: 34 | ``` 35 | ❌ Test failures: {count} 36 | 37 | {test_name} - {file}:{line} 38 | Error: {message} 39 | Fix: {suggestion} 40 | ``` 41 | 42 | ## Common Issues 43 | 44 | - Test not found → Check file path 45 | - Timeout → Kill process, report incomplete 46 | - Framework missing → Install dependencies 47 | 48 | ## Cleanup 49 | 50 | Always clean up after tests: 51 | ```bash 52 | # Kill test processes for all supported frameworks 53 | pkill -f "jest|mocha|pytest|phpunit|rspec|ctest" 2>/dev/null || true 54 | pkill -f "mvn.*test|gradle.*test|gradlew.*test" 2>/dev/null || true 55 | pkill -f "dotnet.*test|cargo.*test|go.*test|swift.*test|flutter.*test" 2>/dev/null || true 56 | ``` 57 | 58 | ## Important Notes 59 | 60 | - Don't parallelize tests (avoid conflicts) 61 | - Let each test complete fully 62 | - Report failures with actionable fixes 63 | - Focus output on failures, not successes -------------------------------------------------------------------------------- /ccpm/scripts/pm/search.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | query="$1" 4 | 5 | if [ -z "$query" ]; then 6 | echo "❌ Please provide a search query" 7 | echo "Usage: /pm:search " 8 | exit 1 9 | fi 10 | 11 | echo "Searching for '$query'..." 12 | echo "" 13 | echo "" 14 | 15 | echo "🔍 Search results for: '$query'" 16 | echo "================================" 17 | echo "" 18 | 19 | # Search in PRDs 20 | if [ -d ".claude/prds" ]; then 21 | echo "📄 PRDs:" 22 | results=$(grep -l -i "$query" .claude/prds/*.md 2>/dev/null) 23 | if [ -n "$results" ]; then 24 | for file in $results; do 25 | name=$(basename "$file" .md) 26 | matches=$(grep -c -i "$query" "$file") 27 | echo " • $name ($matches matches)" 28 | done 29 | else 30 | echo " No matches" 31 | fi 32 | echo "" 33 | fi 34 | 35 | # Search in Epics 36 | if [ -d ".claude/epics" ]; then 37 | echo "📚 Epics:" 38 | results=$(find .claude/epics -name "epic.md" -exec grep -l -i "$query" {} \; 2>/dev/null) 39 | if [ -n "$results" ]; then 40 | for file in $results; do 41 | epic_name=$(basename $(dirname "$file")) 42 | matches=$(grep -c -i "$query" "$file") 43 | echo " • $epic_name ($matches matches)" 44 | done 45 | else 46 | echo " No matches" 47 | fi 48 | echo "" 49 | fi 50 | 51 | # Search in Tasks 52 | if [ -d ".claude/epics" ]; then 53 | echo "📝 Tasks:" 54 | results=$(find .claude/epics -name "[0-9]*.md" -exec grep -l -i "$query" {} \; 2>/dev/null | head -10) 55 | if [ -n "$results" ]; then 56 | for file in $results; do 57 | epic_name=$(basename $(dirname "$file")) 58 | task_num=$(basename "$file" .md) 59 | echo " • Task #$task_num in $epic_name" 60 | done 61 | else 62 | echo " No matches" 63 | fi 64 | fi 65 | 66 | # Summary 67 | total=$(find .claude -name "*.md" -exec grep -l -i "$query" {} \; 2>/dev/null | wc -l) 68 | echo "" 69 | echo "📊 Total files with matches: $total" 70 | 71 | exit 0 72 | -------------------------------------------------------------------------------- /ccpm/scripts/pm/prd-status.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "📄 PRD Status Report" 4 | echo "====================" 5 | echo "" 6 | 7 | if [ ! -d ".claude/prds" ]; then 8 | echo "No PRD directory found." 9 | exit 0 10 | fi 11 | 12 | total=$(ls .claude/prds/*.md 2>/dev/null | wc -l) 13 | [ $total -eq 0 ] && echo "No PRDs found." && exit 0 14 | 15 | # Count by status 16 | backlog=0 17 | in_progress=0 18 | implemented=0 19 | 20 | for file in .claude/prds/*.md; do 21 | [ -f "$file" ] || continue 22 | status=$(grep "^status:" "$file" | head -1 | sed 's/^status: *//') 23 | 24 | case "$status" in 25 | backlog|draft|"") ((backlog++)) ;; 26 | in-progress|active) ((in_progress++)) ;; 27 | implemented|completed|done) ((implemented++)) ;; 28 | *) ((backlog++)) ;; 29 | esac 30 | done 31 | 32 | echo "Getting status..." 33 | echo "" 34 | echo "" 35 | 36 | # Display chart 37 | echo "📊 Distribution:" 38 | echo "================" 39 | 40 | echo "" 41 | echo " Backlog: $(printf '%-3d' $backlog) [$(printf '%0.s█' $(seq 1 $((backlog*20/total))))]" 42 | echo " In Progress: $(printf '%-3d' $in_progress) [$(printf '%0.s█' $(seq 1 $((in_progress*20/total))))]" 43 | echo " Implemented: $(printf '%-3d' $implemented) [$(printf '%0.s█' $(seq 1 $((implemented*20/total))))]" 44 | echo "" 45 | echo " Total PRDs: $total" 46 | 47 | # Recent activity 48 | echo "" 49 | echo "📅 Recent PRDs (last 5 modified):" 50 | ls -t .claude/prds/*.md 2>/dev/null | head -5 | while read file; do 51 | name=$(grep "^name:" "$file" | head -1 | sed 's/^name: *//') 52 | [ -z "$name" ] && name=$(basename "$file" .md) 53 | echo " • $name" 54 | done 55 | 56 | # Suggestions 57 | echo "" 58 | echo "💡 Next Actions:" 59 | [ $backlog -gt 0 ] && echo " • Parse backlog PRDs to epics: /pm:prd-parse " 60 | [ $in_progress -gt 0 ] && echo " • Check progress on active PRDs: /pm:epic-status " 61 | [ $total -eq 0 ] && echo " • Create your first PRD: /pm:prd-new " 62 | 63 | exit 0 64 | -------------------------------------------------------------------------------- /ccpm/scripts/pm/next.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "Getting status..." 3 | echo "" 4 | echo "" 5 | 6 | echo "📋 Next Available Tasks" 7 | echo "=======================" 8 | echo "" 9 | 10 | # Find tasks that are open and have no dependencies or whose dependencies are closed 11 | found=0 12 | 13 | for epic_dir in .claude/epics/*/; do 14 | [ -d "$epic_dir" ] || continue 15 | epic_name=$(basename "$epic_dir") 16 | 17 | for task_file in "$epic_dir"/[0-9]*.md; do 18 | [ -f "$task_file" ] || continue 19 | 20 | # Check if task is open 21 | status=$(grep "^status:" "$task_file" | head -1 | sed 's/^status: *//') 22 | if [ "$status" != "open" ] && [ -n "$status" ]; then 23 | continue 24 | fi 25 | 26 | # Check dependencies 27 | # Extract dependencies from task file 28 | deps_line=$(grep "^depends_on:" "$task_file" | head -1) 29 | if [ -n "$deps_line" ]; then 30 | deps=$(echo "$deps_line" | sed 's/^depends_on: *//') 31 | deps=$(echo "$deps" | sed 's/^\[//' | sed 's/\]$//') 32 | # Trim whitespace and handle empty cases 33 | deps=$(echo "$deps" | sed 's/^[[:space:]]*//' | sed 's/[[:space:]]*$//') 34 | [ -z "$deps" ] && deps="" 35 | else 36 | deps="" 37 | fi 38 | 39 | # If no dependencies or empty, task is available 40 | if [ -z "$deps" ] || [ "$deps" = "depends_on:" ]; then 41 | task_name=$(grep "^name:" "$task_file" | head -1 | sed 's/^name: *//') 42 | task_num=$(basename "$task_file" .md) 43 | parallel=$(grep "^parallel:" "$task_file" | head -1 | sed 's/^parallel: *//') 44 | 45 | echo "✅ Ready: #$task_num - $task_name" 46 | echo " Epic: $epic_name" 47 | [ "$parallel" = "true" ] && echo " 🔄 Can run in parallel" 48 | echo "" 49 | ((found++)) 50 | fi 51 | done 52 | done 53 | 54 | if [ $found -eq 0 ]; then 55 | echo "No available tasks found." 56 | echo "" 57 | echo "💡 Suggestions:" 58 | echo " • Check blocked tasks: /pm:blocked" 59 | echo " • View all tasks: /pm:epic-list" 60 | fi 61 | 62 | echo "" 63 | echo "📊 Summary: $found tasks ready to start" 64 | 65 | exit 0 66 | -------------------------------------------------------------------------------- /ccpm/commands/pm/issue-status.md: -------------------------------------------------------------------------------- 1 | --- 2 | allowed-tools: Bash, Read, LS 3 | --- 4 | 5 | # Issue Status 6 | 7 | Check issue status (open/closed) and current state. 8 | 9 | ## Usage 10 | ``` 11 | /pm:issue-status 12 | ``` 13 | 14 | ## Instructions 15 | 16 | You are checking the current status of a GitHub issue and providing a quick status report for: **Issue #$ARGUMENTS** 17 | 18 | ### 1. Fetch Issue Status 19 | Use GitHub CLI to get current status: 20 | ```bash 21 | gh issue view #$ARGUMENTS --json state,title,labels,assignees,updatedAt 22 | ``` 23 | 24 | ### 2. Status Display 25 | Show concise status information: 26 | ``` 27 | 🎫 Issue #$ARGUMENTS: {Title} 28 | 29 | 📊 Status: {OPEN/CLOSED} 30 | Last update: {timestamp} 31 | Assignee: {assignee or "Unassigned"} 32 | 33 | 🏷️ Labels: {label1}, {label2}, {label3} 34 | ``` 35 | 36 | ### 3. Epic Context 37 | If issue is part of an epic: 38 | ``` 39 | 📚 Epic Context: 40 | Epic: {epic_name} 41 | Epic progress: {completed_tasks}/{total_tasks} tasks complete 42 | This task: {task_position} of {total_tasks} 43 | ``` 44 | 45 | ### 4. Local Sync Status 46 | Check if local files are in sync: 47 | ``` 48 | 💾 Local Sync: 49 | Local file: {exists/missing} 50 | Last local update: {timestamp} 51 | Sync status: {in_sync/needs_sync/local_ahead/remote_ahead} 52 | ``` 53 | 54 | ### 5. Quick Status Indicators 55 | Use clear visual indicators: 56 | - 🟢 Open and ready 57 | - 🟡 Open with blockers 58 | - 🔴 Open and overdue 59 | - ✅ Closed and complete 60 | - ❌ Closed without completion 61 | 62 | ### 6. Actionable Next Steps 63 | Based on status, suggest actions: 64 | ``` 65 | 🚀 Suggested Actions: 66 | - Start work: /pm:issue-start $ARGUMENTS 67 | - Sync updates: /pm:issue-sync $ARGUMENTS 68 | - Close issue: gh issue close #$ARGUMENTS 69 | - Reopen issue: gh issue reopen #$ARGUMENTS 70 | ``` 71 | 72 | ### 7. Batch Status 73 | If checking multiple issues, support comma-separated list: 74 | ``` 75 | /pm:issue-status 123,124,125 76 | ``` 77 | 78 | Keep the output concise but informative, perfect for quick status checks during development of Issue #$ARGUMENTS. 79 | -------------------------------------------------------------------------------- /ccpm/scripts/pm/blocked.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "Getting tasks..." 3 | echo "" 4 | echo "" 5 | 6 | echo "🚫 Blocked Tasks" 7 | echo "================" 8 | echo "" 9 | 10 | found=0 11 | 12 | for epic_dir in .claude/epics/*/; do 13 | [ -d "$epic_dir" ] || continue 14 | epic_name=$(basename "$epic_dir") 15 | 16 | for task_file in "$epic_dir"/[0-9]*.md; do 17 | [ -f "$task_file" ] || continue 18 | 19 | # Check if task is open 20 | status=$(grep "^status:" "$task_file" | head -1 | sed 's/^status: *//') 21 | if [ "$status" != "open" ] && [ -n "$status" ]; then 22 | continue 23 | fi 24 | 25 | # Check for dependencies 26 | # Extract dependencies from task file 27 | deps_line=$(grep "^depends_on:" "$task_file" | head -1) 28 | if [ -n "$deps_line" ]; then 29 | deps=$(echo "$deps_line" | sed 's/^depends_on: *//') 30 | deps=$(echo "$deps" | sed 's/^\[//' | sed 's/\]$//') 31 | deps=$(echo "$deps" | sed 's/,/ /g') 32 | # Trim whitespace and handle empty cases 33 | deps=$(echo "$deps" | sed 's/^[[:space:]]*//' | sed 's/[[:space:]]*$//') 34 | [ -z "$deps" ] && deps="" 35 | else 36 | deps="" 37 | fi 38 | 39 | if [ -n "$deps" ] && [ "$deps" != "depends_on:" ]; then 40 | task_name=$(grep "^name:" "$task_file" | head -1 | sed 's/^name: *//') 41 | task_num=$(basename "$task_file" .md) 42 | 43 | echo "⏸️ Task #$task_num - $task_name" 44 | echo " Epic: $epic_name" 45 | echo " Blocked by: [$deps]" 46 | 47 | # Check status of dependencies 48 | open_deps="" 49 | for dep in $deps; do 50 | dep_file="$epic_dir$dep.md" 51 | if [ -f "$dep_file" ]; then 52 | dep_status=$(grep "^status:" "$dep_file" | head -1 | sed 's/^status: *//') 53 | [ "$dep_status" = "open" ] && open_deps="$open_deps #$dep" 54 | fi 55 | done 56 | 57 | [ -n "$open_deps" ] && echo " Waiting for:$open_deps" 58 | echo "" 59 | ((found++)) 60 | fi 61 | done 62 | done 63 | 64 | if [ $found -eq 0 ]; then 65 | echo "No blocked tasks found!" 66 | echo "" 67 | echo "💡 All tasks with dependencies are either completed or in progress." 68 | else 69 | echo "📊 Total blocked: $found tasks" 70 | fi 71 | 72 | exit 0 73 | -------------------------------------------------------------------------------- /ccpm/commands/pm/sync.md: -------------------------------------------------------------------------------- 1 | --- 2 | allowed-tools: Bash, Read, Write, LS 3 | --- 4 | 5 | # Sync 6 | 7 | Full bidirectional sync between local and GitHub. 8 | 9 | ## Usage 10 | ``` 11 | /pm:sync [epic_name] 12 | ``` 13 | 14 | If epic_name provided, sync only that epic. Otherwise sync all. 15 | 16 | ## Instructions 17 | 18 | ### 1. Pull from GitHub 19 | 20 | Get current state of all issues: 21 | ```bash 22 | # Get all epic and task issues 23 | gh issue list --label "epic" --limit 1000 --json number,title,state,body,labels,updatedAt 24 | gh issue list --label "task" --limit 1000 --json number,title,state,body,labels,updatedAt 25 | ``` 26 | 27 | ### 2. Update Local from GitHub 28 | 29 | For each GitHub issue: 30 | - Find corresponding local file by issue number 31 | - Compare states: 32 | - If GitHub state newer (updatedAt > local updated), update local 33 | - If GitHub closed but local open, close local 34 | - If GitHub reopened but local closed, reopen local 35 | - Update frontmatter to match GitHub state 36 | 37 | ### 3. Push Local to GitHub 38 | 39 | For each local task/epic: 40 | - If has GitHub URL but GitHub issue not found, it was deleted - mark local as archived 41 | - If no GitHub URL, create new issue (like epic-sync) 42 | - If local updated > GitHub updatedAt, push changes: 43 | ```bash 44 | gh issue edit {number} --body-file {local_file} 45 | ``` 46 | 47 | ### 4. Handle Conflicts 48 | 49 | If both changed (local and GitHub updated since last sync): 50 | - Show both versions 51 | - Ask user: "Local and GitHub both changed. Keep: (local/github/merge)?" 52 | - Apply user's choice 53 | 54 | ### 5. Update Sync Timestamps 55 | 56 | Update all synced files with last_sync timestamp. 57 | 58 | ### 6. Output 59 | 60 | ``` 61 | 🔄 Sync Complete 62 | 63 | Pulled from GitHub: 64 | Updated: {count} files 65 | Closed: {count} issues 66 | 67 | Pushed to GitHub: 68 | Updated: {count} issues 69 | Created: {count} new issues 70 | 71 | Conflicts resolved: {count} 72 | 73 | Status: 74 | ✅ All files synced 75 | {or list any sync failures} 76 | ``` 77 | 78 | ## Important Notes 79 | 80 | Follow `/rules/github-operations.md` for GitHub commands. 81 | Follow `/rules/frontmatter-operations.md` for local updates. 82 | Always backup before sync in case of issues. -------------------------------------------------------------------------------- /ccpm/ccpm.config: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # CCPM Configuration 3 | # This ensures all GitHub issues are created in the correct repository 4 | 5 | # Function to detect repository from git remote with enhanced error handling 6 | get_github_repo() { 7 | local remote_url=$(git remote get-url origin 2>/dev/null) 8 | 9 | if [ -z "$remote_url" ]; then 10 | echo "Error: No git remote found" >&2 11 | return 1 12 | fi 13 | 14 | # Handle HTTPS, SSH, and SCP-style URLs 15 | local repo="$remote_url" 16 | # Remove various GitHub URL prefixes 17 | repo=$(echo "$repo" | sed -E 's#^https://github\.com/##') 18 | repo=$(echo "$repo" | sed -E 's#^git@github\.com:##') 19 | repo=$(echo "$repo" | sed -E 's#^ssh://git@github\.com/##') 20 | repo=$(echo "$repo" | sed -E 's#^ssh://github\.com/##') 21 | # Remove .git suffix if present 22 | repo=$(echo "$repo" | sed 's#\.git$##') 23 | 24 | # Validate format 25 | if [[ ! "$repo" =~ ^[^/]+/[^/]+$ ]]; then 26 | echo "Error: Invalid repository format: $repo" >&2 27 | return 1 28 | fi 29 | 30 | echo "$repo" 31 | } 32 | 33 | # Allow environment override 34 | if [ -n "$CCPM_GITHUB_REPO" ]; then 35 | GITHUB_REPO="$CCPM_GITHUB_REPO" 36 | else 37 | GITHUB_REPO=$(get_github_repo) || exit 1 38 | fi 39 | 40 | # Extract owner and repo name 41 | GITHUB_OWNER=$(echo $GITHUB_REPO | cut -d/ -f1) 42 | GITHUB_REPO_NAME=$(echo $GITHUB_REPO | cut -d/ -f2) 43 | 44 | # Export for gh CLI 45 | export GH_REPO="$GITHUB_REPO" 46 | 47 | # Validate repository exists (optional - can be disabled for performance) 48 | if [ "${CCPM_SKIP_REPO_VALIDATION:-false}" != "true" ]; then 49 | if ! gh repo view "$GITHUB_REPO" >/dev/null 2>&1; then 50 | echo "Warning: Repository $GITHUB_REPO not accessible. Please ensure:" >&2 51 | echo " 1. Repository exists on GitHub" >&2 52 | echo " 2. You have write access" >&2 53 | echo " 3. You're authenticated with gh CLI (run: gh auth login)" >&2 54 | fi 55 | fi 56 | 57 | # Wrapper function with error handling and logging 58 | gh_issue_create() { 59 | echo "Creating issue in: $GITHUB_REPO" >&2 60 | gh issue create --repo "$GITHUB_REPO" "$@" 61 | } 62 | 63 | # Export functions for use in other scripts 64 | export -f get_github_repo 65 | export -f gh_issue_create -------------------------------------------------------------------------------- /ccpm/commands/pm/epic-oneshot.md: -------------------------------------------------------------------------------- 1 | --- 2 | allowed-tools: Read, LS 3 | --- 4 | 5 | # Epic Oneshot 6 | 7 | Decompose epic into tasks and sync to GitHub in one operation. 8 | 9 | ## Usage 10 | ``` 11 | /pm:epic-oneshot 12 | ``` 13 | 14 | ## Instructions 15 | 16 | ### 1. Validate Prerequisites 17 | 18 | Check that epic exists and hasn't been processed: 19 | ```bash 20 | # Epic must exist 21 | test -f .claude/epics/$ARGUMENTS/epic.md || echo "❌ Epic not found. Run: /pm:prd-parse $ARGUMENTS" 22 | 23 | # Check for existing tasks 24 | if ls .claude/epics/$ARGUMENTS/[0-9]*.md 2>/dev/null | grep -q .; then 25 | echo "⚠️ Tasks already exist. This will create duplicates." 26 | echo "Delete existing tasks or use /pm:epic-sync instead." 27 | exit 1 28 | fi 29 | 30 | # Check if already synced 31 | if grep -q "github:" .claude/epics/$ARGUMENTS/epic.md; then 32 | echo "⚠️ Epic already synced to GitHub." 33 | echo "Use /pm:epic-sync to update." 34 | exit 1 35 | fi 36 | ``` 37 | 38 | ### 2. Execute Decompose 39 | 40 | Simply run the decompose command: 41 | ``` 42 | Running: /pm:epic-decompose $ARGUMENTS 43 | ``` 44 | 45 | This will: 46 | - Read the epic 47 | - Create task files (using parallel agents if appropriate) 48 | - Update epic with task summary 49 | 50 | ### 3. Execute Sync 51 | 52 | Immediately follow with sync: 53 | ``` 54 | Running: /pm:epic-sync $ARGUMENTS 55 | ``` 56 | 57 | This will: 58 | - Create epic issue on GitHub 59 | - Create sub-issues (using parallel agents if appropriate) 60 | - Rename task files to issue IDs 61 | - Create worktree 62 | 63 | ### 4. Output 64 | 65 | ``` 66 | 🚀 Epic Oneshot Complete: $ARGUMENTS 67 | 68 | Step 1: Decomposition ✓ 69 | - Tasks created: {count} 70 | 71 | Step 2: GitHub Sync ✓ 72 | - Epic: #{number} 73 | - Sub-issues created: {count} 74 | - Worktree: ../epic-$ARGUMENTS 75 | 76 | Ready for development! 77 | Start work: /pm:epic-start $ARGUMENTS 78 | Or single task: /pm:issue-start {task_number} 79 | ``` 80 | 81 | ## Important Notes 82 | 83 | This is simply a convenience wrapper that runs: 84 | 1. `/pm:epic-decompose` 85 | 2. `/pm:epic-sync` 86 | 87 | Both commands handle their own error checking, parallel execution, and validation. This command just orchestrates them in sequence. 88 | 89 | Use this when you're confident the epic is ready and want to go from epic to GitHub issues in one step. -------------------------------------------------------------------------------- /ccpm/commands/pm/clean.md: -------------------------------------------------------------------------------- 1 | --- 2 | allowed-tools: Bash, Read, Write, LS 3 | --- 4 | 5 | # Clean 6 | 7 | Clean up completed work and archive old epics. 8 | 9 | ## Usage 10 | ``` 11 | /pm:clean [--dry-run] 12 | ``` 13 | 14 | Options: 15 | - `--dry-run` - Show what would be cleaned without doing it 16 | 17 | ## Instructions 18 | 19 | ### 1. Identify Completed Epics 20 | 21 | Find epics with: 22 | - `status: completed` in frontmatter 23 | - All tasks closed 24 | - Last update > 30 days ago 25 | 26 | ### 2. Identify Stale Work 27 | 28 | Find: 29 | - Progress files for closed issues 30 | - Update directories for completed work 31 | - Orphaned task files (epic deleted) 32 | - Empty directories 33 | 34 | ### 3. Show Cleanup Plan 35 | 36 | ``` 37 | 🧹 Cleanup Plan 38 | 39 | Completed Epics to Archive: 40 | {epic_name} - Completed {days} days ago 41 | {epic_name} - Completed {days} days ago 42 | 43 | Stale Progress to Remove: 44 | {count} progress files for closed issues 45 | 46 | Empty Directories: 47 | {list_of_empty_dirs} 48 | 49 | Space to Recover: ~{size}KB 50 | 51 | {If --dry-run}: This is a dry run. No changes made. 52 | {Otherwise}: Proceed with cleanup? (yes/no) 53 | ``` 54 | 55 | ### 4. Execute Cleanup 56 | 57 | If user confirms: 58 | 59 | **Archive Epics:** 60 | ```bash 61 | mkdir -p .claude/epics/.archived 62 | mv .claude/epics/{completed_epic} .claude/epics/.archived/ 63 | ``` 64 | 65 | **Remove Stale Files:** 66 | - Delete progress files for closed issues > 30 days 67 | - Remove empty update directories 68 | - Clean up orphaned files 69 | 70 | **Create Archive Log:** 71 | Create `.claude/epics/.archived/archive-log.md`: 72 | ```markdown 73 | # Archive Log 74 | 75 | ## {current_date} 76 | - Archived: {epic_name} (completed {date}) 77 | - Removed: {count} stale progress files 78 | - Cleaned: {count} empty directories 79 | ``` 80 | 81 | ### 5. Output 82 | 83 | ``` 84 | ✅ Cleanup Complete 85 | 86 | Archived: 87 | {count} completed epics 88 | 89 | Removed: 90 | {count} stale files 91 | {count} empty directories 92 | 93 | Space recovered: {size}KB 94 | 95 | System is clean and organized. 96 | ``` 97 | 98 | ## Important Notes 99 | 100 | Always offer --dry-run to preview changes. 101 | Never delete PRDs or incomplete work. 102 | Keep archive log for history. -------------------------------------------------------------------------------- /doc/AGENTS_ZH.md: -------------------------------------------------------------------------------- 1 | # 代理 2 | 3 | 专门处理繁重工作的代理,返回简洁摘要以保留上下文。 4 | 5 | ## 核心理念 6 | 7 | > "不要将子代理拟人化。使用它们来组织你的提示并省略上下文。当子代理能够完成大量工作但只向主线程提供少量信息时效果最佳。" 8 | > 9 | > – Adam Wolff, Anthropic 10 | 11 | ## 可用代理 12 | 13 | ### 🔍 `code-analyzer` 14 | - **目的**: 跨多个文件查找错误而不污染主线程上下文 15 | - **模式**: 搜索多个文件 → 分析代码 → 返回错误报告 16 | - **用法**: 当你需要追踪逻辑流、查找错误或验证更改时 17 | - **返回**: 仅包含关键发现的简洁错误报告 18 | 19 | ### 📄 `file-analyzer` 20 | - **目的**: 读取和总结详细文件(日志、输出、配置) 21 | - **模式**: 读取文件 → 提取见解 → 返回摘要 22 | - **用法**: 当你需要理解日志文件或分析详细输出时 23 | - **返回**: 关键发现和可操作的见解(减少80-90%的大小) 24 | 25 | ### 🧪 `test-runner` 26 | - **目的**: 执行测试而不将输出转储到主线程 27 | - **模式**: 运行测试 → 捕获到日志 → 分析结果 → 返回摘要 28 | - **用法**: 当你需要运行测试并理解失败原因时 29 | - **返回**: 包含失败分析的测试结果摘要 30 | 31 | ### 🔀 `parallel-worker` 32 | - **目的**: 协调处理问题的多个并行工作流 33 | - **模式**: 读取分析 → 生成子代理 → 整合结果 → 返回摘要 34 | - **用法**: 当在工作树中执行并行工作流时 35 | - **返回**: 所有并行工作的整合状态 36 | 37 | ## 为什么使用代理? 38 | 39 | 代理是保护主线程免受信息过载的**上下文防火墙**: 40 | 41 | ``` 42 | 不使用代理: 43 | 主线程读取10个文件 → 上下文爆炸 → 失去连贯性 44 | 45 | 使用代理: 46 | 代理读取10个文件 → 主线程获得1个摘要 → 上下文得以保留 47 | ``` 48 | 49 | ## 代理如何保留上下文 50 | 51 | 1. **繁重工作** - 代理完成繁琐的工作(读取文件、运行测试、实现功能) 52 | 2. **上下文隔离** - 实现细节保留在代理中,不在主线程 53 | 3. **简洁返回** - 只有必要信息返回到主线程对话 54 | 4. **并行执行** - 多个代理可以同时工作而不会产生上下文冲突 55 | 56 | ## 使用示例 57 | 58 | ```bash 59 | # 分析代码查找错误 60 | 任务: "在代码库中搜索内存泄漏" 61 | 代理: code-analyzer 62 | 返回: "发现3个潜在泄漏: [简洁列表]" 63 | 主线程不会看到: 检查的数百个文件 64 | 65 | # 运行测试 66 | 任务: "运行身份验证测试" 67 | 代理: test-runner 68 | 返回: "10个测试中有2个失败: [失败摘要]" 69 | 主线程不会看到: 详细的测试输出和日志 70 | 71 | # 并行实现 72 | 任务: "使用并行流实现问题#1234" 73 | 代理: parallel-worker 74 | 返回: "完成4/4个流,修改了15个文件" 75 | 主线程不会看到: 单个实现细节 76 | ``` 77 | 78 | ## 创建新代理 79 | 80 | 新代理应遵循以下原则: 81 | 82 | 1. **单一目的** - 每个代理都有一个明确的工作 83 | 2. **上下文缩减** - 返回处理内容的10-20% 84 | 3. **不角色扮演** - 代理不是"专家",而是任务执行器 85 | 4. **清晰模式** - 定义输入 → 处理 → 输出模式 86 | 5. **错误处理** - 优雅地处理失败并清晰报告 87 | 88 | ## 需避免的反模式 89 | 90 | ❌ **创建"专家"代理** (数据库专家、API专家) 91 | 代理没有不同的知识 - 它们都是相同的模型 92 | 93 | ❌ **返回详细输出** 94 | 违背了上下文保留的目的 95 | 96 | ❌ **让代理相互沟通** 97 | 应该使用协调代理(如parallel-worker) 98 | 99 | ❌ **为简单任务使用代理** 100 | 只有当上下文缩减有价值时才使用代理 101 | 102 | ## 与PM系统的集成 103 | 104 | 代理与PM命令系统无缝集成: 105 | 106 | - `/pm:issue-analyze` → 识别工作流 107 | - `/pm:issue-start` → 生成parallel-worker代理 108 | - parallel-worker → 生成多个子代理 109 | - 子代理 → 在工作树中并行工作 110 | - 结果 → 整合回主线程 111 | 112 | 这创建了一个层次结构,在每个级别都最大化并行性同时保留上下文。 -------------------------------------------------------------------------------- /zh-docs/AGENTS_ZH.md: -------------------------------------------------------------------------------- 1 | # 代理 2 | 3 | 专门处理繁重工作的代理,返回简洁摘要以保留上下文。 4 | 5 | ## 核心理念 6 | 7 | > "不要将子代理拟人化。使用它们来组织你的提示并省略上下文。当子代理能够完成大量工作但只向主线程提供少量信息时效果最佳。" 8 | > 9 | > – Adam Wolff, Anthropic 10 | 11 | ## 可用代理 12 | 13 | ### 🔍 `code-analyzer` 14 | - **目的**: 跨多个文件查找错误而不污染主线程上下文 15 | - **模式**: 搜索多个文件 → 分析代码 → 返回错误报告 16 | - **用法**: 当你需要追踪逻辑流、查找错误或验证更改时 17 | - **返回**: 仅包含关键发现的简洁错误报告 18 | 19 | ### 📄 `file-analyzer` 20 | - **目的**: 读取和总结详细文件(日志、输出、配置) 21 | - **模式**: 读取文件 → 提取见解 → 返回摘要 22 | - **用法**: 当你需要理解日志文件或分析详细输出时 23 | - **返回**: 关键发现和可操作的见解(减少80-90%的大小) 24 | 25 | ### 🧪 `test-runner` 26 | - **目的**: 执行测试而不将输出转储到主线程 27 | - **模式**: 运行测试 → 捕获到日志 → 分析结果 → 返回摘要 28 | - **用法**: 当你需要运行测试并理解失败原因时 29 | - **返回**: 包含失败分析的测试结果摘要 30 | 31 | ### 🔀 `parallel-worker` 32 | - **目的**: 协调处理问题的多个并行工作流 33 | - **模式**: 读取分析 → 生成子代理 → 整合结果 → 返回摘要 34 | - **用法**: 当在工作树中执行并行工作流时 35 | - **返回**: 所有并行工作的整合状态 36 | 37 | ## 为什么使用代理? 38 | 39 | 代理是保护主线程免受信息过载的**上下文防火墙**: 40 | 41 | ``` 42 | 不使用代理: 43 | 主线程读取10个文件 → 上下文爆炸 → 失去连贯性 44 | 45 | 使用代理: 46 | 代理读取10个文件 → 主线程获得1个摘要 → 上下文得以保留 47 | ``` 48 | 49 | ## 代理如何保留上下文 50 | 51 | 1. **繁重工作** - 代理完成繁琐的工作(读取文件、运行测试、实现功能) 52 | 2. **上下文隔离** - 实现细节保留在代理中,不在主线程 53 | 3. **简洁返回** - 只有必要信息返回到主线程对话 54 | 4. **并行执行** - 多个代理可以同时工作而不会产生上下文冲突 55 | 56 | ## 使用示例 57 | 58 | ```bash 59 | # 分析代码查找错误 60 | 任务: "在代码库中搜索内存泄漏" 61 | 代理: code-analyzer 62 | 返回: "发现3个潜在泄漏: [简洁列表]" 63 | 主线程不会看到: 检查的数百个文件 64 | 65 | # 运行测试 66 | 任务: "运行身份验证测试" 67 | 代理: test-runner 68 | 返回: "10个测试中有2个失败: [失败摘要]" 69 | 主线程不会看到: 详细的测试输出和日志 70 | 71 | # 并行实现 72 | 任务: "使用并行流实现问题#1234" 73 | 代理: parallel-worker 74 | 返回: "完成4/4个流,修改了15个文件" 75 | 主线程不会看到: 单个实现细节 76 | ``` 77 | 78 | ## 创建新代理 79 | 80 | 新代理应遵循以下原则: 81 | 82 | 1. **单一目的** - 每个代理都有一个明确的工作 83 | 2. **上下文缩减** - 返回处理内容的10-20% 84 | 3. **不角色扮演** - 代理不是"专家",而是任务执行器 85 | 4. **清晰模式** - 定义输入 → 处理 → 输出模式 86 | 5. **错误处理** - 优雅地处理失败并清晰报告 87 | 88 | ## 需避免的反模式 89 | 90 | ❌ **创建"专家"代理** (数据库专家、API专家) 91 | 代理没有不同的知识 - 它们都是相同的模型 92 | 93 | ❌ **返回详细输出** 94 | 违背了上下文保留的目的 95 | 96 | ❌ **让代理相互沟通** 97 | 应该使用协调代理(如parallel-worker) 98 | 99 | ❌ **为简单任务使用代理** 100 | 只有当上下文缩减有价值时才使用代理 101 | 102 | ## 与PM系统的集成 103 | 104 | 代理与PM命令系统无缝集成: 105 | 106 | - `/pm:issue-analyze` → 识别工作流 107 | - `/pm:issue-start` → 生成parallel-worker代理 108 | - parallel-worker → 生成多个子代理 109 | - 子代理 → 在工作树中并行工作 110 | - 结果 → 整合回主线程 111 | 112 | 这创建了一个层次结构,在每个级别都最大化并行性同时保留上下文。 -------------------------------------------------------------------------------- /ccpm/scripts/pm/in-progress.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "Getting status..." 3 | echo "" 4 | echo "" 5 | 6 | echo "🔄 In Progress Work" 7 | echo "===================" 8 | echo "" 9 | 10 | # Check for active work in updates directories 11 | found=0 12 | 13 | if [ -d ".claude/epics" ]; then 14 | for updates_dir in .claude/epics/*/updates/*/; do 15 | [ -d "$updates_dir" ] || continue 16 | 17 | issue_num=$(basename "$updates_dir") 18 | epic_name=$(basename $(dirname $(dirname "$updates_dir"))) 19 | 20 | if [ -f "$updates_dir/progress.md" ]; then 21 | completion=$(grep "^completion:" "$updates_dir/progress.md" | head -1 | sed 's/^completion: *//') 22 | [ -z "$completion" ] && completion="0%" 23 | 24 | # Get task name from the task file 25 | task_file=".claude/epics/$epic_name/$issue_num.md" 26 | if [ -f "$task_file" ]; then 27 | task_name=$(grep "^name:" "$task_file" | head -1 | sed 's/^name: *//') 28 | else 29 | task_name="Unknown task" 30 | fi 31 | 32 | echo "📝 Issue #$issue_num - $task_name" 33 | echo " Epic: $epic_name" 34 | echo " Progress: $completion complete" 35 | 36 | # Check for recent updates 37 | if [ -f "$updates_dir/progress.md" ]; then 38 | last_update=$(grep "^last_sync:" "$updates_dir/progress.md" | head -1 | sed 's/^last_sync: *//') 39 | [ -n "$last_update" ] && echo " Last update: $last_update" 40 | fi 41 | 42 | echo "" 43 | ((found++)) 44 | fi 45 | done 46 | fi 47 | 48 | # Also check for in-progress epics 49 | echo "📚 Active Epics:" 50 | for epic_dir in .claude/epics/*/; do 51 | [ -d "$epic_dir" ] || continue 52 | [ -f "$epic_dir/epic.md" ] || continue 53 | 54 | status=$(grep "^status:" "$epic_dir/epic.md" | head -1 | sed 's/^status: *//') 55 | if [ "$status" = "in-progress" ] || [ "$status" = "active" ]; then 56 | epic_name=$(grep "^name:" "$epic_dir/epic.md" | head -1 | sed 's/^name: *//') 57 | progress=$(grep "^progress:" "$epic_dir/epic.md" | head -1 | sed 's/^progress: *//') 58 | [ -z "$epic_name" ] && epic_name=$(basename "$epic_dir") 59 | [ -z "$progress" ] && progress="0%" 60 | 61 | echo " • $epic_name - $progress complete" 62 | fi 63 | done 64 | 65 | echo "" 66 | if [ $found -eq 0 ]; then 67 | echo "No active work items found." 68 | echo "" 69 | echo "💡 Start work with: /pm:next" 70 | else 71 | echo "📊 Total active items: $found" 72 | fi 73 | 74 | exit 0 75 | -------------------------------------------------------------------------------- /ccpm/commands/pm/import.md: -------------------------------------------------------------------------------- 1 | --- 2 | allowed-tools: Bash, Read, Write, LS 3 | --- 4 | 5 | # Import 6 | 7 | Import existing GitHub issues into the PM system. 8 | 9 | ## Usage 10 | ``` 11 | /pm:import [--epic ] [--label