--- name: pulling-before-work version: 1.0.0 description: > Pulls the current branch from origin once at session start and on explicit re-sync requests. Use when CLAUDE.md contains the trigger line "pull remote before work", or when the user says "sync", "resync", "pull", "обнови репо", "git pull please", or close variants asking to refresh from the remote. Runs `git pull --ff-only` — never auto-merges or rebases. Stays silent in non-git folders. Prints one informational line and exits when there is no origin remote, no upstream tracking, the working tree is dirty, or HEAD is detached. Does not stash, commit, or push. Activated by `project-bootstrap` v1.4.0+ via the canonical CLAUDE.md template. --- # pulling-before-work > Pull from `origin` once when work starts. Don't auto-merge. Don't trample dirty work-trees. Don't ask twice in the same session unless asked. ## When this runs **At session start** — once, when the skill is activated by the `pull remote before work` line in `CLAUDE.md`. The cycle below runs immediately. **On explicit re-sync** — when the user says any of: `sync`, `resync`, `pull`, `обнови репо`, `pull please`, `git pull`, `подтяни`, `pull from origin`. Re-runs the full cycle. There is no per-session counter; the user is always allowed to ask. **Never** before each commit, before each tool call, on every message, or in any other implicit cadence. Mode-3 ("start + on-demand") was the explicit design choice — see `.wiki/concepts/pulling-before-work-design.md`. ## The pull cycle Run these checks in order. Print at most one line of chat output per run. ### 1. Inside a git work-tree? ```bash git rev-parse --is-inside-work-tree 2>/dev/null ``` If the command fails or prints anything other than `true` → **exit silently, no chat output.** This is the not-a-git-repo case; the skill must not be noisy in random folders. ### 2. Has an `origin` remote? ```bash git remote get-url origin 2>/dev/null ``` If the command fails (no such remote) → print one line and exit: ``` no origin remote — skip pull ``` ### 3. Is the working tree clean? ```bash git status --porcelain ``` If the output is non-empty → print one line and exit: ``` working tree dirty — skipping pull. commit/stash, потом скажи "sync" ``` Never stash automatically. Stash-pop conflicts are exactly the friction this skill exists to remove. ### 4. Is HEAD attached? ```bash git symbolic-ref -q HEAD ``` If the command fails (empty output, exit 1) → detached HEAD. Print: ``` detached HEAD — skip pull ``` ### 5. Does the current branch have an upstream? ```bash git rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null ``` Capture the upstream name (e.g. `origin/master`). If the command fails → no upstream tracking. Print: ``` no upstream tracking for — skip pull ``` (Where `` is `git rev-parse --abbrev-ref HEAD`.) ### 6. Pull, fast-forward only ```bash git pull --ff-only ``` (No args — uses the configured upstream captured above.) Classify by exit code and stdout: | Result | Print | |---|---| | Already up to date | `✅ already up to date with ` | | Fast-forward, N commits | `✅ pulled N commits from ` | | Non-fast-forward / diverged (exit non-zero with "diverged" or "non-fast-forward" in output) | `⚠️ diverged from — resolve manually (git pull --rebase or merge); skill never auto-merges/rebases` | ### Out of scope The skill never: - commits, stashes, or pushes - recurses into submodules - pulls from non-`origin` remotes - pulls on detached HEAD - runs auto-merge or auto-rebase - runs more than once per session unless the user asks ## Recovery hints If the skill skipped because of a dirty tree: ```powershell # Windows / PowerShell git status # see what's dirty git add . ; git commit -m "wip" # then ask the agent: "sync" ``` ```bash # Linux / macOS git status git add . && git commit -m "wip" # then say "sync" ``` If the skill reported `diverged`: ```bash # Option A: rebase your local commits on top of origin git pull --rebase # Option B: explicit merge (creates a merge commit) git pull --no-ff ``` The skill stays out of these decisions on purpose — both options have valid use cases and the user owns the choice. ## Why this exists Stale local branches are a silent footgun: edits land on top of yesterday's `origin`, the divergence shows up at push time, and by then there's a chunk of work to rebase or merge on the wrong base. One pull at start covers the common case; an explicit re-sync trigger handles long sessions where someone pushed mid-flight. Full design rationale (mode choice, dirty-tree skip vs stash, `--ff-only` vs auto-merge, the upstream-check) lives in `.wiki/concepts/pulling-before-work-design.md`.