npx skills add https://github.com/akillness/oh-my-gods --skill omg关键词:
omg·annotate·UI검토·agentui (已弃用)| 平台: Claude Code · Codex CLI · Gemini CLI · OpenCode一个提供全自动编排流程的统一技能:规划 (ralph+plannotator) → 执行 (team/bmad) → UI反馈 (agentation/annotate) → 清理 (worktree cleanup)
OMG 使用一个跨平台的抽象层进行编排:
settings: 平台/运行时配置,例如 Claude 钩子、Codex 的 config.toml、Gemini 的 settings.json、MCP 注册以及提示参数rules: 必须在每个平台上都遵守的策略约束hooks: 在每个平台上强制执行这些规则的事件回调Keyword:
omg·annotate·UI검토·agentui (deprecated)| Platforms: Claude Code · Codex CLI · Gemini CLI · OpenCodeA unified skill providing fully automated orchestration flow: Plan (ralph+plannotator) → Execute (team/bmad) → UI Feedback (agentation/annotate) → Cleanup (worktree cleanup)
OMG uses one cross-platform abstraction for orchestration:
settings: platform/runtime configuration such as Claude hooks, Codex config.toml, Gemini settings.json, MCP registration, and prompt parametersrules: policy constraints that must hold on every platform广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
关键的 OMG 规则是:
plan_gate_status 重置为 pending权威状态文件是 .omc/state/omg-state.json。钩子可以帮助推进工作流,但它们必须遵守状态文件。
omg 关键词后立即遵循)以下是命令,而非描述。请按顺序执行。每一步只有在前一步完成后才能进行。
mkdir -p .omc/state .omc/plans .omc/logs
如果 .omc/state/omg-state.json 不存在,则创建它:
{
"phase": "plan",
"task": "<检测到的任务>",
"plan_approved": false,
"plan_gate_status": "pending",
"plan_current_hash": null,
"last_reviewed_plan_hash": null,
"last_reviewed_plan_at": null,
"plan_review_method": null,
"team_available": null,
"retry_count": 0,
"last_error": null,
"checkpoint": null,
"created_at": "<ISO 8601>",
"updated_at": "<ISO 8601>",
"agentation": {
"active": false,
"session_id": null,
"keyword_used": null,
"submit_gate_status": "idle",
"submit_signal": null,
"submit_received_at": null,
"submitted_annotation_count": 0,
"started_at": null,
"timeout_seconds": 120,
"annotations": { "total": 0, "acknowledged": 0, "resolved": 0, "dismissed": 0, "pending": 0 },
"completed_at": null,
"exit_reason": null
}
}
通知用户:
"OMG 已激活。阶段:PLAN。如果需要 UI 反馈循环,请添加
annotate关键词。"
检查点记录 — 在进入每个步骤后立即执行:
# 在每个步骤开始时立即执行(智能体直接更新 omg-state.json)
python3 -c "
import json, datetime, os, subprocess, tempfile
try:
root = subprocess.check_output(['git', 'rev-parse', '--show-toplevel'], stderr=subprocess.DEVNULL).decode().strip()
except:
root = os.getcwd()
f = os.path.join(root, '.omc/state/omg-state.json')
if os.path.exists(f):
import fcntl
with open(f, 'r+') as fh:
fcntl.flock(fh, fcntl.LOCK_EX)
try:
d = json.load(fh)
d['checkpoint']='<当前阶段>' # 'plan'|'execute'|'verify'|'cleanup'
d['updated_at']=datetime.datetime.utcnow().isoformat()+'Z'
fh.seek(0)
json.dump(d, fh, ensure_ascii=False, indent=2)
fh.truncate()
finally:
fcntl.flock(fh, fcntl.LOCK_UN)
" 2>/dev/null || true
last_error 记录 — 在预检失败或异常时:
python3 -c "
import json, datetime, os, subprocess, fcntl
try:
root = subprocess.check_output(['git', 'rev-parse', '--show-toplevel'], stderr=subprocess.DEVNULL).decode().strip()
except:
root = os.getcwd()
f = os.path.join(root, '.omc/state/omg-state.json')
if os.path.exists(f):
with open(f, 'r+') as fh:
fcntl.flock(fh, fcntl.LOCK_EX)
try:
d = json.load(fh)
d['last_error']='<错误信息>'
d['retry_count']=d.get('retry_count',0)+1
d['updated_at']=datetime.datetime.utcnow().isoformat()+'Z'
fh.seek(0)
json.dump(d, fh, ensure_ascii=False, indent=2)
fh.truncate()
finally:
fcntl.flock(fh, fcntl.LOCK_UN)
" 2>/dev/null || true
基于检查点的重启恢复:
# 如果 omg-state.json 已存在,则从检查点恢复
python3 -c "
import json, os, subprocess
try:
root = subprocess.check_output(['git', 'rev-parse', '--show-toplevel'], stderr=subprocess.DEVNULL).decode().strip()
except:
root = os.getcwd()
f = os.path.join(root, '.omc/state/omg-state.json')
if os.path.exists(f):
d=json.load(open(f))
cp=d.get('checkpoint')
err=d.get('last_error')
if err: print(f'先前错误: {err}')
if cp: print(f'从以下位置恢复: {cp}')
" 2>/dev/null || true
规则 : 在预检中
exit 1之前,始终更新last_error并递增retry_count。如果retry_count >= 3,询问用户是否中止。
预检(进入前必需):
# 记录检查点
python3 -c "
import json,datetime,os,subprocess,fcntl,tempfile
try:
root=subprocess.check_output(['git','rev-parse','--show-toplevel'],stderr=subprocess.DEVNULL).decode().strip()
except:
root=os.getcwd()
f=os.path.join(root,'.omc/state/omg-state.json')
if os.path.exists(f):
with open(f,'r+') as fh:
fcntl.flock(fh,fcntl.LOCK_EX)
try:
d=json.load(fh)
d.update({'checkpoint':'plan','updated_at':datetime.datetime.utcnow().isoformat()+'Z'})
fh.seek(0); json.dump(d,fh,ensure_ascii=False,indent=2); fh.truncate()
finally:
fcntl.flock(fh,fcntl.LOCK_UN)
" 2>/dev/null || true
# 注意:Claude Code — 跳过整个 bash 块。
# plannotator 是一个仅限钩子的二进制文件;直接调用它总是失败。
# 对于 Claude Code:调用 EnterPlanMode → 编写计划 → 调用 ExitPlanMode。
# ExitPlanMode PermissionRequest 钩子会自动触发 plannotator。
# 以下脚本仅适用于 Codex / Gemini / OpenCode。
# 守卫:通过计划哈希强制禁止重复的 PLAN 审查。
# 相同哈希 + 最终门控状态 => 跳过重新打开计划门控
# 修订后的 plan.md 内容 => 将门控重置为 pending 并重新审查
PLAN_GATE_STATUS=$(python3 -c "
import json, os
try:
s = json.load(open('.omc/state/omg-state.json'))
print(s.get('plan_gate_status', 'pending'))
except Exception:
print('pending')
" 2>/dev/null || echo "pending")
HASH_MATCH=$(python3 -c "
import hashlib, json, os
try:
s = json.load(open('.omc/state/omg-state.json'))
if not os.path.exists('plan.md'):
print('no-match')
else:
current_hash = hashlib.sha256(open('plan.md', 'rb').read()).hexdigest()
print('match' if current_hash == (s.get('last_reviewed_plan_hash') or '') else 'no-match')
except Exception:
print('no-match')
" 2>/dev/null || echo "no-match")
if [[ "$HASH_MATCH" == "match" && "$PLAN_GATE_STATUS" =~ ^(approved|manual_approved|feedback_required|infrastructure_blocked)$ ]]; then
echo "✅ 当前计划哈希已有门控结果: $PLAN_GATE_STATUS。不要重新打开 plannotator。"
exit 0
fi
# plannotator 对于 PLAN 步骤是强制性的(Codex/Gemini/OpenCode)。
# 如果缺失,OMG 会在打开 PLAN 门控前自动安装它。
# 解析 OMG 脚本目录(适用于任何 CWD)
_OMG_SCRIPTS=""
for _candidate in \
"${OMG_SKILL_DIR:-}/scripts" \
"$HOME/.agent-skills/omg/scripts" \
"$HOME/.codex/skills/omg/scripts" \
"$(pwd)/.agent-skills/omg/scripts" \
"scripts" \
; do
if [ -f "${_candidate}/plannotator-plan-loop.sh" ]; then
_OMG_SCRIPTS="$_candidate"
break
fi
done
if [ -z "$_OMG_SCRIPTS" ]; then
echo "❌ 未找到 OMG 脚本。重新运行: bash setup-codex.sh (或 setup-gemini.sh)"
exit 1
fi
if ! bash "${_OMG_SCRIPTS}/ensure-plannotator.sh"; then
echo "❌ plannotator 自动安装失败:无法继续 PLAN 步骤。"
echo " 重试: bash ${_OMG_SCRIPTS}/../scripts/install.sh --with-plannotator"
exit 1
fi
# 必需的 PLAN 门控(Codex / Gemini / OpenCode):
# - 必须等待直到收到批准/反馈
# - 会话退出时自动重启(最多 3 次)
# - 3 次退出后,询问用户是否结束 PLAN
FEEDBACK_DIR=$(python3 -c "import hashlib,os; h=hashlib.md5(os.getcwd().encode()).hexdigest()[:8]; d=f'/tmp/omg-{h}'; os.makedirs(d,exist_ok=True); print(d)" 2>/dev/null || echo '/tmp')
FEEDBACK_FILE="${FEEDBACK_DIR}/plannotator_feedback.txt"
bash "${_OMG_SCRIPTS}/plannotator-plan-loop.sh" plan.md "$FEEDBACK_FILE" 3
PLAN_RC=$?
if [ "$PLAN_RC" -eq 0 ]; then
echo "✅ 计划已批准"
elif [ "$PLAN_RC" -eq 10 ]; then
echo "❌ 计划未批准 — 应用反馈,修订 plan.md,然后重试"
exit 1
elif [ "$PLAN_RC" -eq 32 ]; then
echo "⚠️ plannotator UI 不可用(沙盒/CI)。进入对话批准模式:"
echo " 1. 在对话中向用户输出 plan.md 内容"
echo " 2. 询问用户:'approve' 以继续或提供反馈"
echo " 3. 在用户明确批准之前,不要进入 EXECUTE"
exit 32
elif [ "$PLAN_RC" -eq 30 ] || [ "$PLAN_RC" -eq 31 ]; then
echo "⛔ PLAN 退出决定(或等待确认)。在重试前与用户确认。"
exit 1
else
echo "❌ plannotator PLAN 门控失败 (code=$PLAN_RC)"
exit 1
fi
mkdir -p .omc/plans .omc/logs
plan.md(包含目标、步骤、风险和完成标准)Claude Code(钩子模式 — 唯一支持的方法) : plannotator 是一个仅限钩子的二进制文件。无法通过 MCP 工具或 CLI 直接调用。调用 EnterPlanMode,在计划模式下编写计划内容,然后调用 ExitPlanMode。ExitPlanMode PermissionRequest 钩子会自动触发 OMG Claude 计划门控包装器。该包装器在当前计划哈希已有最终审查结果时必须跳过重新进入。等待钩子返回后再继续 — 批准或反馈将通过钩子结果到达。
Codex / Gemini / OpenCode : 运行阻塞式 CLI(切勿使用 &):
# _OMG_SCRIPTS 必须首先通过上述预检中的动态路径发现块解析
bash "${_OMG_SCRIPTS}/plannotator-plan-loop.sh" plan.md /tmp/plannotator_feedback.txt 3
如果 plannotator 缺失,OMG 必须首先自动运行 bash "${_OMG_SCRIPTS}/ensure-plannotator.sh",并且仅在 CLI 可用后继续。
3. 检查结果:
* approved: true(Claude Code:钩子返回批准)→ 更新 omg-state.json 的 phase 为 "execute",plan_approved 为 true → 进入步骤 2
* 未批准(Claude Code:钩子返回反馈;其他:exit 10)→ 读取反馈,修订 plan.md → 重复步骤 2
* 基础设施受阻(exit 32)→ localhost 绑定不可用(例如,沙盒/CI)。在 TTY 中使用手动门控;在非 TTY 的沙盒外与用户确认并重试
* 会话退出 3 次(exit 30/31)→ 询问用户是否结束 PLAN 并决定中止或恢复
切勿: 在 approved: true 之前进入 EXECUTE。切勿: 使用 & 后台运行。切勿: 在 approved、manual_approved、feedback_required 或 infrastructure_blocked 之后重新打开相同的未更改计划。
预检(自动检测团队可用性):
# 记录检查点
python3 -c "
import json,datetime,os,subprocess,fcntl
try:
root=subprocess.check_output(['git','rev-parse','--show-toplevel'],stderr=subprocess.DEVNULL).decode().strip()
except:
root=os.getcwd()
f=os.path.join(root,'.omc/state/omg-state.json')
if os.path.exists(f):
with open(f,'r+') as fh:
fcntl.flock(fh,fcntl.LOCK_EX)
try:
d=json.load(fh)
d.update({'checkpoint':'execute','updated_at':datetime.datetime.utcnow().isoformat()+'Z'})
fh.seek(0); json.dump(d,fh,ensure_ascii=False,indent=2); fh.truncate()
finally:
fcntl.flock(fh,fcntl.LOCK_UN)
" 2>/dev/null || true
TEAM_AVAILABLE=false
if [[ "${CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS:-}" =~ ^(1|true|True|yes|YES)$ ]]; then
TEAM_AVAILABLE=true
elif python3 -c "
import json, os, sys
try:
s = json.load(open(os.path.expanduser('~/.claude/settings.json')))
val = s.get('env', {}).get('CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS', '')
sys.exit(0 if str(val) in ('1', 'true', 'True', 'yes') else 1)
except Exception:
sys.exit(1)
" 2>/dev/null; then
TEAM_AVAILABLE=true
fi
export TEAM_AVAILABLE_BOOL="$TEAM_AVAILABLE"
python3 -c "
import json,os,subprocess,fcntl
try:
root=subprocess.check_output(['git','rev-parse','--show-toplevel'],stderr=subprocess.DEVNULL).decode().strip()
except:
root=os.getcwd()
f=os.path.join(root,'.omc/state/omg-state.json')
if os.path.exists(f):
with open(f,'r+') as fh:
fcntl.flock(fh,fcntl.LOCK_EX)
try:
d=json.load(fh)
d['team_available']=os.environ.get('TEAM_AVAILABLE_BOOL','false').lower()=='true'
fh.seek(0); json.dump(d,fh,ensure_ascii=False,indent=2); fh.truncate()
finally:
fcntl.flock(fh,fcntl.LOCK_UN)
" 2>/dev/null || true
更新 omg-state.json 的 phase 为 "execute"
团队可用(Claude Code + omc):
/omc:team 3:executor "<任务>"
Claude Code 但无团队:
echo "❌ OMG 需要 Claude Code 团队模式。重新运行 bash scripts/setup-claude.sh,重启 Claude Code,并确认 CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1。"
exit 1
切勿在 Claude Code 中回退到单智能体执行。 4. 无 omc(BMAD 回退 — 仅限 Codex / Gemini / OpenCode):
/workflow-init # 初始化 BMAD
/workflow-status # 检查当前步骤
更新 omg-state.json 的 phase 为 "verify"
使用 agent-browser 进行基本验证(当存在浏览器 UI 时):
agent-browser snapshot http://localhost:3000
检测到 annotate 关键词 → 进入步骤 3.1
否则 → 进入步骤 4
annotate 关键词时执行)预检(进入前必需):
if ! curl -sf --connect-timeout 2 http://localhost:4747/health >/dev/null 2>&1; then
echo "⚠️ agentation-mcp 服务器未运行 — 跳过 VERIFY_UI 并继续到 CLEANUP"
python3 -c "
import json,os,subprocess,fcntl,time try: root=subprocess.check_output(['git','rev-parse','--show-toplevel'],stderr=subprocess.DEVNULL).decode().strip() except: root=os.getcwd() f=os.path.join(root,'.omc/state/omg-state.json') if os.path.exists(f): with open(f,'r+') as fh: fcntl.flock(fh,fcntl.LOCK_EX) try: d=json.load(fh) d['last_error']='agentation-mcp 未运行;VERIFY_UI 已跳过' d['updated_at']=time.strftime('%Y-%m-%dT%H:%M:%SZ',time.gmtime()) fh.seek(0); json.dump(d,fh,ensure_ascii=False,indent=2); fh.truncate() finally: fcntl.flock(fh,fcntl.LOCK_UN) " 2>/dev/null || true # 继续到步骤 4 CLEANUP(不 exit 1 — 优雅跳过) fi
2. 更新 `omg-state.json`: `phase = "verify_ui"`, `agentation.active = true`, `agentation.submit_gate_status = "waiting_for_submit"`
3. 等待显式的人工提交:
- **Claude Code**: 等待用户在按下 **发送标注** / `onSubmit` 后的 `UserPromptSubmit`
- **Codex / Gemini / OpenCode**: 等待直到人类确认提交并且智能体发出 `ANNOTATE_READY`(或兼容别名 `AGENTUI_READY`)
4. 在该提交信号到达之前,不要读取 `/pending`,不要确认标注,也不要开始修复循环
5. 提交到达后,切换 `agentation.submit_gate_status = "submitted"` 并记录 `submit_signal`、`submit_received_at` 和 `submitted_annotation_count`
6. **Claude Code (MCP)**: 阻塞式调用 `agentation_watch_annotations` (`batchWindowSeconds:10`, `timeoutSeconds:120`)
7. **Codex / Gemini / OpenCode (HTTP)**: 通过 `GET http://localhost:4747/pending` 进行轮询循环
8. 处理每个标注:`acknowledge` → 通过 `elementPath` 导航代码 → 应用修复 → `resolve`
9. `count=0` 或超时 → 重置提交门控或完成子阶段 → **进入步骤 4**
**切勿:** 在提交/onSubmit 之前处理草稿标注。
---
### 步骤 4:清理
**预检(进入前检查):**
```bash
# 记录检查点
python3 -c "
import json,datetime,os,subprocess,fcntl
try:
root=subprocess.check_output(['git','rev-parse','--show-toplevel'],stderr=subprocess.DEVNULL).decode().strip()
except:
root=os.getcwd()
f=os.path.join(root,'.omc/state/omg-state.json')
if os.path.exists(f):
with open(f,'r+') as fh:
fcntl.flock(fh,fcntl.LOCK_EX)
try:
d=json.load(fh)
d.update({'checkpoint':'cleanup','updated_at':datetime.datetime.utcnow().isoformat()+'Z'})
fh.seek(0); json.dump(d,fh,ensure_ascii=False,indent=2); fh.truncate()
finally:
fcntl.flock(fh,fcntl.LOCK_UN)
" 2>/dev/null || true
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
echo "⚠️ 不是 git 仓库 — 跳过工作树清理"
else
UNCOMMITTED=$(git status --porcelain 2>/dev/null | wc -l | tr -d ' ')
[[ "$UNCOMMITTED" -gt 0 ]] && echo "⚠️ ${UNCOMMITTED} 个未提交的更改 — 建议在清理前提交/暂存"
fi
更新 omg-state.json 的 phase 为 "cleanup"
工作树清理:
bash scripts/worktree-cleanup.sh || git worktree prune
更新 omg-state.json 的 phase 为 "done"
事实来源 :
https://github.com/supercent-io/skills-template本地路径如~/.claude/skills/omg/是通过npx skills add安装的副本。要更新到最新版本,请使用以下命令重新安装。
# 安装 OMG(npx skills add — 推荐)
npx skills add https://github.com/supercent-io/skills-template --skill omg
# 完整安装(所有 AI 工具 + 所有组件)
bash scripts/install.sh --all
# 检查状态
bash scripts/check-status.sh
# 单个 AI 工具设置
bash scripts/setup-claude.sh # Claude Code 插件 + 钩子
bash scripts/setup-codex.sh # Codex CLI developer_instructions
bash scripts/setup-gemini.sh # Gemini CLI 钩子 + GEMINI.md
bash scripts/setup-opencode.sh # OpenCode 插件注册
OMG 安装和配置的工具:
| 工具 | 描述 | 安装命令 |
|---|---|---|
| omc (oh-my-claudecode) | Claude Code 多智能体编排 | /plugin marketplace add https://github.com/Yeachan-Heo/oh-my-claudecode |
| omx | OpenCode 的多智能体编排 | bunx oh-my-opencode setup |
| ohmg | Gemini CLI 的多智能体框架 | bunx oh-my-ag |
| bmad | BMAD 工作流编排 | 包含在技能中 |
| ralph | 自指完成循环 | 包含在 omc 中或单独安装 |
| plannotator | 可视化计划/差异审查 | 在 PLAN 期间通过 bash scripts/ensure-plannotator.sh 自动安装(或使用 bash scripts/install.sh --with-plannotator 预安装) |
| agentation | UI 标注 → 智能体代码修复集成(annotate 关键词,保持 agentui 兼容性) | bash scripts/install.sh --with-agentation |
| agent-browser | 无头浏览器用于 AI 智能体 — 浏览器行为验证的主要工具 | npm install -g agent-browser |
| playwriter | 基于 Playwright 的浏览器自动化(可选) | npm install -g playwriter |
omg "<任务>"
│
▼
[1] 规划 (ralph + plannotator)
使用 ralph 起草计划 → 使用 plannotator 进行可视化审查 → 批准/反馈
│
▼
[2] 执行
├─ 团队可用? → /omc:team N:executor "<任务>"
│ 分阶段管道:plan→prd→exec→verify→fix
└─ 无团队? → /bmad /workflow-init → 运行 BMAD 步骤
│
▼
[3] 验证 (agent-browser — 默认行为)
使用 agent-browser 验证浏览器行为
→ 捕获快照 → 确认 UI/功能正常工作
│
├─ 带有 annotate 关键词 → [3.3.1] VERIFY_UI (agentation 监视循环)
│ agentation_watch_annotations 阻塞 → 标注确认→修复→解决循环
│
▼
[4] 清理
所有工作完成后 → bash scripts/worktree-cleanup.sh
git worktree prune
平台说明 :
/ralph斜杠命令仅在 Claude Code (omc) 中可用。对于 Codex/Gemini/OpenCode,请使用下面的“替代方法”。
Claude Code (omc):
/ralph "omg-plan: <任务>" --completion-promise="PLAN_APPROVED" --max-iterations=5
Codex / Gemini / OpenCode (替代方法):
# 会话隔离的反馈目录(防止并发运行冲突)
FEEDBACK_DIR=$(python3 -c "import hashlib,os; h=hashlib.md5(os.getcwd().encode()).hexdigest()[:8]; d=f'/tmp/omg-{h}'; os.makedirs(d,exist_ok=True); print(d)" 2>/dev/null || echo '/tmp')
FEEDBACK_FILE="${FEEDBACK_DIR}/plannotator_feedback.txt"
# 1. 直接编写 plan.md,然后使用 plannotator 审查(阻塞 — 无 &)
PLANNOTATOR_RUNTIME_HOME="${FEEDBACK_DIR}/.plannotator"
mkdir -p "$PLANNOTATOR_RUNTIME_HOME"
touch /tmp/omg-plannotator-direct.lock && python3 -c "
import json
print(json.dumps({'tool_input': {'plan': open('plan.md').read(), 'permission_mode': 'acceptEdits'}}))
" | env HOME="$PLANNOTATOR_RUNTIME_HOME" PLANNOTATOR_HOME="$PLANNOTATOR_RUNTIME_HOME" plannotator > "$FEEDBACK_FILE" 2>&1
# ↑ 运行时不带 &: 等待用户在浏览器中点击批准/发送反馈
# 2. 检查结果并分支
if python3 -c "
import json, sys
try:
d = json.load(open('$FEEDBACK_FILE'))
sys.exit(0 if d.get('approved') is True else 1)
except Exception:
sys.exit(1)
" 2>/dev/null; then
echo "PLAN_APPROVED" # → 进入 EXECUTE 步骤
else
echo "PLAN_FEEDBACK" # → 读取 \"$FEEDBACK_FILE\",重新规划,重复上述步骤
fi
重要 : 不要使用
&(后台)运行。必须阻塞运行以接收用户反馈。
常见流程:
plan.md)"approved":true) → 进入 [2] 执行步骤/tmp/plannotator_feedback.txt 标注并重新规划(循环)plan.md 内容omg-state.json plan_approved=true, plan_gate_status="manual_approved" → EXECUTEplan.md,重试循环,重复Claude Code 手动运行:
Shift+Tab×2 → 进入计划模式 → plannotator 在计划完成时自动运行
当团队可用时 (Claude Code + omc):
/omc:team 3:executor "omg-exec: <基于已批准计划的任务>"
当 Claude Code 团队模式不可用时:
echo "❌ OMG 在 Claude Code 中需要 /omc:team。运行 bash scripts/setup-claude.sh,重启 Claude Code,然后重试。"
exit 1
当团队不可用时 (BMAD 回退 — Codex / Gemini / OpenCode):
/workflow-init # 初始化 BMAD 工作流
/workflow-status # 检查当前步骤
当存在基于浏览器的功能时,使用 agent-browser 验证行为。
# 从应用运行的 URL 捕获快照
agent-browser snapshot http://localhost:3000
# 检查特定元素(无障碍树引用方法)
agent-browser snapshot http://localhost:3000 -i
# → 使用 @eN 引用号检查元素状态
# 保存截图
agent-browser screenshot http://localhost:3000 -o verify.png
默认行为 : 当浏览器相关工作完成时,自动运行 agent-browser 验证步骤。没有浏览器 UI 的后端/CLI 任务跳过此步骤。
当检测到 annotate 关键词时,运行 agentation 监视循环。(agentui 关键词也支持以保持向后兼容性。)这遵循与 plannotator 在 planui / ExitPlanMode 中操作相同的模式。
先决条件:
npx agentation-mcp server (HTTP :4747) 正在运行<Agentation endpoint="http://localhost:4747" /> 已挂载到应用中预检(进入前必需 — 所有平台通用):
# 步骤 1: 检查服务器状态(如果未运行则优雅跳过 — 不 exit 1)
if ! curl -sf --connect-timeout 2 http://localhost:4747/health >/dev/null 2>&1; then
echo "⚠️ agentation-mcp 服务器未运行 — 跳过 VERIFY_UI 并继续到 CLEANUP"
echo " (要使用 agentation: npx agentation-mcp server)"
python3 -c "
import json,os,subprocess,fcntl,time
try:
root=subprocess.check_output(['git','rev-parse','--show-toplevel'],stderr=subprocess.DEVNULL).decode().strip()
except:
root=os.getcwd()
f=os.path.join(root,'.omc/state/omg-state.json')
if os.path.exists(f):
with open(f,'r+') as fh:
fcntl.flock(fh,fcntl.LOCK_EX)
try:
d=json.load(fh)
d['last_error']='agentation-mcp 未运行;VERIFY_UI 已跳过'
d['updated_at']=time.strftime('%Y-%m-%dT%H:%M:%SZ',time.gmtime())
fh.seek(0); json.dump(d,fh,ensure_ascii=False,indent=2); fh.truncate()
finally:
fcntl.flock(fh,fcntl.LOCK_UN)
" 2>/dev/null || true
# 继续到步骤 4
hooks: event callbacks that enforce those rules on each platformThe key OMG rules are:
plan_gate_status to pendingThe authoritative state is .omc/state/omg-state.json. Hooks may help advance the workflow, but they must obey the state file.
omg keyword detection)The following are commands, not descriptions. Execute them in order. Each step only proceeds after the previous one completes.
mkdir -p .omc/state .omc/plans .omc/logs
If .omc/state/omg-state.json does not exist, create it:
{
"phase": "plan",
"task": "<감지된 task>",
"plan_approved": false,
"plan_gate_status": "pending",
"plan_current_hash": null,
"last_reviewed_plan_hash": null,
"last_reviewed_plan_at": null,
"plan_review_method": null,
"team_available": null,
"retry_count": 0,
"last_error": null,
"checkpoint": null,
"created_at": "<ISO 8601>",
"updated_at": "<ISO 8601>",
"agentation": {
"active": false,
"session_id": null,
"keyword_used": null,
"submit_gate_status": "idle",
"submit_signal": null,
"submit_received_at": null,
"submitted_annotation_count": 0,
"started_at": null,
"timeout_seconds": 120,
"annotations": { "total": 0, "acknowledged": 0, "resolved": 0, "dismissed": 0, "pending": 0 },
"completed_at": null,
"exit_reason": null
}
}
Notify the user:
"OMG activated. Phase: PLAN. Add the
annotatekeyword if a UI feedback loop is needed."
Checkpoint recording — immediately after entering each STEP:
# Execute immediately at the start of each STEP (agent updates omg-state.json directly)
python3 -c "
import json, datetime, os, subprocess, tempfile
try:
root = subprocess.check_output(['git', 'rev-parse', '--show-toplevel'], stderr=subprocess.DEVNULL).decode().strip()
except:
root = os.getcwd()
f = os.path.join(root, '.omc/state/omg-state.json')
if os.path.exists(f):
import fcntl
with open(f, 'r+') as fh:
fcntl.flock(fh, fcntl.LOCK_EX)
try:
d = json.load(fh)
d['checkpoint']='<current_phase>' # 'plan'|'execute'|'verify'|'cleanup'
d['updated_at']=datetime.datetime.utcnow().isoformat()+'Z'
fh.seek(0)
json.dump(d, fh, ensure_ascii=False, indent=2)
fh.truncate()
finally:
fcntl.flock(fh, fcntl.LOCK_UN)
" 2>/dev/null || true
last_error recording — on pre-flight failure or exception:
python3 -c "
import json, datetime, os, subprocess, fcntl
try:
root = subprocess.check_output(['git', 'rev-parse', '--show-toplevel'], stderr=subprocess.DEVNULL).decode().strip()
except:
root = os.getcwd()
f = os.path.join(root, '.omc/state/omg-state.json')
if os.path.exists(f):
with open(f, 'r+') as fh:
fcntl.flock(fh, fcntl.LOCK_EX)
try:
d = json.load(fh)
d['last_error']='<error message>'
d['retry_count']=d.get('retry_count',0)+1
d['updated_at']=datetime.datetime.utcnow().isoformat()+'Z'
fh.seek(0)
json.dump(d, fh, ensure_ascii=False, indent=2)
fh.truncate()
finally:
fcntl.flock(fh, fcntl.LOCK_UN)
" 2>/dev/null || true
Checkpoint-based resume on restart:
# If omg-state.json already exists, resume from checkpoint
python3 -c "
import json, os, subprocess
try:
root = subprocess.check_output(['git', 'rev-parse', '--show-toplevel'], stderr=subprocess.DEVNULL).decode().strip()
except:
root = os.getcwd()
f = os.path.join(root, '.omc/state/omg-state.json')
if os.path.exists(f):
d=json.load(open(f))
cp=d.get('checkpoint')
err=d.get('last_error')
if err: print(f'Previous error: {err}')
if cp: print(f'Resuming from: {cp}')
" 2>/dev/null || true
Rule : Before
exit 1in pre-flight, always updatelast_errorand incrementretry_count. Ifretry_count >= 3, ask the user whether to abort.
Pre-flight (required before entering):
# Record checkpoint
python3 -c "
import json,datetime,os,subprocess,fcntl,tempfile
try:
root=subprocess.check_output(['git','rev-parse','--show-toplevel'],stderr=subprocess.DEVNULL).decode().strip()
except:
root=os.getcwd()
f=os.path.join(root,'.omc/state/omg-state.json')
if os.path.exists(f):
with open(f,'r+') as fh:
fcntl.flock(fh,fcntl.LOCK_EX)
try:
d=json.load(fh)
d.update({'checkpoint':'plan','updated_at':datetime.datetime.utcnow().isoformat()+'Z'})
fh.seek(0); json.dump(d,fh,ensure_ascii=False,indent=2); fh.truncate()
finally:
fcntl.flock(fh,fcntl.LOCK_UN)
" 2>/dev/null || true
# NOTE: Claude Code — skip this entire bash block.
# plannotator is a hook-only binary; calling it directly always fails.
# For Claude Code: call EnterPlanMode → write plan → call ExitPlanMode.
# The ExitPlanMode PermissionRequest hook fires plannotator automatically.
# The following script is for Codex / Gemini / OpenCode only.
# GUARD: enforce no-repeat PLAN review by plan hash.
# same hash + terminal gate status => skip reopening the plan gate
# revised plan.md content => reset gate to pending and review again
PLAN_GATE_STATUS=$(python3 -c "
import json, os
try:
s = json.load(open('.omc/state/omg-state.json'))
print(s.get('plan_gate_status', 'pending'))
except Exception:
print('pending')
" 2>/dev/null || echo "pending")
HASH_MATCH=$(python3 -c "
import hashlib, json, os
try:
s = json.load(open('.omc/state/omg-state.json'))
if not os.path.exists('plan.md'):
print('no-match')
else:
current_hash = hashlib.sha256(open('plan.md', 'rb').read()).hexdigest()
print('match' if current_hash == (s.get('last_reviewed_plan_hash') or '') else 'no-match')
except Exception:
print('no-match')
" 2>/dev/null || echo "no-match")
if [[ "$HASH_MATCH" == "match" && "$PLAN_GATE_STATUS" =~ ^(approved|manual_approved|feedback_required|infrastructure_blocked)$ ]]; then
echo "✅ Current plan hash already has gate result: $PLAN_GATE_STATUS. Do not reopen plannotator."
exit 0
fi
# plannotator is mandatory for the PLAN step (Codex/Gemini/OpenCode).
# If missing, OMG auto-installs it before opening the PLAN gate.
# Resolve the OMG scripts directory (works from any CWD)
_OMG_SCRIPTS=""
for _candidate in \
"${OMG_SKILL_DIR:-}/scripts" \
"$HOME/.agent-skills/omg/scripts" \
"$HOME/.codex/skills/omg/scripts" \
"$(pwd)/.agent-skills/omg/scripts" \
"scripts" \
; do
if [ -f "${_candidate}/plannotator-plan-loop.sh" ]; then
_OMG_SCRIPTS="$_candidate"
break
fi
done
if [ -z "$_OMG_SCRIPTS" ]; then
echo "❌ OMG scripts not found. Re-run: bash setup-codex.sh (or setup-gemini.sh)"
exit 1
fi
if ! bash "${_OMG_SCRIPTS}/ensure-plannotator.sh"; then
echo "❌ plannotator auto-install failed: cannot proceed with PLAN step."
echo " Retry: bash ${_OMG_SCRIPTS}/../scripts/install.sh --with-plannotator"
exit 1
fi
# Required PLAN gate (Codex / Gemini / OpenCode):
# - Must wait until approve/feedback is received
# - Auto-restart on session exit (up to 3 times)
# - After 3 exits, ask user whether to end PLAN
FEEDBACK_DIR=$(python3 -c "import hashlib,os; h=hashlib.md5(os.getcwd().encode()).hexdigest()[:8]; d=f'/tmp/omg-{h}'; os.makedirs(d,exist_ok=True); print(d)" 2>/dev/null || echo '/tmp')
FEEDBACK_FILE="${FEEDBACK_DIR}/plannotator_feedback.txt"
bash "${_OMG_SCRIPTS}/plannotator-plan-loop.sh" plan.md "$FEEDBACK_FILE" 3
PLAN_RC=$?
if [ "$PLAN_RC" -eq 0 ]; then
echo "✅ Plan approved"
elif [ "$PLAN_RC" -eq 10 ]; then
echo "❌ Plan not approved — apply feedback, revise plan.md, and retry"
exit 1
elif [ "$PLAN_RC" -eq 32 ]; then
echo "⚠️ plannotator UI unavailable (sandbox/CI). Entering Conversation Approval Mode:"
echo " 1. Output plan.md content to user in conversation"
echo " 2. Ask user: 'approve' to proceed or provide feedback"
echo " 3. DO NOT proceed to EXECUTE until user explicitly approves"
exit 32
elif [ "$PLAN_RC" -eq 30 ] || [ "$PLAN_RC" -eq 31 ]; then
echo "⛔ PLAN exit decision (or awaiting confirmation). Confirm with user before retrying."
exit 1
else
echo "❌ plannotator PLAN gate failed (code=$PLAN_RC)"
exit 1
fi
mkdir -p .omc/plans .omc/logs
plan.md (include goal, steps, risks, and completion criteria)Claude Code (hook mode — only supported method) : plannotator is a hook-only binary. It cannot be called via MCP tool or CLI directly. Call EnterPlanMode, write the plan content in plan mode, then call ExitPlanMode. The ExitPlanMode PermissionRequest hook fires the OMG Claude plan-gate wrapper automatically. That wrapper must skip re-entry when the current plan hash already has a terminal review result. Wait for the hook to return before proceeding — approved or feedback will arrive via the hook result.
Codex / Gemini / OpenCode : run blocking CLI (never use &):
# _OMG_SCRIPTS must be resolved first via the dynamic path discovery block in the pre-flight above
bash "${_OMG_SCRIPTS}/plannotator-plan-loop.sh" plan.md /tmp/plannotator_feedback.txt 3
If plannotator is missing, OMG must auto-run bash "${_OMG_SCRIPTS}/ensure-plannotator.sh" first and continue only after the CLI is available.
3. Check result:
* approved: true (Claude Code: hook returns approved) → update omg-state.json phase to "execute" and plan_approved to true → enter STEP 2
* Not approved (Claude Code: hook returns feedback; others: exit 10) → read feedback, revise plan.md → repeat step 2
* Infrastructure blocked (exit 32) → localhost bind unavailable (e.g., sandbox/CI). Use manual gate in TTY; confirm with user and retry outside sandbox in non-TTY
* Session exited 3 times (exit 30/31) → ask user whether to end PLAN and decide to abort or resume
NEVER: enter EXECUTE withoutapproved: true. NEVER: run with & background. NEVER: reopen the same unchanged plan afterapproved, manual_approved, feedback_required, or infrastructure_blocked.
Pre-flight (auto-detect team availability):
# Record checkpoint
python3 -c "
import json,datetime,os,subprocess,fcntl
try:
root=subprocess.check_output(['git','rev-parse','--show-toplevel'],stderr=subprocess.DEVNULL).decode().strip()
except:
root=os.getcwd()
f=os.path.join(root,'.omc/state/omg-state.json')
if os.path.exists(f):
with open(f,'r+') as fh:
fcntl.flock(fh,fcntl.LOCK_EX)
try:
d=json.load(fh)
d.update({'checkpoint':'execute','updated_at':datetime.datetime.utcnow().isoformat()+'Z'})
fh.seek(0); json.dump(d,fh,ensure_ascii=False,indent=2); fh.truncate()
finally:
fcntl.flock(fh,fcntl.LOCK_UN)
" 2>/dev/null || true
TEAM_AVAILABLE=false
if [[ "${CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS:-}" =~ ^(1|true|True|yes|YES)$ ]]; then
TEAM_AVAILABLE=true
elif python3 -c "
import json, os, sys
try:
s = json.load(open(os.path.expanduser('~/.claude/settings.json')))
val = s.get('env', {}).get('CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS', '')
sys.exit(0 if str(val) in ('1', 'true', 'True', 'yes') else 1)
except Exception:
sys.exit(1)
" 2>/dev/null; then
TEAM_AVAILABLE=true
fi
export TEAM_AVAILABLE_BOOL="$TEAM_AVAILABLE"
python3 -c "
import json,os,subprocess,fcntl
try:
root=subprocess.check_output(['git','rev-parse','--show-toplevel'],stderr=subprocess.DEVNULL).decode().strip()
except:
root=os.getcwd()
f=os.path.join(root,'.omc/state/omg-state.json')
if os.path.exists(f):
with open(f,'r+') as fh:
fcntl.flock(fh,fcntl.LOCK_EX)
try:
d=json.load(fh)
d['team_available']=os.environ.get('TEAM_AVAILABLE_BOOL','false').lower()=='true'
fh.seek(0); json.dump(d,fh,ensure_ascii=False,indent=2); fh.truncate()
finally:
fcntl.flock(fh,fcntl.LOCK_UN)
" 2>/dev/null || true
Update omg-state.json phase to "execute"
Team available (Claude Code + omc) :
/omc:team 3:executor "<task>"
Claude Code but no team :
echo "❌ OMG requires Claude Code team mode. Re-run bash scripts/setup-claude.sh, restart Claude Code, and confirm CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1."
exit 1
Never fall back to single-agent execution in Claude Code. 4. No omc (BMAD fallback — Codex / Gemini / OpenCode only) :
/workflow-init # Initialize BMAD
/workflow-status # Check current step
Update omg-state.json phase to "verify"
Basic verification with agent-browser (when browser UI is present):
agent-browser snapshot http://localhost:3000
annotate keyword detected → enter STEP 3.1
Otherwise → enter STEP 4
annotate keyword is detected)Pre-flight check (required before entering):
if ! curl -sf --connect-timeout 2 http://localhost:4747/health >/dev/null 2>&1; then
echo "⚠️ agentation-mcp server not running — skipping VERIFY_UI and proceeding to CLEANUP"
python3 -c "
import json,os,subprocess,fcntl,time try: root=subprocess.check_output(['git','rev-parse','--show-toplevel'],stderr=subprocess.DEVNULL).decode().strip() except: root=os.getcwd() f=os.path.join(root,'.omc/state/omg-state.json') if os.path.exists(f): with open(f,'r+') as fh: fcntl.flock(fh,fcntl.LOCK_EX) try: d=json.load(fh) d['last_error']='agentation-mcp not running; VERIFY_UI skipped' d['updated_at']=time.strftime('%Y-%m-%dT%H:%M:%SZ',time.gmtime()) fh.seek(0); json.dump(d,fh,ensure_ascii=False,indent=2); fh.truncate() finally: fcntl.flock(fh,fcntl.LOCK_UN) " 2>/dev/null || true # Proceed to STEP 4 CLEANUP (no exit 1 — graceful skip) fi
2. Update `omg-state.json`: `phase = "verify_ui"`, `agentation.active = true`, `agentation.submit_gate_status = "waiting_for_submit"`
3. Wait for explicit human submit:
- **Claude Code**: wait for `UserPromptSubmit` after the user presses **Send Annotations** / `onSubmit`
- **Codex / Gemini / OpenCode**: wait until the human confirms submission and the agent emits `ANNOTATE_READY` (or compatibility alias `AGENTUI_READY`)
4. Before that submit signal arrives, do not read `/pending`, do not acknowledge annotations, and do not start the fix loop
5. After submit arrives, switch `agentation.submit_gate_status = "submitted"` and record `submit_signal`, `submit_received_at`, and `submitted_annotation_count`
6. **Claude Code (MCP)**: blocking call to `agentation_watch_annotations` (`batchWindowSeconds:10`, `timeoutSeconds:120`)
7. **Codex / Gemini / OpenCode (HTTP)**: polling loop via `GET http://localhost:4747/pending`
8. Process each annotation: `acknowledge` → navigate code via `elementPath` → apply fix → `resolve`
9. `count=0` or timeout → reset the submit gate or finish the sub-phase → **enter STEP 4**
**NEVER: process draft annotations before submit/onSubmit.**
---
### STEP 4: CLEANUP
**Pre-flight (check before entering):**
```bash
# Record checkpoint
python3 -c "
import json,datetime,os,subprocess,fcntl
try:
root=subprocess.check_output(['git','rev-parse','--show-toplevel'],stderr=subprocess.DEVNULL).decode().strip()
except:
root=os.getcwd()
f=os.path.join(root,'.omc/state/omg-state.json')
if os.path.exists(f):
with open(f,'r+') as fh:
fcntl.flock(fh,fcntl.LOCK_EX)
try:
d=json.load(fh)
d.update({'checkpoint':'cleanup','updated_at':datetime.datetime.utcnow().isoformat()+'Z'})
fh.seek(0); json.dump(d,fh,ensure_ascii=False,indent=2); fh.truncate()
finally:
fcntl.flock(fh,fcntl.LOCK_UN)
" 2>/dev/null || true
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
echo "⚠️ Not a git repository — skipping worktree cleanup"
else
UNCOMMITTED=$(git status --porcelain 2>/dev/null | wc -l | tr -d ' ')
[[ "$UNCOMMITTED" -gt 0 ]] && echo "⚠️ ${UNCOMMITTED} uncommitted change(s) — recommend commit/stash before cleanup"
fi
Update omg-state.json phase to "cleanup"
Worktree cleanup:
bash scripts/worktree-cleanup.sh || git worktree prune
Update omg-state.json phase to "done"
Source of truth :
https://github.com/supercent-io/skills-templateLocal paths like~/.claude/skills/omg/are copies installed vianpx skills add. To update to the latest version, reinstall using the command below.
# Install OMG (npx skills add — recommended)
npx skills add https://github.com/supercent-io/skills-template --skill omg
# Full install (all AI tools + all components)
bash scripts/install.sh --all
# Check status
bash scripts/check-status.sh
# Individual AI tool setup
bash scripts/setup-claude.sh # Claude Code plugin + hooks
bash scripts/setup-codex.sh # Codex CLI developer_instructions
bash scripts/setup-gemini.sh # Gemini CLI hooks + GEMINI.md
bash scripts/setup-opencode.sh # OpenCode plugin registration
Tools that OMG installs and configures:
| Tool | Description | Install Command |
|---|---|---|
| omc (oh-my-claudecode) | Claude Code multi-agent orchestration | /plugin marketplace add https://github.com/Yeachan-Heo/oh-my-claudecode |
| omx | Multi-agent orchestration for OpenCode | bunx oh-my-opencode setup |
| ohmg | Multi-agent framework for Gemini CLI | bunx oh-my-ag |
| bmad | BMAD workflow orchestration | Included in skills |
| ralph | Self-referential completion loop | Included in omc or install separately |
| plannotator | Visual plan/diff review | Auto-installed during PLAN via bash scripts/ensure-plannotator.sh (or preinstall with bash scripts/install.sh --with-plannotator) |
| agentation | UI annotation → agent code fix integration (annotate keyword, agentui compatibility maintained) | bash scripts/install.sh --with-agentation |
| agent-browser | Headless browser for AI agents — primary tool for browser behavior verification | npm install -g agent-browser |
| playwriter | Playwright-based browser automation (optional) | npm install -g playwriter |
omg "<task>"
│
▼
[1] PLAN (ralph + plannotator)
Draft plan with ralph → visual review with plannotator → Approve/Feedback
│
▼
[2] EXECUTE
├─ team available? → /omc:team N:executor "<task>"
│ staged pipeline: plan→prd→exec→verify→fix
└─ no team? → /bmad /workflow-init → run BMAD steps
│
▼
[3] VERIFY (agent-browser — default behavior)
Verify browser behavior with agent-browser
→ capture snapshot → confirm UI/functionality is working
│
├─ with annotate keyword → [3.3.1] VERIFY_UI (agentation watch loop)
│ agentation_watch_annotations blocking → annotation ack→fix→resolve loop
│
▼
[4] CLEANUP
After all work is done → bash scripts/worktree-cleanup.sh
git worktree prune
Platform note : The
/ralphslash command is only available in Claude Code (omc). Use the "alternative method" below for Codex/Gemini/OpenCode.
Claude Code (omc):
/ralph "omg-plan: <task>" --completion-promise="PLAN_APPROVED" --max-iterations=5
Codex / Gemini / OpenCode (alternative):
# Session-isolated feedback directory (prevents concurrent run conflicts)
FEEDBACK_DIR=$(python3 -c "import hashlib,os; h=hashlib.md5(os.getcwd().encode()).hexdigest()[:8]; d=f'/tmp/omg-{h}'; os.makedirs(d,exist_ok=True); print(d)" 2>/dev/null || echo '/tmp')
FEEDBACK_FILE="${FEEDBACK_DIR}/plannotator_feedback.txt"
# 1. Write plan.md directly, then review with plannotator (blocking — no &)
PLANNOTATOR_RUNTIME_HOME="${FEEDBACK_DIR}/.plannotator"
mkdir -p "$PLANNOTATOR_RUNTIME_HOME"
touch /tmp/omg-plannotator-direct.lock && python3 -c "
import json
print(json.dumps({'tool_input': {'plan': open('plan.md').read(), 'permission_mode': 'acceptEdits'}}))
" | env HOME="$PLANNOTATOR_RUNTIME_HOME" PLANNOTATOR_HOME="$PLANNOTATOR_RUNTIME_HOME" plannotator > "$FEEDBACK_FILE" 2>&1
# ↑ Run without &: waits until user clicks Approve/Send Feedback in browser
# 2. Check result and branch
if python3 -c "
import json, sys
try:
d = json.load(open('$FEEDBACK_FILE'))
sys.exit(0 if d.get('approved') is True else 1)
except Exception:
sys.exit(1)
" 2>/dev/null; then
echo "PLAN_APPROVED" # → enter EXECUTE step
else
echo "PLAN_FEEDBACK" # → read \"$FEEDBACK_FILE\", replan, repeat above
fi
Important : Do not run with
&(background). Must run blocking to receive user feedback.
Common flow:
plan.md)"approved":true) → enter [2] EXECUTE step/tmp/plannotator_feedback.txt annotations and replan (loop)plan.md content to useromg-state.json plan_approved=true, plan_gate_status="manual_approved" → EXECUTEplan.md, retry loop, repeatClaude Code manual run:
Shift+Tab×2 → enter plan mode → plannotator runs automatically when plan is complete
When team is available (Claude Code + omc):
/omc:team 3:executor "omg-exec: <task based on approved plan>"
When Claude Code team mode is unavailable:
echo "❌ OMG requires /omc:team in Claude Code. Run bash scripts/setup-claude.sh, restart Claude Code, then retry."
exit 1
When team is unavailable (BMAD fallback — Codex / Gemini / OpenCode):
/workflow-init # Initialize BMAD workflow
/workflow-status # Check current step
When browser-based functionality is present, verify behavior with agent-browser.
# Capture snapshot from the URL where the app is running
agent-browser snapshot http://localhost:3000
# Check specific elements (accessibility tree ref method)
agent-browser snapshot http://localhost:3000 -i
# → check element state using @eN ref numbers
# Save screenshot
agent-browser screenshot http://localhost:3000 -o verify.png
Default behavior : Automatically runs the agent-browser verification step when browser-related work is complete. Backend/CLI tasks without a browser UI skip this step.
Runs the agentation watch loop when the annotate keyword is detected. (The agentui keyword is also supported for backward compatibility.) This follows the same pattern as plannotator operating in planui / ExitPlanMode.
Prerequisites:
npx agentation-mcp server (HTTP :4747) is running<Agentation endpoint="http://localhost:4747" /> is mounted in the appPre-flight Check (required before entering — common to all platforms):
# Step 1: Check server status (graceful skip if not running — no exit 1)
if ! curl -sf --connect-timeout 2 http://localhost:4747/health >/dev/null 2>&1; then
echo "⚠️ agentation-mcp server not running — skipping VERIFY_UI and proceeding to CLEANUP"
echo " (to use agentation: npx agentation-mcp server)"
python3 -c "
import json,os,subprocess,fcntl,time
try:
root=subprocess.check_output(['git','rev-parse','--show-toplevel'],stderr=subprocess.DEVNULL).decode().strip()
except:
root=os.getcwd()
f=os.path.join(root,'.omc/state/omg-state.json')
if os.path.exists(f):
with open(f,'r+') as fh:
fcntl.flock(fh,fcntl.LOCK_EX)
try:
d=json.load(fh)
d['last_error']='agentation-mcp not running; VERIFY_UI skipped'
d['updated_at']=time.strftime('%Y-%m-%dT%H:%M:%SZ',time.gmtime())
fh.seek(0); json.dump(d,fh,ensure_ascii=False,indent=2); fh.truncate()
finally:
fcntl.flock(fh,fcntl.LOCK_UN)
" 2>/dev/null || true
# Proceed to STEP 4 CLEANUP (no exit 1 — graceful skip)
else
# Step 2: Check session existence (<Agentation> component mount status)
SESSIONS=$(curl -sf http://localhost:4747/sessions 2>/dev/null)
S_COUNT=$(echo "$SESSIONS" | python3 -c "import sys,json; print(len(json.load(sys.stdin)))" 2>/dev/null || echo 0)
[ "$S_COUNT" -eq 0 ] && echo "⚠️ No active sessions — <Agentation endpoint='http://localhost:4747' /> needs to be mounted"
echo "✅ agentation ready — server OK, ${S_COUNT} session(s)"
fi
After passing pre-flight (
elsebranch), update omg-state.jsonphaseto"verify_ui", setagentation.activetotrue, and setagentation.submit_gate_statusto"waiting_for_submit". Do not call/pendingyet. Draft annotations are not actionable until the user explicitly submits them.
Claude Code (direct MCP tool call):
# annotate keyword detected (or agentui — backward compatible)
# 1. wait for UserPromptSubmit after the user clicks Send Annotations / onSubmit
# 2. the OMG submit-gate hook records submit_gate_status="submitted"
# 3. only then run the blocking agentation watch loop
#
# batchWindowSeconds:10 — receive annotations in 10-second batches
# timeoutSeconds:120 — auto-exit after 120 seconds with no annotations
#
# Per-annotation processing loop:
# 1. agentation_acknowledge_annotation({id}) — show 'processing' in UI
# 2. navigate code via annotation.elementPath (CSS selector) → apply fix
# 3. agentation_resolve_annotation({id, summary}) — mark 'done' + save summary
#
# Loop ends when annotation count=0 or timeout
Important :
agentation_watch_annotationsis a blocking call. Do not run with&background. Same as plannotator'sapproved:trueloop: annotation count=0 or timeout = completion signal.annotateis the primary keyword.agentuiis a backward-compatible alias and behaves identically.
Codex / Gemini / OpenCode (HTTP REST API fallback):
START_TIME=$(date +%s)
TIMEOUT_SECONDS=120
# Required gate: do not enter the loop until the human has clicked Send Annotations
# and the platform has opened agentation.submit_gate_status="submitted".
while true; do
# Timeout check
NOW=$(date +%s)
ELAPSED=$((NOW - START_TIME))
if [ $ELAPSED -ge $TIMEOUT_SECONDS ]; then
echo "[OMG] agentation polling timeout (${TIMEOUT_SECONDS}s) — some annotations may remain unresolved"
break
fi
SUBMIT_GATE=$(python3 -c "
import json
try:
print(json.load(open('.omc/state/omg-state.json')).get('agentation', {}).get('submit_gate_status', 'idle'))
except Exception:
print('idle')
" 2>/dev/null || echo "idle")
if [ "$SUBMIT_GATE" != "submitted" ]; then
sleep 2
continue
fi
COUNT=$(curl -sf --connect-timeout 3 --max-time 5 http://localhost:4747/pending 2>/dev/null | python3 -c "import sys,json; data=sys.stdin.read(); d=json.loads(data) if data.strip() else {}; print(d.get('count', len(d.get('annotations', [])) if isinstance(d, dict) else 0))" 2>/dev/null || echo 0)
[ "$COUNT" -eq 0 ] && break
# Process each annotation:
# a) Acknowledge (show as in-progress)
curl -X PATCH http://localhost:4747/annotations/<id> \
-H 'Content-Type: application/json' \
-d '{"status": "acknowledged"}'
# b) Navigate code via elementPath (CSS selector) → apply fix
# c) Resolve (mark done + fix summary)
curl -X PATCH http://localhost:4747/annotations/<id> \
-H 'Content-Type: application/json' \
-d '{"status": "resolved", "resolution": "<fix summary>"}'
sleep 3
done
# Runs automatically after all work is complete
bash scripts/worktree-cleanup.sh
# Individual commands
git worktree list # List current worktrees
git worktree prune # Clean up worktrees for deleted branches
bash scripts/worktree-cleanup.sh --force # Force cleanup including dirty worktrees
Default run removes only clean extra worktrees; worktrees with changes are left with a warning. Use
--forceonly after review.
# Automatic setup
bash scripts/setup-claude.sh
# Or manually:
/plugin marketplace add https://github.com/Yeachan-Heo/oh-my-claudecode
/plugin install oh-my-claudecode
/omc:omc-setup
# Add plannotator hook
bash .agent-skills/plannotator/scripts/setup-hook.sh
Config file : ~/.claude/settings.json
{
"hooks": {
"PermissionRequest": [{
"matcher": "ExitPlanMode",
"hooks": [{
"type": "command",
"command": "python3 ~/.claude/skills/omg/scripts/claude-plan-gate.py",
"timeout": 1800
}]
}]
}
}
agentation MCP config (~/.claude/settings.json or .claude/mcp.json):
{
"mcpServers": {
"agentation": {
"command": "npx",
"args": ["-y", "agentation-mcp", "server"]
}
},
"hooks": {
"UserPromptSubmit": [{
"matcher": "*",
"hooks": [{
"type": "command",
"command": "python3 ~/.claude/skills/omg/scripts/claude-agentation-submit-hook.py",
"timeout": 300
}]
}]
}
}
# Automatic setup
bash scripts/setup-codex.sh
# What gets configured:
# - developer_instructions: ~/.codex/config.toml
# - prompt file: ~/.codex/prompts/omg.md
# - notify hook: ~/.codex/hooks/omg-notify.py
# - [tui] notifications: agent-turn-complete
agentation MCP config (~/.codex/config.toml):
[mcp_servers.agentation]
command = "npx"
args = ["-y", "agentation-mcp", "server"]
notify hook (~/.codex/hooks/omg-notify.py):
PLAN_READY signal in last-assistant-message when agent turn completesplan.md exists, compares the current hash against last_reviewed_plan_hash, and skips the gate when the plan was already reviewed/tmp/plannotator_feedback.txtANNOTATE_READY signal (or backward-compatible AGENTUI_READY) only in verify_uiagentation.submit_gate_status="submitted" first, then polls http://localhost:4747/pending~/.codex/config.toml config:
developer_instructions = """
# OMG Orchestration Workflow
# ...
"""
notify = ["python3", "~/.codex/hooks/omg-notify.py"]
[tui]
notifications = ["agent-turn-complete"]
notification_method = "osc9"
developer_instructionsmust be a top-level string. Writing it as a[developer_instructions]table may cause Codex to fail on startup withinvalid type: map, expected a string.notifyand[tui].notificationsmust also be set correctly for the PLAN/ANNOTATE follow-up loop to actually work.
Using in Codex:
/prompts:omg # Activate OMG workflow
# Agent writes plan.md and outputs "PLAN_READY" → notify hook runs automatically
# Automatic setup
bash scripts/setup-gemini.sh
# What gets configured:
# - AfterAgent backup hook: ~/.gemini/hooks/omg-plannotator.sh
# - Instructions (MANDATORY loop): ~/.gemini/GEMINI.md
Key principle : The agent must call plannotator directly in blocking mode to receive feedback in the same turn. The AfterAgent hook serves only as a safety net (runs after turn ends → injected in next turn).
AfterAgent backup hook (~/.gemini/settings.json):
{
"hooks": {
"AfterAgent": [{
"matcher": "",
"hooks": [{
"name": "plannotator-review",
"type": "command",
"command": "bash ~/.gemini/hooks/omg-plannotator.sh",
"description": "Run plannotator when plan.md is detected (AfterAgent backup)"
}]
}]
}
}
PLAN instructions added to GEMINI.md (mandatory loop) :
1. plan.md 작성
2. plannotator blocking 실행 (& 금지) → /tmp/plannotator_feedback.txt
3. approved=true → EXECUTE / 미승인 → 수정 후 2번 반복
NEVER proceed to EXECUTE without approved=true.
agentation MCP config (~/.gemini/settings.json):
{
"mcpServers": {
"agentation": {
"command": "npx",
"args": ["-y", "agentation-mcp", "server"]
}
}
}
Note : Gemini CLI hook events use
BeforeToolandAfterAgent.ExitPlanModeis a Claude Code-only hook.
# Automatic setup
bash scripts/setup-opencode.sh
# Added to opencode.json:
# "@plannotator/opencode@latest" plugin
# "@oh-my-opencode/opencode@latest" plugin (omx)
OpenCode slash commands:
/omg-plan — plan with ralph + plannotator/omg-exec — execute with team/bmad/omg-annotate — start agentation watch loop (annotate; /omg-agentui is a deprecated alias)/omg-cleanup — worktree cleanupplannotator integration (MANDATORY blocking loop):
# Write plan.md then run PLAN gate (no &) — receive feedback in same turn
bash scripts/plannotator-plan-loop.sh plan.md /tmp/plannotator_feedback.txt 3
# - Must wait until approve/feedback is received
# - Auto-restart on session exit (up to 3 times)
# - After 3 exits, confirm with user whether to abort or resume
# - exit 32 if localhost bind unavailable (replace with manual gate in TTY)
# Branch based on result
# approved=true → enter EXECUTE
# not approved → apply feedback, revise plan.md → repeat above
agentation MCP config (opencode.json):
{
"mcp": {
"agentation": {
"type": "local",
"command": ["npx", "-y", "agentation-mcp", "server"]
}
}
}
OMG stores state at the following paths:
{worktree}/.omc/state/omg-state.json # OMG execution state
{worktree}/.omc/plans/omg-plan.md # Approved plan
{worktree}/.omc/logs/omg-*.log # Execution logs
State file structure:
{
"mode": "omg",
"phase": "plan|execute|verify|verify_ui|cleanup|done",
"session_id": "<uuid>",
"task": "current task description",
"plan_approved": true,
"plan_gate_status": "pending|approved|feedback_required|infrastructure_blocked|manual_approved",
"plan_current_hash": "<sha256 or null>",
"last_reviewed_plan_hash": "<sha256 or null>",
"last_reviewed_plan_at": "2026-02-24T00:00:00Z",
"plan_review_method": "plannotator|manual|null",
"team_available": true,
"retry_count": 0,
"last_error": null,
"checkpoint": "plan|execute|verify|verify_ui|cleanup",
"created_at": "2026-02-24T00:00:00Z",
"updated_at": "2026-02-24T00:00:00Z",
"agentation": {
"active": false,
"session_id": null,
"keyword_used": null,
"submit_gate_status": "idle|waiting_for_submit|submitted",
"submit_signal": "claude-user-prompt-submit|codex-notify|gemini-manual|null",
"submit_received_at": "2026-02-24T00:00:00Z",
"submitted_annotation_count": 0,
"started_at": null,
"timeout_seconds": 120,
"annotations": {
"total": 0, "acknowledged": 0, "resolved": 0, "dismissed": 0, "pending": 0
},
"completed_at": null,
"exit_reason": null
}
}
agentation fields :
active— whether the watch loop is running (used as hook guard),session_id— for resuming,submit_gate_status— prevents processing draft annotations before submit/onSubmit,submit_signal— which platform opened the gate,submit_received_at/submitted_annotation_count— audit trail for the submitted batch,exit_reason—"all_resolved"|"timeout"|"user_cancelled"|"error"dismissed annotations : When a user dismisses an annotation in the agentation UI (status becomes
"dismissed"), the agent should skip code changes for that annotation, incrementannotations.dismissed, and continue to the next pending annotation. Dismissed annotations are counted but not acted upon. The watch loop exits normally whenpending == 0(resolved + dismissed covers all).
plan_review_method: set to"plannotator"when approved via UI,"manual"when approved via TTY fallback gate.
cleanup_completed: set totruebyworktree-cleanup.shafter successful worktree prune.
Error recovery fields :
retry_count— number of retries after an error. Increments +1 on each pre-flight failure. Ask user to confirm if>= 3.last_error— most recent error message. Used to identify the cause on restart.checkpoint— last phase that was started. Resume from this phase on restart (plan|execute|verify|cleanup).
Checkpoint-based resume flow:
# Check checkpoint on restart
python3 -c "
import json, os, subprocess
try:
root = subprocess.check_output(['git', 'rev-parse', '--show-toplevel'], stderr=subprocess.DEVNULL).decode().strip()
except:
root = os.getcwd()
f = os.path.join(root, '.omc/state/omg-state.json')
if os.path.exists(f):
d=json.load(open(f))
cp=d.get('checkpoint')
err=d.get('last_error')
rc=d.get('retry_count',0)
print(f'Resume from: {cp or \"beginning\"}')
if err: print(f'Previous error ({rc} time(s)): {err}')
if rc >= 3: print('⚠️ Retry count exceeded 3 — user confirmation required')
"
Restore after restart:
# Check status and resume
bash scripts/check-status.sh --resume
# Step 1: Install (once)
bash scripts/install.sh --all
bash scripts/check-status.sh
# Step 2: Start work
omg "<task description>" # Activate with keyword
# Or in Claude: Shift+Tab×2 → plan mode
# Step 3: Review plan with plannotator
# Approve or Send Feedback in browser UI
# Step 4: Automatic execution
# team or bmad handles the work
# Step 5: Cleanup after completion
bash scripts/worktree-cleanup.sh
worktree-cleanup.sh immediately after work completes (prevents branch pollution).omc/state/omg-state.json to maintain state across sessionsannotate keyword to run the agentation watch loop for complex UI changes (precise code changes via CSS selector). agentui is a backward-compatible alias.| Issue | Solution |
|---|---|
| plannotator not running | OMG first auto-runs bash scripts/ensure-plannotator.sh; if it still fails, run bash .agent-skills/plannotator/scripts/check-status.sh |
| plannotator not opening in Claude Code | plannotator is hook-only. Do NOT call it via MCP or CLI. Use EnterPlanMode → write plan → ExitPlanMode; the hook fires automatically. Verify hook is set: `cat ~/.claude/settings.json |
| plannotator feedback not received | Remove & background execution → run blocking, then check /tmp/plannotator_feedback.txt (Codex/Gemini/OpenCode only) |
| Codex에서 같은 plan이 반복해서 재검토됨 | omg-state.json의 last_reviewed_plan_hash와 현재 plan.md hash를 비교. 같고 plan_gate_status가 terminal이면 재실행 금지 |
Codex startup failure (invalid type: map, expected a string) | Re-run bash scripts/setup-codex.sh and confirm developer_instructions in ~/.codex/config.toml is a top-level string |
| Gemini feedback loop missing | Add blocking direct call instruction to ~/.gemini/GEMINI.md |
| worktree conflict | git worktree prune && git worktree list |
| team mode not working | OMG requires team mode in Claude Code. Run bash scripts/setup-claude.sh, restart Claude Code, and verify CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 before retrying |
| omc install failed | Run /omc:omc-doctor |
| agent-browser error | Check agent-browser --version |
| annotate (agentation) not opening | Check curl http://localhost:4747/health and curl http://localhost:4747/sessions. OMG waits for explicit submit/onSubmit before polling /pending |
| annotation not reflected in code | Confirm summary field is present when calling agentation_resolve_annotation |
agentui keyword not activating | Use the annotate keyword (new). agentui is a deprecated alias but still works. |
| MCP tool not registered (Codex/Gemini) | Re-run bash scripts/setup-codex.sh / setup-gemini.sh |
annotate; agentui backward compatible)Weekly Installs
1
Repository
First Seen
1 day ago
Security Audits
Installed on
mcpjam1
claude-code1
replit1
junie1
windsurf1
zencoder1
Azure Data Explorer (Kusto) 查询技能:KQL数据分析、日志遥测与时间序列处理
119,800 周安装
DeepSpeed 开发助手:官方文档指南、API 使用与性能优化教程
207 周安装
utrace-analysis - GitHub API 代码分析与追踪工具 | 开源项目监控与调试
1 周安装
s8blame - Git 代码责任追踪工具 | 开发调试与团队协作必备
1 周安装
read-email API 技能:通过 API/Git 读取邮件的自动化工具,提升开发效率
1 周安装
qsec-wechat-export:微信数据导出工具,支持API与Git集成,高效管理聊天记录
1 周安装
popo-richtext - 富文本编辑与处理工具,支持API集成与Git版本控制
1 周安装