npx claudepluginhub sd0xdev/sd0x-dev-flow --plugin sd0x-dev-flowWant just this skill?
Add to a custom plugin, then install with one command.
Push to remote and monitor CI. Validates branch safety, executes git push WITH explicit user approval, then monitors CI run status via gh CLI. Use when: user says 'push', 'push and watch CI', 'ship it', 'push-ci'. Not for: committing (use /smart-commit), creating PRs (use /create-pr), merging (use /merge-prep).
This skill is limited to using the following tools:
Push & CI Monitor
Push to remote with user approval, then monitor CI run until completion.
Authorization
⚠️ This skill is the ONLY authorized path for Claude to execute `git push`.
⚠️ All other skills and rules MUST output push commands only (not execute).
⚠️ Push REQUIRES explicit user approval via AskUserQuestion — no exceptions.
| Rule | This Skill | All Other Skills |
|---|---|---|
git push | Execute (after user approval) | Forbidden (output only) |
git push --force | Forbidden | Forbidden |
| Push to protected branches (main/master/develop/release/*) | Warn + pre-approval via AskUserQuestion (terminal hook is final gate) | Forbidden |
Defense in Depth: Push Safety
| 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.
Workflow
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
Phase 0: Preflight
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/*:
- Show warning with branch name and commit count
- Use AskUserQuestion with options:
- "Continue — push to
<branch>" — proceed to Phase 1 - "Abort" — stop immediately
- "Continue — push to
- If user aborts → stop. If user continues → proceed to Phase 1 (push approval asked separately). Note: the git pre-push hook will still require terminal confirmation via
/dev/ttyas the final authorization gate.
Phase 1: Push Plan + User Approval
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:
- "Approve push" — proceed to execute
- "Abort" — stop, do not push
If user rejects → stop immediately. Do NOT retry or persuade.
Phase 2: Execute Push
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.
Phase 3: Monitor CI (delegation)
After successful push, invoke /watch-ci to monitor CI runs:
- Pass
--sha <HEAD_SHA>and--branch <BRANCH>from Phase 0 - Pass
--timeoutfrom arguments (default 10) - Pass
--foregroundto ensure blocking execution (push-ci needs the verdict before completing) /watch-cihandles run discovery, monitoring, retry logic, and verdict reporting
This delegation keeps push authorization logic separate from read-only CI monitoring. See @skills/watch-ci/SKILL.md for CI monitoring details.
Arguments
| 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.
Prohibited
- 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
Verification
- Preflight passed (branch + remote + commits)
- User approved push via AskUserQuestion
- Push executed successfully
- CI monitoring delegated to
/watch-ciwith correct SHA + branch
Examples
Input: /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 → ✅ CI passed
Input: /push-ci --timeout 15
Phase 0-1: Same as above
Phase 2: git push
Phase 3: /watch-ci --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 → gh run watch
Phase 3: ✅ CI passed