gstack

gstack

热门

gstack Skill 套件的路由分发器。(gstack)

12万Star
1.8万Fork
更新于 2026/7/2
SKILL.md
只读
名称
gstack
描述

gstack Skill 套件的路由分发器。(gstack)

版本
1.2.0

<!-- AUTO-GENERATED from SKILL.md.tmpl — do not edit directly -->
<!-- Regenerate: bun run gen:skill-docs -->

何时调用此 Skill

将任意 gstack 请求分发给合适的 Skill(涵盖规划、评审、QA 测试、发布部署、调试、文档编写、安全、设计等)。若涉及浏览器/QA 测试及吃狗粮测试(dogfooding),它会引导使用 /browse。当你直接调用 gstack 但未指定具体的 Skill,或询问“哪个 gstack Skill 适合这个任务?”时使用。

预置命令(优先运行)

_UPD=$(~/.claude/skills/gstack/bin/gstack-update-check 2>/dev/null || .claude/skills/gstack/bin/gstack-update-check 2>/dev/null || true)
[ -n "$_UPD" ] && echo "$_UPD" || true
mkdir -p ~/.gstack/sessions
touch ~/.gstack/sessions/"$PPID"
_SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ')
find ~/.gstack/sessions -mmin +120 -type f -exec rm {} + 2>/dev/null || true
_PROACTIVE=$(~/.claude/skills/gstack/bin/gstack-config get proactive 2>/dev/null || echo "true")
_PROACTIVE_PROMPTED=$([ -f ~/.gstack/.proactive-prompted ] && echo "yes" || echo "no")
_BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
echo "BRANCH: $_BRANCH"
_SKILL_PREFIX=$(~/.claude/skills/gstack/bin/gstack-config get skill_prefix 2>/dev/null || echo "false")
echo "PROACTIVE: $_PROACTIVE"
echo "PROACTIVE_PROMPTED: $_PROACTIVE_PROMPTED"
echo "SKILL_PREFIX: $_SKILL_PREFIX"
source <(~/.claude/skills/gstack/bin/gstack-repo-mode 2>/dev/null) || true
REPO_MODE=${REPO_MODE:-unknown}
echo "REPO_MODE: $REPO_MODE"
_SESSION_KIND=$(~/.claude/skills/gstack/bin/gstack-session-kind 2>/dev/null || echo "interactive")
case "$_SESSION_KIND" in spawned|headless|interactive) ;; *) _SESSION_KIND="interactive" ;; esac
echo "SESSION_KIND: $_SESSION_KIND"
# Conductor host: AskUserQuestion is unreliable here (native disabled, MCP
# variant flaky), so skills render decisions as prose instead of calling the
# tool. Gated on !headless so an eval/CI run INSIDE Conductor (GSTACK_HEADLESS)
# still BLOCKs rather than rendering prose to nobody.
if [ "$_SESSION_KIND" != "headless" ] && { [ -n "${CONDUCTOR_WORKSPACE_PATH:-}" ] || [ -n "${CONDUCTOR_PORT:-}" ]; }; then
  echo "CONDUCTOR_SESSION: true"
fi
_ACTIVATED=$([ -f ~/.gstack/.activated ] && echo "yes" || echo "no")
_FIRST_LOOP_SHOWN=$([ -f ~/.gstack/.first-loop-tip-shown ] && echo "yes" || echo "no")
echo "ACTIVATED: $_ACTIVATED"
echo "FIRST_LOOP_SHOWN: $_FIRST_LOOP_SHOWN"
# First-run project detection: run the detector ONLY on the first-ever skill run
# (ACTIVATED=no, interactive) so it stays off the hot path for every run after.
_FIRST_TASK=""
if [ "$_ACTIVATED" = "no" ] && [ "$_SESSION_KIND" != "headless" ]; then
  _FIRST_TASK=$(~/.claude/skills/gstack/bin/gstack-first-task-detect 2>/dev/null || true)
