Commit changes, push to GitHub, and open a PR. Includes quality checks (security, patterns, simplification). Use --quick to skip checks.
Install
npx skillscat add llama-farm/llamafarm/commit-push-pr Install via the SkillsCat registry.
Commit, Push & PR Skill
Automates the git workflow of committing changes, pushing to GitHub, and opening a PR with intelligent handling of edge cases.
Required Reading
Before executing, internalize the git workflow standards:
@.claude/rules/git_workflow.md
Key rules:
- Use Conventional Commits format:
type(scope): description - NEVER attribute Claude in commits or PRs (no co-author, no mentions)
- NEVER skip pre-commit hooks (no
--no-verify)
Execution Workflow
Step 1: Assess Git State
Run these commands to understand the current state:
# Detect the default branch (main, master, etc.)
DEFAULT_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@')
# Fallback if symbolic-ref fails (e.g., shallow clone or missing HEAD)
if [ -z "$DEFAULT_BRANCH" ]; then
DEFAULT_BRANCH=$(git remote show origin 2>/dev/null | grep 'HEAD branch' | awk '{print $NF}')
fi
# Final fallback to 'main' if detection fails
DEFAULT_BRANCH=${DEFAULT_BRANCH:-main}
# Get current branch
BRANCH=$(git branch --show-current)
# Check for uncommitted changes
git status --porcelain
# Check for unpushed commits (if branch has upstream)
git log origin/$DEFAULT_BRANCH..HEAD --oneline 2>/dev/null || echo "No upstream or no commits ahead"
# Check if branch has upstream tracking
git rev-parse --abbrev-ref @{upstream} 2>/dev/null || echo "No upstream"Determine the state:
HAS_CHANGES: Are there uncommitted changes (staged, unstaged, or untracked)?HAS_UNPUSHED: Are there commits ahead of origin/$DEFAULT_BRANCH?ON_DEFAULT_BRANCH: Is current branch the default branch ($DEFAULT_BRANCH)?HAS_UPSTREAM: Does the branch track a remote?
Step 2: Handle "Nothing to Do" Case
If !HAS_CHANGES && !HAS_UNPUSHED:
Inform user: "No changes to commit and no unpushed commits. Nothing to do."
Exit gracefully.Step 3: Handle "No Changes But Unpushed Commits" Case
If !HAS_CHANGES && HAS_UNPUSHED:
- Check if PR already exists:
gh pr list --head "$(git branch --show-current)" --json number,url,titleIf PR exists:
- Offer to push updates to the existing PR
- Report the PR URL
If no PR:
- Offer to push and create a new PR
- Proceed to Step 7
Step 4: Branch Management (if HAS_CHANGES)
If on default branch ($DEFAULT_BRANCH):
- Inform user that changes need to go on a feature branch
- Stage changes first to analyze them:
git add -A
git diff --staged --statGenerate a conventional commit message based on the changes (see Step 5)
Derive branch name from commit message:
feat(cli): add project list→feat-cli-add-project-listfix: resolve memory leak→fix-resolve-memory-leak- Rules: lowercase, replace spaces/special chars with hyphens, max 50 chars
Create and checkout the new branch:
git checkout -b <branch-name>If already on feature branch:
- Continue with the existing branch
- Check if PR exists for context
Step 5: Stage Changes and Generate Commit Message
- Stage all changes:
git add -A- Analyze the staged changes:
git diff --staged --stat
git diff --stagedGenerate a conventional commit message based on:
- Files changed (infer scope from directory)
- Nature of changes (feat/fix/refactor/docs/test/chore)
- Summarize the "why" not just the "what"
Present the commit message to the user. Example format:
Proposed commit message:
feat(cli): add project listing command
Adds a new 'lf project list' command that displays all projects
in the current workspace with their status.
Do you want to use this message, modify it, or provide your own?Step 5.5: Quality Check
Skip if: --quick flag was passed.
Run quality checks on staged changes before committing.
1. Auto-fix trivial issues (no prompt needed)
Search for and remove debug statements:
# Find files with debug statements
git diff --staged --name-only | xargs grep -l -E "(console\.(log|debug|info)|debugger|print\()" 2>/dev/nullFor each file found:
- Remove
console.log(...),console.debug(...),console.info(...)statements - Remove
debugger;statements - Remove
print(...)statements (Python) - Re-stage the file after fixes
Report: "Auto-fixed: Removed N debug statements from M files"
2. Check for issues requiring attention
Scan staged diff for:
| Issue | Severity | Action |
|---|---|---|
| Hardcoded secrets (API keys, passwords) | BLOCK | Cannot auto-fix - user must remove |
Command injection (shell=True, os.system) |
BLOCK | Cannot auto-fix - user must refactor |
| Empty catch/except blocks | PROPOSE | Suggest adding error logging |
| Duplicate code patterns | PROPOSE | Suggest extraction |
| Unused imports | PROPOSE | Suggest removal |
| TODO/FIXME comments | WARN | Note but allow proceed |
3. Handle blocking issues
If BLOCK issues found:
- List each issue with file:line reference
- Stop the workflow
- User must fix manually and re-run
4. Handle proposable fixes
For each PROPOSE issue:
- Show: file, line, problem, suggested fix
- Ask: "Apply this fix? (y/n/all/skip)"
- If approved: apply edit, re-stage
- If skipped: continue without fix
5. Handle warnings
For WARN issues:
- Display summary
- Continue without blocking
Step 6: Create the Commit
Create the commit with the approved message:
git commit -m "$(cat <<'EOF'
type(scope): short description
Optional longer description explaining the change.
EOF
)"Important:
- Use HEREDOC for multi-line messages
- Never add co-author or Claude attribution
- Let pre-commit hooks run (never use
--no-verify)
If commit fails due to pre-commit hook:
- Report the failure to the user
- Show the hook output
- Do NOT retry with
--no-verify - Ask user how to proceed (fix issues or abort)
Step 7: Push to Remote
- Check if branch has upstream:
git rev-parse --abbrev-ref @{upstream} 2>/dev/null- If no upstream, push with
-u:
git push -u origin $(git branch --show-current)- If has upstream, regular push:
git pushIf push fails due to conflicts:
- Inform user about the conflict
- Suggest:
git pull --rebase origin $DEFAULT_BRANCHorgit merge origin/$DEFAULT_BRANCH - Do NOT force push
Step 8: Create or Report PR
- Check if PR already exists:
gh pr list --head "$(git branch --show-current)" --json number,url,titleIf PR exists:
- Report: "Changes pushed to existing PR: "
- Show PR title and number
If no PR exists:
- Generate PR title from commit message (first line)
- Generate PR body with summary of changes
- Create PR:
gh pr create --title "type(scope): description" --body "$(cat <<'EOF'
## Summary
- Brief description of changes
## Changes
- List of key changes made
## Test Plan
- How to verify these changes work
EOF
)"- Report the new PR URL to the user
Branch Name Generation
Convert commit message to valid branch name:
| Input | Output |
|---|---|
feat(cli): add project list command |
feat-cli-add-project-list-command |
fix: resolve memory leak in cache |
fix-resolve-memory-leak-in-cache |
refactor(server): simplify auth flow |
refactor-server-simplify-auth-flow |
Algorithm:
- Take the commit message (first line only)
- Lowercase everything
- Remove the colon after type/scope
- Replace
(and)with- - Replace spaces and special characters with
- - Collapse multiple hyphens to single hyphen
- Trim to max 50 characters at word boundary
- Remove trailing hyphens
Error Handling
| Error | Action |
|---|---|
| Pre-commit hook fails | Show output, ask user to fix, do NOT bypass |
| Push rejected (conflicts) | Suggest rebase/merge, do NOT force push |
| PR creation fails | Show error, suggest manual creation |
| Not a git repo | Inform user, exit |
| gh CLI not installed | Inform user how to install |
| Not authenticated to GitHub | Suggest gh auth login |
Output Format
On success, report:
Committed: feat(cli): add project list command
Branch: feat-cli-add-project-list-command
Pushed to: origin/feat-cli-add-project-list-command
PR: https://github.com/owner/repo/pull/123Notes for the Agent
- Never mention Claude - No co-author lines, no "generated by Claude" in PR descriptions
- Respect hooks - Pre-commit hooks exist for a reason, never skip them
- Be informative - Tell the user what's happening at each step
- Handle errors gracefully - Don't leave the repo in a broken state
- Ask when uncertain - If the commit message isn't clear, ask the user
- Keep it simple - One commit per invocation, clear linear workflow