Skill

push-ci

Install
1
Install the plugin
$
npx claudepluginhub sd0xdev/sd0x-dev-flow --plugin sd0x-dev-flow

Want just this skill?

Add to a custom plugin, then install with one command.

Description

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).

Tool Access

This skill is limited to using the following tools:

Bash(git:*)Bash(gh:*)Bash(bash:*)ReadGrepGlobAskUserQuestion
Skill Content

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.
RuleThis SkillAll Other Skills
git pushExecute (after user approval)Forbidden (output only)
git push --forceForbiddenForbidden
Push to protected branches (main/master/develop/release/*)Warn + pre-approval via AskUserQuestion (terminal hook is final gate)Forbidden

Defense in Depth: Push Safety

LayerMechanismScopeReliability
L1: git pre-push hookpre-push-gate.sh reads /dev/tty for terminal confirmationProtected branches + non-fast-forward detectionImmune to Claude Code permission caching
L2: AskUserQuestionIn-session advisory prompt before pushAll pushesMay be auto-approved by session caching (advisory only)
L3: git-workflow rulesClaude forbidden from raw git pushAll contextsBehavioral 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)
CheckPassFail
Branch is not protectedContinueWarn + AskUserQuestion (see below)
Remote existsContinueAbort: "No remote 'origin' configured"
Has commits aheadContinueAbort: "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/*:

  1. Show warning with branch name and commit count
  2. Use AskUserQuestion with options:
    • "Continue — push to <branch>" — proceed to Phase 1
    • "Abort" — stop immediately
  3. 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/tty as 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 --timeout from arguments (default 10)
  • Pass --foreground to ensure blocking execution (push-ci needs the verdict before completing)
  • /watch-ci handles 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

ArgumentDescriptionDefault
--timeout <min>CI watch timeout in minutes10
--force-with-leaseUse --force-with-lease instead of regular pushoff
--set-upstreamAdd -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-ci with 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
Stats
Stars90
Forks12
Last CommitMar 19, 2026
Actions

Similar Skills