diff --git a/.claude/commands/pm/epic-sync.md b/.claude/commands/pm/epic-sync.md index 042e8b1..b7a3eb7 100644 --- a/.claude/commands/pm/epic-sync.md +++ b/.claude/commands/pm/epic-sync.md @@ -25,6 +25,34 @@ If no tasks found: "❌ No tasks to sync. Run: /pm:epic-decompose $ARGUMENTS" ## Instructions +### 0. Check Remote Repository + +Follow `/rules/github-operations.md` to ensure we're not syncing to the CCPM template: + +```bash +# Check if remote origin is the CCPM template repository +remote_url=$(git remote get-url origin 2>/dev/null || echo "") +if [[ "$remote_url" == *"automazeio/ccpm"* ]] || [[ "$remote_url" == *"automazeio/ccpm.git"* ]]; then + echo "❌ ERROR: You're trying to sync with the CCPM template repository!" + echo "" + echo "This repository (automazeio/ccpm) is a template for others to use." + echo "You should NOT create issues or PRs here." + echo "" + echo "To fix this:" + echo "1. Fork this repository to your own GitHub account" + echo "2. Update your remote origin:" + echo " git remote set-url origin https://github.com/YOUR_USERNAME/YOUR_REPO.git" + echo "" + echo "Or if this is a new project:" + echo "1. Create a new repository on GitHub" + echo "2. Update your remote origin:" + echo " git remote set-url origin https://github.com/YOUR_USERNAME/YOUR_REPO.git" + echo "" + echo "Current remote: $remote_url" + exit 1 +fi +``` + ### 1. Create Epic Issue Strip frontmatter and prepare GitHub issue body: @@ -34,11 +62,11 @@ sed '1,/^---$/d; 1,/^---$/d' .claude/epics/$ARGUMENTS/epic.md > /tmp/epic-body-r # Remove "## Tasks Created" section and replace with Stats awk ' - /^## Tasks Created/ { + /^## Tasks Created/ { in_tasks=1 next } - /^## / && in_tasks { + /^## / && in_tasks { in_tasks=0 # When we hit the next section after Tasks Created, add Stats if (total_tasks) { @@ -53,10 +81,10 @@ awk ' /^Total tasks:/ && in_tasks { total_tasks = $3; next } /^Parallel tasks:/ && in_tasks { parallel_tasks = $3; next } /^Sequential tasks:/ && in_tasks { sequential_tasks = $3; next } - /^Estimated total effort:/ && in_tasks { + /^Estimated total effort:/ && in_tasks { gsub(/^Estimated total effort: /, "") total_effort = $0 - next + next } !in_tasks { print } END { @@ -112,13 +140,13 @@ if [ "$task_count" -lt 5 ]; then # Create sequentially for small batches for task_file in .claude/epics/$ARGUMENTS/[0-9][0-9][0-9].md; do [ -f "$task_file" ] || continue - + # Extract task name from frontmatter task_name=$(grep '^name:' "$task_file" | sed 's/^name: *//') - + # Strip frontmatter from task content sed '1,/^---$/d; 1,/^---$/d' "$task_file" > /tmp/task-body.md - + # Create sub-issue with labels if [ "$use_subissues" = true ]; then task_number=$(gh sub-issue create \ @@ -134,11 +162,11 @@ if [ "$task_count" -lt 5 ]; then --label "task,epic:$ARGUMENTS" \ --json number -q .number) fi - + # Record mapping for renaming echo "$task_file:$task_number" >> /tmp/task-mapping.txt done - + # After creating all issues, update references and rename files # This follows the same process as step 3 below fi @@ -149,14 +177,14 @@ fi ```bash if [ "$task_count" -ge 5 ]; then echo "Creating $task_count sub-issues in parallel..." - + # Check if gh-sub-issue is available for parallel agents if gh extension list | grep -q "yahsan2/gh-sub-issue"; then subissue_cmd="gh sub-issue create --parent $epic_number" else subissue_cmd="gh issue create" fi - + # Batch tasks for parallel processing # Spawn agents to create sub-issues in parallel with proper labels # Each agent must use: --label "task,epic:$ARGUMENTS" @@ -171,24 +199,24 @@ Task: prompt: | Create GitHub sub-issues for tasks in epic $ARGUMENTS Parent epic issue: #$epic_number - + Tasks to process: - {list of 3-4 task files} - + For each task file: 1. Extract task name from frontmatter 2. Strip frontmatter using: sed '1,/^---$/d; 1,/^---$/d' 3. Create sub-issue using: - - If gh-sub-issue available: + - If gh-sub-issue available: gh sub-issue create --parent $epic_number --title "$task_name" \ --body-file /tmp/task-body.md --label "task,epic:$ARGUMENTS" - - Otherwise: + - Otherwise: gh issue create --title "$task_name" --body-file /tmp/task-body.md \ --label "task,epic:$ARGUMENTS" 4. Record: task_file:issue_number - + IMPORTANT: Always include --label parameter with "task,epic:$ARGUMENTS" - + Return mapping of files to issue numbers. ``` @@ -221,30 +249,30 @@ Then rename files and update all references: # Process each task file while IFS=: read -r task_file task_number; do new_name="$(dirname "$task_file")/${task_number}.md" - + # Read the file content content=$(cat "$task_file") - + # Update depends_on and conflicts_with references while IFS=: read -r old_num new_num; do # Update arrays like [001, 002] to use new issue numbers content=$(echo "$content" | sed "s/\b$old_num\b/$new_num/g") done < /tmp/id-mapping.txt - + # Write updated content to new file echo "$content" > "$new_name" - + # Remove old file if different from new [ "$task_file" != "$new_name" ] && rm "$task_file" - + # Update github field in frontmatter # Add the GitHub URL to the frontmatter repo=$(gh repo view --json nameWithOwner -q .nameWithOwner) github_url="https://github.com/$repo/issues/$task_number" - + # Update frontmatter with GitHub URL and current timestamp current_date=$(date -u +"%Y-%m-%dT%H:%M:%SZ") - + # Use sed to update the github and updated fields sed -i.bak "/^github:/c\github: $github_url" "$new_name" sed -i.bak "/^updated:/c\updated: $current_date" "$new_name" @@ -260,16 +288,16 @@ If NOT using gh-sub-issue, add task list to epic: if [ "$use_subissues" = false ]; then # Get current epic body gh issue view {epic_number} --json body -q .body > /tmp/epic-body.md - + # Append task list cat >> /tmp/epic-body.md << 'EOF' - + ## Tasks - [ ] #{task1_number} {task1_name} - [ ] #{task2_number} {task2_name} - [ ] #{task3_number} {task3_name} EOF - + # Update epic issue gh issue edit {epic_number} --body-file /tmp/epic-body.md fi @@ -304,16 +332,16 @@ EOF # Add each task with its real issue number for task_file in .claude/epics/$ARGUMENTS/[0-9]*.md; do [ -f "$task_file" ] || continue - + # Get issue number (filename without .md) issue_num=$(basename "$task_file" .md) - + # Get task name from frontmatter task_name=$(grep '^name:' "$task_file" | sed 's/^name: *//') - + # Get parallel status parallel=$(grep '^parallel:' "$task_file" | sed 's/^parallel: *//') - + # Add to tasks section echo "- [ ] #${issue_num} - ${task_name} (parallel: ${parallel})" >> /tmp/tasks-section.md done @@ -336,7 +364,7 @@ cp .claude/epics/$ARGUMENTS/epic.md .claude/epics/$ARGUMENTS/epic.md.backup # Use awk to replace the section awk ' - /^## Tasks Created/ { + /^## Tasks Created/ { skip=1 while ((getline line < "/tmp/tasks-section.md") > 0) print line close("/tmp/tasks-section.md") @@ -366,10 +394,10 @@ EOF # Add each task mapping for task_file in .claude/epics/$ARGUMENTS/[0-9]*.md; do [ -f "$task_file" ] || continue - + issue_num=$(basename "$task_file" .md) task_name=$(grep '^name:' "$task_file" | sed 's/^name: *//') - + echo "- #${issue_num}: ${task_name} - https://github.com/${repo}/issues/${issue_num}" >> .claude/epics/$ARGUMENTS/github-mapping.md done @@ -424,4 +452,4 @@ If any issue creation fails: - Trust GitHub CLI authentication - Don't pre-check for duplicates - Update frontmatter only after successful creation -- Keep operations simple and atomic \ No newline at end of file +- Keep operations simple and atomic diff --git a/.claude/commands/pm/issue-sync.md b/.claude/commands/pm/issue-sync.md index 4f2ce95..fd8137c 100644 --- a/.claude/commands/pm/issue-sync.md +++ b/.claude/commands/pm/issue-sync.md @@ -21,6 +21,17 @@ Push local updates as GitHub issue comments for transparent audit trail. Before proceeding, complete these validation steps. Do not bother the user with preflight checks progress ("I'm not going to ..."). Just do them and move on. +0. **Repository Protection Check:** + Follow `/rules/github-operations.md` - check remote origin: + ```bash + remote_url=$(git remote get-url origin 2>/dev/null || echo "") + if [[ "$remote_url" == *"automazeio/ccpm"* ]]; then + echo "❌ ERROR: Cannot sync to CCPM template repository!" + echo "Update your remote: git remote set-url origin https://github.com/YOUR_USERNAME/YOUR_REPO.git" + exit 1 + fi + ``` + 1. **GitHub Authentication:** - Run: `gh auth status` - If not authenticated, tell user: "❌ GitHub CLI not authenticated. Run: gh auth login" diff --git a/.claude/hooks/README.md b/.claude/hooks/README.md new file mode 100644 index 0000000..456e73c --- /dev/null +++ b/.claude/hooks/README.md @@ -0,0 +1,130 @@ +# Claude Hooks Configuration + +## Bash Worktree Fix Hook + +This hook automatically fixes the Bash tool's directory reset issue when working in git worktrees. + +### Problem + +The Bash tool resets to the main project directory after every command, making it impossible to work in worktrees without manually prefixing every command with `cd /path/to/worktree &&`. + +### Solution + +The pre-tool-use hook automatically detects when you're in a worktree and injects the necessary `cd` prefix to all Bash commands. + +### How It Works + +1. **Detection**: Before any Bash command executes, the hook checks if `.git` is a file (worktree) or directory (main repo) +2. **Injection**: If in a worktree, prepends `cd /absolute/path/to/worktree && ` to the command +3. **Transparency**: Agents don't need to know about this - it happens automatically + +### Configuration + +Add to your `.claude/settings.json`: + + +```json +{ + "hooks": { + "pre-tool-use": { + "Bash": { + "enabled": true, + "script": ".claude/hooks/bash-worktree-fix.sh", + "apply_to_subagents": true + } + } + } +} +``` + +### Testing + +To test the hook: + +```bash +# Enable debug mode +export CLAUDE_HOOK_DEBUG=true + +# Test in main repo (should pass through) +.claude/hooks/bash-worktree-fix.sh "ls -la" + +# Test in worktree (should inject cd) +cd /path/to/worktree +.claude/hooks/bash-worktree-fix.sh "npm install" +# Output: cd "/path/to/worktree" && npm install +``` + +### Advanced Features + +The script handles: + +- Background processes (`&`) +- Piped commands (`|`) +- Environment variable prefixes (`VAR=value command`) +- Commands that already have `cd` +- Commands using absolute paths +- Debug logging with `CLAUDE_HOOK_DEBUG=true` + +### Edge Cases Handled + +1. **Double-prefix prevention**: Won't add prefix if command already starts with `cd` +2. **Absolute paths**: Skips injection for commands using absolute paths +3. **Special commands**: Skips for `pwd`, `echo`, `export`, etc. that don't need context +4. **Background processes**: Correctly handles `&` at the end of commands +5. **Pipe chains**: Injects only at the start of pipe chains + +### Troubleshooting + +If the hook isn't working: + +1. **Verify the hook is executable:** + ```bash + chmod +x .claude/hooks/bash-worktree-fix.sh + ``` + +2. **Enable debug logging to see what's happening:** + ```bash + export CLAUDE_HOOK_DEBUG=true + ``` + +3. **Test the hook manually with a sample command:** + ```bash + cd /path/to/worktree + .claude/hooks/bash-worktree-fix.sh "npm test" + ``` + +4. **Check that your settings.json is valid JSON:** + ```bash + cat .claude/settings.json | python -m json.tool + ``` + +### Integration with Claude + +Once configured, this hook will: + +- Automatically apply to all Bash tool invocations +- Work for both main agent and sub-agents +- Be completely transparent to users +- Eliminate the need for worktree-specific instructions + +### Result + +With this hook in place, agents can work in worktrees naturally: + +**Agent writes:** + +```bash +npm install +git status +npm run build +``` + +**Hook transforms to:** + +```bash +cd /path/to/my/project/epic-feature && npm install +cd /path/to/my/project/epic-feature && git status +cd /path/to/my/project/epic-feature && npm run build +``` + +**Without the agent knowing or caring about the worktree context!** diff --git a/.claude/hooks/bash-worktree-fix.sh b/.claude/hooks/bash-worktree-fix.sh new file mode 100755 index 0000000..3eb90ad --- /dev/null +++ b/.claude/hooks/bash-worktree-fix.sh @@ -0,0 +1,189 @@ +#!/bin/sh +# POSIX-compliant pre-tool-use hook for Bash tool +# If inside a Git *worktree checkout*, prefix the incoming command with: +# cd '' && +# No sh -c. No tokenization. Quoting preserved. Robust worktree detection. + +DEBUG_MODE="${CLAUDE_HOOK_DEBUG:-false}" + +debug_log() { + case "${DEBUG_MODE:-}" in + true|TRUE|1|yes|YES) + printf '%s\n' "DEBUG [bash-worktree-fix]: $*" >&2 + ;; + esac +} + +# Safely single-quote a string for shell usage: foo'bar -> 'foo'"'"'bar' +shell_squote() { + printf "%s" "$1" | sed "s/'/'\"'\"'/g" +} + +# Detect if CWD is inside a *linked worktree* and print the worktree root. +# Returns 0 with path on stdout if yes; 1 otherwise. +get_worktree_path() { + check_dir="$(pwd)" + + if [ ! -d "${check_dir}" ]; then + debug_log "pwd is not a directory: ${check_dir}" + return 1 + fi + + while [ "${check_dir}" != "/" ]; do + if [ -f "${check_dir}/.git" ]; then + gitdir_content="" + if [ -r "${check_dir}/.git" ]; then + IFS= read -r gitdir_content < "${check_dir}/.git" || gitdir_content="" + # Strip a possible trailing CR (CRLF files) + gitdir_content=$(printf %s "$gitdir_content" | tr -d '\r') + else + debug_log "Unreadable .git file at: ${check_dir}" + fi + + case "${gitdir_content}" in + gitdir:*) + gitdir_path=${gitdir_content#gitdir:} + # Trim leading spaces (portable) + while [ "${gitdir_path# }" != "${gitdir_path}" ]; do + gitdir_path=${gitdir_path# } + done + # Normalize to absolute + case "${gitdir_path}" in + /*) abs_gitdir="${gitdir_path}" ;; + *) abs_gitdir="${check_dir}/${gitdir_path}" ;; + esac + if [ -d "${abs_gitdir}" ]; then + case "${abs_gitdir}" in + */worktrees/*) + debug_log "Detected worktree root: ${check_dir} (gitdir: ${abs_gitdir})" + printf '%s\n' "${check_dir}" + return 0 + ;; + *) + debug_log "Non-worktree .git indirection at: ${check_dir}" + return 1 + ;; + esac + else + debug_log "gitdir path does not exist: ${abs_gitdir}" + return 1 + fi + ;; + *) + debug_log "Unknown .git file format at: ${check_dir}" + return 1 + ;; + esac + + elif [ -d "${check_dir}/.git" ]; then + # Regular repo with .git directory — not a linked worktree + debug_log "Found regular git repo at: ${check_dir}" + return 1 + fi + + check_dir=$(dirname "${check_dir}") + done + + debug_log "No git repository found" + return 1 +} + +# Decide whether to skip prefixing. +# Returns 0 => SKIP (pass through as-is) +# Returns 1 => Prefix with cd +should_skip_command() { + cmd=$1 + + # Empty or whitespace-only? + # If there are no non-space characters, skip. + if [ -z "${cmd##*[![:space:]]*}" ]; then + debug_log "Skipping: empty/whitespace-only command" + return 0 + fi + + # Starts with optional spaces then 'cd' (with or without args)? + case "${cmd}" in + [[:space:]]cd|cd|[[:space:]]cd[[:space:]]*|cd[[:space:]]*) + debug_log "Skipping: command already begins with cd" + return 0 + ;; + esac + + # Builtins / trivial commands that don't require dir context + case "${cmd}" in + :|[[:space:]]:|true|[[:space:]]true|false|[[:space:]]false|\ + pwd|[[:space:]]pwd*|\ + echo|[[:space:]]echo*|\ + export|[[:space:]]export*|\ + alias|[[:space:]]alias*|\ + unalias|[[:space:]]unalias*|\ + set|[[:space:]]set*|\ + unset|[[:space:]]unset*|\ + readonly|[[:space:]]readonly*|\ + umask|[[:space:]]umask*|\ + times|[[:space:]]times*|\ + .|[[:space:]].[[:space:]]*) + debug_log "Skipping: trivial/builtin command" + return 0 + ;; + esac + + # Do NOT skip absolute-path commands; many still depend on cwd. + # We want: cd '' && /abs/cmd ... to preserve semantics. + + return 1 +} + +# Inject the worktree prefix without changing semantics. +# We do NOT wrap in 'sh -c'. We just prepend 'cd ... && '. +# We preserve trailing '&' if present as the last non-space char. +inject_prefix() { + worktree_path=$1 + command=$2 + + qpath=$(shell_squote "${worktree_path}") + + # Right-trim spaces (portable loop) + trimmed=${command} + while [ "${trimmed% }" != "${trimmed}" ]; do + trimmed=${trimmed% } + done + + case "${trimmed}" in + *"&") + cmd_without_bg=${trimmed%&} + while [ "${cmd_without_bg% }" != "${cmd_without_bg}" ]; do + cmd_without_bg=${cmd_without_bg% } + done + printf '%s\n' "cd '${qpath}' && ${cmd_without_bg} &" + ;; + *) + printf '%s\n' "cd '${qpath}' && ${command}" + ;; + esac +} + +main() { + # Capture the raw command line exactly as provided + original_command="$*" + + debug_log "Processing command: ${original_command}" + + # Fast path: if not in a worktree, pass through unchanged + if ! worktree_path="$(get_worktree_path)"; then + debug_log "Not in worktree, passing through unchanged" + printf '%s\n' "${original_command}" + exit 0 + fi + + if should_skip_command "${original_command}"; then + debug_log "Passing through unchanged" + printf '%s\n' "${original_command}" + else + modified_command="$(inject_prefix "${worktree_path}" "${original_command}")" + debug_log "Modified command: ${modified_command}" + printf '%s\n' "${modified_command}" + fi +} + +main "$@" diff --git a/.claude/rules/github-operations.md b/.claude/rules/github-operations.md index d06447a..50200f0 100644 --- a/.claude/rules/github-operations.md +++ b/.claude/rules/github-operations.md @@ -2,6 +2,41 @@ Standard patterns for GitHub CLI operations across all commands. +## CRITICAL: Repository Protection + +**Before ANY GitHub operation that creates/modifies issues or PRs:** + +```bash +# Check if remote origin is the CCPM template repository +remote_url=$(git remote get-url origin 2>/dev/null || echo "") +if [[ "$remote_url" == *"automazeio/ccpm"* ]] || [[ "$remote_url" == *"automazeio/ccpm.git"* ]]; then + echo "❌ ERROR: You're trying to sync with the CCPM template repository!" + echo "" + echo "This repository (automazeio/ccpm) is a template for others to use." + echo "You should NOT create issues or PRs here." + echo "" + echo "To fix this:" + echo "1. Fork this repository to your own GitHub account" + echo "2. Update your remote origin:" + echo " git remote set-url origin https://github.com/YOUR_USERNAME/YOUR_REPO.git" + echo "" + echo "Or if this is a new project:" + echo "1. Create a new repository on GitHub" + echo "2. Update your remote origin:" + echo " git remote set-url origin https://github.com/YOUR_USERNAME/YOUR_REPO.git" + echo "" + echo "Current remote: $remote_url" + exit 1 +fi +``` + +This check MUST be performed in ALL commands that: +- Create issues (`gh issue create`) +- Edit issues (`gh issue edit`) +- Comment on issues (`gh issue comment`) +- Create PRs (`gh pr create`) +- Any other operation that modifies the GitHub repository + ## Authentication **Don't pre-check authentication.** Just run the command and handle failure: @@ -19,16 +54,19 @@ gh issue view {number} --json state,title,labels,body ### Create Issue ```bash +# ALWAYS check remote origin first! gh issue create --title "{title}" --body-file {file} --label "{labels}" ``` ### Update Issue ```bash +# ALWAYS check remote origin first! gh issue edit {number} --add-label "{label}" --add-assignee @me ``` ### Add Comment ```bash +# ALWAYS check remote origin first! gh issue comment {number} --body-file {file} ``` @@ -41,7 +79,8 @@ If any gh command fails: ## Important Notes +- **ALWAYS** check remote origin before ANY write operation to GitHub - Trust that gh CLI is installed and authenticated - Use --json for structured output when parsing - Keep operations atomic - one gh command per action -- Don't check rate limits preemptively \ No newline at end of file +- Don't check rate limits preemptively diff --git a/.claude/scripts/pm/init.sh b/.claude/scripts/pm/init.sh index 3be92aa..af41a6b 100755 --- a/.claude/scripts/pm/init.sh +++ b/.claude/scripts/pm/init.sh @@ -92,6 +92,19 @@ if git rev-parse --git-dir > /dev/null 2>&1; then if git remote -v | grep -q origin; then remote_url=$(git remote get-url origin) echo " ✅ Remote configured: $remote_url" + + # Check if remote is the CCPM template repository + if [[ "$remote_url" == *"automazeio/ccpm"* ]] || [[ "$remote_url" == *"automazeio/ccpm.git"* ]]; then + echo "" + echo " ⚠️ WARNING: Your remote origin points to the CCPM template repository!" + echo " This means any issues you create will go to the template repo, not your project." + echo "" + echo " To fix this:" + echo " 1. Fork the repository or create your own on GitHub" + echo " 2. Update your remote:" + echo " git remote set-url origin https://github.com/YOUR_USERNAME/YOUR_REPO.git" + echo "" + fi else echo " ⚠️ No remote configured" echo " Add with: git remote add origin " diff --git a/.claude/settings.json.example b/.claude/settings.json.example new file mode 100644 index 0000000..287d771 --- /dev/null +++ b/.claude/settings.json.example @@ -0,0 +1,12 @@ +{ + "hooks": { + "pre-tool-use": { + "Bash": { + "enabled": true, + "script": ".claude/hooks/bash-worktree-fix.sh", + "description": "Automatically prepends worktree path to Bash commands when in a worktree", + "apply_to_subagents": true + } + } + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index af56f61..8f1fe47 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .DS_Store .idea/ +CLAUDE.md diff --git a/README.md b/README.md index bcb6b06..e0a4975 100644 --- a/README.md +++ b/README.md @@ -346,7 +346,7 @@ Focus on building, not managing. Intelligent prioritization, automatic context l Teams using this system report: - **89% less time** lost to context switching – you'll use `/compact` and `/clear` a LOT less - **5-8 parallel tasks** vs 1 previously – editing/testing multiple files at the same time -- **75% reduction** in bug rates – due to the breaking down features into detailed tasks +- **75% reduction** in bug rates – due to the breaking down features into detailed tasks - **Up to 3x faster** feature delivery – based on feature size and complexity ## Example Flow @@ -382,13 +382,26 @@ Teams using this system report: ### Quick Setup (2 minutes) -1. **Clone this repository into your project**: +1. **Install this repository into your project**: + + #### Unix/Linux/macOS + ```bash cd path/to/your/project/ - git clone https://github.com/automazeio/ccpm.git . + curl -sSL https://raw.githubusercontent.com/automazeio/ccpm/main/ccpm.sh | bash + # or: wget -qO- https://raw.githubusercontent.com/automazeio/ccpm/main/ccpm.sh | bash + ``` + + #### Windows (PowerShell) + ```bash + cd path/to/your/project/ + iwr -useb https://raw.githubusercontent.com/automazeio/ccpm/main/ccpm.bat | iex ``` > ⚠️ **IMPORTANT**: If you already have a `.claude` directory, clone this repository to a different directory and copy the contents of the cloned `.claude` directory to your project's `.claude` directory. + See full/other installation options in the [installation guide ›](https://github.com/automazeio/ccpm/tree/main/install) + + 2. **Initialize the PM system**: ```bash /pm:init @@ -460,7 +473,7 @@ Claude Code PM was developed at [Automaze](https://automaze.io) **for developers If Claude Code PM helps your team ship better software: -- ⭐ **[Star this repository](https://github.com/your-username/claude-code-pm)** to show your support +- ⭐ **[Star this repository](https://github.com/automazeio/ccpm)** to show your support - 🐦 **[Follow @aroussi on X](https://x.com/aroussi)** for updates and tips @@ -469,3 +482,9 @@ If Claude Code PM helps your team ship better software: > [!TIP] > **Ship faster with Automaze.** We partner with founders to bring their vision to life, scale their business, and optimize for success. > **[Visit Automaze to book a call with me ›](https://automaze.io)** + +--- + +## Star History + +![Star History Chart](https://api.star-history.com/svg?repos=automazeio/ccpm) diff --git a/install/README.md b/install/README.md new file mode 100644 index 0000000..4680a61 --- /dev/null +++ b/install/README.md @@ -0,0 +1,42 @@ +# Quick Install + +## Unix/Linux/macOS + +```bash +curl -sSL https://raw.githubusercontent.com/automazeio/ccpm/main/ccpm.sh | bash +``` + +Or with wget: + +```bash +wget -qO- https://raw.githubusercontent.com/automazeio/ccpm/main/ccpm.sh | bash +``` + +## Windows (PowerShell) + +```powershell +iwr -useb https://raw.githubusercontent.com/automazeio/ccpm/main/ccpm.bat | iex +``` + +Or download and execute: + +```powershell +curl -o ccpm.bat https://raw.githubusercontent.com/automazeio/ccpm/main/ccpm.bat && ccpm.bat +``` + +## One-liner alternatives + +### Unix/Linux/macOS (direct commands) +```bash +git clone https://github.com/automazeio/ccpm.git . && rm -rf .git +``` + +### Windows (cmd) +```cmd +git clone https://github.com/automazeio/ccpm.git . && rmdir /s /q .git +``` + +### Windows (PowerShell) +```powershell +git clone https://github.com/automazeio/ccpm.git .; Remove-Item -Recurse -Force .git +``` diff --git a/install/ccpm.bat b/install/ccpm.bat new file mode 100644 index 0000000..28a8f79 --- /dev/null +++ b/install/ccpm.bat @@ -0,0 +1,18 @@ +@echo off + +set REPO_URL=https://github.com/automazeio/ccpm.git +set TARGET_DIR=. + +echo Cloning repository from %REPO_URL%... +git clone %REPO_URL% %TARGET_DIR% + +if %ERRORLEVEL% EQU 0 ( + echo Clone successful. Removing .git directory... + rmdir /s /q .git 2>nul + rmdir /s /q install 2>nul + del /q .gitignore 2>nul + echo Git directory removed. Repository is now untracked. +) else ( + echo Error: Failed to clone repository. + exit /b 1 +) diff --git a/install/ccpm.sh b/install/ccpm.sh new file mode 100644 index 0000000..ded501e --- /dev/null +++ b/install/ccpm.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +REPO_URL="https://github.com/automazeio/ccpm.git" +TARGET_DIR="." + +echo "Cloning repository from $REPO_URL..." +git clone "$REPO_URL" "$TARGET_DIR" + +if [ $? -eq 0 ]; then + echo "Clone successful. Removing .git directory..." + rm -rf .git .gitignore install + echo "Git directory removed. Repository is now untracked." +else + echo "Error: Failed to clone repository." + exit 1 +fi