fi
echo "FIRST_TASK: $_FIRST_TASK"
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
echo "LAKE_INTRO: $_LAKE_SEEN"
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
_TEL_START=$(date +%s)
_SESSION_ID="$$-$(date +%s)"
echo "TELEMETRY: ${_TEL:-off}"
echo "TEL_PROMPTED: $_TEL_PROMPTED"
_EXPLAIN_LEVEL=$(~/.claude/skills/gstack/bin/gstack-config get explain_level 2>/dev/null || echo "default")
if [ "$_EXPLAIN_LEVEL" != "default" ] && [ "$_EXPLAIN_LEVEL" != "terse" ]; then _EXPLAIN_LEVEL="default"; fi
echo "EXPLAIN_LEVEL: $_EXPLAIN_LEVEL"
_QUESTION_TUNING=$(~/.claude/skills/gstack/bin/gstack-config get question_tuning 2>/dev/null || echo "false")
echo "QUESTION_TUNING: $_QUESTION_TUNING"
mkdir -p ~/.gstack/analytics
if [ "$_TEL" != "off" ]; then
echo '{"skill":"gstack","ts":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","repo":"'$(_repo=$(basename "$(git rev-parse --show-toplevel 2>/dev/null)" 2>/dev/null | tr -cd 'a-zA-Z0-9._-'); echo "${_repo:-unknown}")'"}'  >> ~/.gstack/analytics/skill-usage.jsonl 2>/dev/null || true
fi
for _PF in $(find ~/.gstack/analytics -maxdepth 1 -name '.pending-*' 2>/dev/null); do
  if [ -f "$_PF" ]; then
    if [ "$_TEL" != "off" ] && [ -x "~/.claude/skills/gstack/bin/gstack-telemetry-log" ]; then
      ~/.claude/skills/gstack/bin/gstack-telemetry-log --event-type skill_run --skill _pending_finalize --outcome unknown --session-id "$_SESSION_ID" 2>/dev/null || true
    fi
    rm -f "$_PF" 2>/dev/null || true
  fi
  break
done
eval "$(~/.claude/skills/gstack/bin/gstack-slug 2>/dev/null)" 2>/dev/null || true
_LEARN_FILE="${GSTACK_HOME:-$HOME/.gstack}/projects/${SLUG:-unknown}/learnings.jsonl"
if [ -f "$_LEARN_FILE" ]; then
  _LEARN_COUNT=$(wc -l < "$_LEARN_FILE" 2>/dev/null | tr -d ' ')
  echo "LEARNINGS: $_LEARN_COUNT entries loaded"
  if [ "$_LEARN_COUNT" -gt 5 ] 2>/dev/null; then
    ~/.claude/skills/gstack/bin/gstack-learnings-search --limit 3 2>/dev/null || true
  fi
else
  echo "LEARNINGS: 0"
fi
~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"gstack","event":"started","branch":"'"$_BRANCH"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null &
_HAS_ROUTING="no"
if [ -f CLAUDE.md ] && grep -q "## Skill routing" CLAUDE.md 2>/dev/null; then
  _HAS_ROUTING="yes"
fi
_ROUTING_DECLINED=$(~/.claude/skills/gstack/bin/gstack-config get routing_declined 2>/dev/null || echo "false")
echo "HAS_ROUTING: $_HAS_ROUTING"
echo "ROUTING_DECLINED: $_ROUTING_DECLINED"
_VENDORED="no"
if [ -d ".claude/skills/gstack" ] && [ ! -L ".claude/skills/gstack" ]; then
  if [ -f ".claude/skills/gstack/VERSION" ] || [ -d ".claude/skills/gstack/.git" ]; then
    _VENDORED="yes"
  fi
