| name | workflows-run |
| description | Run an SDLC delegated workflow via Archon. Wraps the archon CLI with project-aware defaults. |
| disable-model-invocation | false |
| argument-hint | <workflow-name> [arguments] |
Run SDLC Workflow
Execute a named SDLC workflow via the Archon CLI.
Arguments
- First argument: workflow name (e.g.,
sdlc-parallel-review)
- Remaining arguments: passed through to Archon as workflow arguments
Steps
1. Verify Archon is installed and on PATH
The upstream installer places archon at ~/.bun/bin/archon, which is
not on the default macOS PATH. Distinguish between truly missing and
"installed but not discoverable":
if command -v archon >/dev/null 2>&1; then
:
elif [ -x "$HOME/.bun/bin/archon" ]; then
echo "Archon is installed at ~/.bun/bin/archon but that directory"
echo "is not on your PATH. For this session, run:"
echo ""
echo " export PATH=\"\$HOME/.bun/bin:\$PATH\""
echo ""
echo "For a permanent fix (recommended):"
echo " echo 'export PATH=\"\$HOME/.bun/bin:\$PATH\"' >> ~/.zshrc"
echo " # then open a new terminal"
echo ""
echo "Or re-run /sdlc-workflows:workflows-setup --health-check to"
echo "diagnose."
exit 1
else
echo "Archon is not installed. Run /sdlc-workflows:workflows-setup first."
exit 1
fi
Do NOT silently fall back to $HOME/.bun/bin/archon — that hides the
real problem (PATH misconfiguration) and the user will hit it again
the next time they open a shell. Fix the environment, not the
symptom.
2. Verify workflow exists
Run archon workflow list 2>/dev/null and check if the requested workflow name appears.
If not found:
Workflow '{name}' not found. Available workflows:
{list from archon workflow list}
To install SDLC workflows, run /sdlc-workflows:workflows-setup
2b. Preprocess for containerised execution (if workflow has team images)
Check if any node in the workflow has an image: field:
python3 -c "
import yaml
from pathlib import Path
wf = yaml.safe_load(Path('.archon/workflows/<workflow-name>.yaml').read_text())
has_images = any('image' in n for n in wf.get('nodes', []))
print('NEEDS_PREPROCESSING' if has_images else 'NATIVE')
"
If NEEDS_PREPROCESSING:
- Pre-flight image check. Extract every distinct
image: value from
the workflow and verify each exists locally via docker image inspect. Fail fast with a build hint before we do the expensive
rsync + seed-commit setup — otherwise the user waits, then sees a
mid-run docker error from a single node.
MISSING_IMAGES=$(python3 -c "
import yaml
from pathlib import Path
wf = yaml.safe_load(Path('.archon/workflows/<workflow-name>.yaml').read_text())
images = sorted({n['image'] for n in wf.get('nodes', []) if 'image' in n})
for img in images:
print(img)
" | while read -r img; do
[ -z "$img" ] && continue
if ! docker image inspect "$img" >/dev/null 2>&1; then
echo "$img"
fi
done)
if [ -n "$MISSING_IMAGES" ]; then
echo "Workflow references team images that are not built:"
echo "$MISSING_IMAGES" | sed 's/^/ - /'
echo ""
echo "Build the missing images before running:"
echo " • For a team image (sdlc-worker:<team-name>):"
echo " /sdlc-workflows:deploy-team <team-name>"
echo " • For sdlc-worker:base or sdlc-worker:full:"
echo " /sdlc-workflows:workflows-setup --with-docker"
exit 1
fi
This check is deliberate: we do NOT silently auto-build the missing
image. Building a team image requires a manifest the user authored.
Building base/full is the setup skill's job. Either way, the user
makes the call, not us.
- Resolve credentials:
CRED_INFO=$(python3 ${CLAUDE_PLUGIN_ROOT}/scripts/resolve_credentials.py --project-dir . --json)
CRED_TIER=$(echo "$CRED_INFO" | python3 -c "import sys,json; print(json.load(sys.stdin)['tier'])")
CRED_MOUNT=$(echo "$CRED_INFO" | python3 -c "import sys,json; print(json.load(sys.stdin).get('mount_args',''))")
CRED_CLEANUP=$(echo "$CRED_INFO" | python3 -c "import sys,json; p=json.load(sys.stdin).get('cleanup') or ''; print(p)")
cleanup_credentials() {
if [ -n "$CRED_CLEANUP" ] && [ -f "$CRED_CLEANUP" ]; then
rm -f "$CRED_CLEANUP"
fi
}
trap cleanup_credentials EXIT INT TERM
If CRED_TIER is "none", report the error message from the resolver and stop.
- Create workspace directory with its own git root:
WORKSPACE=$(mktemp -d "${TMPDIR:-/tmp}/sdlc-run-XXXXXX")
cleanup_workspace_and_credentials() {
if [ -z "${SKIP_CLEANUP:-}" ] && [ -n "${WORKSPACE:-}" ] && [ -d "$WORKSPACE" ]; then
rm -rf "$WORKSPACE"
fi
cleanup_credentials
}
trap cleanup_workspace_and_credentials EXIT INT TERM
rsync -a \
--exclude='.git' \
--exclude='.worktrees/' \
--exclude='node_modules/' \
--exclude='.venv/' \
--exclude='venv/' \
--exclude='__pycache__/' \
--exclude='.env' \
--exclude='.env.*' \
--exclude='.envrc' \
--exclude='.ssh/' \
--exclude='.aws/' \
--exclude='.gcp/' \
--exclude='.azure/' \
--exclude='.kube/' \
--exclude='.docker/' \
--exclude='.npmrc' \
--exclude='.netrc' \
--exclude='.pypirc' \
--exclude='.gnupg/' \
--exclude='.keychain/' \
--exclude='.*_history' \
--exclude='secrets/' \
--exclude='credentials/' \
./ "$WORKSPACE/"
(cd "$WORKSPACE" \
&& git -c core.hooksPath=/dev/null init -q \
&& git -c core.hooksPath=/dev/null add -A \
&& git -c core.hooksPath=/dev/null \
-c user.email=sdlc-workflows@local \
-c user.name=sdlc-workflows \
commit -q -m "workflow-seed" >/dev/null)
SEED_SHA=$(cd "$WORKSPACE" && git rev-parse HEAD)
- Preprocess the workflow INTO the workspace:
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/preprocess_workflow.py \
"$WORKSPACE/.archon/workflows/<workflow-name>.yaml" \
--output "$WORKSPACE/.archon/workflows/.generated/<workflow-name>.yaml" \
--workspace "$WORKSPACE" \
--cred-mount "$CRED_MOUNT" \
--commands-dir "$WORKSPACE/.archon/commands"
rm -f "$WORKSPACE/.archon/workflows/<workflow-name>.yaml"
cp "$WORKSPACE/.archon/workflows/.generated/<workflow-name>.yaml" \
"$WORKSPACE/.archon/workflows/<workflow-name>.yaml"
- Run the preprocessed workflow from inside the workspace:
(cd "$WORKSPACE" \
&& env -u CLAUDECODE -u CLAUDE_CODE_SSE_PORT -u CLAUDE_CODE_IPC_FD \
archon workflow run <workflow-name> --no-worktree)
Notes:
--no-worktree — workspace isolation is managed by the containers,
not by Archon's worktree provider.
- The
cd "$WORKSPACE" is load-bearing: Archon resolves cwd to the
enclosing git root before looking for .archon/workflows/. The fresh
git in step 2 is what stops that walk.
- The SSE dashboard stream on
archon serve only observes runs
launched through the server; CLI-launched runs write to SQLite but
do not appear in the SSE stream. Use workflows-status (REST or
SQLite) for CLI runs.
While it runs — tell the user where to watch:
Archon ships the monitoring surfaces; our job is to name them.
Emit this block to the user as soon as archon workflow run is
launched so they know how to observe without asking:
Workflow launched. Monitoring surfaces (Archon-native):
• Live per-node lines in this terminal
"[node] Started" / "[node] Completed (duration)" on stderr.
• Archon web UI
archon serve # in another terminal
open http://localhost:3090
Full dashboard with every run, every node, every event.
(First run downloads the UI; subsequent runs start instantly.)
• CLI snapshot (no server needed)
archon workflow status # what's live right now
archon isolation list # per-run worktrees
/sdlc-workflows:workflows-status # REST + SQLite, works either way
• Container-level detail
docker ps --filter name=sdlc-worker
docker logs -f <container-id>
If the run fails part-way, Archon supports resumption:
archon workflow run <name> --resume picks up the most recent
failed run from where it stopped.
- Report artefacts — BEFORE cleanup:
The containers commit to the temp workspace's git. If we cleaned
up silently the user would see "Completed" and have nothing to
look at. Show what was produced first:
echo ""
echo "=== Workflow artefacts ==="
echo "Workspace: $WORKSPACE"
echo ""
echo "--- New commits in workspace (vs seed) ---"
(cd "$WORKSPACE" && git log --oneline "$SEED_SHA..HEAD") \
|| echo "(no commits beyond the seed)"
echo ""
echo "--- New or modified files ---"
(cd "$WORKSPACE" && git diff --stat "$SEED_SHA" HEAD) \
|| echo "(no diff available)"
echo ""
OVERLAP=$(cd "$WORKSPACE" && \
git log --name-only --format="" "$SEED_SHA..HEAD" 2>/dev/null \
| sort | uniq -d)
if [ -n "$OVERLAP" ]; then
echo "⚠ Fan-in overlap: the following files were modified by"
echo " multiple workflow nodes. The last writer's version won."
echo " Review the diff before cherry-picking."
echo "$OVERLAP" | sed 's/^/ /'
echo ""
fi
- Offer the user three choices — NEVER silently discard work:
Workflow complete. What would you like to do with the results?
1. Cherry-pick commits onto your current branch (default)
2. Keep the workspace so you can inspect it: <path>
3. Discard everything (rm -rf the workspace)
Reply with 1, 2, or 3.
Default when the user is absent or replies unclearly: 1
(cherry-pick, the least surprising and the least destructive).
If option 1 — cherry-pick onto current branch:
We cannot use git cherry-pick <sha> or git commit -C <sha> because
those require the main repo to have the commit object — and the
containers committed into a separate git dir (the temp workspace's
.git/). Instead, replay each commit's diff and author metadata
explicitly:
COMMITS=$(cd "$WORKSPACE" && git log --reverse --format=%H \
"$SEED_SHA..HEAD" 2>/dev/null)
for sha in $COMMITS; do
if ! (cd "$WORKSPACE" && git format-patch -1 --stdout "$sha") \
| git apply --index; then
echo "Cherry-pick of $sha failed — workspace preserved at $WORKSPACE for manual recovery."
SKIP_CLEANUP=1
break
fi
AUTHOR_NAME=$(cd "$WORKSPACE" && git log -1 --format=%an "$sha")
AUTHOR_EMAIL=$(cd "$WORKSPACE" && git log -1 --format=%ae "$sha")
AUTHOR_DATE=$(cd "$WORKSPACE" && git log -1 --format=%aI "$sha")
MSG=$(cd "$WORKSPACE" && git log -1 --format=%B "$sha")
if ! GIT_AUTHOR_NAME="$AUTHOR_NAME" \
GIT_AUTHOR_EMAIL="$AUTHOR_EMAIL" \
GIT_AUTHOR_DATE="$AUTHOR_DATE" \
git commit -m "$MSG" >/dev/null; then
echo "Commit of $sha failed — workspace preserved at $WORKSPACE for manual recovery."
SKIP_CLEANUP=1
break
fi
done
[ -n "${SKIP_CLEANUP:-}" ] || rm -rf "$WORKSPACE"
If option 2 — keep: print the path and set SKIP_CLEANUP=1
so the exit trap does not destroy the workspace.
If option 3 — discard: rm -rf "$WORKSPACE".
In all three cases:
cleanup_workspace_and_credentials
Note: the preprocessed YAML lives inside $WORKSPACE, so it goes
away with the workspace (option 3 or a failed run). Options 1 and 2
preserve the workspace intentionally.
If NATIVE (no image: nodes):
Proceed with the existing archon workflow run invocation — no preprocessing needed.
3. Run the workflow
Execute:
archon workflow run {workflow-name} {remaining-arguments}
Stream the output to the user. Report completion status when done.
4. Report results
After workflow completes, report:
- Workflow name and duration
- Node completion status (which nodes passed/failed/skipped)
- Final output (from the terminal node)
- Any errors or warnings
Long-running or multi-cycle workflows
If the workflow has nodes that take more than a few minutes, or the
user is running iterative designer→dev→review cycles:
- Per-node timeout: each long node must set
timeout: <seconds> in its YAML. The default 300 s (5 min) is almost always wrong for real work.
- Live progress during a long node:
archon workflow run emits per-node [name] Started / [name] Completed (duration) lines to stderr as they happen — no redirect needed to see them. For tool-level detail inside a node, add --verbose and pass it through to archon. For the container's own output (whatever the AI is printing), open a second terminal and run docker logs -f $(docker ps -q --filter name=sdlc-worker --latest).
- Cycles (designer → dev → review → designer …): use
loop.stages: — see Long-Running Workflows, Cycles, and Monitoring in CLAUDE-CONTEXT-workflows.md for the primary pattern, with unrolled iterations as a fallback for fixed small counts.
- Monitoring surfaces (any combination): the CLI's own stderr stream (shown automatically),
/sdlc-workflows:workflows-status for historical + REST-backed detail, archon workflow status (what's live), archon isolation list (per-run worktrees), docker logs -f <container> (per-node output), docker events --since <epoch> (node lifecycle), docker stats (resource use). The Archon web UI (archon serve on http://localhost:3090) renders the rich per-run graph only for runs launched through the server — CLI-launched runs show up in listing but the detail pages render empty. Use workflows-status and docker logs for CLI runs.
- Cost: there is no cost meter in v1 — a multi-hour cyclical run on Opus will burn meaningful tokens. Flag this to the user before launching.