关于 cancel
cancel 是 oh-my-claudecode 的技能,用于安全停止指定会话中的活动模式。它按会话限定清理范围,保留可恢复的产物,并区分正常与强制取消。
主要功能
- 01检测活动的 OMC 模式
- 02按会话取消模式
- 03支持正常与强制关闭
- 04保留指定的恢复产物
- 05提供授权的全会话清理
适用场景
- 01停止活动中的 Autopilot 或 Ralph
- 02关闭 Team 工作成员及关联的 Ralph
- 03清理会话中的过期模式状态
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ yeachan-heo/ oh-my-claudecode --skill cancel安装后在 Claude Code 中输入/cancel确认已加载。
详细介绍
Cancel Skill
智能取消,用于检测并取消当前激活的 OMC 模式。
cancel skill 是完成并退出任何 OMC 模式的标准方式。
当 stop hook 检测到完成时,它会指示大模型调用此
skill 以清理状态。在同一作用域内重试失败的操作,并报告
剩余内容;--force 只改变关闭的紧迫程度,绝不改变作用域、锁处理
或所有权检查。--all 是唯一的跨会话授权。
取消契约
这些标志控制相互独立的作用域和关闭维度:
| 调用方式 | 作用域 | 关闭行为 |
|---|---|---|
| 无标志 | 仅当前会话 | 优雅取消,包括等待队友关闭 |
--force | 仅当前会话 | 强制取消:跳过优雅等待,但仍使用受保护的状态工具并遵守锁/所有权 |
--all | 每个已知会话,按显式 session id | 对每个会话独立执行常规安全取消,然后执行显式的旧版/全局清理 |
--force --all | 每个已知会话,按显式 session id | 强制全部:对每个会话跳过优雅等待,然后执行经授权的旧版/全局清理 |
在命令行上下文中从 OMC_SESSION_ID 解析当前身份,或使用
hook 提供的 session_id。对于无标志或 --force,身份缺失或含糊时
按失败关闭处理:不要聚合状态、不要选择某个发现的会话,
也不要发出无作用域的清理。对于默认命令和 --force,这是失败关闭
错误。--all 可以枚举已知会话,但每个具体 id 仍会
被独立读取、取消和清除。
功能说明
自动检测并取消激活的模式:
- Autopilot:停止工作流,同时保留进度以便恢复。
- Ralph:停止持久化循环。
- Legacy Ultrawork / UltraQA:仅移除过时的升级安装状态; 两者都不是活跃工作流。
- Ultragoal:清除其会话运行时防护,同时保留持久化的
.omc/ultragoal/计划和账本产物。 - Swarm:仅在其经授权的共享清理路径中停止协调的 Agent 并释放已认领的任务。
- Ultrapilot / Pipeline:停止其 worker 或顺序执行。
- Team:使用激活的 team 界面进行优雅关闭,然后清除
会话作用域的 Team 状态;强制路径跳过等待。Claude Code 2.1.178+ 没有
TeamDelete。 - Team + Ralph:先取消 Team,然后在同一会话中清除关联的 Ralph; Team 失败时会保留关联的 Ralph。
- OMC Teams、Plan Consensus 和 Self-Improve:使用其模式特定的 受保护清理,并保留为恢复而指定的产物。
用法
/oh-my-claudecode:cancel
/oh-my-claudecode:cancel --force
/oh-my-claudecode:cancel --all
/oh-my-claudecode:cancel --force --all
或者输入:cancelomc、stopomc。
关键:延迟工具处理
状态工具(state_clear、state_read、state_write、
state_list_active、state_get_status)可能会被 Claude Code 延迟。在
调用其中任何一个之前,先用 ToolSearch 加载全部工具:
ToolSearch(query="select:mcp__plugin_oh-my-claudecode_t__state_clear,mcp__plugin_oh-my-claudecode_t__state_read,mcp__plugin_oh-my-claudecode_t__state_write,mcp__plugin_oh-my-claudecode_t__state_list_active,mcp__plugin_oh-my-claudecode_t__state_get_status")
如果 state_clear 不可用或失败,请重试同一作用域的操作并
报告失败。下面的回退方案仅用于从非 force、非 Team 取消的
stop-hook 循环中进行紧急脱身。它仅
为显式标识的当前会话移除文件。不要将此回退方案用于
autopilot、team 或 omc-teams,也不要用于 --force/--all;绝不要用它
绕过锁、所有权检查、损坏或其他状态工具失败。
链接模式需要每个模式执行一次受保护操作。
将 MODE 替换为具体模式(例如 ralplan、ralph、
ultrawork 或 ultragoal)。
# Emergency fallback: direct file removal for one identified session only.
SESSION_ID="${OMC_SESSION_ID:-${CLAUDE_SESSION_ID:-${CLAUDECODE_SESSION_ID:-}}}"
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || { d="$PWD"; while [ "$d" != "/" ] && [ ! -d "$d/.omc" ]; do d="$(dirname "$d")"; done; echo "$d"; })"
sha256portable() { printf '%s' "$1" | (sha256sum 2>/dev/null || shasum -a 256) | cut -c1-16; }
if [ -n "${OMC_STATE_DIR:-}" ]; then
SOURCE="$(git remote get-url origin 2>/dev/null || echo "$REPO_ROOT")"
HASH="$(sha256portable "$SOURCE")"
DIR_NAME="$(basename "$REPO_ROOT" | sed 's/[^a-zA-Z0-9_-]/_/g')"
OMC_STATE="$OMC_STATE_DIR/${DIR_NAME}-${HASH}/state"
elif [ "$REPO_ROOT" != "/" ] && [ -d "$REPO_ROOT/.omc" ]; then
OMC_STATE="$REPO_ROOT/.omc/state"
else
echo "ERROR: Could not locate .omc state directory" >&2; exit 1
fi
[ -d "$OMC_STATE" ] || { echo "ERROR: State dir not found at $OMC_STATE" >&2; exit 1; }
MODE="ralplan" # replace with the target mode
[ -n "$SESSION_ID" ] || { echo "ERROR: current session identity is required; refusing unscoped fallback" >&2; exit 1; }
if [ -d "$OMC_STATE/sessions/$SESSION_ID" ]; then
rm -f "$OMC_STATE/sessions/$SESSION_ID/${MODE}-state.json" \
"$OMC_STATE/sessions/$SESSION_ID/${MODE}-stop-breaker.json" \
"$OMC_STATE/sessions/$SESSION_ID/skill-active-state.json"
NOW_ISO="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
EXPIRES_ISO="$(date -u -d "+30 seconds" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || python3 - <<'PY'
from datetime import datetime, timedelta, timezone
print((datetime.now(timezone.utc) + timedelta(seconds=30)).strftime('%Y-%m-%dT%H:%M:%SZ'))
PY
)"
printf '{"active":true,"requested_at":"%s","expires_at":"%s","mode":"%s","source":"bash_fallback"}' \
"$NOW_ISO" "$EXPIRES_ISO" "$MODE" > "$OMC_STATE/sessions/$SESSION_ID/cancel-signal-state.json"
fi
取消流程
这是每次调用的权威流程。
1. 解析参数
独立解析精确的标志;未知或近似匹配的参数不执行任何操作:
FORCE_MODE=false
ALL_MODE=false
for arg in "$@"; do
case "$arg" in
--force) FORCE_MODE=true ;;
--all) ALL_MODE=true ;;
esac
done
SCOPE="current"
if [[ "$ALL_MODE" == true ]]; then SCOPE="all"; fi
GRACEFUL_MODE=true
if [[ "$FORCE_MODE" == true ]]; then GRACEFUL_MODE=false; fi
解析出的值恰好选择上述契约中的一行。
2. 检测活跃模式
- 对于无标志或
--force,要求存在一个无歧义的当前会话 id,并调用state_list_active(session_id="<current_session_id>")。其作用域内的 结果是权威的;绝不要使用聚合结果来推断归属。 - 对于
--all,调用一次state_list_active(all=true)并保留每个 具体会话 id。发现过程用于枚举目标;它不是 Team 读取。 - 对于每个选定的 id,在模式清理之前调用
state_get_status(mode="<mode>", session_id="<session_id>")。将 Ultrawork 视为已弃用的清理输入。 - 将选定的 id 传递给每次读取、写入和清除。受保护的状态工具 强制执行共享变更锁和归属边界;没有任何标志能绕过 其中任何一个。
当多个模式出现在同一个作用域状态中时,使用此依赖顺序:
- Autopilot(包括其关联的 Ralph 和已弃用状态清理)
- 独立的 Ralph
- 已弃用的 Ultrawork 和 UltraQA
- Ultragoal 运行时防护
- 共享 Swarm 状态(仅全局遍历)
- Ultrapilot 和 Pipeline
- 原生 Team
- 旧版 OMC Teams
- Plan Consensus 和 Self-Improve
关联到 Team 的 Ralph 从独立步骤中排除,仅在 Team 成功后才处理;这可以防止持久化循环比 worker 存活得更久。
3. 取消每个选定的会话
按此依赖顺序独立处理每个选定的会话。失败
或未解决的限定操作会将该会话标记为不成功:保留受影响的
状态/运行时记录,报告作用域和原因,并且不要声称已进行关联
清理。--all 运行可以继续处理其他 id,但任何此类失败都会阻止
最终的全局遍历。
Autopilot(主项优先)
- 读取确切的会话状态,包括
workflowRunId(如果存在)。 - 仅使用
state_write(mode="autopilot", session_id="<session_id>", active=false, state={workflowRunId: "<exact run id>"})暂停该运行;不要重放读回结果。状态工具会在其变更锁下重新验证工作流完整性。 - 如果主写入失败,停止此会话的依赖清理。否则,
仅清除同一会话的命名工作流
state_clear(mode="ralplan", session_id="<session_id>"),然后是关联的 Ralph, 再然后是已弃用的 UltraQA。当 依赖清除失败时,保留已暂停的主项以便恢复。强制模式保持此主项优先的顺序。
主项暂停会保留工作流、管道跟踪和任务身份。只有在它是
当前序列化状态的精确哈希时,才能提供
target_state_sha256。绝不要在主写入失败后清除嵌套的 ralplan、关联状态、取消
信号或运行时产物;报告确切的
依赖失败,并在同一会话中重试。
Team(原生 Claude Code)
- 读取
state_read(mode="team", session_id="<session_id>")并获取 捕获的 team 名称和活跃 worker 标签。绝不要从 聚合读取中选择 Team。 - 在优雅路径上,通过活跃界面向每个具名队友发送信号, 每个成员最多等待 15 秒,然后再协调 5 秒。记录 确认和超时。强制路径跳过这两次等待。
- 在优雅确认/超时后(或在强制时立即),清除
state_clear(mode="team", session_id="<session_id>")。如果受保护的 清除因锁、归属、损坏或其他原因失败,保留 Team 运行时记录和关联的 Ralph;不要使用未限定作用域的清除或回退。 - 仅在 Team 清除成功后,检查关联的 Ralph 并使用
相同的会话 id 清除它(先
state_read(mode="ralph", session_id="<session_id>"),然后state_clear(mode="ralph", session_id="<session_id>"))。对于旧版omc team//omc-teamsworker,在状态清理后运行 捕获的 team 名称孤儿扫描;原生 Team 没有TeamDelete。 报告团队名称、已发出信号的成员、响应、超时情况、Team 和关联的 Ralph 状态是否已清除,以及任何需要手动清理的内容。优雅超时会单独记录;只有未解决的受保护操作才会阻塞全局通过。旧版孤儿扫描仅限于已捕获的名称,且不得终止未捕获的原生 Team,也不得删除~/.claude/teams根目录。
旧版扫描在适用时如下:
node "${CLAUDE_PLUGIN_ROOT}/scripts/cleanup-orphans.mjs" \
--team-name "<captured_team_name>"
使用 --dry-run 可在不终止 worker 的情况下进行检查。此扫描不能替代受保护的 Team 清除,也绝不能通过名称前缀匹配来推断。
关联的 Ralph 上下文
如果在 Ralph 处于关联状态时开始取消,请应用相同的 Team 优先顺序。在关联的 Team 成功处理之前,绝不要清除 Ralph;如果 Team 失败,Ralph 仍受保护。这两个操作都使用选定的 id。
其他模式
- 独立 Ralph:
state_clear(mode="ralph", session_id="<session_id>")。 - 已弃用的 Ultrawork:仅对过期的作用域记录使用
state_clear(mode="ultrawork", session_id="<session_id>");绝不要重新激活或路由它。 - 已弃用的 UltraQA:仅对 5.0.0 之前的过期状态使用
state_clear(mode="ultraqa", session_id="<session_id>")。 - Ultragoal:
state_clear(mode="ultragoal", session_id="<session_id>")仅清除其运行时防护;保留.omc/ultragoal/产物。 - Ultrapilot、Pipeline、Plan Consensus 和 Self-Improve:使用它们受保护的会话作用域清除以及特定模式的恢复/产物规则。
- Swarm 和其他共享状态不能从会话中猜测;仅在授权的全局通过中处理它们。OMC Teams 使用它们自己的 tmux/运行时清理。
Self-Improve 清理会清除其已解决状态和孤立的 worktree,同时保留 iteration_state,并在已解决的 agent-settings.json 中记录 status: "user_stopped"。新的 topic 根目录不会被扁平的旧版根目录替换。OMC Teams 通过它们自己捕获的 tmux/运行时记录进行清理,绝不作为原生 Team 状态;仅通过该模式受保护的会话操作清除 omc-teams。
最后,作为最后一个作用域操作,清除 state_clear(mode="skill-active", session_id="<session_id>")。失败也会使该会话未被解决。
4. 授权的全局遍历
全局遍历仅允许用于 --all,且必须在每个具体会话 id 都尝试成功并完成其范围内流程之后进行,包括最终的 skill-active 清除。如果任何会话操作失败或仍未解决,请报告部分完成并省略此遍历。绝不要用全局重试替代失败的范围内操作。
如果全会话枚举本身失败、返回不明确的 id,或无法捕获 Team owner,则将该受影响范围视为未解决,并在任何非范围操作之前停止。可以报告仅遗留条目,但这并不授权猜测当前会话或删除原生 Team 根。
使用受保护的状态工具进行显式遍历,例如:
state_clear(mode="<legacy-mode>") # no session_id: --all authorization only
非范围的 state_clear 不是仅遗留 API:它既可以重新访问会话状态,也可以重新访问遗留/共享产物。将其限制为此遍历明确授权的兼容路径,包括遗留模式 JSON、Swarm 数据库/标记、检查点,以及共享 OMC worker 注册表。不要清除原生 Claude 根或任何未成功捕获并清除其 owner 的 Team 根;未捕获的 Team 根仍受保护。请将全局清理失败与范围内会话失败分开报告。
显式兼容集合为:
.omc/state/{autopilot,ralph,ralph-plan,ralph-verification}-state.json.omc/state/{ultrawork,ultraqa,ultrapilot,pipeline,omc-teams}-state.json.omc/state/{ultrapilot-ownership,plan-consensus,ralplan,boulder,hud}.json.omc/state/subagent-tracking.json和.omc/state/subagent-tracker.lock.omc/state/{swarm.db,swarm.db-wal,swarm.db-shm,swarm-active.marker,swarm-tasks.db}.omc/state/{rate-limit-daemon.pid,rate-limit-daemon.log}.omc/state/checkpoints/和空的.omc/state/sessions/目录- 共享的遗留 Team bridge 心跳和
.omc/state/team-mcp-workers.json,仅在捕获的 owner 成功之后
这些名称展开为以下遗留记录(且没有会话拥有的替代项):autopilot-state.json、ralph-state.json、
ralph-plan-state.json、ralph-verification.json、ultrawork-state.json、
ultraqa-state.json、ultrapilot-state.json、ultrapilot-ownership.json、
pipeline-state.json、omc-teams-state.json、plan-consensus.json、
ralplan-state.json、boulder.json、hud-state.json、
subagent-tracking.json 和 subagent-tracker.lock。
共享数据库兼容记录为 swarm.db、swarm.db-wal、
swarm.db-shm、swarm-active.marker 和 swarm-tasks.db;守护进程记录
为 rate-limit-daemon.pid 和 rate-limit-daemon.log。检查点仅作为此授权全局遍历的一部分被
移除。
不要将此列表解释为允许移除
.omc/state、~/.claude/teams 或 ~/.claude/tasks 下的任意文件。未列出或未捕获的
Team/运行时记录保留以供检查和未来所有权解析。
全局遍历必须保留与范围内操作相同的锁和所有权检查。它可以在每会话门打开后继续为一个兼容项记录错误, 但必须报告该全局失败,并且绝不声称已完成完整重置。它不得仅仅因为持久 Autopilot、Ultragoal、 Self-Improve 或 Team 交接产物共享同一目录就删除它们。
如果在所选范围中未找到活动模式,请报告:“No active OMC modes
detected.” 对于当前会话命令,不要静默扩大该结果;
使用 --all 枚举其他会话并执行全局遍历。
保留状态
| 模式 | 取消结果 |
|---|---|
| Autopilot | active=false,进度、阶段、计划和判定结果均保留 |
| Ralph、Ultrawork、UltraQA、Swarm、Ultrapilot、Pipeline | 当受保护的限定范围/全局操作成功后,状态被清除 |
| Ultragoal | 运行时守卫被清除;持久化计划/账本保留 |
| Team | 交接和未捕获的运行时根保留;选定状态仅在其流程完成后清除 |
| Plan Consensus / Self-Improve | 按该模式文档所述,模式特定的恢复/产物记录被保留 |
Autopilot 可通过 /oh-my-claudecode:autopilot 恢复;Ultragoal 的持久化计划与账本可通过 /ultragoal 恢复。Ralph 及已退役状态不提供恢复路径。Team 交接仍可用于后续的限定范围恢复,而共享的 Swarm 和旧版记录需要显式授权。
取消报告应标明选定的范围、观察到的模式、成功和失败的操作、跳过的等待,以及任何保留的记录。不要把超时、缺失身份、锁冲突、所有权不匹配或状态格式错误变成成功消息。当前会话的成功报告并不意味着另一个会话或共享的旧版产物已被触及。
MCP Worker 清理
对于选定会话的取消,仅检查所捕获团队的 .omc/state/team-bridge/{team}/*.heartbeat.json 记录,并在状态清理前捕获确切的 worker 句柄。发送关闭信号并仅终止那些确切的 tmux 会话标识符,而不是按名称前缀选定的会话。如果无法确定所有权或身份,则保留记录并报告需手动清理。只有在受保护的清理成功后,才移除它们的 heartbeat/registry 条目。
在每一个具体会话都成功后,经授权的 --all 全局运行时清理可以为所捕获的 Team 名称移除共享的旧版 bridge 状态。仅从成功的限定范围 Team 读取中填充 CAPTURED_TEAM_NAMES;保留每一个未捕获的 registry/root。使用确切捕获的 worker 身份进行关闭;团队名称前缀不是所有权证据。只有在清理成功后,才移除匹配的 bridge 记录和 registry 条目。