fi
echo "VENDORED_GSTACK: $_VENDORED"
echo "MODEL_OVERLAY: claude"
_CHECKPOINT_MODE=$(~/.claude/skills/gstack/bin/gstack-config get checkpoint_mode 2>/dev/null || echo "explicit")
_CHECKPOINT_PUSH=$(~/.claude/skills/gstack/bin/gstack-config get checkpoint_push 2>/dev/null || echo "false")
echo "CHECKPOINT_MODE: $_CHECKPOINT_MODE"
echo "CHECKPOINT_PUSH: $_CHECKPOINT_PUSH"
# Plan-mode hint for skills like /spec that branch behavior on plan-mode state.
# Claude Code exposes plan mode via system reminders; we detect best-effort
# from CLAUDE_PLAN_FILE (set by the harness when plan mode is active) and
# fall back to "inactive". Codex hosts and Claude execution mode both end up
# inactive, which is the safe default (defaults to file+execute pipeline).
if [ -n "${CLAUDE_PLAN_FILE:-}${GSTACK_PLAN_MODE_FORCE:-}" ]; then
  export GSTACK_PLAN_MODE="active"
elif [ "${GSTACK_PLAN_MODE:-}" = "active" ]; then
  export GSTACK_PLAN_MODE="active"
else
  export GSTACK_PLAN_MODE="inactive"
fi
echo "GSTACK_PLAN_MODE: $GSTACK_PLAN_MODE"
[ -n "$OPENCLAW_SESSION" ] && echo "SPAWNED_SESSION: true" || true

Plan Mode 安全操作

在 Plan Mode(规划模式)下,由于以下操作能辅助生成规划方案,因此属于允许的操作:$B$Dcodex exec/codex review、写入 ~/.gstack/、写入规划文件(plan file),以及使用 open 打开生成的产物。

Plan Mode 期间调用 Skill

如果用户在 Plan Mode 期间调用了某个 Skill,则该 Skill 拥有优先于通用 Plan Mode 行为的执行权。请将 Skill 文件视作可执行指令而非参考文档。 从步骤 0 开始逐步执行;其中首次调用 AskUserQuestion 代表工作流开始进入 Plan Mode,并不违背该模式的要求。AskUserQuestion(无论任何变体——mcp__*__AskUserQuestion 或原生组件;详见“AskUserQuestion 格式 → 工具解析”)可满足 Plan Mode 的回合结束(end-of-turn)要求。若 AskUserQuestion 不可用或调用失败,请遵循 AskUserQuestion 格式的降级方案:headless(无头模式)→ 阻断(BLOCKED);interactive(交互模式)→ 降级为纯文本提示(同样满足回合结束要求)。一旦遇到 STOP 节点,须立即停止,切勿在此处继续执行工作流或调用 ExitPlanMode。标有“PLAN MODE EXCEPTION — ALWAYS RUN”(Plan Mode 特例—始终运行)的命令照常执行。仅在 Skill 工作流彻底完成,或者用户显式指示取消 Skill/退出 Plan Mode 时,才可调用 ExitPlanMode。

如果 PROACTIVE"false",请勿主动调用或推荐 Skill。如果发现某 Skill 可能会有帮助,可询问用户:“我觉得 /skillname 对当前任务有帮助,需要我执行吗?”

如果 SKILL_PREFIX"true",在建议/调用时请使用 /gstack-* 前缀名称。磁盘路径依然保持 ~/.claude/skills/gstack/[skill-name]/SKILL.md 不变。

如果输出显示 UPGRADE_AVAILABLE <old> <new>:读取 ~/.claude/skills/gstack/gstack-upgrade/SKILL.md 并遵循“内联升级流程”(Inline upgrade flow,如已配置则自动升级,否则使用 AskUserQuestion 提供 4 个选项;若用户拒绝则写入暂缓提示状态)。

如果输出显示 JUST_UPGRADED <from> <to>:打印 "Running gstack v{to} (just updated!)"。如果 SPAWNED_SESSION 为 true,则跳过功能探索提示(feature discovery)。

功能探索提示(每个会话最多触发一次):

  • 缺少 ~/.claude/skills/gstack/.feature-prompted-continuous-checkpoint:使用 AskUserQuestion 询问是否开启连续检查点自动提交(Continuous checkpoint auto-commits)。若同意,运行 ~/.claude/skills/gstack/bin/gstack-config set checkpoint_mode continuous。无论结果如何,均创建(touch)该标记文件。
  • 缺少 ~/.claude/skills/gstack/.feature-prompted-model-overlay:提示 "Model overlays are active. MODEL_OVERLAY shows the patch."。无论结果如何,均创建(touch)该标记文件。

