| name | commit |
| description | Commit staged changes, push the branch, and create or update a PR with a conventional-commit-formatted title. Use after completing a feature or fix. |
Commit, Push & PR
This skill handles the full workflow: verify quality gates → commit → push → create or update a PR.
Step 1: Quality Gates
Run all checks before committing. All must pass:
make build
make test
make lint
make fmt-check
Stop if any check fails. Fix the issue, then re-run.
Step 2: Create a Feature Branch
Always work on a feature branch — never commit directly to main.
Check the current branch:
git branch --show-current
If already on main (or any protected branch), create and switch to a feature branch before staging anything. Derive the branch name from the commit type and a short summary of the change (kebab-case, no special characters):
git checkout -b type/short-description
If already on a feature branch, continue with that branch — do not create another one.
Step 3: Review Changes
git status && git diff --staged && git diff
Understand what changed so you can write an accurate commit message and PR title.
Step 4: Stage & Commit
Stage relevant files (prefer specific paths over git add -A to avoid accidentally including secrets or build artifacts):
git add <files...>
Write a conventional commit message:
type(scope): summary in imperative mood
Changelog-eligible types (pick the right one — it determines what appears in the changelog):
| Type | Changelog section | Version bump |
|---|
feat | Added | minor |
fix | Fixed | patch |
perf | Performance | patch |
docs | Documentation | none |
test | Tests | none |
refactor, chore, ci, build, style | (not included) | none |
For breaking changes use feat!: or fix!:, or add a BREAKING CHANGE: footer → triggers a major version bump.
Scopes are lowercase, comma-separated if multiple: feat(check,bootstrap): ...
git commit -m "type(scope): summary"
Step 5: Push
git push -u origin HEAD
Step 6: Create or Update the PR
Check if a PR already exists for this branch:
gh pr view --json number,title,url 2>/dev/null
If no PR exists — create one:
The PR title must follow conventional commit format — it becomes the squashed commit message on main and is what drives the changelog. Match it to the overall intent of the branch, not just the latest commit.
gh pr create \
--title "type(scope): summary" \
--body "$(cat <<'EOF'
## Summary
<brief description of the changes and motivation>
## Test plan
- [ ] `make build` passes
- [ ] `make test` passes
- [ ] `make lint` has zero warnings
- [ ] `make fmt-check` applied
## Checklist
- [ ] Tests added/updated
- [ ] Documentation updated (if user-facing behavior changed):
- [ ] `README.md`
- [ ] `man/oss-spec.md`
- [ ] `docs/agent/help-agent.txt`
- [ ] `agent_help::COMMANDS_TABLE` / `COMMAND_SPECS`
- [ ] Commit messages follow conventional commit style
EOF
)"
If a PR already exists — update it:
Re-evaluate the PR title and description to reflect the combined scope of all commits on the branch, then update:
gh pr edit \
--title "type(scope): updated summary" \
--body "$(cat <<'EOF'
## Summary
<updated description covering all changes>
## Test plan
- [ ] `make build` passes
- [ ] `make test` passes
- [ ] `make lint` has zero warnings
- [ ] `make fmt-check` applied
## Checklist
- [ ] Tests added/updated
- [ ] Documentation updated (if user-facing behavior changed):
- [ ] `README.md`
- [ ] `man/oss-spec.md`
- [ ] `docs/agent/help-agent.txt`
- [ ] `agent_help::COMMANDS_TABLE` / `COMMAND_SPECS`
- [ ] Commit messages follow conventional commit style
EOF
)"
Key Reminders
- PR title = squashed commit on main = changelog entry. Choose the type and summary carefully.
- The individual commits within the branch don't appear in the changelog — only the PR title does.
- If the branch touches multiple scopes, use comma-separated scopes:
feat(check,bootstrap): ...
- Never skip hooks (
--no-verify) — fix the underlying issue instead.