claude/skills/commit-push/SKILL.md
This skill should be used when the user asks to "commit and push", "push my changes", or wants to commit, push, and respond to PR comments.
npx skillsauth add tbroadley/dotfiles commit-pushInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Commit changes, run local validation, push to remote, open a draft PR if needed, and ensure CI passes.
Before running validation, clean up your changes:
Before committing, run all local checks:
Linting, Typechecking, and Formatting:
ruff check, eslint, golangci-lint)basedpyright, mypy, tsc --noEmit)ruff format --check, prettier --check, gofmt)Tests:
@pytest.mark.slow (search for mark.slow in test files)pytest -m "not slow" for fast tests, then run affected slow testspytest, npm test, go test ./...uv pip show pytest-xdist), use -n auto for parallel execution:
pytest -n auto -m "not slow" # fast tests in parallel
pytest -n auto path/to/slow_test1.py path/to/slow_test2.py # affected slow tests in parallel
If this is a DVC-tracked repository (has .dvc files or dvc.yaml):
dvc repro to reproduce any affected pipelinesdvc push to push data artifacts to remote storagecheck-dvc CI failuresFixing check-dvc CI failures:
dvc status --remote to see which files are missingdvc push to upload missing files to the remote.dvc files if they changedIf this is a Pivot-tracked repository (has .pvt files or pipeline.py):
pivot run to execute any outdated pipeline stagespivot push to push outputs to S3.pvt or .pivot/stages/*.lock filescheck-pivot CI failuresFixing check-pivot CI failures:
pivot status to see which stages need to runpivot run to execute outdated stages (or pivot run stage_name@variant for specific stages)pivot push to upload outputs to S3.pvt or .pivot/stages/*.lock filesOnce local validation passes:
git status and git diff to see changesgit log --oneline -3 to match commit message stylegit addgit pushDetermine if you're pushing directly to the main branch:
current_branch=$(git branch --show-current)
main_branch=$(git remote show origin | grep 'HEAD branch' | cut -d: -f2 | xargs)
if [ "$current_branch" = "$main_branch" ]; then
# Pushing directly to main - skip PR creation, go to step 10
echo "On main branch, skipping PR workflow"
fi
If on main/master: Skip steps 6-9 and go directly to step 10 (Wait for CI on Direct Push).
If on a feature branch: Continue with step 6.
Before creating a PR, determine the correct base branch:
# Get the main/master branch name
main_branch=$(git remote show origin | grep 'HEAD branch' | cut -d: -f2 | xargs)
# Find the merge-base with main
merge_base=$(git merge-base HEAD origin/$main_branch)
# Check if there's another branch between current branch and main
# This finds branches that contain the merge-base but are not main
intermediate_branch=$(git branch -r --contains $merge_base | grep -v "origin/$main_branch" | grep -v "origin/HEAD" | head -1 | xargs)
# If an intermediate branch exists and is an ancestor of HEAD, use it as base
if [ -n "$intermediate_branch" ]; then
base_branch=${intermediate_branch#origin/}
else
base_branch=$main_branch
fi
Use $base_branch as the PR base instead of always using main/master.
Check if the current branch has an open PR:
gh pr view --json number,url,state,isDraft 2>/dev/null
If no PR exists:
gh pr create --draft --base $base_branch --title "..." --body "..."
gh pr edit --add-assignee tbroadley
OKR-):
# List available OKR labels
gh label list --search "OKR-"
# Add the appropriate label using the API (gh pr edit --add-label can fail due to deprecated Projects classic)
gh api repos/{owner}/{repo}/issues/{pr_number}/labels -f "labels[]=okr-..."
If PR already exists:
# Review all commits on the branch vs base
git log origin/$base_branch..HEAD --oneline
git diff origin/$base_branch..HEAD --stat
# Update the PR title and body via the API
gh api repos/{owner}/{repo}/pulls/{pr_number} -X PATCH \
-f title="<concise title reflecting all branch changes>" \
-f body="$(cat <<'EOF'
## Summary
<1-3 bullet points covering all changes on the branch>
## Test plan
<how the changes were validated>
EOF
)"
First, check if the repo has GitHub Actions workflows:
# Check for workflow files
if ! ls .github/workflows/*.yml .github/workflows/*.yaml 2>/dev/null | head -1 > /dev/null; then
echo "No GitHub Actions workflows found, skipping CI wait"
# Skip to step 9
fi
If no workflows exist, skip waiting for CI and proceed to step 9.
Before waiting for CI, check for merge conflicts:
Merge conflicts prevent CI from running. Check immediately after pushing:
gh pr view --json mergeable,mergeStateStatus
mergeable is false or mergeStateStatus is DIRTY, there are merge conflictsmergeable is UNKNOWN, wait a few seconds and check again (GitHub is still computing)If merge conflicts exist, resolve them before waiting for CI (see "If CI cannot run" below).
If no conflicts, monitor CI status:
gh pr checks --watch
If CI cannot run (e.g., merge conflict):
gh pr view --json mergeable,mergeStateStatusgit fetch origin $base_branch
git rebase origin/$base_branch
# Resolve conflicts
git add .
git rebase --continue
git push --force-with-leaseIf CI fails:
gh pr checksgh run view <run_id> --log-failedIMPORTANT: Never leave top-level comments on the PR (via gh pr comment or the issues comments API). Only reply directly within review comment threads using the replies API. Top-level comments like "Addressed review feedback" clutter the PR.
If there are existing PR review comments, check if pushed changes address them.
Fetch review comments:
gh api repos/{owner}/{repo}/pulls/{pr_number}/comments --paginate
For each unresolved comment that was addressed:
Leave a reply:
gh api repos/{owner}/{repo}/pulls/{pr_number}/comments/{comment_id}/replies \
-f body="<agent-name>: <explanation of how this was addressed>"
Resolve the thread:
gh api graphql -f query='
mutation {
resolveReviewThread(input: {threadId: "<thread_id>"}) {
thread { isResolved }
}
}
'
To get thread IDs:
gh api graphql -f query='
query {
repository(owner: "{owner}", name: "{repo}") {
pullRequest(number: {pr_number}) {
reviewThreads(first: 100) {
nodes {
id
isResolved
comments(first: 1) {
nodes {
id
databaseId
body
}
}
}
}
}
}
}
'
Re-request review: After addressing all comments from a reviewer, request their re-review:
gh pr edit --add-reviewer <reviewer-username>
To find reviewers who left comments:
gh api repos/{owner}/{repo}/pulls/{pr_number}/reviews --jq '.[].user.login' | sort -u
First, check if the repo has GitHub Actions workflows:
# Check for workflow files
if ! ls .github/workflows/*.yml .github/workflows/*.yaml 2>/dev/null | head -1 > /dev/null; then
echo "No GitHub Actions workflows found, skipping CI wait"
# Task complete - no CI to wait for
fi
If no workflows exist, the task is complete.
If workflows exist, monitor CI using the workflow run:
# Watch the CI run for the latest commit
gh run watch
If CI fails:
gh run view --log-failedgh pr edit often fails with "Projects (classic) deprecation" errors. Use the API directly instead:
# Edit PR body
gh api repos/{owner}/{repo}/pulls/{number} -X PATCH -f body="..."
# Add reviewer
gh api repos/{owner}/{repo}/pulls/{number}/requested_reviewers -X POST -f "reviewers[]=username"
# Add label
gh api repos/{owner}/{repo}/issues/{number}/labels -f "labels[]=label-name"
# Add assignee
gh api repos/{owner}/{repo}/issues/{number}/assignees -f "assignees[]=username"
tools
Add words to the Wispr Flow dictionary. Use when the user wants to add a word, phrase, or snippet to Wispr Flow for voice dictation.
documentation
Upload images to a GitHub PR description or comment using a shared gist as image hosting. Use when the user wants to add plots, screenshots, or other images to a PR.
testing
Manage tasks, projects, and productivity in Todoist. View tasks, add new items, check completed work, and organize projects.
data-ai
Use when working with stacked diffs (branch B based on branch A, which is based on main).