setup-deploy
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese<!-- AUTO-GENERATED from SKILL.md.tmpl — do not edit directly -->
<!-- Regenerate: bun run gen:skill-docs -->
<!-- 自动生成自SKILL.md.tmpl — 请勿直接编辑 -->
<!-- 重新生成:bun run gen:skill-docs -->
Preamble (run first)
前置操作(首先执行)
bash
_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 -delete 2>/dev/null || true
_CONTRIB=$(~/.claude/skills/gstack/bin/gstack-config get gstack_contributor 2>/dev/null || true)
_PROACTIVE=$(~/.claude/skills/gstack/bin/gstack-config get proactive 2>/dev/null || echo "true")
_BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
echo "BRANCH: $_BRANCH"
echo "PROACTIVE: $_PROACTIVE"
_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"
mkdir -p ~/.gstack/analytics
echo '{"skill":"setup-deploy","ts":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","repo":"'$(basename "$(git rev-parse --show-toplevel 2>/dev/null)" 2>/dev/null || echo "unknown")'"}' >> ~/.gstack/analytics/skill-usage.jsonl 2>/dev/null || true
for _PF in ~/.gstack/analytics/.pending-*; do [ -f "$_PF" ] && ~/.claude/skills/gstack/bin/gstack-telemetry-log --event-type skill_run --skill _pending_finalize --outcome unknown --session-id "$_SESSION_ID" 2>/dev/null || true; break; doneIf is , do not proactively suggest gstack skills — only invoke
them when the user explicitly asks. The user opted out of proactive suggestions.
PROACTIVE"false"If output shows : read and follow the "Inline upgrade flow" (auto-upgrade if configured, otherwise AskUserQuestion with 4 options, write snooze state if declined). If : tell user "Running gstack v{to} (just updated!)" and continue.
UPGRADE_AVAILABLE <old> <new>~/.claude/skills/gstack/gstack-upgrade/SKILL.mdJUST_UPGRADED <from> <to>If is : Before continuing, introduce the Completeness Principle.
Tell the user: "gstack follows the Boil the Lake principle — always do the complete
thing when AI makes the marginal cost near-zero. Read more: https://garryslist.org/posts/boil-the-ocean"
Then offer to open the essay in their default browser:
LAKE_INTROnobash
open https://garryslist.org/posts/boil-the-ocean
touch ~/.gstack/.completeness-intro-seenOnly run if the user says yes. Always run to mark as seen. This only happens once.
opentouchIf is AND is : After the lake intro is handled,
ask the user about telemetry. Use AskUserQuestion:
TEL_PROMPTEDnoLAKE_INTROyesHelp gstack get better! Community mode shares usage data (which skills you use, how long they take, crash info) with a stable device ID so we can track trends and fix bugs faster. No code, file paths, or repo names are ever sent. Change anytime with.gstack-config set telemetry off
Options:
- A) Help gstack get better! (recommended)
- B) No thanks
If A: run
~/.claude/skills/gstack/bin/gstack-config set telemetry communityIf B: ask a follow-up AskUserQuestion:
How about anonymous mode? We just learn that someone used gstack — no unique ID, no way to connect sessions. Just a counter that helps us know if anyone's out there.
Options:
- A) Sure, anonymous is fine
- B) No thanks, fully off
If B→A: run
If B→B: run
~/.claude/skills/gstack/bin/gstack-config set telemetry anonymous~/.claude/skills/gstack/bin/gstack-config set telemetry offAlways run:
bash
touch ~/.gstack/.telemetry-promptedThis only happens once. If is , skip this entirely.
TEL_PROMPTEDyesbash
_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 -delete 2>/dev/null || true
_CONTRIB=$(~/.claude/skills/gstack/bin/gstack-config get gstack_contributor 2>/dev/null || true)
_PROACTIVE=$(~/.claude/skills/gstack/bin/gstack-config get proactive 2>/dev/null || echo "true")
_BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
echo "BRANCH: $_BRANCH"
echo "PROACTIVE: $_PROACTIVE"
_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"
mkdir -p ~/.gstack/analytics
echo '{"skill":"setup-deploy","ts":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","repo":"'$(basename "$(git rev-parse --show-toplevel 2>/dev/null)" 2>/dev/null || echo "unknown")'"}' >> ~/.gstack/analytics/skill-usage.jsonl 2>/dev/null || true
for _PF in ~/.gstack/analytics/.pending-*; do [ -f "$_PF" ] && ~/.claude/skills/gstack/bin/gstack-telemetry-log --event-type skill_run --skill _pending_finalize --outcome unknown --session-id "$_SESSION_ID" 2>/dev/null || true; break; done如果为,请勿主动推荐gstack技能——仅在用户明确要求时调用。用户已选择退出主动推荐功能。
PROACTIVE"false"如果输出显示:请阅读并遵循「内联升级流程」(如果已配置自动升级则自动执行,否则向用户展示4个选项,若用户拒绝则记录 snooze 状态)。如果显示:告知用户「正在运行gstack v{to}(刚刚完成更新!)」并继续后续操作。
UPGRADE_AVAILABLE <old> <new>~/.claude/skills/gstack/gstack-upgrade/SKILL.mdJUST_UPGRADED <from> <to>如果为:在继续操作前,先向用户介绍完整性原则。告知用户:"gstack遵循煮沸湖水原则——当AI使边际成本趋近于零时,始终完成完整的任务。了解更多:https://garryslist.org/posts/boil-the-ocean"
然后询问用户是否要在默认浏览器中打开该文章:
LAKE_INTROnobash
open https://garryslist.org/posts/boil-the-ocean
touch ~/.gstack/.completeness-intro-seen仅在用户同意时执行命令。无论用户是否同意,都要执行命令标记为已查看。此操作仅执行一次。
opentouch如果为且为:在处理完湖水原则介绍后,询问用户关于遥测的设置。使用AskUserQuestion:
TEL_PROMPTEDnoLAKE_INTROyes帮助gstack变得更好!社区模式会共享使用数据(你使用的技能、耗时、崩溃信息)以及一个稳定的设备ID,以便我们跟踪趋势并更快修复bug。我们绝不会发送任何代码、文件路径或仓库名称。随时可通过更改设置。gstack-config set telemetry off
选项:
- A) 帮助gstack变得更好!(推荐)
- B) 不用了,谢谢
如果选择A:执行
~/.claude/skills/gstack/bin/gstack-config set telemetry community如果选择B:继续询问以下问题:
那匿名模式呢?我们仅会了解到「有人使用了gstack」——没有唯一ID,无法关联会话。只是一个计数器,帮助我们了解产品的使用情况。
选项:
- A) 好的,匿名模式可以
- B) 不用了,完全关闭
如果B→A:执行
如果B→B:执行
~/.claude/skills/gstack/bin/gstack-config set telemetry anonymous~/.claude/skills/gstack/bin/gstack-config set telemetry off无论选择哪个,都要执行:
bash
touch ~/.gstack/.telemetry-prompted此操作仅执行一次。如果为,则完全跳过此步骤。
TEL_PROMPTEDyesAskUserQuestion Format
AskUserQuestion 格式
ALWAYS follow this structure for every AskUserQuestion call:
- Re-ground: State the project, the current branch (use the value printed by the preamble — NOT any branch from conversation history or gitStatus), and the current plan/task. (1-2 sentences)
_BRANCH - Simplify: Explain the problem in plain English a smart 16-year-old could follow. No raw function names, no internal jargon, no implementation details. Use concrete examples and analogies. Say what it DOES, not what it's called.
- Recommend: — always prefer the complete option over shortcuts (see Completeness Principle). Include
RECOMMENDATION: Choose [X] because [one-line reason]for each option. Calibration: 10 = complete implementation (all edge cases, full coverage), 7 = covers happy path but skips some edges, 3 = shortcut that defers significant work. If both options are 8+, pick the higher; if one is ≤5, flag it.Completeness: X/10 - Options: Lettered options: — when an option involves effort, show both scales:
A) ... B) ... C) ...(human: ~X / CC: ~Y)
Assume the user hasn't looked at this window in 20 minutes and doesn't have the code open. If you'd need to read the source to understand your own explanation, it's too complex.
Per-skill instructions may add additional formatting rules on top of this baseline.
每次调用AskUserQuestion时必须遵循以下结构:
- 重新梳理上下文: 说明项目、当前分支(使用前置操作中输出的值——不要使用对话历史或gitStatus中的分支)以及当前计划/任务。(1-2句话)
_BRANCH - 简化说明: 用普通16岁青少年能理解的直白语言解释问题。不要使用原始函数名、内部术语或实现细节。使用具体示例和类比。说明功能,而非名称。
- 推荐选项: ——始终优先选择完整选项而非捷径(参考完整性原则)。为每个选项标注
RECOMMENDATION: 选择[X],因为[一句话理由]。校准标准:10=完整实现(覆盖所有边缘情况、全面支持),7=覆盖常规场景但忽略部分边缘情况,3=推迟大量工作的捷径。如果两个选项评分都≥8,选择评分更高的;如果其中一个≤5,需标记出来。Completeness: X/10 - 选项列表: 带字母的选项:——当选项涉及工作量时,同时显示两种耗时:
A) ... B) ... C) ...(人工: ~X / CC: ~Y)
假设用户已经20分钟没看这个窗口,且没有打开代码。如果你的解释需要阅读源代码才能理解,说明过于复杂。
特定技能的说明可能会在此基础格式上添加额外规则。
Completeness Principle — Boil the Lake
完整性原则——煮沸湖水
AI-assisted coding makes the marginal cost of completeness near-zero. When you present options:
- If Option A is the complete implementation (full parity, all edge cases, 100% coverage) and Option B is a shortcut that saves modest effort — always recommend A. The delta between 80 lines and 150 lines is meaningless with CC+gstack. "Good enough" is the wrong instinct when "complete" costs minutes more.
- Lake vs. ocean: A "lake" is boilable — 100% test coverage for a module, full feature implementation, handling all edge cases, complete error paths. An "ocean" is not — rewriting an entire system from scratch, adding features to dependencies you don't control, multi-quarter platform migrations. Recommend boiling lakes. Flag oceans as out of scope.
- When estimating effort, always show both scales: human team time and CC+gstack time. The compression ratio varies by task type — use this reference:
| Task type | Human team | CC+gstack | Compression |
|---|---|---|---|
| Boilerplate / scaffolding | 2 days | 15 min | ~100x |
| Test writing | 1 day | 15 min | ~50x |
| Feature implementation | 1 week | 30 min | ~30x |
| Bug fix + regression test | 4 hours | 15 min | ~20x |
| Architecture / design | 2 days | 4 hours | ~5x |
| Research / exploration | 1 day | 3 hours | ~3x |
- This principle applies to test coverage, error handling, documentation, edge cases, and feature completeness. Don't skip the last 10% to "save time" — with AI, that 10% costs seconds.
Anti-patterns — DON'T do this:
- BAD: "Choose B — it covers 90% of the value with less code." (If A is only 70 lines more, choose A.)
- BAD: "We can skip edge case handling to save time." (Edge case handling costs minutes with CC.)
- BAD: "Let's defer test coverage to a follow-up PR." (Tests are the cheapest lake to boil.)
- BAD: Quoting only human-team effort: "This would take 2 weeks." (Say: "2 weeks human / ~1 hour CC.")
AI辅助编码使完整性的边际成本趋近于零。当你提供选项时:
- 如果选项A是完整实现(完全兼容、覆盖所有边缘情况、100%支持),选项B是节省少量工作量的捷径——始终推荐A。在CC+gstack的帮助下,80行代码和150行代码的差异毫无意义。当「完整」仅需多花几分钟时,「足够好」是错误的直觉。
- 湖水 vs. 海洋:「湖水」是可以煮沸的——模块的100%测试覆盖率、完整功能实现、处理所有边缘情况、完善的错误处理路径。「海洋」则不行——从头重写整个系统、为你无法控制的依赖添加功能、耗时多个季度的平台迁移。推荐煮沸湖水,标记海洋为超出范围。
- 估算工作量时,始终显示两种耗时: 人工团队耗时和CC+gstack耗时。压缩比因任务类型而异,参考以下标准:
| 任务类型 | 人工团队 | CC+gstack | 压缩比 |
|---|---|---|---|
| 样板代码/脚手架 | 2天 | 15分钟 | ~100x |
| 测试编写 | 1天 | 15分钟 | ~50x |
| 功能实现 | 1周 | 30分钟 | ~30x |
| Bug修复+回归测试 | 4小时 | 15分钟 | ~20x |
| 架构/设计 | 2天 | 4小时 | ~5x |
| 研究/探索 | 1天 | 3小时 | ~3x |
- 此原则适用于测试覆盖率、错误处理、文档、边缘情况和功能完整性。不要为了「节省时间」而跳过最后10%的工作——在AI的帮助下,这10%仅需几秒钟。
反模式——请勿这样做:
- 错误示例:「选择B——它用更少的代码覆盖了90%的价值。」(如果A仅多70行代码,选择A。)
- 错误示例:「我们可以跳过边缘情况处理以节省时间。」(在CC的帮助下,边缘情况处理仅需几分钟。)
- 错误示例:「我们将测试覆盖率推迟到后续PR中。」(测试是最容易煮沸的湖水。)
- 错误示例:仅引用人工团队耗时:「这需要2周时间。」(正确说法:「人工2周 / CC约1小时。」)
Search Before Building
先搜索再构建
Before building infrastructure, unfamiliar patterns, or anything the runtime might have a built-in — search first. Read for the full philosophy.
~/.claude/skills/gstack/ETHOS.mdThree layers of knowledge:
- Layer 1 (tried and true — in distribution). Don't reinvent the wheel. But the cost of checking is near-zero, and once in a while, questioning the tried-and-true is where brilliance occurs.
- Layer 2 (new and popular — search for these). But scrutinize: humans are subject to mania. Search results are inputs to your thinking, not answers.
- Layer 3 (first principles — prize these above all). Original observations derived from reasoning about the specific problem. The most valuable of all.
Eureka moment: When first-principles reasoning reveals conventional wisdom is wrong, name it:
"EUREKA: Everyone does X because [assumption]. But [evidence] shows this is wrong. Y is better because [reasoning]."
Log eureka moments:
bash
jq -n --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" --arg skill "SKILL_NAME" --arg branch "$(git branch --show-current 2>/dev/null)" --arg insight "ONE_LINE_SUMMARY" '{ts:$ts,skill:$skill,branch:$branch,insight:$insight}' >> ~/.gstack/analytics/eureka.jsonl 2>/dev/null || trueReplace SKILL_NAME and ONE_LINE_SUMMARY. Runs inline — don't stop the workflow.
WebSearch fallback: If WebSearch is unavailable, skip the search step and note: "Search unavailable — proceeding with in-distribution knowledge only."
在构建基础设施、不熟悉的模式或任何运行时可能内置的功能之前——先搜索。阅读了解完整理念。
~/.claude/skills/gstack/ETHOS.md三层知识体系:
- 第一层(久经考验——已发布):不要重复造轮子。但检查的成本趋近于零,偶尔质疑既定方案可能会带来创新。
- 第二层(新兴且流行——需要搜索):但要仔细甄别:人类容易跟风。搜索结果是思考的输入,而非答案。
- 第三层(第一性原理——最有价值):从特定问题的推理中得出的原创观察。是所有知识中最有价值的。
灵光一现时刻: 当第一性原理推理揭示传统观点错误时,请记录:
"EUREKA: 所有人都做X是因为[假设]。但[证据]表明这是错误的。Y更好,因为[推理]。"
记录灵光一现时刻:
bash
jq -n --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" --arg skill "SKILL_NAME" --arg branch "$(git branch --show-current 2>/dev/null)" --arg insight "ONE_LINE_SUMMARY" '{ts:$ts,skill:$skill,branch:$branch,insight:$insight}' >> ~/.gstack/analytics/eureka.jsonl 2>/dev/null || true替换SKILL_NAME和ONE_LINE_SUMMARY。直接执行——不要中断工作流。
WebSearch备用方案: 如果WebSearch不可用,跳过搜索步骤并注明:「搜索不可用——仅使用已发布的知识继续操作。」
Contributor Mode
贡献者模式
If is : you are in contributor mode. You're a gstack user who also helps make it better.
_CONTRIBtrueAt the end of each major workflow step (not after every single command), reflect on the gstack tooling you used. Rate your experience 0 to 10. If it wasn't a 10, think about why. If there is an obvious, actionable bug OR an insightful, interesting thing that could have been done better by gstack code or skill markdown — file a field report. Maybe our contributor will help make us better!
Calibration — this is the bar: For example, used to fail with because gstack didn't wrap expressions in async context. Small, but the input was reasonable and gstack should have handled it — that's the kind of thing worth filing. Things less consequential than this, ignore.
$B js "await fetch(...)"SyntaxError: await is only valid in async functionsNOT worth filing: user's app bugs, network errors to user's URL, auth failures on user's site, user's own JS logic bugs.
To file: write with all sections below (do not truncate — include every section through the Date/Version footer):
~/.gstack/contributor-logs/{slug}.mdundefined如果为:你处于贡献者模式。你是gstack用户,同时也帮助改进gstack。
_CONTRIBtrue在每个主要工作流步骤结束时(不是每个命令之后),反思你使用的gstack工具。为你的体验评分0到10。如果评分不是10,思考原因。如果存在明显的可操作bug,或者gstack的代码或技能markdown有可以改进的地方——提交现场报告。也许我们的贡献者会帮助我们变得更好!
校准标准: 例如,曾因gstack未将表达式包裹在async上下文中而失败,报错。这是一个小问题,但输入是合理的,gstack应该处理——这种情况值得提交报告。比这更无关紧要的问题可以忽略。
$B js "await fetch(...)"SyntaxError: await is only valid in async functions不值得提交的问题: 用户应用的bug、用户URL的网络错误、用户站点的认证失败、用户自己的JS逻辑bug。
提交报告: 写入,包含以下所有部分(不要截断——包括到日期/版本页脚的每个部分):
~/.gstack/contributor-logs/{slug}.mdundefined{Title}
{标题}
Hey gstack team — ran into this while using /{skill-name}:
What I was trying to do: {what the user/agent was attempting}
What happened instead: {what actually happened}
My rating: {0-10} — {one sentence on why it wasn't a 10}
嘿gstack团队——我在使用/{skill-name}时遇到了这个问题:
我尝试做的事情: {用户/代理尝试执行的操作}
实际发生的情况: {实际结果}
我的评分: {0-10} — {一句话说明为什么不是10分}
Steps to reproduce
复现步骤
- {step}
- {步骤}
Raw output
原始输出
{paste the actual error or unexpected output here}{粘贴实际错误或意外输出}What would make this a 10
如何做到10分
{one sentence: what gstack should have done differently}
Date: {YYYY-MM-DD} | Version: {gstack version} | Skill: /{skill}
Slug: lowercase, hyphens, max 60 chars (e.g. `browse-js-no-await`). Skip if file already exists. Max 3 reports per session. File inline and continue — don't stop the workflow. Tell user: "Filed gstack field report: {title}"{一句话:gstack应该如何改进}
日期: {YYYY-MM-DD} | 版本: {gstack version} | 技能: /{skill}
Slug:小写,用连字符分隔,最多60个字符(例如`browse-js-no-await`)。如果文件已存在则跳过。每个会话最多提交3份报告。直接写入并继续——不要中断工作流。告知用户:「已提交gstack现场报告:{标题}」Completion Status Protocol
完成状态协议
When completing a skill workflow, report status using one of:
- DONE — All steps completed successfully. Evidence provided for each claim.
- DONE_WITH_CONCERNS — Completed, but with issues the user should know about. List each concern.
- BLOCKED — Cannot proceed. State what is blocking and what was tried.
- NEEDS_CONTEXT — Missing information required to continue. State exactly what you need.
完成技能工作流时,使用以下方式报告状态:
- DONE — 所有步骤成功完成。每个声明都有证据支持。
- DONE_WITH_CONCERNS — 已完成,但存在用户需要了解的问题。列出每个问题。
- BLOCKED — 无法继续。说明阻塞原因和已尝试的操作。
- NEEDS_CONTEXT — 缺少继续所需的信息。明确说明需要的内容。
Escalation
升级处理
It is always OK to stop and say "this is too hard for me" or "I'm not confident in this result."
Bad work is worse than no work. You will not be penalized for escalating.
- If you have attempted a task 3 times without success, STOP and escalate.
- If you are uncertain about a security-sensitive change, STOP and escalate.
- If the scope of work exceeds what you can verify, STOP and escalate.
Escalation format:
STATUS: BLOCKED | NEEDS_CONTEXT
REASON: [1-2 sentences]
ATTEMPTED: [what you tried]
RECOMMENDATION: [what the user should do next]随时可以停止并说「这对我来说太难了」或「我对结果没有信心」。
糟糕的工作不如不做。你不会因升级处理而受到惩罚。
- 如果你尝试某项任务3次都未成功,请停止并升级处理。
- 如果你对安全敏感的更改不确定,请停止并升级处理。
- 如果工作范围超出你能验证的范围,请停止并升级处理。
升级处理格式:
STATUS: BLOCKED | NEEDS_CONTEXT
REASON: [1-2句话]
ATTEMPTED: [已尝试的操作]
RECOMMENDATION: [用户下一步应该做什么]Telemetry (run last)
遥测(最后执行)
After the skill workflow completes (success, error, or abort), log the telemetry event.
Determine the skill name from the field in this file's YAML frontmatter.
Determine the outcome from the workflow result (success if completed normally, error
if it failed, abort if the user interrupted).
name:PLAN MODE EXCEPTION — ALWAYS RUN: This command writes telemetry to
(user config directory, not project files). The skill
preamble already writes to the same directory — this is the same pattern.
Skipping this command loses session duration and outcome data.
~/.gstack/analytics/Run this bash:
bash
_TEL_END=$(date +%s)
_TEL_DUR=$(( _TEL_END - _TEL_START ))
rm -f ~/.gstack/analytics/.pending-"$_SESSION_ID" 2>/dev/null || true
~/.claude/skills/gstack/bin/gstack-telemetry-log \
--skill "SKILL_NAME" --duration "$_TEL_DUR" --outcome "OUTCOME" \
--used-browse "USED_BROWSE" --session-id "$_SESSION_ID" 2>/dev/null &Replace with the actual skill name from frontmatter, with
success/error/abort, and with true/false based on whether was used.
If you cannot determine the outcome, use "unknown". This runs in the background and
never blocks the user.
SKILL_NAMEOUTCOMEUSED_BROWSE$B技能工作流完成后(成功、错误或中止),记录遥测事件。从文件YAML前言的字段中确定技能名称。根据工作流结果确定结果(正常完成则为success,失败则为error,用户中断则为abort)。
name:计划模式例外——必须执行: 此命令将遥测数据写入(用户配置目录,而非项目文件)。技能前置操作已写入同一目录——这是相同的模式。跳过此命令会丢失会话时长和结果数据。
~/.gstack/analytics/执行以下bash命令:
bash
_TEL_END=$(date +%s)
_TEL_DUR=$(( _TEL_END - _TEL_START ))
rm -f ~/.gstack/analytics/.pending-"$_SESSION_ID" 2>/dev/null || true
~/.claude/skills/gstack/bin/gstack-telemetry-log \
--skill "SKILL_NAME" --duration "$_TEL_DUR" --outcome "OUTCOME" \
--used-browse "USED_BROWSE" --session-id "$_SESSION_ID" 2>/dev/null &将替换为前言中的实际技能名称,替换为success/error/abort,根据是否使用替换为true/false。如果无法确定结果,使用「unknown」。此命令在后台运行,不会阻塞用户。
SKILL_NAMEOUTCOMEUSED_BROWSE$B/setup-deploy — Configure Deployment for gstack
/setup-deploy — 为gstack配置部署
You are helping the user configure their deployment so works
automatically. Your job is to detect the deploy platform, production URL, health
checks, and deploy status commands — then persist everything to CLAUDE.md.
/land-and-deployAfter this runs once, reads CLAUDE.md and skips detection entirely.
/land-and-deploy你正在帮助用户配置部署,使/land-and-deploy能够自动工作。你的任务是检测部署平台、生产环境URL、健康检查和部署状态命令——然后将所有信息保存到CLAUDE.md。
此操作执行一次后,/land-and-deploy会读取CLAUDE.md并完全跳过检测步骤。
User-invocable
用户可调用
When the user types , run this skill.
/setup-deploy当用户输入时,运行此技能。
/setup-deployInstructions
操作说明
Step 1: Check existing configuration
步骤1:检查现有配置
bash
grep -A 20 "## Deploy Configuration" CLAUDE.md 2>/dev/null || echo "NO_CONFIG"If configuration already exists, show it and ask:
- Context: Deploy configuration already exists in CLAUDE.md.
- RECOMMENDATION: Choose A to update if your setup changed.
- A) Reconfigure from scratch (overwrite existing)
- B) Edit specific fields (show current config, let me change one thing)
- C) Done — configuration looks correct
If the user picks C, stop.
bash
grep -A 20 "## Deploy Configuration" CLAUDE.md 2>/dev/null || echo "NO_CONFIG"如果配置已存在,显示配置并询问:
- 上下文: CLAUDE.md中已存在部署配置。
- 推荐: 如果你的设置已更改,选择A进行更新。
- A) 从头重新配置(覆盖现有配置)
- B) 编辑特定字段(显示当前配置,让我更改某一项)
- C) 完成——配置看起来正确
如果用户选择C,停止操作。
Step 2: Detect platform
步骤2:检测平台
Run the platform detection from the deploy bootstrap:
bash
undefined运行部署引导程序中的平台检测:
bash
undefinedPlatform config files
平台配置文件
[ -f fly.toml ] && echo "PLATFORM:fly" && cat fly.toml
[ -f render.yaml ] && echo "PLATFORM:render" && cat render.yaml
[ -f vercel.json ] || [ -d .vercel ] && echo "PLATFORM:vercel"
[ -f netlify.toml ] && echo "PLATFORM:netlify" && cat netlify.toml
[ -f Procfile ] && echo "PLATFORM:heroku"
[ -f railway.json ] || [ -f railway.toml ] && echo "PLATFORM:railway"
[ -f fly.toml ] && echo "PLATFORM:fly" && cat fly.toml
[ -f render.yaml ] && echo "PLATFORM:render" && cat render.yaml
[ -f vercel.json ] || [ -d .vercel ] && echo "PLATFORM:vercel"
[ -f netlify.toml ] && echo "PLATFORM:netlify" && cat netlify.toml
[ -f Procfile ] && echo "PLATFORM:heroku"
[ -f railway.json ] || [ -f railway.toml ] && echo "PLATFORM:railway"
GitHub Actions deploy workflows
GitHub Actions 部署工作流
for f in .github/workflows/.yml .github/workflows/.yaml; do
[ -f "$f" ] && grep -qiE "deploy|release|production|staging|cd" "$f" 2>/dev/null && echo "DEPLOY_WORKFLOW:$f"
done
for f in .github/workflows/.yml .github/workflows/.yaml; do
[ -f "$f" ] && grep -qiE "deploy|release|production|staging|cd" "$f" 2>/dev/null && echo "DEPLOY_WORKFLOW:$f"
done
Project type
项目类型
[ -f package.json ] && grep -q '"bin"' package.json 2>/dev/null && echo "PROJECT_TYPE:cli"
ls *.gemspec 2>/dev/null && echo "PROJECT_TYPE:library"
undefined[ -f package.json ] && grep -q '"bin"' package.json 2>/dev/null && echo "PROJECT_TYPE:cli"
ls *.gemspec 2>/dev/null && echo "PROJECT_TYPE:library"
undefinedStep 3: Platform-specific setup
步骤3:特定平台设置
Based on what was detected, guide the user through platform-specific configuration.
根据检测结果,引导用户完成特定平台的配置。
Fly.io
Fly.io
If detected:
fly.toml- Extract app name:
grep -m1 "^app" fly.toml | sed 's/app = "\(.*\)"/\1/' - Check if CLI is installed:
flywhich fly 2>/dev/null - If installed, verify:
fly status --app {app} 2>/dev/null - Infer URL:
https://{app}.fly.dev - Set deploy status command:
fly status --app {app} - Set health check: (or
https://{app}.fly.devif the app has one)/health
Ask the user to confirm the production URL. Some Fly apps use custom domains.
如果检测到:
fly.toml- 提取应用名称:
grep -m1 "^app" fly.toml | sed 's/app = "\(.*\)"/\1/' - 检查CLI是否安装:
flywhich fly 2>/dev/null - 如果已安装,验证:
fly status --app {app} 2>/dev/null - 推断URL:
https://{app}.fly.dev - 设置部署状态命令:
fly status --app {app} - 设置健康检查:(如果应用有/health端点则使用该端点)
https://{app}.fly.dev
请用户确认生产环境URL。部分Fly应用使用自定义域名。
Render
Render
If detected:
render.yaml- Extract service name and type from render.yaml
- Check for Render API key: (don't expose the full key)
echo $RENDER_API_KEY | head -c 4 - Infer URL:
https://{service-name}.onrender.com - Render deploys automatically on push to the connected branch — no deploy workflow needed
- Set health check: the inferred URL
Ask the user to confirm. Render uses auto-deploy from the connected git branch — after
merge to main, Render picks it up automatically. The "deploy wait" in /land-and-deploy
should poll the Render URL until it responds with the new version.
如果检测到:
render.yaml- 从render.yaml中提取服务名称和类型
- 检查是否有Render API密钥:(不要暴露完整密钥)
echo $RENDER_API_KEY | head -c 4 - 推断URL:
https://{service-name}.onrender.com - Render会在推送到关联分支时自动部署——无需部署工作流
- 设置健康检查:推断的URL
请用户确认。Render从关联的git分支自动部署——合并到main分支后,Render会自动处理。/land-and-deploy中的「deploy wait」会轮询Render URL,直到返回新版本。
Vercel
Vercel
If vercel.json or .vercel detected:
- Check for CLI:
vercelwhich vercel 2>/dev/null - If installed:
vercel ls --prod 2>/dev/null | head -3 - Vercel deploys automatically on push — preview on PR, production on merge to main
- Set health check: the production URL from vercel project settings
如果检测到vercel.json或.vercel:
- 检查是否有CLI:
vercelwhich vercel 2>/dev/null - 如果已安装:
vercel ls --prod 2>/dev/null | head -3 - Vercel会在推送时自动部署——PR上是预览环境,合并到main分支后是生产环境
- 设置健康检查:Vercel项目设置中的生产环境URL
Netlify
Netlify
If netlify.toml detected:
- Extract site info from netlify.toml
- Netlify deploys automatically on push
- Set health check: the production URL
如果检测到netlify.toml:
- 从netlify.toml中提取站点信息
- Netlify会在推送时自动部署
- 设置健康检查:生产环境URL
GitHub Actions only
仅GitHub Actions
If deploy workflows detected but no platform config:
- Read the workflow file to understand what it does
- Extract the deploy target (if mentioned)
- Ask the user for the production URL
如果检测到部署工作流但没有平台配置:
- 读取工作流文件以了解其功能
- 提取部署目标(如果有提及)
- 向用户询问生产环境URL
Custom / Manual
自定义/手动
If nothing detected:
Use AskUserQuestion to gather the information:
-
How are deploys triggered?
- A) Automatically on push to main (Fly, Render, Vercel, Netlify, etc.)
- B) Via GitHub Actions workflow
- C) Via a deploy script or CLI command (describe it)
- D) Manually (SSH, dashboard, etc.)
- E) This project doesn't deploy (library, CLI, tool)
-
What's the production URL? (Free text — the URL where the app runs)
-
How can gstack check if a deploy succeeded?
- A) HTTP health check at a specific URL (e.g., /health, /api/status)
- B) CLI command (e.g., ,
fly status)kubectl rollout status - C) Check the GitHub Actions workflow status
- D) No automated way — just check the URL loads
-
Any pre-merge or post-merge hooks?
- Commands to run before merging (e.g., )
bun run build - Commands to run after merge but before deploy verification
- Commands to run before merging (e.g.,
如果未检测到任何内容:
使用AskUserQuestion收集信息:
-
部署如何触发?
- A) 推送到main分支时自动触发(Fly、Render、Vercel、Netlify等)
- B) 通过GitHub Actions工作流
- C) 通过部署脚本或CLI命令(请描述)
- D) 手动触发(SSH、控制台等)
- E) 此项目无需部署(库、CLI、工具)
-
生产环境URL是什么?(自由文本——应用运行的URL)
-
gstack如何检查部署是否成功?
- A) 特定URL的HTTP健康检查(例如/health、/api/status)
- B) CLI命令(例如、
fly status)kubectl rollout status - C) 检查GitHub Actions工作流状态
- D) 没有自动化方式——仅检查URL是否可访问
-
是否有合并前或合并后钩子?
- 合并前需运行的命令(例如)
bun run build - 合并后但部署验证前需运行的命令
- 合并前需运行的命令(例如
Step 4: Write configuration
步骤4:写入配置
Read CLAUDE.md (or create it). Find and replace the section
if it exists, or append it at the end.
## Deploy Configurationmarkdown
undefined读取CLAUDE.md(如果不存在则创建)。如果存在部分则替换,否则追加到文件末尾。
## Deploy Configurationmarkdown
undefinedDeploy Configuration (configured by /setup-deploy)
Deploy Configuration (configured by /setup-deploy)
- Platform: {platform}
- Production URL: {url}
- Deploy workflow: {workflow file or "auto-deploy on push"}
- Deploy status command: {command or "HTTP health check"}
- Merge method: {squash/merge/rebase}
- Project type: {web app / API / CLI / library}
- Post-deploy health check: {health check URL or command}
- Platform: {platform}
- Production URL: {url}
- Deploy workflow: {workflow file or "auto-deploy on push"}
- Deploy status command: {command or "HTTP health check"}
- Merge method: {squash/merge/rebase}
- Project type: {web app / API / CLI / library}
- Post-deploy health check: {health check URL or command}
Custom deploy hooks
Custom deploy hooks
- Pre-merge: {command or "none"}
- Deploy trigger: {command or "automatic on push to main"}
- Deploy status: {command or "poll production URL"}
- Health check: {URL or command}
undefined- Pre-merge: {command or "none"}
- Deploy trigger: {command or "automatic on push to main"}
- Deploy status: {command or "poll production URL"}
- Health check: {URL or command}
undefinedStep 5: Verify
步骤5:验证
After writing, verify the configuration works:
- If a health check URL was configured, try it:
bash
curl -sf "{health-check-url}" -o /dev/null -w "%{http_code}" 2>/dev/null || echo "UNREACHABLE"- If a deploy status command was configured, try it:
bash
{deploy-status-command} 2>/dev/null | head -5 || echo "COMMAND_FAILED"Report results. If anything failed, note it but don't block — the config is still
useful even if the health check is temporarily unreachable.
写入后,验证配置是否有效:
- 如果配置了健康检查URL,尝试访问:
bash
curl -sf "{health-check-url}" -o /dev/null -w "%{http_code}" 2>/dev/null || echo "UNREACHABLE"- 如果配置了部署状态命令,尝试执行:
bash
{deploy-status-command} 2>/dev/null | head -5 || echo "COMMAND_FAILED"报告结果。如果有任何失败,记录下来但不要阻塞——即使健康检查暂时不可访问,配置仍然有用。
Step 6: Summary
步骤6:总结
DEPLOY CONFIGURATION — COMPLETE
════════════════════════════════
Platform: {platform}
URL: {url}
Health check: {health check}
Status cmd: {status command}
Merge method: {merge method}
Saved to CLAUDE.md. /land-and-deploy will use these settings automatically.
Next steps:
- Run /land-and-deploy to merge and deploy your current PR
- Edit the "## Deploy Configuration" section in CLAUDE.md to change settings
- Run /setup-deploy again to reconfigureDEPLOY CONFIGURATION — COMPLETE
════════════════════════════════
Platform: {platform}
URL: {url}
Health check: {health check}
Status cmd: {status command}
Merge method: {merge method}
已保存到CLAUDE.md。/land-and-deploy会自动使用这些设置。
下一步:
- 运行/land-and-deploy以合并并部署当前PR
- 编辑CLAUDE.md中的「## Deploy Configuration」部分以更改设置
- 再次运行/setup-deploy以重新配置Important Rules
重要规则
- Never expose secrets. Don't print full API keys, tokens, or passwords.
- Confirm with the user. Always show the detected config and ask for confirmation before writing.
- CLAUDE.md is the source of truth. All configuration lives there — not in a separate config file.
- Idempotent. Running /setup-deploy multiple times overwrites the previous config cleanly.
- Platform CLIs are optional. If or
flyCLI isn't installed, fall back to URL-based health checks.vercel
- 永远不要暴露机密信息。 不要打印完整的API密钥、令牌或密码。
- 与用户确认。 写入前始终显示检测到的配置并请求用户确认。
- CLAUDE.md是唯一可信源。 所有配置都存储在此——不要使用单独的配置文件。
- 幂等性。 多次运行/setup-deploy会干净地覆盖之前的配置。
- 平台CLI是可选的。 如果或
flyCLI未安装,回退到基于URL的健康检查。vercel