diff --git a/.claude/commands/create-pr.md b/.claude/commands/create-pr.md
new file mode 100644
index 0000000..12d3d03
--- /dev/null
+++ b/.claude/commands/create-pr.md
@@ -0,0 +1,93 @@
+Create a GitHub pull request for the current branch, writing the title and description from the actual work done in this session — not reconstructed from the diff.
+
+## Why this command exists
+
+The previous flow outsourced PR-description authoring to a GitHub Action that only saw the diff and commit messages. It could not know _why_ the changes were made, so it frequently described things that weren't true. Those inaccurate descriptions then fed `@claude` reviews, compounding the bad information. This command fixes that at the root: **you author the description here, where the full context of what was done and why is available.**
+
+This is the RoboSystems Python client — a type-safe, async-ready Python SDK generated against the RoboSystems API. Tooling is driven by `just`, not npm.
+
+## Instructions
+
+### 1. Preflight
+
+Run these checks before touching anything:
+
+```bash
+# Current and target branches
+CURRENT=$(git branch --show-current)
+TARGET=${1:-main} # override target via the first argument
+```
+
+- **Never PR from the default branch.** If `CURRENT` is `main` (or `master`/`staging`), stop and tell the user to switch to a feature branch first.
+- **Source ≠ target.** If `CURRENT == TARGET`, stop.
+- **Uncommitted changes.** Run `git status --porcelain`. If there are uncommitted/staged changes, surface them and ask whether to commit them (respecting the repo's commit rules — never on `main`, no `git add -A`, stage files by name) or proceed without them. The PR description must reflect committed state.
+- **Existing PR.** Check `gh pr list --head "$CURRENT" --base "$TARGET" --json url,number`. If a PR already exists, do **not** create a duplicate — offer to update its title/body with `gh pr edit` instead.
+- **Push the branch.** `gh pr create` requires the branch on the remote. Ensure it's pushed: `git push -u origin "$CURRENT"` (the user invoking `/create-pr` is the explicit, in-the-moment request that authorizes pushing _this feature branch_ — this is the one push allowed without a separate ask; never push `main`).
+
+### 2. Gather the real change context
+
+This is the whole point — ground the description in what actually happened:
+
+- **Primary source: this session.** Use what was actually changed and why from the conversation context. This is the information the old GHA workflow never had.
+- **Corroborate against the branch:**
+ ```bash
+ git log --oneline "$TARGET".."$CURRENT" # commits on this branch
+ git diff --stat "$TARGET"..."$CURRENT" # files + churn
+ git diff "$TARGET"..."$CURRENT" # full diff — read it, don't guess
+ ```
+- **Hard rule — no confabulation.** Every claim in the description must be supported by the diff. If you didn't touch the auth client, don't write "auth improvements." If a behavior isn't in the diff, don't mention it. When the session context and the diff disagree, the diff wins and you investigate the discrepancy.
+- **Generated code.** Much of `robosystems_client/` is generated from the OpenAPI spec via `just generate-sdk`. If a change is a regeneration, say so plainly rather than narrating individual model edits as if hand-written.
+
+### 3. Compose the PR
+
+- **Type** — derive from the branch prefix (`feature/` → feat, `bugfix/`/`fix/` → fix, `hotfix/` → fix, `chore/` → chore, `refactor/` → refactor, `release/` → release). Default to `feat` if unprefixed.
+- **Title** — concise (~50–72 chars), conventional-commit style, e.g. `feat(clients): add streaming query helper`. Match the style in `git log`.
+- **Body** — markdown, only sections that apply:
+ - **Summary** — 1–3 sentences: what this PR does and why.
+ - **Changes** — bullets grouped by area/file/module, describing real edits.
+ - **Testing** — state truthfully what was run. If `just test-all` (or a subset like `just test` / `just lint` / `just typecheck`) was run this session, say so and give the result. If nothing was run, say "Not run" — never claim passing tests that weren't executed.
+ - **Notes / Follow-ups** — optional: deferred items, risks, related issues, SDK-regeneration implications.
+- **Attribution** — attribute to the user only. Do **not** add a "Generated with Claude Code" footer or a `Co-Authored-By: Claude` trailer (per `CLAUDE.local.md`). Include such a line only if the user explicitly asks.
+
+### 4. Create the PR
+
+Write the body to a temp file to avoid shell-escaping problems, then:
+
+```bash
+gh pr create \
+ --base "$TARGET" \
+ --head "$CURRENT" \
+ --title "
" \
+ --body-file /tmp/pr-body.md
+```
+
+Print the resulting PR URL.
+
+### 5. Optional Claude review
+
+Only if the user explicitly asks (e.g. passes `review` / `--review` in arguments), request a review:
+
+```bash
+gh pr comment --body "@claude please review this PR"
+```
+
+Otherwise leave it off — the description is now accurate, and the user can run `/pr-review` locally (full context) or `@claude` manually when ready. Do not request review by default.
+
+## Output
+
+After creating the PR, report:
+
+1. The PR URL.
+2. A one-line summary of the title.
+3. Target ← source branches.
+4. Whether a Claude review was requested.
+
+## Arguments
+
+`$ARGUMENTS` may contain:
+
+- A target branch (default `main`).
+- `review` / `--review` to auto-request a `@claude` review.
+- Freeform guidance on what to emphasize in the description.
+
+$ARGUMENTS
diff --git a/.github/workflows/create-pr.yml b/.github/workflows/create-pr.yml
deleted file mode 100644
index 7f34fa8..0000000
--- a/.github/workflows/create-pr.yml
+++ /dev/null
@@ -1,387 +0,0 @@
-name: Create Claude PR
-
-on:
- workflow_dispatch:
- inputs:
- source_branch:
- description: "Source branch to create PR from (defaults to current branch)"
- required: false
- type: string
- target_branch:
- description: "Target branch to merge into"
- required: true
- type: choice
- options:
- - main
- default: main
- pr_type:
- description: "Type of PR"
- required: true
- type: choice
- options:
- - release
- - feature
- - bugfix
- - hotfix
- default: release
- claude_review:
- description: "Request Claude review automatically"
- required: false
- type: boolean
- default: true
-
-jobs:
- create-pr:
- runs-on: ubuntu-latest
- timeout-minutes: 10
- env:
- # ACTIONS_TOKEN (PAT) preferred - PRs created with github.token won't trigger CI workflows
- GH_TOKEN: ${{ secrets.ACTIONS_TOKEN || github.token }}
- steps:
- - name: Check token configuration
- run: |
- if [ -z "${{ secrets.ACTIONS_TOKEN }}" ]; then
- echo "::warning::ACTIONS_TOKEN not set - using github.token as fallback"
- echo ""
- echo "⚠️ PRs created with github.token have limitations:"
- echo " - Won't trigger on:pull_request workflows (CI won't run automatically)"
- echo " - May be blocked by branch protection rules"
- echo ""
- echo "To enable full functionality, set ACTIONS_TOKEN secret:"
- echo " gh secret set ACTIONS_TOKEN"
- else
- echo "✅ Using ACTIONS_TOKEN for full PR functionality"
- fi
-
- - name: Checkout
- uses: actions/checkout@v4
- with:
- # ACTIONS_TOKEN preferred for pushing to protected branches
- token: ${{ secrets.ACTIONS_TOKEN || github.token }}
- fetch-depth: 0
-
- - name: Determine source branch
- id: source-branch
- run: |
- if [ -n "${{ inputs.source_branch }}" ]; then
- SOURCE_BRANCH="${{ inputs.source_branch }}"
- echo "Using specified source branch: $SOURCE_BRANCH"
- git checkout "$SOURCE_BRANCH"
- else
- SOURCE_BRANCH=$(git branch --show-current)
- echo "Using current branch: $SOURCE_BRANCH"
- fi
- echo "source_branch=$SOURCE_BRANCH" >> $GITHUB_OUTPUT
-
- - name: Validate branches
- id: validate
- run: |
- SOURCE_BRANCH="${{ steps.source-branch.outputs.source_branch }}"
- TARGET_BRANCH="${{ inputs.target_branch }}"
-
- echo "Source branch: $SOURCE_BRANCH"
- echo "Target branch: $TARGET_BRANCH"
-
- # Check if source branch exists
- if ! git show-ref --verify --quiet refs/heads/$SOURCE_BRANCH && ! git show-ref --verify --quiet refs/remotes/origin/$SOURCE_BRANCH; then
- echo "❌ Source branch $SOURCE_BRANCH does not exist"
- exit 1
- fi
-
- # Check if target branch exists
- if ! git show-ref --verify --quiet refs/heads/$TARGET_BRANCH && ! git show-ref --verify --quiet refs/remotes/origin/$TARGET_BRANCH; then
- echo "❌ Target branch $TARGET_BRANCH does not exist"
- exit 1
- fi
-
- # Check if branches are different
- if [ "$SOURCE_BRANCH" = "$TARGET_BRANCH" ]; then
- echo "❌ Source and target branches cannot be the same"
- exit 1
- fi
-
- echo "✅ Branch validation passed"
-
- - name: Analyze changes with Claude
- id: analyze
- run: |
- SOURCE_BRANCH="${{ steps.source-branch.outputs.source_branch }}"
- TARGET_BRANCH="${{ inputs.target_branch }}"
- PR_TYPE="${{ inputs.pr_type }}"
-
- # Get commit range for analysis
- git fetch origin $TARGET_BRANCH
- COMMIT_RANGE="origin/$TARGET_BRANCH...$SOURCE_BRANCH"
-
- # Get diff stats (limit output to prevent memory issues)
- DIFF_STATS=$(git diff --stat --no-color $COMMIT_RANGE | head -50 | sed 's/`//g') # Limit to 50 lines
- FILES_CHANGED=$(git diff --name-only $COMMIT_RANGE | wc -l)
- COMMITS_COUNT=$(git rev-list --count $COMMIT_RANGE)
-
- # Get commit messages (limit to recent commits)
- COMMIT_MESSAGES=$(git log --oneline --no-color $COMMIT_RANGE | head -20 | sed 's/`//g') # Limit to 20 commits
-
- # Get detailed changes (limit to prevent memory issues)
- DETAILED_CHANGES=$(git diff $COMMIT_RANGE --name-status --no-color | head -100 | sed 's/`//g') # Limit to 100 files
-
- # Create analysis prompt for Claude
- cat << 'EOF' > /tmp/pr_analysis_prompt.txt
- I need you to analyze the following git changes and create a comprehensive PR title and description.
-
- **Context:**
- - Source Branch: ${SOURCE_BRANCH}
- - Target Branch: ${TARGET_BRANCH}
- - PR Type: ${PR_TYPE}
- - Files Changed: ${FILES_CHANGED}
- - Commits: ${COMMITS_COUNT}
-
- **Commit Messages:**
- ${COMMIT_MESSAGES}
-
- **Diff Statistics:**
- ${DIFF_STATS}
-
- **Detailed Changes:**
- ${DETAILED_CHANGES}
-
- Please provide:
- 1. A concise, descriptive PR title (50-72 characters)
- 2. A comprehensive PR description with:
- - Summary of changes
- - Key accomplishments
- - Breaking changes (if any)
- - Testing notes
- - Infrastructure considerations (avoid mentioning specific script paths or commands)
-
- Format the response as:
- TITLE: [your title here]
-
- DESCRIPTION:
- [your description here]
- EOF
-
- # Create the final prompt by writing directly to a file (avoiding envsubst issues)
- cat > /tmp/pr_analysis_prompt_final.txt << PROMPT_EOF
- I need you to analyze the following git changes and create a comprehensive PR title and description.
-
- **Context:**
- - Source Branch: $SOURCE_BRANCH
- - Target Branch: $TARGET_BRANCH
- - PR Type: $PR_TYPE
- - Files Changed: $FILES_CHANGED
- - Commits: $COMMITS_COUNT
-
- **Commit Messages:**
- $COMMIT_MESSAGES
-
- **Diff Statistics:**
- $DIFF_STATS
-
- **Detailed Changes:**
- $DETAILED_CHANGES
-
- Please provide:
- 1. A concise, descriptive PR title (50-72 characters)
- 2. A comprehensive PR description with:
- - Summary of changes
- - Key accomplishments
- - Breaking changes (if any)
- - Testing notes
- - Infrastructure considerations (avoid mentioning specific script paths or commands)
-
- Format the response as:
- TITLE: [your title here]
-
- DESCRIPTION:
- [your description here]
- PROMPT_EOF
- mv /tmp/pr_analysis_prompt_final.txt /tmp/pr_analysis_prompt.txt
-
- echo "analysis_prompt_file=/tmp/pr_analysis_prompt.txt" >> $GITHUB_OUTPUT
- echo "commit_range=$COMMIT_RANGE" >> $GITHUB_OUTPUT
- echo "files_changed=$FILES_CHANGED" >> $GITHUB_OUTPUT
- echo "commits_count=$COMMITS_COUNT" >> $GITHUB_OUTPUT
-
- - name: Call Claude API
- id: claude
- run: |
- # Call Claude API with the analysis prompt
- PROMPT=$(cat /tmp/pr_analysis_prompt.txt)
-
- # Create a proper JSON payload using jq to handle escaping
- PAYLOAD=$(jq -n \
- --arg model "${{ vars.CLAUDE_MODEL || 'claude-sonnet-4-6' }}" \
- --arg content "$PROMPT" \
- '{
- "model": $model,
- "max_tokens": 4000,
- "messages": [
- {
- "role": "user",
- "content": $content
- }
- ]
- }')
-
- # Retry logic with exponential backoff
- MAX_RETRIES=3
- RETRY_COUNT=0
- RETRY_DELAY=5
-
- while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
- RESPONSE=$(curl -s -X POST "https://api.anthropic.com/v1/messages" \
- -H "Content-Type: application/json" \
- -H "x-api-key: ${{ secrets.ANTHROPIC_API_KEY }}" \
- -H "anthropic-version: 2023-06-01" \
- -d "$PAYLOAD")
-
- # Check for API errors
- if echo "$RESPONSE" | jq -e '.error' > /dev/null; then
- ERROR_TYPE=$(echo "$RESPONSE" | jq -r '.error.type // "unknown"')
- ERROR_MSG=$(echo "$RESPONSE" | jq -r '.error.message // "Unknown error"')
-
- # Check if it's a rate limit or overload error
- if [[ "$ERROR_TYPE" == "overloaded_error" ]] || [[ "$ERROR_TYPE" == "rate_limit_error" ]] || [[ "$ERROR_MSG" == *"Overloaded"* ]]; then
- RETRY_COUNT=$((RETRY_COUNT + 1))
- if [ $RETRY_COUNT -lt $MAX_RETRIES ]; then
- echo "⚠️ Claude API overloaded (attempt $RETRY_COUNT/$MAX_RETRIES). Retrying in ${RETRY_DELAY}s..."
- sleep $RETRY_DELAY
- RETRY_DELAY=$((RETRY_DELAY * 2)) # Exponential backoff
- continue
- else
- echo "❌ Claude API error after $MAX_RETRIES attempts: $ERROR_MSG"
- echo "Using fallback PR description..."
- # Set a fallback description
- PR_TITLE="PR: ${{ steps.source-branch.outputs.source_branch }} → ${{ inputs.target_branch }}"
- PR_DESCRIPTION="Automated PR from ${{ steps.source-branch.outputs.source_branch }} to ${{ inputs.target_branch }}"$'\n\n'"**Type:** ${{ inputs.pr_type }}"$'\n'"**Files Changed:** ${{ steps.analyze.outputs.files_changed }}"$'\n'"**Commits:** ${{ steps.analyze.outputs.commits_count }}"$'\n\n'"Please review the changes in the Files tab."
- break
- fi
- else
- echo "❌ Claude API error: $ERROR_MSG"
- exit 1
- fi
- else
- # Success - break out of retry loop
- break
- fi
- done
-
- # Only process Claude response if we didn't use fallback
- if [ -z "$PR_TITLE" ]; then
- # Check for successful response
- if echo "$RESPONSE" | jq -e '.content[0].text' > /dev/null; then
- # Extract title and description from Claude's response
- CLAUDE_OUTPUT=$(echo "$RESPONSE" | jq -r '.content[0].text')
-
- # Parse the title and description
- PR_TITLE=$(echo "$CLAUDE_OUTPUT" | grep "^TITLE:" | sed 's/^TITLE: //')
- PR_DESCRIPTION=$(echo "$CLAUDE_OUTPUT" | sed -n '/^DESCRIPTION:/,$ p' | sed '1d')
-
- # Validate that Claude returned meaningful content
- if [ -z "$PR_TITLE" ] || [ -z "$PR_DESCRIPTION" ]; then
- echo "⚠️ Claude returned empty title or description, using fallback"
- PR_TITLE="PR: ${{ steps.source-branch.outputs.source_branch }} → ${{ inputs.target_branch }}"
- PR_DESCRIPTION="Automated PR from ${{ steps.source-branch.outputs.source_branch }} to ${{ inputs.target_branch }}"
- PR_DESCRIPTION="${PR_DESCRIPTION}"$'\n\n'"**Type:** ${{ inputs.pr_type }}"
- PR_DESCRIPTION="${PR_DESCRIPTION}"$'\n'"**Files Changed:** ${{ steps.analyze.outputs.files_changed }}"
- PR_DESCRIPTION="${PR_DESCRIPTION}"$'\n'"**Commits:** ${{ steps.analyze.outputs.commits_count }}"
- PR_DESCRIPTION="${PR_DESCRIPTION}"$'\n\n'"Please review the changes in the Files tab."
- fi
- else
- echo "⚠️ Invalid Claude response format, using fallback"
- PR_TITLE="PR: ${{ steps.source-branch.outputs.source_branch }} → ${{ inputs.target_branch }}"
- PR_DESCRIPTION="Automated PR from ${{ steps.source-branch.outputs.source_branch }} to ${{ inputs.target_branch }}"
- PR_DESCRIPTION="${PR_DESCRIPTION}"$'\n\n'"**Type:** ${{ inputs.pr_type }}"
- PR_DESCRIPTION="${PR_DESCRIPTION}"$'\n\n'"Please review the changes in the Files tab."
- fi
- fi
-
- # Save to outputs (escape for JSON)
- {
- echo "pr_title<> $GITHUB_OUTPUT
-
- {
- echo "pr_description<> $GITHUB_OUTPUT
-
- echo "✅ Claude analysis completed"
-
- - name: Create Pull Request
- id: create-pr
- env:
- CLAUDE_PR_TITLE: ${{ steps.claude.outputs.pr_title }}
- CLAUDE_PR_DESCRIPTION: ${{ steps.claude.outputs.pr_description }}
- run: |
- SOURCE_BRANCH="${{ steps.source-branch.outputs.source_branch }}"
- TARGET_BRANCH="${{ inputs.target_branch }}"
-
- # Use environment variables to safely handle Claude's output
- PR_TITLE="$CLAUDE_PR_TITLE"
- PR_DESCRIPTION="$CLAUDE_PR_DESCRIPTION"
-
- # Check if PR already exists
- EXISTING_PR=$(gh pr list --head "$SOURCE_BRANCH" --base "$TARGET_BRANCH" --json url --jq '.[0].url' 2>/dev/null || echo "")
-
- if [ -n "$EXISTING_PR" ] && [ "$EXISTING_PR" != "null" ]; then
- echo "✅ PR already exists: $EXISTING_PR"
- echo "pr_url=$EXISTING_PR" >> $GITHUB_OUTPUT
- PR_URL="$EXISTING_PR"
- else
- # Create PR description with Claude analysis + footer
- cat > /tmp/pr_description.txt << EOF
- $PR_DESCRIPTION
-
- ---
- 🤖 Generated with [Claude Code](https://claude.ai/code)
-
- **Branch Info:**
- - Source: \`$SOURCE_BRANCH\`
- - Target: \`$TARGET_BRANCH\`
- - Type: ${{ inputs.pr_type }}
-
- Co-Authored-By: Claude
- EOF
-
- FINAL_PR_DESCRIPTION=$(cat /tmp/pr_description.txt)
-
- # Create the PR
- PR_URL=$(gh pr create \
- --title "$PR_TITLE" \
- --body "$FINAL_PR_DESCRIPTION" \
- --base "$TARGET_BRANCH" \
- --head "$SOURCE_BRANCH")
-
- echo "pr_url=$PR_URL" >> $GITHUB_OUTPUT
- echo "✅ Pull Request created: $PR_URL"
- fi
-
- - name: Request Claude review
- if: ${{ inputs.claude_review }}
- run: |
- PR_NUMBER=$(echo "${{ steps.create-pr.outputs.pr_url }}" | sed 's/.*pull\///')
-
- gh pr comment "$PR_NUMBER" --body "@claude please review this PR"
- echo "✅ Claude review requested"
-
- - name: Create summary
- run: |
- SOURCE_BRANCH="${{ steps.source-branch.outputs.source_branch }}"
- TARGET_BRANCH="${{ inputs.target_branch }}"
- PR_URL="${{ steps.create-pr.outputs.pr_url }}"
-
- echo "## 🚀 Claude-Powered PR Created" >> $GITHUB_STEP_SUMMARY
- echo "" >> $GITHUB_STEP_SUMMARY
- echo "**PR URL:** [$PR_URL]($PR_URL)" >> $GITHUB_STEP_SUMMARY
- echo "**Source:** \`$SOURCE_BRANCH\`" >> $GITHUB_STEP_SUMMARY
- echo "**Target:** \`$TARGET_BRANCH\`" >> $GITHUB_STEP_SUMMARY
- echo "**Type:** ${{ inputs.pr_type }}" >> $GITHUB_STEP_SUMMARY
- echo "" >> $GITHUB_STEP_SUMMARY
- echo "### PR Details" >> $GITHUB_STEP_SUMMARY
- echo "**Title:** ${{ steps.claude.outputs.pr_title }}" >> $GITHUB_STEP_SUMMARY
- echo "" >> $GITHUB_STEP_SUMMARY
- echo "**Commits:** ${{ steps.analyze.outputs.commit_range }}" >> $GITHUB_STEP_SUMMARY
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index ce241c7..1ddfd14 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -73,12 +73,6 @@
"command": "just create-feature ${input:branchType} ${input:branchName} ${input:baseBranch} ${input:updateDependencies}",
"problemMatcher": []
},
- {
- "label": "Create PR",
- "type": "shell",
- "command": "just create-pr ${input:targetBranch} ${input:claudeReview}",
- "problemMatcher": []
- },
{
"label": "Create Release",
"type": "shell",
@@ -127,19 +121,6 @@
"default": "yes",
"options": ["yes", "no"]
},
- {
- "id": "targetBranch",
- "type": "promptString",
- "description": "Choose target branch:",
- "default": "main"
- },
- {
- "id": "claudeReview",
- "type": "pickString",
- "description": "Request Claude review automatically:",
- "default": "true",
- "options": ["true", "false"]
- },
{
"id": "apiUrl",
"type": "promptString",
diff --git a/bin/create-feature.sh b/bin/create-feature.sh
index 1f62153..870c02e 100755
--- a/bin/create-feature.sh
+++ b/bin/create-feature.sh
@@ -93,7 +93,7 @@ echo "📝 Next steps:"
echo " 1. Make your changes and commit them"
echo " 2. Push your changes: git push"
echo " 3. Create a PR: gh pr create --base $BASE_BRANCH --title \"Your PR title\" --body \"Your PR description\""
-echo " or use: just create-pr $BASE_BRANCH $BRANCH_TYPE"
+echo " or in a Claude Code session: /create-pr"
# Check if we had stashed changes and auto-apply them
if git stash list | grep -q "Auto-stash before creating branch $FULL_BRANCH"; then
diff --git a/bin/create-pr.sh b/bin/create-pr.sh
deleted file mode 100755
index fb05aa4..0000000
--- a/bin/create-pr.sh
+++ /dev/null
@@ -1,145 +0,0 @@
-#!/bin/bash
-set -e
-
-# Create PR script using GitHub Actions
-# Analyzes current branch changes and creates a comprehensive PR with Claude
-# Usage: ./bin/tools/create-pr.sh [target_branch] [claude_review]
-
-# Default values
-TARGET_BRANCH=${1:-main}
-CLAUDE_REVIEW=${2:-true}
-
-# Get current branch
-CURRENT_BRANCH=$(git branch --show-current)
-
-# Validate current branch is not target branch
-if [ "$CURRENT_BRANCH" = "$TARGET_BRANCH" ]; then
- echo "❌ Cannot create PR: you're currently on the target branch ($TARGET_BRANCH)"
- echo "Switch to your feature/release branch first: git checkout "
- exit 1
-fi
-
-# Validate target branch (only main is allowed as target)
-if [[ "$TARGET_BRANCH" != "main" ]]; then
- echo "❌ Invalid target branch: $TARGET_BRANCH. Only 'main' is allowed as target."
- exit 1
-fi
-
-# Determine PR type from branch prefix
-if [[ "$CURRENT_BRANCH" == release/* ]]; then
- PR_TYPE="release"
-elif [[ "$CURRENT_BRANCH" == feature/* ]]; then
- PR_TYPE="feature"
-elif [[ "$CURRENT_BRANCH" == bugfix/* ]]; then
- PR_TYPE="bugfix"
-elif [[ "$CURRENT_BRANCH" == hotfix/* ]]; then
- PR_TYPE="hotfix"
-else
- # Default to feature for any other branch names
- PR_TYPE="feature"
- echo "⚠️ Could not determine PR type from branch name '$CURRENT_BRANCH', defaulting to 'feature'"
-fi
-
-# Validate Claude review parameter
-if [[ "$CLAUDE_REVIEW" != "true" && "$CLAUDE_REVIEW" != "false" ]]; then
- echo "❌ Invalid claude_review value: $CLAUDE_REVIEW. Use 'true' or 'false'."
- exit 1
-fi
-
-echo "🤖 Creating Claude-powered PR..."
-echo "📋 Details:"
-echo " Source Branch: $CURRENT_BRANCH"
-echo " Target Branch: $TARGET_BRANCH"
-echo " PR Type: $PR_TYPE"
-echo " Claude Review: $CLAUDE_REVIEW"
-echo ""
-
-# Check for uncommitted changes
-if ! git diff --quiet || ! git diff --cached --quiet; then
- echo "⚠️ You have uncommitted changes. Please commit or stash them first."
- echo ""
- echo "Uncommitted files:"
- git status --porcelain
- exit 1
-fi
-
-# Push current branch to remote if needed
-echo "📤 Ensuring current branch is pushed to remote..."
-if ! git show-ref --verify --quiet refs/remotes/origin/$CURRENT_BRANCH; then
- echo "Branch $CURRENT_BRANCH doesn't exist on remote. Pushing..."
- git push -u origin $CURRENT_BRANCH
-else
- echo "Pushing latest changes..."
- git push origin $CURRENT_BRANCH
-fi
-
-echo ""
-echo "🚀 Triggering Claude analysis workflow..."
-
-# Trigger the GitHub Actions workflow
-gh workflow run create-pr.yml \
- --field source_branch="$CURRENT_BRANCH" \
- --field target_branch="$TARGET_BRANCH" \
- --field pr_type="$PR_TYPE" \
- --field claude_review="$CLAUDE_REVIEW"
-
-echo "⏳ Waiting for Claude to analyze changes and create PR..."
-
-# Wait for workflow to complete and find the PR
-MAX_ATTEMPTS=30 # 5 minutes with 10-second intervals
-ATTEMPT=1
-
-while [ $ATTEMPT -le $MAX_ATTEMPTS ]; do
- echo "Attempt $ATTEMPT/$MAX_ATTEMPTS: Checking for created PR..."
-
- # Check if the workflow run failed
- LATEST_RUN_STATUS=$(gh run list --workflow=create-pr.yml --limit=1 --json status --jq '.[0].status' 2>/dev/null || echo "")
- if [ "$LATEST_RUN_STATUS" = "failure" ] || [ "$LATEST_RUN_STATUS" = "cancelled" ]; then
- echo "❌ GitHub Actions workflow failed or was cancelled"
- echo "Check the workflow run details:"
- echo " gh run list --workflow=create-pr.yml"
- echo " gh run view --workflow=create-pr.yml"
- echo ""
- echo "You can create the PR manually:"
- echo " gh pr create --base $TARGET_BRANCH --head $CURRENT_BRANCH"
- exit 1
- fi
-
- # Check if PR exists from current branch to target
- PR_URL=$(gh pr list --head "$CURRENT_BRANCH" --base "$TARGET_BRANCH" --json url --jq '.[0].url' 2>/dev/null || echo "")
-
- if [ -n "$PR_URL" ] && [ "$PR_URL" != "null" ]; then
- echo "✅ PR created successfully!"
- echo "🔗 PR URL: $PR_URL"
- echo ""
- echo "🎉 Claude has analyzed your changes and created a comprehensive PR"
- echo "📝 Review the PR description and make any necessary adjustments"
-
- # Try to open PR in browser
- if command -v open >/dev/null 2>&1; then
- echo "🌐 Opening PR in browser..."
- open "$PR_URL"
- elif command -v xdg-open >/dev/null 2>&1; then
- echo "🌐 Opening PR in browser..."
- xdg-open "$PR_URL"
- else
- echo "💡 Open the PR manually: $PR_URL"
- fi
-
- exit 0
- fi
-
- if [ $ATTEMPT -eq $MAX_ATTEMPTS ]; then
- echo "❌ Timeout: PR was not created after 5 minutes"
- echo "Check the GitHub Actions workflow status:"
- echo " gh run list --workflow=create-pr.yml"
- echo ""
- echo "You can also create the PR manually:"
- echo " gh pr create --base $TARGET_BRANCH --head $CURRENT_BRANCH"
- exit 1
- fi
-
- echo "PR not yet created, waiting 10 seconds..."
- sleep 10
- ATTEMPT=$((ATTEMPT + 1))
-done
diff --git a/justfile b/justfile
index ea1dcfc..7e9014f 100644
--- a/justfile
+++ b/justfile
@@ -59,10 +59,6 @@ create-feature branch_type="feature" branch_name="" base_branch="main" update="y
create-release type="patch":
bin/create-release.sh {{type}}
-# Create PR
-create-pr target_branch="main" claude_review="true":
- bin/create-pr.sh {{target_branch}} {{claude_review}}
-
# Clean up development artifacts
clean:
rm -rf .pytest_cache