How this skill is triggered — by the user, by Claude, or both
Slash command
/workflow:resumeThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Resume an interrupted or paused workflow from its current state.
Resume an interrupted or paused workflow from its current state.
/workflow-resume [workflow_id]
If no workflow_id is provided, resumes the most recent active workflow.
$ARGUMENTS
You are the supervisor agent resuming a workflow.
First, get the absolute home path:
echo $HOME
Resolve the repo-scoped active directory (workflows are isolated per repo since v2):
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/workflow}"
ACTIVE_DIR=$(node "$PLUGIN_ROOT/lib/active-dir-cli.js")
echo "$ACTIVE_DIR"
Store as $ACTIVE_DIR. Also note the legacy flat directory
$HOME/.claude-workflows/active/ — workflows created before repo-scoping live
there directly (no subdirectory).
Then find the workflow file. Never use ~ in tool calls — always use the
absolute path. Search BOTH the repo-scoped dir and the legacy flat root:
Glob(pattern="$ACTIVE_DIR/*")
Glob(pattern="$HOME/.claude-workflows/active/*.state.json") # legacy
Glob(pattern="$HOME/.claude-workflows/active/*.org") # legacy
Glob(pattern="$HOME/.claude-workflows/active/*.md") # legacy
$ARGUMENTS is empty: prefer the most recent .org/.md file in
$ACTIVE_DIR. Fall back to a legacy file only if the repo-scoped dir is
empty.$ARGUMENTS provided: search both locations for a matching workflow ID.If a workflow is found in the legacy flat layout, leave it where it is — do not auto-migrate. Resume operates in place.
Read the workflow org file and determine:
After finding the workflow, bind this session to it so hooks only affect this workflow:
First, get the OS temp directory:
node -e "console.log(require('os').tmpdir())"
Store this as $TMPDIR_PATH.
$TMPDIR_PATH/workflow-session-marker-*.json and read the most recent file to get the session_id$TMPDIR_PATH/workflow-binding-{session_id}.json with:
{
"session_id": "<session_id>",
"workflow_path": "<path to .state.json>",
"workflow_id": "<workflow_id>",
"bound_at": "<ISO timestamp>"
}
If no session marker is found, skip this step (backward compatible).
Before resuming, output:
Resuming workflow: <ID>
Type: <workflow_type>
Task: <description>
Current step: <step_name>
Progress: <X of Y steps completed>
Ask the user:
"I found the workflow at step X. Before continuing:
- Have you modified the plan or any step in the org file?
- Do you want to add any instructions before I continue?
- Or should I proceed from where we left off?"
Once user confirms:
/workflow commandIf a step was started but not completed:
Always check state.phase.rate_limit first, regardless of workflow type.
Rate-limit pauses are now common to every workflow (epic, swarm, feature,
bugfix, refactor, translate). The shared protocol lives in
skills/shared/rate-limit-handling.md.
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/workflow}"
# Compute the current state of the rate-limit pause:
node <<EOF
const fs = require('fs');
const { isRateLimited, clearRateLimitPause } = require('$PLUGIN_ROOT/hooks/lib/rate-limit');
const statePath = process.env.WORKFLOW_STATE_FILE;
const state = JSON.parse(fs.readFileSync(statePath, 'utf8'));
if (!state.phase || !state.phase.rate_limit || !state.phase.rate_limit.paused_at) {
console.log('NO_PAUSE');
process.exit(0);
}
if (isRateLimited(state)) {
console.log('STILL_LIMITED ' + state.phase.rate_limit.resumes_at);
} else {
clearRateLimitPause(state);
state.updated_at = new Date().toISOString();
fs.writeFileSync(statePath, JSON.stringify(state, null, 2) + '\n');
console.log('CLEARED');
}
EOF
NO_PAUSE → proceed straight to step 8 (workflow-type branch).CLEARED → log "Rate limit cleared. Resuming workflow." and proceed.STILL_LIMITED <iso> → report ETA and offer the user three options:
clearRateLimitPause and try anyway (warn that
work may fail again immediately).After the rate-limit check, branch on state.workflow.type.
When resuming an epic workflow (state.workflow.type === "epic"), follow this specialized logic:
When state.phase.current === "component_execution":
┌─────────────────────────────────────────────────────┐
│ EPIC COMPONENT STATUS │
├──────────────┬────────────┬──────────────────────────┤
│ Component │ Status │ PR │
├──────────────┼────────────┼──────────────────────────┤
│ lexer │ completed │ #1 │
│ scanner │ completed │ #2 │
│ parser │ in_progress│ - │
│ type_checker │ pending │ - │
│ codegen │ pending │ - │
└──────────────┴────────────┴──────────────────────────┘
Identify next actionable components:
For components with status "in_progress":
git worktree list | grep epic/{id}gh pr list --head epic/{id}Continue the component execution loop from the epic-orchestration skill
When state.phase.current === "integration":
Check integration status:
integration.status === "pending": start integration from scratchintegration.merged has entries: some merges already done — continue from next unmerged componentintegration.test_results exists but failed: re-run fixes + testsintegration.review_status !== "passed": re-run integration reviewCheck if integration branch exists:
git branch --list "epic/*/integration"
When state.phase.current === "post_merge_review":
state.gates.post_merge_review.iteration to know which retry we're onskills/phases/post-merge-review/SKILL.mdchore(epic): post-merge fixes (resumed) before re-running architectsiteration >= MAX_REVIEW_ITERATIONS already, surface the last failure
list and ask the user how to proceed (do not auto-pass)When state.phase.current === "completion_guard":
npx claudepluginhub zb-ss/claude-plugin-workflow --plugin workflowGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.