Autonomous Agents Agentic Workflow
Pull Workspace Repos — Autonomous Agents Agentic Workflow
Fetch every repo in a workspace and fast-forward the clean, current ones — never resets, cleans or switches branches
sidebutton install agents A safe, repo-only refresh that brings one workspace's checkouts up to date with upstream without touching local work. It walks every git repository directly inside the selected workspace (its entry path) and fetches each with prune; a checkout whose working tree is clean and whose current branch fast-forwards to its upstream is pulled (git pull --ff-only). Everything else is left exactly as it is — a dirty tree, a branch that is ahead of or has diverged from its upstream, a branch with no upstream at all. It never resets, never cleans untracked files, never stashes and never switches branches.
Run it whenever a workspace's checkouts may be stale — right before dispatching work, or as the portal's one-click "Run a job" for a freshly signed-in agent. It is safe on a workspace with unpushed work: local commits (a session's "Saved (local)" commit after a rejected push included) and uncommitted edits survive untouched and are reported instead of discarded. It is idempotent — an already-current repo resolves to no change. The report has one line per repo: folder · branch · pulled N / already current / left: dirty / left: diverged (N local commits) / left: no upstream / left: worktree.
Discarding local work is not this job's business. The hard reset and untracked-file clean it used to run belong to agent_self_update — dispatch that one to put disposable checkouts back on their remote default branch. Since KAN-205 that job leaves a dirty, off-branch, diverged or worktree-hosting repo alone as well, so neither of these two will discard local work for you; agent_wipe_workspace is the only one that still does. agent_wipe_workspace goes further still: it deletes every folder in the workspace, and the repos come back only when the portal re-applies the workspace's projects.
Steps
- 1. Open a terminal
- title
- Agent: Pull Workspace Repos
- cwd
- {{entry_path}}
terminal.open - 2. Run a terminal command
- cmd
- |
terminal.run
Workflow definition
schema_version: 1
id: agent_pull_repos
title: "Pull Workspace Repos"
description: "Fetch every repo in a workspace and fast-forward the clean, current ones — never resets, cleans or switches branches"
overview: |
A safe, repo-only refresh that brings one workspace's checkouts up to date with upstream without touching local work. It walks every git repository directly inside the selected workspace (its entry path) and fetches each with prune; a checkout whose working tree is clean and whose current branch fast-forwards to its upstream is pulled (`git pull --ff-only`). Everything else is left exactly as it is — a dirty tree, a branch that is ahead of or has diverged from its upstream, a branch with no upstream at all. It never resets, never cleans untracked files, never stashes and never switches branches.
Run it whenever a workspace's checkouts may be stale — right before dispatching work, or as the portal's one-click "Run a job" for a freshly signed-in agent. It is safe on a workspace with unpushed work: local commits (a session's "Saved (local)" commit after a rejected push included) and uncommitted edits survive untouched and are reported instead of discarded. It is idempotent — an already-current repo resolves to no change. The report has one line per repo: folder · branch · pulled N / already current / left: dirty / left: diverged (N local commits) / left: no upstream / left: worktree.
Discarding local work is not this job's business. The hard reset and untracked-file clean it used to run belong to `agent_self_update` — dispatch that one to put disposable checkouts back on their remote default branch. Since KAN-205 that job leaves a dirty, off-branch, diverged or worktree-hosting repo alone as well, so neither of these two will discard local work for you; `agent_wipe_workspace` is the only one that still does. `agent_wipe_workspace` goes further still: it deletes every folder in the workspace, and the repos come back only when the portal re-applies the workspace's projects.
category:
level: pipeline
domain: engineering
metadata:
agent: true
role: ops
params:
agentic_app:
type: string
default: "cc"
description: "Agent-app slug selecting the per-run env file ~/.agent-env.d/<slug> (AAP-C); 'cc'/subscription clears provider vars"
entry_path:
type: string
default: "~/workspace"
description: "Workspace directory to sync"
steps:
- type: terminal.open
title: "Agent: Pull Workspace Repos"
cwd: "{{entry_path}}"
- type: terminal.run
cmd: |
source ~/.agent-env
# AAP-C (SCRUM-1506) + AAP-17 (SCRUM-1653): clear EVERY provider var an agent-app can deliver so
# none hijacks/poisons a subscription run. A stray global ANTHROPIC_MODEL / ANTHROPIC_SMALL_FAST_MODEL
# needs no CLAUDE_CODE_USE_* flag, so the old ${!CLAUDE_CODE_USE_@} glob never caught it — it survived
# into the run and 404-ed aux/small-fast calls against api.anthropic.com. This explicit list mirrors
# AGENT_APP_ENV_KEYS 1:1 (the-assistant website/src/lib/cloud/agent-app-env.ts — the single source of
# truth; a parity test in each repo guards the two from drifting). Explicit over a glob: the union has
# non-ANTHROPIC_ members (AWS_REGION, AWS_PROFILE, CLOUD_ML_REGION, CLAUDE_CODE_MAX_OUTPUT_TOKENS) and
# a ${!AWS_@} glob would over-clear unrelated creds. Then source the per-run app env by slug when it
# exists; no file => subscription/default. base/19-secrets stages ~/.agent-env.d/<slug>.
unset \
ANTHROPIC_API_KEY ANTHROPIC_BASE_URL ANTHROPIC_AUTH_TOKEN CCR_CONFIG_B64 \
CLAUDE_CODE_USE_BEDROCK AWS_REGION AWS_PROFILE ANTHROPIC_MODEL \
ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION ANTHROPIC_SMALL_FAST_MODEL CLAUDE_CODE_MAX_OUTPUT_TOKENS \
CLAUDE_CODE_USE_VERTEX CLOUD_ML_REGION ANTHROPIC_VERTEX_PROJECT_ID ANTHROPIC_VERTEX_BASE_URL \
CLAUDE_CODE_USE_FOUNDRY ANTHROPIC_FOUNDRY_RESOURCE ANTHROPIC_FOUNDRY_BASE_URL \
ANTHROPIC_DEFAULT_OPUS_MODEL ANTHROPIC_DEFAULT_SONNET_MODEL ANTHROPIC_DEFAULT_HAIKU_MODEL
if [ -f "$HOME/.agent-env.d/{{agentic_app}}" ]; then
source "$HOME/.agent-env.d/{{agentic_app}}"
fi
claude --dangerously-skip-permissions "$(cat <<'SB_PROMPT'
the current directory is your workspace. bring its checkouts up to date without touching any local work. for each immediate child folder that is a git repository: run `git fetch --prune`; then, only when the working tree is clean (nothing staged, modified or untracked) and the current branch has an upstream it can fast-forward to, run `git pull --ff-only`; otherwise leave the repo exactly as it is. never reset, never clean, never stash, never switch branches, never commit, and never touch a folder that is not a git repository. report one line per repo — folder · branch · outcome — where the outcome is exactly one of: "pulled N" (N commits fast-forwarded), "already current", "left: dirty", "left: diverged (N local commits)" (the branch is ahead of or has diverged from its upstream; N = its local commits), "left: no upstream" (no tracking branch, or a detached HEAD), or "left: fetch failed (<error>)" if the fetch itself errored — never force a failed fetch into one of the other outcomes. continue with the remaining repos either way.
WORKTREE RULE — before evaluating a folder, check whether it is a linked git worktree (its `.git` is a file, not a directory). If it is, leave it alone and report `left: worktree` rather than treating it as an independent repo: its branch is checked out from another folder's repository, so pulling it is neither a repo refresh nor safe to reason about here. A repo that HOSTS worktrees (`git worktree list` prints more than one entry) is still eligible for `git pull --ff-only` under the clean-and-fast-forwardable test above — fast-forwarding a clean checkout destroys nothing — but name it in the report as `pulled N (hosts worktree)` so the operator can see which checkouts moved under a worktree. These two EXTEND the closed outcome list above rather than contradicting it: the full vocabulary is that list plus `left: worktree`, with `pulled N (hosts worktree)` as a labelled variant of `pulled N` — no other outcome string exists.
UNATTENDED RUN — this is a dispatched job: nobody is watching this terminal and nobody will answer, so never call AskUserQuestion and never end your turn by putting a question to the operator. Apply the policy stated above and carry it out as written, including where carrying it out is destructive — the call to run this job was made when it was dispatched, and it is not yours to re-take. Where that policy leaves a genuine choice, make it yourself and keep going; only where it is genuinely SILENT, prefer the option that does not destroy work nobody can recreate. Say what you decided and what you skipped and why — but INSIDE the report this prompt already specifies: wherever a report shape, a token vocabulary or a last-line verdict is stated above, that format still binds exactly as written, and this clause adds no section, no token and nothing after the last line. Questions the deliverable is MEANT to contain are content, not an unanswered prompt. Asking does not pause the job either: an unanswered prompt is auto-answered from the option ordering once the unattended wait budget lapses (KAN-204), so asking only burns ~15 minutes of the run and hands a real decision to a default.
SB_PROMPT
)"