升级提示处理完成后,继续后续工作流。

如果 WRITING_STYLE_PENDINGyes:仅询问一次写作风格偏好:

v1 版本的提示词更加简洁明了:首次出现的术语提供简要注释、问题侧重于最终结果、文案更简练。是否保留当前新默认风格,还是恢复精简模式(terse)?

选项:

  • A) 保留新默认设置(推荐 — 优秀的文案体验对所有人都有益)
  • B) 恢复 V0 文案风格 — 设置 explain_level: terse

如果选择 A:保持 explain_level 未设置(默认降级为 default)。
如果选择 B:运行 ~/.claude/skills/gstack/bin/gstack-config set explain_level terse

无论做出什么选择,始终运行:

rm -f ~/.gstack/.writing-style-prompt-pending
touch ~/.gstack/.writing-style-prompted

如果 WRITING_STYLE_PENDINGno,则跳过此步骤。

如果 LAKE_INTROno:提示:"gstack 遵循 Boil the Ocean(彻底解决问题) 原则 — 在 AI 将边际成本降低至趋近于零时,就应当把事情做彻底。了解更多:https://garryslist.org/posts/boil-the-ocean",并询问是否打开网页:

open https://garryslist.org/posts/boil-the-ocean
touch ~/.gstack/.completeness-intro-seen

仅在用户同意时运行 open。始终运行 touch

如果 TEL_PROMPTEDnoLAKE_INTROyes:使用 AskUserQuestion 询问一次遥测数据收集偏好:

帮助 gstack 变得更好。仅共享使用数据:调用的 skill、运行时长、崩溃记录、稳定的设备 ID。绝不包含代码或文件路径。您的仓库名称仅在本地记录,并在上传前彻底擦除。

选项:

  • A) 帮助 gstack 变得更好!(推荐)
  • B) 不了,谢谢

如果选择 A:运行 ~/.claude/skills/gstack/bin/gstack-config set telemetry community

如果选择 B:询问追问选项:

匿名模式仅发送汇总的使用情况,不包含任何唯一设备标识符。

选项:

  • A) 没问题,匿名模式可以接受
  • B) 不了,彻底关闭遥测

如果 B→A:运行 ~/.claude/skills/gstack/bin/gstack-config set telemetry anonymous
如果 B→B:运行 ~/.claude/skills/gstack/bin/gstack-config set telemetry off

始终运行:

touch ~/.gstack/.telemetry-prompted

如果 TEL_PROMPTEDyes,则跳过此步骤。

如果 PROACTIVE_PROMPTEDnoTEL_PROMPTEDyes:询问一次:

是否允许 gstack 主动为你推荐 Skill,比如遇到“这个正常工作吗?”时推荐 /qa,遇到 Bug 时推荐 /investigate?

选项:

  • A) 保持开启(推荐)
  • B) 关闭 — 我会自己手动输入 /斜杠命令

如果选择 A:运行 ~/.claude/skills/gstack/bin/gstack-config set proactive true
如果选择 B:运行 ~/.claude/skills/gstack/bin/gstack-config set proactive false

始终运行:

touch ~/.gstack/.proactive-prompted

如果 PROACTIVE_PROMPTEDyes,则跳过此步骤。

首次运行引导(仅一次)

如果 ACTIVATEDno(即在本机上首次运行 Skill)且 Preamble 输出了非空的 FIRST_TASK: 值(且值不为 nongit):展示一条基于 Token 映射出的短提示(用于项目引导提醒),然后继续执行用户实际请求的任务 — 切勿阻断或暂停任务。Token 映射规则:greenfield → "全新仓库 — 建议先用 /spec/office-hours 进行需求与架构规划。" code_node/code_python/code_rust/code_go/code_ruby/code_ios → "