From sd0x-dev-flow
Executes git push to remote after branch safety checks and explicit user approval, then monitors CI status via gh CLI. Use for 'push', 'push-ci' requests.
npx claudepluginhub sd0xdev/sd0x-dev-flow --plugin sd0x-dev-flowThis skill is limited to using the following tools:
Push to remote with user approval, then monitor CI run until completion.
Safeguards git push operations: detects protected branches, enforces force-push confirmations, runs pre-push quality gates (lint, test, type-check), emits structured receipts, and suggests PR automation. Use when pushing commits, force pushing, or to protected/feature branches.
Stages changes, creates conventional commit messages with Claude footer, and pushes to remote securely via script. Blocks force pushes and secrets.
Pushes local Git commits to remote repositories, handling branch tracking, upstream setup, safe push patterns like force-with-lease, and verification. Useful after local commits when syncing to remote.
Share bugs, ideas, or general feedback.
Push to remote with user approval, then monitor CI run until completion.
⚠️ This skill is one of two authorized paths for Claude to execute `git push`.
⚠️ The other is /epic-merge (force-push --force-with-lease for stacked PR chains, per-iteration AskUserQuestion gate).
⚠️ All other skills and rules MUST output push commands only (not execute).
⚠️ Push REQUIRES explicit user approval via AskUserQuestion — no exceptions.
| Rule | This Skill | /epic-merge | All Other Skills |
|---|---|---|---|
git push | Execute (after user approval) | Forbidden (uses --force-with-lease only) | Forbidden (output only) |
git push --force | Forbidden | Forbidden | Forbidden |
git push --force-with-lease | Forbidden | Execute (after per-iteration AskUserQuestion) | Forbidden |
| Push to protected branches (main/master/develop/release/*) | Warn + pre-approval via AskUserQuestion (terminal hook is final gate) | N/A (only pushes to PR head branches) | Forbidden |
| Layer | Mechanism | Scope | Reliability |
|---|---|---|---|
| L1: git pre-push hook | pre-push-gate.sh reads /dev/tty for terminal confirmation | Protected branches + non-fast-forward detection | Immune to Claude Code permission caching |
| L2: AskUserQuestion | In-session advisory prompt before push | All pushes | May be auto-approved by session caching (advisory only) |
| L3: git-workflow rules | Claude forbidden from raw git push | All contexts | Behavioral enforcement |
Primary gate: pre-push-gate.sh (install via /install-scripts). This script runs as a git pre-push hook and prompts the developer directly via /dev/tty, which is immune to Claude Code's permission caching. AskUserQuestion remains as an advisory UX layer but is not the authorization gate — the git hook is.
Why AskUserQuestion alone is insufficient: Session permission caching can auto-approve AskUserQuestion calls in long-running sessions, especially with -c continue mode. See GitHub Issue #15400.
sequenceDiagram
participant C as Claude
participant U as User
participant GH as GitHub
C->>C: Phase 0: Preflight
alt Protected branch detected
C->>U: ⚠️ Warning + ask pre-approval
U->>C: Continue / Abort
end
C->>U: Phase 1: Show push plan + ask approval
U->>C: Approve / Reject
alt Approved
C->>GH: Execute git push
C->>C: Phase 2: Execute git push
C->>GH: Phase 3: Delegate to /watch-ci
GH-->>C: CI verdict
else Rejected
C->>U: Abort (no push)
end
Run all checks. Hard-abort on infrastructure failures; warn-and-confirm on protected branches.
# 1. Current branch
BRANCH=$(git rev-parse --abbrev-ref HEAD)
# 2. Protected branch detection
# If main, master, develop, or release/* → warn + AskUserQuestion pre-approval
# (do NOT hard-abort; let user decide)
# 3. Remote exists
git ls-remote --exit-code origin >/dev/null 2>&1
# 4. Working tree status
git status --short
# 5. Commits ahead of remote
git rev-list --count origin/$BRANCH..HEAD 2>/dev/null || echo "new branch"
# 6. Local HEAD SHA (for CI run matching later)
HEAD_SHA=$(git rev-parse HEAD)
| Check | Pass | Fail |
|---|---|---|
| Branch is not protected | Continue | Warn + AskUserQuestion (see below) |
| Remote exists | Continue | Abort: "No remote 'origin' configured" |
| Has commits ahead | Continue | Abort: "Nothing to push (0 commits ahead)" |
Protected branch pre-approval flow (advisory — terminal hook remains final gate):
When branch is main, master, develop, or release/*:
<branch>" — proceed to Phase 1/dev/tty as the final authorization gate.Present push summary and ask user for explicit approval using AskUserQuestion:
## Push Plan
- Branch: `<branch>`
- Remote: `origin`
- Commits: <N> ahead
- HEAD: `<sha>`
Command to execute: `git push origin <branch>`
Gate: Use AskUserQuestion with options:
If user rejects → stop immediately. Do NOT retry or persuade.
After user approval:
Command assembly (deterministic):
# Build and execute push command (ONLY after explicit approval)
# ⚠️ Always unset ALLOW_PUSH_PROTECTED to prevent env inheritance bypassing the hook.
# Only set ALLOW_FORCE_WITH_LEASE when --force-with-lease is explicitly requested.
if [[ "$FORCE_WITH_LEASE" == "true" ]]; then
if [[ "$SET_UPSTREAM" == "true" ]]; then
ALLOW_PUSH_PROTECTED= ALLOW_FORCE_WITH_LEASE=1 git push --force-with-lease -u origin "$BRANCH"
else
ALLOW_PUSH_PROTECTED= ALLOW_FORCE_WITH_LEASE=1 git push --force-with-lease origin "$BRANCH"
fi
else
if [[ "$SET_UPSTREAM" == "true" ]]; then
ALLOW_PUSH_PROTECTED= ALLOW_FORCE_WITH_LEASE= git push -u origin "$BRANCH"
else
ALLOW_PUSH_PROTECTED= ALLOW_FORCE_WITH_LEASE= git push origin "$BRANCH"
fi
fi
# If push fails (non-zero exit) → stop immediately, report error, do NOT proceed to CI
--set-upstream auto-detect: If git rev-parse --abbrev-ref --symbolic-full-name @{u} fails (no upstream), add -u automatically.
After successful push, invoke /watch-ci to monitor CI runs:
--sha <HEAD_SHA> and --branch <BRANCH> from Phase 0--timeout from arguments (default 10)/watch-ci runs in Monitor streaming mode (default) — Claude receives progress notifications and reports verdict on completion/watch-ci handles run discovery, quick-check, monitoring, retry logic, and verdict reportingThis delegation keeps push authorization logic separate from read-only CI monitoring. See @skills/watch-ci/SKILL.md for CI monitoring details.
| Argument | Description | Default |
|---|---|---|
--timeout <min> | CI watch timeout in minutes | 10 |
--force-with-lease | Use --force-with-lease instead of regular push | off |
--set-upstream | Add -u flag (first push of new branch) | auto-detect |
--force is NOT supported. Force push is always forbidden.
- Executing git push WITHOUT prior user approval via AskUserQuestion
- Suggesting or executing git push --force (ever)
- Pushing to protected branches WITHOUT explicit user pre-approval via AskUserQuestion
- Setting ALLOW_PUSH_PROTECTED=1 (this skill must NEVER set this env var; it is reserved for manual developer use only)
- Auto-triggering this skill (disable-model-invocation: true)
- Skipping preflight checks
- Skipping `/watch-ci` delegation after successful push
/watch-ci with correct SHA + branchInput: /push-ci
Phase 0: Preflight — branch feat/auth, 3 commits ahead, remote OK
Phase 1: Show plan → user approves
Phase 2: git push origin feat/auth
Phase 3: /watch-ci --sha <HEAD> --branch feat/auth (Monitor streaming — receive progress notifications)
Input: /push-ci --timeout 15
Phase 0-1: Same as above
Phase 2: git push
Phase 3: /watch-ci --sha <HEAD> --branch <branch> --timeout 15
Input: /push-ci --force-with-lease
Phase 0: Preflight (warns on protected branches)
Phase 1: Show plan with --force-with-lease → user approves
Phase 2: git push --force-with-lease origin feat/rebase-cleanup
Phase 3: CI monitoring
Input: /push-ci (on main branch)
Phase 0: Preflight — ⚠️ "main is a protected branch" → AskUserQuestion pre-approval
User: Continue → proceed
Phase 1: Show plan → user approves push
Phase 2: git push origin main
Phase 3: /watch-ci (Monitor streaming — receive progress notifications)